我正在努力使用MediaExtractor seekTo()
进行精确搜索。虽然我可以毫无问题地寻求同步帧,但我想寻求具体的时间。 This问题让我想到了如何做到这一点,但我不确定它们是否有效。基本上,我必须寻找最接近的前一个同步帧然后advance()
提取器,直到达到目标时间。该过程中的每一帧都将被馈送到解码器,即第一个I帧和其余的P帧。这是相关的代码段(基于google/grafika的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
?
答案 0 :(得分:5)
你似乎没有从输出端拉出缓冲区。 MediaCodec解码器不会丢帧,所以当内部缓冲区填满时,它会停止处理输入缓冲区。
您需要通过请求输出缓冲区来耗尽解码器。释放缓冲区时,设置&#34;渲染&#34;标记为false,因此它不会出现在屏幕上。