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