Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/221.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android视频的精确搜索_Android_Android Mediacodec_Seek_Mediaextractor_Grafika - Fatal编程技术网

Android视频的精确搜索

Android视频的精确搜索,android,android-mediacodec,seek,mediaextractor,grafika,Android,Android Mediacodec,Seek,Mediaextractor,Grafika,我正在使用MediaExtractor的seekTo()进行精确搜索。虽然我可以毫无问题地尝试同步帧,但我想尝试特定的时间。这个问题让我想到了一些方法,但我不确定它们是否有效。基本上,我必须寻找最接近的前一个同步帧,然后advance()提取程序,直到达到目标时间。该过程中的每一帧将被馈送到解码器,即第一个i帧和剩余的P帧。这是相关的代码片段(基于的MoviePlayer): extractor.seekTo((长)seekTarget[threadNr],MediaExtractor.SEEK

我正在使用MediaExtractor的
seekTo()
进行精确搜索。虽然我可以毫无问题地尝试同步帧,但我想尝试特定的时间。这个问题让我想到了一些方法,但我不确定它们是否有效。基本上,我必须寻找最接近的前一个同步帧,然后
advance()
提取程序,直到达到目标时间。该过程中的每一帧将被馈送到解码器,即第一个i帧和剩余的P帧。这是相关的代码片段(基于的MoviePlayer):

extractor.seekTo((长)seekTarget[threadNr],MediaExtractor.SEEK\u TO\u PREVIOUS\u SYNC);
...
while(extractor.getSampleTime()<(长)seekTarget[threadNr]){
Log.d(标记“Thread”+threadNr+“advanced to timestamp”+extractor.getSampleTime());
int inputBufIndex=解码器.dequeueInputBuffer(超时\u USEC);
如果(inputBufIndex>=0){
ByteBuffer InBuffer=decoderInputBuffers[inputBufIndex];
int chunkSize=extractor.readSampleData(inBufer,0);
if(chunkSize<0){
//流结束——发送设置了EOS标志的空帧。
解码器。queueInputBuffer(inputBufIndex,0,0,0L,
MediaCodec.BUFFER\u标志\u结束\u流);
输入完成=真;
if(VERBOSE)Log.d(标记“发送的输入EOS”);
}否则{
if(提取器.getSampleTrackIndex()!=trackIndex){
Log.w(标记“怪异:从跟踪中获取样本”+
提取器.getSampleTrackIndex()+”,应为“+trackIndex);
}
long presentationTimeUs=提取器.getSampleTime();
解码器.queueInputBuffer(inputBufIndex,0,chunkSize,
presentationTimeUs,0/*标志*/);
如果(详细){
Log.d(标记“提交的帧”+inputChunk+”到十二月,大小=”+
chunkSize+“inputBufIndex:”+inputBufIndex);
}
inputChunk++;
提取器;
}
}
}

你可以想象,通常我会排队等待大量的帧,但现在我对内存消耗或最终的延迟没有意见。问题是
dequeueInputBuffer()
方法只在循环中工作一段时间,最终在返回-1时出错,根据文档说明,这意味着缓冲区不可用。如果我将
超时\u USEC
更改为
-1
,我将得到无限循环

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

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

您需要通过请求输出缓冲区来耗尽解码器。释放缓冲区时,将“render”标志设置为false,这样它就不会出现在屏幕上

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();
        }
    }
}