summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MediaSync.cpp
diff options
context:
space:
mode:
authorWei Jia <wjia@google.com>2015-05-07 18:08:27 -0700
committerWei Jia <wjia@google.com>2015-05-11 12:50:00 -0700
commitb6ea1292f8adae45d95c6f37d50c96534219b6d2 (patch)
tree6e7bb052c951853364226209bf4b3309ff542831 /media/libstagefright/MediaSync.cpp
parentd975e98aac096b8b0ed600f39c18630ba234ef7d (diff)
downloadframeworks_av-b6ea1292f8adae45d95c6f37d50c96534219b6d2.zip
frameworks_av-b6ea1292f8adae45d95c6f37d50c96534219b6d2.tar.gz
frameworks_av-b6ea1292f8adae45d95c6f37d50c96534219b6d2.tar.bz2
MediaSync: support changing surface on the fly.
Bug: 19666434 Change-Id: I5809df2d3bb0dd6b4a982f11d62c4b7a452ed6fb
Diffstat (limited to 'media/libstagefright/MediaSync.cpp')
-rw-r--r--media/libstagefright/MediaSync.cpp70
1 files changed, 57 insertions, 13 deletions
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index 97264fb..b402e48 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -49,6 +49,7 @@ MediaSync::MediaSync()
mMutex(),
mReleaseCondition(),
mNumOutstandingBuffers(0),
+ mUsageFlagsFromOutput(0),
mNativeSampleRateInHz(0),
mNumFramesWritten(0),
mHasAudio(false),
@@ -82,10 +83,8 @@ MediaSync::~MediaSync() {
status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
Mutex::Autolock lock(mMutex);
- // TODO: support suface change.
- if (mOutput != NULL) {
- ALOGE("setSurface: output surface has already been configured.");
- return INVALID_OPERATION;
+ if (output == mOutput) {
+ return NO_ERROR; // same output surface.
}
if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
@@ -94,8 +93,24 @@ status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
}
if (output != NULL) {
+ int newUsage = 0;
+ output->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &newUsage);
+
+ // Check usage flags only when current output surface has been used to create input surface.
+ if (mOutput != NULL && mInput != NULL) {
+ int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER
+ | GRALLOC_USAGE_EXTERNAL_DISP);
+ // New output surface is not allowed to add new usage flag except ignored ones.
+ if ((newUsage & ~(mUsageFlagsFromOutput | ignoredFlags)) != 0) {
+ ALOGE("setSurface: new output surface has new usage flag not used by current one.");
+ return BAD_VALUE;
+ }
+ }
+
+ // Try to connect to new output surface. If failed, current output surface will not
+ // be changed.
IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
- sp<OutputListener> listener(new OutputListener(this));
+ sp<OutputListener> listener(new OutputListener(this, output));
IInterface::asBinder(output)->linkToDeath(listener);
status_t status =
output->connect(listener,
@@ -106,10 +121,18 @@ status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
ALOGE("setSurface: failed to connect (%d)", status);
return status;
}
+ }
- mOutput = output;
+ if (mOutput != NULL) {
+ mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
+ while (!mBuffersSentToOutput.isEmpty()) {
+ returnBufferToInput_l(mBuffersSentToOutput.valueAt(0), Fence::NO_FENCE);
+ mBuffersSentToOutput.removeItemsAt(0);
+ }
}
+ mOutput = output;
+
return NO_ERROR;
}
@@ -181,9 +204,9 @@ status_t MediaSync::createInputSurface(
if (status == NO_ERROR) {
bufferConsumer->setConsumerName(String8("MediaSync"));
// propagate usage bits from output surface
- int usage = 0;
- mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
- bufferConsumer->setConsumerUsageBits(usage);
+ mUsageFlagsFromOutput = 0;
+ mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mUsageFlagsFromOutput);
+ bufferConsumer->setConsumerUsageBits(mUsageFlagsFromOutput);
*outBufferProducer = bufferProducer;
mInput = bufferConsumer;
}
@@ -602,12 +625,24 @@ void MediaSync::renderOneBufferItem_l( const BufferItem &bufferItem) {
return;
}
+ if (mBuffersSentToOutput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
+ // Something is wrong since this buffer should be held by output now, bail.
+ mInput->consumerDisconnect();
+ onAbandoned_l(true /* isInput */);
+ return;
+ }
+ mBuffersSentToOutput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
+
ALOGV("queued buffer %#llx to output", (long long)bufferItem.mGraphicBuffer->getId());
}
-void MediaSync::onBufferReleasedByOutput() {
+void MediaSync::onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output) {
Mutex::Autolock lock(mMutex);
+ if (output != mOutput) {
+ return; // This is not the current output, ignore.
+ }
+
sp<GraphicBuffer> buffer;
sp<Fence> fence;
status_t status = mOutput->detachNextBuffer(&buffer, &fence);
@@ -628,6 +663,13 @@ void MediaSync::onBufferReleasedByOutput() {
return;
}
+ ssize_t ix = mBuffersSentToOutput.indexOfKey(buffer->getId());
+ if (ix < 0) {
+ // The buffer is unknown, maybe leftover, ignore.
+ return;
+ }
+ mBuffersSentToOutput.removeItemsAt(ix);
+
returnBufferToInput_l(buffer, fence);
}
@@ -727,13 +769,15 @@ void MediaSync::InputListener::binderDied(const wp<IBinder> &/* who */) {
mSync->onAbandoned_l(true /* isInput */);
}
-MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync)
- : mSync(sync) {}
+MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync,
+ const sp<IGraphicBufferProducer> &output)
+ : mSync(sync),
+ mOutput(output) {}
MediaSync::OutputListener::~OutputListener() {}
void MediaSync::OutputListener::onBufferReleased() {
- mSync->onBufferReleasedByOutput();
+ mSync->onBufferReleasedByOutput(mOutput);
}
void MediaSync::OutputListener::binderDied(const wp<IBinder> &/* who */) {