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