ffmpeg avcodec_receive_packet一直返回-11

软解码和软编码时都没问题,换成硬解码之后,程序一直卡在avcodec_receive_frame这里,一直返回-11

    std::cout << output <<std::endl;
    while (av_read_frame(fmt_ctx, &avpkt) >= 0) {
        if (avpkt.stream_index == stream_index) {
            // 8 发送等待解码帧
            int re = avcodec_send_packet(codeCtx, &avpkt);
            if (re < 0) {
                continue;
            }
            std::cout << 1 << std::endl;
            // 9 接收解码后frame数据
            std::cout << avcodec_receive_frame(codeCtx, frame) << std::endl;
            while (avcodec_receive_frame(codeCtx, frame) == 0) {
                // 拼接图片路径、名称,测试输出用
                snprintf(buf, sizeof(buf), "%s/Demo-%d.jpg", output, frame_count++);
                std::cout << 2 << std::endl;
                width = frame->width;
                height = frame->height;
                Encode2Jpg(frame); //保存为jpg图片
            }

            // 测试从内存读数据到文件里是否正常  
            FILE *fp = fopen(buf,"wb");
            fwrite(bd_out.ptr, sizeof(char), bd_out.size, fp);
            fclose(fp);
        }
        av_packet_unref(&avpkt);
    }

这个问题可能是由于在硬解码模式下,解码器需要更多的时间来处理数据,因此在调用avcodec_receive_frame时可能会返回EAGAIN(-11)错误,表示解码器需要更多的输入数据才能产生输出帧。

你可以尝试修改你的代码,当avcodec_receive_frame返回-11时,再次发送数据到解码器,直到avcodec_receive_frame返回0,表示成功接收到解码后的帧。你可以尝试以下修改后的代码:

while (av_read_frame(fmt_ctx, &avpkt) >= 0) {
    if (avpkt.stream_index == stream_index) {
        // 8 发送等待解码帧
        int re = avcodec_send_packet(codeCtx, &avpkt);
        if (re < 0) {
            continue;
        }
        std::cout << 1 << std::endl;
        // 9 接收解码后frame数据
        int ret;
        while ((ret = avcodec_receive_frame(codeCtx, frame)) == 0) {
            // 拼接图片路径、名称,测试输出用
            snprintf(buf, sizeof(buf), "%s/Demo-%d.jpg", output, frame_count++);
            std::cout << 2 << std::endl;
            width = frame->width;
            height = frame->height;
            Encode2Jpg(frame); //保存为jpg图片
        }
        if (ret == AVERROR(EAGAIN)) {
            // 解码器需要更多数据,继续发送数据
            continue;
        } else if (ret < 0) {
            // 其他错误
            break;
        }
        // 测试从内存读数据到文件里是否正常
        FILE *fp = fopen(buf,"wb");
        fwrite(bd_out.ptr, sizeof(char), bd_out.size, fp);
        fclose(fp);
    }
    av_packet_unref(&avpkt);
}

这样修改后,当解码器需要更多的输入数据时,会继续发送数据,直到成功接收到解码后的帧。

avcodec_receive_frame返回-11的错误代码是EAGAIN。这种情况通常表示当前没有可用的输出帧,需要发送更多的输入数据。您可以尝试增加更多的输入数据以及等待更长的时间,以等待解码器输出可用的帧。同时,您也可以检查解码器的设置是否正确,并且可能需要升级您的硬件设备以提高计算能力和内存速度。

这段代码中的问题可能是在接收解码后frame数据时,使用了两次avcodec_receive_frame函数,而且没有检查返回值。您可以尝试修改代码如下:

std::cout << output <<std::endl;
while (av_read_frame(fmt_ctx, &avpkt) >= 0) {
    if (avpkt.stream_index == stream_index) {
        // 8 发送等待解码帧
        int re = avcodec_send_packet(codeCtx, &avpkt);
        if (re < 0) {
            continue;
        }
        std::cout << 1 << std::endl;
        // 9 接收解码后frame数据
        while (true) {
            int ret = avcodec_receive_frame(codeCtx, frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                break;
            }
            if (ret < 0) {
                std::cerr << "Error while receiving a frame from the decoder: " << av_err2str(ret) << std::endl;
                exit(1);
            }
            // 拼接图片路径、名称,测试输出用
            snprintf(buf, sizeof(buf), "%s/Demo-%d.jpg", output, frame_count++);
            std::cout << 2 << std::endl;
            width = frame->width;
            height = frame->height;
            Encode2Jpg(frame); //保存为jpg图片

            // 测试从内存读数据到文件里是否正常  
            FILE *fp = fopen(buf,"wb");
            fwrite(bd_out.ptr, sizeof(char), bd_out.size, fp);
            fclose(fp);
        }
    }
    av_packet_unref(&avpkt);
}

这样可以避免多次调用avcodec_receive_frame函数,同时也增加了对函数返回值的检查。

  • 这篇文章讲的很详细,请看:avcodec_send_frame和avcodec_receive_packet
  • 除此之外, 这篇博客: ffplay分析(视频解码线程的操作)中的 9、decoder_decode_frame():调用avcodec_send_packet() 进行解码 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 在这里插入图片描述

  • 以下回答由chatgpt基于相关博客总结生成:

    根据参考资料和问题描述,可以初步得出以下结论:

    1. 使用FFmpeg进行硬解码时,在调用avcodec_receive_frame函数时一直卡住并返回错误码-11。
    2. 而软解码和软编码时没有问题。
    3. 需要更多详细信息,例如输入的视频格式、FFmpeg的版本、硬件设备等,以便更好地理解问题并提供解决方案。

    针对这个问题,可能需要对以下方面进行排查和处理:

    1. 确认输入的视频格式是否支持硬解码。不同的硬件设备、操作系统和FFmpeg版本支持的视频格式不同,需要确保使用的视频格式能够被硬解码器支持。
    2. 确认硬件设备是否正常。如果硬件设备损坏或者不支持硬件解码,就会导致解码出错。
    3. 确认FFmpeg版本是否正常。不同版本的FFmpeg有不同的功能支持和Bug修复,需要确保使用的FFmpeg版本能够正确解析视频。
    4. 检查代码实现是否正确。需要对视频流的解码、解封装、送入空包等步骤逐个进行排查和确认,确认代码实现是否正确。

    因为这个问题涉及到具体的硬件设备、FFmpeg版本和代码实现,需要更多的信息和具体的排查过程才能够找到问题的根本原因并提供解决方案。在此无法提供具体的代码实现和解决方案,建议结合具体的场景和资料逐个排查和分析,找到问题后再进行相应的解决方案。