| /* |
| * 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 <utils/Log.h> |
| |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/MediaAdapter.h> |
| #include <media/stagefright/MediaBuffer.h> |
| |
| namespace android { |
| |
| MediaAdapter::MediaAdapter(const sp<MetaData> &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<MetaData> 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 |
| |