c - libav C++ sw_scale 返回 BGR24 缓冲区的可变字节大小

标签 c ffmpeg libav libavformat swscale

我正在尝试将我的本地/dev/video0 cam 转换为 BGR24 格式。如果我调整图像大小(虽然不是 100% 的时间,更像是 85% 的时间),它会起作用,但我想保持与输入视频相同的大小。
我像这样初始化 BGR 图像,包括 sws 上下文:

AVPixelFormat outputPixFormat = AV_PIX_FMT_BGR24;

    AVFrame* pFrameBGR = av_frame_alloc();
    pFrameBGR->width = decoder->video_codec_context->width;
    pFrameBGR->height = decoder->video_codec_context->height;
    pFrameBGR->format = outputPixFormat;

    int alloRet = av_image_alloc(pFrameBGR->data, pFrameBGR->linesize, decoder->video_codec_context->width, decoder->video_codec_context->height, outputPixFormat, 1);
    if (alloRet < 0) {
        logging("failed to allocate image");
        return -1;
    }

    struct SwsContext *sws_ctx = NULL;

    sws_ctx = sws_getContext(decoder->video_codec_context->width,
    decoder->video_codec_context->height,
    decoder->video_codec_context->pix_fmt,
    decoder->video_codec_context->width,
    decoder->video_codec_context->height,
    outputPixFormat,
    SWS_DIRECT_BGR,
    0,
    0,
    0
    );
这是我的解码循环的一部分:
int response = avcodec_send_packet(pCodecContext, pPacket);
    if (response < 0) {
        logging("Error while sending a packet to decoder: %s", av_err2str(response));
        return response;
    }

    while (response >= 0) {
        response = avcodec_receive_frame(pCodecContext, pFrame);
         if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
            break;
        } else if (response < 0) {
            logging("Error while receiving a frame from the decoder: %s", av_err2str(response));
            return response;
        }
        if (response >= 0) {

            sws_scale(sws_ctx,  (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecContext->height, pFrameBGR->data, pFrameBGR->linesize);

THe question is how to copy the plane of AVFrame into a buffer :
  size_t rgb_size = av_image_get_buffer_size(AV_PIX_FMT_BGR24, bgrFrame->width, bgrFrame->height, 1);

    uint8_t *dst_data;
    dst_data = (uint8_t *)(av_malloc(rgb_size));

    av_image_copy_to_buffer(dst_data, rgb_size, (const uint8_t* const *)bgrFrame->data, bgrFrame->linesize, AV_PIX_FMT_BGR24, bgrFrame->width, bgrFrame->height, 1);

如果我尝试保存到文件 BGR 图像被正确复制:
char filebuf[256];
snprintf(filebuf, sizeof filebuf, "%s%d%s", "out_", pPacket->dts, ".rgb");
std::FILE *output=fopen(filebuf,"wb+");  

fwrite(bgrFrame->data[0],(pFrame->width)*(pFrame->height)*3,1,output);  
std::fclose(output);
所以看起来我的缓冲区功能有问题,但我可以弄清楚它有什么问题:
  uint8_t *dst_data;
    dst_data = (uint8_t *)(av_malloc(rgb_size));

    av_image_copy_to_buffer(dst_data, rgb_size, (const uint8_t* const *)bgrFrame->data, bgrFrame->linesize, AV_PIX_FMT_BGR24, bgrFrame->width, bgrFrame->height, 1);

最佳答案

上面的代码是完全正确的。问题出在序列化 dst_data 的后续代码中。我忽略/忘记缓冲区长度的缓冲区。感谢 @SuRGeoNix引导我走向正确的方向。

关于c - libav C++ sw_scale 返回 BGR24 缓冲区的可变字节大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66500358/

相关文章:

c# - Word16 和 UWord16 之间的混淆

image - 如何使用ffmpeg从视频中制作平铺图像

c++ - 获取合成时间 C++

FFmpeg/Libav 音频解码示例

c++ - 将帧号/索引添加到 AVFrame 对象

c - 如何将链表中的节点分割成 8 字节的 block ?

c - 自然排序与 qsort 不起作用

ffmpeg - 使用 FFMPEG 从 720p .mov 文件转换的 FLV 视频缺少音频和播放问题

php - 多个视频上传时如何处理视频编码排队?

c++ - C和C++中的全局变量有什么区别?