Mediacodec渲染到Surface慢

3
我正在尝试将数据(h.264原始1080p)流式传输到Android并将其渲染到SurfaceView上。问题在于,如果我发送的数据速度超过45fps,则解码器输出会出现像素化(输入索引和输出索引为-1或未准备好)。
此外,如果我发送的是720p或更低分辨率视频,则结果相同,我无法以不出现像素化的方式呈现速度快于45fps的视频。
但是,如果我在releaseOutputBuffer()中设置渲染标志为“False”,则我能够达到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");

    }

Decoding(...)

//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);

     }

如果需要其他内容,请告诉我。
1个回答

3
我不确定发生了什么 - 解码帧传递到SurfaceView的速率不应影响输出质量。这更像是数据被输入解码器的方式存在问题,例如,您正在覆盖尚未读取的H.264数据缓冲区。
发送到SurfaceView Surface的帧不会丢失,因此如果您尝试以快于设备刷新率的速度提供帧,则releaseOutputBuffer(...,true)将被阻止。 在大多数设备上,这是60fps。 您可以在图形架构文档中了解有关系统工作方式的更多信息。
需要记住的一件事是,解码后的视频帧并没有由releaseOutputBuffer()渲染,而是转发。 IPC事务存在一些成本,但我认为您看到的大部分是呼叫阻塞以保持每帧16.7ms的稳定效果。

感谢您的回复。基本上,无论我向解码器提供什么分辨率,流都以45fps渲染(没有伪影)。我只是想知道SurfaceView是否有一个Vsync来限制帧率。 - MyNameisAwesome
1
SurfaceView将限制您的设备刷新率。这应该只表现为releaseOutputBuffer()需要很长时间才能返回,同时等待vsync - 它不应对输出质量产生任何影响。我猜测时间上的变化暴露了您代码中的竞争条件。如果您需要解码比它们可以显示更快的帧,则需要将“false”传递给释放方法以丢弃帧(例如,交替使用true / false来减半显示的帧速率)。 - fadden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接