blob: c1d08036d6bd79c3091e1a4bd038978b6ca200e9 [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>
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);
Andreas Huber5ea13722011-02-04 10:14:08 -0800189 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Hubera1587462010-12-15 15:17:42 -0800190 } 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 getpid(),
547 String8("A Surface"),
548 0,
549 1280,
550 800,
551 PIXEL_FORMAT_RGB_565,
552 0);
553
554 CHECK(control != NULL);
555 CHECK(control->isValid());
556
557 CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
558 CHECK_EQ(control->setLayer(30000), (status_t)OK);
559 CHECK_EQ(control->show(), (status_t)OK);
560 CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
561
562 surface = control->getSurface();
563 CHECK(surface != NULL);
564 }
565
566 sp<Controller> controller = new Controller(argv[0], decodeAudio, surface);
567 looper->registerHandler(controller);
568
569 controller->startAsync();
570
571 CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK);
572
573 looper->unregisterHandler(controller->id());
574
575 if (!decodeAudio && useSurface) {
576 composerClient->dispose();
577 }
578
579 return 0;
580}
581