blob: 0345de659d95ae9928a9926ce495be961fdb1abe [file] [log] [blame]
Pannag Sanketi3399b722011-06-10 18:30:30 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Pannag Sanketi7dc9b302011-09-08 14:15:00 -070016//#define LOG_NDEBUG 0
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070017#define LOG_TAG "SurfaceMediaSource"
Pannag Sanketi3399b722011-06-10 18:30:30 -070018
James Dongf1d5aa12012-02-06 23:46:37 -080019#include <media/stagefright/foundation/ADebug.h>
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070020#include <media/stagefright/SurfaceMediaSource.h>
Pannag Sanketi3399b722011-06-10 18:30:30 -070021#include <media/stagefright/MediaDefs.h>
Andreas Huberb62f9512012-09-12 12:08:55 -070022#include <media/stagefright/MetaData.h>
James Dong6c6b4d02012-03-12 14:37:53 -070023#include <OMX_IVCommon.h>
24#include <MetadataBufferType.h>
Pannag Sanketi3399b722011-06-10 18:30:30 -070025
James Dongf1d5aa12012-02-06 23:46:37 -080026#include <ui/GraphicBuffer.h>
Mathias Agopiandf712ea2012-02-25 18:48:35 -080027#include <gui/ISurfaceComposer.h>
28#include <gui/IGraphicBufferAlloc.h>
Pannag Sanketi3399b722011-06-10 18:30:30 -070029#include <OMX_Component.h>
30
31#include <utils/Log.h>
32#include <utils/String8.h>
33
Mathias Agopian404a1232011-11-17 17:48:35 -080034#include <private/gui/ComposerService.h>
35
Pannag Sanketi3399b722011-06-10 18:30:30 -070036namespace android {
37
Daniel Lambdddc652012-03-30 16:04:43 -070038SurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight) :
39 mWidth(bufferWidth),
40 mHeight(bufferHeight),
41 mCurrentSlot(BufferQueue::INVALID_BUFFER_SLOT),
Andreas Huberb62f9512012-09-12 12:08:55 -070042 mNumPendingBuffers(0),
Daniel Lambdddc652012-03-30 16:04:43 -070043 mCurrentTimestamp(0),
44 mFrameRate(30),
Andreas Hubera54dee42012-10-01 11:22:05 -070045 mStarted(false),
Daniel Lambdddc652012-03-30 16:04:43 -070046 mNumFramesReceived(0),
47 mNumFramesEncoded(0),
Andreas Huberb62f9512012-09-12 12:08:55 -070048 mFirstFrameTimestamp(0),
Andreas Huber90689fd2012-10-01 15:59:54 -070049 mMaxAcquiredBufferCount(4), // XXX double-check the default
50 mUseAbsoluteTimestamps(false) {
Jamie Gennisa0ead0a2012-08-23 20:24:09 -070051 ALOGV("SurfaceMediaSource");
Daniel Lambdddc652012-03-30 16:04:43 -070052
53 if (bufferWidth == 0 || bufferHeight == 0) {
54 ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight);
55 }
56
James Dong56fc8fb2012-08-23 09:23:07 -070057 mBufferQueue = new BufferQueue(true);
Daniel Lambdddc652012-03-30 16:04:43 -070058 mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight);
59 mBufferQueue->setSynchronousMode(true);
Eino-Ville Talvala8add6cf2012-04-13 16:06:16 -070060 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
61 GRALLOC_USAGE_HW_TEXTURE);
Daniel Lambdddc652012-03-30 16:04:43 -070062
Pannag Sanketi3399b722011-06-10 18:30:30 -070063 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
Daniel Lambdddc652012-03-30 16:04:43 -070064
65 // Note that we can't create an sp<...>(this) in a ctor that will not keep a
66 // reference once the ctor ends, as that would cause the refcount of 'this'
67 // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
68 // that's what we create.
69 wp<BufferQueue::ConsumerListener> listener;
70 sp<BufferQueue::ConsumerListener> proxy;
71 listener = static_cast<BufferQueue::ConsumerListener*>(this);
72 proxy = new BufferQueue::ProxyConsumerListener(listener);
73
74 status_t err = mBufferQueue->consumerConnect(proxy);
75 if (err != NO_ERROR) {
76 ALOGE("SurfaceMediaSource: error connecting to BufferQueue: %s (%d)",
77 strerror(-err), err);
Daniel Lamabf06102012-02-23 14:35:13 -080078 }
Pannag Sanketi3399b722011-06-10 18:30:30 -070079}
80
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070081SurfaceMediaSource::~SurfaceMediaSource() {
Jamie Gennisa0ead0a2012-08-23 20:24:09 -070082 ALOGV("~SurfaceMediaSource");
Andreas Hubera54dee42012-10-01 11:22:05 -070083 CHECK(!mStarted);
Pannag Sanketi3399b722011-06-10 18:30:30 -070084}
85
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070086nsecs_t SurfaceMediaSource::getTimestamp() {
Jamie Gennisa0ead0a2012-08-23 20:24:09 -070087 ALOGV("getTimestamp");
Pannag Sanketi3399b722011-06-10 18:30:30 -070088 Mutex::Autolock lock(mMutex);
89 return mCurrentTimestamp;
90}
91
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070092void SurfaceMediaSource::setFrameAvailableListener(
Pannag Sanketi3399b722011-06-10 18:30:30 -070093 const sp<FrameAvailableListener>& listener) {
Jamie Gennisa0ead0a2012-08-23 20:24:09 -070094 ALOGV("setFrameAvailableListener");
Pannag Sanketi3399b722011-06-10 18:30:30 -070095 Mutex::Autolock lock(mMutex);
96 mFrameAvailableListener = listener;
97}
98
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -070099void SurfaceMediaSource::dump(String8& result) const
Pannag Sanketi3399b722011-06-10 18:30:30 -0700100{
101 char buffer[1024];
102 dump(result, "", buffer, 1024);
103}
104
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -0700105void SurfaceMediaSource::dump(String8& result, const char* prefix,
Pannag Sanketi3399b722011-06-10 18:30:30 -0700106 char* buffer, size_t SIZE) const
107{
Daniel Lambdddc652012-03-30 16:04:43 -0700108 Mutex::Autolock lock(mMutex);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700109
110 result.append(buffer);
Daniel Lambdddc652012-03-30 16:04:43 -0700111 mBufferQueue->dump(result);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700112}
113
Pannag Sanketib33f3402011-07-01 17:39:39 -0700114status_t SurfaceMediaSource::setFrameRate(int32_t fps)
Pannag Sanketi3399b722011-06-10 18:30:30 -0700115{
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700116 ALOGV("setFrameRate");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700117 Mutex::Autolock lock(mMutex);
Pannag Sanketib33f3402011-07-01 17:39:39 -0700118 const int MAX_FRAME_RATE = 60;
119 if (fps < 0 || fps > MAX_FRAME_RATE) {
120 return BAD_VALUE;
121 }
Pannag Sanketi3399b722011-06-10 18:30:30 -0700122 mFrameRate = fps;
Pannag Sanketib33f3402011-07-01 17:39:39 -0700123 return OK;
Pannag Sanketi3399b722011-06-10 18:30:30 -0700124}
125
Pannag Sanketib33f3402011-07-01 17:39:39 -0700126bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
Steve Block3856b092011-10-20 11:56:00 +0100127 ALOGV("isMetaDataStoredInVideoBuffers");
Pannag Sanketib33f3402011-07-01 17:39:39 -0700128 return true;
129}
130
131int32_t SurfaceMediaSource::getFrameRate( ) const {
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700132 ALOGV("getFrameRate");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700133 Mutex::Autolock lock(mMutex);
134 return mFrameRate;
135}
136
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -0700137status_t SurfaceMediaSource::start(MetaData *params)
Pannag Sanketi3399b722011-06-10 18:30:30 -0700138{
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700139 ALOGV("start");
Eino-Ville Talvaladf4a59c2011-08-29 18:16:03 -0700140
James Dong56fc8fb2012-08-23 09:23:07 -0700141 Mutex::Autolock lock(mMutex);
142
Andreas Hubera54dee42012-10-01 11:22:05 -0700143 CHECK(!mStarted);
144
Eino-Ville Talvaladf4a59c2011-08-29 18:16:03 -0700145 mStartTimeNs = 0;
146 int64_t startTimeUs;
James Dong56fc8fb2012-08-23 09:23:07 -0700147 int32_t bufferCount = 0;
148 if (params) {
149 if (params->findInt64(kKeyTime, &startTimeUs)) {
150 mStartTimeNs = startTimeUs * 1000;
151 }
152
153 if (!params->findInt32(kKeyNumBuffers, &bufferCount)) {
154 ALOGE("Failed to find the advertised buffer count");
155 return UNKNOWN_ERROR;
156 }
157
158 if (bufferCount <= 1) {
159 ALOGE("bufferCount %d is too small", bufferCount);
160 return BAD_VALUE;
161 }
Andreas Huberb62f9512012-09-12 12:08:55 -0700162
163 mMaxAcquiredBufferCount = bufferCount;
James Dong56fc8fb2012-08-23 09:23:07 -0700164 }
165
Andreas Huberb62f9512012-09-12 12:08:55 -0700166 CHECK_GT(mMaxAcquiredBufferCount, 1);
167
168 status_t err =
169 mBufferQueue->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount);
170
171 if (err != OK) {
172 return err;
Eino-Ville Talvaladf4a59c2011-08-29 18:16:03 -0700173 }
174
Andreas Huberb62f9512012-09-12 12:08:55 -0700175 mNumPendingBuffers = 0;
Andreas Hubera54dee42012-10-01 11:22:05 -0700176 mStarted = true;
Andreas Huberb62f9512012-09-12 12:08:55 -0700177
Pannag Sanketi3399b722011-06-10 18:30:30 -0700178 return OK;
179}
180
Andreas Huber7f066392012-09-04 16:30:49 -0700181status_t SurfaceMediaSource::setMaxAcquiredBufferCount(size_t count) {
Andreas Huberb62f9512012-09-12 12:08:55 -0700182 ALOGV("setMaxAcquiredBufferCount(%d)", count);
183 Mutex::Autolock lock(mMutex);
184
185 CHECK_GT(count, 1);
186 mMaxAcquiredBufferCount = count;
187
188 return OK;
Andreas Huber7f066392012-09-04 16:30:49 -0700189}
190
Andreas Huber90689fd2012-10-01 15:59:54 -0700191status_t SurfaceMediaSource::setUseAbsoluteTimestamps() {
192 ALOGV("setUseAbsoluteTimestamps");
193 Mutex::Autolock lock(mMutex);
194 mUseAbsoluteTimestamps = true;
195
196 return OK;
197}
Pannag Sanketi3399b722011-06-10 18:30:30 -0700198
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700199status_t SurfaceMediaSource::stop()
Pannag Sanketi3399b722011-06-10 18:30:30 -0700200{
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700201 ALOGV("stop");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700202 Mutex::Autolock lock(mMutex);
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700203
Andreas Hubera54dee42012-10-01 11:22:05 -0700204 if (!mStarted) {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700205 return OK;
206 }
207
208 while (mNumPendingBuffers > 0) {
209 ALOGI("Still waiting for %d buffers to be returned.",
210 mNumPendingBuffers);
211
212#if DEBUG_PENDING_BUFFERS
213 for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
214 ALOGI("%d: %p", i, mPendingBuffers.itemAt(i));
215 }
216#endif
217
218 mMediaBuffersAvailableCondition.wait(mMutex);
219 }
220
Andreas Hubera54dee42012-10-01 11:22:05 -0700221 mStarted = false;
Pannag Sanketi3399b722011-06-10 18:30:30 -0700222 mFrameAvailableCondition.signal();
Andreas Huberbe996642012-09-27 14:13:05 -0700223 mMediaBuffersAvailableCondition.signal();
Pannag Sanketi3399b722011-06-10 18:30:30 -0700224
Jamie Gennisa0ead0a2012-08-23 20:24:09 -0700225 return mBufferQueue->consumerDisconnect();
Pannag Sanketi3399b722011-06-10 18:30:30 -0700226}
227
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -0700228sp<MetaData> SurfaceMediaSource::getFormat()
Pannag Sanketi3399b722011-06-10 18:30:30 -0700229{
Steve Block3856b092011-10-20 11:56:00 +0100230 ALOGV("getFormat");
Daniel Lambdddc652012-03-30 16:04:43 -0700231
232 Mutex::Autolock lock(mMutex);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700233 sp<MetaData> meta = new MetaData;
Pannag Sanketib33f3402011-07-01 17:39:39 -0700234
Daniel Lambdddc652012-03-30 16:04:43 -0700235 meta->setInt32(kKeyWidth, mWidth);
236 meta->setInt32(kKeyHeight, mHeight);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700237 // The encoder format is set as an opaque colorformat
238 // The encoder will later find out the actual colorformat
239 // from the GL Frames itself.
240 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
Daniel Lambdddc652012-03-30 16:04:43 -0700241 meta->setInt32(kKeyStride, mWidth);
242 meta->setInt32(kKeySliceHeight, mHeight);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700243 meta->setInt32(kKeyFrameRate, mFrameRate);
244 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
245 return meta;
246}
247
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700248// Pass the data to the MediaBuffer. Pass in only the metadata
249// The metadata passed consists of two parts:
250// 1. First, there is an integer indicating that it is a GRAlloc
251// source (kMetadataBufferTypeGrallocSource)
252// 2. This is followed by the buffer_handle_t that is a handle to the
253// GRalloc buffer. The encoder needs to interpret this GRalloc handle
254// and encode the frames.
255// --------------------------------------------------------------
256// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
257// --------------------------------------------------------------
258// Note: Call only when you have the lock
259static void passMetadataBuffer(MediaBuffer **buffer,
260 buffer_handle_t bufferHandle) {
Andreas Huberb62f9512012-09-12 12:08:55 -0700261 *buffer = new MediaBuffer(4 + sizeof(buffer_handle_t));
262 char *data = (char *)(*buffer)->data();
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700263 if (data == NULL) {
264 ALOGE("Cannot allocate memory for metadata buffer!");
265 return;
266 }
267 OMX_U32 type = kMetadataBufferTypeGrallocSource;
268 memcpy(data, &type, 4);
269 memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t));
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700270
271 ALOGV("handle = %p, , offset = %d, length = %d",
272 bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset());
273}
274
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -0700275status_t SurfaceMediaSource::read( MediaBuffer **buffer,
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700276 const ReadOptions *options)
Pannag Sanketi3399b722011-06-10 18:30:30 -0700277{
Daniel Lambdddc652012-03-30 16:04:43 -0700278 ALOGV("read");
279 Mutex::Autolock lock(mMutex);
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700280
Pannag Sanketi3399b722011-06-10 18:30:30 -0700281 *buffer = NULL;
282
Andreas Hubera54dee42012-10-01 11:22:05 -0700283 while (mStarted && mNumPendingBuffers == mMaxAcquiredBufferCount) {
Andreas Huberb62f9512012-09-12 12:08:55 -0700284 mMediaBuffersAvailableCondition.wait(mMutex);
285 }
286
Daniel Lambdddc652012-03-30 16:04:43 -0700287 // Update the current buffer info
288 // TODO: mCurrentSlot can be made a bufferstate since there
289 // can be more than one "current" slots.
290
291 BufferQueue::BufferItem item;
Pannag Sanketi3399b722011-06-10 18:30:30 -0700292 // If the recording has started and the queue is empty, then just
293 // wait here till the frames come in from the client side
Andreas Hubera54dee42012-10-01 11:22:05 -0700294 while (mStarted) {
Daniel Lambdddc652012-03-30 16:04:43 -0700295
296 status_t err = mBufferQueue->acquireBuffer(&item);
297 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
298 // wait for a buffer to be queued
299 mFrameAvailableCondition.wait(mMutex);
300 } else if (err == OK) {
Greg Hackmann10174bf2012-12-14 13:49:48 -0800301 err = item.mFence->waitForever(1000, "SurfaceMediaSource::read");
302 if (err) {
303 ALOGW("read: failed to wait for buffer fence: %d", err);
304 }
Daniel Lambdddc652012-03-30 16:04:43 -0700305
306 // First time seeing the buffer? Added it to the SMS slot
307 if (item.mGraphicBuffer != NULL) {
308 mBufferSlot[item.mBuf] = item.mGraphicBuffer;
309 }
310
311 // check for the timing of this buffer
Andreas Huber90689fd2012-10-01 15:59:54 -0700312 if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) {
Daniel Lambdddc652012-03-30 16:04:43 -0700313 mFirstFrameTimestamp = item.mTimestamp;
314 // Initial delay
315 if (mStartTimeNs > 0) {
316 if (item.mTimestamp < mStartTimeNs) {
317 // This frame predates start of record, discard
Jesse Hallf15f6e22012-06-13 14:52:12 -0700318 mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
319 EGL_NO_SYNC_KHR, Fence::NO_FENCE);
Daniel Lambdddc652012-03-30 16:04:43 -0700320 continue;
321 }
322 mStartTimeNs = item.mTimestamp - mStartTimeNs;
323 }
324 }
325 item.mTimestamp = mStartTimeNs + (item.mTimestamp - mFirstFrameTimestamp);
326
327 mNumFramesReceived++;
328
329 break;
330 } else {
331 ALOGE("read: acquire failed with error code %d", err);
332 return ERROR_END_OF_STREAM;
333 }
334
Pannag Sanketi3399b722011-06-10 18:30:30 -0700335 }
336
337 // If the loop was exited as a result of stopping the recording,
338 // it is OK
Andreas Hubera54dee42012-10-01 11:22:05 -0700339 if (!mStarted) {
Steve Block3856b092011-10-20 11:56:00 +0100340 ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
Pannag Sanketi3e9bf402011-09-22 17:03:48 -0700341 return ERROR_END_OF_STREAM;
Pannag Sanketi3399b722011-06-10 18:30:30 -0700342 }
343
Daniel Lambdddc652012-03-30 16:04:43 -0700344 mCurrentSlot = item.mBuf;
345
346 // First time seeing the buffer? Added it to the SMS slot
347 if (item.mGraphicBuffer != NULL) {
348 mBufferSlot[mCurrentSlot] = item.mGraphicBuffer;
349 }
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700350
351 mCurrentBuffers.push_back(mBufferSlot[mCurrentSlot]);
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700352 int64_t prevTimeStamp = mCurrentTimestamp;
Daniel Lambdddc652012-03-30 16:04:43 -0700353 mCurrentTimestamp = item.mTimestamp;
Eino-Ville Talvaladf4a59c2011-08-29 18:16:03 -0700354
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700355 mNumFramesEncoded++;
Pannag Sanketia3614832011-07-14 14:37:47 -0700356 // Pass the data to the MediaBuffer. Pass in only the metadata
Andreas Huberb62f9512012-09-12 12:08:55 -0700357
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700358 passMetadataBuffer(buffer, mBufferSlot[mCurrentSlot]->handle);
Pannag Sanketia3614832011-07-14 14:37:47 -0700359
Pannag Sanketi3399b722011-06-10 18:30:30 -0700360 (*buffer)->setObserver(this);
361 (*buffer)->add_ref();
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700362 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
Steve Block3856b092011-10-20 11:56:00 +0100363 ALOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700364 mNumFramesEncoded, mCurrentTimestamp / 1000,
365 mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700366
Andreas Huberb62f9512012-09-12 12:08:55 -0700367 ++mNumPendingBuffers;
Daniel Lambdddc652012-03-30 16:04:43 -0700368
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700369#if DEBUG_PENDING_BUFFERS
370 mPendingBuffers.push_back(*buffer);
371#endif
372
373 ALOGV("returning mbuf %p", *buffer);
374
Pannag Sanketi3399b722011-06-10 18:30:30 -0700375 return OK;
376}
377
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700378static buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) {
379 // need to convert to char* for pointer arithmetic and then
380 // copy the byte stream into our handle
381 buffer_handle_t bufferHandle;
382 memcpy(&bufferHandle, (char*)(buffer->data()) + 4, sizeof(buffer_handle_t));
383 return bufferHandle;
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700384}
Pannag Sanketia3614832011-07-14 14:37:47 -0700385
Pannag Sanketi1a2fafb2011-06-30 15:30:03 -0700386void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
Steve Block3856b092011-10-20 11:56:00 +0100387 ALOGV("signalBufferReturned");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700388
389 bool foundBuffer = false;
Daniel Lambdddc652012-03-30 16:04:43 -0700390
391 Mutex::Autolock lock(mMutex);
Pannag Sanketi3399b722011-06-10 18:30:30 -0700392
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700393 buffer_handle_t bufferHandle = getMediaBufferHandle(buffer);
394
395 for (size_t i = 0; i < mCurrentBuffers.size(); i++) {
396 if (mCurrentBuffers[i]->handle == bufferHandle) {
397 mCurrentBuffers.removeAt(i);
398 foundBuffer = true;
399 break;
400 }
401 }
402
403 if (!foundBuffer) {
404 ALOGW("returned buffer was not found in the current buffer list");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700405 }
406
Daniel Lambdddc652012-03-30 16:04:43 -0700407 for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
408 if (mBufferSlot[id] == NULL) {
Pannag Sanketi0c5c7d22011-08-18 21:53:02 -0700409 continue;
410 }
Jamie Gennis2cd25a92012-06-22 14:42:00 -0700411
412 if (bufferHandle == mBufferSlot[id]->handle) {
Steve Block3856b092011-10-20 11:56:00 +0100413 ALOGV("Slot %d returned, matches handle = %p", id,
Daniel Lambdddc652012-03-30 16:04:43 -0700414 mBufferSlot[id]->handle);
415
Jesse Hallf15f6e22012-06-13 14:52:12 -0700416 mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
417 Fence::NO_FENCE);
Daniel Lambdddc652012-03-30 16:04:43 -0700418
Pannag Sanketi3399b722011-06-10 18:30:30 -0700419 buffer->setObserver(0);
420 buffer->release();
Daniel Lambdddc652012-03-30 16:04:43 -0700421
Pannag Sanketi3399b722011-06-10 18:30:30 -0700422 foundBuffer = true;
423 break;
424 }
425 }
426
427 if (!foundBuffer) {
James Dongf1d5aa12012-02-06 23:46:37 -0800428 CHECK(!"signalBufferReturned: bogus buffer");
Pannag Sanketi3399b722011-06-10 18:30:30 -0700429 }
Andreas Huberb62f9512012-09-12 12:08:55 -0700430
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700431#if DEBUG_PENDING_BUFFERS
432 for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
433 if (mPendingBuffers.itemAt(i) == buffer) {
434 mPendingBuffers.removeAt(i);
435 break;
436 }
437 }
438#endif
439
Andreas Huberb62f9512012-09-12 12:08:55 -0700440 --mNumPendingBuffers;
441 mMediaBuffersAvailableCondition.broadcast();
Pannag Sanketi3399b722011-06-10 18:30:30 -0700442}
443
Daniel Lambdddc652012-03-30 16:04:43 -0700444// Part of the BufferQueue::ConsumerListener
445void SurfaceMediaSource::onFrameAvailable() {
446 ALOGV("onFrameAvailable");
447
448 sp<FrameAvailableListener> listener;
449 { // scope for the lock
450 Mutex::Autolock lock(mMutex);
451 mFrameAvailableCondition.broadcast();
452 listener = mFrameAvailableListener;
453 }
454
455 if (listener != NULL) {
456 ALOGV("actually calling onFrameAvailable");
457 listener->onFrameAvailable();
458 }
459}
460
461// SurfaceMediaSource hijacks this event to assume
462// the prodcuer is disconnecting from the BufferQueue
463// and that it should stop the recording
464void SurfaceMediaSource::onBuffersReleased() {
465 ALOGV("onBuffersReleased");
466
467 Mutex::Autolock lock(mMutex);
468
469 mFrameAvailableCondition.signal();
Daniel Lambdddc652012-03-30 16:04:43 -0700470
471 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
472 mBufferSlot[i] = 0;
473 }
Pannag Sanketia3614832011-07-14 14:37:47 -0700474}
Pannag Sanketi3399b722011-06-10 18:30:30 -0700475
Pannag Sanketi3399b722011-06-10 18:30:30 -0700476} // end of namespace android