Mediacodec 渲染到表面缓慢

Mediacodec rendering to surface slow

我正在尝试将数据(h.264 原始 1080p)流式传输到 android 并将其渲染到表面 view.The 问题是,如果我发送数据的速度超过 45fps,则解码器输出是像素化(输入索引和输出索引为-1或未准备好)

此外,如果我发送 720p 或更低分辨率的视频,结果是相同的,我无法渲染(没有像素化)快于 45fps。

但是如果我在 releaseOutputBuffer() 中将渲染标志设置为 "False" 我能够达到 75fps(我收到的输入和输出索引是正常的)

那么有没有办法 "unlock" 帧率?或另一种渲染速度更快的方法。

注意:我在 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);

     }

如果还有什么需要请告诉我。

我不完全确定发生了什么 -- 解码帧传送到 SurfaceView 的速率不应影响输出质量。这听起来更像是数据被送入解码器的方式的问题,例如您正在覆盖仍在读取的 H.264 数据缓冲区。

发送到 SurfaceView 的 Surface 的帧不会被丢弃,因此如果您尝试以快于设备刷新率的速度为其提供帧,您的 releaseOutputBuffer(..., true) 将被阻止。在大多数设备上,这是 60fps。您可以在 graphics architecture doc.

中阅读有关系统工作方式的更多信息

要记住的一件事是,解码后的视频帧没有被 releaseOutputBuffer() 渲染,而是 转发 ]. IPC 事务有一些成本,但我希望您看到的大部分是调用阻塞的效果,以保持稳定的每帧 16.7 毫秒。