[英]Use MediaMuxer to encode a MP4 file but it crashes when calling mediaMuxer.stop()
我正在使用MediaMuxer和MediaCodec對來自攝像機的音頻(H264)數據和音頻(AAC-LC)數據進行編碼,並將其編碼為MP4文件。 但是MediaMuxer對象有時會在mediaMuxer.stop()
崩潰,並且錯誤日志為
11-03 16:28:36.956: A/DEBUG(711): Abort message: 'frameworks/av/media/libstagefright/MPEG4Writer.cpp:2983 CHECK_LT( mCodecSpecificDataSize + 23,128) failed: 399 vs. 128'
11-03 16:28:36.957: A/DEBUG(711): x0 0000000000000000 x1 0000000000001184 x2 0000000000000006 x3 0000000000000000
11-03 16:28:36.957: A/DEBUG(711): x4 0000000000000000 x5 0000000000000001 x6 0000000000000000 x7 0000000000000000
11-03 16:28:36.957: A/DEBUG(711): x8 0000000000000083 x9 0000000000000000 x10 0000000000000000 x11 0000007f91bb0df8
11-03 16:28:36.958: A/DEBUG(711): x12 0000007f91bb0cd0 x13 0000000000000077 x14 0000007f91bb0ea8 x15 0000000000000000
11-03 16:28:36.958: A/DEBUG(711): x16 0000007faca8d6a8 x17 0000007faca4fb2c x18 0000007face14418 x19 0000007f91bb3510
11-03 16:28:36.959: A/DEBUG(711): x20 0000007f91bb3450 x21 000000000000000b x22 0000000000000006 x23 00000055a17fd260
11-03 16:28:36.959: A/DEBUG(711): x24 0000007f91bb1c58 x25 0000007f91bb18b4 x26 0000007f91bb1f90 x27 0000007fa9715000
11-03 16:28:36.960: A/DEBUG(711): x28 0000007f91bb1898 x29 0000007f91bb0d60 x30 0000007faca4d2c8
11-03 16:28:36.960: A/DEBUG(711): sp 0000007f91bb0d60 pc 0000007faca4fb34 pstate 0000000020000000
我嘗試過多次只編碼一條音軌(視頻或音頻)。 mediaMuxer.stop()
的執行完全正常。
為什么我對兩條音軌進行編碼時CHECK_LT
失敗?
好吧,我在這里回答自己。
晝夜MediaMuxer.stop()
工作后,我發現有很多因素會導致在MediaMuxer.stop()
AAC軌道時導致MediaMuxer.stop()
崩潰。
為了避免崩潰,您最好在實現時遵循以下規則:
在同步模式下使用MediaCodec
進行AAC編碼。 通過使用同步模式,您可以將AudioRecorder的音頻樣本(即DirectByteBuffer
)快速輸入到MediaCodec
的inputbuffer中,而無需進行任何額外的內存復制。 如果您放下太多樣本, MediaMuxer
將崩潰。
使用同步模式的另一個原因是,您可以使用MediaMuxer.dequeueInputBuffer(-1)
來確保始終可以在writeAudioSample
方法中獲得可用的InputBuffer, writeAudioSample
方法實現了將樣本寫入MediaCodec
。
另一個理由使用同步模式是,你需要之前排放的AAC編碼數據MediaMuxer.stop()
(請參閱規則9)
自行設置MediaFormat.KEY_MAX_INPUT_SIZE
,該值應為2048的倍數(1024個16位樣本,對於字節,長度為2048)。 我通常將其設置為8192 ,這取決於音頻源的采樣率,通道數以及應用程序和設備的性能。
確保輸入樣本中充滿音頻數據,並且長度應為您設置為MediaFormat.KEY_MAX_INPUT_SIZE
的值。 並以毫秒為單位計算演示時間。 任何兩個相鄰輸入樣本之間的顯示時間間隔應相同。 通過以下公式計算樣本的持續時間: 1_000_000L * KEY_MAX_INPUT_SIZE / SAMPLE_RATE / NUMBER_OF_CHANNELS / 2
。 您無需將演示時間對齊或移動到0 。 我強烈建議您使用long initialTime = System.nanoTime() / 1000L
來獲取初始時間並將其傳遞給MediaCodec
。 因此,下次編寫示例時,顯示時間應為initialTime + 1_000_000L * KEY_MAX_INPUT_SIZE / SAMPLE_RATE / NUMBER_OF_CHANNELS / 2
,依此類推。
這部分是最大的坑。 將AAC編碼數據寫入MediaMuxer
,請檢查演示時間,即使在將音頻樣本輸入到MediaCodec
時已經設置了演示時間。 AAC編碼數據的顯示時間有時可能不會增加。 您應該記錄您寫入MediaMuxer
的上次演示時間。 如果發現AAC數據presentationTime = ++lastPresentationTime
通過presentationTime = ++lastPresentationTime
調整演示時間。 此外,您可能會獲得一些零表示時間的AAC數據。 別管他們。 不要將它們寫入MediaMuxer
。
如果MediaMuxer
還有其他軌道,請確保每個軌道的演示時間在相同范圍內(允許幾秒鍾的錯誤)。
一個MediaMuxer
一個AAC MediaCodec
。 並且不要重復使用輸出MediaFormat
對象。
在執行MediaMuxer.stop()
之前,請停止調用writeAudioSample
方法,並通過queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
將EOS發送到MediaCodec
。 並從MediaCodec
排出剩余的AAC數據以寫入MediaMuxer
。 執行MediaMuxer.stop()
看看發生了什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.