Loading include/media/IOMX.h +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ public: INTERNAL_OPTION_START_TIME, // data is an int64_t INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2] INTERNAL_OPTION_COLOR_ASPECTS, // data is ColorAspects INTERNAL_OPTION_TIME_OFFSET, // data is an int64_t }; virtual status_t setInternalOption( node_id node, Loading include/media/stagefright/MediaCodecSource.h +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ struct MediaCodecSource : public MediaSource, bool isVideo() const { return mIsVideo; } sp<IGraphicBufferProducer> getGraphicBufferProducer(); void setInputBufferTimeOffset(int64_t timeOffsetUs); status_t setInputBufferTimeOffset(int64_t timeOffsetUs); int64_t getFirstSampleSystemTimeUs(); // MediaSource Loading media/libstagefright/ACodec.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -7473,6 +7473,23 @@ status_t ACodec::setParameters(const sp<AMessage> ¶ms) { } } int64_t timeOffsetUs; if (params->findInt64("time-offset-us", &timeOffsetUs)) { status_t err = mOMX->setInternalOption( mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_TIME_OFFSET, &timeOffsetUs, sizeof(timeOffsetUs)); if (err != OK) { ALOGE("[%s] Unable to set input buffer time offset (err %d)", mComponentName.c_str(), err); return err; } } int64_t skipFramesBeforeUs; if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { status_t err = Loading media/libstagefright/MediaCodecSource.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -336,10 +336,10 @@ sp<MediaCodecSource> MediaCodecSource::Create( return NULL; } void MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { status_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector); msg->setInt64("time-offset-us", timeOffsetUs); postSynchronouslyAndReturnError(msg); return postSynchronouslyAndReturnError(msg); } int64_t MediaCodecSource::getFirstSampleSystemTimeUs() { Loading Loading @@ -874,9 +874,7 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { break; } } // Time offset is not applied at // feedEncoderInputBuffer() in surface input case. timeUs += mInputBufferTimeOffsetUs; // Timestamp offset is already adjusted in GraphicBufferSource. // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); Loading Loading @@ -1015,10 +1013,18 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { { sp<AReplyToken> replyID; CHECK(msg->senderAwaitsResponse(&replyID)); status_t err = OK; CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs)); // Propagate the timestamp offset to GraphicBufferSource. if (mIsVideo) { sp<AMessage> params = new AMessage; params->setInt64("time-offset-us", mInputBufferTimeOffsetUs); err = mEncoder->setParameters(params); } sp<AMessage> response = new AMessage; response->setInt32("err", err); response->postReply(replyID); break; } Loading media/libstagefright/omx/GraphicBufferSource.cpp +40 −23 Original line number Diff line number Diff line Loading @@ -145,7 +145,8 @@ GraphicBufferSource::GraphicBufferSource( mTimePerCaptureUs(-1ll), mTimePerFrameUs(-1ll), mPrevCaptureUs(-1ll), mPrevFrameUs(-1ll) { mPrevFrameUs(-1ll), mInputBufferTimeOffsetUs(0ll) { ALOGV("GraphicBufferSource w=%u h=%u c=%u", bufferWidth, bufferHeight, bufferCount); Loading Loading @@ -774,6 +775,7 @@ status_t GraphicBufferSource::signalEndOfInputStream() { int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { int64_t timeUs = item.mTimestamp / 1000; timeUs += mInputBufferTimeOffsetUs; if (mTimePerCaptureUs > 0ll && (mTimePerCaptureUs > 2 * mTimePerFrameUs Loading Loading @@ -802,7 +804,16 @@ int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { static_cast<long long>(mPrevFrameUs)); return mPrevFrameUs; } else if (mMaxTimestampGapUs > 0ll) { } else { int64_t originalTimeUs = timeUs; if (originalTimeUs <= mPrevOriginalTimeUs) { // Drop the frame if it's going backward in time. Bad timestamp // could disrupt encoder's rate control completely. ALOGW("Dropping frame that's going backward in time"); return -1; } if (mMaxTimestampGapUs > 0ll) { //TODO: Fix the case when mMaxTimestampGapUs and mTimePerCaptureUs are both set. /* Cap timestamp gap between adjacent frames to specified max Loading @@ -812,26 +823,20 @@ int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { * where encoder's rate control logic produces huge frames after a * long period of suspension. */ int64_t originalTimeUs = timeUs; if (mPrevOriginalTimeUs >= 0ll) { if (originalTimeUs < mPrevOriginalTimeUs) { // Drop the frame if it's going backward in time. Bad timestamp // could disrupt encoder's rate control completely. ALOGW("Dropping frame that's going backward in time"); return -1; } int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs; timeUs = (timestampGapUs < mMaxTimestampGapUs ? timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs; } mPrevOriginalTimeUs = originalTimeUs; mPrevModifiedTimeUs = timeUs; mOriginalTimeUs.add(timeUs, originalTimeUs); ALOGV("IN timestamp: %lld -> %lld", static_cast<long long>(originalTimeUs), static_cast<long long>(timeUs)); } } mPrevOriginalTimeUs = originalTimeUs; mPrevModifiedTimeUs = timeUs; } return timeUs; } Loading Loading @@ -1048,6 +1053,18 @@ status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) { return OK; } status_t GraphicBufferSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { Mutex::Autolock autoLock(mMutex); // timeOffsetUs must be negative for adjustment. if (timeOffsetUs >= 0ll) { return INVALID_OPERATION; } mInputBufferTimeOffsetUs = timeOffsetUs; return OK; } status_t GraphicBufferSource::setMaxFps(float maxFps) { Mutex::Autolock autoLock(mMutex); Loading Loading
include/media/IOMX.h +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ public: INTERNAL_OPTION_START_TIME, // data is an int64_t INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2] INTERNAL_OPTION_COLOR_ASPECTS, // data is ColorAspects INTERNAL_OPTION_TIME_OFFSET, // data is an int64_t }; virtual status_t setInternalOption( node_id node, Loading
include/media/stagefright/MediaCodecSource.h +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ struct MediaCodecSource : public MediaSource, bool isVideo() const { return mIsVideo; } sp<IGraphicBufferProducer> getGraphicBufferProducer(); void setInputBufferTimeOffset(int64_t timeOffsetUs); status_t setInputBufferTimeOffset(int64_t timeOffsetUs); int64_t getFirstSampleSystemTimeUs(); // MediaSource Loading
media/libstagefright/ACodec.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -7473,6 +7473,23 @@ status_t ACodec::setParameters(const sp<AMessage> ¶ms) { } } int64_t timeOffsetUs; if (params->findInt64("time-offset-us", &timeOffsetUs)) { status_t err = mOMX->setInternalOption( mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_TIME_OFFSET, &timeOffsetUs, sizeof(timeOffsetUs)); if (err != OK) { ALOGE("[%s] Unable to set input buffer time offset (err %d)", mComponentName.c_str(), err); return err; } } int64_t skipFramesBeforeUs; if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { status_t err = Loading
media/libstagefright/MediaCodecSource.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -336,10 +336,10 @@ sp<MediaCodecSource> MediaCodecSource::Create( return NULL; } void MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { status_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector); msg->setInt64("time-offset-us", timeOffsetUs); postSynchronouslyAndReturnError(msg); return postSynchronouslyAndReturnError(msg); } int64_t MediaCodecSource::getFirstSampleSystemTimeUs() { Loading Loading @@ -874,9 +874,7 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { break; } } // Time offset is not applied at // feedEncoderInputBuffer() in surface input case. timeUs += mInputBufferTimeOffsetUs; // Timestamp offset is already adjusted in GraphicBufferSource. // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); Loading Loading @@ -1015,10 +1013,18 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { { sp<AReplyToken> replyID; CHECK(msg->senderAwaitsResponse(&replyID)); status_t err = OK; CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs)); // Propagate the timestamp offset to GraphicBufferSource. if (mIsVideo) { sp<AMessage> params = new AMessage; params->setInt64("time-offset-us", mInputBufferTimeOffsetUs); err = mEncoder->setParameters(params); } sp<AMessage> response = new AMessage; response->setInt32("err", err); response->postReply(replyID); break; } Loading
media/libstagefright/omx/GraphicBufferSource.cpp +40 −23 Original line number Diff line number Diff line Loading @@ -145,7 +145,8 @@ GraphicBufferSource::GraphicBufferSource( mTimePerCaptureUs(-1ll), mTimePerFrameUs(-1ll), mPrevCaptureUs(-1ll), mPrevFrameUs(-1ll) { mPrevFrameUs(-1ll), mInputBufferTimeOffsetUs(0ll) { ALOGV("GraphicBufferSource w=%u h=%u c=%u", bufferWidth, bufferHeight, bufferCount); Loading Loading @@ -774,6 +775,7 @@ status_t GraphicBufferSource::signalEndOfInputStream() { int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { int64_t timeUs = item.mTimestamp / 1000; timeUs += mInputBufferTimeOffsetUs; if (mTimePerCaptureUs > 0ll && (mTimePerCaptureUs > 2 * mTimePerFrameUs Loading Loading @@ -802,7 +804,16 @@ int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { static_cast<long long>(mPrevFrameUs)); return mPrevFrameUs; } else if (mMaxTimestampGapUs > 0ll) { } else { int64_t originalTimeUs = timeUs; if (originalTimeUs <= mPrevOriginalTimeUs) { // Drop the frame if it's going backward in time. Bad timestamp // could disrupt encoder's rate control completely. ALOGW("Dropping frame that's going backward in time"); return -1; } if (mMaxTimestampGapUs > 0ll) { //TODO: Fix the case when mMaxTimestampGapUs and mTimePerCaptureUs are both set. /* Cap timestamp gap between adjacent frames to specified max Loading @@ -812,26 +823,20 @@ int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { * where encoder's rate control logic produces huge frames after a * long period of suspension. */ int64_t originalTimeUs = timeUs; if (mPrevOriginalTimeUs >= 0ll) { if (originalTimeUs < mPrevOriginalTimeUs) { // Drop the frame if it's going backward in time. Bad timestamp // could disrupt encoder's rate control completely. ALOGW("Dropping frame that's going backward in time"); return -1; } int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs; timeUs = (timestampGapUs < mMaxTimestampGapUs ? timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs; } mPrevOriginalTimeUs = originalTimeUs; mPrevModifiedTimeUs = timeUs; mOriginalTimeUs.add(timeUs, originalTimeUs); ALOGV("IN timestamp: %lld -> %lld", static_cast<long long>(originalTimeUs), static_cast<long long>(timeUs)); } } mPrevOriginalTimeUs = originalTimeUs; mPrevModifiedTimeUs = timeUs; } return timeUs; } Loading Loading @@ -1048,6 +1053,18 @@ status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) { return OK; } status_t GraphicBufferSource::setInputBufferTimeOffset(int64_t timeOffsetUs) { Mutex::Autolock autoLock(mMutex); // timeOffsetUs must be negative for adjustment. if (timeOffsetUs >= 0ll) { return INVALID_OPERATION; } mInputBufferTimeOffsetUs = timeOffsetUs; return OK; } status_t GraphicBufferSource::setMaxFps(float maxFps) { Mutex::Autolock autoLock(mMutex); Loading