libav - 解码H264帧错误

3

我正在尝试使用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() 的返回值是什么? - Anton Angelov
返回值等于剩余字节数。此外,got_picture指针不为零 - 因此,我认为解压成功了。然而,我总是收到这个错误。 - chrisp
我甚至不知道错误信息想要表达什么。错误在谈论哪个缓冲区? - chrisp
你从哪里获取最终的数据包(h264帧)?您是否使用 libavformat 从容器中读取它?此外,您是否使用实际版本的 libav? - Anton Angelov
我正在使用LIVE555接收H264帧,然后使用libav进行解码。这是一个实时流。 - chrisp
@AntonAngelov,我正在使用11.04。你知道这个错误应该是什么意思吗?这个错误在谈论哪个缓冲区? - chrisp
2个回答

1
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,但是您没有告诉我们缓冲区/大小来自何处。根据错误消息,我几乎可以确定您正在从文件、套接字或类似的地方读取原始数据,就像它是原始annexb流一样。
FFmpeg(或Libav)不接受这样的数据作为其H.264解码器的输入。要解决此问题,请使用AVParser,如this帖子中先前所述。

谢谢您的回答。然而,这并不是情况。缓冲区包含LIVE555传递的一个帧。问题似乎与SPS和PPS值有关。我会在原始线程中发布更新。 :) - chrisp

1

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

而且@AntonAngelov,我正在使用11.04。您知道错误应该是什么吗?错误所说的缓冲区是什么?

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

似乎错误表示您发送到解码器的NALU数据包的大小为0

我猜想您必须以某种方式从LIVE555获取SPSPPS头,并通过extradata将它们提供给解码器(还必须设置extradata_size),然后才能调用avcodec_open2()。

另一个想法是将接收到的所有数据包都倒入一个单独的 .h264 文件中,然后使用解析 h264 比特流的软件 (例如此处)。同时尝试使用 avplayVLC 播放,查看比特流是否正确。

编辑: 这里 有一个类似的问题得到了回答。


谢谢您的回复。这为我缩小了错误范围。我将再次查看PPS和SPS单元的解码。目前,我正在使用LIVE555的´fmtp_spropparametersets´函数接收这些单元。也许在尝试解码参数集时存在问题。此外,我将重新检查我所使用的libav版本。明天我会回复您所有的信息(现在不在家)。您的第二个想法很好,但是我以前已经使用ffplay做过了。因此,比特流似乎没问题。 - chrisp
@Chris。你找出问题了吗?我也遇到了同样的情况,使用Live555 + Libav。解码正常,但是不断输出缓冲区大小错误。 - Sergio Basurco
1
@chuckleplant 我重新下载了libav并修复了SPS和PPS初始化的问题。 - chrisp
@Chris。这就是我尝试做的事情,我通过Live接收SPS PPS并将其设置在Libav的pCodecCtx->extradata上。应该没问题了,但我仍然得到错误输出。谢谢! - Sergio Basurco
1
@chuckleplant 尝试调试它。使用十六进制编辑器在通过网络发送的原始h264比特流中搜索SPS和PPS值。然后使用base64进行编码,并将其与您在客户端应用程序中设置的内容进行比较。 - chrisp
重新下载libav加一分。对于我来说,“缓冲区大小太短”的输出是一个bug,这在Libav的11.4版本中出现过。与SPS / PPS无关。 - Sergio Basurco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接