SurfaceMediaSource.cpp revision 85eafc680a0bf5e0253cf611ac525769fc9bef3e
1/*
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 */
16
17// #define LOG_NDEBUG 0
18#define LOG_TAG "SurfaceMediaSource"
19
20#include <media/stagefright/SurfaceMediaSource.h>
21#include <ui/GraphicBuffer.h>
22#include <media/stagefright/MetaData.h>
23#include <media/stagefright/MediaDefs.h>
24#include <media/stagefright/MediaDebug.h>
25#include <media/stagefright/openmax/OMX_IVCommon.h>
26
27#include <surfaceflinger/ISurfaceComposer.h>
28#include <surfaceflinger/SurfaceComposerClient.h>
29#include <surfaceflinger/IGraphicBufferAlloc.h>
30#include <OMX_Component.h>
31
32#include <utils/Log.h>
33#include <utils/String8.h>
34
35namespace android {
36
37SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
38    mDefaultWidth(bufW),
39    mDefaultHeight(bufH),
40    mPixelFormat(0),
41    mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
42    mClientBufferCount(0),
43    mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
44    mCurrentSlot(INVALID_BUFFER_SLOT),
45    mCurrentTimestamp(0),
46    mSynchronousMode(true),
47    mConnectedApi(NO_CONNECTED_API),
48    mFrameRate(30),
49    mStarted(false)     {
50    LOGV("SurfaceMediaSource::SurfaceMediaSource");
51    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
52    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
53}
54
55SurfaceMediaSource::~SurfaceMediaSource() {
56    LOGV("SurfaceMediaSource::~SurfaceMediaSource");
57    if (mStarted) {
58        stop();
59    }
60    freeAllBuffers();
61}
62
63size_t SurfaceMediaSource::getQueuedCount() const {
64    Mutex::Autolock lock(mMutex);
65    return mQueue.size();
66}
67
68status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) {
69    if (bufferCount > NUM_BUFFER_SLOTS)
70        return BAD_VALUE;
71
72    // special-case, nothing to do
73    if (bufferCount == mBufferCount)
74        return OK;
75
76    if (!mClientBufferCount &&
77        bufferCount >= mBufferCount) {
78        // easy, we just have more buffers
79        mBufferCount = bufferCount;
80        mServerBufferCount = bufferCount;
81        mDequeueCondition.signal();
82    } else {
83        // we're here because we're either
84        // - reducing the number of available buffers
85        // - or there is a client-buffer-count in effect
86
87        // less than 2 buffers is never allowed
88        if (bufferCount < 2)
89            return BAD_VALUE;
90
91        // when there is non client-buffer-count in effect, the client is not
92        // allowed to dequeue more than one buffer at a time,
93        // so the next time they dequeue a buffer, we know that they don't
94        // own one. the actual resizing will happen during the next
95        // dequeueBuffer.
96
97        mServerBufferCount = bufferCount;
98    }
99    return OK;
100}
101
102// Called from the consumer side
103status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
104    Mutex::Autolock lock(mMutex);
105    return setBufferCountServerLocked(bufferCount);
106}
107
108status_t SurfaceMediaSource::setBufferCount(int bufferCount) {
109    LOGV("SurfaceMediaSource::setBufferCount");
110    if (bufferCount > NUM_BUFFER_SLOTS) {
111        LOGE("setBufferCount: bufferCount is larger than the number of buffer slots");
112        return BAD_VALUE;
113    }
114
115    Mutex::Autolock lock(mMutex);
116    // Error out if the user has dequeued buffers
117    for (int i = 0 ; i < mBufferCount ; i++) {
118        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
119            LOGE("setBufferCount: client owns some buffers");
120            return INVALID_OPERATION;
121        }
122    }
123
124    if (bufferCount == 0) {
125        const int minBufferSlots = mSynchronousMode ?
126                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
127        mClientBufferCount = 0;
128        bufferCount = (mServerBufferCount >= minBufferSlots) ?
129                mServerBufferCount : minBufferSlots;
130        return setBufferCountServerLocked(bufferCount);
131    }
132
133    // We don't allow the client to set a buffer-count less than
134    // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
135    if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
136        return BAD_VALUE;
137    }
138
139    // here we're guaranteed that the client doesn't have dequeued buffers
140    // and will release all of its buffer references.
141    freeAllBuffers();
142    mBufferCount = bufferCount;
143    mClientBufferCount = bufferCount;
144    mCurrentSlot = INVALID_BUFFER_SLOT;
145    mQueue.clear();
146    mDequeueCondition.signal();
147    return OK;
148}
149
150sp<GraphicBuffer> SurfaceMediaSource::requestBuffer(int buf) {
151    LOGV("SurfaceMediaSource::requestBuffer");
152    Mutex::Autolock lock(mMutex);
153    if (buf < 0 || mBufferCount <= buf) {
154        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
155                mBufferCount, buf);
156        return 0;
157    }
158    mSlots[buf].mRequestBufferCalled = true;
159    return mSlots[buf].mGraphicBuffer;
160}
161
162status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
163                                            uint32_t format, uint32_t usage) {
164    LOGV("dequeueBuffer");
165
166
167    // Check for the buffer size- the client should just use the
168    // default width and height, and not try to set those.
169    // This is needed since
170    // the getFormat() returns mDefaultWidth/ Height for the OMX. It is
171    // queried by OMX in the beginning and not every time a frame comes.
172    // Not sure if there is  a way to update the
173    // frame size while recording. So as of now, the client side
174    // sets the default values via the constructor, and the encoder is
175    // setup to encode frames of that size
176    // The design might need to change in the future.
177    // TODO: Currently just uses mDefaultWidth/Height. In the future
178    // we might declare mHeight and mWidth and check against those here.
179    if ((w != 0) || (h != 0)) {
180        LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
181                mDefaultWidth, mDefaultHeight, w, h);
182        return BAD_VALUE;
183    }
184
185    Mutex::Autolock lock(mMutex);
186
187    status_t returnFlags(OK);
188
189    int found, foundSync;
190    int dequeuedCount = 0;
191    bool tryAgain = true;
192    while (tryAgain) {
193        // We need to wait for the FIFO to drain if the number of buffer
194        // needs to change.
195        //
196        // The condition "number of buffer needs to change" is true if
197        // - the client doesn't care about how many buffers there are
198        // - AND the actual number of buffer is different from what was
199        //   set in the last setBufferCountServer()
200        //                         - OR -
201        //   setBufferCountServer() was set to a value incompatible with
202        //   the synchronization mode (for instance because the sync mode
203        //   changed since)
204        //
205        // As long as this condition is true AND the FIFO is not empty, we
206        // wait on mDequeueCondition.
207
208        int minBufferCountNeeded = mSynchronousMode ?
209                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
210
211        if (!mClientBufferCount &&
212                ((mServerBufferCount != mBufferCount) ||
213                        (mServerBufferCount < minBufferCountNeeded))) {
214            // wait for the FIFO to drain
215            while (!mQueue.isEmpty()) {
216                LOGV("Waiting for the FIFO to drain");
217                mDequeueCondition.wait(mMutex);
218            }
219            // need to check again since the mode could have changed
220            // while we were waiting
221            minBufferCountNeeded = mSynchronousMode ?
222                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
223        }
224
225        if (!mClientBufferCount &&
226                ((mServerBufferCount != mBufferCount) ||
227                        (mServerBufferCount < minBufferCountNeeded))) {
228            // here we're guaranteed that mQueue is empty
229            freeAllBuffers();
230            mBufferCount = mServerBufferCount;
231            if (mBufferCount < minBufferCountNeeded)
232                mBufferCount = minBufferCountNeeded;
233            mCurrentSlot = INVALID_BUFFER_SLOT;
234            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
235        }
236
237        // look for a free buffer to give to the client
238        found = INVALID_BUFFER_SLOT;
239        foundSync = INVALID_BUFFER_SLOT;
240        dequeuedCount = 0;
241        for (int i = 0; i < mBufferCount; i++) {
242            const int state = mSlots[i].mBufferState;
243            if (state == BufferSlot::DEQUEUED) {
244                dequeuedCount++;
245                continue; // won't be continuing if could
246                // dequeue a non 'FREE' current slot like
247                // that in SurfaceTexture
248            }
249            // In case of Encoding, we do not deque the mCurrentSlot buffer
250            //  since we follow synchronous mode (unlike possibly in
251            //  SurfaceTexture that could be using the asynch mode
252            //  or has some mechanism in GL to be able to wait till the
253            //  currentslot is done using the data)
254            // Here, we have to wait for the MPEG4Writer(or equiv)
255            // to tell us when it's done using the current buffer
256            if (state == BufferSlot::FREE) {
257                foundSync = i;
258                // Unlike that in SurfaceTexture,
259                // We don't need to worry if it is the
260                // currentslot or not as it is in state FREE
261                found = i;
262                break;
263            }
264        }
265
266        // clients are not allowed to dequeue more than one buffer
267        // if they didn't set a buffer count.
268        if (!mClientBufferCount && dequeuedCount) {
269            return -EINVAL;
270        }
271
272        // See whether a buffer has been queued since the last setBufferCount so
273        // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
274        bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
275        if (bufferHasBeenQueued) {
276            // make sure the client is not trying to dequeue more buffers
277            // than allowed.
278            const int avail = mBufferCount - (dequeuedCount+1);
279            if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
280                LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
281                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
282                        dequeuedCount);
283                return -EBUSY;
284            }
285        }
286
287        // we're in synchronous mode and didn't find a buffer, we need to wait
288        // for for some buffers to be consumed
289        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
290        if (tryAgain) {
291            LOGW("Waiting..In synchronous mode and no buffer to dQ");
292            mDequeueCondition.wait(mMutex);
293        }
294    }
295
296    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
297        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
298        found = foundSync;
299    }
300
301    if (found == INVALID_BUFFER_SLOT) {
302        return -EBUSY;
303    }
304
305    const int buf = found;
306    *outBuf = found;
307
308    const bool useDefaultSize = !w && !h;
309    if (useDefaultSize) {
310        // use the default size
311        w = mDefaultWidth;
312        h = mDefaultHeight;
313    }
314
315    const bool updateFormat = (format != 0);
316    if (!updateFormat) {
317        // keep the current (or default) format
318        format = mPixelFormat;
319    }
320
321    // buffer is now in DEQUEUED (but can also be current at the same time,
322    // if we're in synchronous mode)
323    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
324
325    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
326    if ((buffer == NULL) ||
327        (uint32_t(buffer->width)  != w) ||
328        (uint32_t(buffer->height) != h) ||
329        (uint32_t(buffer->format) != format) ||
330        ((uint32_t(buffer->usage) & usage) != usage)) {
331            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
332            status_t error;
333            sp<GraphicBuffer> graphicBuffer(
334                    mGraphicBufferAlloc->createGraphicBuffer(
335                                    w, h, format, usage, &error));
336            if (graphicBuffer == 0) {
337                LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
338                return error;
339            }
340            if (updateFormat) {
341                mPixelFormat = format;
342            }
343            mSlots[buf].mGraphicBuffer = graphicBuffer;
344            mSlots[buf].mRequestBufferCalled = false;
345            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
346    }
347    return returnFlags;
348}
349
350status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
351    Mutex::Autolock lock(mMutex);
352
353    status_t err = OK;
354    if (!enabled) {
355        // going to asynchronous mode, drain the queue
356        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
357            mDequeueCondition.wait(mMutex);
358        }
359    }
360
361    if (mSynchronousMode != enabled) {
362        // - if we're going to asynchronous mode, the queue is guaranteed to be
363        // empty here
364        // - if the client set the number of buffers, we're guaranteed that
365        // we have at least 3 (because we don't allow less)
366        mSynchronousMode = enabled;
367        mDequeueCondition.signal();
368    }
369    return err;
370}
371
372status_t SurfaceMediaSource::connect(int api) {
373    LOGV("SurfaceMediaSource::connect");
374    Mutex::Autolock lock(mMutex);
375    int err = NO_ERROR;
376    switch (api) {
377        case NATIVE_WINDOW_API_EGL:
378        case NATIVE_WINDOW_API_CPU:
379        case NATIVE_WINDOW_API_MEDIA:
380        case NATIVE_WINDOW_API_CAMERA:
381            if (mConnectedApi != NO_CONNECTED_API) {
382                err = -EINVAL;
383            } else {
384                mConnectedApi = api;
385            }
386            break;
387        default:
388            err = -EINVAL;
389            break;
390    }
391    return err;
392}
393
394status_t SurfaceMediaSource::disconnect(int api) {
395    LOGV("SurfaceMediaSource::disconnect");
396    Mutex::Autolock lock(mMutex);
397    int err = NO_ERROR;
398    switch (api) {
399        case NATIVE_WINDOW_API_EGL:
400        case NATIVE_WINDOW_API_CPU:
401        case NATIVE_WINDOW_API_MEDIA:
402        case NATIVE_WINDOW_API_CAMERA:
403            if (mConnectedApi == api) {
404                mConnectedApi = NO_CONNECTED_API;
405            } else {
406                err = -EINVAL;
407            }
408            break;
409        default:
410            err = -EINVAL;
411            break;
412    }
413    return err;
414}
415
416status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
417        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
418    LOGV("queueBuffer");
419
420    Mutex::Autolock lock(mMutex);
421    if (buf < 0 || buf >= mBufferCount) {
422        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
423                mBufferCount, buf);
424        return -EINVAL;
425    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
426        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
427                buf, mSlots[buf].mBufferState);
428        return -EINVAL;
429    } else if (!mSlots[buf].mRequestBufferCalled) {
430        LOGE("queueBuffer: slot %d was enqueued without requesting a "
431                "buffer", buf);
432        return -EINVAL;
433    }
434
435    if (mSynchronousMode) {
436        // in synchronous mode we queue all buffers in a FIFO
437        mQueue.push_back(buf);
438        LOGV("Client queued buffer on slot: %d, Q size = %d",
439                                                buf, mQueue.size());
440    } else {
441        // in asynchronous mode we only keep the most recent buffer
442        if (mQueue.empty()) {
443            mQueue.push_back(buf);
444        } else {
445            Fifo::iterator front(mQueue.begin());
446            // buffer currently queued is freed
447            mSlots[*front].mBufferState = BufferSlot::FREE;
448            // and we record the new buffer index in the queued list
449            *front = buf;
450        }
451    }
452
453    mSlots[buf].mBufferState = BufferSlot::QUEUED;
454    mSlots[buf].mTimestamp = timestamp;
455    // TODO: (Confirm) Don't want to signal dequeue here.
456    // May be just in asynchronous mode?
457    // mDequeueCondition.signal();
458
459    // Once the queuing is done, we need to let the listener
460    // and signal the buffer consumer (encoder) know that a
461    // buffer is available
462    onFrameReceivedLocked();
463
464    *outWidth = mDefaultWidth;
465    *outHeight = mDefaultHeight;
466    *outTransform = 0;
467
468    return OK;
469}
470
471
472// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
473// or listeners that a frame has been received
474// It is supposed to be called only from queuebuffer.
475// The buffer is NOT made available for dequeueing immediately. We need to
476// wait to hear from StageFrightRecorder to set the buffer FREE
477// Make sure this is called when the mutex is locked
478status_t SurfaceMediaSource::onFrameReceivedLocked() {
479    LOGV("On Frame Received");
480    // Signal the encoder that a new frame has arrived
481    mFrameAvailableCondition.signal();
482
483    // call back the listener
484    // TODO: The listener may not be needed in SurfaceMediaSource at all.
485    // This can be made a SurfaceTexture specific thing
486    sp<FrameAvailableListener> listener;
487    if (mSynchronousMode || mQueue.empty()) {
488        listener = mFrameAvailableListener;
489    }
490
491    if (listener != 0) {
492        listener->onFrameAvailable();
493    }
494    return OK;
495}
496
497
498void SurfaceMediaSource::cancelBuffer(int buf) {
499    LOGV("SurfaceMediaSource::cancelBuffer");
500    Mutex::Autolock lock(mMutex);
501    if (buf < 0 || buf >= mBufferCount) {
502        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
503                mBufferCount, buf);
504        return;
505    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
506        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
507                buf, mSlots[buf].mBufferState);
508        return;
509    }
510    mSlots[buf].mBufferState = BufferSlot::FREE;
511    mDequeueCondition.signal();
512}
513
514nsecs_t SurfaceMediaSource::getTimestamp() {
515    LOGV("SurfaceMediaSource::getTimestamp");
516    Mutex::Autolock lock(mMutex);
517    return mCurrentTimestamp;
518}
519
520
521void SurfaceMediaSource::setFrameAvailableListener(
522        const sp<FrameAvailableListener>& listener) {
523    LOGV("SurfaceMediaSource::setFrameAvailableListener");
524    Mutex::Autolock lock(mMutex);
525    mFrameAvailableListener = listener;
526}
527
528void SurfaceMediaSource::freeAllBuffers() {
529    LOGV("freeAllBuffers");
530    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
531        mSlots[i].mGraphicBuffer = 0;
532        mSlots[i].mBufferState = BufferSlot::FREE;
533    }
534}
535
536sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
537    Mutex::Autolock lock(mMutex);
538    return mCurrentBuf;
539}
540
541int SurfaceMediaSource::query(int what, int* outValue)
542{
543    LOGV("query");
544    Mutex::Autolock lock(mMutex);
545    int value;
546    switch (what) {
547    case NATIVE_WINDOW_WIDTH:
548        value = mDefaultWidth;
549        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
550            value = mCurrentBuf->width;
551        break;
552    case NATIVE_WINDOW_HEIGHT:
553        value = mDefaultHeight;
554        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
555            value = mCurrentBuf->height;
556        break;
557    case NATIVE_WINDOW_FORMAT:
558        value = mPixelFormat;
559        break;
560    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
561        value = mSynchronousMode ?
562                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
563        break;
564    default:
565        return BAD_VALUE;
566    }
567    outValue[0] = value;
568    return NO_ERROR;
569}
570
571void SurfaceMediaSource::dump(String8& result) const
572{
573    char buffer[1024];
574    dump(result, "", buffer, 1024);
575}
576
577void SurfaceMediaSource::dump(String8& result, const char* prefix,
578        char* buffer, size_t SIZE) const
579{
580    Mutex::Autolock _l(mMutex);
581    snprintf(buffer, SIZE,
582            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
583            "mPixelFormat=%d, \n",
584            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
585            mPixelFormat);
586    result.append(buffer);
587
588    String8 fifo;
589    int fifoSize = 0;
590    Fifo::const_iterator i(mQueue.begin());
591    while (i != mQueue.end()) {
592        snprintf(buffer, SIZE, "%02d ", *i++);
593        fifoSize++;
594        fifo.append(buffer);
595    }
596
597    result.append(buffer);
598
599    struct {
600        const char * operator()(int state) const {
601            switch (state) {
602                case BufferSlot::DEQUEUED: return "DEQUEUED";
603                case BufferSlot::QUEUED: return "QUEUED";
604                case BufferSlot::FREE: return "FREE";
605                default: return "Unknown";
606            }
607        }
608    } stateName;
609
610    for (int i = 0; i < mBufferCount; i++) {
611        const BufferSlot& slot(mSlots[i]);
612        snprintf(buffer, SIZE,
613                "%s%s[%02d] state=%-8s, "
614                "timestamp=%lld\n",
615                prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
616                slot.mTimestamp
617        );
618        result.append(buffer);
619    }
620}
621
622void SurfaceMediaSource::setFrameRate(uint32_t fps)
623{
624    Mutex::Autolock lock(mMutex);
625    mFrameRate = fps;
626}
627
628uint32_t SurfaceMediaSource::getFrameRate( ) const {
629    Mutex::Autolock lock(mMutex);
630    return mFrameRate;
631}
632
633status_t SurfaceMediaSource::start(MetaData *params)
634{
635    LOGV("start");
636    Mutex::Autolock lock(mMutex);
637    CHECK(!mStarted);
638    mStarted = true;
639    return OK;
640}
641
642
643status_t SurfaceMediaSource::stop()
644{
645    LOGV("Stop");
646
647    Mutex::Autolock lock(mMutex);
648    // TODO: Add waiting on mFrameCompletedCondition here?
649    mStarted = false;
650    mFrameAvailableCondition.signal();
651
652    return OK;
653}
654
655sp<MetaData> SurfaceMediaSource::getFormat()
656{
657    LOGV("getFormat");
658    Mutex::Autolock autoLock(mMutex);
659    sp<MetaData> meta = new MetaData;
660    // XXX: Check if this is right. or should we wait on some
661    // condition?
662    meta->setInt32(kKeyWidth, mDefaultWidth);
663    meta->setInt32(kKeyHeight, mDefaultHeight);
664    // The encoder format is set as an opaque colorformat
665    // The encoder will later find out the actual colorformat
666    // from the GL Frames itself.
667    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
668    meta->setInt32(kKeyStride, mDefaultWidth);
669    meta->setInt32(kKeySliceHeight, mDefaultHeight);
670    meta->setInt32(kKeyFrameRate, mFrameRate);
671    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
672    return meta;
673}
674
675status_t SurfaceMediaSource::read( MediaBuffer **buffer,
676                                const ReadOptions *options)
677{
678    LOGV("Read. Size of queued buffer: %d", mQueue.size());
679    *buffer = NULL;
680
681    Mutex::Autolock autoLock(mMutex) ;
682    // If the recording has started and the queue is empty, then just
683    // wait here till the frames come in from the client side
684    while (mStarted && mQueue.empty()) {
685        LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
686        mFrameAvailableCondition.wait(mMutex);
687    }
688
689    // If the loop was exited as a result of stopping the recording,
690    // it is OK
691    if (!mStarted) {
692        return OK;
693    }
694
695    // Update the current buffer info
696    // TODO: mCurrentSlot can be made a bufferstate since there
697    // can be more than one "current" slots.
698    Fifo::iterator front(mQueue.begin());
699    mCurrentSlot = *front;
700    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
701    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
702
703    // Pass the data to the MediaBuffer
704    // TODO: Change later to pass in only the metadata
705    *buffer = new MediaBuffer(mCurrentBuf);
706    (*buffer)->setObserver(this);
707    (*buffer)->add_ref();
708    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
709
710    return OK;
711}
712
713void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
714    LOGV("signalBufferReturned");
715
716    bool foundBuffer = false;
717    Mutex::Autolock autoLock(mMutex);
718
719    if (!mStarted) {
720        LOGV("started = false. Nothing to do");
721        return;
722    }
723
724    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
725        if (mSlots[*it].mGraphicBuffer  ==  buffer->graphicBuffer()) {
726            LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d",
727                    *it, mQueue.size()-1);
728            mSlots[*it].mBufferState = BufferSlot::FREE;
729            mQueue.erase(it);
730            buffer->setObserver(0);
731            buffer->release();
732            mDequeueCondition.signal();
733            mFrameCompleteCondition.signal();
734            foundBuffer = true;
735            break;
736        }
737    }
738
739    if (!foundBuffer) {
740        CHECK_EQ(0, "signalBufferReturned: bogus buffer");
741    }
742}
743
744
745
746} // end of namespace android
747