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