include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ MediaBufferPuller.cpp \
VideoEditorVideoDecoder.cpp \
VideoEditorAudioDecoder.cpp \
VideoEditorMp3Reader.cpp \
--- /dev/null
+/*
+ * 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 <utils/Log.h>
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include "MediaBufferPuller.h"
+
+namespace android {
+
+
+MediaBufferPuller::MediaBufferPuller(const sp<MediaSource>& 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
--- /dev/null
+/*
+ * 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 <utils/threads.h>
+#include <utils/Vector.h>
+
+
+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<MediaSource>& 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<MediaSource> mSource;
+ Vector<MediaBuffer*> mBuffers;
+ Vector<MediaBuffer*> 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
#include "M4SYS_AccessUnit.h"
#include "VideoEditorVideoEncoder.h"
#include "VideoEditorUtils.h"
+#include "MediaBufferPuller.h"
#include <I420ColorConverter.h>
+#include <unistd.h>
#include "utils/Log.h"
#include "utils/Vector.h"
#include <media/stagefright/foundation/ADebug.h>
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<MediaSource> 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<MediaSource> mSource;
- Vector<MediaBuffer*> mBuffers;
- Vector<MediaBuffer*> 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<MediaSource> 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();
-}
/**
******************************************************************************
OMXClient mClient;
sp<MediaSource> mEncoder;
OMX_COLOR_FORMATTYPE mEncoderColorFormat;
- VideoEditorVideoEncoderPuller* mPuller;
+ MediaBufferPuller* mPuller;
I420ColorConverter* mI420ColorConverter;
uint32_t mNbInputFrames;
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