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