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