Android 音視頻開發(fā)之MediaMuxer

簡介

在Android中,可以使用MediaMuxer來封裝編碼后的視頻流和音頻流到mp4容器中,MediaMuxer最多僅支持一個視頻track和一個音頻track,所以如果有多個音頻track可以先把它們混合成為一個音頻track然后再使用MediaMuxer封裝到mp4容器中。
通常視頻編碼使用H.264(AVC)編碼,音頻編碼使用AAC編碼,在MediaFormat中我們可以看到各種編碼格式:

public static final String MIMETYPE_VIDEO_AVC = "video/avc";
public static final String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
public static final String MIMETYPE_TEXT_CEA_608 = "text/cea-608";

  • 使用
  1. 通過new MediaMuxer(String path, int format)指定視頻文件輸出路徑和文件格式:

    MediaMuxer mMediaMuxer = new MediaMuxer(mOutputVideoPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    
  2. 創(chuàng)建MediaMuxer對象之后,一個比較重要的操作就是addTrack(MediaFormat format),添加媒體通道,該函數(shù)需要傳入MediaFormat對象,通常從MediaExtractor或者MediaCodec中獲取,如果希望自己創(chuàng)建的話可以直接new或者通過該類如下靜態(tài)方法創(chuàng)建:

    MediaFormat.createAudioFormat(...);
    MediaFormat.createVideoFormat(...);
    MediaFormat.createSubtitleFormat(...);
    

    如果是自己創(chuàng)建MediaFormat要根據(jù)媒體類型配置好相應的keys,這里注意一定要設置csd參數(shù),否則添加進MediaMuxer的MediaFormat會導致MediaMuxer調(diào)用stop()時拋出異常。csd參數(shù)在官方文檔中叫Codec-specific Data,詳細介紹可以看MediaCodec官方文檔 - Codec-specific Data部分。對于H.264來說,"csd-0"和"csd-1"分別對應sps和pps;對于AAC來說,"csd-0"對應ADTS。

    MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
    byte[] header_sps = {0, 0, 0, 1, 103, 100, 0, 31, -84, -76, 2, -128, 45, -56};
    byte[] header_pps = {0, 0, 0, 1, 104, -18, 60, 97, 15, -1, -16, -121, -1, -8, 67, -1, -4, 33, -1, -2, 16, -1, -1, 8, 127, -1, -64};
    videoFormat.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps));
    videoFormat.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps));
    videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
    videoFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
    videoFormat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 25);
    
  3. 把MediaFormat添加到MediaMuxer后記錄返回的track index,添加完所有track后調(diào)用start方法:

    videoTrackIndex = mMediaMuxer.addTrack(format);
    audioTrackIndex = mMediaMuxer.addTrack(format);
    mMediaMuxer.start();
    
  4. 然后就可以調(diào)用MediaMuxer.writeSampleData()向mp4文件中寫入數(shù)據(jù)了。這里要注意每次只能添加一幀視頻數(shù)據(jù)或者單個Sample的音頻數(shù)據(jù),并且BufferInfo對象的值一定要設置正確:

    info.offset = 0;
    info.size = sampleSize;
    必須填入數(shù)據(jù)的大小
    info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
    需要給出是否為同步幀/關鍵幀
    info.presentationTimeUs = mVideoExtractor.getSampleTime();
    必須給出正確的時間戳,注意單位是 us
    mMediaMuxer.writeSampleData(videoTrackIndex, buffer, info);
    
  5. 結束寫入后關閉以及釋放資源

    mMediaMuxer.stop();
    mMediaMuxer.release();
    
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容