Android精确搜索视频 [英] Android Precise seeking of video

查看:198
本文介绍了Android精确搜索视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力使用MediaExtractor的seekTo()进行精确查找.虽然我可以尝试无问题地同步帧,但我想尝试特定的时间. 这个问题使我想到了一些实现方法,但是我不确定它们是否有效.基本上,我将必须先寻找最接近的上一个同步帧,然后再提取advance()直到达到目标时间.该过程中的每个帧将被馈送到解码器,即第一个I帧和其余的P帧.这是相关的代码段(基于 google/grafika 的MoviePlayer):

I'm struggling with precise seeking using MediaExtractor's seekTo(). While I can seek to sync frames without problems, I would like to seek to specific time. This question led me to some ideas how to do this, but I'm not sure if they are valid. Basicly, I would have to seek to closest previous sync frame and then advance() the extractor until target time is reached. Every frame in the process would be fed to the decoder, i.e the first I-frame and the rest P-frames. This is related code snippet (based on google/grafika's MoviePlayer):

extractor.seekTo((long) seekTarget[threadNr], MediaExtractor.SEEK_TO_PREVIOUS_SYNC);

...

while (extractor.getSampleTime() < (long) seekTarget[threadNr]) {
    Log.d(TAG, "Thread " + threadNr + " advanced to timestamp " + extractor.getSampleTime());

    int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
    if (inputBufIndex >= 0) {
        ByteBuffer inBufer = decoderInputBuffers[inputBufIndex];
        int chunkSize = extractor.readSampleData(inBufer, 0);

        if (chunkSize < 0) {
            // End of stream -- send empty frame with EOS flag set.
            decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L,
                    MediaCodec.BUFFER_FLAG_END_OF_STREAM);
            inputDone = true;
            if (VERBOSE) Log.d(TAG, "sent input EOS");
        } else {
            if (extractor.getSampleTrackIndex() != trackIndex) {
                Log.w(TAG, "WEIRD: got sample from track " +
                        extractor.getSampleTrackIndex() + ", expected " + trackIndex);
            }

            long presentationTimeUs = extractor.getSampleTime();
            decoder.queueInputBuffer(inputBufIndex, 0, chunkSize,
                    presentationTimeUs, 0 /*flags*/);
            if (VERBOSE) {
                Log.d(TAG, "submitted frame " + inputChunk + " to dec, size=" +
                        chunkSize + " inputBufIndex: " + inputBufIndex);
            }
            inputChunk++;
            extractor.advance();
        }
    }
}

您可以想象,通常我会排队大量帧,但是现在我可以解决内存消耗或最终出现滞后的问题.问题在于dequeueInputBuffer()方法仅在循环中工作一段时间,最终在返回-1时卡住,因此根据文档,这意味着该缓冲区不可用.如果将TIMEOUT_USEC更改为-1,则会出现无限循环.

有人可以告诉我这种方法是否正确,或者为什么在某些时候我无法访问inputBuffer?

As you can imagine, usually I'm queuing large amount of frames, but for now I'm fine with memory consumption or eventual lag. The problem is that the dequeueInputBuffer() method works only for some time in the loop, eventualy stucks at returning -1, which accordingly to documentation means that the buffer is unavailiable. If I would change the TIMEOUT_USEC to -1, I get infinite loop.

Can someone please tell me if this approach is correct or why at some point I can't get access to inputBuffer?

推荐答案

您似乎没有从输出端提取缓冲区. MediaCodec解码器不会丢帧,因此当其内部缓冲区填满时,它将停止处理输入缓冲区.

You don't appear to be pulling buffers from the output side. The MediaCodec decoder doesn't drop frames, so when its internal buffers fill up it will stop handing you input buffers.

您需要通过请求输出缓冲区来耗尽解码器.释放缓冲区时,请将"render"标志设置为false,以使其不显示在屏幕上.

You need to drain the decoder by requesting output buffers. When you release the buffer, set the "render" flag to false so it doesn't appear on screen.

这篇关于Android精确搜索视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