使用FFmpeg,如何解码H264数据包

时间:2012-02-16 09:52:20

标签: streaming ffmpeg decode h.264

我是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,或者如果它是< 0,数据包应附加到前一个数据包。

  4. 删除数据包的所有RTP标头,使其只有FU指示符| FU标题| NAL

  5. 尝试使用av​​codec_decode_video2()

  6. 播放

    但它只返回-1 .....我是否应该删除FU指示符和标题?

    任何建议都将非常感激

    提前感谢。

3 个答案:

答案 0 :(得分:5)

  

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

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

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

答案 1 :(得分:1)

我不认为您可以在没有RTP标头的情况下解码H264数据包,因为RTP标头中嵌入了相当多的视频流信息。同时,我猜可能所有视频流信息都可以在RTP视频数据包中复制。所以它还取决于流的生成方式。

VIBGYOR

答案 2 :(得分:0)

这是我的工作代码

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;
}