Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright 2016, 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 
     17 #include <gui/Surface.h>
     18 
     19 #include <media/ICrypto.h>
     20 #include <media/stagefright/foundation/ABuffer.h>
     21 #include <media/stagefright/foundation/ALooper.h>
     22 #include <media/stagefright/foundation/AMessage.h>
     23 #include <media/stagefright/foundation/AUtils.h>
     24 #include <media/stagefright/MediaBuffer.h>
     25 #include <media/stagefright/MediaCodecList.h>
     26 #include <media/stagefright/MediaCodec.h>
     27 #include <media/stagefright/MetaData.h>
     28 #include <media/stagefright/SimpleDecodingSource.h>
     29 #include <media/stagefright/Utils.h>
     30 
     31 using namespace android;
     32 
     33 const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
     34 const int64_t kTimeoutWaitForInputUs = 5000; // 5 milliseconds
     35 
     36 //static
     37 sp<SimpleDecodingSource> SimpleDecodingSource::Create(
     38         const sp<IMediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow,
     39         const char *desiredCodec) {
     40     sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
     41     const char *mime = NULL;
     42     sp<MetaData> meta = source->getFormat();
     43     CHECK(meta->findCString(kKeyMIMEType, &mime));
     44 
     45     sp<AMessage> format = new AMessage;
     46     if (convertMetaDataToMessage(source->getFormat(), &format) != OK) {
     47         return NULL;
     48     }
     49 
     50     Vector<AString> matchingCodecs;
     51     MediaCodecList::findMatchingCodecs(
     52             mime, false /* encoder */, flags, &matchingCodecs);
     53 
     54     sp<ALooper> looper = new ALooper;
     55     looper->setName("stagefright");
     56     looper->start();
     57 
     58     sp<MediaCodec> codec;
     59 
     60     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
     61         const AString &componentName = matchingCodecs[i];
     62         if (desiredCodec != NULL && componentName.compare(desiredCodec)) {
     63             continue;
     64         }
     65 
     66         ALOGV("Attempting to allocate codec '%s'", componentName.c_str());
     67 
     68         codec = MediaCodec::CreateByComponentName(looper, componentName);
     69         if (codec != NULL) {
     70             ALOGI("Successfully allocated codec '%s'", componentName.c_str());
     71 
     72             status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
     73             if (err == OK) {
     74                 err = codec->getOutputFormat(&format);
     75             }
     76             if (err == OK) {
     77                 return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
     78             }
     79 
     80             ALOGD("Failed to configure codec '%s'", componentName.c_str());
     81             codec->release();
     82             codec = NULL;
     83         }
     84     }
     85 
     86     looper->stop();
     87     ALOGE("No matching decoder! (mime: %s)", mime);
     88     return NULL;
     89 }
     90 
     91 SimpleDecodingSource::SimpleDecodingSource(
     92         const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
     93         bool usingSurface, const sp<AMessage> &format)
     94     : mCodec(codec),
     95       mSource(source),
     96       mLooper(looper),
     97       mUsingSurface(usingSurface),
     98       mProtectedState(format) {
     99     mCodec->getName(&mComponentName);
    100 }
    101 
    102 SimpleDecodingSource::~SimpleDecodingSource() {
    103     mCodec->release();
    104     mLooper->stop();
    105 }
    106 
    107 status_t SimpleDecodingSource::start(MetaData *params) {
    108     (void)params;
    109     Mutexed<ProtectedState>::Locked me(mProtectedState);
    110     if (me->mState != INIT) {
    111         return -EINVAL;
    112     }
    113     status_t res = mCodec->start();
    114     if (res == OK) {
    115         res = mSource->start();
    116     }
    117 
    118     if (res == OK) {
    119         me->mState = STARTED;
    120         me->mQueuedInputEOS = false;
    121         me->mGotOutputEOS = false;
    122     } else {
    123         me->mState = ERROR;
    124     }
    125 
    126     return res;
    127 }
    128 
    129 status_t SimpleDecodingSource::stop() {
    130     Mutexed<ProtectedState>::Locked me(mProtectedState);
    131     if (me->mState != STARTED) {
    132         return -EINVAL;
    133     }
    134 
    135     // wait for any pending reads to complete
    136     me->mState = STOPPING;
    137     while (me->mReading) {
    138         me.waitForCondition(me->mReadCondition);
    139     }
    140 
    141     status_t res1 = mCodec->stop();
    142     if (res1 != OK) {
    143         mCodec->release();
    144     }
    145     status_t res2 = mSource->stop();
    146     if (res1 == OK && res2 == OK) {
    147         me->mState = STOPPED;
    148     } else {
    149         me->mState = ERROR;
    150     }
    151     return res1 != OK ? res1 : res2;
    152 }
    153 
    154 sp<MetaData> SimpleDecodingSource::getFormat() {
    155     Mutexed<ProtectedState>::Locked me(mProtectedState);
    156     if (me->mState == STARTED || me->mState == INIT) {
    157         sp<MetaData> meta = new MetaData();
    158         convertMessageToMetaData(me->mFormat, meta);
    159         return meta;
    160     }
    161     return NULL;
    162 }
    163 
    164 SimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
    165     : mReading(false),
    166       mFormat(format),
    167       mState(INIT),
    168       mQueuedInputEOS(false),
    169       mGotOutputEOS(false) {
    170 }
    171 
    172 status_t SimpleDecodingSource::read(
    173         MediaBuffer **buffer, const ReadOptions *options) {
    174     *buffer = NULL;
    175 
    176     Mutexed<ProtectedState>::Locked me(mProtectedState);
    177     if (me->mState != STARTED) {
    178         return ERROR_END_OF_STREAM;
    179     }
    180     me->mReading = true;
    181 
    182     status_t res = doRead(me, buffer, options);
    183 
    184     me.lock();
    185     me->mReading = false;
    186     if (me->mState != STARTED) {
    187         me->mReadCondition.signal();
    188     }
    189 
    190     return res;
    191 }
    192 
    193 status_t SimpleDecodingSource::doRead(
    194         Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options) {
    195     // |me| is always locked on entry, but is allowed to be unlocked on exit
    196     CHECK_EQ(me->mState, STARTED);
    197 
    198     size_t out_ix, in_ix, out_offset, out_size;
    199     int64_t out_pts;
    200     uint32_t out_flags;
    201     status_t res;
    202 
    203     // flush codec on seek
    204     IMediaSource::ReadOptions::SeekMode mode;
    205     if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
    206         me->mQueuedInputEOS = false;
    207         me->mGotOutputEOS = false;
    208         mCodec->flush();
    209     }
    210 
    211     if (me->mGotOutputEOS) {
    212         return ERROR_END_OF_STREAM;
    213     }
    214 
    215     for (int retries = 0; ++retries; ) {
    216         // If we fill all available input buffers, we should expect that
    217         // the codec produces at least one output buffer. Also, the codec
    218         // should produce an output buffer in at most 1 seconds. Retry a
    219         // few times nonetheless.
    220         while (!me->mQueuedInputEOS) {
    221             // allow some time to get input buffer after flush
    222             res = mCodec->dequeueInputBuffer(&in_ix, kTimeoutWaitForInputUs);
    223             if (res == -EAGAIN) {
    224                 // no available input buffers
    225                 break;
    226             }
    227 
    228             sp<ABuffer> in_buffer;
    229             if (res == OK) {
    230                 res = mCodec->getInputBuffer(in_ix, &in_buffer);
    231             }
    232 
    233             if (res != OK || in_buffer == NULL) {
    234                 ALOGW("[%s] could not get input buffer #%zu",
    235                         mComponentName.c_str(), in_ix);
    236                 me->mState = ERROR;
    237                 return UNKNOWN_ERROR;
    238             }
    239 
    240             MediaBuffer *in_buf;
    241             while (true) {
    242                 in_buf = NULL;
    243                 me.unlock();
    244                 res = mSource->read(&in_buf, options);
    245                 me.lock();
    246                 if (res != OK || me->mState != STARTED) {
    247                     if (in_buf != NULL) {
    248                         in_buf->release();
    249                         in_buf = NULL;
    250                     }
    251 
    252                     // queue EOS
    253                     me->mQueuedInputEOS = true;
    254                     if (mCodec->queueInputBuffer(
    255                                  in_ix, 0 /* offset */, 0 /* size */,
    256                                  0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
    257                         ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
    258                         me->mState = ERROR;
    259                         return UNKNOWN_ERROR;
    260                     }
    261 
    262                     // don't stop on EOS, but report error or EOS on stop
    263                     if (res != ERROR_END_OF_STREAM) {
    264                         me->mState = ERROR;
    265                         return res;
    266                     }
    267                     if (me->mState != STARTED) {
    268                         return ERROR_END_OF_STREAM;
    269                     }
    270                     break;
    271                 }
    272                 if (in_buf == NULL) { // should not happen
    273                     continue;
    274                 } else if (in_buf->range_length() != 0) {
    275                     break;
    276                 }
    277                 in_buf->release();
    278             }
    279 
    280             if (in_buf != NULL) {
    281                 int64_t timestampUs = 0;
    282                 CHECK(in_buf->meta_data()->findInt64(kKeyTime, &timestampUs));
    283                 if (in_buf->range_length() > in_buffer->capacity()) {
    284                     ALOGW("'%s' received %zu input bytes for buffer of size %zu",
    285                             mComponentName.c_str(),
    286                             in_buf->range_length(), in_buffer->capacity());
    287                 }
    288                 memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
    289                        min(in_buf->range_length(), in_buffer->capacity()));
    290 
    291                 res = mCodec->queueInputBuffer(
    292                         in_ix, 0 /* offset */, in_buf->range_length(),
    293                         timestampUs, 0 /* flags */);
    294                 if (res != OK) {
    295                     ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
    296                     me->mState = ERROR;
    297                 }
    298                 in_buf->release();
    299             }
    300         }
    301 
    302         me.unlock();
    303         res = mCodec->dequeueOutputBuffer(
    304                 &out_ix, &out_offset, &out_size, &out_pts,
    305                 &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
    306         me.lock();
    307         // abort read on stop
    308         if (me->mState != STARTED) {
    309             if (res == OK) {
    310                 mCodec->releaseOutputBuffer(out_ix);
    311             }
    312             return ERROR_END_OF_STREAM;
    313         }
    314 
    315         if (res == -EAGAIN) {
    316             ALOGD("[%s] did not produce an output buffer. retry count: %d",
    317                   mComponentName.c_str(), retries);
    318             continue;
    319         } else if (res == INFO_FORMAT_CHANGED) {
    320             if (mCodec->getOutputFormat(&me->mFormat) != OK) {
    321                 me->mState = ERROR;
    322                 res = UNKNOWN_ERROR;
    323             }
    324             return res;
    325         } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
    326             ALOGV("output buffers changed");
    327             continue;
    328         } else if (res != OK) {
    329             me->mState = ERROR;
    330             return res;
    331         }
    332 
    333         sp<ABuffer> out_buffer;
    334         res = mCodec->getOutputBuffer(out_ix, &out_buffer);
    335         if (res != OK) {
    336             ALOGW("[%s] could not get output buffer #%zu",
    337                     mComponentName.c_str(), out_ix);
    338             me->mState = ERROR;
    339             return UNKNOWN_ERROR;
    340         }
    341         if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
    342             me->mGotOutputEOS = true;
    343             // return EOS immediately if last buffer is empty
    344             if (out_size == 0) {
    345                 mCodec->releaseOutputBuffer(out_ix);
    346                 return ERROR_END_OF_STREAM;
    347             }
    348         }
    349 
    350         if (mUsingSurface && out_size > 0) {
    351             *buffer = new MediaBuffer(0);
    352             mCodec->renderOutputBufferAndRelease(out_ix);
    353         } else {
    354             *buffer = new MediaBuffer(out_size);
    355             CHECK_LE(out_buffer->size(), (*buffer)->size());
    356             memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
    357             (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
    358             mCodec->releaseOutputBuffer(out_ix);
    359         }
    360         return OK;
    361     }
    362 
    363     return TIMED_OUT;
    364 }
    365