Android 音视频深入 三 MP4解码播放视频 (附源码下载)
本篇项目地址,名字是媒体解码MediaCodec,MediaExtractor,求star
https://github.com/979451341/Audio-and-video-learning-materials
这次要用到新的东西SurfaceView、MediaCodec、MediaExtractor、MediaFormat
1.文字说明
SurfaceView:一个View,用来显示视频的,使用的时候代码都比较简单就不多说了
MediaCodec:访问底层媒体编码,能够完成媒体编码和解码
编码是将源对象内容按照一种标准转换为一种标准格式内容。
解码是和编码对应的,它使用和编码相同的标准将编码内容还原为最初的对象内容。
MediaExtractor:负责将指定类型的媒体文件从文件中找到轨道,并填充到MediaCodec的缓冲区中
MediaFormat:封装描述媒体数据格式的信息,无论是音频还是视频。媒体数据的格式被指定为字符串/值对。所有格式通用的键,所有未标记为可选的键都是必需的:
名称 值类型 描述
KEY_MIME 串 格式的类型。
KEY_MAX_INPUT_SIZE 整数 可选,输入数据缓冲区的最大大小
KEY_BIT_RATE 整数 仅编码器,所需比特率(以比特/秒为单位)
2.视频播放顺序
(1)开启两个线程分别处理MP4的音频和视频
我先说一下视频的处理
使用MediaExtractor提取资源,选择频道
MediaExtractor videoExtractor = new MediaExtractor();
MediaCodec videoCodec = null;
try {
videoExtractor.setDataSource(filePath);
} catch (IOException e) {
e.printStackTrace();
}
int videoTrackIndex;
//获取视频所在轨道
videoTrackIndex = getMediaTrackIndex(videoExtractor, "video/");
videoExtractor.selectTrack(videoTrackIndex);
设置解码配置,并给MediaCodec配置,而且将SurfaceView于MediaCodec相关联,设置为在这个SurfaceView上显示
MediaFormat mediaFormat = videoExtractor.getTrackFormat(videoTrackIndex);
int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
float time = mediaFormat.getLong(MediaFormat.KEY_DURATION) / 1000000;
callBack.videoAspect(width, height, time);
videoExtractor.selectTrack(videoTrackIndex);
try {
videoCodec = MediaCodec.createDecoderByType(mediaFormat.getString(MediaFormat.KEY_MIME));
videoCodec.configure(mediaFormat, surface, null, 0);
} catch (IOException e) {
e.printStackTrace();
}
循环从MediaExtractor取数据放入MediaCodec,同时MediaCodec返回数据,表示视频播放状态,然后对应转台做不同的处理,
while (!Thread.interrupted()) {
if (!isPlaying) {
continue;
}
//将资源传递到解码器
if (!isVideoEOS) {
isVideoEOS = putBufferToCoder(videoExtractor, videoCodec, inputBuffers);
}
int outputBufferIndex = videoCodec.dequeueOutputBuffer(videoBufferInfo, TIMEOUT_US);
switch (outputBufferIndex) {
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.v(TAG, "format changed");
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.v(TAG, "超时");
break;
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
//outputBuffers = videoCodec.getOutputBuffers();
Log.v(TAG, "output buffers changed");
break;
default:
//直接渲染到Surface时使用不到outputBuffer
//ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
//延时操作
//如果缓冲区里的可展示时间>当前视频播放的进度,就休眠一下
sleepRender(videoBufferInfo, startMs);
//渲染
videoCodec.releaseOutputBuffer(outputBufferIndex, true);
break;
} if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.v(TAG, "buffer stream end");
break;
}
}//end while
然后是音频,很相似
MediaExtractor获取资源,选择频道,得到MediaFormat,获取一些参数来配置AudioTrack,然后就不说了,上一篇博客说了如何播放音频,
MediaExtractor audioExtractor = new MediaExtractor();
try {
audioExtractor.setDataSource(filePath);
} catch (IOException e) {
e.printStackTrace();
} MediaFormat mediaFormat = audioExtractor.getTrackFormat(i);
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
audioExtractor.selectTrack(i); int audioChannels = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int audioSampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int minBufferSize = AudioTrack.getMinBufferSize(audioSampleRate,
(audioChannels == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO),
AudioFormat.ENCODING_PCM_16BIT);
int maxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
audioSampleRate,
(audioChannels == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO),
AudioFormat.ENCODING_PCM_16BIT,
audioInputBufferSize,
AudioTrack.MODE_STREAM);
其实这做的不太好,因为音频和视频没有做协调,之前可能不同步
完整代码下载地址在文章头部
参考文章:
http://blog.csdn.net/qq_36467463/article/details/77990089
https://www.cnblogs.com/jiy-for-you/p/7282033.html
https://www.jianshu.com/p/6df2ab17651a
Android 音视频深入 三 MP4解码播放视频 (附源码下载)的更多相关文章
- leaflet-webpack 入门开发系列三地图分屏对比(附源码下载)
前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Android 高仿 频道管理----网易、今日头条、腾讯视频 (可以拖动的GridView)附源码DEMO
距离上次发布(android高仿系列)今日头条 --新闻阅读器 (二) 相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下.完善的功能一个一个全部实现后,就放整个源码.开发的进度就是按 ...
- Android 音视频深入 四 录视频MP4(附源码下载)
本篇项目地址,名字是<录音视频(有的播放器不能放,而且没有时长显示)>,求star https://github.com/979451341/Audio-and-video-learnin ...
- Android 音视频深入 十八 FFmpeg播放视频,有声音(附源码下载)
项目地址https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpegv%E6%92%AD%E6%94%BE%E8%A7% ...
- Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)
源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...
- Android 音视频深入 九 FFmpeg解码视频生成yuv文件(附源码下载)
项目地址,求star https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(MP4%E8 ...
- Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)
项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...
- Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)
项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...
随机推荐
- "不是内部或外部命令"
问题描述: 使用cmd 运行某个路径下(一般是C:PROGRAM FILES\...或者E:\program files\....或者D:\program files\......下面的某个)的exe ...
- 力扣(LeetCode) 27. 移除元素
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...
- 认识flask框架-2
1.json:基于键值对的字符串,轻量级的数据交互格式,用来传输数据 2.json模块 dumps:把字典转化成json字符串. loads:把json字符串转成字典. dump.load操作的是文件 ...
- 获取解码字符串指定位置的数值 Decoded String at Index
2018-10-04 12:53:06 问题描述: 问题求解: 首先本题给出了问题的规模,从Note中我们可以看到解码后的字符串长度甚至可以达到2^63的长度,这个长度已经远远超过整型数的范围,因此如 ...
- CentOS 6.8 源码安装RabbitMQ
一.安装依赖环境 yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ ...
- 在python中使用正则表达式(二)
这一节主要学习一下compile()函数和group()方法 1. re.compile() compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,然后就可以用编译后 ...
- 如何修改Sublime Text3 的侧边栏字体大小
如何修改Sublime Text3 的侧边栏字体大小 一.总结 一句话总结:用PackageResourceViewer插件来修改 PackageResourceViewer插件 1.如果Sublim ...
- (转)stm32硬件IIC
cube与I2C:https://www.cnblogs.com/121792730applllo/p/5044920.html I2C官网:https://www.i2c-bus.org/stand ...
- SQLSERVER 和 ORACLE的if not exist 用法
sql server: if not exists (select 1 from TB_Procedure where Id='2018ZZZ') BEGIN insert into TB_Proce ...
- 雷林鹏分享:jQuery EasyUI 数据网格 - 创建子网格
jQuery EasyUI 数据网格 - 创建子网格 使用数据网格(datagrid)的详细视图,用户可以展开一行来显示附加的详细信息. 任何内容都可以加载作为行详细,子网格也可以动态加载. 本教程将 ...