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/foundation/ADebug.h>
     20 #include <media/stagefright/SurfaceMediaSource.h>
     21 #include <media/stagefright/MediaDefs.h>
     22 #include <media/stagefright/MetaData.h>
     23 #include <OMX_IVCommon.h>
     24 #include <media/hardware/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 
     36 namespace android {
     37 
     38 SurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight) :
     39     mWidth(bufferWidth),
     40     mHeight(bufferHeight),
     41     mCurrentSlot(BufferQueue::INVALID_BUFFER_SLOT),
     42     mNumPendingBuffers(0),
     43     mCurrentTimestamp(0),
     44     mFrameRate(30),
     45     mStarted(false),
     46     mNumFramesReceived(0),
     47     mNumFramesEncoded(0),
     48     mFirstFrameTimestamp(0),
     49     mMaxAcquiredBufferCount(4),  // XXX double-check the default
     50     mUseAbsoluteTimestamps(false) {
     51     ALOGV("SurfaceMediaSource");
     52 
     53     if (bufferWidth == 0 || bufferHeight == 0) {
     54         ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight);
     55     }
     56 
     57     mBufferQueue = new BufferQueue();
     58     mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight);
     59     mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
     60             GRALLOC_USAGE_HW_TEXTURE);
     61 
     62     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     63 
     64     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     65     // reference once the ctor ends, as that would cause the refcount of 'this'
     66     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     67     // that's what we create.
     68     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
     69     sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
     70 
     71     status_t err = mBufferQueue->consumerConnect(proxy, false);
     72     if (err != NO_ERROR) {
     73         ALOGE("SurfaceMediaSource: error connecting to BufferQueue: %s (%d)",
     74                 strerror(-err), err);
     75     }
     76 }
     77 
     78 SurfaceMediaSource::~SurfaceMediaSource() {
     79     ALOGV("~SurfaceMediaSource");
     80     CHECK(!mStarted);
     81 }
     82 
     83 nsecs_t SurfaceMediaSource::getTimestamp() {
     84     ALOGV("getTimestamp");
     85     Mutex::Autolock lock(mMutex);
     86     return mCurrentTimestamp;
     87 }
     88 
     89 void SurfaceMediaSource::setFrameAvailableListener(
     90         const sp<FrameAvailableListener>& listener) {
     91     ALOGV("setFrameAvailableListener");
     92     Mutex::Autolock lock(mMutex);
     93     mFrameAvailableListener = listener;
     94 }
     95 
     96 void SurfaceMediaSource::dump(String8& result) const
     97 {
     98     char buffer[1024];
     99     dump(result, "", buffer, 1024);
    100 }
    101 
    102 void SurfaceMediaSource::dump(String8& result, const char* prefix,
    103         char* buffer, size_t SIZE) const
    104 {
    105     Mutex::Autolock lock(mMutex);
    106 
    107     result.append(buffer);
    108     mBufferQueue->dump(result, "");
    109 }
    110 
    111 status_t SurfaceMediaSource::setFrameRate(int32_t fps)
    112 {
    113     ALOGV("setFrameRate");
    114     Mutex::Autolock lock(mMutex);
    115     const int MAX_FRAME_RATE = 60;
    116     if (fps < 0 || fps > MAX_FRAME_RATE) {
    117         return BAD_VALUE;
    118     }
    119     mFrameRate = fps;
    120     return OK;
    121 }
    122 
    123 bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
    124     ALOGV("isMetaDataStoredInVideoBuffers");
    125     return true;
    126 }
    127 
    128 int32_t SurfaceMediaSource::getFrameRate( ) const {
    129     ALOGV("getFrameRate");
    130     Mutex::Autolock lock(mMutex);
    131     return mFrameRate;
    132 }
    133 
    134 status_t SurfaceMediaSource::start(MetaData *params)
    135 {
    136     ALOGV("start");
    137 
    138     Mutex::Autolock lock(mMutex);
    139 
    140     CHECK(!mStarted);
    141 
    142     mStartTimeNs = 0;
    143     int64_t startTimeUs;
    144     int32_t bufferCount = 0;
    145     if (params) {
    146         if (params->findInt64(kKeyTime, &startTimeUs)) {
    147             mStartTimeNs = startTimeUs * 1000;
    148         }
    149 
    150         if (!params->findInt32(kKeyNumBuffers, &bufferCount)) {
    151             ALOGE("Failed to find the advertised buffer count");
    152             return UNKNOWN_ERROR;
    153         }
    154 
    155         if (bufferCount <= 1) {
    156             ALOGE("bufferCount %d is too small", bufferCount);
    157             return BAD_VALUE;
    158         }
    159 
    160         mMaxAcquiredBufferCount = bufferCount;
    161     }
    162 
    163     CHECK_GT(mMaxAcquiredBufferCount, 1);
    164 
    165     status_t err =
    166         mBufferQueue->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount);
    167 
    168     if (err != OK) {
    169         return err;
    170     }
    171 
    172     mNumPendingBuffers = 0;
    173     mStarted = true;
    174 
    175     return OK;
    176 }
    177 
    178 status_t SurfaceMediaSource::setMaxAcquiredBufferCount(size_t count) {
    179     ALOGV("setMaxAcquiredBufferCount(%d)", count);
    180     Mutex::Autolock lock(mMutex);
    181 
    182     CHECK_GT(count, 1);
    183     mMaxAcquiredBufferCount = count;
    184 
    185     return OK;
    186 }
    187 
    188 status_t SurfaceMediaSource::setUseAbsoluteTimestamps() {
    189     ALOGV("setUseAbsoluteTimestamps");
    190     Mutex::Autolock lock(mMutex);
    191     mUseAbsoluteTimestamps = true;
    192 
    193     return OK;
    194 }
    195 
    196 status_t SurfaceMediaSource::stop()
    197 {
    198     ALOGV("stop");
    199     Mutex::Autolock lock(mMutex);
    200 
    201     if (!mStarted) {
    202         return OK;
    203     }
    204 
    205     while (mNumPendingBuffers > 0) {
    206         ALOGI("Still waiting for %d buffers to be returned.",
    207                 mNumPendingBuffers);
    208 
    209 #if DEBUG_PENDING_BUFFERS
    210         for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
    211             ALOGI("%d: %p", i, mPendingBuffers.itemAt(i));
    212         }
    213 #endif
    214 
    215         mMediaBuffersAvailableCondition.wait(mMutex);
    216     }
    217 
    218     mStarted = false;
    219     mFrameAvailableCondition.signal();
    220     mMediaBuffersAvailableCondition.signal();
    221 
    222     return mBufferQueue->consumerDisconnect();
    223 }
    224 
    225 sp<MetaData> SurfaceMediaSource::getFormat()
    226 {
    227     ALOGV("getFormat");
    228 
    229     Mutex::Autolock lock(mMutex);
    230     sp<MetaData> meta = new MetaData;
    231 
    232     meta->setInt32(kKeyWidth, mWidth);
    233     meta->setInt32(kKeyHeight, mHeight);
    234     // The encoder format is set as an opaque colorformat
    235     // The encoder will later find out the actual colorformat
    236     // from the GL Frames itself.
    237     meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
    238     meta->setInt32(kKeyStride, mWidth);
    239     meta->setInt32(kKeySliceHeight, mHeight);
    240     meta->setInt32(kKeyFrameRate, mFrameRate);
    241     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
    242     return meta;
    243 }
    244 
    245 // Pass the data to the MediaBuffer. Pass in only the metadata
    246 // The metadata passed consists of two parts:
    247 // 1. First, there is an integer indicating that it is a GRAlloc
    248 // source (kMetadataBufferTypeGrallocSource)
    249 // 2. This is followed by the buffer_handle_t that is a handle to the
    250 // GRalloc buffer. The encoder needs to interpret this GRalloc handle
    251 // and encode the frames.
    252 // --------------------------------------------------------------
    253 // |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
    254 // --------------------------------------------------------------
    255 // Note: Call only when you have the lock
    256 static void passMetadataBuffer(MediaBuffer **buffer,
    257         buffer_handle_t bufferHandle) {
    258     *buffer = new MediaBuffer(4 + sizeof(buffer_handle_t));
    259     char *data = (char *)(*buffer)->data();
    260     if (data == NULL) {
    261         ALOGE("Cannot allocate memory for metadata buffer!");
    262         return;
    263     }
    264     OMX_U32 type = kMetadataBufferTypeGrallocSource;
    265     memcpy(data, &type, 4);
    266     memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t));
    267 
    268     ALOGV("handle = %p, , offset = %d, length = %d",
    269             bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset());
    270 }
    271 
    272 status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    273                                     const ReadOptions *options)
    274 {
    275     ALOGV("read");
    276     Mutex::Autolock lock(mMutex);
    277 
    278     *buffer = NULL;
    279 
    280     while (mStarted && mNumPendingBuffers == mMaxAcquiredBufferCount) {
    281         mMediaBuffersAvailableCondition.wait(mMutex);
    282     }
    283 
    284     // Update the current buffer info
    285     // TODO: mCurrentSlot can be made a bufferstate since there
    286     // can be more than one "current" slots.
    287 
    288     BufferQueue::BufferItem item;
    289     // If the recording has started and the queue is empty, then just
    290     // wait here till the frames come in from the client side
    291     while (mStarted) {
    292 
    293         status_t err = mBufferQueue->acquireBuffer(&item, 0);
    294         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    295             // wait for a buffer to be queued
    296             mFrameAvailableCondition.wait(mMutex);
    297         } else if (err == OK) {
    298             err = item.mFence->waitForever("SurfaceMediaSource::read");
    299             if (err) {
    300                 ALOGW("read: failed to wait for buffer fence: %d", err);
    301             }
    302 
    303             // First time seeing the buffer?  Added it to the SMS slot
    304             if (item.mGraphicBuffer != NULL) {
    305                 mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
    306             }
    307             mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
    308 
    309             // check for the timing of this buffer
    310             if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) {
    311                 mFirstFrameTimestamp = item.mTimestamp;
    312                 // Initial delay
    313                 if (mStartTimeNs > 0) {
    314                     if (item.mTimestamp < mStartTimeNs) {
    315                         // This frame predates start of record, discard
    316                         mBufferQueue->releaseBuffer(
    317                                 item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY,
    318                                 EGL_NO_SYNC_KHR, Fence::NO_FENCE);
    319                         continue;
    320                     }
    321                     mStartTimeNs = item.mTimestamp - mStartTimeNs;
    322                 }
    323             }
    324             item.mTimestamp = mStartTimeNs + (item.mTimestamp - mFirstFrameTimestamp);
    325 
    326             mNumFramesReceived++;
    327 
    328             break;
    329         } else {
    330             ALOGE("read: acquire failed with error code %d", err);
    331             return ERROR_END_OF_STREAM;
    332         }
    333 
    334     }
    335 
    336     // If the loop was exited as a result of stopping the recording,
    337     // it is OK
    338     if (!mStarted) {
    339         ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
    340         return ERROR_END_OF_STREAM;
    341     }
    342 
    343     mCurrentSlot = item.mBuf;
    344 
    345     // First time seeing the buffer?  Added it to the SMS slot
    346     if (item.mGraphicBuffer != NULL) {
    347         mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
    348     }
    349     mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
    350 
    351     mCurrentBuffers.push_back(mSlots[mCurrentSlot].mGraphicBuffer);
    352     int64_t prevTimeStamp = mCurrentTimestamp;
    353     mCurrentTimestamp = item.mTimestamp;
    354 
    355     mNumFramesEncoded++;
    356     // Pass the data to the MediaBuffer. Pass in only the metadata
    357 
    358     passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);
    359 
    360     (*buffer)->setObserver(this);
    361     (*buffer)->add_ref();
    362     (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
    363     ALOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
    364             mNumFramesEncoded, mCurrentTimestamp / 1000,
    365             mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
    366 
    367     ++mNumPendingBuffers;
    368 
    369 #if DEBUG_PENDING_BUFFERS
    370     mPendingBuffers.push_back(*buffer);
    371 #endif
    372 
    373     ALOGV("returning mbuf %p", *buffer);
    374 
    375     return OK;
    376 }
    377 
    378 static buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) {
    379     // need to convert to char* for pointer arithmetic and then
    380     // copy the byte stream into our handle
    381     buffer_handle_t bufferHandle;
    382     memcpy(&bufferHandle, (char*)(buffer->data()) + 4, sizeof(buffer_handle_t));
    383     return bufferHandle;
    384 }
    385 
    386 void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    387     ALOGV("signalBufferReturned");
    388 
    389     bool foundBuffer = false;
    390 
    391     Mutex::Autolock lock(mMutex);
    392 
    393     buffer_handle_t bufferHandle = getMediaBufferHandle(buffer);
    394 
    395     for (size_t i = 0; i < mCurrentBuffers.size(); i++) {
    396         if (mCurrentBuffers[i]->handle == bufferHandle) {
    397             mCurrentBuffers.removeAt(i);
    398             foundBuffer = true;
    399             break;
    400         }
    401     }
    402 
    403     if (!foundBuffer) {
    404         ALOGW("returned buffer was not found in the current buffer list");
    405     }
    406 
    407     for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
    408         if (mSlots[id].mGraphicBuffer == NULL) {
    409             continue;
    410         }
    411 
    412         if (bufferHandle == mSlots[id].mGraphicBuffer->handle) {
    413             ALOGV("Slot %d returned, matches handle = %p", id,
    414                     mSlots[id].mGraphicBuffer->handle);
    415 
    416             mBufferQueue->releaseBuffer(id, mSlots[id].mFrameNumber,
    417                                         EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
    418                     Fence::NO_FENCE);
    419 
    420             buffer->setObserver(0);
    421             buffer->release();
    422 
    423             foundBuffer = true;
    424             break;
    425         }
    426     }
    427 
    428     if (!foundBuffer) {
    429         CHECK(!"signalBufferReturned: bogus buffer");
    430     }
    431 
    432 #if DEBUG_PENDING_BUFFERS
    433     for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
    434         if (mPendingBuffers.itemAt(i) == buffer) {
    435             mPendingBuffers.removeAt(i);
    436             break;
    437         }
    438     }
    439 #endif
    440 
    441     --mNumPendingBuffers;
    442     mMediaBuffersAvailableCondition.broadcast();
    443 }
    444 
    445 // Part of the BufferQueue::ConsumerListener
    446 void SurfaceMediaSource::onFrameAvailable() {
    447     ALOGV("onFrameAvailable");
    448 
    449     sp<FrameAvailableListener> listener;
    450     { // scope for the lock
    451         Mutex::Autolock lock(mMutex);
    452         mFrameAvailableCondition.broadcast();
    453         listener = mFrameAvailableListener;
    454     }
    455 
    456     if (listener != NULL) {
    457         ALOGV("actually calling onFrameAvailable");
    458         listener->onFrameAvailable();
    459     }
    460 }
    461 
    462 // SurfaceMediaSource hijacks this event to assume
    463 // the prodcuer is disconnecting from the BufferQueue
    464 // and that it should stop the recording
    465 void SurfaceMediaSource::onBuffersReleased() {
    466     ALOGV("onBuffersReleased");
    467 
    468     Mutex::Autolock lock(mMutex);
    469 
    470     mFrameAvailableCondition.signal();
    471 
    472     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    473        mSlots[i].mGraphicBuffer = 0;
    474     }
    475 }
    476 
    477 } // end of namespace android
    478