Home | History | Annotate | Download | only in stagefright
      1 /*
      2  * Copyright (C) 2010 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 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "sf2"
     19 #include <utils/Log.h>
     20 
     21 #include <binder/ProcessState.h>
     22 
     23 #include <media/stagefright/foundation/hexdump.h>
     24 #include <media/stagefright/foundation/ABuffer.h>
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <media/stagefright/foundation/ALooper.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 
     29 #include <media/stagefright/ACodec.h>
     30 #include <media/stagefright/DataSource.h>
     31 #include <media/stagefright/MediaBuffer.h>
     32 #include <media/stagefright/MediaDefs.h>
     33 #include <media/stagefright/MediaExtractor.h>
     34 #include <media/stagefright/MediaSource.h>
     35 #include <media/stagefright/MetaData.h>
     36 #include <media/stagefright/NativeWindowWrapper.h>
     37 #include <media/stagefright/Utils.h>
     38 
     39 #include <gui/SurfaceComposerClient.h>
     40 
     41 #include "include/ESDS.h"
     42 
     43 using namespace android;
     44 
     45 struct Controller : public AHandler {
     46     Controller(const char *uri, bool decodeAudio,
     47                const sp<Surface> &surface, bool renderToSurface)
     48         : mURI(uri),
     49           mDecodeAudio(decodeAudio),
     50           mSurface(surface),
     51           mRenderToSurface(renderToSurface),
     52           mCodec(new ACodec),
     53           mIsVorbis(false) {
     54         CHECK(!mDecodeAudio || mSurface == NULL);
     55     }
     56 
     57     void startAsync() {
     58         (new AMessage(kWhatStart, id()))->post();
     59     }
     60 
     61 protected:
     62     virtual ~Controller() {
     63     }
     64 
     65     virtual void onMessageReceived(const sp<AMessage> &msg) {
     66         switch (msg->what()) {
     67             case kWhatStart:
     68             {
     69 #if 1
     70                 mDecodeLooper = looper();
     71 #else
     72                 mDecodeLooper = new ALooper;
     73                 mDecodeLooper->setName("sf2 decode looper");
     74                 mDecodeLooper->start();
     75 #endif
     76 
     77                 sp<DataSource> dataSource =
     78                     DataSource::CreateFromURI(mURI.c_str());
     79 
     80                 sp<MediaExtractor> extractor =
     81                     MediaExtractor::Create(dataSource);
     82 
     83                 for (size_t i = 0; i < extractor->countTracks(); ++i) {
     84                     sp<MetaData> meta = extractor->getTrackMetaData(i);
     85 
     86                     const char *mime;
     87                     CHECK(meta->findCString(kKeyMIMEType, &mime));
     88 
     89                     if (!strncasecmp(mDecodeAudio ? "audio/" : "video/",
     90                                      mime, 6)) {
     91                         mSource = extractor->getTrack(i);
     92 
     93                         if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
     94                             mIsVorbis = true;
     95                         } else {
     96                             mIsVorbis = false;
     97                         }
     98                         break;
     99                     }
    100                 }
    101                 CHECK(mSource != NULL);
    102 
    103                 CHECK_EQ(mSource->start(), (status_t)OK);
    104 
    105                 mDecodeLooper->registerHandler(mCodec);
    106 
    107                 mCodec->setNotificationMessage(
    108                         new AMessage(kWhatCodecNotify, id()));
    109 
    110                 sp<AMessage> format = makeFormat(mSource->getFormat());
    111 
    112                 if (mSurface != NULL) {
    113                     format->setObject(
    114                             "native-window", new NativeWindowWrapper(mSurface));
    115                 }
    116 
    117                 mCodec->initiateSetup(format);
    118 
    119                 mCSDIndex = 0;
    120                 mStartTimeUs = ALooper::GetNowUs();
    121                 mNumOutputBuffersReceived = 0;
    122                 mTotalBytesReceived = 0;
    123                 mLeftOverBuffer = NULL;
    124                 mFinalResult = OK;
    125                 mSeekState = SEEK_NONE;
    126 
    127                 // (new AMessage(kWhatSeek, id()))->post(5000000ll);
    128                 break;
    129             }
    130 
    131             case kWhatSeek:
    132             {
    133                 printf("+");
    134                 fflush(stdout);
    135 
    136                 CHECK(mSeekState == SEEK_NONE
    137                         || mSeekState == SEEK_FLUSH_COMPLETED);
    138 
    139                 if (mLeftOverBuffer != NULL) {
    140                     mLeftOverBuffer->release();
    141                     mLeftOverBuffer = NULL;
    142                 }
    143 
    144                 mSeekState = SEEK_FLUSHING;
    145                 mSeekTimeUs = 30000000ll;
    146 
    147                 mCodec->signalFlush();
    148                 break;
    149             }
    150 
    151             case kWhatStop:
    152             {
    153                 if (mLeftOverBuffer != NULL) {
    154                     mLeftOverBuffer->release();
    155                     mLeftOverBuffer = NULL;
    156                 }
    157 
    158                 CHECK_EQ(mSource->stop(), (status_t)OK);
    159                 mSource.clear();
    160 
    161                 mCodec->initiateShutdown();
    162                 break;
    163             }
    164 
    165             case kWhatCodecNotify:
    166             {
    167                 int32_t what;
    168                 CHECK(msg->findInt32("what", &what));
    169 
    170                 if (what == ACodec::kWhatFillThisBuffer) {
    171                     onFillThisBuffer(msg);
    172                 } else if (what == ACodec::kWhatDrainThisBuffer) {
    173                     if ((mNumOutputBuffersReceived++ % 16) == 0) {
    174                         printf(".");
    175                         fflush(stdout);
    176                     }
    177 
    178                     onDrainThisBuffer(msg);
    179                 } else if (what == ACodec::kWhatEOS
    180                         || what == ACodec::kWhatError) {
    181                     printf((what == ACodec::kWhatEOS) ? "$\n" : "E\n");
    182 
    183                     int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs;
    184 
    185                     if (mDecodeAudio) {
    186                         printf("%lld bytes received. %.2f KB/sec\n",
    187                                mTotalBytesReceived,
    188                                mTotalBytesReceived * 1E6 / 1024 / delayUs);
    189                     } else {
    190                         printf("%d frames decoded, %.2f fps. %lld bytes "
    191                                "received. %.2f KB/sec\n",
    192                                mNumOutputBuffersReceived,
    193                                mNumOutputBuffersReceived * 1E6 / delayUs,
    194                                mTotalBytesReceived,
    195                                mTotalBytesReceived * 1E6 / 1024 / delayUs);
    196                     }
    197 
    198                     (new AMessage(kWhatStop, id()))->post();
    199                 } else if (what == ACodec::kWhatFlushCompleted) {
    200                     mSeekState = SEEK_FLUSH_COMPLETED;
    201                     mCodec->signalResume();
    202 
    203                     (new AMessage(kWhatSeek, id()))->post(5000000ll);
    204                 } else if (what == ACodec::kWhatOutputFormatChanged) {
    205                 } else if (what == ACodec::kWhatShutdownCompleted) {
    206                     mDecodeLooper->unregisterHandler(mCodec->id());
    207 
    208                     if (mDecodeLooper != looper()) {
    209                         mDecodeLooper->stop();
    210                     }
    211 
    212                     looper()->stop();
    213                 } else if (what == ACodec::kWhatError) {
    214                     ALOGE("something went wrong, codec reported an error.");
    215 
    216                     printf("E\n");
    217 
    218                     (new AMessage(kWhatStop, id()))->post();
    219                 }
    220                 break;
    221             }
    222 
    223             default:
    224                 TRESPASS();
    225                 break;
    226         }
    227     }
    228 
    229 private:
    230     enum {
    231         kWhatStart             = 'strt',
    232         kWhatStop              = 'stop',
    233         kWhatCodecNotify       = 'noti',
    234         kWhatSeek              = 'seek',
    235     };
    236 
    237     sp<ALooper> mDecodeLooper;
    238 
    239     AString mURI;
    240     bool mDecodeAudio;
    241     sp<Surface> mSurface;
    242     bool mRenderToSurface;
    243     sp<ACodec> mCodec;
    244     sp<MediaSource> mSource;
    245     bool mIsVorbis;
    246 
    247     Vector<sp<ABuffer> > mCSD;
    248     size_t mCSDIndex;
    249 
    250     MediaBuffer *mLeftOverBuffer;
    251     status_t mFinalResult;
    252 
    253     int64_t mStartTimeUs;
    254     int32_t mNumOutputBuffersReceived;
    255     int64_t mTotalBytesReceived;
    256 
    257     enum SeekState {
    258         SEEK_NONE,
    259         SEEK_FLUSHING,
    260         SEEK_FLUSH_COMPLETED,
    261     };
    262     SeekState mSeekState;
    263     int64_t mSeekTimeUs;
    264 
    265     sp<AMessage> makeFormat(const sp<MetaData> &meta) {
    266         CHECK(mCSD.isEmpty());
    267 
    268         const char *mime;
    269         CHECK(meta->findCString(kKeyMIMEType, &mime));
    270 
    271         sp<AMessage> msg = new AMessage;
    272         msg->setString("mime", mime);
    273 
    274         if (!strncasecmp("video/", mime, 6)) {
    275             int32_t width, height;
    276             CHECK(meta->findInt32(kKeyWidth, &width));
    277             CHECK(meta->findInt32(kKeyHeight, &height));
    278 
    279             msg->setInt32("width", width);
    280             msg->setInt32("height", height);
    281         } else {
    282             CHECK(!strncasecmp("audio/", mime, 6));
    283 
    284             int32_t numChannels, sampleRate;
    285             CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
    286             CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
    287 
    288             msg->setInt32("channel-count", numChannels);
    289             msg->setInt32("sample-rate", sampleRate);
    290 
    291             int32_t isADTS;
    292             if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) {
    293                 msg->setInt32("is-adts", true);
    294             }
    295         }
    296 
    297         uint32_t type;
    298         const void *data;
    299         size_t size;
    300         if (meta->findData(kKeyAVCC, &type, &data, &size)) {
    301             // Parse the AVCDecoderConfigurationRecord
    302 
    303             const uint8_t *ptr = (const uint8_t *)data;
    304 
    305             CHECK(size >= 7);
    306             CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
    307             uint8_t profile = ptr[1];
    308             uint8_t level = ptr[3];
    309 
    310             // There is decodable content out there that fails the following
    311             // assertion, let's be lenient for now...
    312             // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
    313 
    314             size_t lengthSize = 1 + (ptr[4] & 3);
    315 
    316             // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
    317             // violates it...
    318             // CHECK((ptr[5] >> 5) == 7);  // reserved
    319 
    320             size_t numSeqParameterSets = ptr[5] & 31;
    321 
    322             ptr += 6;
    323             size -= 6;
    324 
    325             sp<ABuffer> buffer = new ABuffer(1024);
    326             buffer->setRange(0, 0);
    327 
    328             for (size_t i = 0; i < numSeqParameterSets; ++i) {
    329                 CHECK(size >= 2);
    330                 size_t length = U16_AT(ptr);
    331 
    332                 ptr += 2;
    333                 size -= 2;
    334 
    335                 CHECK(size >= length);
    336 
    337                 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
    338                 memcpy(buffer->data() + buffer->size() + 4, ptr, length);
    339                 buffer->setRange(0, buffer->size() + 4 + length);
    340 
    341                 ptr += length;
    342                 size -= length;
    343             }
    344 
    345             buffer->meta()->setInt32("csd", true);
    346             mCSD.push(buffer);
    347 
    348             buffer = new ABuffer(1024);
    349             buffer->setRange(0, 0);
    350 
    351             CHECK(size >= 1);
    352             size_t numPictureParameterSets = *ptr;
    353             ++ptr;
    354             --size;
    355 
    356             for (size_t i = 0; i < numPictureParameterSets; ++i) {
    357                 CHECK(size >= 2);
    358                 size_t length = U16_AT(ptr);
    359 
    360                 ptr += 2;
    361                 size -= 2;
    362 
    363                 CHECK(size >= length);
    364 
    365                 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
    366                 memcpy(buffer->data() + buffer->size() + 4, ptr, length);
    367                 buffer->setRange(0, buffer->size() + 4 + length);
    368 
    369                 ptr += length;
    370                 size -= length;
    371             }
    372 
    373             buffer->meta()->setInt32("csd", true);
    374             mCSD.push(buffer);
    375 
    376             msg->setBuffer("csd", buffer);
    377         } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
    378             ESDS esds((const char *)data, size);
    379             CHECK_EQ(esds.InitCheck(), (status_t)OK);
    380 
    381             const void *codec_specific_data;
    382             size_t codec_specific_data_size;
    383             esds.getCodecSpecificInfo(
    384                     &codec_specific_data, &codec_specific_data_size);
    385 
    386             sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
    387 
    388             memcpy(buffer->data(), codec_specific_data,
    389                    codec_specific_data_size);
    390 
    391             buffer->meta()->setInt32("csd", true);
    392             mCSD.push(buffer);
    393         } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
    394             sp<ABuffer> buffer = new ABuffer(size);
    395             memcpy(buffer->data(), data, size);
    396 
    397             buffer->meta()->setInt32("csd", true);
    398             mCSD.push(buffer);
    399 
    400             CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
    401 
    402             buffer = new ABuffer(size);
    403             memcpy(buffer->data(), data, size);
    404 
    405             buffer->meta()->setInt32("csd", true);
    406             mCSD.push(buffer);
    407         }
    408 
    409         int32_t maxInputSize;
    410         if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
    411             msg->setInt32("max-input-size", maxInputSize);
    412         }
    413 
    414         return msg;
    415     }
    416 
    417     void onFillThisBuffer(const sp<AMessage> &msg) {
    418         sp<AMessage> reply;
    419         CHECK(msg->findMessage("reply", &reply));
    420 
    421         if (mSource == NULL || mSeekState == SEEK_FLUSHING) {
    422             reply->setInt32("err", ERROR_END_OF_STREAM);
    423             reply->post();
    424             return;
    425         }
    426 
    427         sp<ABuffer> outBuffer;
    428         CHECK(msg->findBuffer("buffer", &outBuffer));
    429 
    430         if (mCSDIndex < mCSD.size()) {
    431             outBuffer = mCSD.editItemAt(mCSDIndex++);
    432             outBuffer->meta()->setInt64("timeUs", 0);
    433         } else {
    434             size_t sizeLeft = outBuffer->capacity();
    435             outBuffer->setRange(0, 0);
    436 
    437             int32_t n = 0;
    438 
    439             for (;;) {
    440                 MediaBuffer *inBuffer;
    441 
    442                 if (mLeftOverBuffer != NULL) {
    443                     inBuffer = mLeftOverBuffer;
    444                     mLeftOverBuffer = NULL;
    445                 } else if (mFinalResult != OK) {
    446                     break;
    447                 } else {
    448                     MediaSource::ReadOptions options;
    449                     if (mSeekState == SEEK_FLUSH_COMPLETED) {
    450                         options.setSeekTo(mSeekTimeUs);
    451                         mSeekState = SEEK_NONE;
    452                     }
    453                     status_t err = mSource->read(&inBuffer, &options);
    454 
    455                     if (err != OK) {
    456                         mFinalResult = err;
    457                         break;
    458                     }
    459                 }
    460 
    461                 size_t sizeNeeded = inBuffer->range_length();
    462                 if (mIsVorbis) {
    463                     // Vorbis data is suffixed with the number of
    464                     // valid samples on the page.
    465                     sizeNeeded += sizeof(int32_t);
    466                 }
    467 
    468                 if (sizeNeeded > sizeLeft) {
    469                     if (outBuffer->size() == 0) {
    470                         ALOGE("Unable to fit even a single input buffer of size %d.",
    471                              sizeNeeded);
    472                     }
    473                     CHECK_GT(outBuffer->size(), 0u);
    474 
    475                     mLeftOverBuffer = inBuffer;
    476                     break;
    477                 }
    478 
    479                 ++n;
    480 
    481                 if (outBuffer->size() == 0) {
    482                     int64_t timeUs;
    483                     CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
    484 
    485                     outBuffer->meta()->setInt64("timeUs", timeUs);
    486                 }
    487 
    488                 memcpy(outBuffer->data() + outBuffer->size(),
    489                        (const uint8_t *)inBuffer->data()
    490                         + inBuffer->range_offset(),
    491                        inBuffer->range_length());
    492 
    493                 if (mIsVorbis) {
    494                     int32_t numPageSamples;
    495                     if (!inBuffer->meta_data()->findInt32(
    496                                 kKeyValidSamples, &numPageSamples)) {
    497                         numPageSamples = -1;
    498                     }
    499 
    500                     memcpy(outBuffer->data()
    501                             + outBuffer->size() + inBuffer->range_length(),
    502                            &numPageSamples, sizeof(numPageSamples));
    503                 }
    504 
    505                 outBuffer->setRange(
    506                         0, outBuffer->size() + sizeNeeded);
    507 
    508                 sizeLeft -= sizeNeeded;
    509 
    510                 inBuffer->release();
    511                 inBuffer = NULL;
    512 
    513                 break;  // Don't coalesce
    514             }
    515 
    516             ALOGV("coalesced %d input buffers", n);
    517 
    518             if (outBuffer->size() == 0) {
    519                 CHECK_NE(mFinalResult, (status_t)OK);
    520 
    521                 reply->setInt32("err", mFinalResult);
    522                 reply->post();
    523                 return;
    524             }
    525         }
    526 
    527         reply->setBuffer("buffer", outBuffer);
    528         reply->post();
    529     }
    530 
    531     void onDrainThisBuffer(const sp<AMessage> &msg) {
    532         sp<ABuffer> buffer;
    533         CHECK(msg->findBuffer("buffer", &buffer));
    534 
    535         mTotalBytesReceived += buffer->size();
    536 
    537         sp<AMessage> reply;
    538         CHECK(msg->findMessage("reply", &reply));
    539 
    540         if (mRenderToSurface) {
    541             reply->setInt32("render", 1);
    542         }
    543 
    544         reply->post();
    545     }
    546 
    547     DISALLOW_EVIL_CONSTRUCTORS(Controller);
    548 };
    549 
    550 static void usage(const char *me) {
    551     fprintf(stderr, "usage: %s\n", me);
    552     fprintf(stderr, "       -h(elp)\n");
    553     fprintf(stderr, "       -a(udio)\n");
    554 
    555     fprintf(stderr,
    556             "       -S(urface) Allocate output buffers on a surface.\n"
    557             "       -R(ender)  Render surface-allocated buffers.\n");
    558 }
    559 
    560 int main(int argc, char **argv) {
    561     android::ProcessState::self()->startThreadPool();
    562 
    563     bool decodeAudio = false;
    564     bool useSurface = false;
    565     bool renderToSurface = false;
    566 
    567     int res;
    568     while ((res = getopt(argc, argv, "haSR")) >= 0) {
    569         switch (res) {
    570             case 'a':
    571                 decodeAudio = true;
    572                 break;
    573 
    574             case 'S':
    575                 useSurface = true;
    576                 break;
    577 
    578             case 'R':
    579                 renderToSurface = true;
    580                 break;
    581 
    582             case '?':
    583             case 'h':
    584             default:
    585             {
    586                 usage(argv[0]);
    587                 return 1;
    588             }
    589         }
    590     }
    591 
    592     argc -= optind;
    593     argv += optind;
    594 
    595     if (argc != 1) {
    596         usage(argv[-optind]);
    597         return 1;
    598     }
    599 
    600     DataSource::RegisterDefaultSniffers();
    601 
    602     sp<ALooper> looper = new ALooper;
    603     looper->setName("sf2");
    604 
    605     sp<SurfaceComposerClient> composerClient;
    606     sp<SurfaceControl> control;
    607     sp<Surface> surface;
    608 
    609     if (!decodeAudio && useSurface) {
    610         composerClient = new SurfaceComposerClient;
    611         CHECK_EQ(composerClient->initCheck(), (status_t)OK);
    612 
    613         control = composerClient->createSurface(
    614                 String8("A Surface"),
    615                 1280,
    616                 800,
    617                 PIXEL_FORMAT_RGB_565,
    618                 0);
    619 
    620         CHECK(control != NULL);
    621         CHECK(control->isValid());
    622 
    623         SurfaceComposerClient::openGlobalTransaction();
    624         CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
    625         CHECK_EQ(control->show(), (status_t)OK);
    626         SurfaceComposerClient::closeGlobalTransaction();
    627 
    628         surface = control->getSurface();
    629         CHECK(surface != NULL);
    630 
    631         CHECK_EQ((status_t)OK,
    632                  native_window_api_connect(
    633                      surface.get(), NATIVE_WINDOW_API_MEDIA));
    634     }
    635 
    636     sp<Controller> controller =
    637         new Controller(argv[0], decodeAudio, surface, renderToSurface);
    638 
    639     looper->registerHandler(controller);
    640 
    641     controller->startAsync();
    642 
    643     CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK);
    644 
    645     looper->unregisterHandler(controller->id());
    646 
    647     if (!decodeAudio && useSurface) {
    648         CHECK_EQ((status_t)OK,
    649                  native_window_api_disconnect(
    650                      surface.get(), NATIVE_WINDOW_API_MEDIA));
    651 
    652         composerClient->dispose();
    653     }
    654 
    655     return 0;
    656 }
    657 
    658