Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee9bde7b authored by Pawin Vongmasa's avatar Pawin Vongmasa
Browse files

GraphicBufferSource: Add timestamp snapping toggle

The timestamp snapping logic for the slow motion recording can now be
toggled on or off at run time with the property
"debug.stagefright.snap_timestamps". If the property is set to any
value other than 1, GraphicBufferSource will not snap timestamps in
the slow motion mode.

Test: atest CtsMediaTestCases -- \
--module-arg CtsMediaTestCases:size:small

Test: adb shell setprop debug.stagefright.snap_timestamps 0
- Then do slow motion recording.

Bug: 135030072
Change-Id: I959f8640a932cb7a7b8bcdc97b15f7affe4d24ef
parent 06088ce2
Loading
Loading
Loading
Loading
+30 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/FileDescriptor.h>

#include <android-base/properties.h>
#include <media/hardware/MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
@@ -800,6 +801,9 @@ void GraphicBufferSource::queueFrameRepeat_l() {
    }
}

#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
bool GraphicBufferSource::calculateCodecTimestamp_l(
        nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
    int64_t timeUs = bufferTimeNs / 1000;
@@ -816,14 +820,15 @@ bool GraphicBufferSource::calculateCodecTimestamp_l(
            mPrevFrameUs = mBaseFrameUs =
                    std::llround((timeUs * mCaptureFps) / mFps);
            mFrameCount = 0;
        } else {
            // snap to nearest capture point
        } else if (mSnapTimestamps) {
            double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000;
            if (nFrames < 0.5 - kTimestampFluctuation) {
                // skip this frame as it's too close to previous capture
                ALOGD("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
                ALOGD("skipping frame, timeUs %lld",
                      static_cast<long long>(timeUs));
                return false;
            }
            // snap to nearest capture point
            if (nFrames <= 1.0) {
                nFrames = 1.0;
            }
@@ -832,6 +837,22 @@ bool GraphicBufferSource::calculateCodecTimestamp_l(
                    mFrameCount * 1000000 / mCaptureFps);
            mPrevFrameUs = mBaseFrameUs + std::llround(
                    mFrameCount * 1000000 / mFps);
        } else {
            if (timeUs <= mPrevCaptureUs) {
                if (mFrameDropper != NULL && mFrameDropper->disabled()) {
                    // Warn only, client has disabled frame drop logic possibly for image
                    // encoding cases where camera's ZSL mode could send out of order frames.
                    ALOGW("Received frame that's going backward in time");
                } else {
                    // 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 false;
                }
            }
            mPrevCaptureUs = timeUs;
            mPrevFrameUs = mBaseFrameUs + std::llround(
                    (timeUs - mBaseCaptureUs) * (mCaptureFps / mFps));
        }

        ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
@@ -1359,6 +1380,12 @@ status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps)

    mFps = fps;
    mCaptureFps = captureFps;
    if (captureFps > fps) {
        mSnapTimestamps = 1 == base::GetIntProperty(
                "debug.stagefright.snap_timestamps", int64_t(1));
    } else {
        mSnapTimestamps = false;
    }

    return OK;
}
+26 −5
Original line number Diff line number Diff line
@@ -461,12 +461,33 @@ private:
    // Slow motion mode is enabled if both encoding and capture frame rates are
    // defined and the encoding frame rate is less than half the capture frame
    // rate. In this mode, the source is expected to produce frames with an even
    // timestamp interval (after rounding) with the configured capture fps. The
    // first source timestamp is used as the source base time. Afterwards, the
    // timestamp of each source frame is snapped to the nearest expected capture
    // timestamp and scaled to match the configured encoding frame rate.
    // timestamp interval (after rounding) with the configured capture fps.
    //
    // These modes must be configured by calling setTimeLapseConfig() before
    // using this source.
    //
    // Timestamp snapping for slow motion recording
    // ============================================
    //
    // When the slow motion mode is configured with setTimeLapseConfig(), the
    // property "debug.stagefright.snap_timestamps" will be checked. If the
    // value of the property is set to any value other than 1, mSnapTimestamps
    // will be set to false. Otherwise, mSnapTimestamps will be set to true.
    // (mSnapTimestamps will be false for time lapse recording regardless of the
    // value of the property.)
    //
    // If mSnapTimestamps is true, i.e., timestamp snapping is enabled, the
    // first source timestamp will be used as the source base time; afterwards,
    // the timestamp of each source frame will be snapped to the nearest
    // expected capture timestamp and scaled to match the configured encoding
    // frame rate.
    //
    // If timestamp snapping is disabled, the timestamp of source frames will
    // be scaled to match the ratio between the configured encoding frame rate
    // and the configured capture frame rate.

    // These modes must be enabled before using this source.
    // whether timestamps will be snapped
    bool mSnapTimestamps{true};

    // adjusted capture timestamp of the base frame
    int64_t mBaseCaptureUs;