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