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