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