【问题标题】:libav - Decoding H264 Frame Errorlibav - 解码 H264 帧错误
【发布时间】:2015-12-30 13:31:50
【问题描述】:

我正在尝试使用 libav 库解码 H264 帧。通过分配框架和上下文初始化库后,我使用以下代码进行解码:

AVPacket pkt;
int got_picture, len;
av_init_packet(&pkt);
pkt.size = size;
pkt.data = buffer;
while(pkt.size > 0) {
    if((len = avcodec_decode_video2(context, frame, &got_picture, &pkt)) < 0) {
        break;
    }

    if(got_picture) {
        // Do something with the picture...
    }

    avPkt.size -= len;
    avPkt.data += len;
}

但是,每当我调用 avcodec_decode_video2 时,它都会在控制台中打印以下错误:

[...]    
[h264 @ 000000000126db40] AVC: The buffer size 210 is too short to read the nal length size 0 at the offset 210.
[h264 @ 000000000126db40] AVC: The buffer size 283997 is too short to read the nal length size 0 at the offset 283997.
[h264 @ 000000000126db40] AVC: The buffer size 17137 is too short to read the nal length size 0 at the offset 17137.
[...]

我错过了什么?我尝试搜索有关类似问题的线程,但没有任何结果。或者有什么方法可以调试错误以获取有关它的更多信息?

【问题讨论】:

  • avcodec_decode_video2()的返回值是多少?
  • 返回值等于剩余的字节数。此外,got_picture 指针非零 - 因此,我假设解压缩成功。但是,我总是收到此错误。
  • 我什至不知道错误消息想说什么。错误在说什么缓冲区?
  • 你从哪里得到最终的数据包(h264 帧)?您是否使用 libavformat 从容器中读取它?你也使用实际版本的 libav 吗?
  • 我使用 LIVE555 接收 H264 帧,然后使用 libav 对其进行解码。这是一场直播。

标签: c++ ffmpeg libav


【解决方案1】:

首先,我假设您正确分配了输出帧。

还有@AntonAngelov,我使用的是 11.04。你知道错误是什么吗 应该说?错误在说什么缓冲区?

我只是查看了 11.04 的源代码(在 /avcodec/h264.c 中),但我没有看到这个错误是在哪里产生的,而在旧版本中它是存在的。

似乎错误表明您发送给解码器的 NALU 数据包的大小是 0

我的猜测是您必须以某种方式从 LIVE555 获取 SPSPPS 标头,并通过 @987654324 将它们提供给解码器@(你也必须设置 extradata_size),在你调用 avcodec_open2() 之前。

另一个想法是将收到的所有数据包转储到单个 .h264 文件中。然后使用解析h264比特流的软件(see here for example)。也可以尝试用avplayVLC播放,看看码流是否正确。

编辑: Here 回答了类似的问题。

【讨论】:

  • 感谢您的回复。这对我来说缩小了错误范围。我将再次研究 PPS 和 SPS 单元的解码。目前我正在使用 LIVE555 的“fmtp_spropparametersets”函数来接收单位。当我尝试解码参数集时,可能会出现问题。另外,我将重新检查我正在使用的 libav 版本。明天我会回复你所有的事情(现在不在家里)。您的第二个想法很好,但是,我过去已经使用 ffplay 做到了。所以比特流看起来不错。
  • @Chris。你找出问题所在了吗?我处于同样的情况 Live555 + Libav。解码正常,但不断输出缓冲区大小错误。
  • @chuckleplant 我重新下载了 libav + 致力于修复 SPS 和 PPS 初始化。
  • @Chris。这就是我试图做的,我通过 Live 接收 SPS PPS 并将其设置在 Libav 的 pCodecCtx-&gt;extradata 上。应该是这样,但我仍然得到错误输出。谢谢!
  • @chuckleplant 尝试调试它。使用十六进制编辑器在通过网络发送的原始 h264 比特流中搜索 SPS 和 PPS 值。然后使用 base64 对其进行编码,并将其与您在客户端应用程序中设置的内容进行比较。
【解决方案2】:
AVPacket pkt;
int got_picture, len;
av_init_packet(&pkt);
pkt.size = size;
pkt.data = buffer;
while(pkt.size > 0) {
    if((len = avcodec_decode_video2(context, frame, &got_picture, &pkt)) < 0) {

你的代码让我担心,因为你手动初始化一个 AVPacket,但你没有告诉我们缓冲区/大小来自哪里。鉴于错误消息,我几乎可以肯定,您正在从文件、套接字或类似的东西中读取原始数据,就好像它是原始附件 b 流一样。

FFmpeg(或 Libav,就此而言)不接受此类数据作为其 H.264 解码器的输入。要解决此问题,请使用 AVParser,如前面 this 帖子中所述。

【讨论】:

  • 感谢您的回答。然而,这种情况并非如此。缓冲区包括 LIVE555 提供的一帧。这个问题似乎与 SPS 和 PPS 值有关。稍后我将发布对原始线程的更新。 :)
猜你喜欢
  • 2023-03-10
  • 2015-05-13
  • 2014-10-25
  • 2016-11-10
  • 2018-08-21
  • 2015-11-10
  • 2011-11-26
  • 2015-06-07
  • 2014-02-06
相关资源
最近更新 更多