1427e38084a16ec063983346347decf3ec461eed1James Dong/*
2427e38084a16ec063983346347decf3ec461eed1James Dong * Copyright (C) 2012 The Android Open Source Project
3427e38084a16ec063983346347decf3ec461eed1James Dong *
4427e38084a16ec063983346347decf3ec461eed1James Dong * Licensed under the Apache License, Version 2.0 (the "License");
5427e38084a16ec063983346347decf3ec461eed1James Dong * you may not use this file except in compliance with the License.
6427e38084a16ec063983346347decf3ec461eed1James Dong * You may obtain a copy of the License at
7427e38084a16ec063983346347decf3ec461eed1James Dong *
8427e38084a16ec063983346347decf3ec461eed1James Dong *      http://www.apache.org/licenses/LICENSE-2.0
9427e38084a16ec063983346347decf3ec461eed1James Dong *
10427e38084a16ec063983346347decf3ec461eed1James Dong * Unless required by applicable law or agreed to in writing, software
11427e38084a16ec063983346347decf3ec461eed1James Dong * distributed under the License is distributed on an "AS IS" BASIS,
12427e38084a16ec063983346347decf3ec461eed1James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13427e38084a16ec063983346347decf3ec461eed1James Dong * See the License for the specific language governing permissions and
14427e38084a16ec063983346347decf3ec461eed1James Dong * limitations under the License.
15427e38084a16ec063983346347decf3ec461eed1James Dong */
16427e38084a16ec063983346347decf3ec461eed1James Dong
17427e38084a16ec063983346347decf3ec461eed1James Dong//#define LOG_NDEBUG 0
18427e38084a16ec063983346347decf3ec461eed1James Dong#define LOG_TAG "MediaBufferPuller"
19427e38084a16ec063983346347decf3ec461eed1James Dong#include <utils/Log.h>
20427e38084a16ec063983346347decf3ec461eed1James Dong
21427e38084a16ec063983346347decf3ec461eed1James Dong#include <media/stagefright/MediaSource.h>
22427e38084a16ec063983346347decf3ec461eed1James Dong#include <media/stagefright/MediaBuffer.h>
23427e38084a16ec063983346347decf3ec461eed1James Dong#include <media/stagefright/MediaDefs.h>
24427e38084a16ec063983346347decf3ec461eed1James Dong#include "MediaBufferPuller.h"
25427e38084a16ec063983346347decf3ec461eed1James Dong
26427e38084a16ec063983346347decf3ec461eed1James Dongnamespace android {
27427e38084a16ec063983346347decf3ec461eed1James Dong
28427e38084a16ec063983346347decf3ec461eed1James Dong
29427e38084a16ec063983346347decf3ec461eed1James DongMediaBufferPuller::MediaBufferPuller(const sp<MediaSource>& source)
30427e38084a16ec063983346347decf3ec461eed1James Dong    : mSource(source),
31427e38084a16ec063983346347decf3ec461eed1James Dong      mAskToStart(false),
32427e38084a16ec063983346347decf3ec461eed1James Dong      mAskToStop(false),
33427e38084a16ec063983346347decf3ec461eed1James Dong      mAcquireStopped(false),
34427e38084a16ec063983346347decf3ec461eed1James Dong      mReleaseStopped(false),
35427e38084a16ec063983346347decf3ec461eed1James Dong      mSourceError(OK) {
36427e38084a16ec063983346347decf3ec461eed1James Dong
37427e38084a16ec063983346347decf3ec461eed1James Dong    androidCreateThread(acquireThreadStart, this);
38427e38084a16ec063983346347decf3ec461eed1James Dong    androidCreateThread(releaseThreadStart, this);
39427e38084a16ec063983346347decf3ec461eed1James Dong}
40427e38084a16ec063983346347decf3ec461eed1James Dong
41427e38084a16ec063983346347decf3ec461eed1James DongMediaBufferPuller::~MediaBufferPuller() {
42427e38084a16ec063983346347decf3ec461eed1James Dong    stop();
43427e38084a16ec063983346347decf3ec461eed1James Dong}
44427e38084a16ec063983346347decf3ec461eed1James Dong
45427e38084a16ec063983346347decf3ec461eed1James Dongbool MediaBufferPuller::hasMediaSourceReturnedError() const {
46427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
47427e38084a16ec063983346347decf3ec461eed1James Dong    return ((mSourceError != OK) ? true : false);
48427e38084a16ec063983346347decf3ec461eed1James Dong}
49427e38084a16ec063983346347decf3ec461eed1James Dongvoid MediaBufferPuller::start() {
50427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
51427e38084a16ec063983346347decf3ec461eed1James Dong    mAskToStart = true;
52427e38084a16ec063983346347decf3ec461eed1James Dong    mAcquireCond.signal();
53427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseCond.signal();
54427e38084a16ec063983346347decf3ec461eed1James Dong}
55427e38084a16ec063983346347decf3ec461eed1James Dong
56427e38084a16ec063983346347decf3ec461eed1James Dongvoid MediaBufferPuller::stop() {
57427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
58427e38084a16ec063983346347decf3ec461eed1James Dong    mAskToStop = true;
59427e38084a16ec063983346347decf3ec461eed1James Dong    mAcquireCond.signal();
60427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseCond.signal();
61427e38084a16ec063983346347decf3ec461eed1James Dong    while (!mAcquireStopped || !mReleaseStopped) {
62427e38084a16ec063983346347decf3ec461eed1James Dong        mUserCond.wait(mLock);
63427e38084a16ec063983346347decf3ec461eed1James Dong    }
64427e38084a16ec063983346347decf3ec461eed1James Dong
65427e38084a16ec063983346347decf3ec461eed1James Dong    // Release remaining buffers
66427e38084a16ec063983346347decf3ec461eed1James Dong    for (size_t i = 0; i < mBuffers.size(); i++) {
67427e38084a16ec063983346347decf3ec461eed1James Dong        mBuffers.itemAt(i)->release();
68427e38084a16ec063983346347decf3ec461eed1James Dong    }
69427e38084a16ec063983346347decf3ec461eed1James Dong
70427e38084a16ec063983346347decf3ec461eed1James Dong    for (size_t i = 0; i < mReleaseBuffers.size(); i++) {
71427e38084a16ec063983346347decf3ec461eed1James Dong        mReleaseBuffers.itemAt(i)->release();
72427e38084a16ec063983346347decf3ec461eed1James Dong    }
73427e38084a16ec063983346347decf3ec461eed1James Dong
74427e38084a16ec063983346347decf3ec461eed1James Dong    mBuffers.clear();
75427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseBuffers.clear();
76427e38084a16ec063983346347decf3ec461eed1James Dong}
77427e38084a16ec063983346347decf3ec461eed1James Dong
78427e38084a16ec063983346347decf3ec461eed1James DongMediaBuffer* MediaBufferPuller::getBufferNonBlocking() {
79427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
80427e38084a16ec063983346347decf3ec461eed1James Dong    if (mBuffers.empty()) {
81427e38084a16ec063983346347decf3ec461eed1James Dong        return NULL;
82427e38084a16ec063983346347decf3ec461eed1James Dong    } else {
83427e38084a16ec063983346347decf3ec461eed1James Dong        MediaBuffer* b = mBuffers.itemAt(0);
84427e38084a16ec063983346347decf3ec461eed1James Dong        mBuffers.removeAt(0);
85427e38084a16ec063983346347decf3ec461eed1James Dong        return b;
86427e38084a16ec063983346347decf3ec461eed1James Dong    }
87427e38084a16ec063983346347decf3ec461eed1James Dong}
88427e38084a16ec063983346347decf3ec461eed1James Dong
89427e38084a16ec063983346347decf3ec461eed1James DongMediaBuffer* MediaBufferPuller::getBufferBlocking() {
90427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
91427e38084a16ec063983346347decf3ec461eed1James Dong    while (mBuffers.empty() && !mAcquireStopped) {
92427e38084a16ec063983346347decf3ec461eed1James Dong        mUserCond.wait(mLock);
93427e38084a16ec063983346347decf3ec461eed1James Dong    }
94427e38084a16ec063983346347decf3ec461eed1James Dong
95427e38084a16ec063983346347decf3ec461eed1James Dong    if (mBuffers.empty()) {
96427e38084a16ec063983346347decf3ec461eed1James Dong        return NULL;
97427e38084a16ec063983346347decf3ec461eed1James Dong    } else {
98427e38084a16ec063983346347decf3ec461eed1James Dong        MediaBuffer* b = mBuffers.itemAt(0);
99427e38084a16ec063983346347decf3ec461eed1James Dong        mBuffers.removeAt(0);
100427e38084a16ec063983346347decf3ec461eed1James Dong        return b;
101427e38084a16ec063983346347decf3ec461eed1James Dong    }
102427e38084a16ec063983346347decf3ec461eed1James Dong}
103427e38084a16ec063983346347decf3ec461eed1James Dong
104427e38084a16ec063983346347decf3ec461eed1James Dongvoid MediaBufferPuller::putBuffer(MediaBuffer* buffer) {
105427e38084a16ec063983346347decf3ec461eed1James Dong    Mutex::Autolock autolock(mLock);
106427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseBuffers.push(buffer);
107427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseCond.signal();
108427e38084a16ec063983346347decf3ec461eed1James Dong}
109427e38084a16ec063983346347decf3ec461eed1James Dong
110427e38084a16ec063983346347decf3ec461eed1James Dongint MediaBufferPuller::acquireThreadStart(void* arg) {
111427e38084a16ec063983346347decf3ec461eed1James Dong    MediaBufferPuller* self = (MediaBufferPuller*)arg;
112427e38084a16ec063983346347decf3ec461eed1James Dong    self->acquireThreadFunc();
113427e38084a16ec063983346347decf3ec461eed1James Dong    return 0;
114427e38084a16ec063983346347decf3ec461eed1James Dong}
115427e38084a16ec063983346347decf3ec461eed1James Dong
116427e38084a16ec063983346347decf3ec461eed1James Dongint MediaBufferPuller::releaseThreadStart(void* arg) {
117427e38084a16ec063983346347decf3ec461eed1James Dong    MediaBufferPuller* self = (MediaBufferPuller*)arg;
118427e38084a16ec063983346347decf3ec461eed1James Dong    self->releaseThreadFunc();
119427e38084a16ec063983346347decf3ec461eed1James Dong    return 0;
120427e38084a16ec063983346347decf3ec461eed1James Dong}
121427e38084a16ec063983346347decf3ec461eed1James Dong
122427e38084a16ec063983346347decf3ec461eed1James Dongvoid MediaBufferPuller::acquireThreadFunc() {
123427e38084a16ec063983346347decf3ec461eed1James Dong    mLock.lock();
124427e38084a16ec063983346347decf3ec461eed1James Dong
125427e38084a16ec063983346347decf3ec461eed1James Dong    // Wait for the start signal
126427e38084a16ec063983346347decf3ec461eed1James Dong    while (!mAskToStart && !mAskToStop) {
127427e38084a16ec063983346347decf3ec461eed1James Dong        mAcquireCond.wait(mLock);
128427e38084a16ec063983346347decf3ec461eed1James Dong    }
129427e38084a16ec063983346347decf3ec461eed1James Dong
130427e38084a16ec063983346347decf3ec461eed1James Dong    // Loop until we are asked to stop, or there is nothing more to read
131427e38084a16ec063983346347decf3ec461eed1James Dong    while (!mAskToStop) {
132427e38084a16ec063983346347decf3ec461eed1James Dong        MediaBuffer* pBuffer;
133427e38084a16ec063983346347decf3ec461eed1James Dong        mLock.unlock();
134427e38084a16ec063983346347decf3ec461eed1James Dong        status_t result = mSource->read(&pBuffer, NULL);
135427e38084a16ec063983346347decf3ec461eed1James Dong        mLock.lock();
136427e38084a16ec063983346347decf3ec461eed1James Dong        mSourceError = result;
137427e38084a16ec063983346347decf3ec461eed1James Dong        if (result != OK) {
138427e38084a16ec063983346347decf3ec461eed1James Dong            break;
139427e38084a16ec063983346347decf3ec461eed1James Dong        }
140427e38084a16ec063983346347decf3ec461eed1James Dong        mBuffers.push(pBuffer);
141427e38084a16ec063983346347decf3ec461eed1James Dong        mUserCond.signal();
142427e38084a16ec063983346347decf3ec461eed1James Dong    }
143427e38084a16ec063983346347decf3ec461eed1James Dong
144427e38084a16ec063983346347decf3ec461eed1James Dong    mAcquireStopped = true;
145427e38084a16ec063983346347decf3ec461eed1James Dong    mUserCond.signal();
146427e38084a16ec063983346347decf3ec461eed1James Dong    mLock.unlock();
147427e38084a16ec063983346347decf3ec461eed1James Dong}
148427e38084a16ec063983346347decf3ec461eed1James Dong
149427e38084a16ec063983346347decf3ec461eed1James Dongvoid MediaBufferPuller::releaseThreadFunc() {
150427e38084a16ec063983346347decf3ec461eed1James Dong    mLock.lock();
151427e38084a16ec063983346347decf3ec461eed1James Dong
152427e38084a16ec063983346347decf3ec461eed1James Dong    // Wait for the start signal
153427e38084a16ec063983346347decf3ec461eed1James Dong    while (!mAskToStart && !mAskToStop) {
154427e38084a16ec063983346347decf3ec461eed1James Dong        mReleaseCond.wait(mLock);
155427e38084a16ec063983346347decf3ec461eed1James Dong    }
156427e38084a16ec063983346347decf3ec461eed1James Dong
157427e38084a16ec063983346347decf3ec461eed1James Dong    // Loop until we are asked to stop
158427e38084a16ec063983346347decf3ec461eed1James Dong    while (1) {
159427e38084a16ec063983346347decf3ec461eed1James Dong        if (mReleaseBuffers.empty()) {
160427e38084a16ec063983346347decf3ec461eed1James Dong            if (mAskToStop) {
161427e38084a16ec063983346347decf3ec461eed1James Dong                break;
162427e38084a16ec063983346347decf3ec461eed1James Dong            } else {
163427e38084a16ec063983346347decf3ec461eed1James Dong                mReleaseCond.wait(mLock);
164427e38084a16ec063983346347decf3ec461eed1James Dong                continue;
165427e38084a16ec063983346347decf3ec461eed1James Dong            }
166427e38084a16ec063983346347decf3ec461eed1James Dong        }
167427e38084a16ec063983346347decf3ec461eed1James Dong        MediaBuffer* pBuffer = mReleaseBuffers.itemAt(0);
168427e38084a16ec063983346347decf3ec461eed1James Dong        mReleaseBuffers.removeAt(0);
169427e38084a16ec063983346347decf3ec461eed1James Dong        mLock.unlock();
170427e38084a16ec063983346347decf3ec461eed1James Dong        pBuffer->release();
171427e38084a16ec063983346347decf3ec461eed1James Dong        mLock.lock();
172427e38084a16ec063983346347decf3ec461eed1James Dong    }
173427e38084a16ec063983346347decf3ec461eed1James Dong
174427e38084a16ec063983346347decf3ec461eed1James Dong    mReleaseStopped = true;
175427e38084a16ec063983346347decf3ec461eed1James Dong    mUserCond.signal();
176427e38084a16ec063983346347decf3ec461eed1James Dong    mLock.unlock();
177427e38084a16ec063983346347decf3ec461eed1James Dong}
178427e38084a16ec063983346347decf3ec461eed1James Dong
179427e38084a16ec063983346347decf3ec461eed1James Dong};  // namespace android
180