首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MediaCodec.dequeueOutputBuffer在搜索Ogg音频文件时超时

MediaCodec.dequeueOutputBuffer在搜索Ogg音频文件时超时
EN

Stack Overflow用户
提问于 2014-03-01 09:47:49
回答 1查看 4K关注 0票数 1

播放.ogg文件时,.dequeueOutputBuffer()总是在MediaCodec.INFO_TRY_AGAIN_LATER调用MediaExtractor.seekTo()后超时。这会导致问题,因为我正在尝试创建近乎无缝的搜索。最大阻塞时间是无关紧要的,无论设置多长时间,它都会超时。

所有.ogg文件都会发生这种情况,而不是其他音频文件类型。

下面是相关代码,超时发生在

代码语言:javascript
复制
final int res = codec.dequeueOutputBuffer(info, TIMEOUT_US);

每次对.ogg文件调用seekTo()后都会发生这种情况,有没有办法纠正这个问题呢?

代码语言:javascript
复制
public MediaCodecMp3Decoder(String fullPath) throws IOException
    {
        extractor = new MediaExtractor();
        extractor.setDataSource(fullPath);

        format = extractor.getTrackFormat(0);
        String mime = format.getString(MediaFormat.KEY_MIME);
        durationUs = format.getLong(MediaFormat.KEY_DURATION);

        codec = MediaCodec.createDecoderByType(mime);
        codec.configure(format, null, null, 0);
        codec.start();
        codecInputBuffers = codec.getInputBuffers();
        codecOutputBuffers = codec.getOutputBuffers();

        extractor.selectTrack(0);
        info = new MediaCodec.BufferInfo();
    }


public byte[] decodeChunk()
    {
        advanceInput();

        final int res = codec.dequeueOutputBuffer(info, TIMEOUT_US);
        if (res >= 0)
        {
            int outputBufIndex = res;
            ByteBuffer buf = codecOutputBuffers[outputBufIndex];
            if(chunk == null || chunk.length != info.size)
            {
                chunk = new byte[info.size];
            }
            buf.get(chunk);
            buf.clear();
            codec.releaseOutputBuffer(outputBufIndex, false);
        }
        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
        {
            sawOutputEOS = true;
        }
        else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
        {
            codecOutputBuffers = codec.getOutputBuffers();
        }
        else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
        {
            format = codec.getOutputFormat();
            Log.d("MP3", "Output format has changed to " + format);
        }

        return chunk;
    }

private void advanceInput()
{
    boolean sawInputEOS = false;

    int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_US);
    if (inputBufIndex >= 0)
    {
        ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];

        int sampleSize = extractor.readSampleData(dstBuf, 0);
        long presentationTimeUs = 0;

        if (sampleSize < 0)
        {
            sawInputEOS = true;
            sampleSize = 0;
        }
        else
        {
            presentationTimeUs = extractor.getSampleTime();
            currentTimeUs += presentationTimeUs - lastPresentationTime;
            lastPresentationTime = presentationTimeUs;
        }

        codec.queueInputBuffer(inputBufIndex,
                0,
                sampleSize,
                presentationTimeUs,
                sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
        if (!sawInputEOS)
        {
            extractor.advance();
        }
    }
}

public void seek(long timeInUs)
    {
        extractor.seekTo(timeInUs, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
        lastPresentationTime = currentTimeUs = timeInUs;
        codec.flush();
    }

在seekTo()之前和之后,AudioTrack上的缓冲区不足是由于我当前为dequeueOutputBuffer()设置的1秒超时造成的

代码语言:javascript
复制
03-01 13:48:25.042: I/AudioFlinger(125): BUFFER TIMEOUT: remove(4099) from active list on thread 0x40b42008
03-01 13:48:25.312: W/AudioTrack(29349): releaseBuffer() track 0x6a110c10 name=s:125;n:3;f:-1 disabled due to previous underrun, restarting

另外,我应该注意到,对seekTo()和decodeChunk()的调用发生在不同的线程上,但它们在同一对象上是同步的。

代码语言:javascript
复制
synchronized (decodeLock)
{
    decoder.seek(timeInUs);
}

synchronized (decodeLock)
{
    input = decoder.decodeChunk();
...
}
EN

回答 1

Stack Overflow用户

发布于 2015-06-28 09:33:24

seek的实现调用codec.flush,它将丢弃输出队列中任何已解码的缓冲区。如果decoder.seek恰好在decoder.decodeChunk之前,则输出队列将为空。在调用seek之前,请确保输出已出队。

此外,某些解码器(依赖于芯片组/OEM)将具有输入阈值。在期望任何输出缓冲区之前,请尝试多次调用advanceInput

例如,请参阅MediaCodecTrackRenderer.java中的ExoPlayer的输入/输出工作循环。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22109050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档