blob: 602469b0000b2aeb697decfa64fb94fed4ccd4c0 [file] [log] [blame]
Pannag Sanketi26a19712011-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 Sanketie46fcef2011-09-08 14:15:00 -070016//#define LOG_NDEBUG 0
Pannag Sanketif48987d2011-06-30 15:30:03 -070017#define LOG_TAG "SurfaceMediaSource"
Pannag Sanketi26a19712011-06-10 18:30:30 -070018
James Dong8e9d67a2012-02-06 23:46:37 -080019#include <media/stagefright/foundation/ADebug.h>
Pannag Sanketif48987d2011-06-30 15:30:03 -070020#include <media/stagefright/SurfaceMediaSource.h>
Pannag Sanketi26a19712011-06-10 18:30:30 -070021#include <media/stagefright/MetaData.h>
22#include <media/stagefright/MediaDefs.h>
James Donge1dea482012-03-12 14:37:53 -070023#include <OMX_IVCommon.h>
24#include <MetadataBufferType.h>
Pannag Sanketi26a19712011-06-10 18:30:30 -070025
James Dong8e9d67a2012-02-06 23:46:37 -080026#include <ui/GraphicBuffer.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080027#include <gui/ISurfaceComposer.h>
28#include <gui/IGraphicBufferAlloc.h>
Pannag Sanketi26a19712011-06-10 18:30:30 -070029#include <OMX_Component.h>
30
31#include <utils/Log.h>
32#include <utils/String8.h>
33
Mathias Agopian3f157002011-11-17 17:48:35 -080034#include <private/gui/ComposerService.h>
35
Pannag Sanketi26a19712011-06-10 18:30:30 -070036namespace android {
37
Pannag Sanketif48987d2011-06-30 15:30:03 -070038SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
Pannag Sanketi897e27b2011-07-01 17:39:39 -070039 mDefaultWidth(bufW),
40 mDefaultHeight(bufH),
41 mPixelFormat(0),
42 mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
43 mClientBufferCount(0),
44 mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
45 mCurrentSlot(INVALID_BUFFER_SLOT),
46 mCurrentTimestamp(0),
47 mSynchronousMode(true),
48 mConnectedApi(NO_CONNECTED_API),
49 mFrameRate(30),
Eino-Ville Talvala728e08bc2011-08-29 18:16:03 -070050 mStopped(false),
Pannag Sanketi557b7092011-08-18 21:53:02 -070051 mNumFramesReceived(0),
52 mNumFramesEncoded(0),
Eino-Ville Talvala728e08bc2011-08-29 18:16:03 -070053 mFirstFrameTimestamp(0) {
Steve Block71f2cf12011-10-20 11:56:00 +010054 ALOGV("SurfaceMediaSource::SurfaceMediaSource");
Pannag Sanketi26a19712011-06-10 18:30:30 -070055 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
56 mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
57}
58
Pannag Sanketif48987d2011-06-30 15:30:03 -070059SurfaceMediaSource::~SurfaceMediaSource() {
Steve Block71f2cf12011-10-20 11:56:00 +010060 ALOGV("SurfaceMediaSource::~SurfaceMediaSource");
Pannag Sanketi557b7092011-08-18 21:53:02 -070061 if (!mStopped) {
James Dongf5a9f432012-02-04 06:19:50 -080062 reset();
Pannag Sanketi26a19712011-06-10 18:30:30 -070063 }
Pannag Sanketi26a19712011-06-10 18:30:30 -070064}
65
Pannag Sanketif48987d2011-06-30 15:30:03 -070066size_t SurfaceMediaSource::getQueuedCount() const {
Pannag Sanketi26a19712011-06-10 18:30:30 -070067 Mutex::Autolock lock(mMutex);
68 return mQueue.size();
69}
70
Pannag Sanketif48987d2011-06-30 15:30:03 -070071status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) {
Pannag Sanketi26a19712011-06-10 18:30:30 -070072 if (bufferCount > NUM_BUFFER_SLOTS)
73 return BAD_VALUE;
74
75 // special-case, nothing to do
76 if (bufferCount == mBufferCount)
77 return OK;
78
79 if (!mClientBufferCount &&
80 bufferCount >= mBufferCount) {
81 // easy, we just have more buffers
82 mBufferCount = bufferCount;
83 mServerBufferCount = bufferCount;
84 mDequeueCondition.signal();
85 } else {
86 // we're here because we're either
87 // - reducing the number of available buffers
88 // - or there is a client-buffer-count in effect
89
90 // less than 2 buffers is never allowed
91 if (bufferCount < 2)
92 return BAD_VALUE;
93
94 // when there is non client-buffer-count in effect, the client is not
95 // allowed to dequeue more than one buffer at a time,
96 // so the next time they dequeue a buffer, we know that they don't
97 // own one. the actual resizing will happen during the next
98 // dequeueBuffer.
99
100 mServerBufferCount = bufferCount;
101 }
102 return OK;
103}
104
105// Called from the consumer side
Pannag Sanketif48987d2011-06-30 15:30:03 -0700106status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
Pannag Sanketi26a19712011-06-10 18:30:30 -0700107 Mutex::Autolock lock(mMutex);
108 return setBufferCountServerLocked(bufferCount);
109}
110
Pannag Sanketif48987d2011-06-30 15:30:03 -0700111status_t SurfaceMediaSource::setBufferCount(int bufferCount) {
Steve Block71f2cf12011-10-20 11:56:00 +0100112 ALOGV("SurfaceMediaSource::setBufferCount");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700113 if (bufferCount > NUM_BUFFER_SLOTS) {
Steve Block3762c312012-01-06 19:20:56 +0000114 ALOGE("setBufferCount: bufferCount is larger than the number of buffer slots");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700115 return BAD_VALUE;
116 }
117
118 Mutex::Autolock lock(mMutex);
119 // Error out if the user has dequeued buffers
120 for (int i = 0 ; i < mBufferCount ; i++) {
121 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
Steve Block3762c312012-01-06 19:20:56 +0000122 ALOGE("setBufferCount: client owns some buffers");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700123 return INVALID_OPERATION;
124 }
125 }
126
127 if (bufferCount == 0) {
128 const int minBufferSlots = mSynchronousMode ?
129 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
130 mClientBufferCount = 0;
131 bufferCount = (mServerBufferCount >= minBufferSlots) ?
132 mServerBufferCount : minBufferSlots;
133 return setBufferCountServerLocked(bufferCount);
134 }
135
136 // We don't allow the client to set a buffer-count less than
137 // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
138 if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
139 return BAD_VALUE;
140 }
141
142 // here we're guaranteed that the client doesn't have dequeued buffers
143 // and will release all of its buffer references.
Pannag Sanketi26a19712011-06-10 18:30:30 -0700144 mBufferCount = bufferCount;
145 mClientBufferCount = bufferCount;
146 mCurrentSlot = INVALID_BUFFER_SLOT;
147 mQueue.clear();
148 mDequeueCondition.signal();
Pannag Sanketi557b7092011-08-18 21:53:02 -0700149 freeAllBuffersLocked();
Pannag Sanketi26a19712011-06-10 18:30:30 -0700150 return OK;
151}
152
Jamie Gennis5ef59bc2011-07-19 12:08:33 -0700153status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
Steve Block71f2cf12011-10-20 11:56:00 +0100154 ALOGV("SurfaceMediaSource::requestBuffer");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700155 Mutex::Autolock lock(mMutex);
Jamie Gennis5ef59bc2011-07-19 12:08:33 -0700156 if (slot < 0 || mBufferCount <= slot) {
Steve Block3762c312012-01-06 19:20:56 +0000157 ALOGE("requestBuffer: slot index out of range [0, %d]: %d",
Jamie Gennis5ef59bc2011-07-19 12:08:33 -0700158 mBufferCount, slot);
159 return BAD_VALUE;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700160 }
Jamie Gennis5ef59bc2011-07-19 12:08:33 -0700161 mSlots[slot].mRequestBufferCalled = true;
162 *buf = mSlots[slot].mGraphicBuffer;
163 return NO_ERROR;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700164}
165
Pannag Sanketif48987d2011-06-30 15:30:03 -0700166status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
Pannag Sanketi26a19712011-06-10 18:30:30 -0700167 uint32_t format, uint32_t usage) {
Steve Block71f2cf12011-10-20 11:56:00 +0100168 ALOGV("dequeueBuffer");
Pannag Sanketi557b7092011-08-18 21:53:02 -0700169 Mutex::Autolock lock(mMutex);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700170
171 // Check for the buffer size- the client should just use the
172 // default width and height, and not try to set those.
173 // This is needed since
174 // the getFormat() returns mDefaultWidth/ Height for the OMX. It is
175 // queried by OMX in the beginning and not every time a frame comes.
176 // Not sure if there is a way to update the
177 // frame size while recording. So as of now, the client side
178 // sets the default values via the constructor, and the encoder is
179 // setup to encode frames of that size
180 // The design might need to change in the future.
181 // TODO: Currently just uses mDefaultWidth/Height. In the future
182 // we might declare mHeight and mWidth and check against those here.
183 if ((w != 0) || (h != 0)) {
Pannag Sanketi88653072011-08-24 17:39:09 -0700184 if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
Steve Block3762c312012-01-06 19:20:56 +0000185 ALOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
Pannag Sanketi88653072011-08-24 17:39:09 -0700186 mDefaultWidth, mDefaultHeight, w, h);
187 return BAD_VALUE;
188 }
Pannag Sanketi26a19712011-06-10 18:30:30 -0700189 }
190
Pannag Sanketi26a19712011-06-10 18:30:30 -0700191 status_t returnFlags(OK);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700192 int found, foundSync;
193 int dequeuedCount = 0;
194 bool tryAgain = true;
195 while (tryAgain) {
196 // We need to wait for the FIFO to drain if the number of buffer
197 // needs to change.
198 //
199 // The condition "number of buffer needs to change" is true if
200 // - the client doesn't care about how many buffers there are
201 // - AND the actual number of buffer is different from what was
202 // set in the last setBufferCountServer()
203 // - OR -
204 // setBufferCountServer() was set to a value incompatible with
205 // the synchronization mode (for instance because the sync mode
206 // changed since)
207 //
208 // As long as this condition is true AND the FIFO is not empty, we
209 // wait on mDequeueCondition.
210
211 int minBufferCountNeeded = mSynchronousMode ?
212 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
213
214 if (!mClientBufferCount &&
215 ((mServerBufferCount != mBufferCount) ||
216 (mServerBufferCount < minBufferCountNeeded))) {
217 // wait for the FIFO to drain
218 while (!mQueue.isEmpty()) {
Steve Block71f2cf12011-10-20 11:56:00 +0100219 ALOGV("Waiting for the FIFO to drain");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700220 mDequeueCondition.wait(mMutex);
221 }
Pannag Sanketi557b7092011-08-18 21:53:02 -0700222 if (mStopped) {
223 return NO_INIT;
224 }
Pannag Sanketi26a19712011-06-10 18:30:30 -0700225 // need to check again since the mode could have changed
226 // while we were waiting
227 minBufferCountNeeded = mSynchronousMode ?
228 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
229 }
230
231 if (!mClientBufferCount &&
232 ((mServerBufferCount != mBufferCount) ||
233 (mServerBufferCount < minBufferCountNeeded))) {
234 // here we're guaranteed that mQueue is empty
Pannag Sanketi557b7092011-08-18 21:53:02 -0700235 freeAllBuffersLocked();
Pannag Sanketi26a19712011-06-10 18:30:30 -0700236 mBufferCount = mServerBufferCount;
237 if (mBufferCount < minBufferCountNeeded)
238 mBufferCount = minBufferCountNeeded;
239 mCurrentSlot = INVALID_BUFFER_SLOT;
240 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
241 }
242
243 // look for a free buffer to give to the client
244 found = INVALID_BUFFER_SLOT;
245 foundSync = INVALID_BUFFER_SLOT;
246 dequeuedCount = 0;
247 for (int i = 0; i < mBufferCount; i++) {
248 const int state = mSlots[i].mBufferState;
249 if (state == BufferSlot::DEQUEUED) {
250 dequeuedCount++;
251 continue; // won't be continuing if could
252 // dequeue a non 'FREE' current slot like
253 // that in SurfaceTexture
254 }
255 // In case of Encoding, we do not deque the mCurrentSlot buffer
256 // since we follow synchronous mode (unlike possibly in
257 // SurfaceTexture that could be using the asynch mode
258 // or has some mechanism in GL to be able to wait till the
259 // currentslot is done using the data)
260 // Here, we have to wait for the MPEG4Writer(or equiv)
261 // to tell us when it's done using the current buffer
262 if (state == BufferSlot::FREE) {
263 foundSync = i;
264 // Unlike that in SurfaceTexture,
265 // We don't need to worry if it is the
266 // currentslot or not as it is in state FREE
267 found = i;
268 break;
269 }
270 }
271
272 // clients are not allowed to dequeue more than one buffer
273 // if they didn't set a buffer count.
274 if (!mClientBufferCount && dequeuedCount) {
275 return -EINVAL;
276 }
277
278 // See whether a buffer has been queued since the last setBufferCount so
279 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
280 bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
281 if (bufferHasBeenQueued) {
282 // make sure the client is not trying to dequeue more buffers
283 // than allowed.
284 const int avail = mBufferCount - (dequeuedCount+1);
285 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
Steve Block3762c312012-01-06 19:20:56 +0000286 ALOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
Pannag Sanketi26a19712011-06-10 18:30:30 -0700287 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
288 dequeuedCount);
289 return -EBUSY;
290 }
291 }
292
293 // we're in synchronous mode and didn't find a buffer, we need to wait
294 // for for some buffers to be consumed
295 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
296 if (tryAgain) {
Steve Block71f2cf12011-10-20 11:56:00 +0100297 ALOGV("Waiting..In synchronous mode and no buffer to dequeue");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700298 mDequeueCondition.wait(mMutex);
299 }
Pannag Sanketi557b7092011-08-18 21:53:02 -0700300 if (mStopped) {
301 return NO_INIT;
302 }
Pannag Sanketi26a19712011-06-10 18:30:30 -0700303 }
304
305 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
306 // foundSync guaranteed to be != INVALID_BUFFER_SLOT
307 found = foundSync;
308 }
309
310 if (found == INVALID_BUFFER_SLOT) {
311 return -EBUSY;
312 }
313
Pannag Sanketi557b7092011-08-18 21:53:02 -0700314 const int bufIndex = found;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700315 *outBuf = found;
316
317 const bool useDefaultSize = !w && !h;
318 if (useDefaultSize) {
319 // use the default size
320 w = mDefaultWidth;
321 h = mDefaultHeight;
322 }
323
324 const bool updateFormat = (format != 0);
325 if (!updateFormat) {
326 // keep the current (or default) format
327 format = mPixelFormat;
328 }
329
330 // buffer is now in DEQUEUED (but can also be current at the same time,
331 // if we're in synchronous mode)
Pannag Sanketi557b7092011-08-18 21:53:02 -0700332 mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700333
Pannag Sanketi557b7092011-08-18 21:53:02 -0700334 const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700335 if ((buffer == NULL) ||
336 (uint32_t(buffer->width) != w) ||
337 (uint32_t(buffer->height) != h) ||
338 (uint32_t(buffer->format) != format) ||
339 ((uint32_t(buffer->usage) & usage) != usage)) {
Jamie Gennis09fc7662011-12-15 18:14:05 -0800340 // XXX: This will be changed to USAGE_HW_VIDEO_ENCODER once driver
341 // issues with that flag get fixed.
342 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700343 status_t error;
344 sp<GraphicBuffer> graphicBuffer(
345 mGraphicBufferAlloc->createGraphicBuffer(
346 w, h, format, usage, &error));
347 if (graphicBuffer == 0) {
Steve Block3762c312012-01-06 19:20:56 +0000348 ALOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700349 return error;
350 }
351 if (updateFormat) {
352 mPixelFormat = format;
353 }
Pannag Sanketi557b7092011-08-18 21:53:02 -0700354 mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
355 mSlots[bufIndex].mRequestBufferCalled = false;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700356 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
357 }
358 return returnFlags;
359}
360
Pannag Sanketi557b7092011-08-18 21:53:02 -0700361// TODO: clean this up
Pannag Sanketif48987d2011-06-30 15:30:03 -0700362status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
Pannag Sanketi26a19712011-06-10 18:30:30 -0700363 Mutex::Autolock lock(mMutex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700364 if (mStopped) {
Steve Block3762c312012-01-06 19:20:56 +0000365 ALOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
Pannag Sanketi557b7092011-08-18 21:53:02 -0700366 return NO_INIT;
367 }
Pannag Sanketi26a19712011-06-10 18:30:30 -0700368
Pannag Sanketi26a19712011-06-10 18:30:30 -0700369 if (!enabled) {
Pannag Sanketi557b7092011-08-18 21:53:02 -0700370 // Async mode is not allowed
Steve Block3762c312012-01-06 19:20:56 +0000371 ALOGE("SurfaceMediaSource can be used only synchronous mode!");
Pannag Sanketi557b7092011-08-18 21:53:02 -0700372 return INVALID_OPERATION;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700373 }
374
375 if (mSynchronousMode != enabled) {
376 // - if we're going to asynchronous mode, the queue is guaranteed to be
377 // empty here
378 // - if the client set the number of buffers, we're guaranteed that
379 // we have at least 3 (because we don't allow less)
380 mSynchronousMode = enabled;
381 mDequeueCondition.signal();
382 }
Pannag Sanketi557b7092011-08-18 21:53:02 -0700383 return OK;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700384}
385
Mathias Agopian053b02d2011-08-08 19:14:03 -0700386status_t SurfaceMediaSource::connect(int api,
387 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Steve Block71f2cf12011-10-20 11:56:00 +0100388 ALOGV("SurfaceMediaSource::connect");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700389 Mutex::Autolock lock(mMutex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700390
391 if (mStopped) {
Steve Block3762c312012-01-06 19:20:56 +0000392 ALOGE("Connect: SurfaceMediaSource has been stopped!");
Pannag Sanketi557b7092011-08-18 21:53:02 -0700393 return NO_INIT;
394 }
395
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700396 status_t err = NO_ERROR;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700397 switch (api) {
398 case NATIVE_WINDOW_API_EGL:
399 case NATIVE_WINDOW_API_CPU:
400 case NATIVE_WINDOW_API_MEDIA:
401 case NATIVE_WINDOW_API_CAMERA:
402 if (mConnectedApi != NO_CONNECTED_API) {
403 err = -EINVAL;
404 } else {
405 mConnectedApi = api;
Mathias Agopian053b02d2011-08-08 19:14:03 -0700406 *outWidth = mDefaultWidth;
407 *outHeight = mDefaultHeight;
408 *outTransform = 0;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700409 }
410 break;
411 default:
412 err = -EINVAL;
413 break;
414 }
415 return err;
416}
417
Pannag Sanketi557b7092011-08-18 21:53:02 -0700418// This is called by the client side when it is done
419// TODO: Currently, this also sets mStopped to true which
420// is needed for unblocking the encoder which might be
421// waiting to read more frames. So if on the client side,
422// the same thread supplies the frames and also calls stop
423// on the encoder, the client has to call disconnect before
424// it calls stop.
425// In the case of the camera,
426// that need not be required since the thread supplying the
427// frames is separate than the one calling stop.
Pannag Sanketif48987d2011-06-30 15:30:03 -0700428status_t SurfaceMediaSource::disconnect(int api) {
Steve Block71f2cf12011-10-20 11:56:00 +0100429 ALOGV("SurfaceMediaSource::disconnect");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700430 Mutex::Autolock lock(mMutex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700431
432 if (mStopped) {
Steve Block3762c312012-01-06 19:20:56 +0000433 ALOGE("disconnect: SurfaceMediaSoource is already stopped!");
Pannag Sanketi557b7092011-08-18 21:53:02 -0700434 return NO_INIT;
435 }
436
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700437 status_t err = NO_ERROR;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700438 switch (api) {
439 case NATIVE_WINDOW_API_EGL:
440 case NATIVE_WINDOW_API_CPU:
441 case NATIVE_WINDOW_API_MEDIA:
442 case NATIVE_WINDOW_API_CAMERA:
443 if (mConnectedApi == api) {
444 mConnectedApi = NO_CONNECTED_API;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700445 mStopped = true;
446 mDequeueCondition.signal();
447 mFrameAvailableCondition.signal();
Pannag Sanketi26a19712011-06-10 18:30:30 -0700448 } else {
449 err = -EINVAL;
450 }
451 break;
452 default:
453 err = -EINVAL;
454 break;
455 }
456 return err;
457}
458
Pannag Sanketi557b7092011-08-18 21:53:02 -0700459status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
Pannag Sanketi26a19712011-06-10 18:30:30 -0700460 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Steve Block71f2cf12011-10-20 11:56:00 +0100461 ALOGV("queueBuffer");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700462
463 Mutex::Autolock lock(mMutex);
Pannag Sanketie46fcef2011-09-08 14:15:00 -0700464 *outWidth = mDefaultWidth;
465 *outHeight = mDefaultHeight;
466 *outTransform = 0;
467
Pannag Sanketi557b7092011-08-18 21:53:02 -0700468 if (bufIndex < 0 || bufIndex >= mBufferCount) {
Steve Block3762c312012-01-06 19:20:56 +0000469 ALOGE("queueBuffer: slot index out of range [0, %d]: %d",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700470 mBufferCount, bufIndex);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700471 return -EINVAL;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700472 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
Steve Block3762c312012-01-06 19:20:56 +0000473 ALOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700474 bufIndex, mSlots[bufIndex].mBufferState);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700475 return -EINVAL;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700476 } else if (!mSlots[bufIndex].mRequestBufferCalled) {
Steve Block3762c312012-01-06 19:20:56 +0000477 ALOGE("queueBuffer: slot %d was enqueued without requesting a "
Pannag Sanketi557b7092011-08-18 21:53:02 -0700478 "buffer", bufIndex);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700479 return -EINVAL;
480 }
481
Eino-Ville Talvala728e08bc2011-08-29 18:16:03 -0700482 if (mNumFramesReceived == 0) {
483 mFirstFrameTimestamp = timestamp;
484 // Initial delay
485 if (mStartTimeNs > 0) {
486 if (timestamp < mStartTimeNs) {
487 // This frame predates start of record, discard
488 mSlots[bufIndex].mBufferState = BufferSlot::FREE;
489 mDequeueCondition.signal();
490 return OK;
491 }
492 mStartTimeNs = timestamp - mStartTimeNs;
493 }
494 }
495 timestamp = mStartTimeNs + (timestamp - mFirstFrameTimestamp);
496
497 mNumFramesReceived++;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700498 if (mSynchronousMode) {
499 // in synchronous mode we queue all buffers in a FIFO
Pannag Sanketi557b7092011-08-18 21:53:02 -0700500 mQueue.push_back(bufIndex);
Steve Block71f2cf12011-10-20 11:56:00 +0100501 ALOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700502 mNumFramesReceived, bufIndex, mQueue.size(),
503 mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700504 } else {
505 // in asynchronous mode we only keep the most recent buffer
506 if (mQueue.empty()) {
Pannag Sanketi557b7092011-08-18 21:53:02 -0700507 mQueue.push_back(bufIndex);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700508 } else {
509 Fifo::iterator front(mQueue.begin());
510 // buffer currently queued is freed
511 mSlots[*front].mBufferState = BufferSlot::FREE;
512 // and we record the new buffer index in the queued list
Pannag Sanketi557b7092011-08-18 21:53:02 -0700513 *front = bufIndex;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700514 }
515 }
516
Pannag Sanketi557b7092011-08-18 21:53:02 -0700517 mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
518 mSlots[bufIndex].mTimestamp = timestamp;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700519 // TODO: (Confirm) Don't want to signal dequeue here.
520 // May be just in asynchronous mode?
521 // mDequeueCondition.signal();
522
523 // Once the queuing is done, we need to let the listener
524 // and signal the buffer consumer (encoder) know that a
525 // buffer is available
526 onFrameReceivedLocked();
527
Pannag Sanketi26a19712011-06-10 18:30:30 -0700528
529 return OK;
530}
531
532
533// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
534// or listeners that a frame has been received
535// It is supposed to be called only from queuebuffer.
536// The buffer is NOT made available for dequeueing immediately. We need to
537// wait to hear from StageFrightRecorder to set the buffer FREE
538// Make sure this is called when the mutex is locked
Pannag Sanketif48987d2011-06-30 15:30:03 -0700539status_t SurfaceMediaSource::onFrameReceivedLocked() {
Steve Block71f2cf12011-10-20 11:56:00 +0100540 ALOGV("On Frame Received locked");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700541 // Signal the encoder that a new frame has arrived
542 mFrameAvailableCondition.signal();
543
544 // call back the listener
Pannag Sanketif48987d2011-06-30 15:30:03 -0700545 // TODO: The listener may not be needed in SurfaceMediaSource at all.
Pannag Sanketi26a19712011-06-10 18:30:30 -0700546 // This can be made a SurfaceTexture specific thing
547 sp<FrameAvailableListener> listener;
548 if (mSynchronousMode || mQueue.empty()) {
549 listener = mFrameAvailableListener;
550 }
551
552 if (listener != 0) {
553 listener->onFrameAvailable();
554 }
555 return OK;
556}
557
558
Pannag Sanketi557b7092011-08-18 21:53:02 -0700559void SurfaceMediaSource::cancelBuffer(int bufIndex) {
Steve Block71f2cf12011-10-20 11:56:00 +0100560 ALOGV("SurfaceMediaSource::cancelBuffer");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700561 Mutex::Autolock lock(mMutex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700562 if (bufIndex < 0 || bufIndex >= mBufferCount) {
Steve Block3762c312012-01-06 19:20:56 +0000563 ALOGE("cancelBuffer: slot index out of range [0, %d]: %d",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700564 mBufferCount, bufIndex);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700565 return;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700566 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
Steve Block3762c312012-01-06 19:20:56 +0000567 ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700568 bufIndex, mSlots[bufIndex].mBufferState);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700569 return;
570 }
Pannag Sanketi557b7092011-08-18 21:53:02 -0700571 mSlots[bufIndex].mBufferState = BufferSlot::FREE;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700572 mDequeueCondition.signal();
573}
574
Pannag Sanketif48987d2011-06-30 15:30:03 -0700575nsecs_t SurfaceMediaSource::getTimestamp() {
Steve Block71f2cf12011-10-20 11:56:00 +0100576 ALOGV("SurfaceMediaSource::getTimestamp");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700577 Mutex::Autolock lock(mMutex);
578 return mCurrentTimestamp;
579}
580
581
Pannag Sanketif48987d2011-06-30 15:30:03 -0700582void SurfaceMediaSource::setFrameAvailableListener(
Pannag Sanketi26a19712011-06-10 18:30:30 -0700583 const sp<FrameAvailableListener>& listener) {
Steve Block71f2cf12011-10-20 11:56:00 +0100584 ALOGV("SurfaceMediaSource::setFrameAvailableListener");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700585 Mutex::Autolock lock(mMutex);
586 mFrameAvailableListener = listener;
587}
588
Pannag Sanketi557b7092011-08-18 21:53:02 -0700589void SurfaceMediaSource::freeAllBuffersLocked() {
Steve Block71f2cf12011-10-20 11:56:00 +0100590 ALOGV("freeAllBuffersLocked");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700591 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
592 mSlots[i].mGraphicBuffer = 0;
593 mSlots[i].mBufferState = BufferSlot::FREE;
594 }
595}
596
Pannag Sanketif48987d2011-06-30 15:30:03 -0700597sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
Pannag Sanketi26a19712011-06-10 18:30:30 -0700598 Mutex::Autolock lock(mMutex);
599 return mCurrentBuf;
600}
601
Pannag Sanketif48987d2011-06-30 15:30:03 -0700602int SurfaceMediaSource::query(int what, int* outValue)
Pannag Sanketi26a19712011-06-10 18:30:30 -0700603{
Steve Block71f2cf12011-10-20 11:56:00 +0100604 ALOGV("query");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700605 Mutex::Autolock lock(mMutex);
606 int value;
607 switch (what) {
608 case NATIVE_WINDOW_WIDTH:
609 value = mDefaultWidth;
610 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
611 value = mCurrentBuf->width;
612 break;
613 case NATIVE_WINDOW_HEIGHT:
614 value = mDefaultHeight;
615 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
616 value = mCurrentBuf->height;
617 break;
618 case NATIVE_WINDOW_FORMAT:
619 value = mPixelFormat;
620 break;
621 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
622 value = mSynchronousMode ?
623 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
624 break;
625 default:
626 return BAD_VALUE;
627 }
628 outValue[0] = value;
629 return NO_ERROR;
630}
631
Pannag Sanketif48987d2011-06-30 15:30:03 -0700632void SurfaceMediaSource::dump(String8& result) const
Pannag Sanketi26a19712011-06-10 18:30:30 -0700633{
634 char buffer[1024];
635 dump(result, "", buffer, 1024);
636}
637
Pannag Sanketif48987d2011-06-30 15:30:03 -0700638void SurfaceMediaSource::dump(String8& result, const char* prefix,
Pannag Sanketi26a19712011-06-10 18:30:30 -0700639 char* buffer, size_t SIZE) const
640{
641 Mutex::Autolock _l(mMutex);
642 snprintf(buffer, SIZE,
643 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
644 "mPixelFormat=%d, \n",
645 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
646 mPixelFormat);
647 result.append(buffer);
648
649 String8 fifo;
650 int fifoSize = 0;
651 Fifo::const_iterator i(mQueue.begin());
652 while (i != mQueue.end()) {
653 snprintf(buffer, SIZE, "%02d ", *i++);
654 fifoSize++;
655 fifo.append(buffer);
656 }
657
658 result.append(buffer);
659
660 struct {
661 const char * operator()(int state) const {
662 switch (state) {
663 case BufferSlot::DEQUEUED: return "DEQUEUED";
664 case BufferSlot::QUEUED: return "QUEUED";
665 case BufferSlot::FREE: return "FREE";
666 default: return "Unknown";
667 }
668 }
669 } stateName;
670
671 for (int i = 0; i < mBufferCount; i++) {
672 const BufferSlot& slot(mSlots[i]);
673 snprintf(buffer, SIZE,
674 "%s%s[%02d] state=%-8s, "
675 "timestamp=%lld\n",
676 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
677 slot.mTimestamp
678 );
679 result.append(buffer);
680 }
681}
682
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700683status_t SurfaceMediaSource::setFrameRate(int32_t fps)
Pannag Sanketi26a19712011-06-10 18:30:30 -0700684{
685 Mutex::Autolock lock(mMutex);
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700686 const int MAX_FRAME_RATE = 60;
687 if (fps < 0 || fps > MAX_FRAME_RATE) {
688 return BAD_VALUE;
689 }
Pannag Sanketi26a19712011-06-10 18:30:30 -0700690 mFrameRate = fps;
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700691 return OK;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700692}
693
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700694bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
Steve Block71f2cf12011-10-20 11:56:00 +0100695 ALOGV("isMetaDataStoredInVideoBuffers");
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700696 return true;
697}
698
699int32_t SurfaceMediaSource::getFrameRate( ) const {
Pannag Sanketi26a19712011-06-10 18:30:30 -0700700 Mutex::Autolock lock(mMutex);
701 return mFrameRate;
702}
703
Pannag Sanketif48987d2011-06-30 15:30:03 -0700704status_t SurfaceMediaSource::start(MetaData *params)
Pannag Sanketi26a19712011-06-10 18:30:30 -0700705{
Steve Block71f2cf12011-10-20 11:56:00 +0100706 ALOGV("started!");
Eino-Ville Talvala728e08bc2011-08-29 18:16:03 -0700707
708 mStartTimeNs = 0;
709 int64_t startTimeUs;
710 if (params && params->findInt64(kKeyTime, &startTimeUs)) {
711 mStartTimeNs = startTimeUs * 1000;
712 }
713
Pannag Sanketi26a19712011-06-10 18:30:30 -0700714 return OK;
715}
716
717
James Dongf5a9f432012-02-04 06:19:50 -0800718status_t SurfaceMediaSource::reset()
Pannag Sanketi26a19712011-06-10 18:30:30 -0700719{
James Dongf5a9f432012-02-04 06:19:50 -0800720 ALOGV("Reset");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700721
722 Mutex::Autolock lock(mMutex);
723 // TODO: Add waiting on mFrameCompletedCondition here?
Pannag Sanketi557b7092011-08-18 21:53:02 -0700724 mStopped = true;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700725 mFrameAvailableCondition.signal();
Pannag Sanketi557b7092011-08-18 21:53:02 -0700726 mDequeueCondition.signal();
727 mQueue.clear();
728 freeAllBuffersLocked();
Pannag Sanketi26a19712011-06-10 18:30:30 -0700729
730 return OK;
731}
732
Pannag Sanketif48987d2011-06-30 15:30:03 -0700733sp<MetaData> SurfaceMediaSource::getFormat()
Pannag Sanketi26a19712011-06-10 18:30:30 -0700734{
Steve Block71f2cf12011-10-20 11:56:00 +0100735 ALOGV("getFormat");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700736 Mutex::Autolock autoLock(mMutex);
737 sp<MetaData> meta = new MetaData;
Pannag Sanketi897e27b2011-07-01 17:39:39 -0700738
Pannag Sanketi26a19712011-06-10 18:30:30 -0700739 meta->setInt32(kKeyWidth, mDefaultWidth);
740 meta->setInt32(kKeyHeight, mDefaultHeight);
741 // The encoder format is set as an opaque colorformat
742 // The encoder will later find out the actual colorformat
743 // from the GL Frames itself.
744 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
745 meta->setInt32(kKeyStride, mDefaultWidth);
746 meta->setInt32(kKeySliceHeight, mDefaultHeight);
747 meta->setInt32(kKeyFrameRate, mFrameRate);
748 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
749 return meta;
750}
751
Pannag Sanketif48987d2011-06-30 15:30:03 -0700752status_t SurfaceMediaSource::read( MediaBuffer **buffer,
Pannag Sanketi557b7092011-08-18 21:53:02 -0700753 const ReadOptions *options)
Pannag Sanketi26a19712011-06-10 18:30:30 -0700754{
Pannag Sanketi557b7092011-08-18 21:53:02 -0700755 Mutex::Autolock autoLock(mMutex) ;
756
Steve Block71f2cf12011-10-20 11:56:00 +0100757 ALOGV("Read. Size of queued buffer: %d", mQueue.size());
Pannag Sanketi26a19712011-06-10 18:30:30 -0700758 *buffer = NULL;
759
Pannag Sanketi26a19712011-06-10 18:30:30 -0700760 // If the recording has started and the queue is empty, then just
761 // wait here till the frames come in from the client side
Pannag Sanketi557b7092011-08-18 21:53:02 -0700762 while (!mStopped && mQueue.empty()) {
Steve Block71f2cf12011-10-20 11:56:00 +0100763 ALOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700764 mFrameAvailableCondition.wait(mMutex);
765 }
766
767 // If the loop was exited as a result of stopping the recording,
768 // it is OK
Pannag Sanketi557b7092011-08-18 21:53:02 -0700769 if (mStopped) {
Steve Block71f2cf12011-10-20 11:56:00 +0100770 ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
Pannag Sanketia1849fc2011-09-22 17:03:48 -0700771 return ERROR_END_OF_STREAM;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700772 }
773
774 // Update the current buffer info
775 // TODO: mCurrentSlot can be made a bufferstate since there
776 // can be more than one "current" slots.
777 Fifo::iterator front(mQueue.begin());
778 mCurrentSlot = *front;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700779 mQueue.erase(front);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700780 mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
Pannag Sanketi557b7092011-08-18 21:53:02 -0700781 int64_t prevTimeStamp = mCurrentTimestamp;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700782 mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
Eino-Ville Talvala728e08bc2011-08-29 18:16:03 -0700783
Pannag Sanketi557b7092011-08-18 21:53:02 -0700784 mNumFramesEncoded++;
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700785 // Pass the data to the MediaBuffer. Pass in only the metadata
786 passMetadataBufferLocked(buffer);
787
Pannag Sanketi26a19712011-06-10 18:30:30 -0700788 (*buffer)->setObserver(this);
789 (*buffer)->add_ref();
Pannag Sanketi557b7092011-08-18 21:53:02 -0700790 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
Steve Block71f2cf12011-10-20 11:56:00 +0100791 ALOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700792 mNumFramesEncoded, mCurrentTimestamp / 1000,
793 mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
Pannag Sanketi26a19712011-06-10 18:30:30 -0700794
795 return OK;
796}
797
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700798// Pass the data to the MediaBuffer. Pass in only the metadata
799// The metadata passed consists of two parts:
800// 1. First, there is an integer indicating that it is a GRAlloc
801// source (kMetadataBufferTypeGrallocSource)
802// 2. This is followed by the buffer_handle_t that is a handle to the
803// GRalloc buffer. The encoder needs to interpret this GRalloc handle
804// and encode the frames.
805// --------------------------------------------------------------
806// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
807// --------------------------------------------------------------
808// Note: Call only when you have the lock
809void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
Steve Block71f2cf12011-10-20 11:56:00 +0100810 ALOGV("passMetadataBuffer");
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700811 // MediaBuffer allocates and owns this data
812 MediaBuffer *tempBuffer =
813 new MediaBuffer(4 + sizeof(buffer_handle_t));
814 char *data = (char *)tempBuffer->data();
815 if (data == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000816 ALOGE("Cannot allocate memory for metadata buffer!");
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700817 return;
818 }
819 OMX_U32 type = kMetadataBufferTypeGrallocSource;
820 memcpy(data, &type, 4);
821 memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
822 *buffer = tempBuffer;
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700823
Steve Block71f2cf12011-10-20 11:56:00 +0100824 ALOGV("handle = %p, , offset = %d, length = %d",
Pannag Sanketi557b7092011-08-18 21:53:02 -0700825 mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
826}
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700827
Pannag Sanketif48987d2011-06-30 15:30:03 -0700828void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
Steve Block71f2cf12011-10-20 11:56:00 +0100829 ALOGV("signalBufferReturned");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700830
831 bool foundBuffer = false;
832 Mutex::Autolock autoLock(mMutex);
833
Pannag Sanketi557b7092011-08-18 21:53:02 -0700834 if (mStopped) {
Steve Block71f2cf12011-10-20 11:56:00 +0100835 ALOGV("signalBufferReturned: mStopped = true! Nothing to do!");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700836 return;
837 }
838
Pannag Sanketi557b7092011-08-18 21:53:02 -0700839 for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
840 if (mSlots[id].mGraphicBuffer == NULL) {
841 continue;
842 }
843 if (checkBufferMatchesSlot(id, buffer)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100844 ALOGV("Slot %d returned, matches handle = %p", id,
Pannag Sanketi557b7092011-08-18 21:53:02 -0700845 mSlots[id].mGraphicBuffer->handle);
846 mSlots[id].mBufferState = BufferSlot::FREE;
Pannag Sanketi26a19712011-06-10 18:30:30 -0700847 buffer->setObserver(0);
848 buffer->release();
849 mDequeueCondition.signal();
850 mFrameCompleteCondition.signal();
851 foundBuffer = true;
852 break;
853 }
854 }
855
856 if (!foundBuffer) {
James Dong8e9d67a2012-02-06 23:46:37 -0800857 CHECK(!"signalBufferReturned: bogus buffer");
Pannag Sanketi26a19712011-06-10 18:30:30 -0700858 }
859}
860
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700861bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
Steve Block71f2cf12011-10-20 11:56:00 +0100862 ALOGV("Check if Buffer matches slot");
Pannag Sanketib1f8c262011-07-14 14:37:47 -0700863 // need to convert to char* for pointer arithmetic and then
864 // copy the byte stream into our handle
865 buffer_handle_t bufferHandle ;
866 memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
867 return mSlots[slot].mGraphicBuffer->handle == bufferHandle;
868}
Pannag Sanketi26a19712011-06-10 18:30:30 -0700869
Pannag Sanketi26a19712011-06-10 18:30:30 -0700870} // end of namespace android