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