视频保存为yuv文件

来源:互联网 发布:java编程用户管理系统 编辑:程序博客网 时间:2024/06/07 01:40

视频保存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);}
阅读全文
0 0
原创粉丝点击