您的位置:首页 > 其它

使用ffmpeg将视频解析为YUV420

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

#ifdef __cplusplus
extern "C" {
#endif
#include<stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>

#ifdef __cplusplus
}
#endif

static 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: