【问题标题】:h264 ffmpeg: How to initialize ffmpeg to decode NALs created with x264h264 ffmpeg:如何初始化 ffmpeg 以解码使用 x264 创建的 NAL
【发布时间】:2013-01-14 16:40:03
【问题描述】:

我使用 x264 编码了一些帧,使用 x264_encoder_encode,之后我使用如下函数创建了 AVPackets:

bool PacketizeNals( uint8_t* a_pNalBuffer, int a_nNalBufferSize, AVPacket* a_pPacket )
{
    if ( !a_pPacket )
return false;
    a_pPacket->data = a_pNalBuffer;
    a_pPacket->size = a_nNalBufferSize;
    a_pPacket->stream_index = 0;
    a_pPacket->flags = AV_PKT_FLAG_KEY;

    a_pPacket->pts = int64_t(0x8000000000000000);
    a_pPacket->dts = int64_t(0x8000000000000000);
}

我这样称呼这个函数:

x264_nal_t* nals;
int num_nals = encode_frame(pic, &nals);
for (int i = 0; i < num_nals; i++)
{
    AVPacket* pPacket = ( AVPacket* )av_malloc( sizeof( AVPacket ) );
    av_init_packet( pPacket );
    if ( PacketizeNals( nals[i].p_payload, nals[i].i_payload, pPacket ) )
    {
        packets.push_back( pPacket );
    }
}

现在我想做的是使用 avcodec_decode_video2 解码这些 AVPackets。我认为问题在于我没有正确初始化解码器,因为编码我使用了“超快”配置文件和“零延迟”调谐( x264 )并且解码我不知道如何指定 ffmpeg 这些选项。 在一些示例中,我读过人们使用存储视频的文件初始化解码器,但在这种情况下,我直接使用了 AVPackets。 我正在尝试解码的是:

avcodec_init();  
avcodec_register_all();  
AVCodec* pCodec;  
pCodec=avcodec_find_decoder(CODEC_ID_H264);  
AVCodecContext* pCodecContext;  
pCodecContext=avcodec_alloc_context();  
avcodec_open(pCodecContext,pCodec);  
pCodecContext->width = 320;
pCodecContext->height = 200;
pCodecContext->extradata = NULL;
unsigned int nNumPackets = packets.size();
int frameFinished = 0;
for ( auto it = packets.begin(); it != packets.end(); it++ )
{
    AVFrame* pFrame;
    pFrame = avcodec_alloc_frame();
    AVPacket* pPacket = *it;
    int iReturn = avcodec_decode_video2( pCodecContext, pFrame, &frameFinished, pPacket );
}

但在 iReturn 中总是 -1。

谁能帮帮我?对不起,如果我在这方面的知识很低,我是新手。

谢谢。

【问题讨论】:

  • 显示ffmpeg输出到控制台

标签: c++ ffmpeg decode h.264 x264


【解决方案1】:

我编写了一个简单的客户端/服务器应用程序,它使用 lib x264 进行编码和 ffmpeg 进行解码来传输原始 RGB 视频。 你可以在这里找到代码:https://github.com/filippobrizzi/raw_rgb_straming

它展示了如何设置 x264 和 ffmpeg 来编码/解码。

【讨论】:

    【解决方案2】:

    现在你像这样初始化解码器

    pCodecContext->extradata = NULL;

    这是不正确的。您需要为此字段分配内存并将数据从编码器的 AVCodecContext::extradata 复制到分配的缓冲区中。 AVCodecContext::extradata_size 指定此额外数据缓冲区的大小(以字节为单位)

    【讨论】:

      【解决方案3】:

      确保您正在构建正确的数据包。看看这是如何在 ffmpeg 中完成的:http://ffmpeg.org/doxygen/trunk/libx264_8c_source.htmlstatic int encode_nals(AVCodecContext *ctx, AVPacket *pkt, x264_nal_t *nals, int nnal)static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)

      【讨论】:

      • 根据我在 encode_nals 中看到的情况,我的代码的不同之处在于我为每个 NAL 生成一个数据包,而 encode_nals 用一组 NAL 生成一个数据包......而且我还填写了 steram_index、标志, pts 和 dts 数据包的字段。每次使用一个数据包是否正确?而关于其他参数......是否正确? encode_nals 不填充它们(我想实时流式传输)。关于 X264Frame,我使用 X264_encoder_encode 进行编码,它直接返回给我 NAL。谢谢。
      • 好吧,假设不正确,你知道如何获取encode_nals函数中使用的sei_size和sei数据吗?我正在使用 x264 的库 x264_encoder_encode 进行编码,该函数为我提供了 NALS。我没有任何 AVCodecContext。如果我尝试使用 ffmpeg 调用 avcodec_find_encoder( CODEC_ID_H264 ) 进行编码,则返回 NULL ...
      • 可以下载ffmpeg,也可以使用libx264编解码器自己编译。
      • 您可以像在函数X264_init (ffmpeg.org/doxygen/trunk/libx264_8c_source.html) 中那样获得sei_sizesei 值。忘记AVCodecContext。它仅用作 ffmpeg 中的通用接口。您无需为编码创建它。
      • 很奇怪,encode_nals 放入数据包 SEI 数据的第一个数据,但是如果我以在 X264_init 上完成的方式获取 SEI 数据,我可以从 NAL_SEI 类型的 NAL 中获取它(第三个 NAL)。写入SEI数据后encode_nals继续复制所有的NAL,所以SEI数据在包数据中有两次??? (在数据包数据的开头以及第三个 NAL 的副本中)这是正确的吗?好像很奇怪……
      猜你喜欢
      • 2010-12-30
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 2011-08-26
      • 2011-08-16
      • 2011-08-29
      相关资源
      最近更新 更多