Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "MediaBufferPuller"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/MediaSource.h>
     22 #include <media/stagefright/MediaBuffer.h>
     23 #include <media/stagefright/MediaDefs.h>
     24 #include "MediaBufferPuller.h"
     25 
     26 namespace android {
     27 
     28 
     29 MediaBufferPuller::MediaBufferPuller(const sp<MediaSource>& source)
     30     : mSource(source),
     31       mAskToStart(false),
     32       mAskToStop(false),
     33       mAcquireStopped(false),
     34       mReleaseStopped(false),
     35       mSourceError(OK) {
     36 
     37     androidCreateThread(acquireThreadStart, this);
     38     androidCreateThread(releaseThreadStart, this);
     39 }
     40 
     41 MediaBufferPuller::~MediaBufferPuller() {
     42     stop();
     43 }
     44 
     45 bool MediaBufferPuller::hasMediaSourceReturnedError() const {
     46     Mutex::Autolock autolock(mLock);
     47     return ((mSourceError != OK) ? true : false);
     48 }
     49 void MediaBufferPuller::start() {
     50     Mutex::Autolock autolock(mLock);
     51     mAskToStart = true;
     52     mAcquireCond.signal();
     53     mReleaseCond.signal();
     54 }
     55 
     56 void MediaBufferPuller::stop() {
     57     Mutex::Autolock autolock(mLock);
     58     mAskToStop = true;
     59     mAcquireCond.signal();
     60     mReleaseCond.signal();
     61     while (!mAcquireStopped || !mReleaseStopped) {
     62         mUserCond.wait(mLock);
     63     }
     64 
     65     // Release remaining buffers
     66     for (size_t i = 0; i < mBuffers.size(); i++) {
     67         mBuffers.itemAt(i)->release();
     68     }
     69 
     70     for (size_t i = 0; i < mReleaseBuffers.size(); i++) {
     71         mReleaseBuffers.itemAt(i)->release();
     72     }
     73 
     74     mBuffers.clear();
     75     mReleaseBuffers.clear();
     76 }
     77 
     78 MediaBuffer* MediaBufferPuller::getBufferNonBlocking() {
     79     Mutex::Autolock autolock(mLock);
     80     if (mBuffers.empty()) {
     81         return NULL;
     82     } else {
     83         MediaBuffer* b = mBuffers.itemAt(0);
     84         mBuffers.removeAt(0);
     85         return b;
     86     }
     87 }
     88 
     89 MediaBuffer* MediaBufferPuller::getBufferBlocking() {
     90     Mutex::Autolock autolock(mLock);
     91     while (mBuffers.empty() && !mAcquireStopped) {
     92         mUserCond.wait(mLock);
     93     }
     94 
     95     if (mBuffers.empty()) {
     96         return NULL;
     97     } else {
     98         MediaBuffer* b = mBuffers.itemAt(0);
     99         mBuffers.removeAt(0);
    100         return b;
    101     }
    102 }
    103 
    104 void MediaBufferPuller::putBuffer(MediaBuffer* buffer) {
    105     Mutex::Autolock autolock(mLock);
    106     mReleaseBuffers.push(buffer);
    107     mReleaseCond.signal();
    108 }
    109 
    110 int MediaBufferPuller::acquireThreadStart(void* arg) {
    111     MediaBufferPuller* self = (MediaBufferPuller*)arg;
    112     self->acquireThreadFunc();
    113     return 0;
    114 }
    115 
    116 int MediaBufferPuller::releaseThreadStart(void* arg) {
    117     MediaBufferPuller* self = (MediaBufferPuller*)arg;
    118     self->releaseThreadFunc();
    119     return 0;
    120 }
    121 
    122 void MediaBufferPuller::acquireThreadFunc() {
    123     mLock.lock();
    124 
    125     // Wait for the start signal
    126     while (!mAskToStart && !mAskToStop) {
    127         mAcquireCond.wait(mLock);
    128     }
    129 
    130     // Loop until we are asked to stop, or there is nothing more to read
    131     while (!mAskToStop) {
    132         MediaBuffer* pBuffer;
    133         mLock.unlock();
    134         status_t result = mSource->read(&pBuffer, NULL);
    135         mLock.lock();
    136         mSourceError = result;
    137         if (result != OK) {
    138             break;
    139         }
    140         mBuffers.push(pBuffer);
    141         mUserCond.signal();
    142     }
    143 
    144     mAcquireStopped = true;
    145     mUserCond.signal();
    146     mLock.unlock();
    147 }
    148 
    149 void MediaBufferPuller::releaseThreadFunc() {
    150     mLock.lock();
    151 
    152     // Wait for the start signal
    153     while (!mAskToStart && !mAskToStop) {
    154         mReleaseCond.wait(mLock);
    155     }
    156 
    157     // Loop until we are asked to stop
    158     while (1) {
    159         if (mReleaseBuffers.empty()) {
    160             if (mAskToStop) {
    161                 break;
    162             } else {
    163                 mReleaseCond.wait(mLock);
    164                 continue;
    165             }
    166         }
    167         MediaBuffer* pBuffer = mReleaseBuffers.itemAt(0);
    168         mReleaseBuffers.removeAt(0);
    169         mLock.unlock();
    170         pBuffer->release();
    171         mLock.lock();
    172     }
    173 
    174     mReleaseStopped = true;
    175     mUserCond.signal();
    176     mLock.unlock();
    177 }
    178 
    179 };  // namespace android
    180