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