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