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