本文共 8620 字,大约阅读时间需要 28 分钟。
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:
MediaExtractor主要用于提取音视频相关信息,分离音视频。MediaMuxer主要复用和解复用音视频。MediaExtractor使用一般步骤
1.//设置数据源setDataSource2.//分离轨道getTrackCount,getTrackFormat3.//选择轨道selectTrack,unselectTrack4.//读取数据readSampleData5.//下一帧advance6.//释放release
举例说明:
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(); }
原文链接:
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:转载地址:http://vcfz.baihongyu.com/