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