summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/source/RepeaterSource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/wifi-display/source/RepeaterSource.cpp')
-rw-r--r--media/libstagefright/wifi-display/source/RepeaterSource.cpp196
1 files changed, 196 insertions, 0 deletions
diff --git a/media/libstagefright/wifi-display/source/RepeaterSource.cpp b/media/libstagefright/wifi-display/source/RepeaterSource.cpp
new file mode 100644
index 0000000..641e63f
--- /dev/null
+++ b/media/libstagefright/wifi-display/source/RepeaterSource.cpp
@@ -0,0 +1,196 @@
+//#define LOG_NDEBUG 0
+#define LOG_TAG "RepeaterSource"
+#include <utils/Log.h>
+
+#include "RepeaterSource.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+RepeaterSource::RepeaterSource(const sp<MediaSource> &source, double rateHz)
+ : mStarted(false),
+ mSource(source),
+ mRateHz(rateHz),
+ mBuffer(NULL),
+ mResult(OK),
+ mLastBufferUpdateUs(-1ll),
+ mStartTimeUs(-1ll),
+ mFrameCount(0) {
+}
+
+RepeaterSource::~RepeaterSource() {
+ CHECK(!mStarted);
+}
+
+status_t RepeaterSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ status_t err = mSource->start(params);
+
+ if (err != OK) {
+ return err;
+ }
+
+ mBuffer = NULL;
+ mResult = OK;
+ mStartTimeUs = -1ll;
+ mFrameCount = 0;
+
+ mLooper = new ALooper;
+ mLooper->setName("repeater_looper");
+ mLooper->start();
+
+ mReflector = new AHandlerReflector<RepeaterSource>(this);
+ mLooper->registerHandler(mReflector);
+
+ postRead();
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t RepeaterSource::stop() {
+ CHECK(mStarted);
+
+ ALOGV("stopping");
+
+ if (mLooper != NULL) {
+ mLooper->stop();
+ mLooper.clear();
+
+ mReflector.clear();
+ }
+
+ if (mBuffer != NULL) {
+ ALOGV("releasing mbuf %p", mBuffer);
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+
+ status_t err = mSource->stop();
+
+ ALOGV("stopped");
+
+ mStarted = false;
+
+ return err;
+}
+
+sp<MetaData> RepeaterSource::getFormat() {
+ return mSource->getFormat();
+}
+
+status_t RepeaterSource::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &seekMode));
+
+ for (;;) {
+ int64_t bufferTimeUs = -1ll;
+
+ if (mStartTimeUs < 0ll) {
+ Mutex::Autolock autoLock(mLock);
+ while ((mLastBufferUpdateUs < 0ll || mBuffer == NULL)
+ && mResult == OK) {
+ mCondition.wait(mLock);
+ }
+
+ ALOGV("now resuming.");
+ mStartTimeUs = ALooper::GetNowUs();
+ bufferTimeUs = mStartTimeUs;
+ } else {
+ bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz;
+
+ int64_t nowUs = ALooper::GetNowUs();
+ int64_t delayUs = bufferTimeUs - nowUs;
+
+ if (delayUs > 0ll) {
+ usleep(delayUs);
+ }
+ }
+
+ bool stale = false;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (mResult != OK) {
+ CHECK(mBuffer == NULL);
+ return mResult;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ if (nowUs - mLastBufferUpdateUs > 1000000ll) {
+ mLastBufferUpdateUs = -1ll;
+ stale = true;
+ } else {
+ mBuffer->add_ref();
+ *buffer = mBuffer;
+ (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs);
+ ++mFrameCount;
+ }
+ }
+
+ if (!stale) {
+ break;
+ }
+
+ mStartTimeUs = -1ll;
+ mFrameCount = 0;
+ ALOGV("now dormant");
+ }
+
+ return OK;
+}
+
+void RepeaterSource::postRead() {
+ (new AMessage(kWhatRead, mReflector->id()))->post();
+}
+
+void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatRead:
+ {
+ MediaBuffer *buffer;
+ status_t err = mSource->read(&buffer);
+
+ ALOGV("read mbuf %p", buffer);
+
+ Mutex::Autolock autoLock(mLock);
+ if (mBuffer != NULL) {
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+ mBuffer = buffer;
+ mResult = err;
+ mLastBufferUpdateUs = ALooper::GetNowUs();
+
+ mCondition.broadcast();
+
+ if (err == OK) {
+ postRead();
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void RepeaterSource::wakeUp() {
+ ALOGV("wakeUp");
+ Mutex::Autolock autoLock(mLock);
+ if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) {
+ mLastBufferUpdateUs = ALooper::GetNowUs();
+ mCondition.broadcast();
+ }
+}
+
+} // namespace android