網路視訊直播系統開發,視訊解碼是如何實現的?

雲豹科技程式設計師發表於2021-09-25
在網路視訊直播系統中,流媒體傳輸流程涉及了很多環節,像採集、編碼、解碼、傳輸、處理等,其中解碼關係著直播內容呈現的效果,所以需要引起足夠的重視,在網路視訊直播系統中解碼的實現流程是什麼樣的呢?

解碼流程

1、初識化,啟動解碼器根據MediaFormat中的編碼型別(如video/avc,即H264;audio/mp4a-latm,即AAC)建立MediaCodec
//通過Extractor獲取到音視訊資料的編碼資訊MediaFormat
val type = mExtractor!!.getFormat()!!.getString(MediaFormat.KEY_MIME)
//呼叫createDecoderByType建立解碼器。
mCodec = MediaCodec.createDecoderByType(type)
2、將網路視訊直播系統資料壓入解碼器輸入緩衝如果SampleSize返回-1,說明沒有更多的資料了。queueInputBuffer的最後一個引數要傳入結束標記MediaCodec.BUFFER_FLAG_END_OF_STREAM。
//查詢是否有可用的輸入緩衝,返回緩衝索引
var inputBufferIndex = mCodec!!.dequeueInputBuffer(2000)
//獲取可用的緩衝區,並使用Extractor提取待解碼資料,填充到緩衝區中。
val inputBuffer = mInputBuffers!![inputBufferIndex]
val sampleSize = mExtractor!!.readBuffer(inputBuffer)
//呼叫queueInputBuffer將資料壓入解碼器。
mCodec!!.queueInputBuffer(inputBufferIndex, 0,sampleSize, mExtractor!!.getCurrentTimestamp(), 0)
    /**
     * 讀取視訊資料
     */
    fun readBuffer(byteBuffer: ByteBuffer): Int {
        //【3,提取資料】
        byteBuffer.clear()
        selectSourceTrack()
        var readSampleCount = mExtractor!!.readSampleData(byteBuffer, 0)
        if (readSampleCount < 0) {
            return -1
        }
        mCurSampleTime = mExtractor!!.sampleTime
        mExtractor!!.advance()
        return readSampleCount
    }
    /**
     * 選擇通道
     */
    private fun selectSourceTrack() {
        if (mVideoTrack >= 0) {
            mExtractor!!.selectTrack(mVideoTrack)
        } else if (mAudioTrack >= 0) {
            mExtractor!!.selectTrack(mAudioTrack)
        }
    }
3、將解碼好的資料從網路視訊直播系統緩衝區拉取出來
// 查詢是否有解碼完成的資料,index >=0 時,表示資料有效,並且index為緩衝區索引
var index = mCodec!!.dequeueOutputBuffer(mBufferInfo, 1000)
when (index) {
//輸出格式改變了
MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> {}
//沒有可用資料,等會再來
MediaCodec.INFO_TRY_AGAIN_LATER -> {}
//輸入緩衝改變了
MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED -> {
mOutputBuffers = mCodec!!.outputBuffers
}
else -> {
return index
}
}
4、渲染 視訊渲染網路視訊直播系統中視訊的渲染並不需要客戶端手動去渲染,只需在config時提供繪製表面surface,如果為編解碼器配置了輸出表面,則將render設定為true會首先將緩衝區傳送到該輸出表面。
public void configure (MediaFormat format, Surface surface, MediaCrypto crypto, int flags)
releaseOutputBuffer (int index, boolean render)
音訊渲染config時音訊不需要surface,直接傳null。需要獲取取樣率,通道數,取樣位數等。需要初始化一個網路視訊直播系統音訊渲染器:AudioTrack
AudioTrack只能播放PCM資料流。
//獲取最小緩衝區
val minBufferSize = AudioTrack.getMinBufferSize(mSampleRate, channel, mPCMEncodeBit)
mAudioTrack = AudioTrack(
    AudioManager.STREAM_MUSIC,//播放型別:音樂
    mSampleRate, //取樣率
    channel, //通道
    mPCMEncodeBit, //取樣位數
    minBufferSize, //緩衝區大小
    AudioTrack.MODE_STREAM) //播放模式:資料流動態寫入,另一種是一次性寫入
 
mAudioTrack!!.play()
AudioTrack中有MODE_STATIC和MODE_STREAM兩種分類。STREAM的意思是由使用者在應用程式通過write方式把資料一次一次得寫到audiotrack中。這個和我們在socket中傳送資料一樣,AudioTrack應用層從某個地方獲取資料,例如通過編解碼得到PCM資料,然後write到audiotrack。這種方式的壞處就是總是在JAVA層和Native層互動,效率損失較大。
而STATIC的意思是一開始建立的時候,就把音訊資料放到一個固定的buffer,然後直接傳給audiotrack,後續就不用一次次得write了。AudioTrack會自己播放這個buffer中的資料。這種方法對於AudioTrack鈴聲等記憶體佔用較小,延時要求較高的聲音來說很適用
5、釋放輸出緩衝
mCodec!!.releaseOutputBuffer(index, true)
6、判斷解碼是否完成
  if (mBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
    }
7、釋放解碼器釋放掉所有的資源。至此,網路視訊直播系統一次解碼結束。
mExtractor?.stop()
 mCodec?.stop()
 mCodec?.release()
 /**
     * 停止讀取資料
     */
    fun stop() {
        //【4,釋放提取器】
        mExtractor?.release()
        mExtractor = null    }
以上便是“網路視訊直播系統的流媒體傳輸中解碼的實現流程”的全部內容,希望對大家有幫助。 本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2793678/,如需轉載,請註明出處,否則將追究法律責任。

相關文章