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
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, id()))->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, 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
253private:
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
574static 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
584int 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