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