/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaAdapter" #include #include #include #include namespace android { MediaAdapter::MediaAdapter(const sp &meta) : mCurrentMediaBuffer(NULL), mStarted(false), mOutputFormat(meta) { } MediaAdapter::~MediaAdapter() { Mutex::Autolock autoLock(mAdapterLock); mOutputFormat.clear(); CHECK(mCurrentMediaBuffer == NULL); } status_t MediaAdapter::start(MetaData * /* params */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { mStarted = true; } return OK; } status_t MediaAdapter::stop() { Mutex::Autolock autoLock(mAdapterLock); if (mStarted) { mStarted = false; // If stop() happens immediately after a pushBuffer(), we should // clean up the mCurrentMediaBuffer if (mCurrentMediaBuffer != NULL) { mCurrentMediaBuffer->release(); mCurrentMediaBuffer = NULL; } // While read() is still waiting, we should signal it to finish. mBufferReadCond.signal(); } return OK; } sp MediaAdapter::getFormat() { Mutex::Autolock autoLock(mAdapterLock); return mOutputFormat; } void MediaAdapter::signalBufferReturned(MediaBuffer *buffer) { Mutex::Autolock autoLock(mAdapterLock); CHECK(buffer != NULL); buffer->setObserver(0); buffer->release(); ALOGV("buffer returned %p", buffer); mBufferReturnedCond.signal(); } status_t MediaAdapter::read( MediaBuffer **buffer, const ReadOptions * /* options */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { ALOGV("Read before even started!"); return ERROR_END_OF_STREAM; } while (mCurrentMediaBuffer == NULL && mStarted) { ALOGV("waiting @ read()"); mBufferReadCond.wait(mAdapterLock); } if (!mStarted) { ALOGV("read interrupted after stop"); CHECK(mCurrentMediaBuffer == NULL); return ERROR_END_OF_STREAM; } CHECK(mCurrentMediaBuffer != NULL); *buffer = mCurrentMediaBuffer; mCurrentMediaBuffer = NULL; (*buffer)->setObserver(this); return OK; } status_t MediaAdapter::pushBuffer(MediaBuffer *buffer) { if (buffer == NULL) { ALOGE("pushBuffer get an NULL buffer"); return -EINVAL; } Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { ALOGE("pushBuffer called before start"); return INVALID_OPERATION; } mCurrentMediaBuffer = buffer; mBufferReadCond.signal(); ALOGV("wait for the buffer returned @ pushBuffer! %p", buffer); mBufferReturnedCond.wait(mAdapterLock); return OK; } } // namespace android