MediaMuxer和MediaExtractor

来源:互联网 发布:json数组格式怎样写 编辑:程序博客网 时间:2024/04/30 14:04

MediaExtractor主要用于提取音视频相关信息,分离音视频。
MediaMuxer主要复用和解复用音视频。

MediaExtractor使用一般步骤

1.//设置数据源setDataSource2.//分离轨道getTrackCount,getTrackFormat3.//选择轨道selectTrack,unselectTrack4.//读取数据readSampleData5.//下一帧advance6.//释放release

eg:

int trackCount = mediaExtractor.getTrackCount();for (int i = 0; i < trackCount; i++) {      MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);      String mime = trackFormat.getString(MediaFormat.KEY_MIME);      if (mime.startsWith("video/")) {          mediaExtractor.selectTrack(i);          break;      } else if (mime.startsWith("audio/")) {          mediaExtractor.selectTrack(i);          break;      }  }

MediaMuxer使用一般步骤

1.//添加轨道addTrack2.写数据writeSampleData3.释放release

注意点

 buffinfo 必须设置相应的有效值,不然会引发错误 //写入数据大小 bufferInfo.size = readSampleDataSize; //偏移量 bufferInfo.offset = 0; //是否为关键帧 bufferInfo.flags = mediaExtractor.getSampleFlags(); //PTS 单位为微妙,必须为递增不然会报错 bufferInfo.presentationTimeUs += videoSampleTime; mediaMuxer.writeSampleData(trackIndex, buffer, bufferInfo);这里重点关注下bufferInfo.presentationTimeUsmediaExtractor.getSampleTime()因为mediaExtractor的提取顺序应该是dts的顺序不是pts的顺序,如果视频中存在b帧则getSampleTime不可能递增的,所以bufferInfo.presentationTimeUs=mediaExtractor.getSampleTime()可能会报错,前面说了这个值必须递增。如果不存在b帧,pts==dts,使用没问题。

设置PTS的办法
1.算出帧时间距,github上看见的,排除i帧来计算不知道是为什么,不排除感觉也一样的

        long videoSampleTime;//            mediaExtractor.readSampleData(buffer, 0);//            //skip first I frame//            if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)//                mediaExtractor.advance();        mediaExtractor.readSampleData(buffer, 0);        long firstVideoPTS = mediaExtractor.getSampleTime();        mediaExtractor.advance();        mediaExtractor.readSampleData(buffer, 0);        long SecondVideoPTS = mediaExtractor.getSampleTime();        videoSampleTime = Math.abs(SecondVideoPTS - firstVideoPTS);

2.通过帧率来计算

//每秒多少帧int frameRate=mediaFormat=getInteger(MediaFormat.KEY_FRAME_RATE)//得出平均每一帧间隔多少微妙videoSampleTime=1000*1000/frameRate

