使用ffmpeg将视频解析为YUV420

来源:互联网 发布:网络实时监控软件 编辑:程序博客网 时间:2024/06/06 22:32

 使用ffmpeg解析视频文件为YUV420,下载最新的 ffmpeg-20151221-git-c0f67e1-win32-dev 版本的开发库,然后用里面的sample做熟悉测试,发现由不少问题,还以为在Win7+VS2010中无法编译呢。但是经过一天多的查找终于解决了,实现了avi和mp4视频的解析(只做了这两种格式的测试)为YUV420.下面的代码是在filtering_video.c例子上做了改进得到的。

#ifdef __cplusplusextern "C" {#endif#include<stdio.h>#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libavutil/opt.h>#ifdef __cplusplus}#endifstatic AVFormatContext *fmt_ctx;static AVCodecContext *dec_ctx;static int video_stream_index = -1;static int open_input_file(const char *filename){    int ret;    AVCodec *dec;    if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {        av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");        return ret;    }    if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {        av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");        return ret;    }    /* select the video stream */    ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);    if (ret < 0) {        av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");        return ret;    }    video_stream_index = ret;    dec_ctx = fmt_ctx->streams[video_stream_index]->codec;    av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);    /* init the video decoder */    if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {        av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");        return ret;    }    return 0;}int main(int argc, char **argv){    int ret;int got_frame;    AVPacket packet;    AVFrame *frame = av_frame_alloc();    if (!frame) {        perror("Could not allocate frame");        exit(1);    }    av_register_all();    if ((ret = open_input_file(argv[1])) < 0){printf("open_input_file wrong\n");        exit(1);        }clock_t start = 0;FILE *fp = fopen("video.yuv", "wb");    /* read all packets */    while (1){        if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)        {break;}        if (packet.stream_index == video_stream_index) {            got_frame = 0;start = clock();            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet);            if (ret < 0) {                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");                break;            }printf("Time:  %d\n",(clock()-start));            if (got_frame){//use to ouput 1920*1080 yuv420 video with faster speed, need data line alignment//fwrite(frame->data[0], sizeof(frame->data[0][0]), frame->width*frame->height, fp);//fwrite(frame->data[1], sizeof(frame->data[1][0]), frame->width*frame->height/4, fp);//fwrite(frame->data[2], sizeof(frame->data[2][0]), frame->width*frame->height/4, fp);//can be used to ouput any size yuv420 video with fast speed//int width = dec_ctx->width, height = dec_ctx->height;//int height_half = height / 2, width_half = width / 2;//int y_wrap = frame->linesize[0];//int u_wrap = frame->linesize[1];//int v_wrap = frame->linesize[2];//unsigned char *y_buf = frame->data[0];//unsigned char *u_buf = frame->data[1];//unsigned char *v_buf = frame->data[2];////save y//for (int i = 0; i < height; i++)//fwrite(y_buf + i * y_wrap, 1, width, fp);////save u//for (int i = 0; i < height_half; i++)//fwrite(u_buf + i * u_wrap, 1, width_half, fp);////save v//for (int i = 0; i < height_half; i++)//fwrite(v_buf + i * v_wrap, 1, width_half, fp);//fflush(fp);                av_frame_unref(frame);            }        }        av_packet_unref(&packet);    }fclose(fp);    avcodec_close(dec_ctx);    avformat_close_input(&fmt_ctx);    av_frame_free(&frame);system("pause");    return 0;}

参考链接:

http://www.cnblogs.com/lidabo/p/3326502.html

http://m.blog.csdn.net/blog/sun6623518/8602372


0 0
原创粉丝点击