MediaExtractor的使用
分离mp4、flv,生成视频H264/mpeg和音频mp3或aac(无adts头)
下面是应用层mediaExtractor使用,分离一mp4文件,生成h264和aac,并添加adts头文件。
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;/*** mp4extractor 分离器* 分离mp4 成h264 和 aac* 分别生成h264和aac文件(无adts头)* <p>* android的无法分离高profile的h264文件,这里分离的是Baseline(profile)* <p>* 合成的时候,MP4,flv,rtmp都不需要adts头* 合成的时候:hls,rtp,ts需要adts头* 所以这里分离出来的aac是没有adts头的,mediainfo读取到的音频信息是从moov中box中读取的*/public class MP4VideoExtractor {private static final String TAG = "MP4VideoExtractor";//test3.mp4 h264,aacpublic static void exactorMedia(String sdcard_path) {FileOutputStream videoOutputStream = null;FileOutputStream audioOutputStream = null;MediaExtractor mediaExtractor = new MediaExtractor();try {//分离的视频文件File videoFile = new File(sdcard_path, "output_video.h264");//分离的音频文件File audioFile = new File(sdcard_path, "output_audio.aac");videoOutputStream = new FileOutputStream(videoFile);audioOutputStream = new FileOutputStream(audioFile);//输入文件,也可以是网络文件//oxford.mp4 视频 h264/baseline 音频 aac/lc 44.1k 2 channel 128kb/smediaExtractor.setDataSource(sdcard_path + "/oxford.mp4");//test3.mp4 视频h264 high 音频aac// mediaExtractor.setDataSource(sdcard_path + "/test3.mp4");//test2.mp4 视频mpeg4 音频MP3// mediaExtractor.setDataSource(sdcard_path + "/test2.mp4");//信道总数int trackCount = mediaExtractor.getTrackCount();Log.d(TAG, "trackCount:" + trackCount);int audioTrackIndex = -1;int videoTrackIndex = -1;for (int i = 0; i < trackCount; i++) {MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);String mineType = trackFormat.getString(MediaFormat.KEY_MIME);//视频信道if (mineType.startsWith("video/")) {videoTrackIndex = i;}//音频信道if (mineType.startsWith("audio/")) {audioTrackIndex = i;}}ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);//切换到视频信道mediaExtractor.selectTrack(videoTrackIndex);while (true) {int readSampleCount = mediaExtractor.readSampleData(byteBuffer, 0);Log.d(TAG, "video:readSampleCount:" + readSampleCount);if (readSampleCount < 0) {break;}//保存视频信道信息byte[] buffer = new byte[readSampleCount];byteBuffer.get(buffer);videoOutputStream.write(buffer);//buffer 写入到 videooutputstream中byteBuffer.clear();mediaExtractor.advance();}//切换到音频信道mediaExtractor.selectTrack(audioTrackIndex);while (true) {int readSampleCount = mediaExtractor.readSampleData(byteBuffer, 0);Log.d(TAG, "audio:readSampleCount:" + readSampleCount);if (readSampleCount < 0) {break;}//保存音频信息byte[] buffer = new byte[readSampleCount];byteBuffer.get(buffer);/************************* 用来为aac添加adts头**************************/byte[] aacaudiobuffer = new byte[readSampleCount + 7];addADTStoPacket(aacaudiobuffer, readSampleCount + 7);System.arraycopy(buffer, 0, aacaudiobuffer, 7, readSampleCount);audioOutputStream.write(aacaudiobuffer);/***************************************close**************************/// audioOutputStream.write(buffer);byteBuffer.clear();mediaExtractor.advance();}} catch (IOException e) {e.printStackTrace();} finally {Log.d(TAG, "mediaExtractor.release!\n");mediaExtractor.release();mediaExtractor = null;try {videoOutputStream.close();audioOutputStream.close();} catch (IOException e) {e.printStackTrace();}}}/** 这里之前遇到一个坑,以为这个packetLen是adts头的长度,也就是7,仔细看了下代码,发现这个不是adts头的长度,而是一帧音频的长度* @param packet 一帧数据(包含adts头长度)* @param packetLen 一帧数据(包含adts头)的长度*/private static void addADTStoPacket(byte[] packet, int packetLen) {int profile = 2; // AAC LCint freqIdx = getFreqIdx(44100);int chanCfg = 2; // CPE// fill in ADTS datapacket[0] = (byte) 0xFF;packet[1] = (byte) 0xF9;packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));packet[4] = (byte) ((packetLen & 0x7FF) >> 3);packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);packet[6] = (byte) 0xFC;}private static int getFreqIdx(int sampleRate) {int freqIdx;switch (sampleRate) {case 96000:freqIdx = 0;break;case 88200:freqIdx = 1;break;case 64000:freqIdx = 2;break;case 48000:freqIdx = 3;break;case 44100:freqIdx = 4;break;case 32000:freqIdx = 5;break;case 24000:freqIdx = 6;break;case 22050:freqIdx = 7;break;case 16000:freqIdx = 8;break;case 12000:freqIdx = 9;break;case 11025:freqIdx = 10;break;case 8000:freqIdx = 11;break;case 7350:freqIdx = 12;break;default:freqIdx = 8;break;}return freqIdx;}}
MediaExtractor的使用相关推荐
- Android媒体解码MediaCodec,MediaExtractor
Android提供了MediaPlayer播放器播放媒体文件,其实MediaPlyer只是对Android Media包下的MediaCodec和MediaExtractor进行了包装,方便使用.但是 ...
- Android 用MediaCodec ,MediaExtractor解码播放MP4文件
上一篇讲了如何采集摄像头画面并且进行编码,再进行封装成MP4格式文件,如需了解可以看 安卓采集摄像头画面生成MP4文件 本篇博客,主要讲解如何对MP4文件进行解封装,再进行解H264码流,进行画面显示 ...
- 【Android】使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据
1 简介 本文以 mp4 文件为例,讲解去音频操作.mp4 是一种视频封装的容器,里面包含音频(audio)和视频(video)数据,对应的数据编码格式分别为 aac 和 h264.在去音频过程中,主 ...
- Android音频学习之MediaExtractor,提取音频视频轨道数据(从视频中分离音频视频数据)
一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor.MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放: 1 MediaExtractor 说明 ...
- 使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor.MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放: 一.MediaExtractor API ...
- stagefright 架构分析(四) MediaExtractor
MediaExtractor 是什么? MediaExtractor 就是解复用器,将audio和video分离 Android 4.1目前支持mp4 mkv ogg wav flac amr ts ...
- 10. Android MultiMedia框架完全解析 - MediaExtractor::Create函数的解析和FslExtractor分析
先来看看MediaExtractor所处的位置: (一)创建流程 在GenericSource.cpp的NuPlayer::GenericSource::initFromDataSource()函数中 ...
- Android MediaExtractor + MediaCodec构建简单播放器
对于一个播放器,基本上可以分为以下模块:数据接收(网络/本地)->解复用->音视频解码->音视频同步->音视频输出. 今天我们介绍Android系统中提供的两个播放器模块Med ...
- 使用MediaExtractor+MediaCodec+MediaMuxer实现视频截取和拼接
Android中使用MediaExtractor+MediaCodec+MediaMuxer实现将本地视频解码截取再和另外的视频进行拼接编码合成一个视频,主要有两个类. 下面是解码相关的类VideoD ...
最新文章
- Java内部类详解(使用场景和好处、相关内部类的笔试面试题)
- 中国消费者为何不愿为App付费?
- 南方周末:阿里巴巴的大数据梦
- 基于WPF系统框架设计(7)-TextBox/PasswordBox在ViewModel中支持回车命令
- eclipse安装lua
- 四、时间 .认知 .迭代
- 中文文档保存到mysql_mysql 中文 存储
- 【java与智能设备】01_1Android简介与环境搭建
- ❤️❤️新生代农民工熬夜整理Python入门教程,包教包会!附源码❤️❤️
- ThunderSoft Video to GIF Converter(电脑视频转gif软件)官方正式版V3.3.0 | 轻松将视频转换成GIF图片
- 逆函数求导公式_反函数求导法则
- 网络爬虫笔记【4】 掌握获取 Ajax 异步加载网页内容的方法
- 服务器pe系统ghost系统安装教程,极速PE U盘安装GHOST系统详细图文教程
- Modbus 的RTU、ASCII、TCP傻傻搞不清楚?一文最全解读
- Edittext不自动获取焦点的方法
- 高中数学40分怎么办_新高一第一次考试数学只考了40分,还有救吗?
- IPv4与IPv6区别
- Python制作简易计算器
- chrome浏览器如何避免network报错:ERR_CERT_AUTHORITY_INVALID并添加为例外或继续前往
- 网康防火墙--上线指南_在线付款接受指南-第2部分