From 427e38084a16ec063983346347decf3ec461eed1 Mon Sep 17 00:00:00 2001 From: James Dong Date: Tue, 6 Mar 2012 10:59:23 -0800 Subject: Refactored MediaBufferPuller class from VideoEditorVideoEncoder class o MediaBufferPull class will be useful for the audio encoder also once we switch to use OMX-based audio encoder. o This is the part one for fixing bug 5947347 Change-Id: Icddfeb636f7a59ad766220ef0d3155abace73ad3 --- .../vss/stagefrightshells/src/Android.mk | 1 + .../stagefrightshells/src/MediaBufferPuller.cpp | 179 +++++++++++++++++++ .../vss/stagefrightshells/src/MediaBufferPuller.h | 90 ++++++++++ .../src/VideoEditorVideoEncoder.cpp | 194 +-------------------- 4 files changed, 274 insertions(+), 190 deletions(-) create mode 100644 libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.cpp create mode 100644 libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.h (limited to 'libvideoeditor') diff --git a/libvideoeditor/vss/stagefrightshells/src/Android.mk b/libvideoeditor/vss/stagefrightshells/src/Android.mk index e81f8da..ea742cb 100755 --- a/libvideoeditor/vss/stagefrightshells/src/Android.mk +++ b/libvideoeditor/vss/stagefrightshells/src/Android.mk @@ -18,6 +18,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ + MediaBufferPuller.cpp \ VideoEditorVideoDecoder.cpp \ VideoEditorAudioDecoder.cpp \ VideoEditorMp3Reader.cpp \ diff --git a/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.cpp b/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.cpp new file mode 100644 index 0000000..acc8268 --- /dev/null +++ b/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 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 "MediaBufferPuller" +#include + +#include +#include +#include +#include "MediaBufferPuller.h" + +namespace android { + + +MediaBufferPuller::MediaBufferPuller(const sp& source) + : mSource(source), + mAskToStart(false), + mAskToStop(false), + mAcquireStopped(false), + mReleaseStopped(false), + mSourceError(OK) { + + androidCreateThread(acquireThreadStart, this); + androidCreateThread(releaseThreadStart, this); +} + +MediaBufferPuller::~MediaBufferPuller() { + stop(); +} + +bool MediaBufferPuller::hasMediaSourceReturnedError() const { + Mutex::Autolock autolock(mLock); + return ((mSourceError != OK) ? true : false); +} +void MediaBufferPuller::start() { + Mutex::Autolock autolock(mLock); + mAskToStart = true; + mAcquireCond.signal(); + mReleaseCond.signal(); +} + +void MediaBufferPuller::stop() { + Mutex::Autolock autolock(mLock); + mAskToStop = true; + mAcquireCond.signal(); + mReleaseCond.signal(); + while (!mAcquireStopped || !mReleaseStopped) { + mUserCond.wait(mLock); + } + + // Release remaining buffers + for (size_t i = 0; i < mBuffers.size(); i++) { + mBuffers.itemAt(i)->release(); + } + + for (size_t i = 0; i < mReleaseBuffers.size(); i++) { + mReleaseBuffers.itemAt(i)->release(); + } + + mBuffers.clear(); + mReleaseBuffers.clear(); +} + +MediaBuffer* MediaBufferPuller::getBufferNonBlocking() { + Mutex::Autolock autolock(mLock); + if (mBuffers.empty()) { + return NULL; + } else { + MediaBuffer* b = mBuffers.itemAt(0); + mBuffers.removeAt(0); + return b; + } +} + +MediaBuffer* MediaBufferPuller::getBufferBlocking() { + Mutex::Autolock autolock(mLock); + while (mBuffers.empty() && !mAcquireStopped) { + mUserCond.wait(mLock); + } + + if (mBuffers.empty()) { + return NULL; + } else { + MediaBuffer* b = mBuffers.itemAt(0); + mBuffers.removeAt(0); + return b; + } +} + +void MediaBufferPuller::putBuffer(MediaBuffer* buffer) { + Mutex::Autolock autolock(mLock); + mReleaseBuffers.push(buffer); + mReleaseCond.signal(); +} + +int MediaBufferPuller::acquireThreadStart(void* arg) { + MediaBufferPuller* self = (MediaBufferPuller*)arg; + self->acquireThreadFunc(); + return 0; +} + +int MediaBufferPuller::releaseThreadStart(void* arg) { + MediaBufferPuller* self = (MediaBufferPuller*)arg; + self->releaseThreadFunc(); + return 0; +} + +void MediaBufferPuller::acquireThreadFunc() { + mLock.lock(); + + // Wait for the start signal + while (!mAskToStart && !mAskToStop) { + mAcquireCond.wait(mLock); + } + + // Loop until we are asked to stop, or there is nothing more to read + while (!mAskToStop) { + MediaBuffer* pBuffer; + mLock.unlock(); + status_t result = mSource->read(&pBuffer, NULL); + mLock.lock(); + mSourceError = result; + if (result != OK) { + break; + } + mBuffers.push(pBuffer); + mUserCond.signal(); + } + + mAcquireStopped = true; + mUserCond.signal(); + mLock.unlock(); +} + +void MediaBufferPuller::releaseThreadFunc() { + mLock.lock(); + + // Wait for the start signal + while (!mAskToStart && !mAskToStop) { + mReleaseCond.wait(mLock); + } + + // Loop until we are asked to stop + while (1) { + if (mReleaseBuffers.empty()) { + if (mAskToStop) { + break; + } else { + mReleaseCond.wait(mLock); + continue; + } + } + MediaBuffer* pBuffer = mReleaseBuffers.itemAt(0); + mReleaseBuffers.removeAt(0); + mLock.unlock(); + pBuffer->release(); + mLock.lock(); + } + + mReleaseStopped = true; + mUserCond.signal(); + mLock.unlock(); +} + +}; // namespace android diff --git a/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.h b/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.h new file mode 100644 index 0000000..ed72a53 --- /dev/null +++ b/libvideoeditor/vss/stagefrightshells/src/MediaBufferPuller.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 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. + */ + +#ifndef _MEDIA_BUFFER_PULLER_H +#define _MEDIA_BUFFER_PULLER_H + +#include +#include + + +namespace android { + +struct MediaSource; +struct MediaBuffer; + +/* + * An object of this class can pull a list of media buffers + * from a MediaSource repeatedly. The user can then get the + * buffers from that list. + */ +struct MediaBufferPuller { +public: + MediaBufferPuller(const sp& source); + ~MediaBufferPuller(); + + // Start to build up the list of the buffers. + void start(); + + // Release the list of the available buffers, and stop + // pulling buffers from the MediaSource. + void stop(); + + // Get a buffer from the list. If there is no buffer available + // at the time this method is called, NULL is returned. + MediaBuffer* getBufferBlocking(); + + // Get a buffer from the list. If there is no buffer available + // at the time this method is called, it blocks waiting for + // a buffer to become available or until stop() is called. + MediaBuffer* getBufferNonBlocking(); + + // Add a buffer to the end of the list available media buffers + void putBuffer(MediaBuffer* buffer); + + // Check whether the source returned an error or not. + bool hasMediaSourceReturnedError() const; + +private: + static int acquireThreadStart(void* arg); + void acquireThreadFunc(); + + static int releaseThreadStart(void* arg); + void releaseThreadFunc(); + + sp mSource; + Vector mBuffers; + Vector mReleaseBuffers; + + mutable Mutex mLock; + Condition mUserCond; // for the user of this class + Condition mAcquireCond; // for the acquire thread + Condition mReleaseCond; // for the release thread + + bool mAskToStart; // Asks the threads to start + bool mAskToStop; // Asks the threads to stop + bool mAcquireStopped; // The acquire thread has stopped + bool mReleaseStopped; // The release thread has stopped + status_t mSourceError; // Error returned by MediaSource read + + // Don't call me! + MediaBufferPuller(const MediaBufferPuller&); + MediaBufferPuller& operator=(const MediaBufferPuller&); +}; + +} // namespace android + +#endif // _MEDIA_BUFFER_PULLER_H diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp index 9311e94..4787680 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp @@ -29,8 +29,10 @@ #include "M4SYS_AccessUnit.h" #include "VideoEditorVideoEncoder.h" #include "VideoEditorUtils.h" +#include "MediaBufferPuller.h" #include +#include #include "utils/Log.h" #include "utils/Vector.h" #include @@ -248,194 +250,6 @@ int32_t VideoEditorVideoEncoderSource::getNumberOfBuffersInQueue() { Mutex::Autolock autolock(mLock); return mNbBuffer; } -/******************** - * PULLER * - ********************/ - -// Pulls media buffers from a MediaSource repeatedly. -// The user can then get the buffers from that list. -class VideoEditorVideoEncoderPuller { -public: - VideoEditorVideoEncoderPuller(sp source); - ~VideoEditorVideoEncoderPuller(); - void start(); - void stop(); - MediaBuffer* getBufferBlocking(); - MediaBuffer* getBufferNonBlocking(); - void putBuffer(MediaBuffer* buffer); - bool hasMediaSourceReturnedError(); -private: - static int acquireThreadStart(void* arg); - void acquireThreadFunc(); - - static int releaseThreadStart(void* arg); - void releaseThreadFunc(); - - sp mSource; - Vector mBuffers; - Vector mReleaseBuffers; - - Mutex mLock; - Condition mUserCond; // for the user of this class - Condition mAcquireCond; // for the acquire thread - Condition mReleaseCond; // for the release thread - - bool mAskToStart; // Asks the threads to start - bool mAskToStop; // Asks the threads to stop - bool mAcquireStopped; // The acquire thread has stopped - bool mReleaseStopped; // The release thread has stopped - status_t mSourceError; // Error returned by MediaSource read -}; - -VideoEditorVideoEncoderPuller::VideoEditorVideoEncoderPuller( - sp source) { - mSource = source; - mAskToStart = false; - mAskToStop = false; - mAcquireStopped = false; - mReleaseStopped = false; - mSourceError = OK; - androidCreateThread(acquireThreadStart, this); - androidCreateThread(releaseThreadStart, this); -} - -VideoEditorVideoEncoderPuller::~VideoEditorVideoEncoderPuller() { - stop(); -} - -bool VideoEditorVideoEncoderPuller::hasMediaSourceReturnedError() { - Mutex::Autolock autolock(mLock); - return ((mSourceError != OK) ? true : false); -} -void VideoEditorVideoEncoderPuller::start() { - Mutex::Autolock autolock(mLock); - mAskToStart = true; - mAcquireCond.signal(); - mReleaseCond.signal(); -} - -void VideoEditorVideoEncoderPuller::stop() { - Mutex::Autolock autolock(mLock); - mAskToStop = true; - mAcquireCond.signal(); - mReleaseCond.signal(); - while (!mAcquireStopped || !mReleaseStopped) { - mUserCond.wait(mLock); - } - - // Release remaining buffers - for (size_t i = 0; i < mBuffers.size(); i++) { - mBuffers.itemAt(i)->release(); - } - - for (size_t i = 0; i < mReleaseBuffers.size(); i++) { - mReleaseBuffers.itemAt(i)->release(); - } - - mBuffers.clear(); - mReleaseBuffers.clear(); -} - -MediaBuffer* VideoEditorVideoEncoderPuller::getBufferNonBlocking() { - Mutex::Autolock autolock(mLock); - if (mBuffers.empty()) { - return NULL; - } else { - MediaBuffer* b = mBuffers.itemAt(0); - mBuffers.removeAt(0); - return b; - } -} - -MediaBuffer* VideoEditorVideoEncoderPuller::getBufferBlocking() { - Mutex::Autolock autolock(mLock); - while (mBuffers.empty() && !mAcquireStopped) { - mUserCond.wait(mLock); - } - - if (mBuffers.empty()) { - return NULL; - } else { - MediaBuffer* b = mBuffers.itemAt(0); - mBuffers.removeAt(0); - return b; - } -} - -void VideoEditorVideoEncoderPuller::putBuffer(MediaBuffer* buffer) { - Mutex::Autolock autolock(mLock); - mReleaseBuffers.push(buffer); - mReleaseCond.signal(); -} - -int VideoEditorVideoEncoderPuller::acquireThreadStart(void* arg) { - VideoEditorVideoEncoderPuller* self = (VideoEditorVideoEncoderPuller*)arg; - self->acquireThreadFunc(); - return 0; -} - -int VideoEditorVideoEncoderPuller::releaseThreadStart(void* arg) { - VideoEditorVideoEncoderPuller* self = (VideoEditorVideoEncoderPuller*)arg; - self->releaseThreadFunc(); - return 0; -} - -void VideoEditorVideoEncoderPuller::acquireThreadFunc() { - mLock.lock(); - - // Wait for the start signal - while (!mAskToStart && !mAskToStop) { - mAcquireCond.wait(mLock); - } - - // Loop until we are asked to stop, or there is nothing more to read - while (!mAskToStop) { - MediaBuffer* pBuffer; - mLock.unlock(); - status_t result = mSource->read(&pBuffer, NULL); - mLock.lock(); - mSourceError = result; - if (result != OK) { - break; - } - mBuffers.push(pBuffer); - mUserCond.signal(); - } - - mAcquireStopped = true; - mUserCond.signal(); - mLock.unlock(); -} - -void VideoEditorVideoEncoderPuller::releaseThreadFunc() { - mLock.lock(); - - // Wait for the start signal - while (!mAskToStart && !mAskToStop) { - mReleaseCond.wait(mLock); - } - - // Loop until we are asked to stop - while (1) { - if (mReleaseBuffers.empty()) { - if (mAskToStop) { - break; - } else { - mReleaseCond.wait(mLock); - continue; - } - } - MediaBuffer* pBuffer = mReleaseBuffers.itemAt(0); - mReleaseBuffers.removeAt(0); - mLock.unlock(); - pBuffer->release(); - mLock.lock(); - } - - mReleaseStopped = true; - mUserCond.signal(); - mLock.unlock(); -} /** ****************************************************************************** @@ -468,7 +282,7 @@ typedef struct { OMXClient mClient; sp mEncoder; OMX_COLOR_FORMATTYPE mEncoderColorFormat; - VideoEditorVideoEncoderPuller* mPuller; + MediaBufferPuller* mPuller; I420ColorConverter* mI420ColorConverter; uint32_t mNbInputFrames; @@ -902,7 +716,7 @@ M4OSA_ERR VideoEditorVideoEncoder_open(M4ENCODER_Context pContext, pEncoderContext->mEncoderSource, NULL, codecFlags); VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE); ALOGV("VideoEditorVideoEncoder_open : DONE"); - pEncoderContext->mPuller = new VideoEditorVideoEncoderPuller( + pEncoderContext->mPuller = new MediaBufferPuller( pEncoderContext->mEncoder); // Set the new state -- cgit v1.1