视频保存为yuv文件

视频保存yuv文件,应考虑转换成什么yuv文件格式以及为什么要转换格式,还有改变视频画面宽高,核心函数是sws_scale

/**
* 本程序实现了视频文件解码为YUV数据。
*
*/
#include <stdio.h>


extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
};
const char* src_filename = "cuc_ieschool.flv";
const char* dst_filename = "output_test.yuv";
const int dst_w = 200,dst_h=200;
int video_stream_idx = -1;

int open_codec_context(int *stream_idx,
    AVFormatContext *fmt_ctx,AVCodecContext **codec_context, enum AVMediaType type)
{
    int ret;

    ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not find %s stream in input file '%s'\n",
            av_get_media_type_string(type), src_filename);
        return ret;
    }
    else {
        int stream_index = ret;
        AVStream *st = fmt_ctx->streams[stream_index];

        /* find decoder for the stream */
        *codec_context = st->codec;
        AVCodec *dec = avcodec_find_decoder((*codec_context)->codec_id);
        if (!dec) {
            fprintf(stderr, "Failed to find %s codec\n",
                av_get_media_type_string(type));
            return AVERROR(EINVAL);
        }


        if ((ret = avcodec_open2(*codec_context, dec, NULL)) < 0) {
            fprintf(stderr, "Failed to open %s codec\n",
                av_get_media_type_string(type));
            return ret;
        }
        *stream_idx = stream_index;
    }

    return 0;
}

void initPakcet(AVPacket *packet){

    av_init_packet(packet);
    packet->data = NULL;
    packet->size = 0;
}

void inityuvframe(AVFrame **yuvFrame,AVCodecContext* codec_context){
    *yuvFrame = av_frame_alloc();
    uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, dst_w, dst_h));
    avpicture_fill((AVPicture *)(*yuvFrame), out_buffer, AV_PIX_FMT_YUV420P, dst_w, dst_h);

}

void makeyuvfile(FILE *fp_yuv,AVFrame *yuvFrame){

    int y_size = dst_w * dst_h;
    fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
    fwrite(yuvFrame->data[1], 1, y_size / 4, fp_yuv);
    fwrite(yuvFrame->data[2], 1, y_size / 4, fp_yuv);
    av_frame_free(&yuvFrame);


}

void decodeVideo(AVFormatContext *format_context,AVCodecContext* codec_context){
    int framecount = 0;
    //用于改变像素格式或者图像宽高
    SwsContext *sws_ctx = sws_getContext(
        codec_context->width, codec_context->height, codec_context->pix_fmt,
        dst_w, dst_h, AV_PIX_FMT_YUV420P,
        SWS_BILINEAR, NULL, NULL, NULL);
    FILE *fp_yuv = fopen(dst_filename, "wb");
    while (1){
        int got_frame = 0;
        AVPacket packet;
        initPakcet(&packet);
        AVFrame *frame = av_frame_alloc();
        if (av_read_frame(format_context,&packet) >= 0){
            if (packet.stream_index == video_stream_idx){
                avcodec_decode_video2(codec_context, frame, &got_frame, &packet);
                if (got_frame){
                    //sws_getContext只是起手式,实际的图像转换在这里
                    AVFrame* yuvFrame = NULL;
                    inityuvframe(&yuvFrame,codec_context);
                    sws_scale(sws_ctx,
                        frame->data, frame->linesize, 0, frame->height,
                        yuvFrame->data, yuvFrame->linesize);
                    //AVFrame->YUV
                    makeyuvfile(fp_yuv,yuvFrame);
                    framecount++;
                    printf("parse %d\n", framecount);
                    av_free_packet(&packet);
                    av_frame_free(&frame);
                }
            }
        }
        else{
            break;
        }
    }
    fclose(fp_yuv);
    sws_freeContext(sws_ctx);

}

void main(int argc, char* argv[])
{
    AVFormatContext *fmt_ctx = NULL;
    AVCodecContext *codec_context = NULL;
    /* register all formats and codecs */
    av_register_all();
    avformat_network_init();

    /* open input file, and allocate format context */
    if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
        fprintf(stderr, "Could not open source file %s\n", src_filename);
        exit(1);
    }

    /* retrieve stream information */
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
        fprintf(stderr, "Could not find stream information\n");
        exit(1);
    }
    if (open_codec_context(&video_stream_idx, fmt_ctx, &codec_context, AVMEDIA_TYPE_VIDEO) < 0) {
        exit(1);
    }
    av_dump_format(fmt_ctx, 0, src_filename, 0);
    decodeVideo(fmt_ctx,codec_context);

    if (codec_context)
        avcodec_close(codec_context);
    if (fmt_ctx)
        avformat_close_input(&fmt_ctx);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值