1c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia/*
2c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * Copyright 2015 The Android Open Source Project
3c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia *
4c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * Licensed under the Apache License, Version 2.0 (the "License");
5c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * you may not use this file except in compliance with the License.
6c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * You may obtain a copy of the License at
7c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia *
8c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia *      http://www.apache.org/licenses/LICENSE-2.0
9c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia *
10c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * Unless required by applicable law or agreed to in writing, software
11c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * distributed under the License is distributed on an "AS IS" BASIS,
12c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * See the License for the specific language governing permissions and
14c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia * limitations under the License.
15c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia */
16c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
17c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia//#define LOG_NDEBUG 0
18c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#define LOG_TAG "MediaSync"
19c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <inttypes.h>
20c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
21c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <gui/BufferQueue.h>
22c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <gui/IGraphicBufferConsumer.h>
23c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <gui/IGraphicBufferProducer.h>
24c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
25c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/AudioTrack.h>
26c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/stagefright/MediaClock.h>
27c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/stagefright/MediaSync.h>
28a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar#include <media/stagefright/VideoFrameScheduler.h>
29c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/stagefright/foundation/ADebug.h>
30c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/stagefright/foundation/ALooper.h>
31c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <media/stagefright/foundation/AMessage.h>
32c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
33c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia#include <ui/GraphicBuffer.h>
34c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
35c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia// Maximum late time allowed for a video frame to be rendered. When a video
36c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia// frame arrives later than this number, it will be discarded without rendering.
37c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiastatic const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
38c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
39c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jianamespace android {
40c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
41c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia// static
42c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiasp<MediaSync> MediaSync::create() {
43c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<MediaSync> sync = new MediaSync();
44c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sync->mLooper->registerHandler(sync);
45c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return sync;
46c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
47c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
48c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei JiaMediaSync::MediaSync()
49c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia      : mIsAbandoned(false),
50c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mMutex(),
51c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mReleaseCondition(),
52c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mNumOutstandingBuffers(0),
53b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mUsageFlagsFromOutput(0),
54a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        mMaxAcquiredBufferCount(1),
5508dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        mReturnPendingInputFrame(false),
56c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mNativeSampleRateInHz(0),
57c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mNumFramesWritten(0),
58c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mHasAudio(false),
59c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mNextBufferItemMediaUs(-1),
60c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mPlaybackRate(0.0) {
61c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mMediaClock = new MediaClock;
62c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // initialize settings
643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = AUDIO_PLAYBACK_RATE_DEFAULT;
653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings.mSpeed = mPlaybackRate;
663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
67c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mLooper = new ALooper;
68c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mLooper->setName("MediaSync");
69c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
70c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
71c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
72c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei JiaMediaSync::~MediaSync() {
73c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mInput != NULL) {
74c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mInput->consumerDisconnect();
75c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
76c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mOutput != NULL) {
77c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
78c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
79c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
80c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mLooper != NULL) {
81c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mLooper->unregisterHandler(id());
82c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mLooper->stop();
83c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
84c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
85c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
86ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jiastatus_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
87c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
88c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
89b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    if (output == mOutput) {
90b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        return NO_ERROR;  // same output surface.
91c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
92c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
94ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jia        ALOGE("setSurface: output surface is used as sync source and cannot be removed.");
953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return INVALID_OPERATION;
963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
98c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (output != NULL) {
99b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        int newUsage = 0;
100b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        output->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &newUsage);
101b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
102b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        // Check usage flags only when current output surface has been used to create input surface.
103b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        if (mOutput != NULL && mInput != NULL) {
104b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER
105b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia                    | GRALLOC_USAGE_EXTERNAL_DISP);
106b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            // New output surface is not allowed to add new usage flag except ignored ones.
107b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            if ((newUsage & ~(mUsageFlagsFromOutput | ignoredFlags)) != 0) {
108b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia                ALOGE("setSurface: new output surface has new usage flag not used by current one.");
109b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia                return BAD_VALUE;
110b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            }
111b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        }
112b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
113b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        // Try to connect to new output surface. If failed, current output surface will not
114b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        // be changed.
115c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
116b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        sp<OutputListener> listener(new OutputListener(this, output));
117c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        IInterface::asBinder(output)->linkToDeath(listener);
118c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        status_t status =
119c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            output->connect(listener,
120c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                            NATIVE_WINDOW_API_MEDIA,
121c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                            true /* producerControlledByApp */,
122c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                            &queueBufferOutput);
123c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (status != NO_ERROR) {
124ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jia            ALOGE("setSurface: failed to connect (%d)", status);
125c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            return status;
126c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
127a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
128a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        if (mFrameScheduler == NULL) {
129a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            mFrameScheduler = new VideoFrameScheduler();
130a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            mFrameScheduler->init();
131a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        }
132b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    }
133c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
134b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    if (mOutput != NULL) {
135b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
136b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        while (!mBuffersSentToOutput.isEmpty()) {
137b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            returnBufferToInput_l(mBuffersSentToOutput.valueAt(0), Fence::NO_FENCE);
138b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia            mBuffersSentToOutput.removeItemsAt(0);
139b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        }
140c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
141c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
142b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    mOutput = output;
143b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
144c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return NO_ERROR;
145c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
146c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
147c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia// |audioTrack| is used only for querying information.
148ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jiastatus_t MediaSync::setAudioTrack(const sp<AudioTrack> &audioTrack) {
149c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
150c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
151c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // TODO: support audio track change.
152c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mAudioTrack != NULL) {
153ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jia        ALOGE("setAudioTrack: audioTrack has already been configured.");
154c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return INVALID_OPERATION;
155c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
156c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
1573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (audioTrack == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_AUDIO) {
158ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jia        ALOGE("setAudioTrack: audioTrack is used as sync source and cannot be removed.");
1593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return INVALID_OPERATION;
1609767a47dcf9bbe090045ab99e0290d73289c704fWei Jia    }
1619767a47dcf9bbe090045ab99e0290d73289c704fWei Jia
1623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (audioTrack != NULL) {
1633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // check if audio track supports the playback settings
1643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (mPlaybackSettings.mSpeed != 0.f
1653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                && audioTrack->setPlaybackRate(mPlaybackSettings) != OK) {
1663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGE("playback settings are not supported by the audio track");
1673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return INVALID_OPERATION;
1683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        uint32_t nativeSampleRateInHz = audioTrack->getOriginalSampleRate();
1703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (nativeSampleRateInHz <= 0) {
171ce8c218ec9db7acd86f9f8929f8bbb668151b53dWei Jia            ALOGE("setAudioTrack: native sample rate should be positive.");
1723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return BAD_VALUE;
1733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mAudioTrack = audioTrack;
1753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mNativeSampleRateInHz = nativeSampleRateInHz;
1763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        (void)setPlaybackSettings_l(mPlaybackSettings);
1773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    else {
1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mAudioTrack = NULL;
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mNativeSampleRateInHz = 0;
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
182c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // potentially resync to new source
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    resync_l();
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
186c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
187c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
188c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiastatus_t MediaSync::createInputSurface(
189c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        sp<IGraphicBufferProducer> *outBufferProducer) {
190c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (outBufferProducer == NULL) {
191c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return BAD_VALUE;
192c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
193c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
194c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
195c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
196c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mOutput == NULL) {
197c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return NO_INIT;
198c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
199c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
200c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mInput != NULL) {
201c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return INVALID_OPERATION;
202c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
203c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
204c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<IGraphicBufferProducer> bufferProducer;
205c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<IGraphicBufferConsumer> bufferConsumer;
206c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    BufferQueue::createBufferQueue(&bufferProducer, &bufferConsumer);
207c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
208c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<InputListener> listener(new InputListener(this));
209c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    IInterface::asBinder(bufferConsumer)->linkToDeath(listener);
210c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    status_t status =
211c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        bufferConsumer->consumerConnect(listener, false /* controlledByApp */);
212c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status == NO_ERROR) {
213c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        bufferConsumer->setConsumerName(String8("MediaSync"));
2149b73fa9a02b7234b43ac2be66a3328ff36d39c2dLajos Molnar        // propagate usage bits from output surface
215b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mUsageFlagsFromOutput = 0;
216b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mUsageFlagsFromOutput);
217b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        bufferConsumer->setConsumerUsageBits(mUsageFlagsFromOutput);
218c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        *outBufferProducer = bufferProducer;
219c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mInput = bufferConsumer;
220a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
221a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        // set undequeued buffer count
222a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        int minUndequeuedBuffers;
223a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        mOutput->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
224a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        mMaxAcquiredBufferCount = minUndequeuedBuffers;
225a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        bufferConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount);
226c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
227c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return status;
228c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
229c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarvoid MediaSync::resync_l() {
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    AVSyncSource src = mSyncSettings.mSource;
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (src == AVSYNC_SOURCE_DEFAULT) {
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (mAudioTrack != NULL) {
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            src = AVSYNC_SOURCE_AUDIO;
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        } else {
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            src = AVSYNC_SOURCE_SYSTEM_CLOCK;
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
238c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
239c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: resync ourselves to the current clock (e.g. on sync source change)
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    updatePlaybackRate_l(mPlaybackRate);
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
243c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarvoid MediaSync::updatePlaybackRate_l(float rate) {
245c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (rate > mPlaybackRate) {
246c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mNextBufferItemMediaUs = -1;
247c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
248c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mPlaybackRate = rate;
24908dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    // TODO: update frame scheduler with this info
250c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mMediaClock->setPlaybackRate(rate);
251c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    onDrainVideo_l();
252c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
253c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
254c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiasp<const MediaClock> MediaSync::getMediaClock() {
255c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return mMediaClock;
256c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
257c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
25899d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jiastatus_t MediaSync::getPlayTimeForPendingAudioFrames(int64_t *outTimeUs) {
25999d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    Mutex::Autolock lock(mMutex);
26099d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    // User should check the playback rate if it doesn't want to receive a
26199d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    // huge number for play time.
26299d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    if (mPlaybackRate == 0.0f) {
26399d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        *outTimeUs = INT64_MAX;
26499d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        return OK;
26599d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    }
26699d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia
26799d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    uint32_t numFramesPlayed = 0;
26899d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    if (mAudioTrack != NULL) {
26999d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        status_t res = mAudioTrack->getPosition(&numFramesPlayed);
27099d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        if (res != OK) {
27199d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia            return res;
27299d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        }
27399d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    }
27499d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia
27599d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    int64_t numPendingFrames = mNumFramesWritten - numFramesPlayed;
27699d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    if (numPendingFrames < 0) {
27799d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        numPendingFrames = 0;
27899d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        ALOGW("getPlayTimeForPendingAudioFrames: pending frame count is negative.");
27999d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    }
28099d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    double timeUs = numPendingFrames * 1000000.0
28199d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia            / (mNativeSampleRateInHz * (double)mPlaybackRate);
28299d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    if (timeUs > (double)INT64_MAX) {
28399d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        // Overflow.
28499d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        *outTimeUs = INT64_MAX;
28599d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        ALOGW("getPlayTimeForPendingAudioFrames: play time for pending audio frames "
28699d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia              "is too high, possibly due to super low playback rate(%f)", mPlaybackRate);
28799d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    } else {
28899d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia        *outTimeUs = (int64_t)timeUs;
28999d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    }
29099d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia
29199d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia    return OK;
29299d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia}
29399d1f78c9b16b5668e78c353373e0e7f4592cab9Wei Jia
294c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiastatus_t MediaSync::updateQueuedAudioData(
295c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        size_t sizeInBytes, int64_t presentationTimeUs) {
296c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (sizeInBytes == 0) {
297c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return OK;
298c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
299c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
300c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
301c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
302c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mAudioTrack == NULL) {
303c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGW("updateQueuedAudioData: audioTrack has NOT been configured.");
304c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return INVALID_OPERATION;
305c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
306c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
307c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t numFrames = sizeInBytes / mAudioTrack->frameSize();
308c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t maxMediaTimeUs = presentationTimeUs
309c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            + getDurationIfPlayedAtNativeSampleRate_l(numFrames);
310c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
311c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t nowUs = ALooper::GetNowUs();
31280243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    int64_t nowMediaUs = presentationTimeUs
313c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            - getDurationIfPlayedAtNativeSampleRate_l(mNumFramesWritten)
314c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            + getPlayedOutAudioDurationMedia_l(nowUs);
315c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
31680243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    mNumFramesWritten += numFrames;
31780243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia
318c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t oldRealTime = -1;
319c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mNextBufferItemMediaUs != -1) {
320c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        oldRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
321c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
322c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
323c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mMediaClock->updateAnchor(nowMediaUs, nowUs, maxMediaTimeUs);
324c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mHasAudio = true;
325c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
326c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (oldRealTime != -1) {
327c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        int64_t newRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
32880243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia        if (newRealTime >= oldRealTime) {
32980243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia            return OK;
330c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
331c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
332c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
33380243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    mNextBufferItemMediaUs = -1;
33480243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    onDrainVideo_l();
335c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return OK;
336c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
337c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
338c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::setName(const AString &name) {
339c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
340c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mInput->setConsumerName(String8(name.c_str()));
341c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
342c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
34308dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnarvoid MediaSync::flush() {
34408dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    Mutex::Autolock lock(mMutex);
34508dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    if (mFrameScheduler != NULL) {
34608dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        mFrameScheduler->restart();
34708dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    }
34808dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    while (!mBufferItems.empty()) {
34908dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        BufferItem *bufferItem = &*mBufferItems.begin();
35008dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        returnBufferToInput_l(bufferItem->mGraphicBuffer, bufferItem->mFence);
35108dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        mBufferItems.erase(mBufferItems.begin());
35208dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    }
35308dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mNextBufferItemMediaUs = -1;
35408dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mNumFramesWritten = 0;
35508dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mReturnPendingInputFrame = true;
35608dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mReleaseCondition.signal();
35708dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mMediaClock->clearAnchor();
35808dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar}
35908dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar
3603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t MediaSync::setVideoFrameRateHint(float rate) {
361a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    Mutex::Autolock lock(mMutex);
362a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    if (rate < 0.f) {
363a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        return BAD_VALUE;
364a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    }
365a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    if (mFrameScheduler != NULL) {
366a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        mFrameScheduler->init(rate);
367a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    }
368a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    return OK;
3693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
3703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
3713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarfloat MediaSync::getVideoFrameRate() {
372a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    Mutex::Autolock lock(mMutex);
373a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    if (mFrameScheduler != NULL) {
374a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        float fps = mFrameScheduler->getFrameRate();
375a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        if (fps > 0.f) {
376a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            return fps;
377a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        }
378a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    }
379a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
380a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    // we don't have or know the frame rate
3813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return -1.f;
3823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
3833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
3843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t MediaSync::setSyncSettings(const AVSyncSettings &syncSettings) {
3853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // validate settings
3863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (syncSettings.mSource >= AVSYNC_SOURCE_MAX
3873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            || syncSettings.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
3883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            || syncSettings.mTolerance < 0.f
3893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            || syncSettings.mTolerance >= AVSYNC_TOLERANCE_MAX) {
3903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
3913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
3923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
3933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    Mutex::Autolock lock(mMutex);
3943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
3953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // verify that we have the sync source
3963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    switch (syncSettings.mSource) {
3973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case AVSYNC_SOURCE_AUDIO:
3983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mAudioTrack == NULL) {
3993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGE("setSyncSettings: audio sync source requires an audio track");
4003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                return BAD_VALUE;
4013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
4023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
4033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case AVSYNC_SOURCE_VSYNC:
4043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mOutput == NULL) {
4053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGE("setSyncSettings: vsync sync source requires an output surface");
4063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                return BAD_VALUE;
4073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
4083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
4093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        default:
4103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
4113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
4123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mSyncSettings = syncSettings;
4143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    resync_l();
4153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
4163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
4173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarvoid MediaSync::getSyncSettings(AVSyncSettings *syncSettings) {
4193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    Mutex::Autolock lock(mMutex);
4203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *syncSettings = mSyncSettings;
4213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
4223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t MediaSync::setPlaybackSettings(const AudioPlaybackRate &rate) {
4243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    Mutex::Autolock lock(mMutex);
4253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = setPlaybackSettings_l(rate);
4273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK) {
4283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // TODO: adjust rate if using VSYNC as source
4293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        updatePlaybackRate_l(rate.mSpeed);
4303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
4313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
4323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
4333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t MediaSync::setPlaybackSettings_l(const AudioPlaybackRate &rate) {
4353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
4363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // We don't validate other audio settings.
4373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // They will be validated when/if audiotrack is set.
4383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
4393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
4403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (mAudioTrack != NULL) {
4423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (rate.mSpeed == 0.f) {
4433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioTrack->pause();
4443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        } else {
4453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = mAudioTrack->setPlaybackRate(rate);
4463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err != OK) {
4473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                return BAD_VALUE;
4483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
4493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // ignore errors
4513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            (void)mAudioTrack->start();
4523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
4533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
4543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
4553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
4563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
4573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
4583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarvoid MediaSync::getPlaybackSettings(AudioPlaybackRate *rate) {
4593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    Mutex::Autolock lock(mMutex);
4603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
4613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
4623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
463c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiaint64_t MediaSync::getRealTime(int64_t mediaTimeUs, int64_t nowUs) {
464c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t realUs;
465c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
466c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // If failed to get current position, e.g. due to audio clock is
467c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // not ready, then just play out video immediately without delay.
468c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return nowUs;
469c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
470c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return realUs;
471c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
472c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
473c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiaint64_t MediaSync::getDurationIfPlayedAtNativeSampleRate_l(int64_t numFrames) {
474c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return (numFrames * 1000000LL / mNativeSampleRateInHz);
475c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
476c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
477c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiaint64_t MediaSync::getPlayedOutAudioDurationMedia_l(int64_t nowUs) {
478c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    CHECK(mAudioTrack != NULL);
479c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
480c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    uint32_t numFramesPlayed;
481c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t numFramesPlayedAt;
482c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    AudioTimestamp ts;
483c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    static const int64_t kStaleTimestamp100ms = 100000;
484c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
485c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    status_t res = mAudioTrack->getTimestamp(ts);
486c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (res == OK) {
487c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // case 1: mixing audio tracks.
488c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayed = ts.mPosition;
489c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayedAt =
490c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
491c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        const int64_t timestampAge = nowUs - numFramesPlayedAt;
492c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (timestampAge > kStaleTimestamp100ms) {
493c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // This is an audio FIXME.
494c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // getTimestamp returns a timestamp which may come from audio
495c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // mixing threads. After pausing, the MixerThread may go idle,
496c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // thus the mTime estimate may become stale. Assuming that the
497c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // MixerThread runs 20ms, with FastMixer at 5ms, the max latency
498c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // should be about 25ms with an average around 12ms (to be
499c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // verified). For safety we use 100ms.
500c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) "
501c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                  "numFramesPlayedAt(%lld)",
502c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                  (long long)nowUs, (long long)numFramesPlayedAt);
503c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
504c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
505c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //ALOGD("getTimestamp: OK %d %lld",
506c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //      numFramesPlayed, (long long)numFramesPlayedAt);
507c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    } else if (res == WOULD_BLOCK) {
508c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // case 2: transitory state on start of a new track
509c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayed = 0;
510c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayedAt = nowUs;
511c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
512c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //      numFramesPlayed, (long long)numFramesPlayedAt);
513c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    } else {
514c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // case 3: transitory at new track or audio fast tracks.
515c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        res = mAudioTrack->getPosition(&numFramesPlayed);
516c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        CHECK_EQ(res, (status_t)OK);
517c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayedAt = nowUs;
518c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        numFramesPlayedAt += 1000LL * mAudioTrack->latency() / 2; /* XXX */
519a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        //ALOGD("getPosition: %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
520c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
521c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
522c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    //can't be negative until 12.4 hrs, test.
523c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    //CHECK_EQ(numFramesPlayed & (1 << 31), 0);
524c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int64_t durationUs =
525c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        getDurationIfPlayedAtNativeSampleRate_l(numFramesPlayed)
526c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            + nowUs - numFramesPlayedAt;
527c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (durationUs < 0) {
528c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // Occurs when numFramesPlayed position is very small and the following:
529c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // (1) In case 1, the time nowUs is computed before getTimestamp() is
530c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //     called and numFramesPlayedAt is greater than nowUs by time more
531c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //     than numFramesPlayed.
532c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // (2) In case 3, using getPosition and adding mAudioTrack->latency()
533c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //     to numFramesPlayedAt, by a time amount greater than
534c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //     numFramesPlayed.
535c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        //
536c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // Both of these are transitory conditions.
537c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGV("getPlayedOutAudioDurationMedia_l: negative duration %lld "
538c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia              "set to zero", (long long)durationUs);
539c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        durationUs = 0;
540c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
541c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGV("getPlayedOutAudioDurationMedia_l(%lld) nowUs(%lld) frames(%u) "
542c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia          "framesAt(%lld)",
543c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia          (long long)durationUs, (long long)nowUs, numFramesPlayed,
544c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia          (long long)numFramesPlayedAt);
545c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    return durationUs;
546c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
547c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
548c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::onDrainVideo_l() {
549c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (!isPlaying()) {
550c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return;
551c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
552c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
553c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    while (!mBufferItems.empty()) {
55480243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia        int64_t nowUs = ALooper::GetNowUs();
555c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        BufferItem *bufferItem = &*mBufferItems.begin();
556c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        int64_t itemMediaUs = bufferItem->mTimestamp / 1000;
557c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        int64_t itemRealUs = getRealTime(itemMediaUs, nowUs);
55880243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia
559a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        // adjust video frame PTS based on vsync
560a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        itemRealUs = mFrameScheduler->schedule(itemRealUs * 1000) / 1000;
56182a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        int64_t twoVsyncsUs = 2 * (mFrameScheduler->getVsyncPeriod() / 1000);
562a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
563a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        // post 2 display refreshes before rendering is due
564a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        if (itemRealUs <= nowUs + twoVsyncsUs) {
565a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            ALOGV("adjusting PTS from %lld to %lld",
566a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar                    (long long)bufferItem->mTimestamp / 1000, (long long)itemRealUs);
567a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            bufferItem->mTimestamp = itemRealUs * 1000;
568a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar            bufferItem->mIsAutoTimestamp = false;
569a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
570c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            if (mHasAudio) {
571c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                if (nowUs - itemRealUs <= kMaxAllowedVideoLateTimeUs) {
57282a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar                    renderOneBufferItem_l(*bufferItem);
573c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                } else {
574c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                    // too late.
575c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                    returnBufferToInput_l(
576c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                            bufferItem->mGraphicBuffer, bufferItem->mFence);
577a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar                    mFrameScheduler->restart();
578c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                }
579c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            } else {
580c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                // always render video buffer in video-only mode.
58182a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar                renderOneBufferItem_l(*bufferItem);
582c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
583c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                // smooth out videos >= 10fps
584c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                mMediaClock->updateAnchor(
585c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                        itemMediaUs, nowUs, itemMediaUs + 100000);
586c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            }
587c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
588c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            mBufferItems.erase(mBufferItems.begin());
58980243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia            mNextBufferItemMediaUs = -1;
590c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        } else {
591c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            if (mNextBufferItemMediaUs == -1
59280243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                    || mNextBufferItemMediaUs > itemMediaUs) {
593c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                sp<AMessage> msg = new AMessage(kWhatDrainVideo, this);
594a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar                msg->post(itemRealUs - nowUs - twoVsyncsUs);
59580243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                mNextBufferItemMediaUs = itemMediaUs;
596c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            }
597c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            break;
598c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
599c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
600c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
601c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
602c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::onFrameAvailableFromInput() {
603c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
604c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
605a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    const static nsecs_t kAcquireWaitTimeout = 2000000000; // 2 seconds
606a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar
60708dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    mReturnPendingInputFrame = false;
60808dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar
609c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // If there are too many outstanding buffers, wait until a buffer is
610c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // released back to the input in onBufferReleased.
611a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    // NOTE: BufferQueue allows dequeuing maxAcquiredBufferCount + 1 buffers
61208dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    while (mNumOutstandingBuffers > mMaxAcquiredBufferCount
61308dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar            && !mIsAbandoned && !mReturnPendingInputFrame) {
614a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        if (mReleaseCondition.waitRelative(mMutex, kAcquireWaitTimeout) != OK) {
61582a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar            ALOGI_IF(mPlaybackRate != 0.f, "still waiting to release a buffer before acquire");
616a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        }
617c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
618c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // If the sync is abandoned while we are waiting, the release
619c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // condition variable will be broadcast, and we should just return
620c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // without attempting to do anything more (since the input queue will
621c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        // also be abandoned).
622c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (mIsAbandoned) {
623c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            return;
624c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
625c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
626c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
627c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // Acquire and detach the buffer from the input.
628c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    BufferItem bufferItem;
629c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    status_t status = mInput->acquireBuffer(&bufferItem, 0 /* presentWhen */);
630c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status != NO_ERROR) {
631c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGE("acquiring buffer from input failed (%d)", status);
632c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return;
633c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
634264bac95912efe121d6a60026612617f04f42966Lajos Molnar    ++mNumOutstandingBuffers;
635c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
636c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId());
637c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
638a8f5e0c24143299e3b3d722487de7322f7761559Pablo Ceballos    status = mInput->detachBuffer(bufferItem.mSlot);
639c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status != NO_ERROR) {
640c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGE("detaching buffer from input failed (%d)", status);
641c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (status == NO_INIT) {
642c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // If the input has been abandoned, move on.
643c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            onAbandoned_l(true /* isInput */);
644c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
645c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return;
646c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
647c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
648bac588208fadec78e3fa205c238089df277d3817Wei Jia    if (mBuffersFromInput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
649bac588208fadec78e3fa205c238089df277d3817Wei Jia        // Something is wrong since this buffer should be at our hands, bail.
650a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        ALOGE("received buffer multiple times from input");
651bac588208fadec78e3fa205c238089df277d3817Wei Jia        mInput->consumerDisconnect();
652bac588208fadec78e3fa205c238089df277d3817Wei Jia        onAbandoned_l(true /* isInput */);
653bac588208fadec78e3fa205c238089df277d3817Wei Jia        return;
654bac588208fadec78e3fa205c238089df277d3817Wei Jia    }
655bac588208fadec78e3fa205c238089df277d3817Wei Jia    mBuffersFromInput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
656bac588208fadec78e3fa205c238089df277d3817Wei Jia
65708dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    // If flush happened while waiting for a buffer to be released, simply return it
65808dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    // TRICKY: do it here after it is detached so that we don't have to cache mGraphicBuffer.
65908dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    if (mReturnPendingInputFrame) {
66008dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        mReturnPendingInputFrame = false;
66108dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        returnBufferToInput_l(bufferItem.mGraphicBuffer, bufferItem.mFence);
66208dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar        return;
66308dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar    }
66408dc42c46c942ff316a69be1cf74f3c60cf53e7fLajos Molnar
665c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mBufferItems.push_back(bufferItem);
666bac588208fadec78e3fa205c238089df277d3817Wei Jia
66780243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    if (mBufferItems.size() == 1) {
66880243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia        onDrainVideo_l();
66980243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia    }
670c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
671c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
67282a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnarvoid MediaSync::renderOneBufferItem_l(const BufferItem &bufferItem) {
673c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    IGraphicBufferProducer::QueueBufferInput queueInput(
674c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mTimestamp,
675c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mIsAutoTimestamp,
676c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mDataSpace,
677c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mCrop,
678c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            static_cast<int32_t>(bufferItem.mScalingMode),
679c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mTransform,
680c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            bufferItem.mFence);
681c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
682c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // Attach and queue the buffer to the output.
683c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int slot;
684264bac95912efe121d6a60026612617f04f42966Lajos Molnar    mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber());
685c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer);
686c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status);
687c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status == NO_ERROR) {
688c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        IGraphicBufferProducer::QueueBufferOutput queueOutput;
689c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        status = mOutput->queueBuffer(slot, queueInput, &queueOutput);
690c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGE_IF(status != NO_ERROR, "queueing buffer to output failed (%d)", status);
691c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
692c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
693c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status != NO_ERROR) {
694c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        returnBufferToInput_l(bufferItem.mGraphicBuffer, bufferItem.mFence);
695c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (status == NO_INIT) {
696c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            // If the output has been abandoned, move on.
697c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            onAbandoned_l(false /* isInput */);
698c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
699c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        return;
700c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
701c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
702b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    if (mBuffersSentToOutput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
703b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        // Something is wrong since this buffer should be held by output now, bail.
704b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mInput->consumerDisconnect();
705b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        onAbandoned_l(true /* isInput */);
706b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        return;
707b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    }
708b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    mBuffersSentToOutput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
709b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
710c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGV("queued buffer %#llx to output", (long long)bufferItem.mGraphicBuffer->getId());
711c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
712c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
713b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jiavoid MediaSync::onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output) {
714c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mMutex);
715c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
716b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    if (output != mOutput) {
717b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        return;  // This is not the current output, ignore.
718b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    }
719b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
720c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<GraphicBuffer> buffer;
721c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    sp<Fence> fence;
72282a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    status_t status = mOutput->detachNextBuffer(&buffer, &fence);
72382a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    ALOGE_IF(status != NO_ERROR, "detaching buffer from output failed (%d)", status);
724c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
72582a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    if (status == NO_INIT) {
72682a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        // If the output has been abandoned, we can't do anything else,
72782a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        // since buffer is invalid.
72882a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        onAbandoned_l(false /* isInput */);
72982a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        return;
73082a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    }
731c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
73282a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    ALOGV("detached buffer %#llx from output", (long long)buffer->getId());
733c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
73482a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    // If we've been abandoned, we can't return the buffer to the input, so just
73582a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    // move on.
73682a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    if (mIsAbandoned) {
73782a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        return;
73882a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    }
739b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia
74082a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    ssize_t ix = mBuffersSentToOutput.indexOfKey(buffer->getId());
74182a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    if (ix < 0) {
74282a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        // The buffer is unknown, maybe leftover, ignore.
74382a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar        return;
744a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar    }
74582a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    mBuffersSentToOutput.removeItemsAt(ix);
74682a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar
74782a633b602a7ffe1efd9886744393f52a093a2f3Lajos Molnar    returnBufferToInput_l(buffer, fence);
748c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
749c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
750c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::returnBufferToInput_l(
751c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        const sp<GraphicBuffer> &buffer, const sp<Fence> &fence) {
752bac588208fadec78e3fa205c238089df277d3817Wei Jia    ssize_t ix = mBuffersFromInput.indexOfKey(buffer->getId());
753bac588208fadec78e3fa205c238089df277d3817Wei Jia    if (ix < 0) {
754bac588208fadec78e3fa205c238089df277d3817Wei Jia        // The buffer is unknown, something is wrong, bail.
755a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar        ALOGE("output returned unknown buffer");
756bac588208fadec78e3fa205c238089df277d3817Wei Jia        mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
757bac588208fadec78e3fa205c238089df277d3817Wei Jia        onAbandoned_l(false /* isInput */);
758bac588208fadec78e3fa205c238089df277d3817Wei Jia        return;
759bac588208fadec78e3fa205c238089df277d3817Wei Jia    }
760bac588208fadec78e3fa205c238089df277d3817Wei Jia    sp<GraphicBuffer> oldBuffer = mBuffersFromInput.valueAt(ix);
761bac588208fadec78e3fa205c238089df277d3817Wei Jia    mBuffersFromInput.removeItemsAt(ix);
762bac588208fadec78e3fa205c238089df277d3817Wei Jia
763c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // Attach and release the buffer back to the input.
764c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    int consumerSlot;
765bac588208fadec78e3fa205c238089df277d3817Wei Jia    status_t status = mInput->attachBuffer(&consumerSlot, oldBuffer);
766c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGE_IF(status != NO_ERROR, "attaching buffer to input failed (%d)", status);
767c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (status == NO_ERROR) {
768c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        status = mInput->releaseBuffer(consumerSlot, 0 /* frameNumber */,
769c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
770c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status);
771c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
772c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
773c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    // Notify any waiting onFrameAvailable calls.
774c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    --mNumOutstandingBuffers;
775c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mReleaseCondition.signal();
776264bac95912efe121d6a60026612617f04f42966Lajos Molnar
777264bac95912efe121d6a60026612617f04f42966Lajos Molnar    if (status == NO_ERROR) {
778264bac95912efe121d6a60026612617f04f42966Lajos Molnar        ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
779264bac95912efe121d6a60026612617f04f42966Lajos Molnar    }
780c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
781c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
782c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::onAbandoned_l(bool isInput) {
783c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGE("the %s has abandoned me", (isInput ? "input" : "output"));
784c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    if (!mIsAbandoned) {
785c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        if (isInput) {
786c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
787c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        } else {
788c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            mInput->consumerDisconnect();
789c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
790c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        mIsAbandoned = true;
791c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
792c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mReleaseCondition.broadcast();
793c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
794c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
795c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::onMessageReceived(const sp<AMessage> &msg) {
796c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    switch (msg->what()) {
797c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        case kWhatDrainVideo:
798c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        {
799c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            Mutex::Autolock lock(mMutex);
80080243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia            if (mNextBufferItemMediaUs != -1) {
80180243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                int64_t nowUs = ALooper::GetNowUs();
80280243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                int64_t itemRealUs = getRealTime(mNextBufferItemMediaUs, nowUs);
80380243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia
80480243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                // The message could arrive earlier than expected due to
80580243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                // various reasons, e.g., media clock has been changed because
80680243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                // of new anchor time or playback rate. In such cases, the
80780243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                // message needs to be re-posted.
80880243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                if (itemRealUs > nowUs) {
80980243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                    msg->post(itemRealUs - nowUs);
81080243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                    break;
81180243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia                }
81280243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia            }
81380243639b0aa2c7c941c23c1aaeaa75de38c148cWei Jia
814c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            onDrainVideo_l();
815c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            break;
816c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        }
817c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
818c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia        default:
819c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            TRESPASS();
820c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia            break;
821c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    }
822c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
823c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
824c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei JiaMediaSync::InputListener::InputListener(const sp<MediaSync> &sync)
825c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia      : mSync(sync) {}
826c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
827c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei JiaMediaSync::InputListener::~InputListener() {}
828c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
829c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::InputListener::onFrameAvailable(const BufferItem &/* item */) {
830c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mSync->onFrameAvailableFromInput();
831c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
832c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
833c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia// We don't care about sideband streams, since we won't relay them.
834c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::InputListener::onSidebandStreamChanged() {
835c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    ALOGE("onSidebandStreamChanged: got sideband stream unexpectedly.");
836c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
837c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
838c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
839c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::InputListener::binderDied(const wp<IBinder> &/* who */) {
840c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mSync->mMutex);
841c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mSync->onAbandoned_l(true /* isInput */);
842c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
843c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
844b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei JiaMediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync,
845b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        const sp<IGraphicBufferProducer> &output)
846b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia      : mSync(sync),
847b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia        mOutput(output) {}
848c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
849c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei JiaMediaSync::OutputListener::~OutputListener() {}
850c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
851c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::OutputListener::onBufferReleased() {
852b6ea1292f8adae45d95c6f37d50c96534219b6d2Wei Jia    mSync->onBufferReleasedByOutput(mOutput);
853c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
854c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
855c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jiavoid MediaSync::OutputListener::binderDied(const wp<IBinder> &/* who */) {
856c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    Mutex::Autolock lock(mSync->mMutex);
857c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia    mSync->onAbandoned_l(false /* isInput */);
858c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia}
859c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia
860c8db9712d9abe9b0d74193ea7d7cff428e32e62cWei Jia} // namespace android
861