最后提供2个简单的运用示例
有耗时,不要ui线程使用,只是演示

    /**     * 提取音/视频     *     * @param inPath     * @param outPath     * @param isVideo     */    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)    public static void trackExtractor(String inPath, String outPath, boolean isVideo) {        //提取器        MediaExtractor mediaExtractor = new MediaExtractor();        try {            mediaExtractor.setDataSource(inPath);        } catch (IOException e) {            e.printStackTrace();        }        MediaMuxer mediaMuxer = null;        //复用器        try {            mediaMuxer = new MediaMuxer(outPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);        } catch (IOException e) {            e.printStackTrace();        }        int trackIndex = 0;        int trackCount = mediaExtractor.getTrackCount();        for (int i = 0; i < trackCount; i++) {            MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);            String mime = trackFormat.getString(MediaFormat.KEY_MIME);            if (mime.startsWith("video/") && isVideo) {                trackIndex = mediaMuxer.addTrack(trackFormat);                mediaExtractor.selectTrack(i);                break;            } else if (mime.startsWith("audio/") && !isVideo) {                trackIndex = mediaMuxer.addTrack(trackFormat);                mediaExtractor.selectTrack(i);                break;            }        }        mediaMuxer.start();        ByteBuffer buffer = ByteBuffer.allocate(1024 * 1000);        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();        long videoSampleTime=getSampleTime(mediaExtractor,buffer);        while (true) {            int readSampleDataSize = mediaExtractor.readSampleData(buffer, 0);            if (readSampleDataSize < 0) {                break;            }            bufferInfo.size = readSampleDataSize;            bufferInfo.offset = 0;            bufferInfo.flags = mediaExtractor.getSampleFlags();            bufferInfo.presentationTimeUs += videoSampleTime;            mediaMuxer.writeSampleData(trackIndex, buffer, bufferInfo);            mediaExtractor.advance();        }        mediaExtractor.release();        mediaMuxer.stop();        //内部也会执行stop,所以可以不用执行stop        mediaMuxer.release();    }    private static long getSampleTime(MediaExtractor mediaExtractor, ByteBuffer buffer) {        long videoSampleTime;//            mediaExtractor.readSampleData(buffer, 0);//            //skip first I frame//            if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)//                mediaExtractor.advance();        mediaExtractor.readSampleData(buffer, 0);        long firstVideoPTS = mediaExtractor.getSampleTime();        mediaExtractor.advance();        mediaExtractor.readSampleData(buffer, 0);        long SecondVideoPTS = mediaExtractor.getSampleTime();        videoSampleTime = Math.abs(SecondVideoPTS - firstVideoPTS);        Log.d("MediaMuxerUtil", "videoSampleTime is " + videoSampleTime);        return videoSampleTime;    }    /**     * 合成音视频     *     * @param videoPath     * @param audioPath     * @param outPath     */    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)    public static void trackMuxer(String videoPath, String audioPath, String outPath) {        MediaExtractor videoExtractor = new MediaExtractor();        try {            videoExtractor.setDataSource(videoPath);        } catch (IOException e) {            e.printStackTrace();        }        MediaFormat videoFormat = null;        int videoTrackIndex = -1;        int videoTrackCount = videoExtractor.getTrackCount();        for (int i = 0; i < videoTrackCount; i++) {            videoFormat = videoExtractor.getTrackFormat(i);            String mime = videoFormat.getString(MediaFormat.KEY_MIME);            if (mime.startsWith("video/")) {                videoTrackIndex = i;                break;            }        }        MediaExtractor audioExtractor = new MediaExtractor();        try {            audioExtractor.setDataSource(audioPath);        } catch (IOException e) {            e.printStackTrace();        }        MediaFormat audioFormat = null;        int audioTrackIndex = -1;        int audioTrackCount = audioExtractor.getTrackCount();        for (int i = 0; i < audioTrackCount; i++) {            audioFormat = audioExtractor.getTrackFormat(i);            String mime = audioFormat.getString(MediaFormat.KEY_MIME);            if (mime.startsWith("audio/")) {                audioTrackIndex = i;                break;            }        }        videoExtractor.selectTrack(videoTrackIndex);        audioExtractor.selectTrack(audioTrackIndex);        MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();        MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();        MediaMuxer mediaMuxer = null;        try {            mediaMuxer = new MediaMuxer(outPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);        } catch (IOException e) {            e.printStackTrace();        }        int writeVideoTrackIndex = mediaMuxer.addTrack(videoFormat);        int writeAudioTrackIndex = mediaMuxer.addTrack(audioFormat);        mediaMuxer.start();        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1000);        long videoSampleTime=getSampleTime(videoExtractor,byteBuffer);        while (true) {            int readVideoSampleSize = videoExtractor.readSampleData(byteBuffer, 0);            if (readVideoSampleSize < 0) {                break;            }            videoBufferInfo.size = readVideoSampleSize;            videoBufferInfo.presentationTimeUs +=videoSampleTime;            videoBufferInfo.offset = 0;            videoBufferInfo.flags = videoExtractor.getSampleFlags();            mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videoBufferInfo);            videoExtractor.advance();        }        long audioSampleTime=getSampleTime(audioExtractor,byteBuffer);        while (true) {            int readAudioSampleSize = audioExtractor.readSampleData(byteBuffer, 0);            if (readAudioSampleSize < 0) {                break;            }            audioBufferInfo.size = readAudioSampleSize;            audioBufferInfo.presentationTimeUs += audioSampleTime;            audioBufferInfo.offset = 0;            audioBufferInfo.flags = audioExtractor.getSampleFlags();            mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audioBufferInfo);            audioExtractor.advance();        }        mediaMuxer.stop();        mediaMuxer.release();        videoExtractor.release();        audioExtractor.release();    }
0 0
原创粉丝点击