SurfaceMediaSource.cpp revision c7de3f6bbaa6c1b8b334574fad34d583e3a67f5d
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// #define LOG_NDEBUG 0
17#define LOG_TAG "SurfaceMediaSource"
18
19#include <media/stagefright/SurfaceMediaSource.h>
20#include <ui/GraphicBuffer.h>
21#include <media/stagefright/MetaData.h>
22#include <media/stagefright/MediaDefs.h>
23#include <media/stagefright/MediaDebug.h>
24#include <media/stagefright/openmax/OMX_IVCommon.h>
25#include <media/stagefright/MetadataBufferType.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                mNumFramesReceived(0),
50                mNumFramesEncoded(0),
51                mStopped(false) {
52    LOGV("SurfaceMediaSource::SurfaceMediaSource");
53    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
54    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
55}
56
57SurfaceMediaSource::~SurfaceMediaSource() {
58    LOGV("SurfaceMediaSource::~SurfaceMediaSource");
59    if (!mStopped) {
60        stop();
61    }
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    mBufferCount = bufferCount;
143    mClientBufferCount = bufferCount;
144    mCurrentSlot = INVALID_BUFFER_SLOT;
145    mQueue.clear();
146    mDequeueCondition.signal();
147    freeAllBuffersLocked();
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    Mutex::Autolock lock(mMutex);
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        if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
183            LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
184                    mDefaultWidth, mDefaultHeight, w, h);
185            return BAD_VALUE;
186        }
187    }
188
189    status_t returnFlags(OK);
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            if (mStopped) {
221                return NO_INIT;
222            }
223            // need to check again since the mode could have changed
224            // while we were waiting
225            minBufferCountNeeded = mSynchronousMode ?
226                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
227        }
228
229        if (!mClientBufferCount &&
230                ((mServerBufferCount != mBufferCount) ||
231                        (mServerBufferCount < minBufferCountNeeded))) {
232            // here we're guaranteed that mQueue is empty
233            freeAllBuffersLocked();
234            mBufferCount = mServerBufferCount;
235            if (mBufferCount < minBufferCountNeeded)
236                mBufferCount = minBufferCountNeeded;
237            mCurrentSlot = INVALID_BUFFER_SLOT;
238            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
239        }
240
241        // look for a free buffer to give to the client
242        found = INVALID_BUFFER_SLOT;
243        foundSync = INVALID_BUFFER_SLOT;
244        dequeuedCount = 0;
245        for (int i = 0; i < mBufferCount; i++) {
246            const int state = mSlots[i].mBufferState;
247            if (state == BufferSlot::DEQUEUED) {
248                dequeuedCount++;
249                continue; // won't be continuing if could
250                // dequeue a non 'FREE' current slot like
251                // that in SurfaceTexture
252            }
253            // In case of Encoding, we do not deque the mCurrentSlot buffer
254            //  since we follow synchronous mode (unlike possibly in
255            //  SurfaceTexture that could be using the asynch mode
256            //  or has some mechanism in GL to be able to wait till the
257            //  currentslot is done using the data)
258            // Here, we have to wait for the MPEG4Writer(or equiv)
259            // to tell us when it's done using the current buffer
260            if (state == BufferSlot::FREE) {
261                foundSync = i;
262                // Unlike that in SurfaceTexture,
263                // We don't need to worry if it is the
264                // currentslot or not as it is in state FREE
265                found = i;
266                break;
267            }
268        }
269
270        // clients are not allowed to dequeue more than one buffer
271        // if they didn't set a buffer count.
272        if (!mClientBufferCount && dequeuedCount) {
273            return -EINVAL;
274        }
275
276        // See whether a buffer has been queued since the last setBufferCount so
277        // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
278        bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
279        if (bufferHasBeenQueued) {
280            // make sure the client is not trying to dequeue more buffers
281            // than allowed.
282            const int avail = mBufferCount - (dequeuedCount+1);
283            if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
284                LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
285                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
286                        dequeuedCount);
287                return -EBUSY;
288            }
289        }
290
291        // we're in synchronous mode and didn't find a buffer, we need to wait
292        // for for some buffers to be consumed
293        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
294        if (tryAgain) {
295            LOGV("Waiting..In synchronous mode and no buffer to dequeue");
296            mDequeueCondition.wait(mMutex);
297        }
298        if (mStopped) {
299            return NO_INIT;
300        }
301    }
302
303    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
304        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
305        found = foundSync;
306    }
307
308    if (found == INVALID_BUFFER_SLOT) {
309        return -EBUSY;
310    }
311
312    const int bufIndex = found;
313    *outBuf = found;
314
315    const bool useDefaultSize = !w && !h;
316    if (useDefaultSize) {
317        // use the default size
318        w = mDefaultWidth;
319        h = mDefaultHeight;
320    }
321
322    const bool updateFormat = (format != 0);
323    if (!updateFormat) {
324        // keep the current (or default) format
325        format = mPixelFormat;
326    }
327
328    // buffer is now in DEQUEUED (but can also be current at the same time,
329    // if we're in synchronous mode)
330    mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED;
331
332    const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer);
333    if ((buffer == NULL) ||
334        (uint32_t(buffer->width)  != w) ||
335        (uint32_t(buffer->height) != h) ||
336        (uint32_t(buffer->format) != format) ||
337        ((uint32_t(buffer->usage) & usage) != usage)) {
338            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
339            status_t error;
340            sp<GraphicBuffer> graphicBuffer(
341                    mGraphicBufferAlloc->createGraphicBuffer(
342                                    w, h, format, usage, &error));
343            if (graphicBuffer == 0) {
344                LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
345                return error;
346            }
347            if (updateFormat) {
348                mPixelFormat = format;
349            }
350            mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
351            mSlots[bufIndex].mRequestBufferCalled = false;
352            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
353    }
354    return returnFlags;
355}
356
357// TODO: clean this up
358status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
359    Mutex::Autolock lock(mMutex);
360    if (mStopped) {
361        LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
362        return NO_INIT;
363    }
364
365    if (!enabled) {
366        // Async mode is not allowed
367        LOGE("SurfaceMediaSource can be used only synchronous mode!");
368        return INVALID_OPERATION;
369    }
370
371    if (mSynchronousMode != enabled) {
372        // - if we're going to asynchronous mode, the queue is guaranteed to be
373        // empty here
374        // - if the client set the number of buffers, we're guaranteed that
375        // we have at least 3 (because we don't allow less)
376        mSynchronousMode = enabled;
377        mDequeueCondition.signal();
378    }
379    return OK;
380}
381
382status_t SurfaceMediaSource::connect(int api,
383        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
384    LOGV("SurfaceMediaSource::connect");
385    Mutex::Autolock lock(mMutex);
386
387    if (mStopped) {
388        LOGE("Connect: SurfaceMediaSource has been stopped!");
389        return NO_INIT;
390    }
391
392    status_t err = NO_ERROR;
393    switch (api) {
394        case NATIVE_WINDOW_API_EGL:
395        case NATIVE_WINDOW_API_CPU:
396        case NATIVE_WINDOW_API_MEDIA:
397        case NATIVE_WINDOW_API_CAMERA:
398            if (mConnectedApi != NO_CONNECTED_API) {
399                err = -EINVAL;
400            } else {
401                mConnectedApi = api;
402                *outWidth = mDefaultWidth;
403                *outHeight = mDefaultHeight;
404                *outTransform = 0;
405            }
406            break;
407        default:
408            err = -EINVAL;
409            break;
410    }
411    return err;
412}
413
414// This is called by the client side when it is done
415// TODO: Currently, this also sets mStopped to true which
416// is needed for unblocking the encoder which might be
417// waiting to read more frames. So if on the client side,
418// the same thread supplies the frames and also calls stop
419// on the encoder, the client has to call disconnect before
420// it calls stop.
421// In the case of the camera,
422// that need not be required since the thread supplying the
423// frames is separate than the one calling stop.
424status_t SurfaceMediaSource::disconnect(int api) {
425    LOGV("SurfaceMediaSource::disconnect");
426    Mutex::Autolock lock(mMutex);
427
428    if (mStopped) {
429        LOGE("disconnect: SurfaceMediaSoource is already stopped!");
430        return NO_INIT;
431    }
432
433    status_t err = NO_ERROR;
434    switch (api) {
435        case NATIVE_WINDOW_API_EGL:
436        case NATIVE_WINDOW_API_CPU:
437        case NATIVE_WINDOW_API_MEDIA:
438        case NATIVE_WINDOW_API_CAMERA:
439            if (mConnectedApi == api) {
440                mConnectedApi = NO_CONNECTED_API;
441                mStopped = true;
442                mDequeueCondition.signal();
443                mFrameAvailableCondition.signal();
444            } else {
445                err = -EINVAL;
446            }
447            break;
448        default:
449            err = -EINVAL;
450            break;
451    }
452    return err;
453}
454
455status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
456        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
457    LOGV("queueBuffer");
458
459    Mutex::Autolock lock(mMutex);
460    if (bufIndex < 0 || bufIndex >= mBufferCount) {
461        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
462                mBufferCount, bufIndex);
463        return -EINVAL;
464    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
465        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
466                bufIndex, mSlots[bufIndex].mBufferState);
467        return -EINVAL;
468    } else if (!mSlots[bufIndex].mRequestBufferCalled) {
469        LOGE("queueBuffer: slot %d was enqueued without requesting a "
470                "buffer", bufIndex);
471        return -EINVAL;
472    }
473
474    if (mSynchronousMode) {
475        // in synchronous mode we queue all buffers in a FIFO
476        mQueue.push_back(bufIndex);
477        mNumFramesReceived++;
478        LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
479            mNumFramesReceived, bufIndex, mQueue.size(),
480            mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
481    } else {
482        // in asynchronous mode we only keep the most recent buffer
483        if (mQueue.empty()) {
484            mQueue.push_back(bufIndex);
485        } else {
486            Fifo::iterator front(mQueue.begin());
487            // buffer currently queued is freed
488            mSlots[*front].mBufferState = BufferSlot::FREE;
489            // and we record the new buffer index in the queued list
490            *front = bufIndex;
491        }
492    }
493
494    mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
495    mSlots[bufIndex].mTimestamp = timestamp;
496    // TODO: (Confirm) Don't want to signal dequeue here.
497    // May be just in asynchronous mode?
498    // mDequeueCondition.signal();
499
500    // Once the queuing is done, we need to let the listener
501    // and signal the buffer consumer (encoder) know that a
502    // buffer is available
503    onFrameReceivedLocked();
504
505    *outWidth = mDefaultWidth;
506    *outHeight = mDefaultHeight;
507    *outTransform = 0;
508
509    return OK;
510}
511
512
513// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
514// or listeners that a frame has been received
515// It is supposed to be called only from queuebuffer.
516// The buffer is NOT made available for dequeueing immediately. We need to
517// wait to hear from StageFrightRecorder to set the buffer FREE
518// Make sure this is called when the mutex is locked
519status_t SurfaceMediaSource::onFrameReceivedLocked() {
520    LOGV("On Frame Received locked");
521    // Signal the encoder that a new frame has arrived
522    mFrameAvailableCondition.signal();
523
524    // call back the listener
525    // TODO: The listener may not be needed in SurfaceMediaSource at all.
526    // This can be made a SurfaceTexture specific thing
527    sp<FrameAvailableListener> listener;
528    if (mSynchronousMode || mQueue.empty()) {
529        listener = mFrameAvailableListener;
530    }
531
532    if (listener != 0) {
533        listener->onFrameAvailable();
534    }
535    return OK;
536}
537
538
539void SurfaceMediaSource::cancelBuffer(int bufIndex) {
540    LOGV("SurfaceMediaSource::cancelBuffer");
541    Mutex::Autolock lock(mMutex);
542    if (bufIndex < 0 || bufIndex >= mBufferCount) {
543        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
544                mBufferCount, bufIndex);
545        return;
546    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
547        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
548                bufIndex, mSlots[bufIndex].mBufferState);
549        return;
550    }
551    mSlots[bufIndex].mBufferState = BufferSlot::FREE;
552    mDequeueCondition.signal();
553}
554
555nsecs_t SurfaceMediaSource::getTimestamp() {
556    LOGV("SurfaceMediaSource::getTimestamp");
557    Mutex::Autolock lock(mMutex);
558    return mCurrentTimestamp;
559}
560
561
562void SurfaceMediaSource::setFrameAvailableListener(
563        const sp<FrameAvailableListener>& listener) {
564    LOGV("SurfaceMediaSource::setFrameAvailableListener");
565    Mutex::Autolock lock(mMutex);
566    mFrameAvailableListener = listener;
567}
568
569void SurfaceMediaSource::freeAllBuffersLocked() {
570    LOGV("freeAllBuffersLocked");
571    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
572        mSlots[i].mGraphicBuffer = 0;
573        mSlots[i].mBufferState = BufferSlot::FREE;
574    }
575}
576
577sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
578    Mutex::Autolock lock(mMutex);
579    return mCurrentBuf;
580}
581
582int SurfaceMediaSource::query(int what, int* outValue)
583{
584    LOGV("query");
585    Mutex::Autolock lock(mMutex);
586    int value;
587    switch (what) {
588    case NATIVE_WINDOW_WIDTH:
589        value = mDefaultWidth;
590        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
591            value = mCurrentBuf->width;
592        break;
593    case NATIVE_WINDOW_HEIGHT:
594        value = mDefaultHeight;
595        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
596            value = mCurrentBuf->height;
597        break;
598    case NATIVE_WINDOW_FORMAT:
599        value = mPixelFormat;
600        break;
601    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
602        value = mSynchronousMode ?
603                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
604        break;
605    default:
606        return BAD_VALUE;
607    }
608    outValue[0] = value;
609    return NO_ERROR;
610}
611
612void SurfaceMediaSource::dump(String8& result) const
613{
614    char buffer[1024];
615    dump(result, "", buffer, 1024);
616}
617
618void SurfaceMediaSource::dump(String8& result, const char* prefix,
619        char* buffer, size_t SIZE) const
620{
621    Mutex::Autolock _l(mMutex);
622    snprintf(buffer, SIZE,
623            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
624            "mPixelFormat=%d, \n",
625            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
626            mPixelFormat);
627    result.append(buffer);
628
629    String8 fifo;
630    int fifoSize = 0;
631    Fifo::const_iterator i(mQueue.begin());
632    while (i != mQueue.end()) {
633        snprintf(buffer, SIZE, "%02d ", *i++);
634        fifoSize++;
635        fifo.append(buffer);
636    }
637
638    result.append(buffer);
639
640    struct {
641        const char * operator()(int state) const {
642            switch (state) {
643                case BufferSlot::DEQUEUED: return "DEQUEUED";
644                case BufferSlot::QUEUED: return "QUEUED";
645                case BufferSlot::FREE: return "FREE";
646                default: return "Unknown";
647            }
648        }
649    } stateName;
650
651    for (int i = 0; i < mBufferCount; i++) {
652        const BufferSlot& slot(mSlots[i]);
653        snprintf(buffer, SIZE,
654                "%s%s[%02d] state=%-8s, "
655                "timestamp=%lld\n",
656                prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
657                slot.mTimestamp
658        );
659        result.append(buffer);
660    }
661}
662
663status_t SurfaceMediaSource::setFrameRate(int32_t fps)
664{
665    Mutex::Autolock lock(mMutex);
666    const int MAX_FRAME_RATE = 60;
667    if (fps < 0 || fps > MAX_FRAME_RATE) {
668        return BAD_VALUE;
669    }
670    mFrameRate = fps;
671    return OK;
672}
673
674bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
675    LOGV("isMetaDataStoredInVideoBuffers");
676    return true;
677}
678
679int32_t SurfaceMediaSource::getFrameRate( ) const {
680    Mutex::Autolock lock(mMutex);
681    return mFrameRate;
682}
683
684status_t SurfaceMediaSource::start(MetaData *params)
685{
686    LOGV("started!");
687    return OK;
688}
689
690
691status_t SurfaceMediaSource::stop()
692{
693    LOGV("Stop");
694
695    Mutex::Autolock lock(mMutex);
696    // TODO: Add waiting on mFrameCompletedCondition here?
697    mStopped = true;
698    mFrameAvailableCondition.signal();
699    mDequeueCondition.signal();
700    mQueue.clear();
701    freeAllBuffersLocked();
702
703    return OK;
704}
705
706sp<MetaData> SurfaceMediaSource::getFormat()
707{
708    LOGV("getFormat");
709    Mutex::Autolock autoLock(mMutex);
710    sp<MetaData> meta = new MetaData;
711
712    meta->setInt32(kKeyWidth, mDefaultWidth);
713    meta->setInt32(kKeyHeight, mDefaultHeight);
714    // The encoder format is set as an opaque colorformat
715    // The encoder will later find out the actual colorformat
716    // from the GL Frames itself.
717    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
718    meta->setInt32(kKeyStride, mDefaultWidth);
719    meta->setInt32(kKeySliceHeight, mDefaultHeight);
720    meta->setInt32(kKeyFrameRate, mFrameRate);
721    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
722    return meta;
723}
724
725status_t SurfaceMediaSource::read( MediaBuffer **buffer,
726                                    const ReadOptions *options)
727{
728    Mutex::Autolock autoLock(mMutex) ;
729
730    LOGV("Read. Size of queued buffer: %d", mQueue.size());
731    *buffer = NULL;
732
733    // If the recording has started and the queue is empty, then just
734    // wait here till the frames come in from the client side
735    while (!mStopped && mQueue.empty()) {
736        LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
737        mFrameAvailableCondition.wait(mMutex);
738    }
739
740    // If the loop was exited as a result of stopping the recording,
741    // it is OK
742    if (mStopped) {
743        LOGV("Read: SurfaceMediaSource is stopped. Returning NO_INIT;");
744        return NO_INIT;
745    }
746
747    // Update the current buffer info
748    // TODO: mCurrentSlot can be made a bufferstate since there
749    // can be more than one "current" slots.
750    Fifo::iterator front(mQueue.begin());
751    mCurrentSlot = *front;
752    mQueue.erase(front);
753    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
754    int64_t prevTimeStamp = mCurrentTimestamp;
755    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
756    mNumFramesEncoded++;
757    // Pass the data to the MediaBuffer. Pass in only the metadata
758    passMetadataBufferLocked(buffer);
759
760    (*buffer)->setObserver(this);
761    (*buffer)->add_ref();
762    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
763    LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
764            mNumFramesEncoded, mCurrentTimestamp / 1000,
765            mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
766
767    return OK;
768}
769
770// Pass the data to the MediaBuffer. Pass in only the metadata
771// The metadata passed consists of two parts:
772// 1. First, there is an integer indicating that it is a GRAlloc
773// source (kMetadataBufferTypeGrallocSource)
774// 2. This is followed by the buffer_handle_t that is a handle to the
775// GRalloc buffer. The encoder needs to interpret this GRalloc handle
776// and encode the frames.
777// --------------------------------------------------------------
778// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
779// --------------------------------------------------------------
780// Note: Call only when you have the lock
781void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
782    LOGV("passMetadataBuffer");
783    // MediaBuffer allocates and owns this data
784    MediaBuffer *tempBuffer =
785        new MediaBuffer(4 + sizeof(buffer_handle_t));
786    char *data = (char *)tempBuffer->data();
787    if (data == NULL) {
788        LOGE("Cannot allocate memory for metadata buffer!");
789        return;
790    }
791    OMX_U32 type = kMetadataBufferTypeGrallocSource;
792    memcpy(data, &type, 4);
793    memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
794    *buffer = tempBuffer;
795
796    LOGV("handle = %p, , offset = %d, length = %d",
797            mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
798}
799
800void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
801    LOGV("signalBufferReturned");
802
803    bool foundBuffer = false;
804    Mutex::Autolock autoLock(mMutex);
805
806    if (mStopped) {
807        LOGV("signalBufferReturned: mStopped = true! Nothing to do!");
808        return;
809    }
810
811    for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
812        if (mSlots[id].mGraphicBuffer == NULL) {
813            continue;
814        }
815        if (checkBufferMatchesSlot(id, buffer)) {
816            LOGV("Slot %d returned, matches handle = %p", id,
817                    mSlots[id].mGraphicBuffer->handle);
818            mSlots[id].mBufferState = BufferSlot::FREE;
819            buffer->setObserver(0);
820            buffer->release();
821            mDequeueCondition.signal();
822            mFrameCompleteCondition.signal();
823            foundBuffer = true;
824            break;
825        }
826    }
827
828    if (!foundBuffer) {
829        CHECK_EQ(0, "signalBufferReturned: bogus buffer");
830    }
831}
832
833bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
834    LOGV("Check if Buffer matches slot");
835    // need to convert to char* for pointer arithmetic and then
836    // copy the byte stream into our handle
837    buffer_handle_t bufferHandle ;
838    memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
839    return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
840}
841
842} // end of namespace android
843