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