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