Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75dd1750 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Refactored MediaBufferPuller class from VideoEditorVideoEncoder class"

parents 18f1ff3f 427e3808
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    MediaBufferPuller.cpp \
    VideoEditorVideoDecoder.cpp \
    VideoEditorAudioDecoder.cpp \
    VideoEditorMp3Reader.cpp \
+179 −0
Original line number Diff line number Diff line
/*
 * 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
+90 −0
Original line number Diff line number Diff line
/*
 * 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
+4 −190
Original line number Diff line number Diff line
@@ -29,8 +29,10 @@
#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>
@@ -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<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();
}

/**
 ******************************************************************************
@@ -468,7 +282,7 @@ typedef struct {
    OMXClient                         mClient;
    sp<MediaSource>                   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