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