diff options
author | Andreas Huber <andih@google.com> | 2010-07-20 15:04:28 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-07-21 08:51:29 -0700 |
commit | 6624c9fd0bc5e3858a22a04c05b5059445c1c367 (patch) | |
tree | 009c6806cadd4a6da28f3d497043b9665a16f134 /media/libstagefright/codecs | |
parent | d7514ec6eb17d262d6f9605a2c2f245b7ad7c0b9 (diff) | |
download | frameworks_base-6624c9fd0bc5e3858a22a04c05b5059445c1c367.zip frameworks_base-6624c9fd0bc5e3858a22a04c05b5059445c1c367.tar.gz frameworks_base-6624c9fd0bc5e3858a22a04c05b5059445c1c367.tar.bz2 |
Support finer seek control on MediaSources.
related-to-bug: 2858448
Change-Id: Ifb4b13b990fd5889113e47e2c62249ac43391fa1
Diffstat (limited to 'media/libstagefright/codecs')
11 files changed, 157 insertions, 22 deletions
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp index 8ae1135..c5b51c0 100644 --- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp +++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp @@ -159,7 +159,8 @@ status_t AACDecoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumSamplesOutput = 0; diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp index 2317de6..e8235c2 100644 --- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp +++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp @@ -202,7 +202,8 @@ status_t AACEncoder::read( *out = NULL; int64_t seekTimeUs; - CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); + ReadOptions::SeekMode mode; + CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp index 7728597..fb300da 100644 --- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp +++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp @@ -117,7 +117,8 @@ status_t AMRNBDecoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumSamplesOutput = 0; diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp index 4c02fe9..c875426 100644 --- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp +++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp @@ -145,7 +145,8 @@ status_t AMRNBEncoder::read( *out = NULL; int64_t seekTimeUs; - CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); + ReadOptions::SeekMode mode; + CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); while (mNumInputSamples < kNumSamplesPerFrame) { if (mInputBuffer == NULL) { diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp index c17c100..2a21472 100644 --- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp +++ b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp @@ -135,7 +135,8 @@ status_t AMRWBDecoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode seekMode; + if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { CHECK(seekTimeUs >= 0); mNumSamplesOutput = 0; diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp index 4257c6a..93304d0 100644 --- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp +++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp @@ -196,7 +196,8 @@ status_t AMRWBEncoder::read( *out = NULL; int64_t seekTimeUs; - CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); + ReadOptions::SeekMode mode; + CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); while (mNumInputSamples < kNumSamplesPerFrame) { if (mInputBuffer == NULL) { diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp index 24c361e..050e3da 100644 --- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp @@ -51,7 +51,9 @@ AVCDecoder::AVCDecoder(const sp<MediaSource> &source) mInputBuffer(NULL), mAnchorTimeUs(0), mNumSamplesOutput(0), - mPendingSeekTimeUs(-1) { + mPendingSeekTimeUs(-1), + mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC), + mTargetTimeUs(-1) { memset(mHandle, 0, sizeof(tagAVCHandle)); mHandle->AVCObject = NULL; mHandle->userData = this; @@ -161,6 +163,8 @@ status_t AVCDecoder::start(MetaData *) { mAnchorTimeUs = 0; mNumSamplesOutput = 0; mPendingSeekTimeUs = -1; + mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; + mTargetTimeUs = -1; mStarted = true; return OK; @@ -229,11 +233,13 @@ status_t AVCDecoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); CHECK(seekTimeUs >= 0); mPendingSeekTimeUs = seekTimeUs; + mPendingSeekMode = mode; if (mInputBuffer) { mInputBuffer->release(); @@ -246,6 +252,8 @@ status_t AVCDecoder::read( if (mInputBuffer == NULL) { LOGV("fetching new input buffer."); + bool seeking = false; + if (!mCodecSpecificData.isEmpty()) { mInputBuffer = mCodecSpecificData.editItemAt(0); mCodecSpecificData.removeAt(0); @@ -258,7 +266,9 @@ status_t AVCDecoder::read( ReadOptions seekOptions; if (mPendingSeekTimeUs >= 0) { - seekOptions.setSeekTo(mPendingSeekTimeUs); + seeking = true; + + seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode); mPendingSeekTimeUs = -1; } status_t err = mSource->read(&mInputBuffer, &seekOptions); @@ -276,6 +286,16 @@ status_t AVCDecoder::read( mInputBuffer = NULL; } } + + if (seeking) { + int64_t targetTimeUs; + if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) + && targetTimeUs >= 0) { + mTargetTimeUs = targetTimeUs; + } else { + mTargetTimeUs = -1; + } + } } const uint8_t *fragPtr; @@ -394,9 +414,35 @@ status_t AVCDecoder::read( CHECK(index >= 0); CHECK(index < (int32_t)mFrames.size()); - *out = mFrames.editItemAt(index); - (*out)->set_range(0, (*out)->size()); - (*out)->add_ref(); + MediaBuffer *mbuf = mFrames.editItemAt(index); + + bool skipFrame = false; + + if (mTargetTimeUs >= 0) { + int64_t timeUs; + CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); + CHECK(timeUs <= mTargetTimeUs); + + if (timeUs < mTargetTimeUs) { + // We're still waiting for the frame with the matching + // timestamp and we won't return the current one. + skipFrame = true; + + LOGV("skipping frame at %lld us", timeUs); + } else { + LOGV("found target frame at %lld us", timeUs); + + mTargetTimeUs = -1; + } + } + + if (!skipFrame) { + *out = mbuf; + (*out)->set_range(0, (*out)->size()); + (*out)->add_ref(); + } else { + *out = new MediaBuffer(0); + } // Do _not_ release input buffer yet. diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp index 8350f7a..0f08f6e 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp @@ -37,7 +37,8 @@ M4vH263Decoder::M4vH263Decoder(const sp<MediaSource> &source) mStarted(false), mHandle(new tagvideoDecControls), mInputBuffer(NULL), - mNumSamplesOutput(0) { + mNumSamplesOutput(0), + mTargetTimeUs(-1) { LOGV("M4vH263Decoder"); memset(mHandle, 0, sizeof(tagvideoDecControls)); @@ -146,6 +147,7 @@ status_t M4vH263Decoder::start(MetaData *) { mSource->start(); mNumSamplesOutput = 0; + mTargetTimeUs = -1; mStarted = true; return OK; @@ -175,8 +177,11 @@ status_t M4vH263Decoder::read( MediaBuffer **out, const ReadOptions *options) { *out = NULL; + bool seeking = false; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { + seeking = true; CHECK_EQ(PVResetVideoDecoder(mHandle), PV_TRUE); } @@ -186,6 +191,16 @@ status_t M4vH263Decoder::read( return err; } + if (seeking) { + int64_t targetTimeUs; + if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) + && targetTimeUs >= 0) { + mTargetTimeUs = targetTimeUs; + } else { + mTargetTimeUs = -1; + } + } + uint8_t *bitstream = (uint8_t *) inputBuffer->data() + inputBuffer->range_offset(); @@ -221,17 +236,40 @@ status_t M4vH263Decoder::read( return INFO_FORMAT_CHANGED; } - *out = mFrames[mNumSamplesOutput & 0x01]; - (*out)->add_ref(); - int64_t timeUs; CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); - (*out)->meta_data()->setInt64(kKeyTime, timeUs); - ++mNumSamplesOutput; inputBuffer->release(); inputBuffer = NULL; + bool skipFrame = false; + + if (mTargetTimeUs >= 0) { + CHECK(timeUs <= mTargetTimeUs); + + if (timeUs < mTargetTimeUs) { + // We're still waiting for the frame with the matching + // timestamp and we won't return the current one. + skipFrame = true; + + LOGV("skipping frame at %lld us", timeUs); + } else { + LOGV("found target frame at %lld us", timeUs); + + mTargetTimeUs = -1; + } + } + + if (skipFrame) { + *out = new MediaBuffer(0); + } else { + *out = mFrames[mNumSamplesOutput & 0x01]; + (*out)->add_ref(); + (*out)->meta_data()->setInt64(kKeyTime, timeUs); + } + + ++mNumSamplesOutput; + return OK; } diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp index f40bd11..c4a8280 100644 --- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp @@ -122,7 +122,8 @@ status_t MP3Decoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumFramesOutput = 0; diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp index bad8956..fbc97f4 100644 --- a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp +++ b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp @@ -39,7 +39,8 @@ VPXDecoder::VPXDecoder(const sp<MediaSource> &source) mStarted(false), mBufferSize(0), mCtx(NULL), - mBufferGroup(NULL) { + mBufferGroup(NULL), + mTargetTimeUs(-1) { sp<MetaData> inputFormat = source->getFormat(); const char *mime; CHECK(inputFormat->findCString(kKeyMIMEType, &mime)); @@ -94,6 +95,8 @@ status_t VPXDecoder::start(MetaData *) { mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); + mTargetTimeUs = -1; + mStarted = true; return OK; @@ -126,6 +129,13 @@ status_t VPXDecoder::read( MediaBuffer **out, const ReadOptions *options) { *out = NULL; + bool seeking = false; + int64_t seekTimeUs; + ReadOptions::SeekMode seekMode; + if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { + seeking = true; + } + MediaBuffer *input; status_t err = mSource->read(&input, options); @@ -135,6 +145,16 @@ status_t VPXDecoder::read( LOGV("read %d bytes from source\n", input->range_length()); + if (seeking) { + int64_t targetTimeUs; + if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) + && targetTimeUs >= 0) { + mTargetTimeUs = targetTimeUs; + } else { + mTargetTimeUs = -1; + } + } + if (vpx_codec_decode( (vpx_codec_ctx_t *)mCtx, (uint8_t *)input->data() + input->range_offset(), @@ -156,6 +176,29 @@ status_t VPXDecoder::read( input->release(); input = NULL; + bool skipFrame = false; + + if (mTargetTimeUs >= 0) { + CHECK(timeUs <= mTargetTimeUs); + + if (timeUs < mTargetTimeUs) { + // We're still waiting for the frame with the matching + // timestamp and we won't return the current one. + skipFrame = true; + + LOGV("skipping frame at %lld us", timeUs); + } else { + LOGV("found target frame at %lld us", timeUs); + + mTargetTimeUs = -1; + } + } + + if (skipFrame) { + *out = new MediaBuffer(0); + return OK; + } + vpx_codec_iter_t iter = NULL; vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp index df3f16a..53f0638 100644 --- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp +++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp @@ -200,7 +200,8 @@ status_t VorbisDecoder::read( *out = NULL; int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumFramesOutput = 0; |