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

问题描述

我正在尝试将我的本地 /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->pix_fmt,SWS_DIRECT_BGR,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,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,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,1);

解决方法

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...