嵌入式Linux下FFmpeg为AVFrame绑定预分配Buffer是否可行?
我正在基于嵌入式Linux系统(5.10.200)开发视频播放器,使用FFmpeg-4.4.4库构建。我希望将预分配的buffer绑定到AVFrame以接收解码数据,具体代码如下:
#define FRM_WIDTH 1920 #define FRM_HEIGHT 1080 AVFrame myframe; uint8_t *buffer; int init_frame_buffer(void) { int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, FRM_WIDTH, FRM_HEIGHT, 1); buffer = (uint8_t *)av_malloc(num_bytes * sizeof(uint8_t)); av_image_fill_arrays(myframe.data, myframe.linesize, buffer, AV_PIX_FMT_RGB32, FRM_WIDTH, FRM_HEIGHT, 1); .... } int process_decoded_frame(AVFrame *pframe) { // Can use buffer to process the decoded frame? } int process_packet(AVCodecContext *codectx, AVPacket *pkt) { int ret = avcodec_send_packet(codectx, pkt); AVFrame *pframe = &myframe; if (ret < 0) { fprintf(stderr, "Error sending packet for decoding\n"); return ret; } while (ret >= 0) { ret = avcodec_receive_frame(codectx, pframe); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error during decoding\n"); goto out; } process_decoded_frame(pframe); //// <<<< } }
具体步骤为:
- 分配
buffer; - 将其绑定到
myframe; - 在
avcodec_receive_frame中使用myframe,期望解码帧数据存入myframe和buffer; - 直接用
buffer处理解码数据。
请问上述步骤是否可行?
可行,但必须满足严格前提并注意以下关键问题:
像素格式匹配是核心前提
你预分配的缓冲区格式是AV_PIX_FMT_RGB32,但FFmpeg解码器默认输出原生格式(比如H.264解码器通常输出YUV420P)。如果解码器输出格式与预分配格式不匹配,avcodec_receive_frame会直接返回错误。必须在打开解码器前,通过codectx->pix_fmt = AV_PIX_FMT_RGB32强制设置输出格式,否则需要后续调用sws_scale做格式转换。AVFrame结构体需完整初始化
当前代码仅调用av_image_fill_arrays绑定缓冲区,但myframe的width、height、format等核心字段未初始化,可能引发未定义行为。建议在绑定缓冲区前先调用av_frame_init(&myframe)完成结构体初始化,或使用av_frame_unref(&myframe)重置状态。缓冲区对齐与大小需匹配
av_image_get_buffer_size的最后一个参数是行对齐值,你传入的1可能不符合解码器的对齐要求,存在缓冲区溢出风险。建议传入0(使用FFmpeg默认对齐值AV_INPUT_BUFFER_PADDING_SIZE),确保计算的缓冲区大小与解码器需求完全匹配。多线程解码的线程安全问题
如果开启了解码多线程(codectx->thread_count > 1),复用同一个myframe会导致多个线程同时写入缓冲区,引发数据混乱。这种场景下必须为每个解码线程分配独立的AVFrame和缓冲区。内存释放规范
退出时必须调用av_free(buffer)释放预分配的缓冲区,同时调用av_frame_unref(&myframe)重置AVFrame结构体,避免内存泄漏。数据访问的可选方式
在process_decoded_frame中,既可以直接使用全局的buffer,也可以通过pframe->data[0]访问数据(两者指向同一块内存),后者更符合FFmpeg API的使用习惯,代码可维护性更强。
内容的提问来源于stack exchange,提问作者wangt13

