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