经过排查,原来是aac编码时,输出的第一包数据只有2个字节,且codecInfo的pts为0,因为该数据
是音频编码参数相关的东西,在mediaMuxer writeSampleData时,不需要写入该数据,写入了的话
就会报这个错误
在Android中,简单的说可以使用 MediaMuxer 来封装编码后的视频流和音频流到mp4容器中,MediaMuxer从api18开始提供,可以封装编码后的视频流和音频流到视频文件中。目前MediaMuxer支持的文件输出格式包括MP4,webm和3gp:
构造函数
方法
MediaMuxer基本使用我们学完了,主要是结合MediaCodec一起来使用,后面我们会在来学习MediaCodec来一起使用,来完成编码录制功能。
最近开始学习Android下的封装和解封装技术,熟悉MediaExtractor和MediaMuxer的使用。
1、MainActivity.java文件:
packagecom.example.tongjiangsong.mediaextractmuxer
importandroid.support.v7.app.AppCompatActivity
importandroid.os.Bundle
importandroid.view.View
importandroid.widget.Button
publicclassMainActivityextendsAppCompatActivity{
privateButton button
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = (Button)findViewById(R.id.button)
button.setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(View v){
newExtractorMuxerThread().start()
}
})
}
}
2、ExtractorMuxerThread.java文件:
packagecom.example.tongjiangsong.mediaextractmuxer
importandroid.media.MediaCodec
importandroid.media.MediaExtractor
importandroid.media.MediaFormat
importandroid.media.MediaMuxer
importandroid.os.Environment
importandroid.widget.Toast
importjava.io.IOException
importjava.nio.ByteBuffer
importandroid.view.View
publicclassExtractorMuxerThreadextendsThread{
@Override
publicvoidrun(){
super.run()
mixer()
}
publicvoidmixer(){
MediaExtractor videoExtractor =null
MediaExtractor audioExtractor =null
MediaMuxer mixMediaMuxer =null
String outputVideoFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/people.mp4"
String outputAudioFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/qishi.aac"
String outputFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/mixer.mp4"
try{
videoExtractor =newMediaExtractor()
videoExtractor.setDataSource(outputVideoFilePath)
intvideoIndex = -1
MediaFormat videoTrackFormat =null
inttrackCount = videoExtractor.getTrackCount()
for(inti =0i <trackCounti++) {
videoTrackFormat = videoExtractor.getTrackFormat(i)
if(videoTrackFormat.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
videoIndex = i
break
}
}
audioExtractor =newMediaExtractor()
audioExtractor.setDataSource(outputAudioFilePath)
intaudioIndex = -1
MediaFormat audioTrackFormat =null
trackCount = audioExtractor.getTrackCount()
for(inti =0i <trackCounti++) {
audioTrackFormat = audioExtractor.getTrackFormat(i)
if(audioTrackFormat.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {
audioIndex = i
break
}
}
videoExtractor.selectTrack(videoIndex)
audioExtractor.selectTrack(audioIndex)
MediaCodec.BufferInfo videoBufferInfo =newMediaCodec.BufferInfo()
MediaCodec.BufferInfo audioBufferInfo =newMediaCodec.BufferInfo()
mixMediaMuxer =newMediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
intvideoTrackIndex = mixMediaMuxer.addTrack(videoTrackFormat)
intaudioTrackIndex = mixMediaMuxer.addTrack(audioTrackFormat)
mixMediaMuxer.start()
ByteBuffer byteBuffer = ByteBuffer.allocate(1024*1024)
longvideotime
longaudiotime
{
videoExtractor.readSampleData(byteBuffer,0)
if(videoExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
videoExtractor.advance()
}
videoExtractor.readSampleData(byteBuffer,0)
longsampleTime = videoExtractor.getSampleTime()
videoExtractor.advance()
videoExtractor.readSampleData(byteBuffer,0)
longsampleTime1 = videoExtractor.getSampleTime()
videoExtractor.advance()
videotime = Math.abs(sampleTime - sampleTime1)
}
{
audioExtractor.readSampleData(byteBuffer,0)
if(audioExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
audioExtractor.advance()
}
audioExtractor.readSampleData(byteBuffer,0)
longsampleTime = audioExtractor.getSampleTime()
audioExtractor.advance()
audioExtractor.readSampleData(byteBuffer,0)
longsampleTime1 = audioExtractor.getSampleTime()
audioExtractor.advance()
audiotime = Math.abs(sampleTime - sampleTime1)
}
videoExtractor.unselectTrack(videoIndex)
videoExtractor.selectTrack(videoIndex)
while(true) {
intdata = videoExtractor.readSampleData(byteBuffer,0)
if(data <0) {
break
}
videoBufferInfo.size = data
videoBufferInfo.presentationTimeUs += videotime
videoBufferInfo.offset =0
videoBufferInfo.flags = videoExtractor.getSampleFlags()
mixMediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, videoBufferInfo)
videoExtractor.advance()
}
while(true) {
intdata = audioExtractor.readSampleData(byteBuffer,0)
if(data <0) {
break
}
audioBufferInfo.size = data
audioBufferInfo.presentationTimeUs += audiotime
audioBufferInfo.offset =0
audioBufferInfo.flags = audioExtractor.getSampleFlags()
mixMediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, audioBufferInfo)
audioExtractor.advance()
}
}catch(IOException e) {
e.printStackTrace()
}finally{
if(mixMediaMuxer !=null) {
mixMediaMuxer.stop()
mixMediaMuxer.release()
}
if(videoExtractor !=null){
videoExtractor.release()
}
if(audioExtractor !=null){
audioExtractor.release()
}
}
}
}
3、activity_main.xml文件:
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解封装和封装!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
4、权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)