1/* 2 * Copyright (C) 2013 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 "MediaAdapter" 19#include <utils/Log.h> 20 21#include <media/stagefright/foundation/ADebug.h> 22#include <media/stagefright/MediaAdapter.h> 23#include <media/stagefright/MediaBuffer.h> 24 25namespace android { 26 27MediaAdapter::MediaAdapter(const sp<MetaData> &meta) 28 : mCurrentMediaBuffer(NULL), 29 mStarted(false), 30 mOutputFormat(meta) { 31} 32 33MediaAdapter::~MediaAdapter() { 34 Mutex::Autolock autoLock(mAdapterLock); 35 mOutputFormat.clear(); 36 CHECK(mCurrentMediaBuffer == NULL); 37} 38 39status_t MediaAdapter::start(MetaData * /* params */) { 40 Mutex::Autolock autoLock(mAdapterLock); 41 if (!mStarted) { 42 mStarted = true; 43 } 44 return OK; 45} 46 47status_t MediaAdapter::stop() { 48 MediaBuffer *currentBuffer = NULL; 49 { 50 Mutex::Autolock autoLock(mAdapterLock); 51 if (mStarted) { 52 mStarted = false; 53 // If stop() happens immediately after a pushBuffer(), we should 54 // clean up the mCurrentMediaBuffer. But need to release without 55 // the lock as signalBufferReturned() will acquire the lock. 56 currentBuffer = mCurrentMediaBuffer; 57 mCurrentMediaBuffer = NULL; 58 59 // While read() is still waiting, we should signal it to finish. 60 mBufferReadCond.signal(); 61 } 62 } 63 if (currentBuffer != NULL) { 64 currentBuffer->release(); 65 currentBuffer = NULL; 66 } 67 return OK; 68} 69 70sp<MetaData> MediaAdapter::getFormat() { 71 Mutex::Autolock autoLock(mAdapterLock); 72 return mOutputFormat; 73} 74 75void MediaAdapter::signalBufferReturned(MediaBufferBase *buffer) { 76 Mutex::Autolock autoLock(mAdapterLock); 77 CHECK(buffer != NULL); 78 buffer->setObserver(0); 79 buffer->release(); 80 ALOGV("buffer returned %p", buffer); 81 mBufferReturnedCond.signal(); 82} 83 84status_t MediaAdapter::read( 85 MediaBufferBase **buffer, const ReadOptions * /* options */) { 86 Mutex::Autolock autoLock(mAdapterLock); 87 if (!mStarted) { 88 ALOGV("Read before even started!"); 89 return ERROR_END_OF_STREAM; 90 } 91 92 while (mCurrentMediaBuffer == NULL && mStarted) { 93 ALOGV("waiting @ read()"); 94 mBufferReadCond.wait(mAdapterLock); 95 } 96 97 if (!mStarted) { 98 ALOGV("read interrupted after stop"); 99 CHECK(mCurrentMediaBuffer == NULL); 100 return ERROR_END_OF_STREAM; 101 } 102 103 CHECK(mCurrentMediaBuffer != NULL); 104 105 *buffer = mCurrentMediaBuffer; 106 mCurrentMediaBuffer = NULL; 107 108 return OK; 109} 110 111status_t MediaAdapter::pushBuffer(MediaBuffer *buffer) { 112 if (buffer == NULL) { 113 ALOGE("pushBuffer get an NULL buffer"); 114 return -EINVAL; 115 } 116 117 Mutex::Autolock autoLock(mAdapterLock); 118 if (!mStarted) { 119 ALOGE("pushBuffer called before start"); 120 return INVALID_OPERATION; 121 } 122 mCurrentMediaBuffer = buffer; 123 mCurrentMediaBuffer->setObserver(this); 124 mBufferReadCond.signal(); 125 126 ALOGV("wait for the buffer returned @ pushBuffer! %p", buffer); 127 mBufferReturnedCond.wait(mAdapterLock); 128 129 return OK; 130} 131 132} // namespace android 133 134