libav C++ sw_scale returns BGR24 缓冲区的可变字节大小
libav C++ sw_scale returns variable byte size of BGR24 buffer
我正在尝试将本地 /dev/video0 摄像头转换为 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
缓冲区时,我是 ignoring/forgetting 缓冲区的长度。感谢 @SuRGeoNix 指引我正确的方向。
我正在尝试将本地 /dev/video0 摄像头转换为 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
缓冲区时,我是 ignoring/forgetting 缓冲区的长度。感谢 @SuRGeoNix 指引我正确的方向。