libavcodec:如何将原始视频(YUV420P)帧编码为有效位图以保存到“ .bmp”文件?

时间:2019-11-20 05:22:23

标签: ffmpeg yuv libavcodec

我试图通过使用libavcodec将原始视频(YUV420P)编码为AV_CODEC_ID_BMP格式,将随机视频帧保存到'.bmp'文件中,但结果是图像损坏,包含3个RGB通道:

resulting bmp

channels: blue

channels: green

channels: red

original yuv frame

这是我的功能代码(获取当前的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;
}

有人知道如何正确执行此操作吗?

0 个答案:

没有答案