2014-03-24 42 views
5

Android提供了查詢支持的編碼配置文件的方法。但是,當設置一個編碼器時,我找不到指定要使用的所需配置文件的方式。使用MediaCodec API在Android中編碼視頻時設置AVC/H.264配置文件

查找支持配置文件/等級對

android系統中使用MediaCodec API,您可以撥打getCodecInfo()你一旦選擇一個編碼器組件。這將返回一個MediaCodecInfo對象,該對象提供有關正在使用的編解碼器組件的詳細信息。 getCapabilitiesForType()返回一個CodecCapabilities對象,詳細說明編解碼器的功能。它包含一個數組CodecProfileLevel,詳細說明支持的受支持的配置文件和級別。

嘗試設置輪廓

我看不到一個字段設置天寒MedieCodec或爲MediaFormat

對於MediaFormatKEY_AAC_PROFILE,但在參考文獻中明確指出這僅用於aac音頻。

MediaCodec有一種方法可以使用setParameters()Bundle的額外參數傳遞給編解碼器。這看起來好像沒有通用文檔,接受的參數在編解碼器(不同設備)之間會有所不同。

背景

檔案指定一組編碼功能來使用。簡單的配置文件計算量較小,但通常會因爲給定的比特率而犧牲質量。這些級別指定給定配置文件支持的最大分辨率/比特率。我期望的水平通常與解碼能力有關,但由於它描述了一個必須實時運行的硬件編碼器,因此具有最大的設置對我來說是合情合理的。

META:(我本來有很多更多的鏈接到我提到的每個類+功能,但我不得不刪除他們,因爲我還沒有在代表發佈超過2個鏈接)

回答

3

有在MediaCodec API中沒有顯式的配置文件選擇。編解碼器將自行選擇一個配置文件。它還將根據輸入寬度/高度和幀速率數字選擇一個級別,但它可能會選擇高於配置所需最低級別的級別。

您可以查詢支持級別的編碼器編解碼器以查看它可能生成的配置文件,但是您將無法選擇首選的配置文件。編解碼器很可能會選擇它可以在給定級別上處理的最高配置文件,但不能保證這一點。

3

對於Android Kitkat設備,我們可以根據下面的代碼片段(設置基準級別爲1.3)將所需的AVC配置文件和級別設置爲媒體格式。請在啓動MediaCodec之前設置此項。

format.setInteger("profile",MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline); 
    format.setInteger("level", MediaCodecInfo.CodecProfileLevel.AVCLevel13); 
+0

選擇AVCProfileHigh,我應該選擇什麼水平? – dragonfly

0

配置文件和級別提示可以被給定的AVC編碼器忽略。

要絕對確定AVC編碼器選擇了哪個配置文件和級別,可以在MediaFormat啓動後(例如在初始格式更改事件期間)實時查詢SPS。

請參閱spec的第7部分。

這張海報顯示拉從這些的base64字符串的檔次和級別(請給予好評他!):

Can profile-level-id and sprop-parameter-sets be extracted from an RTP stream?

下面是Base64編碼的SPS和PPS:如果我

... 
mIndex = mMediaEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT); 

// First buffer encoded is the NAL frame metadata 
if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
{ 
    Log.i("PPS: "+getParameterSetAsString(mMediaEncoder, "csd-0"); 
    Log.i("SPS: "+getParameterSetAsString(mMediaEncoder, "csd-1"); 
} 
... 

private String getParameterSetAsString(MediaCodec encoder, String csd) 
{ 
    MediaFormat mMediaFormat = encoder.getOutputFormat(); 
    ByteBuffer ps = mMediaFormat.getByteBuffer(csd); 

    // The actual SPS and PPS byte codes 
    byte[] mPS = new byte[ps.capacity()-4]; 
    ps.position(4); 
    ps.get(mPS,0,mPS.length); 

    //Covert to String 
    return Base64.encodeToString(mPS, 0, mPS.length, Base64.NO_WRAP); 
}