Home | History | Annotate | Download | only in libstagefright
      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 
     35 namespace android {
     36 
     37 SurfaceMediaSource::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 
     58 SurfaceMediaSource::~SurfaceMediaSource() {
     59     LOGV("SurfaceMediaSource::~SurfaceMediaSource");
     60     if (!mStopped) {
     61         stop();
     62     }
     63 }
     64 
     65 size_t SurfaceMediaSource::getQueuedCount() const {
     66     Mutex::Autolock lock(mMutex);
     67     return mQueue.size();
     68 }
     69 
     70 status_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
    105 status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
    106     Mutex::Autolock lock(mMutex);
    107     return setBufferCountServerLocked(bufferCount);
    108 }
    109 
    110 status_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 
    152 status_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 
    165 status_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             // XXX: This will be changed to USAGE_HW_VIDEO_ENCODER once driver
    340             // issues with that flag get fixed.
    341             usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    342             status_t error;
    343             sp<GraphicBuffer> graphicBuffer(
    344                     mGraphicBufferAlloc->createGraphicBuffer(
    345                                     w, h, format, usage, &error));
    346             if (graphicBuffer == 0) {
    347                 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
    348                 return error;
    349             }
    350             if (updateFormat) {
    351                 mPixelFormat = format;
    352             }
    353             mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
    354             mSlots[bufIndex].mRequestBufferCalled = false;
    355             returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    356     }
    357     return returnFlags;
    358 }
    359 
    360 // TODO: clean this up
    361 status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
    362     Mutex::Autolock lock(mMutex);
    363     if (mStopped) {
    364         LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
    365         return NO_INIT;
    366     }
    367 
    368     if (!enabled) {
    369         // Async mode is not allowed
    370         LOGE("SurfaceMediaSource can be used only synchronous mode!");
    371         return INVALID_OPERATION;
    372     }
    373 
    374     if (mSynchronousMode != enabled) {
    375         // - if we're going to asynchronous mode, the queue is guaranteed to be
    376         // empty here
    377         // - if the client set the number of buffers, we're guaranteed that
    378         // we have at least 3 (because we don't allow less)
    379         mSynchronousMode = enabled;
    380         mDequeueCondition.signal();
    381     }
    382     return OK;
    383 }
    384 
    385 status_t SurfaceMediaSource::connect(int api,
    386         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    387     LOGV("SurfaceMediaSource::connect");
    388     Mutex::Autolock lock(mMutex);
    389 
    390     if (mStopped) {
    391         LOGE("Connect: SurfaceMediaSource has been stopped!");
    392         return NO_INIT;
    393     }
    394 
    395     status_t err = NO_ERROR;
    396     switch (api) {
    397         case NATIVE_WINDOW_API_EGL:
    398         case NATIVE_WINDOW_API_CPU:
    399         case NATIVE_WINDOW_API_MEDIA:
    400         case NATIVE_WINDOW_API_CAMERA:
    401             if (mConnectedApi != NO_CONNECTED_API) {
    402                 err = -EINVAL;
    403             } else {
    404                 mConnectedApi = api;
    405                 *outWidth = mDefaultWidth;
    406                 *outHeight = mDefaultHeight;
    407                 *outTransform = 0;
    408             }
    409             break;
    410         default:
    411             err = -EINVAL;
    412             break;
    413     }
    414     return err;
    415 }
    416 
    417 // This is called by the client side when it is done
    418 // TODO: Currently, this also sets mStopped to true which
    419 // is needed for unblocking the encoder which might be
    420 // waiting to read more frames. So if on the client side,
    421 // the same thread supplies the frames and also calls stop
    422 // on the encoder, the client has to call disconnect before
    423 // it calls stop.
    424 // In the case of the camera,
    425 // that need not be required since the thread supplying the
    426 // frames is separate than the one calling stop.
    427 status_t SurfaceMediaSource::disconnect(int api) {
    428     LOGV("SurfaceMediaSource::disconnect");
    429     Mutex::Autolock lock(mMutex);
    430 
    431     if (mStopped) {
    432         LOGE("disconnect: SurfaceMediaSoource is already stopped!");
    433         return NO_INIT;
    434     }
    435 
    436     status_t err = NO_ERROR;
    437     switch (api) {
    438         case NATIVE_WINDOW_API_EGL:
    439         case NATIVE_WINDOW_API_CPU:
    440         case NATIVE_WINDOW_API_MEDIA:
    441         case NATIVE_WINDOW_API_CAMERA:
    442             if (mConnectedApi == api) {
    443                 mConnectedApi = NO_CONNECTED_API;
    444                 mStopped = true;
    445                 mDequeueCondition.signal();
    446                 mFrameAvailableCondition.signal();
    447             } else {
    448                 err = -EINVAL;
    449             }
    450             break;
    451         default:
    452             err = -EINVAL;
    453             break;
    454     }
    455     return err;
    456 }
    457 
    458 status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
    459         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    460     LOGV("queueBuffer");
    461 
    462     Mutex::Autolock lock(mMutex);
    463     *outWidth = mDefaultWidth;
    464     *outHeight = mDefaultHeight;
    465     *outTransform = 0;
    466 
    467     if (bufIndex < 0 || bufIndex >= mBufferCount) {
    468         LOGE("queueBuffer: slot index out of range [0, %d]: %d",
    469                 mBufferCount, bufIndex);
    470         return -EINVAL;
    471     } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
    472         LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
    473                 bufIndex, mSlots[bufIndex].mBufferState);
    474         return -EINVAL;
    475     } else if (!mSlots[bufIndex].mRequestBufferCalled) {
    476         LOGE("queueBuffer: slot %d was enqueued without requesting a "
    477                 "buffer", bufIndex);
    478         return -EINVAL;
    479     }
    480 
    481     if (mNumFramesReceived == 0) {
    482         mFirstFrameTimestamp = timestamp;
    483         // Initial delay
    484         if (mStartTimeNs > 0) {
    485             if (timestamp < mStartTimeNs) {
    486                 // This frame predates start of record, discard
    487                 mSlots[bufIndex].mBufferState = BufferSlot::FREE;
    488                 mDequeueCondition.signal();
    489                 return OK;
    490             }
    491             mStartTimeNs = timestamp - mStartTimeNs;
    492         }
    493     }
    494     timestamp = mStartTimeNs + (timestamp - mFirstFrameTimestamp);
    495 
    496     mNumFramesReceived++;
    497     if (mSynchronousMode) {
    498         // in synchronous mode we queue all buffers in a FIFO
    499         mQueue.push_back(bufIndex);
    500         LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
    501             mNumFramesReceived, bufIndex, mQueue.size(),
    502             mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
    503     } else {
    504         // in asynchronous mode we only keep the most recent buffer
    505         if (mQueue.empty()) {
    506             mQueue.push_back(bufIndex);
    507         } else {
    508             Fifo::iterator front(mQueue.begin());
    509             // buffer currently queued is freed
    510             mSlots[*front].mBufferState = BufferSlot::FREE;
    511             // and we record the new buffer index in the queued list
    512             *front = bufIndex;
    513         }
    514     }
    515 
    516     mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
    517     mSlots[bufIndex].mTimestamp = timestamp;
    518     // TODO: (Confirm) Don't want to signal dequeue here.
    519     // May be just in asynchronous mode?
    520     // mDequeueCondition.signal();
    521 
    522     // Once the queuing is done, we need to let the listener
    523     // and signal the buffer consumer (encoder) know that a
    524     // buffer is available
    525     onFrameReceivedLocked();
    526 
    527 
    528     return OK;
    529 }
    530 
    531 
    532 // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
    533 // or listeners that a frame has been received
    534 // It is supposed to be called only from queuebuffer.
    535 // The buffer is NOT made available for dequeueing immediately. We need to
    536 // wait to hear from StageFrightRecorder to set the buffer FREE
    537 // Make sure this is called when the mutex is locked
    538 status_t SurfaceMediaSource::onFrameReceivedLocked() {
    539     LOGV("On Frame Received locked");
    540     // Signal the encoder that a new frame has arrived
    541     mFrameAvailableCondition.signal();
    542 
    543     // call back the listener
    544     // TODO: The listener may not be needed in SurfaceMediaSource at all.
    545     // This can be made a SurfaceTexture specific thing
    546     sp<FrameAvailableListener> listener;
    547     if (mSynchronousMode || mQueue.empty()) {
    548         listener = mFrameAvailableListener;
    549     }
    550 
    551     if (listener != 0) {
    552         listener->onFrameAvailable();
    553     }
    554     return OK;
    555 }
    556 
    557 
    558 void SurfaceMediaSource::cancelBuffer(int bufIndex) {
    559     LOGV("SurfaceMediaSource::cancelBuffer");
    560     Mutex::Autolock lock(mMutex);
    561     if (bufIndex < 0 || bufIndex >= mBufferCount) {
    562         LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
    563                 mBufferCount, bufIndex);
    564         return;
    565     } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
    566         LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
    567                 bufIndex, mSlots[bufIndex].mBufferState);
    568         return;
    569     }
    570     mSlots[bufIndex].mBufferState = BufferSlot::FREE;
    571     mDequeueCondition.signal();
    572 }
    573 
    574 nsecs_t SurfaceMediaSource::getTimestamp() {
    575     LOGV("SurfaceMediaSource::getTimestamp");
    576     Mutex::Autolock lock(mMutex);
    577     return mCurrentTimestamp;
    578 }
    579 
    580 
    581 void SurfaceMediaSource::setFrameAvailableListener(
    582         const sp<FrameAvailableListener>& listener) {
    583     LOGV("SurfaceMediaSource::setFrameAvailableListener");
    584     Mutex::Autolock lock(mMutex);
    585     mFrameAvailableListener = listener;
    586 }
    587 
    588 void SurfaceMediaSource::freeAllBuffersLocked() {
    589     LOGV("freeAllBuffersLocked");
    590     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
    591         mSlots[i].mGraphicBuffer = 0;
    592         mSlots[i].mBufferState = BufferSlot::FREE;
    593     }
    594 }
    595 
    596 sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
    597     Mutex::Autolock lock(mMutex);
    598     return mCurrentBuf;
    599 }
    600 
    601 int SurfaceMediaSource::query(int what, int* outValue)
    602 {
    603     LOGV("query");
    604     Mutex::Autolock lock(mMutex);
    605     int value;
    606     switch (what) {
    607     case NATIVE_WINDOW_WIDTH:
    608         value = mDefaultWidth;
    609         if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
    610             value = mCurrentBuf->width;
    611         break;
    612     case NATIVE_WINDOW_HEIGHT:
    613         value = mDefaultHeight;
    614         if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
    615             value = mCurrentBuf->height;
    616         break;
    617     case NATIVE_WINDOW_FORMAT:
    618         value = mPixelFormat;
    619         break;
    620     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
    621         value = mSynchronousMode ?
    622                 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
    623         break;
    624     default:
    625         return BAD_VALUE;
    626     }
    627     outValue[0] = value;
    628     return NO_ERROR;
    629 }
    630 
    631 void SurfaceMediaSource::dump(String8& result) const
    632 {
    633     char buffer[1024];
    634     dump(result, "", buffer, 1024);
    635 }
    636 
    637 void SurfaceMediaSource::dump(String8& result, const char* prefix,
    638         char* buffer, size_t SIZE) const
    639 {
    640     Mutex::Autolock _l(mMutex);
    641     snprintf(buffer, SIZE,
    642             "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
    643             "mPixelFormat=%d, \n",
    644             prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
    645             mPixelFormat);
    646     result.append(buffer);
    647 
    648     String8 fifo;
    649     int fifoSize = 0;
    650     Fifo::const_iterator i(mQueue.begin());
    651     while (i != mQueue.end()) {
    652         snprintf(buffer, SIZE, "%02d ", *i++);
    653         fifoSize++;
    654         fifo.append(buffer);
    655     }
    656 
    657     result.append(buffer);
    658 
    659     struct {
    660         const char * operator()(int state) const {
    661             switch (state) {
    662                 case BufferSlot::DEQUEUED: return "DEQUEUED";
    663                 case BufferSlot::QUEUED: return "QUEUED";
    664                 case BufferSlot::FREE: return "FREE";
    665                 default: return "Unknown";
    666             }
    667         }
    668     } stateName;
    669 
    670     for (int i = 0; i < mBufferCount; i++) {
    671         const BufferSlot& slot(mSlots[i]);
    672         snprintf(buffer, SIZE,
    673                 "%s%s[%02d] state=%-8s, "
    674                 "timestamp=%lld\n",
    675                 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
    676                 slot.mTimestamp
    677         );
    678         result.append(buffer);
    679     }
    680 }
    681 
    682 status_t SurfaceMediaSource::setFrameRate(int32_t fps)
    683 {
    684     Mutex::Autolock lock(mMutex);
    685     const int MAX_FRAME_RATE = 60;
    686     if (fps < 0 || fps > MAX_FRAME_RATE) {
    687         return BAD_VALUE;
    688     }
    689     mFrameRate = fps;
    690     return OK;
    691 }
    692 
    693 bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
    694     LOGV("isMetaDataStoredInVideoBuffers");
    695     return true;
    696 }
    697 
    698 int32_t SurfaceMediaSource::getFrameRate( ) const {
    699     Mutex::Autolock lock(mMutex);
    700     return mFrameRate;
    701 }
    702 
    703 status_t SurfaceMediaSource::start(MetaData *params)
    704 {
    705     LOGV("started!");
    706 
    707     mStartTimeNs = 0;
    708     int64_t startTimeUs;
    709     if (params && params->findInt64(kKeyTime, &startTimeUs)) {
    710         mStartTimeNs = startTimeUs * 1000;
    711     }
    712 
    713     return OK;
    714 }
    715 
    716 
    717 status_t SurfaceMediaSource::stop()
    718 {
    719     LOGV("Stop");
    720 
    721     Mutex::Autolock lock(mMutex);
    722     // TODO: Add waiting on mFrameCompletedCondition here?
    723     mStopped = true;
    724     mFrameAvailableCondition.signal();
    725     mDequeueCondition.signal();
    726     mQueue.clear();
    727     freeAllBuffersLocked();
    728 
    729     return OK;
    730 }
    731 
    732 sp<MetaData> SurfaceMediaSource::getFormat()
    733 {
    734     LOGV("getFormat");
    735     Mutex::Autolock autoLock(mMutex);
    736     sp<MetaData> meta = new MetaData;
    737 
    738     meta->setInt32(kKeyWidth, mDefaultWidth);
    739     meta->setInt32(kKeyHeight, mDefaultHeight);
    740     // The encoder format is set as an opaque colorformat
    741     // The encoder will later find out the actual colorformat
    742     // from the GL Frames itself.
    743     meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
    744     meta->setInt32(kKeyStride, mDefaultWidth);
    745     meta->setInt32(kKeySliceHeight, mDefaultHeight);
    746     meta->setInt32(kKeyFrameRate, mFrameRate);
    747     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
    748     return meta;
    749 }
    750 
    751 status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    752                                     const ReadOptions *options)
    753 {
    754     Mutex::Autolock autoLock(mMutex) ;
    755 
    756     LOGV("Read. Size of queued buffer: %d", mQueue.size());
    757     *buffer = NULL;
    758 
    759     // If the recording has started and the queue is empty, then just
    760     // wait here till the frames come in from the client side
    761     while (!mStopped && mQueue.empty()) {
    762         LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
    763         mFrameAvailableCondition.wait(mMutex);
    764     }
    765 
    766     // If the loop was exited as a result of stopping the recording,
    767     // it is OK
    768     if (mStopped) {
    769         LOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
    770         return ERROR_END_OF_STREAM;
    771     }
    772 
    773     // Update the current buffer info
    774     // TODO: mCurrentSlot can be made a bufferstate since there
    775     // can be more than one "current" slots.
    776     Fifo::iterator front(mQueue.begin());
    777     mCurrentSlot = *front;
    778     mQueue.erase(front);
    779     mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
    780     int64_t prevTimeStamp = mCurrentTimestamp;
    781     mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
    782 
    783     mNumFramesEncoded++;
    784     // Pass the data to the MediaBuffer. Pass in only the metadata
    785     passMetadataBufferLocked(buffer);
    786 
    787     (*buffer)->setObserver(this);
    788     (*buffer)->add_ref();
    789     (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
    790     LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
    791             mNumFramesEncoded, mCurrentTimestamp / 1000,
    792             mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
    793 
    794     return OK;
    795 }
    796 
    797 // Pass the data to the MediaBuffer. Pass in only the metadata
    798 // The metadata passed consists of two parts:
    799 // 1. First, there is an integer indicating that it is a GRAlloc
    800 // source (kMetadataBufferTypeGrallocSource)
    801 // 2. This is followed by the buffer_handle_t that is a handle to the
    802 // GRalloc buffer. The encoder needs to interpret this GRalloc handle
    803 // and encode the frames.
    804 // --------------------------------------------------------------
    805 // |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
    806 // --------------------------------------------------------------
    807 // Note: Call only when you have the lock
    808 void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
    809     LOGV("passMetadataBuffer");
    810     // MediaBuffer allocates and owns this data
    811     MediaBuffer *tempBuffer =
    812         new MediaBuffer(4 + sizeof(buffer_handle_t));
    813     char *data = (char *)tempBuffer->data();
    814     if (data == NULL) {
    815         LOGE("Cannot allocate memory for metadata buffer!");
    816         return;
    817     }
    818     OMX_U32 type = kMetadataBufferTypeGrallocSource;
    819     memcpy(data, &type, 4);
    820     memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
    821     *buffer = tempBuffer;
    822 
    823     LOGV("handle = %p, , offset = %d, length = %d",
    824             mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
    825 }
    826 
    827 void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    828     LOGV("signalBufferReturned");
    829 
    830     bool foundBuffer = false;
    831     Mutex::Autolock autoLock(mMutex);
    832 
    833     if (mStopped) {
    834         LOGV("signalBufferReturned: mStopped = true! Nothing to do!");
    835         return;
    836     }
    837 
    838     for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
    839         if (mSlots[id].mGraphicBuffer == NULL) {
    840             continue;
    841         }
    842         if (checkBufferMatchesSlot(id, buffer)) {
    843             LOGV("Slot %d returned, matches handle = %p", id,
    844                     mSlots[id].mGraphicBuffer->handle);
    845             mSlots[id].mBufferState = BufferSlot::FREE;
    846             buffer->setObserver(0);
    847             buffer->release();
    848             mDequeueCondition.signal();
    849             mFrameCompleteCondition.signal();
    850             foundBuffer = true;
    851             break;
    852         }
    853     }
    854 
    855     if (!foundBuffer) {
    856         CHECK_EQ(0, "signalBufferReturned: bogus buffer");
    857     }
    858 }
    859 
    860 bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
    861     LOGV("Check if Buffer matches slot");
    862     // need to convert to char* for pointer arithmetic and then
    863     // copy the byte stream into our handle
    864     buffer_handle_t bufferHandle ;
    865     memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
    866     return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
    867 }
    868 
    869 } // end of namespace android
    870