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