Android 音视频深入 九 FFmpeg解码视频生成yuv文件(附源码下载)
项目地址,求star
https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(MP4%E8%BD%ACyuv%EF%BC%89
这一次是将MP4解码出yuv文件出来,先介绍一波yuv文件
YUV是指亮度参量和色度参量分开表示的像素格式,而这样分开的好处就是不但可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大。YUV是一个比较笼统地说法,针对它的具体排列方式,可以分为很多种具体的格式。
直接上主菜,如何将MP4解码出yuv文件
首先在java使用NDK,调用解码函数,输入MP4文件的路径和输出yuv文件的路径
decode(inputurl,outputurl);
接下来就是正式的解说FFmpeg相关函数的作用了
先来一张图片,理清代码运行顺序
接下来看注释,。。。。要是每一个函数详细的讲,我做不到,也写不完,重在熟悉流程
- //1.注册所有组件
- av_register_all();
- //初始网络流
- avformat_network_init();
- //封装格式上下文,统领全局的结构体,保存了视频文件封装格式的相关信息
- pFormatCtx = avformat_alloc_context();
- //2.打开输入视频文件
- if(avformat_open_input(&pFormatCtx,input_str,NULL,NULL)!=0){
- LOGE("Couldn't open input stream.\n");
- return -1;
- }
- //3.获取视频文件信息
- if(avformat_find_stream_info(pFormatCtx,NULL)<0){
- LOGE("Couldn't find stream information.\n");
- return -1;
- }
- //获取视频流的索引位置
- //遍历所有类型的流(音频流、视频流、字幕流),找到视频流
- videoindex=-1;
- for(i=0; i<pFormatCtx->nb_streams; i++)
- if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
- videoindex=i;
- break;
- }
- if(videoindex==-1){
- LOGE("Couldn't find a video stream.\n");
- return -1;
- }
- //只有知道视频的编码方式,才能够根据编码方式去找到解码器
- //获取视频流中的编解码上下文
- pCodecCtx=pFormatCtx->streams[videoindex]->codec;
- //4.根据编解码上下文中的编码id查找对应的解码
- pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
- if(pCodec==NULL){
- LOGE("Couldn't find Codec.\n");
- return -1;
- }
- if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){
- LOGE("Couldn't open codec.\n");
- return -1;
- }
- pFrame=av_frame_alloc();
- pFrameYUV=av_frame_alloc();
- out_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,1));
- av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer,
- AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height,1);
- //准备读取
- //AVPacket用于存储一帧一帧的压缩数据(H264)
- //缓冲区,开辟空间
- packet=(AVPacket *)av_malloc(sizeof(AVPacket));
- //用于转码(缩放)的参数,转之前的宽高,转之后的宽高,格式等
- img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
- pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
- //输出视频信息
- sprintf(info, "[Input ]%s\n", input_str);
- sprintf(info, "%s[Output ]%s\n",info,output_str);
- sprintf(info, "%s[Format ]%s\n",info, pFormatCtx->iformat->name);
- sprintf(info, "%s[Codec ]%s\n",info, pCodecCtx->codec->name);
- sprintf(info, "%s[Resolution]%dx%d\n",info, pCodecCtx->width,pCodecCtx->height);
- fp_yuv=fopen(output_str,"wb+");
- if(fp_yuv==NULL){
- printf("Cannot open output file.\n");
- return -1;
- }
- frame_cnt=0;
- time_start = clock();
- //6.一帧一帧的读取压缩数据
- while(av_read_frame(pFormatCtx, packet)>=0){
- //只要视频压缩数据(根据流的索引位置判断)
- if(packet->stream_index==videoindex){
- //7.解码一帧视频压缩数据,得到视频像素数据
- ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
- if(ret < 0){
- LOGE("Decode Error.\n");
- return -1;
- }
- //为0说明解码完成,非0正在解码
- if(got_picture){
- //AVFrame转为像素格式YUV420,宽高
- //2 6输入、输出数据
- //3 7输入、输出画面一行的数据的大小 AVFrame 转换是一行一行转换的
- //4 输入数据第一列要转码的位置 从0开始
- //5 输入画面的高度
- sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
- pFrameYUV->data, pFrameYUV->linesize);
- //输出到YUV文件
- //AVFrame像素帧写入文件
- //data解码后的图像像素数据(音频采样数据)
- //Y 亮度 UV 色度(压缩了) 人对亮度更加敏感
- //U V 个数是Y的1/4
- y_size=pCodecCtx->width*pCodecCtx->height;
- fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y
- fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
- fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V
- //Output info
- char pictype_str[10]={0};
- switch(pFrame->pict_type){
- case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;
- case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;
- case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;
- default:sprintf(pictype_str,"Other");break;
- }
- LOGI("Frame Index: %5d. Type:%s",frame_cnt,pictype_str);
- //释放资源
- frame_cnt++;
- }
- }
- av_free_packet(packet);
- }
这只是说如何解码视频,还有音频没有解码,但是过程相似,甚至更简单
参考文章:
https://www.cnblogs.com/CoderTian/p/6791638.html
Android 音视频深入 九 FFmpeg解码视频生成yuv文件(附源码下载)的更多相关文章
- Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)
项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)
项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E ...
- Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)
本篇项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg%E6%92 ...
- Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)
项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...
- Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)
源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...
- Android 音视频深入 十四 FFmpeg与OpenSL ES 播放mp3音乐,能暂停(附源码下载)
项目地址https://github.com/979451341/FFmpegOpenslES 这次说的是FFmpeg解码mp3,数据给OpenSL ES播放,并且能够暂停. 1.创建引擎 slCre ...
- Android 音视频深入 十二 FFmpeg视频替换声音(附源码下载)
项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E7%BB%99%E8%A7%86%E ...
- Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)
源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...
随机推荐
- 监听器&上传下载&I18N
监听器(Listener) 监听Java对象 的方法调用和属性改变() web的一个组件 事件驱动编程:事件源,事件名称,事件响应函数,事件对象 以后在Spring中的配置 WEB中有哪些监听器? ...
- POJ 3080 Blue Jeans(Java暴力)
Blue Jeans [题目链接]Blue Jeans [题目类型]Java暴力 &题意: 就是求k个长度为60的字符串的最长连续公共子串,2<=k<=10 规定: 1. 最长公共 ...
- linux----------linux下配置内网ip
1./etc/sysconfig/network-scripts/ifcfg-eth1 创建这个文件里面的内容如下 TYPE="Ethernet" BOOTPROTO=&quo ...
- [ Python ] KMP Algorithms
def pmt(s): """ :param s: the string to get its partial match table :return: partial ...
- liunx 常用命令学习笔记
通过linux 命令pwd:显示当前所在的目录ls:显示当前目录下的文件cd:切换路径 cd..返回上一级路径mkdir:新建目录rmdir:删除目录 touch:新建文件rm:删除文件 gedit: ...
- mybites
[mybatis-spring] http://www.mybatis.org/spring/zh/index.html 使用spring mybatis 中间件 方便使用 mybatis [myba ...
- Spring Boot中JSON参数传递,后台实体接受问题
1.json参数为json字符串 var data = { name: '超管不是11', password: '123456' }; $.ajax({ type:"post", ...
- jquery easyui datagrid 将值作为img显示图片时报404 undefined
原因:datagrid 在请求到数据先进行头部数据和样式的渲染,之后数据 obj = {} value = undefined index = 0 进行一次渲染, 在没有formater情况将数据 ...
- Navigation包中的move_base和amcl实现自动驾驶
安装功能包: 1.安装导航定位包navigation $ sudo apt-get install ros-indigo-navigation 2.由于导航包在/cmd_val下发布的移动数据加速度会 ...
- Netty原理分析
Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用 ...