下面列出了android.media.MediaCodec# flush ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* This method implements the actual seeking and can be overwritten by subclasses to implement
* custom seeking methods.
*
* @see #seekTo(MediaPlayer.SeekMode, long)
*/
protected FrameInfo seekTo(MediaPlayer.SeekMode seekMode, long seekTargetTimeUs,
MediaExtractor extractor, MediaCodec codec) throws IOException {
if(mPassive) {
// Even when not actively seeking, the codec must be flushed to get rid of left over
// audio frames from the previous playback position and the EOS flags need to be reset too.
mInputEos = false;
mOutputEos = false;
codec.flush();
return null;
}
Log.d(TAG, "seeking to: " + seekTargetTimeUs);
Log.d(TAG, "extractor current position: " + extractor.getSampleTime());
extractor.seekTo(seekTargetTimeUs, seekMode.getBaseSeekMode());
Log.d(TAG, "extractor new position: " + extractor.getSampleTime());
// TODO add seek cancellation possibility
// e.g. by returning an object with a cancel method and checking the flag at fitting places within this method
mInputEos = false;
mOutputEos = false;
codec.flush();
if(extractor.hasTrackFormatChanged()) {
reinitCodec();
mRepresentationChanged = true;
}
return decodeFrame(true, true);
}
private static void renderHevcImage(ByteBuffer bitstream, ImageInfo info, Surface surface) {
long beginTime = SystemClock.elapsedRealtimeNanos();
// configure HEVC decoder
MediaCodec decoder = configureDecoder(info, bitstream.limit(), surface);
MediaFormat outputFormat = decoder.getOutputFormat();
Log.d(TAG, "HEVC output-format=" + outputFormat);
decoder.start();
try {
// set bitstream to decoder
int inputBufferId = decoder.dequeueInputBuffer(-1);
if (inputBufferId < 0) {
throw new IllegalStateException("dequeueInputBuffer return " + inputBufferId);
}
ByteBuffer inBuffer = decoder.getInputBuffer(inputBufferId);
inBuffer.put(bitstream);
decoder.queueInputBuffer(inputBufferId, 0, bitstream.limit(), 0, 0);
// notify end of stream
inputBufferId = decoder.dequeueInputBuffer(-1);
if (inputBufferId < 0) {
throw new IllegalStateException("dequeueInputBuffer return " + inputBufferId);
}
decoder.queueInputBuffer(inputBufferId, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
// get decoded image
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
while (true) {
int outputBufferId = decoder.dequeueOutputBuffer(bufferInfo, -1);
if (outputBufferId >= 0) {
decoder.releaseOutputBuffer(outputBufferId, true);
break;
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
outputFormat = decoder.getOutputFormat();
Log.d(TAG, "HEVC output-format=" + outputFormat);
} else {
Log.d(TAG, "HEVC dequeueOutputBuffer return " + outputBufferId);
}
}
decoder.flush();
} finally {
decoder.stop();
decoder.release();
}
long endTime = SystemClock.elapsedRealtimeNanos();
Log.i(TAG, "HEVC decoding elapsed=" + (endTime - beginTime) / 1000000.f + "[msec]");
}
private long fastSeek(long targetTime, MediaExtractor extractor, MediaCodec codec) throws IOException {
codec.flush();
extractor.seekTo(targetTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
if(extractor.getSampleTime() == targetTime) {
Log.d(TAG, "skip fastseek, already there");
return targetTime;
}
// 1. Queue first sample which should be the sync/I frame
skipToNextSample();
queueSampleToCodec(false);
// 2. Then, fast forward to target frame
/* 2.1 Search for the best candidate frame, which is the one whose
* right/positive/future distance is minimized
*/
extractor.seekTo(targetTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
/* Specifies how many frames we continue to check after the first candidate,
* to account for DTS picture reordering (this value is arbitrarily chosen) */
int maxFrameLookahead = 20;
long candidatePTS = 0;
long candidateDistance = Long.MAX_VALUE;
int lookaheadCount = 0;
while (extractor.advance() && lookaheadCount < maxFrameLookahead) {
long distance = targetTime - extractor.getSampleTime();
if (distance >= 0 && distance < candidateDistance) {
candidateDistance = distance;
candidatePTS = extractor.getSampleTime();
//Log.d(TAG, "candidate " + candidatePTS + " d=" + candidateDistance);
}
if (distance < 0) {
lookaheadCount++;
}
}
targetTime = candidatePTS; // set best candidate frame as exact seek target
// 2.2 Fast forward to chosen candidate frame
extractor.seekTo(targetTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
while (extractor.getSampleTime() != targetTime) {
extractor.advance();
}
Log.d(TAG, "exact fastseek match: " + extractor.getSampleTime());
return targetTime;
}