04 ffmpeg 从媒体文件解封装,输出YUV420图像
2017-10-30 01:16
441 查看
输出AAC声音目前有点问题:
输出YUV420 很好
Makefile 与使用方法:
输出YUV420 很好
[root@localhost 04]# cat main.c #include <stdio.h> #include "libavformat/avformat.h" int frame_width = 0; int frame_height = 0; const char *src_filename = NULL; const char *video_filename = NULL; const char *audio_filename = NULL; unsigned char *video_dst_data[4]; int video_dst_linesize[4]; int video_dst_buffersize; enum AVPixelFormat pix_fmt; //tmp var AVFormatContext *fmt_ctx = NULL; AVStream *pStream = NULL; AVCodec *pcodec = NULL; AVCodecContext *pCodecContext = NULL; //video & audio var AVStream *pVideoStream = NULL; AVStream *pAudioStream = NULL; AVCodecContext *pVideoCodecContext = NULL; AVCodecContext *pAudioCodecContext = NULL; FILE *pFilein = NULL; FILE *pFileVideoOut = NULL; FILE *pFileAudioOut = NULL; AVFrame *frame = NULL; AVPacket packet; static int open_codec_context(enum AVMediaType type) { int ret = 0; ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); if(ret < 0) { printf("av_find_best_stream fail [%d]\n", ret); return -1; } printf("av_find_best_stream OK [%d] \n", ret); pStream = fmt_ctx->streams[ret]; pCodecContext = pStream->codec; pcodec = avcodec_find_decoder(pCodecContext->codec_id); if(NULL == pcodec) { printf("avcodec_find_decoder error \n"); return -1; } ret = avcodec_open2(pCodecContext, pcodec, NULL); if(ret < 0) { printf("avcodec_open2 error [%d]", ret); return -1; } } static int decode_packet(int *got_frame) { int ret = 0 ; if(packet.stream_index == pVideoStream->index) { //该packet属于视频 ret = avcodec_decode_video2(pVideoCodecContext, frame, got_frame, &packet); printf("deal audio packet size=[%d], ", packet.size); if(ret < 0) { printf("Error: decodec video frame \n"); return -1; } if(*got_frame) { printf("got audio frame, packet size=[%d]\n", packet.size); av_image_copy(video_dst_data, video_dst_linesize, (const char **)frame->data, frame->linesize, pix_fmt, frame_width, frame_height); fwrite(video_dst_data[0],1, video_dst_buffersize, pFileVideoOut); } } else if(packet.stream_index == pAudioStream->index) { //该packet属于音频 ret = avcodec_decode_audio4(pAudioCodecContext, frame, got_frame, &packet); printf("deal audio packet size=[%d], ", packet.size); if(ret < 0) { printf("Error: decodec audio frame \n"); return -1; } if(*got_frame) { printf("got video frame, packet size=[%d]\n", packet.size); size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); fwrite(frame->extended_data[0], 1, unpadded_linesize, pFileAudioOut); } } else { printf("unknow stream \n"); exit(0); } return packet.size; } int main(int argc, char **argv) { int ret = 0; if(argc == 4) { src_filename = argv[1]; video_filename = argv[2]; audio_filename = argv[3]; printf("parameter OK \n"); printf("src_filename:[%s] \n", src_filename); printf("video_filename:[%s] \n", video_filename); printf("audio_filename:[%s] \n", audio_filename); } else { printf("parameter ERROR: \n"); return -1; } //加载编解码器 av_register_all(); //根据输入的视频文件初始化 AVFormatContext ret = avformat_open_input(&fmt_ctx, src_filename, NULL, NULL); if(ret < 0) { printf("ERROR avformat_open_input fail [%d] \n", ret); return -1; } printf("avformat_open_input OK [%d] \n", ret); //根据视频信息,查找解码器 ret = avformat_find_stream_info(fmt_ctx, NULL); if(ret < 0) { printf("ERROR avformat_find_stream_info [%d]\n", ret); return -1; } printf("avformat_find_stream_info OK [%d] \n", ret); //打开视频 ret = open_codec_context(AVMEDIA_TYPE_VIDEO); if(ret < 0) { printf("open_codec_context ERROR [%d]", ret); return -1; } pVideoStream = pStream; pVideoCodecContext = pCodecContext; frame_width = pVideoCodecContext->width; frame_height = pVideoCodecContext->height; pix_fmt = pVideoCodecContext->pix_fmt; printf("frame_width=[%d] \n", frame_width); printf("frame_height=[%d] \n", frame_height); ret = av_image_alloc(video_dst_data, video_dst_linesize, frame_width, frame_height, pix_fmt, 1); if(ret < 0) { printf("av_image_alloc error [%d] \n", ret); return -1; } printf("av_image_alloc buffersize=[%d] \n", ret); video_dst_buffersize = ret; pFileVideoOut = fopen(video_filename, "wb"); if(NULL == pFileVideoOut) { printf("foopen video_filename ERROR\n"); return -1; } // 打开音频 ret = open_codec_context(AVMEDIA_TYPE_AUDIO); if(ret < 0) { printf("open_codec_context Audio ERROR [%d]", ret); return -1; } pAudioStream = pStream; pAudioCodecContext = pCodecContext; pFileAudioOut = fopen(audio_filename, "wb"); if(NULL == pFileAudioOut) { printf("foopen audio_filename ERROR\n"); return -1; } av_dump_format(fmt_ctx, 0, src_filename, 0);//输出信息 //读取和处理音视频数据 frame = av_frame_alloc(); if(NULL == frame) { printf("av_frame_alloc error \n"); return -1; } printf("av_frame_alloc OK \n"); av_init_packet(&packet); packet.data = NULL; packet.size = 0 ; int get_frame_flags; while(av_read_frame(fmt_ctx, &packet) >= 0)//从文件中读取出1帧 { while(packet.size > 0) { ret = decode_packet(&get_frame_flags); packet.data += ret; packet.size -= ret; } } //处理缓存区的数据 packet.data = NULL; packet.size = 0; while(get_frame_flags) { ret = decode_packet(&get_frame_flags); packet.data += ret; packet.size -= ret; } //收尾工作 avcodec_close(pVideoCodecContext); avcodec_close(pAudioCodecContext); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_free(video_dst_data[0]); fclose(pFilein); fclose(pFileVideoOut); fclose(pFileAudioOut); return 0; } [root@localhost 04]#
Makefile 与使用方法:
[root@localhost 04]# cat makefile FLAGS = -g INCLUDEPATH = -I /home/ffmpeg_dev/include/ LIBPATH = -L /home/ffmpeg_dev/lib/ LIBS= -l avcodec \ -l pthread \ -l avutil \ -l m \ -l dl \ -l swresample \ -l avformat \ exe=test $(exe): gcc main.c ${FLAGS} ${INCLUDEPATH} ${LIBPATH} ${LIBS} -o $@ clean: rm -rf ${exe} [root@localhost 04]# [root@localhost 04]# cat auto.sh clear make clean make ./test in.mp4 out.yuv out.aac [root@localhost 04]#
相关文章推荐
- [学习笔记]基于ffmpeg的视频解码,输出YUV图像到文件。
- 我的Android进阶之旅------>Android使用正则表达式匹配扫描指定目录下的所有媒体文件(音乐、图像、视频文件)
- ffmpeg将flv解封装为h264和mp3文件测试代码
- ffmpeg 重写tutorial01程序--将一个视频文件解码输出bmp和jpg文件
- 用directshow做的一个媒体文件播放器,有图像无声音----解决办法
- 请求之前~HttpHandler实现媒体文件和图像文件的盗链
- 如何用ffmpeg解码H.264文件为一帧帧图像
- ffmpeg 输出日志到文件
- opencv输出图像数据到txt文件
- 利用FFmpeg将H.264文件读入内存,再输出封装格式文件
- 在ffmpeg中增加libavformat库所支持格式的媒体文件
- 深入分析FFmpeg之一-打开媒体文件并读取文件头信息
- 【转】ffmpeg解码含有B帧的视频文件的输出顺序
- AutoCAD输出图像文件技巧
- 关于Tomcat调用FFmpeg进行切片转码输出文件权限不足的问题-----终于得到解决!!!
- ffmpeg输出x264的CBR流或者文件
- ffmpeg——AVOutputFormat 输出文件格式
- iOS开发的一些小技术:让UIImage有缩放功能、控制log的输出、xcode修改文件注释、随机数的使用、在UIImageView 中旋转图像、在Quartz中如何设置旋转点、创建.plist文件并存储
- 处理媒体文件的工具ffmpeg
- YUV420图像转换到400图像并输出