Android短影片系統硬編碼—實現音影片編碼(三)
MediaMuxer(音影片混合API)
MediaMuxer 的使用很簡單,在 Android Developer 官網 上MediaMuxer 的 API 說明中,也有其簡單的使用示例程式碼:
MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
// More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
// or MediaExtractor.getTrackFormat().
MediaFormat audioFormat = new MediaFormat(...);
MediaFormat videoFormat = new MediaFormat(...);
int audioTrackIndex = muxer.addTrack(audioFormat);
int videoTrackIndex = muxer.addTrack(videoFormat);
ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
boolean finished = false;
BufferInfo bufferInfo = new BufferInfo();
muxer.start();
while(!finished) {
// getInputBuffer() will fill the inputBuffer with one frame of encoded
// sample from either MediaCodec or MediaExtractor, set isAudioSample to
// true when the sample is audio data, set up all the fields of bufferInfo,
// and return true if there are no more samples.
finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo);
if (!finished) {
int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex;
muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
}
};
muxer.stop();
muxer.release();
參照官方的說明和程式碼示例,我們可以知道,音影片混合(也可以音訊和音訊混合),只需要將編碼器的MediaFormat
加入到
MediaMuxer
中,得到一個音軌影片軌的索引,然後每次從編碼器中取出來的
ByteBuffer
,寫入(
writeSampleData
)到編碼器所在的軌道中就
ok
了。
這裡需要注意的是,一定要等編碼器設定編碼格式完成後,再將它加入到混合器中,編碼器編碼格式設定完成的標誌是dequeueOutputBuffer
得到返回值為
MediaCodec.INFO_OUTPUT_FORMAT_CHANGED
。
音影片錄製MP4檔案
前面兩篇文章已經給出了短影片系統音訊錄製的程式碼和影片錄製的程式碼,利用MediaMuxer 將其結合起來,就可以和簡單的完成錄製有聲音有影像的 MP4 檔案的功能了。短影片系統音訊錄製和影片錄製的基本流程保持不變,在錄製編碼後,不再將編碼的結果寫入到檔案流中,而是寫入為混合器的 sample data 。以影片為例,更改迴圈編碼的程式碼為:
// 流程一直,無需更改
int index=mVideoEnc.dequeueInputBuffer(-1);
if(index>=0){
if(hasNewData){
if(yuv==null){
yuv=new byte[width*height*3/2];
}
rgbaToYuv(data,width,height,yuv);
}
ByteBuffer buffer=getInputBuffer(mVideoEnc,index);
buffer.clear();
buffer.put(yuv);
// 結束時,傳送結束標誌,在編碼完成後結束
mVideoEnc.queueInputBuffer(index,0,yuv.length,
mStartFlag?0:MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
MediaCodec.BufferInfo mInfo=new MediaCodec.BufferInfo();
int outIndex=mVideoEnc.dequeueOutputBuffer(mInfo,0);
do {
if(outIndex>=0){
ByteBuffer outBuf=getOutputBuffer(mVideoEnc,outIndex);
// 裡面不在是寫入到檔案,而是寫入為混合器的 sample data
if(mTrackCount==3&&mInfo.size>0){
mMuxer.writeSampleData(mVideoTrack,outBuf,mInfo);
}
mVideoEnc.releaseOutputBuffer(outIndex,false);
outIndex=mVideoEnc.dequeueOutputBuffer(mInfo,0);
Log.e("wuwang","outIndex-->"+outIndex);
// 編碼結束的標誌
if((mInfo.flags&MediaCodec.BUFFER_FLAG_END_OF_STREAM)!=0){
return true;
}
}else if(outIndex==MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
// 按照 MediaMuxer 中所說,加入軌道的時機在這裡
mVideoTrack=mMuxer.addTrack(mVideoEnc.getOutputFormat());
Log.e("wuwang","video track-->"+mVideoTrack);
mTrackCount++;
// 一定要音軌影片軌都加入後,再開始混合
if(mTrackCount==2){
mMuxer.start();
mTrackCount=3;
}
}
}while (outIndex>=0);
當然是用MediaMuxer 前,肯定是需要建立一個 MediaMuxer 的例項的:
mMuxer=new MediaMuxer(path+"."+postfix, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
短影片系統音訊的操作和影片一樣更改,將音訊編碼也加入MeidaMuxer 的軌道中,得到一個軌道索引,將編碼後的資料加入為 MediaMuxer 當前音軌的 sample data 。音軌和上面的視軌各自做各自的,結束錄製時,都傳送結束標誌,然後在短影片系統編碼結束後,停止混合器就可以得到一個固定位元速率的 MP4 檔案了。
總結
至此,有關Android
短影片系統硬編碼部落格就結束了。但是在實際使用
MediaCodec
和
MediaMuxer
的過程中,總會遇到這樣或者那樣的問題,硬編硬解,和硬體相關比較緊密,
Android
雖然提供了一個很好的
API
,但是各個廠商在實現的過程中,總是會做些讓自己變得獨特的事情。當然他們的目的並不是為了獨特,有的是為了讓產品變得更優秀(雖然最後可能會做砸了),有的是為了省錢,用軟體去彌補硬體的缺陷,最後的結果就是苦了做上層開發的碼農們。
從博主在使用MediaCodec
和
MediaMuxer
的過程中遇到的問題,總結下需要注意主要有以下幾點:
MediaCodec
是
Android4.1
新增
API
,
MediaMuxer
是
Android4.3
新增
API
。
顏色空間。按照Android
本身的意思,
COLOR_FormatYUV420Planar
應該是所有硬體平臺都支援的。但是實際上並不是這樣。所以在設定顏色空間時,應該獲取硬體平臺所支援的顏色空間,確保它是支援你打算使用的顏色空間,不支援的話應該啟用備用方案(使用其他當前硬體支援的顏色空間)。
影片尺寸,在一些手機上,短影片系統影片錄製的尺寸可以是任意的。但是有些手機,不支援的尺寸設定會導致錄製的影片現錯亂。博主在使用Oppo R7
測試,
360*640
的影片,單獨錄製影片沒問題,音影片混合後,出現了顏色錯亂的情況,而在
360F4
手機上,卻都是沒問題的。將影片寬高都設定為
16
的倍數,可以解決這個問題。
短影片系統編碼器格式設定,諸如音訊編碼的取樣率、位元率等,取值也需要結合硬體平臺來設定,否則也會導致崩潰或其他問題。這個其實和顏色空間的選擇一樣。
網上看到許多queueInputBuffer
中設定
presentationTimeUs
為
System.nanoTime()/1000
,這樣做會導致編碼出來的音影片,在播放時,總時長顯示的是錯誤的。應該記錄開始時候的
nanoTime
,然後設定
presentationTimeUs
為
(System.nanoTime()-nanoTime)/1000
。
短影片系統錄製結束時,應該傳送結束標誌MediaCodec.BUFFER_FLAG_END_OF_STREAM
,在編碼後區獲得這個標誌時再終止迴圈,而不是直接終止迴圈。
應該還有其他需要注意的問題。我暫時還沒遇到。
————————————————
宣告:宣告:本文由雲豹科技轉發自CSDN
【
湖廣午王
】部落格,如有侵權請聯絡作者刪除
原文連結:https://blog.csdn.net/junzia/article/details/54018671
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70002045/viewspace-2779322/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android短影片系統硬編碼—實現音影片編碼(二)Android
- 短影片電商系統,編寫延遲訊息實現程式碼
- Android 音視訊錄製硬編碼實現Android
- Android音訊實時傳輸與播放(三):AMR硬編碼與硬解碼Android音訊
- 短影片程式原始碼,如何實現短影片的熱門頁面原始碼
- 秘樂短影片原始碼系統開發搭建原始碼
- C++實現RTMP協議傳送H.264編碼及AAC編碼的直播軟體開發音影片C++協議
- 短影片APP系統原始碼,定製開發功能APP原始碼
- 六點概括短影片系統原始碼的實用功能機制原始碼
- 陪玩系統原始碼實現音訊編碼的相關步驟原始碼音訊
- Media Encoder 2022 for Mac(AME音影片編碼工具)Mac
- 夢幻自主研發android安卓和IOS蘋果系統短影片原始碼Android安卓iOS蘋果原始碼
- 短影片的“火”,離不開短影片app原始碼的這三個核心功能APP原始碼
- Python音影片編輯庫:moviepyPython
- 阿里雲影片雲正式支援AV1編碼格式 為影片編碼服務降本提效阿里
- 短影片系統原始碼——“潮流”標籤之下蘊藏哪些實用功能原始碼
- 影片轉碼編輯工具Compressor for MacMac
- 一文搞懂影片編解碼原理
- iOS/Android 影片編輯SDKiOSAndroid
- 短影片商城系統,session和cookie實現登入SessionCookie
- 影片直播系統原始碼,非同步處理實現程式碼分析原始碼非同步
- 短影片整套原始碼,如何實現冪等性校驗?原始碼
- Android 音視訊開發 視訊編碼,音訊編碼格式Android音訊
- C++語言的音影片開發應用模式(採集、編碼、解碼...)C++模式
- QLab Pro for Mac(現場表演類實時音影片編輯工具)Mac
- 移動端短影片SDK,企業級影片編輯解決方案
- 短影片軟體系統開發:選擇開源原始碼原始碼
- 短影片直播系統,Android卡片式輪播Android
- pygame播放影片並實現音影片同步GAM
- H.265 & HEVC 影片編碼 All In One
- 短影片直播功能開發定製短影片系統功能需求無加密加密
- 轉載:iOS音視訊實時採集硬體編碼iOS
- 兔子短影片直播(卷軸)系統技術開發(原始碼搭建)原始碼
- 如何提高還在用window系統的編碼硬效率
- Filmage Editor for Mac(專業音影片編輯工具)Mac
- 短影片直播APP原生開發直播系統無加密搭建定製短影片APP加密
- 短影片app開發,短影片系統發展的收益方式是什麼?APP
- 音影片編解碼技術在直播平臺中是如何運用的?