首页 > 其他分享 >【android】音视频开发五:学习MediaExtractor 和 MediaMuxer,知道如何解析和封装 mp4 文件

【android】音视频开发五:学习MediaExtractor 和 MediaMuxer,知道如何解析和封装 mp4 文件

时间:2023-02-16 17:37:06浏览次数:35  
标签:MediaMuxer MediaExtractor int 轨道 mMediaExtractor mMediaMuxer 音视频 MediaCodec

MediaExtractor
MediaExtractor顾名思义就是多媒体提取器,主要负责:

获取媒体文件的格式,包括音视频轨道,编码格式,宽高,采样率,声道数等,

分离音频流,视频流,读取分离后的音视频数据。
相关API概述:

setDataSource(String path)
指定数据来源,支持网络地址和本地地址

getTrackCount()
获取轨道数据数量

getTrackFormat(int index)
获取指定索引位置的轨道格式信息

selectTrack(int index)
根据轨道索引选中指定轨道,选中后将分离器读取选中轨道的数据,读取数据之前必须选中一个轨道,而且同时只能选中一个轨道。

seekTo(long timeUs,int mode)
根据帧时间(timeUs)以及搜寻模式(mode),搜寻最匹配的关键帧。
注意:分离视频轨道时,seekTo不能精确到视频时间,只能根据mode找到最匹配的关键帧。
SEEK_TO_CLOSEST_SYNC 最接近 timeUS 的关键帧
SEEK_TO_NEXT_SYNC timeUS 的下一个关键帧
SEEK_TO_PREVIOUS_SYNC timeUS 的上一个关键帧

advance()
将分离器游标移动到下一帧

readSampleData(ByteBuffer buffer,int offset)
读取当前位置样本数据

getSampleTrackIndex()
获取当前选中的轨道索引

getSampleTime()
当前分离样本时间

getSampleFlags()
获取当前样本类型,为SAMPLE_FLAG_SYNC时表示为关键帧

MediaMuxer
MediaMuxer有助于混合基本流。目前支持mp4或者webm文件作为输出和最多一个音频和、或一个视频基本流。
MediaMuxer不支持复用B帧。
相关API概述:

addTrack(MediaFormat format)
添加具有指定格式的曲目
start()
启动混合器,确保在addTrack之后和writeSampleData之前调用。
writeSampleData(int trackIndex,ByteBuffer byte,MediaCodec.BufferInfo bufferInfo)
将编码的样本写入复用器
stop()
停止混合器
release()
确保在完成任务时释放任何资源

 public void extractFile(String path){
        File file  = new File(path);
        if (!file.exists()){
            return;
        }
        try {
            mMediaExtractor.setDataSource(file.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取轨道数量
        int trackCount = mMediaExtractor.getTrackCount();
        Log.e(TAG, "extractFile: track count"+trackCount);
        if (trackCount >0){
            for (int i = 0; i < trackCount; i++) {
                MediaFormat trackFormat = mMediaExtractor.getTrackFormat(i);
                String trackMime = trackFormat.getString(MediaFormat.KEY_MIME);
                Log.e(TAG, "extractFile: track format"+trackMime);
                if (trackMime != null && trackMime.startsWith("video/")){
                    //代表是视频轨道
                    //以帧/秒为单位描述视频格式帧频的关键
                    integer = trackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
                    //根据轨道索引选中指定轨道
                    mMediaExtractor.selectTrack(i);
                    //初始化合成器
                    try {
                        mMediaMuxer = new MediaMuxer(SDCARD_PATH
                                +"/output.mp4",MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
                        //添加具有指定格式的曲目
                        mVideoTrackIndex = mMediaMuxer.addTrack(trackFormat);
                       //启动混合器
                        mMediaMuxer.start();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            if (mMediaMuxer == null){
                return;
            }
            ByteBuffer allocate = ByteBuffer.allocate(500 * 1024);
            int sampleSize = 0;
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            while ((sampleSize = mMediaExtractor.readSampleData(allocate,0))>0){
                info.offset = 0;
                info.size = sampleSize;
                info.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                info.presentationTimeUs += 1000*1000/integer;
                //将编码的样本写入复用器
                mMediaMuxer.writeSampleData(mVideoTrackIndex,allocate,info);
                mMediaExtractor.advance();
            }
            mMediaExtractor.release();
            //停止混合器
            mMediaMuxer.stop();
            //释放资源
            mMediaMuxer.release();
        }
    }

在解析和封装音视频的过程中,还使用到了MediaFormat,MediaCodec等,详细介绍请点击:MediaCodec,MediaFormat详解。
接下来学习----音视频开发六:学习 Android 平台 OpenGL ES

 

标签:MediaMuxer,MediaExtractor,int,轨道,mMediaExtractor,mMediaMuxer,音视频,MediaCodec
From: https://www.cnblogs.com/opensmarty/p/17127510.html

相关文章