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