簡體   English   中英

使用MediaMuxer編碼MP4文件,但在調用mediaMuxer.stop()時崩潰

[英]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()崩潰。

為了避免崩潰,您最好在實現時遵循以下規則:

  1. 在同步模式下使用MediaCodec進行AAC編碼。 通過使用同步模式,您可以將AudioRecorder的音頻樣本(即DirectByteBuffer )快速輸入到MediaCodec的inputbuffer中,而無需進行任何額外的內存復制。 如果您放下太多樣本, MediaMuxer將崩潰。

  2. 使用同步模式的另一個原因是,您可以使用MediaMuxer.dequeueInputBuffer(-1)來確保始終可以在writeAudioSample方法中獲得可用的InputBuffer, writeAudioSample方法實現了將樣本寫入MediaCodec

  3. 另一個理由使用同步模式是,你需要之前排放的AAC編碼數據MediaMuxer.stop() (請參閱規則9)

  4. 自行設置MediaFormat.KEY_MAX_INPUT_SIZE ,該值應為2048的倍數(1024個16位樣本,對於字節,長度為2048)。 我通常將其設置為8192 ,這取決於音頻源的采樣率,通道數以及應用程序和設備的性能。

  5. 確保輸入樣本中充滿音頻數據,並且長度應為您設置為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 ,依此類推。

  6. 這部分是最大的坑。 將AAC編碼數據寫入MediaMuxer ,請檢查演示時間,即使在將音頻樣本輸入到MediaCodec時已經設置了演示時間。 AAC編碼數據的顯示時間有時可能不會增加。 您應該記錄您寫入MediaMuxer的上次演示時間。 如果發現AAC數據presentationTime = ++lastPresentationTime通過presentationTime = ++lastPresentationTime調整演示時間。 此外,您可能會獲得一些零表示時間的AAC數據。 別管他們。 不要將它們寫入MediaMuxer

  7. 如果MediaMuxer還有其他軌道,請確保每個軌道的演示時間在相同范圍內(允許幾秒鍾的錯誤)。

  8. 一個MediaMuxer一個AAC MediaCodec 並且不要重復使用輸出MediaFormat對象。

  9. 在執行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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM