项目地址,求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文件(附源码下载)的更多相关文章

  1. Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)

    项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...

  2. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  3. Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)

    项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E ...

  4. Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)

    本篇项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg%E6%92 ...

  5. Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)

    项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...

  6. Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

    源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...

  7. Android 音视频深入 十四 FFmpeg与OpenSL ES 播放mp3音乐,能暂停(附源码下载)

    项目地址https://github.com/979451341/FFmpegOpenslES 这次说的是FFmpeg解码mp3,数据给OpenSL ES播放,并且能够暂停. 1.创建引擎 slCre ...

  8. Android 音视频深入 十二 FFmpeg视频替换声音(附源码下载)

    项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E7%BB%99%E8%A7%86%E ...

  9. Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)

    源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...

随机推荐

  1. python_字符串的格式化输出

    name = input("Name:")age = int(input("Age:")) input: 输入的内容默认为字符串格式job = input(&q ...

  2. [pat]1068 Find More Coins

    满背包问题,把体积和价值看成相等的.用滚动数组优化,然后额外开辟一个choice数组来记录每次的选择,然后回溯打印.因为要按字典序,先把价值进行排序.假如选最小的商品能装满m的话,那就把判断条件改成大 ...

  3. 53.CSS---CSS水平垂直居中常见方法总结

    CSS水平垂直居中常见方法总结 1.元素水平居中 当然最好使的是: margin: 0 auto; 居中不好使的原因: 1.元素没有设置宽度,没有宽度怎么居中嘛! 2.设置了宽度依然不好使,你设置的是 ...

  4. gateway + jwt 网关认证

    思路: 全局过滤器对所有的请求拦截(生成token有效期30分钟,放入redis设置有效期3天.3天之类可以通过刷新接口自动刷新,超过3天需要重新登录.) 前端在调用接口之前先判断token是否过期( ...

  5. linux终端使用ss代理

    title: linux终端使用ss代理 date: 2017-11-09 21:06:16 tags: linux categories: linux 系统为archlinux 先将ss代理转化为h ...

  6. javascript DOM 常用方法

    前端HTML+CSS+JS流程导图:https://www.processon.com/view/link/5ad1c2d0e4b0b74a6dd64f3c HTML+CSS+Javascript+j ...

  7. 收银台数据库存储AES加解密

    高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合.缺点是密钥的传输 ...

  8. MySQL插入更新_ON DUPLICATE KEY UPDATE

    前提:操作的表具有主键或唯一索引 INSERT INTO:表中不存在对应的记录,则插入:若存在对应的记录,则报错: INSERT INTO IGNORE:表中不存在对应的记录,则插入:若存在对应的记录 ...

  9. PHP5.6 Dockerfile

    FROM centos COPY ["src","/src"] RUN groupadd -g 1000 www \ && useradd -u ...

  10. JavaScript if 条件语句

    JavaScript if 条件语句 使用: if(条件){ }else if(条件){ }else if(条件){ }else{ } 示例: // 判断相等 if(1==1){ } // 判断不等 ...