2016-04-29 640 views
1

我試圖流數據(h.264原始1080p)到android並呈現它到表面view.The問題是,如果我發送數據速度超過45fps解碼器輸出像素化(輸入索引&輸出索引是-1或沒有準備好)Mediacodec渲染到表面緩慢

此外,如果我發送720p或更低分辨率的視頻結果是相同的我無法呈現(沒有像素化)比45fps更快。

但如果我設置渲染標誌爲「假」,在releaseOutputBuffer(),我能夠達到75fps(我接收輸入&輸出指標均正常)

那麼,有沒有「解鎖」的一種方式幀率?或另一種渲染速度更快的方式。

注意:我在ndk裏面做這個。

初始化解碼器()

AMediaFormat *AVm_format = AMediaFormat_new(); 
AMediaFormat *AVm_formattesting = AMediaFormat_new(); 
AVm_codec = AMediaCodec_createDecoderByType("video/avc"); 
AVm_formattesting =AMediaCodec_getOutputFormat(AVm_codec); 
int formatint=0; 
AMediaCodec_createCodecByName("OMX.qcom.video.decoder.avc"); 
    AMediaFormat_setString(AVm_format,AMEDIAFORMAT_KEY_MIME,"video/avc"); 
    AMediaFormat_setInt32(AVm_format,AMEDIAFORMAT_KEY_HEIGHT,1920); 
    AMediaFormat_setInt32(AVm_format,AMEDIAFORMAT_KEY_WIDTH,1080); 
     AMediaFormat_setInt32(AVm_format,AMEDIAFORMAT_KEY_COLOR_FORMAT,13); 
    try { 

     AMediaCodec_configure(AVm_codec, AVm_format, Nwindow, NULL, 0); 
     LOGD("Configure finished...\n"); 
     AMediaCodec_start(AVm_codec); 
     LOGD("Decoder started\n"); 
    }catch(std::exception e){ 

     LOGD("FAILED TO CONFIGURE DECODER\n"); 

    } 

解碼(...)

//pData is the frame I recive 
//sz is the size of the frame 

ssize_t indx = AMediaCodec_dequeueInputBuffer(AVm_codec, 0); 


    if (indx >= 0) { 
     input = AMediaCodec_getInputBuffer(AVm_codec, indx, &insize); 

    // memset(input,0,sz); 
     memcpy(input,pData,sz); 
     AMediaCodec_queueInputBuffer(AVm_codec, indx, 0, sz, 0, 0); 
    } 

    ssize_t indy = AMediaCodec_dequeueOutputBuffer(AVm_codec, AVm_buffinfo, 0); 

    if (indy >= 0) { 
     AMediaCodec_releaseOutputBuffer(AVm_codec, indy, false); 
    } else if(indy == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED){ 
     LOGD("output buffers changed\n"); 
    } else if (indy == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { 
     AMediaFormat *format = NULL; 
     format = AMediaCodec_getOutputFormat(AVm_codec); 
     LOGD("format changed to: %s", AMediaFormat_toString(format)); 
     AMediaFormat_delete(format); 
     LOGD("format changed to:\n"); 
    } else if (indy == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { 
     LOGD("no output buffer right now\n"); 

    } else { 
     LOGD("unexpected info code: %zd\n", indy); 

    } 

如果需要其他任何東西讓我知道吧。

回答

0

我並不完全確定發生了什麼 - 將解碼幀傳遞給SurfaceView的速率不應影響輸出的質量。這聽起來更像是數據被饋送到解碼器的方式的問題,例如,您正在覆蓋仍在讀取的H.264數據的緩衝區。

發送到SurfaceView表面的幀不會丟失,因此如果您嘗試以比設備刷新速率更快的速度提供幀,您的releaseOutputBuffer(..., true)將會被阻擋。在大多數設備上,這是60fps。您可以閱讀更多關於系統在graphics architecture doc中的工作方式。

有一點要記住的是,解碼視頻幀並不通過releaseOutputBuffer()這麼多呈現轉發。 IPC交易有一定的成本,但我預計你所看到的大部分是呼叫阻塞的效果,以保持每幀穩定16.7ms。

+0

感謝您的回覆。基本上,流正在渲染(無論artifact0爲45fps,無論解析度是什麼分辨率,我只是想知道如果表面視圖有一個Vsync限制fps。 – MyNameisAwesome

+1

SurfaceView將限制您的設備刷新率。僅僅作爲'releaseOutputBuffer()'在等待vsync時花費很長時間纔會返回 - 它不應該對輸出的質量產生任何影響。我的猜測是時序變化暴露了代碼中的競爭條件。如果你需要將幀解碼得比它能夠顯示的速度快,你需要將「false」傳遞給釋放方法來丟棄幀(例如替代真/假以將顯示的幀速率減半)。 – fadden