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