我试图通过使用libavcodec将原始视频(YUV420P)编码为AV_CODEC_ID_BMP格式,将随机视频帧保存到'.bmp'文件中,但结果是图像损坏,包含3个RGB通道:
这是我的功能代码(获取当前的yuv帧并将其编码为BMP)
int
__create_bmp(AVPacket *pkt, AVCodecContext *video_dec_ctx,
int video_stream_idx)
{
int err = 0;
int got_frame = 0;
static int vfnum = 0; //current v.frame num
if (pkt->stream_index == video_stream_idx) {
fprintf(stderr, "AVCodecContext codec: (name: %s), ID %d\n",
video_dec_ctx->codec->name, video_dec_ctx->codec_id);
/* decode video frame */
AVFrame *frame = av_frame_alloc();
// !!! 'avcodec_decode_video2' IS DEPRECATED !!!
err = avcodec_decode_video2(video_dec_ctx, frame, got_frame, pkt);
if (err < 0) {
fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(err));
return err;
}
if(got_frame == 0) return 1;
// !!! this dbg func save mjpeg YUV420P into '.jpg' file FINE !!!
__encode_image_frame(frame);
AVCodec *bmpc = avcodec_find_encoder(AV_CODEC_ID_BMP);
if(bmpc == NULL){
fprintf(stderr, "'AV_CODEC_ID_BMP' encoder NOT FOUND!.\n");
exit(-1);
}
AVCodecContext *__bmpcc = avcodec_alloc_context3(bmpc);
__bmpcc->width = frame->width;
__bmpcc->height = frame->height;
__bmpcc->pix_fmt = AV_PIX_FMT_BGR24;
__bmpcc->time_base = (AVRational){1,1};
err = avcodec_open2(__bmpcc, bmpc, NULL);
if(err == 0){
fprintf(stderr, "avcodec_open2 success.\n");
}else{
fprintf(stderr, "avcodec_open2 ERROR!\n");
}
err = avcodec_send_frame(__bmpcc, frame);
if(err == 0){
fprintf(stderr, "avcodec_send_frame success.\n");
}
else{
fprintf(stderr, "avcodec_send_frame ERROR! (code: %d)\n",err);
}
AVPacket *bmp_pkt = av_packet_alloc();
err = avcodec_receive_packet(__bmpcc, bmp_pkt);
if(err == 0){
fprintf(stderr, "avcodec_receive_packet success.\n");
}
else{
fprintf(stderr, "avcodec_receive_packet ERROR! (code: %d)\n",err);
}
av_frame_unref(frame);
/* write to bitmap file */
char outimg[2048] = {0};
snprintf(outimg, 2048,"out-%06d.bmp", vfnum);
FILE *outf = fopen(outimg, "wb");
vfnum++;
if (!outf) {
fprintf(stderr, "Could not open destination file %s\n", outimg);
}else{
fwrite(bmp_pkt->data, 1, bmp_pkt->size , outf);
fclose(outf);
}
av_packet_unref(bmp_pkt);
return 0;
}
return 1;
}
有人知道如何正确执行此操作吗?