【问题标题】:using FFmpeg, how to decode H264 packets使用 FFmpeg,如何解码 H264 数据包
【发布时间】:2012-03-07 17:09:45
【问题描述】:

我是 FFmpeg 的新手,正在努力解码可以作为 uint8_t 数组获得的 H264 数据包。

经过多次调查,我认为应该可以将数组放入如下所示的 AVPacket 中

AVPacket *avpkt = (AVPacket *)malloc(sizeof(AVPacket) * 1);
av_init_packet(avpkt);  
avpkt->data = ct;   // ct is the array
avpkt->length =....

并由avcodec_decode_video2() 解码。

部分代码是这样的:

...
codec = avcodec_find_decoder(CODEC_ID_H264);
gVideoCodecCtx = avcodec_alloc_context();
gFrame = avcodec_alloc_frame();
avcodec_decode_video2(gVideoCodecCtx, gFrame, &frameFinished, packet);
...

我想我正确设置了所有必需的属性,但这个函数只返回-1

我刚刚发现-1 来自

ret = avctx->codec->decode(avctx, picture, got_picture_ptr, avpkt);

avcodec_decode_video2();

实际上,我想知道的是如何通过avcodec_decode_video2() 解码 H264 数据包(没有 RTP 标头)?


更新:

好的,我仍在努力寻找解决方案。我现在在做的是下面的

**这个RTP码流中的H264码流是FU-A编码的

  1. 接收 RTP 数据包

  2. 查看 RTP 标头的第二个字节是否 > 0,这意味着它是第一个数据包(可能会被跟随)

  3. 查看下一个 RTP 数据包的第二个字节是否也 > 0,则表示前一帧是完整的 NAL,或者如果这是

  4. 删除数据包的所有 RTP 标头,使其仅具有类似 FU 指示符 | FU头| NAL

  5. 试试avcodec_decode_video2()

但它只返回-1.....
我也应该删除 FU 指示器和标题吗??

任何建议将不胜感激

【问题讨论】:

    标签: streaming ffmpeg decode h.264


    【解决方案1】:

    实际上,我想知道的是我是否可以通过 avcodec_decode_video2() 解码 H264 数据包(没有 RTP 标头)。

    如果您使用除单个 NAL 单元模式之外的打包模式,则在将 NAL 单元传递给解码器之前,您可能需要预处理 RTP 有效负载(重新组装分段的 NALU,拆分聚合的 NALU)。流中允许的 NAL 单元类型(STAP、MTAP、FU)取决于打包模式。阅读RFC 6184 了解有关打包模式的更多信息。

    其次,虽然我对 FFMPEG 不太熟悉,但它可能更像是一般的 H.264 解码问题:您必须始终使用 H.264 序列 (SPS) 和图片参数集 (PPS) 初始化解码器您将能够解码其他帧。你做到了吗?

    【讨论】:

    • 谢谢拉尔夫,事实证明 spydroid 在单 nal 模式和 fu-1 模式下发送 rtp 包,所以我想我需要将数据包作为带有 fu-1 情况的标头的 RTP 处理,但不知道如何使用 ffmpeg 库解码 RTP。我认为没有适用于 RTP 级别的功能,这就是为什么我要使用 H264 开始这项工作:( .. 我能得到任何建议吗?
    • 如果 ffmpeg 在 RTP 层不起作用,您要么必须自己编写该代码,然后再将其传递给 FFMPEG(这还不错),要么使用另一个第三方库。 Live555 (www.live555.com) 将是一个开源 LGPL 库,可处理 RTP,包括 H.264 有效负载特定的数据包化等。
    • @Ralf 我相信单 NAL 单元数据包模式也是 RFC6184 的一部分,请参阅 RFC 的第 5.6 节。我不确定您为什么说它不需要 RTP 标头。如果我错了,请纠正我。
    • @Krishna_Oza 谢谢,真的,我表达得不是很好。更新了答案。
    【解决方案2】:

    我认为没有 RTP 标头您将无法解码 H264 数据包,因为 RTP 标头中嵌入了相当多的视频流信息。同时,我猜有可能所有的视频流信息都可以复制到 RTP 视频包中。所以这也取决于流是如何生成的。

    维乔尔

    【讨论】:

    • 感谢 Vibgyor,实际上发件人是 spydroid 开源,它的 rtp 标头看起来并不包含很多东西。它由有效负载类型、序列号、时间戳、同步源标识符组成。它们是指视频流信息??我不这么认为..我仍在努力,并将更新我的进度。
    【解决方案3】:

    这是我的工作代码

    bool VideoDecoder::decode(const QByteArray &encoded)
    {
        AVPacket packet;
       av_new_packet(&packet, encoded.size());
       memcpy(packet.data, encoded.data(), encoded.size());
       //TODO: use AVPacket directly instead of Packet?
       //TODO: some decoders might in addition need other fields like flags&AV_PKT_FLAG_KEY
    
       int ret = avcodec_decode_video2(d->codec_ctx, d->frame, &d->got_frame_ptr, &packet);
       av_free_packet(&packet);
    
       if ((ret < 0) || (!d->got_frame_ptr))
           return false;
    
        d->sws_ctx = sws_getCachedContext(d->sws_ctx
            , d->codec_ctx->width, d->codec_ctx->height, d->codec_ctx->pix_fmt
            , d->width, d->height, d->pix_fmt
            , (d->width == d->codec_ctx->width && d->height == d->codec_ctx->height) ? SWS_POINT : SWS_BICUBIC
            , NULL, NULL, NULL
            );
    
        int v_scale_result = sws_scale(
            d->sws_ctx,
            d->frame->data,
            d->frame->linesize,
            0,
            d->codec_ctx->height,
            d->picture.data,
            d->picture.linesize
            );
        Q_UNUSED(v_scale_result);
    
        if (d->frame->interlaced_frame)
            avpicture_deinterlace(&d->picture, &d->picture, d->pix_fmt, d->width, d->height);
        return true;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-24
      • 1970-01-01
      • 2012-07-05
      • 2011-08-26
      • 2011-08-24
      • 2019-08-25
      • 2015-03-25
      • 2011-08-16
      • 2020-10-06
      相关资源
      最近更新 更多