blob: 35d599c315ede212aad7d9bf5b4e9fb896042315 [file] [log] [blame]
Andreas Huberbe06d262009-08-14 14:37:10 -07001/*
2 * Copyright (C) 2009 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 "OMXCodec"
19#include <utils/Log.h>
20
21#include <binder/IServiceManager.h>
22#include <binder/MemoryDealer.h>
23#include <binder/ProcessState.h>
24#include <media/IMediaPlayerService.h>
25#include <media/stagefright/ESDS.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaBufferGroup.h>
28#include <media/stagefright/MediaDebug.h>
29#include <media/stagefright/MediaExtractor.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/MmapSource.h>
32#include <media/stagefright/OMXCodec.h>
33#include <utils/Vector.h>
34
35#include <OMX_Audio.h>
36#include <OMX_Component.h>
37
38namespace android {
39
40struct CodecInfo {
41 const char *mime;
42 const char *codec;
43};
44
45static const CodecInfo kDecoderInfo[] = {
46 { "image/jpeg", "OMX.TI.JPEG.decode" },
47 { "audio/mpeg", "OMX.TI.MP3.decode" },
48 { "audio/mpeg", "OMX.PV.mp3dec" },
49 { "audio/3gpp", "OMX.TI.AMR.decode" },
50 { "audio/3gpp", "OMX.PV.amrdec" },
51 { "audio/mp4a-latm", "OMX.TI.AAC.decode" },
52 { "audio/mp4a-latm", "OMX.PV.aacdec" },
53 { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" },
54 { "video/mp4v-es", "OMX.TI.Video.Decoder" },
55 { "video/mp4v-es", "OMX.PV.mpeg4dec" },
56 { "video/3gpp", "OMX.qcom.video.decoder.h263" },
57 { "video/3gpp", "OMX.TI.Video.Decoder" },
58 { "video/3gpp", "OMX.PV.h263dec" },
59 { "video/avc", "OMX.qcom.video.decoder.avc" },
60 { "video/avc", "OMX.TI.Video.Decoder" },
61 { "video/avc", "OMX.PV.avcdec" },
62};
63
64static const CodecInfo kEncoderInfo[] = {
65 { "audio/3gpp", "OMX.TI.AMR.encode" },
66 { "audio/3gpp", "OMX.PV.amrencnb" },
67 { "audio/mp4a-latm", "OMX.TI.AAC.encode" },
68 { "audio/mp4a-latm", "OMX.PV.aacenc" },
69 { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" },
70 { "video/mp4v-es", "OMX.TI.Video.encoder" },
71 { "video/mp4v-es", "OMX.PV.mpeg4enc" },
72 { "video/3gpp", "OMX.qcom.video.encoder.h263" },
73 { "video/3gpp", "OMX.TI.Video.encoder" },
74 { "video/3gpp", "OMX.PV.h263enc" },
75 { "video/avc", "OMX.TI.Video.encoder" },
76 { "video/avc", "OMX.PV.avcenc" },
77};
78
79struct OMXCodecObserver : public BnOMXObserver {
80 OMXCodecObserver(const wp<OMXCodec> &target)
81 : mTarget(target) {
82 }
83
84 // from IOMXObserver
85 virtual void on_message(const omx_message &msg) {
86 sp<OMXCodec> codec = mTarget.promote();
87
88 if (codec.get() != NULL) {
89 codec->on_message(msg);
90 }
91 }
92
93protected:
94 virtual ~OMXCodecObserver() {}
95
96private:
97 wp<OMXCodec> mTarget;
98
99 OMXCodecObserver(const OMXCodecObserver &);
100 OMXCodecObserver &operator=(const OMXCodecObserver &);
101};
102
103static const char *GetCodec(const CodecInfo *info, size_t numInfos,
104 const char *mime, int index) {
105 CHECK(index >= 0);
106 for(size_t i = 0; i < numInfos; ++i) {
107 if (!strcasecmp(mime, info[i].mime)) {
108 if (index == 0) {
109 return info[i].codec;
110 }
111
112 --index;
113 }
114 }
115
116 return NULL;
117}
118
119// static
120sp<OMXCodec> OMXCodec::Create(
121 const sp<IOMX> &omx,
122 const sp<MetaData> &meta, bool createEncoder,
123 const sp<MediaSource> &source) {
124 const char *mime;
125 bool success = meta->findCString(kKeyMIMEType, &mime);
126 CHECK(success);
127
128 const char *componentName = NULL;
129 IOMX::node_id node = 0;
130 for (int index = 0;; ++index) {
131 if (createEncoder) {
132 componentName = GetCodec(
133 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
134 mime, index);
135 } else {
136 componentName = GetCodec(
137 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
138 mime, index);
139 }
140
141 if (!componentName) {
142 return NULL;
143 }
144
145 LOGV("Attempting to allocate OMX node '%s'", componentName);
146
147 status_t err = omx->allocate_node(componentName, &node);
148 if (err == OK) {
149 break;
150 }
151 }
152
153 uint32_t quirks = 0;
154 if (!strcmp(componentName, "OMX.PV.avcdec")) {
155 quirks |= kWantsRawNALFrames;
156 }
157 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
158 quirks |= kNeedsFlushBeforeDisable;
159 }
160 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
161 quirks |= kNeedsFlushBeforeDisable;
162 }
163 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
164 quirks |= kRequiresLoadedToIdleAfterAllocation;
165 quirks |= kRequiresAllocateBufferOnInputPorts;
166 }
167
168 sp<OMXCodec> codec = new OMXCodec(
169 omx, node, quirks, createEncoder, mime, componentName,
170 source);
171
172 uint32_t type;
173 const void *data;
174 size_t size;
175 if (meta->findData(kKeyESDS, &type, &data, &size)) {
176 ESDS esds((const char *)data, size);
177 CHECK_EQ(esds.InitCheck(), OK);
178
179 const void *codec_specific_data;
180 size_t codec_specific_data_size;
181 esds.getCodecSpecificInfo(
182 &codec_specific_data, &codec_specific_data_size);
183
184 printf("found codec-specific data of size %d\n",
185 codec_specific_data_size);
186
187 codec->addCodecSpecificData(
188 codec_specific_data, codec_specific_data_size);
189 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
190 printf("found avcc of size %d\n", size);
191
192 const uint8_t *ptr = (const uint8_t *)data + 6;
193 size -= 6;
194 while (size >= 2) {
195 size_t length = ptr[0] << 8 | ptr[1];
196
197 ptr += 2;
198 size -= 2;
199
200 // printf("length = %d, size = %d\n", length, size);
201
202 CHECK(size >= length);
203
204 codec->addCodecSpecificData(ptr, length);
205
206 ptr += length;
207 size -= length;
208
209 if (size <= 1) {
210 break;
211 }
212
213 ptr++; // XXX skip trailing 0x01 byte???
214 --size;
215 }
216 }
217
218 if (!strcasecmp("audio/3gpp", mime)) {
219 codec->setAMRFormat();
220 }
221 if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
222 codec->setAACFormat();
223 }
224 if (!strncasecmp(mime, "video/", 6)) {
225 int32_t width, height;
226 bool success = meta->findInt32(kKeyWidth, &width);
227 success = success && meta->findInt32(kKeyHeight, &height);
228 assert(success);
229
230 if (createEncoder) {
231 codec->setVideoInputFormat(mime, width, height);
232 } else {
233 codec->setVideoOutputFormat(mime, width, height);
234 }
235 }
236 if (!strcasecmp(mime, "image/jpeg")
237 && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
238 OMX_COLOR_FORMATTYPE format =
239 OMX_COLOR_Format32bitARGB8888;
240 // OMX_COLOR_FormatYUV420PackedPlanar;
241 // OMX_COLOR_FormatCbYCrY;
242 // OMX_COLOR_FormatYUV411Planar;
243
244 int32_t width, height;
245 bool success = meta->findInt32(kKeyWidth, &width);
246 success = success && meta->findInt32(kKeyHeight, &height);
247 assert(success);
248
249 codec->setImageOutputFormat(format, width, height);
250 }
251
252 codec->initOutputFormat(meta);
253
254 return codec;
255}
256
257status_t OMXCodec::setVideoPortFormatType(
258 OMX_U32 portIndex,
259 OMX_VIDEO_CODINGTYPE compressionFormat,
260 OMX_COLOR_FORMATTYPE colorFormat) {
261 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
262 format.nSize = sizeof(format);
263 format.nVersion.s.nVersionMajor = 1;
264 format.nVersion.s.nVersionMinor = 1;
265 format.nPortIndex = portIndex;
266 format.nIndex = 0;
267 bool found = false;
268
269 OMX_U32 index = 0;
270 for (;;) {
271 format.nIndex = index;
272 status_t err = mOMX->get_parameter(
273 mNode, OMX_IndexParamVideoPortFormat,
274 &format, sizeof(format));
275
276 if (err != OK) {
277 return err;
278 }
279
280 // The following assertion is violated by TI's video decoder.
281 // assert(format.nIndex == index);
282
283#if 1
284 LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
285 portIndex,
286 index, format.eCompressionFormat, format.eColorFormat);
287#endif
288
289 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
290 if (portIndex == kPortIndexInput
291 && colorFormat == format.eColorFormat) {
292 // eCompressionFormat does not seem right.
293 found = true;
294 break;
295 }
296 if (portIndex == kPortIndexOutput
297 && compressionFormat == format.eCompressionFormat) {
298 // eColorFormat does not seem right.
299 found = true;
300 break;
301 }
302 }
303
304 if (format.eCompressionFormat == compressionFormat
305 && format.eColorFormat == colorFormat) {
306 found = true;
307 break;
308 }
309
310 ++index;
311 }
312
313 if (!found) {
314 return UNKNOWN_ERROR;
315 }
316
317 LOGI("found a match.");
318 status_t err = mOMX->set_parameter(
319 mNode, OMX_IndexParamVideoPortFormat,
320 &format, sizeof(format));
321
322 return err;
323}
324
325void OMXCodec::setVideoInputFormat(
326 const char *mime, OMX_U32 width, OMX_U32 height) {
327 LOGI("setVideoInputFormat width=%ld, height=%ld", width, height);
328
329 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
330 if (!strcasecmp("video/avc", mime)) {
331 compressionFormat = OMX_VIDEO_CodingAVC;
332 } else if (!strcasecmp("video/mp4v-es", mime)) {
333 compressionFormat = OMX_VIDEO_CodingMPEG4;
334 } else if (!strcasecmp("video/3gpp", mime)) {
335 compressionFormat = OMX_VIDEO_CodingH263;
336 } else {
337 LOGE("Not a supported video mime type: %s", mime);
338 CHECK(!"Should not be here. Not a supported video mime type.");
339 }
340
341 OMX_COLOR_FORMATTYPE colorFormat =
342 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
343
344 if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
345 colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
346 }
347
348 setVideoPortFormatType(
349 kPortIndexInput, OMX_VIDEO_CodingUnused,
350 colorFormat);
351
352 setVideoPortFormatType(
353 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
354
355 OMX_PARAM_PORTDEFINITIONTYPE def;
356 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
357
358 def.nSize = sizeof(def);
359 def.nVersion.s.nVersionMajor = 1;
360 def.nVersion.s.nVersionMinor = 1;
361 def.nPortIndex = kPortIndexOutput;
362
363 status_t err = mOMX->get_parameter(
364 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
365
366 CHECK_EQ(err, OK);
367 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
368
369 video_def->nFrameWidth = width;
370 video_def->nFrameHeight = height;
371
372 video_def->eCompressionFormat = compressionFormat;
373 video_def->eColorFormat = OMX_COLOR_FormatUnused;
374
375 err = mOMX->set_parameter(
376 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
377 CHECK_EQ(err, OK);
378
379 ////////////////////////////////////////////////////////////////////////////
380
381 def.nSize = sizeof(def);
382 def.nVersion.s.nVersionMajor = 1;
383 def.nVersion.s.nVersionMinor = 1;
384 def.nPortIndex = kPortIndexInput;
385
386 err = mOMX->get_parameter(
387 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
388 CHECK_EQ(err, OK);
389
390 def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
391 LOGI("setting nBufferSize = %ld", def.nBufferSize);
392
393 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
394
395 video_def->nFrameWidth = width;
396 video_def->nFrameHeight = height;
397 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
398 video_def->eColorFormat = colorFormat;
399
400 err = mOMX->set_parameter(
401 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
402 CHECK_EQ(err, OK);
403}
404
405void OMXCodec::setVideoOutputFormat(
406 const char *mime, OMX_U32 width, OMX_U32 height) {
407 LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
408
409 // Enabling this code appears to be the right thing(tm), but,...
410 // the TI decoder then loses the ability to output YUV420 and only outputs
411 // YCbYCr (16bit)
412 if (!strcmp("OMX.TI.Video.Decoder", mComponentName)
413 && !strcasecmp("video/avc", mime)) {
414 OMX_PARAM_COMPONENTROLETYPE role;
415 role.nSize = sizeof(role);
416 role.nVersion.s.nVersionMajor = 1;
417 role.nVersion.s.nVersionMinor = 1;
418 strncpy((char *)role.cRole, "video_decoder.avc",
419 OMX_MAX_STRINGNAME_SIZE - 1);
420 role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
421
422 status_t err = mOMX->set_parameter(
423 mNode, OMX_IndexParamStandardComponentRole,
424 &role, sizeof(role));
425 CHECK_EQ(err, OK);
426 }
427
428 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
429 if (!strcasecmp("video/avc", mime)) {
430 compressionFormat = OMX_VIDEO_CodingAVC;
431 } else if (!strcasecmp("video/mp4v-es", mime)) {
432 compressionFormat = OMX_VIDEO_CodingMPEG4;
433 } else if (!strcasecmp("video/3gpp", mime)) {
434 compressionFormat = OMX_VIDEO_CodingH263;
435 } else {
436 LOGE("Not a supported video mime type: %s", mime);
437 CHECK(!"Should not be here. Not a supported video mime type.");
438 }
439
440 setVideoPortFormatType(
441 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
442
443#if 1
444 {
445 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
446 format.nSize = sizeof(format);
447 format.nVersion.s.nVersionMajor = 1;
448 format.nVersion.s.nVersionMinor = 1;
449 format.nPortIndex = kPortIndexOutput;
450 format.nIndex = 0;
451
452 status_t err = mOMX->get_parameter(
453 mNode, OMX_IndexParamVideoPortFormat,
454 &format, sizeof(format));
455 CHECK_EQ(err, OK);
456 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
457
458 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
459
460 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
461 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
462 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
463 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
464
465 err = mOMX->set_parameter(
466 mNode, OMX_IndexParamVideoPortFormat,
467 &format, sizeof(format));
468 CHECK_EQ(err, OK);
469 }
470#endif
471
472 OMX_PARAM_PORTDEFINITIONTYPE def;
473 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
474
475 def.nSize = sizeof(def);
476 def.nVersion.s.nVersionMajor = 1;
477 def.nVersion.s.nVersionMinor = 1;
478 def.nPortIndex = kPortIndexInput;
479
480 status_t err = mOMX->get_parameter(
481 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
482
483 CHECK_EQ(err, OK);
484
485#if 1
486 // XXX Need a (much) better heuristic to compute input buffer sizes.
487 const size_t X = 64 * 1024;
488 if (def.nBufferSize < X) {
489 def.nBufferSize = X;
490 }
491#endif
492
493 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
494
495 video_def->nFrameWidth = width;
496 video_def->nFrameHeight = height;
497
498 video_def->eColorFormat = OMX_COLOR_FormatUnused;
499
500 err = mOMX->set_parameter(
501 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
502 CHECK_EQ(err, OK);
503
504 ////////////////////////////////////////////////////////////////////////////
505
506 def.nSize = sizeof(def);
507 def.nVersion.s.nVersionMajor = 1;
508 def.nVersion.s.nVersionMinor = 1;
509 def.nPortIndex = kPortIndexOutput;
510
511 err = mOMX->get_parameter(
512 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
513 CHECK_EQ(err, OK);
514 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
515
516#if 0
517 def.nBufferSize =
518 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
519#endif
520
521 video_def->nFrameWidth = width;
522 video_def->nFrameHeight = height;
523
524 err = mOMX->set_parameter(
525 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
526 CHECK_EQ(err, OK);
527}
528
529
530OMXCodec::OMXCodec(
531 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
532 bool isEncoder,
533 const char *mime,
534 const char *componentName,
535 const sp<MediaSource> &source)
536 : mOMX(omx),
537 mNode(node),
538 mQuirks(quirks),
539 mIsEncoder(isEncoder),
540 mMIME(strdup(mime)),
541 mComponentName(strdup(componentName)),
542 mSource(source),
543 mCodecSpecificDataIndex(0),
544 mDealer(new MemoryDealer(5 * 1024 * 1024)),
545 mState(LOADED),
546 mSignalledEOS(false),
547 mNoMoreOutputData(false),
548 mSeekTimeUs(-1) {
549 mPortStatus[kPortIndexInput] = ENABLED;
550 mPortStatus[kPortIndexOutput] = ENABLED;
551
552 mObserver = new OMXCodecObserver(this);
553 mOMX->observe_node(mNode, mObserver);
554}
555
556OMXCodec::~OMXCodec() {
557 CHECK_EQ(mState, LOADED);
558
559 status_t err = mOMX->observe_node(mNode, NULL);
560 CHECK_EQ(err, OK);
561
562 err = mOMX->free_node(mNode);
563 CHECK_EQ(err, OK);
564
565 mNode = NULL;
566 setState(DEAD);
567
568 clearCodecSpecificData();
569
570 free(mComponentName);
571 mComponentName = NULL;
572
573 free(mMIME);
574 mMIME = NULL;
575}
576
577status_t OMXCodec::init() {
578 Mutex::Autolock autoLock(mLock);
579
580 CHECK_EQ(mState, LOADED);
581
582 status_t err;
583 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
584 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
585 CHECK_EQ(err, OK);
586
587 setState(LOADED_TO_IDLE);
588 }
589
590 err = allocateBuffers();
591 CHECK_EQ(err, OK);
592
593 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
594 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
595 CHECK_EQ(err, OK);
596
597 setState(LOADED_TO_IDLE);
598 }
599
600 while (mState != EXECUTING && mState != ERROR) {
601 mAsyncCompletion.wait(mLock);
602 }
603
604 return mState == ERROR ? UNKNOWN_ERROR : OK;
605}
606
607// static
608bool OMXCodec::isIntermediateState(State state) {
609 return state == LOADED_TO_IDLE
610 || state == IDLE_TO_EXECUTING
611 || state == EXECUTING_TO_IDLE
612 || state == IDLE_TO_LOADED
613 || state == RECONFIGURING;
614}
615
616status_t OMXCodec::allocateBuffers() {
617 status_t err = allocateBuffersOnPort(kPortIndexInput);
618
619 if (err != OK) {
620 return err;
621 }
622
623 return allocateBuffersOnPort(kPortIndexOutput);
624}
625
626status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
627 OMX_PARAM_PORTDEFINITIONTYPE def;
628 def.nSize = sizeof(def);
629 def.nVersion.s.nVersionMajor = 1;
630 def.nVersion.s.nVersionMinor = 1;
631 def.nVersion.s.nRevision = 0;
632 def.nVersion.s.nStep = 0;
633 def.nPortIndex = portIndex;
634
635 status_t err = mOMX->get_parameter(
636 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
637
638 if (err != OK) {
639 return err;
640 }
641
642 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
643 sp<IMemory> mem = mDealer->allocate(def.nBufferSize);
644 CHECK(mem.get() != NULL);
645
646 IOMX::buffer_id buffer;
647 if (portIndex == kPortIndexInput
648 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
649 err = mOMX->allocate_buffer_with_backup(
650 mNode, portIndex, mem, &buffer);
651 } else {
652 err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
653 }
654
655 if (err != OK) {
656 LOGE("allocate_buffer_with_backup failed");
657 return err;
658 }
659
660 BufferInfo info;
661 info.mBuffer = buffer;
662 info.mOwnedByComponent = false;
663 info.mMem = mem;
664 info.mMediaBuffer = NULL;
665
666 if (portIndex == kPortIndexOutput) {
667 info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
668 info.mMediaBuffer->setObserver(this);
669 }
670
671 mPortBuffers[portIndex].push(info);
672
673 LOGV("allocated buffer %p on %s port", buffer,
674 portIndex == kPortIndexInput ? "input" : "output");
675 }
676
677 dumpPortStatus(portIndex);
678
679 return OK;
680}
681
682void OMXCodec::on_message(const omx_message &msg) {
683 Mutex::Autolock autoLock(mLock);
684
685 switch (msg.type) {
686 case omx_message::EVENT:
687 {
688 onEvent(
689 msg.u.event_data.event, msg.u.event_data.data1,
690 msg.u.event_data.data2);
691
692 break;
693 }
694
695 case omx_message::EMPTY_BUFFER_DONE:
696 {
697 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
698
699 LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
700
701 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
702 size_t i = 0;
703 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
704 ++i;
705 }
706
707 CHECK(i < buffers->size());
708 if (!(*buffers)[i].mOwnedByComponent) {
709 LOGW("We already own input buffer %p, yet received "
710 "an EMPTY_BUFFER_DONE.", buffer);
711 }
712
713 buffers->editItemAt(i).mOwnedByComponent = false;
714
715 if (mPortStatus[kPortIndexInput] == DISABLING) {
716 LOGV("Port is disabled, freeing buffer %p", buffer);
717
718 status_t err =
719 mOMX->free_buffer(mNode, kPortIndexInput, buffer);
720 CHECK_EQ(err, OK);
721
722 buffers->removeAt(i);
723 } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
724 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
725 drainInputBuffer(&buffers->editItemAt(i));
726 }
727
728 break;
729 }
730
731 case omx_message::FILL_BUFFER_DONE:
732 {
733 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
734 OMX_U32 flags = msg.u.extended_buffer_data.flags;
735
736 LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
737 buffer,
738 msg.u.extended_buffer_data.range_length,
739 flags);
740
741 LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
742 msg.u.extended_buffer_data.timestamp,
743 msg.u.extended_buffer_data.timestamp / 1E6);
744
745 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
746 size_t i = 0;
747 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
748 ++i;
749 }
750
751 CHECK(i < buffers->size());
752 BufferInfo *info = &buffers->editItemAt(i);
753
754 if (!info->mOwnedByComponent) {
755 LOGW("We already own output buffer %p, yet received "
756 "a FILL_BUFFER_DONE.", buffer);
757 }
758
759 info->mOwnedByComponent = false;
760
761 if (mPortStatus[kPortIndexOutput] == DISABLING) {
762 LOGV("Port is disabled, freeing buffer %p", buffer);
763
764 status_t err =
765 mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
766 CHECK_EQ(err, OK);
767
768 buffers->removeAt(i);
769 } else if (flags & OMX_BUFFERFLAG_EOS) {
770 LOGV("No more output data.");
771 mNoMoreOutputData = true;
772 mBufferFilled.signal();
773 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
774 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
775
776 MediaBuffer *buffer = info->mMediaBuffer;
777
778 buffer->set_range(
779 msg.u.extended_buffer_data.range_offset,
780 msg.u.extended_buffer_data.range_length);
781
782 buffer->meta_data()->clear();
783
784 buffer->meta_data()->setInt32(
785 kKeyTimeUnits,
786 (msg.u.extended_buffer_data.timestamp + 500) / 1000);
787
788 buffer->meta_data()->setInt32(
789 kKeyTimeScale, 1000);
790
791 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
792 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
793 }
794
795 buffer->meta_data()->setPointer(
796 kKeyPlatformPrivate,
797 msg.u.extended_buffer_data.platform_private);
798
799 buffer->meta_data()->setPointer(
800 kKeyBufferID,
801 msg.u.extended_buffer_data.buffer);
802
803 mFilledBuffers.push_back(i);
804 mBufferFilled.signal();
805 }
806
807 break;
808 }
809
810 default:
811 {
812 CHECK(!"should not be here.");
813 break;
814 }
815 }
816}
817
818void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
819 switch (event) {
820 case OMX_EventCmdComplete:
821 {
822 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
823 break;
824 }
825
826 case OMX_EventError:
827 {
828 LOGE("ERROR(%ld, %ld)", data1, data2);
829
830 setState(ERROR);
831 break;
832 }
833
834 case OMX_EventPortSettingsChanged:
835 {
836 onPortSettingsChanged(data1);
837 break;
838 }
839
840 case OMX_EventBufferFlag:
841 {
842 LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
843
844 if (data1 == kPortIndexOutput) {
845 mNoMoreOutputData = true;
846 }
847 break;
848 }
849
850 default:
851 {
852 LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
853 break;
854 }
855 }
856}
857
858void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
859 switch (cmd) {
860 case OMX_CommandStateSet:
861 {
862 onStateChange((OMX_STATETYPE)data);
863 break;
864 }
865
866 case OMX_CommandPortDisable:
867 {
868 OMX_U32 portIndex = data;
869 LOGV("PORT_DISABLED(%ld)", portIndex);
870
871 CHECK(mState == EXECUTING || mState == RECONFIGURING);
872 CHECK_EQ(mPortStatus[portIndex], DISABLING);
873 CHECK_EQ(mPortBuffers[portIndex].size(), 0);
874
875 mPortStatus[portIndex] = DISABLED;
876
877 if (mState == RECONFIGURING) {
878 CHECK_EQ(portIndex, kPortIndexOutput);
879
880 enablePortAsync(portIndex);
881
882 status_t err = allocateBuffersOnPort(portIndex);
883 CHECK_EQ(err, OK);
884 }
885 break;
886 }
887
888 case OMX_CommandPortEnable:
889 {
890 OMX_U32 portIndex = data;
891 LOGV("PORT_ENABLED(%ld)", portIndex);
892
893 CHECK(mState == EXECUTING || mState == RECONFIGURING);
894 CHECK_EQ(mPortStatus[portIndex], ENABLING);
895
896 mPortStatus[portIndex] = ENABLED;
897
898 if (mState == RECONFIGURING) {
899 CHECK_EQ(portIndex, kPortIndexOutput);
900
901 setState(EXECUTING);
902
903 fillOutputBuffers();
904 }
905 break;
906 }
907
908 case OMX_CommandFlush:
909 {
910 OMX_U32 portIndex = data;
911
912 LOGV("FLUSH_DONE(%ld)", portIndex);
913
914 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
915 mPortStatus[portIndex] = ENABLED;
916
917 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
918 mPortBuffers[portIndex].size());
919
920 if (mState == RECONFIGURING) {
921 CHECK_EQ(portIndex, kPortIndexOutput);
922
923 disablePortAsync(portIndex);
924 } else {
925 // We're flushing both ports in preparation for seeking.
926
927 if (mPortStatus[kPortIndexInput] == ENABLED
928 && mPortStatus[kPortIndexOutput] == ENABLED) {
929 LOGV("Finished flushing both ports, now continuing from"
930 " seek-time.");
931
932 drainInputBuffers();
933 fillOutputBuffers();
934 }
935 }
936
937 break;
938 }
939
940 default:
941 {
942 LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
943 break;
944 }
945 }
946}
947
948void OMXCodec::onStateChange(OMX_STATETYPE newState) {
949 switch (newState) {
950 case OMX_StateIdle:
951 {
952 LOGV("Now Idle.");
953 if (mState == LOADED_TO_IDLE) {
954 status_t err = mOMX->send_command(
955 mNode, OMX_CommandStateSet, OMX_StateExecuting);
956
957 CHECK_EQ(err, OK);
958
959 setState(IDLE_TO_EXECUTING);
960 } else {
961 CHECK_EQ(mState, EXECUTING_TO_IDLE);
962
963 CHECK_EQ(
964 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
965 mPortBuffers[kPortIndexInput].size());
966
967 CHECK_EQ(
968 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
969 mPortBuffers[kPortIndexOutput].size());
970
971 status_t err = mOMX->send_command(
972 mNode, OMX_CommandStateSet, OMX_StateLoaded);
973
974 CHECK_EQ(err, OK);
975
976 err = freeBuffersOnPort(kPortIndexInput);
977 CHECK_EQ(err, OK);
978
979 err = freeBuffersOnPort(kPortIndexOutput);
980 CHECK_EQ(err, OK);
981
982 mPortStatus[kPortIndexInput] = ENABLED;
983 mPortStatus[kPortIndexOutput] = ENABLED;
984
985 setState(IDLE_TO_LOADED);
986 }
987 break;
988 }
989
990 case OMX_StateExecuting:
991 {
992 CHECK_EQ(mState, IDLE_TO_EXECUTING);
993
994 LOGV("Now Executing.");
995
996 setState(EXECUTING);
997
998 drainInputBuffers();
999 fillOutputBuffers();
1000 break;
1001 }
1002
1003 case OMX_StateLoaded:
1004 {
1005 CHECK_EQ(mState, IDLE_TO_LOADED);
1006
1007 LOGV("Now Loaded.");
1008
1009 setState(LOADED);
1010 break;
1011 }
1012
1013 default:
1014 {
1015 CHECK(!"should not be here.");
1016 break;
1017 }
1018 }
1019}
1020
1021// static
1022size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1023 size_t n = 0;
1024 for (size_t i = 0; i < buffers.size(); ++i) {
1025 if (!buffers[i].mOwnedByComponent) {
1026 ++n;
1027 }
1028 }
1029
1030 return n;
1031}
1032
1033status_t OMXCodec::freeBuffersOnPort(
1034 OMX_U32 portIndex, bool onlyThoseWeOwn) {
1035 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1036
1037 status_t stickyErr = OK;
1038
1039 for (size_t i = buffers->size(); i-- > 0;) {
1040 BufferInfo *info = &buffers->editItemAt(i);
1041
1042 if (onlyThoseWeOwn && info->mOwnedByComponent) {
1043 continue;
1044 }
1045
1046 CHECK_EQ(info->mOwnedByComponent, false);
1047
1048 status_t err =
1049 mOMX->free_buffer(mNode, portIndex, info->mBuffer);
1050
1051 if (err != OK) {
1052 stickyErr = err;
1053 }
1054
1055 if (info->mMediaBuffer != NULL) {
1056 info->mMediaBuffer->setObserver(NULL);
1057
1058 // Make sure nobody but us owns this buffer at this point.
1059 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1060
1061 info->mMediaBuffer->release();
1062 }
1063
1064 buffers->removeAt(i);
1065 }
1066
1067 CHECK(onlyThoseWeOwn || buffers->isEmpty());
1068
1069 return stickyErr;
1070}
1071
1072void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
1073 LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
1074
1075 CHECK_EQ(mState, EXECUTING);
1076 CHECK_EQ(portIndex, kPortIndexOutput);
1077 setState(RECONFIGURING);
1078
1079 if (mQuirks & kNeedsFlushBeforeDisable) {
1080 flushPortAsync(portIndex);
1081 } else {
1082 disablePortAsync(portIndex);
1083 }
1084}
1085
1086void OMXCodec::flushPortAsync(OMX_U32 portIndex) {
1087 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1088
1089 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1090 mPortStatus[portIndex] = SHUTTING_DOWN;
1091
1092 status_t err =
1093 mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
1094 CHECK_EQ(err, OK);
1095}
1096
1097void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1098 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1099
1100 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1101 mPortStatus[portIndex] = DISABLING;
1102
1103 status_t err =
1104 mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
1105 CHECK_EQ(err, OK);
1106
1107 freeBuffersOnPort(portIndex, true);
1108}
1109
1110void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1111 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1112
1113 CHECK_EQ(mPortStatus[portIndex], DISABLED);
1114 mPortStatus[portIndex] = ENABLING;
1115
1116 status_t err =
1117 mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
1118 CHECK_EQ(err, OK);
1119}
1120
1121void OMXCodec::fillOutputBuffers() {
1122 CHECK_EQ(mState, EXECUTING);
1123
1124 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1125 for (size_t i = 0; i < buffers->size(); ++i) {
1126 fillOutputBuffer(&buffers->editItemAt(i));
1127 }
1128}
1129
1130void OMXCodec::drainInputBuffers() {
1131 CHECK_EQ(mState, EXECUTING);
1132
1133 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1134 for (size_t i = 0; i < buffers->size(); ++i) {
1135 drainInputBuffer(&buffers->editItemAt(i));
1136 }
1137}
1138
1139void OMXCodec::drainInputBuffer(BufferInfo *info) {
1140 CHECK_EQ(info->mOwnedByComponent, false);
1141
1142 if (mSignalledEOS) {
1143 return;
1144 }
1145
1146 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1147 const CodecSpecificData *specific =
1148 mCodecSpecificData[mCodecSpecificDataIndex];
1149
1150 size_t size = specific->mSize;
1151
1152 if (!strcasecmp(mMIME, "video/avc")
1153 && !(mQuirks & kWantsRawNALFrames)) {
1154 static const uint8_t kNALStartCode[4] =
1155 { 0x00, 0x00, 0x00, 0x01 };
1156
1157 CHECK(info->mMem->size() >= specific->mSize + 4);
1158
1159 size += 4;
1160
1161 memcpy(info->mMem->pointer(), kNALStartCode, 4);
1162 memcpy((uint8_t *)info->mMem->pointer() + 4,
1163 specific->mData, specific->mSize);
1164 } else {
1165 CHECK(info->mMem->size() >= specific->mSize);
1166 memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1167 }
1168
1169 mOMX->empty_buffer(
1170 mNode, info->mBuffer, 0, size,
1171 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1172 0);
1173
1174 info->mOwnedByComponent = true;
1175
1176 ++mCodecSpecificDataIndex;
1177 return;
1178 }
1179
1180 MediaBuffer *srcBuffer;
1181 status_t err;
1182 if (mSeekTimeUs >= 0) {
1183 MediaSource::ReadOptions options;
1184 options.setSeekTo(mSeekTimeUs);
1185 mSeekTimeUs = -1;
1186
1187 err = mSource->read(&srcBuffer, &options);
1188 } else {
1189 err = mSource->read(&srcBuffer);
1190 }
1191
1192 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1193 OMX_TICKS timestamp = 0;
1194 size_t srcLength = 0;
1195
1196 if (err != OK) {
1197 LOGV("signalling end of input stream.");
1198 flags |= OMX_BUFFERFLAG_EOS;
1199
1200 mSignalledEOS = true;
1201 } else {
1202 srcLength = srcBuffer->range_length();
1203
1204 if (info->mMem->size() < srcLength) {
1205 LOGE("info->mMem->size() = %d, srcLength = %d",
1206 info->mMem->size(), srcLength);
1207 }
1208 CHECK(info->mMem->size() >= srcLength);
1209 memcpy(info->mMem->pointer(),
1210 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1211 srcLength);
1212
1213 int32_t units, scale;
1214 if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units)
1215 && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) {
1216 timestamp = ((OMX_TICKS)units * 1000000) / scale;
1217
1218 LOGV("Calling empty_buffer on buffer %p (length %d)",
1219 info->mBuffer, srcLength);
1220 LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
1221 timestamp, timestamp / 1E6);
1222 }
1223 }
1224
1225 mOMX->empty_buffer(
1226 mNode, info->mBuffer, 0, srcLength,
1227 flags, timestamp);
1228
1229 info->mOwnedByComponent = true;
1230
1231 if (srcBuffer != NULL) {
1232 srcBuffer->release();
1233 srcBuffer = NULL;
1234 }
1235}
1236
1237void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1238 CHECK_EQ(info->mOwnedByComponent, false);
1239
1240 LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
1241 mOMX->fill_buffer(mNode, info->mBuffer);
1242
1243 info->mOwnedByComponent = true;
1244}
1245
1246void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1247 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1248 for (size_t i = 0; i < buffers->size(); ++i) {
1249 if ((*buffers)[i].mBuffer == buffer) {
1250 drainInputBuffer(&buffers->editItemAt(i));
1251 return;
1252 }
1253 }
1254
1255 CHECK(!"should not be here.");
1256}
1257
1258void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1259 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1260 for (size_t i = 0; i < buffers->size(); ++i) {
1261 if ((*buffers)[i].mBuffer == buffer) {
1262 fillOutputBuffer(&buffers->editItemAt(i));
1263 return;
1264 }
1265 }
1266
1267 CHECK(!"should not be here.");
1268}
1269
1270void OMXCodec::setState(State newState) {
1271 mState = newState;
1272 mAsyncCompletion.signal();
1273
1274 // This may cause some spurious wakeups but is necessary to
1275 // unblock the reader if we enter ERROR state.
1276 mBufferFilled.signal();
1277}
1278
1279void OMXCodec::setAMRFormat() {
1280 if (!mIsEncoder) {
1281 OMX_AUDIO_PARAM_AMRTYPE def;
1282 def.nSize = sizeof(def);
1283 def.nVersion.s.nVersionMajor = 1;
1284 def.nVersion.s.nVersionMinor = 1;
1285 def.nPortIndex = kPortIndexInput;
1286
1287 status_t err =
1288 mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1289
1290 CHECK_EQ(err, OK);
1291
1292 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1293 def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1294
1295 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1296 CHECK_EQ(err, OK);
1297 }
1298
1299 ////////////////////////
1300
1301 if (mIsEncoder) {
1302 sp<MetaData> format = mSource->getFormat();
1303 int32_t sampleRate;
1304 int32_t numChannels;
1305 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1306 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1307
1308 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1309 pcmParams.nSize = sizeof(pcmParams);
1310 pcmParams.nVersion.s.nVersionMajor = 1;
1311 pcmParams.nVersion.s.nVersionMinor = 1;
1312 pcmParams.nPortIndex = kPortIndexInput;
1313
1314 status_t err = mOMX->get_parameter(
1315 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1316
1317 CHECK_EQ(err, OK);
1318
1319 pcmParams.nChannels = numChannels;
1320 pcmParams.eNumData = OMX_NumericalDataSigned;
1321 pcmParams.bInterleaved = OMX_TRUE;
1322 pcmParams.nBitPerSample = 16;
1323 pcmParams.nSamplingRate = sampleRate;
1324 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1325
1326 if (numChannels == 1) {
1327 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1328 } else {
1329 CHECK_EQ(numChannels, 2);
1330
1331 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1332 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1333 }
1334
1335 err = mOMX->set_parameter(
1336 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1337
1338 CHECK_EQ(err, OK);
1339 }
1340}
1341
1342void OMXCodec::setAACFormat() {
1343 OMX_AUDIO_PARAM_AACPROFILETYPE def;
1344 def.nSize = sizeof(def);
1345 def.nVersion.s.nVersionMajor = 1;
1346 def.nVersion.s.nVersionMinor = 1;
1347 def.nPortIndex = kPortIndexInput;
1348
1349 status_t err =
1350 mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
1351 CHECK_EQ(err, OK);
1352
1353 def.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1354
1355 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
1356 CHECK_EQ(err, OK);
1357}
1358
1359void OMXCodec::setImageOutputFormat(
1360 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
1361 LOGV("setImageOutputFormat(%ld, %ld)", width, height);
1362
1363#if 0
1364 OMX_INDEXTYPE index;
1365 status_t err = mOMX->get_extension_index(
1366 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1367 CHECK_EQ(err, OK);
1368
1369 err = mOMX->set_config(mNode, index, &format, sizeof(format));
1370 CHECK_EQ(err, OK);
1371#endif
1372
1373 OMX_PARAM_PORTDEFINITIONTYPE def;
1374 def.nSize = sizeof(def);
1375 def.nVersion.s.nVersionMajor = 1;
1376 def.nVersion.s.nVersionMinor = 1;
1377 def.nPortIndex = kPortIndexOutput;
1378
1379 status_t err = mOMX->get_parameter(
1380 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1381 CHECK_EQ(err, OK);
1382
1383 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1384
1385 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1386
1387 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1388 imageDef->eColorFormat = format;
1389 imageDef->nFrameWidth = width;
1390 imageDef->nFrameHeight = height;
1391
1392 switch (format) {
1393 case OMX_COLOR_FormatYUV420PackedPlanar:
1394 case OMX_COLOR_FormatYUV411Planar:
1395 {
1396 def.nBufferSize = (width * height * 3) / 2;
1397 break;
1398 }
1399
1400 case OMX_COLOR_FormatCbYCrY:
1401 {
1402 def.nBufferSize = width * height * 2;
1403 break;
1404 }
1405
1406 case OMX_COLOR_Format32bitARGB8888:
1407 {
1408 def.nBufferSize = width * height * 4;
1409 break;
1410 }
1411
1412 default:
1413 CHECK(!"Should not be here. Unknown color format.");
1414 break;
1415 }
1416
1417 err = mOMX->set_parameter(
1418 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1419 CHECK_EQ(err, OK);
1420
1421 ////
1422
1423 def.nPortIndex = kPortIndexInput;
1424
1425 err = mOMX->get_parameter(
1426 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1427 CHECK_EQ(err, OK);
1428
1429 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1430 imageDef->nFrameWidth = width;
1431 imageDef->nFrameHeight = height;
1432
1433 def.nBufferSize = 128 * 1024;
1434 def.nBufferCountActual = def.nBufferCountMin;
1435
1436 err = mOMX->set_parameter(
1437 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1438 CHECK_EQ(err, OK);
1439}
1440
1441void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
1442 CodecSpecificData *specific =
1443 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
1444
1445 specific->mSize = size;
1446 memcpy(specific->mData, data, size);
1447
1448 mCodecSpecificData.push(specific);
1449}
1450
1451void OMXCodec::clearCodecSpecificData() {
1452 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
1453 free(mCodecSpecificData.editItemAt(i));
1454 }
1455 mCodecSpecificData.clear();
1456 mCodecSpecificDataIndex = 0;
1457}
1458
1459status_t OMXCodec::start(MetaData *) {
1460 if (mState != LOADED) {
1461 return UNKNOWN_ERROR;
1462 }
1463
1464 sp<MetaData> params = new MetaData;
1465 if (!strcasecmp(mMIME, "video/avc") && !(mQuirks & kWantsRawNALFrames)) {
1466 params->setInt32(kKeyNeedsNALFraming, true);
1467 }
1468 status_t err = mSource->start(params.get());
1469
1470 if (err != OK) {
1471 return err;
1472 }
1473
1474 mCodecSpecificDataIndex = 0;
1475 mSignalledEOS = false;
1476 mNoMoreOutputData = false;
1477 mSeekTimeUs = -1;
1478 mFilledBuffers.clear();
1479
1480 return init();
1481}
1482
1483status_t OMXCodec::stop() {
1484 LOGI("stop");
1485
1486 Mutex::Autolock autoLock(mLock);
1487
1488 while (isIntermediateState(mState)) {
1489 mAsyncCompletion.wait(mLock);
1490 }
1491
1492 switch (mState) {
1493 case LOADED:
1494 case ERROR:
1495 break;
1496
1497 case EXECUTING:
1498 {
1499 setState(EXECUTING_TO_IDLE);
1500
1501 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1502 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1503
1504 status_t err =
1505 mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
1506 CHECK_EQ(err, OK);
1507
1508 while (mState != LOADED && mState != ERROR) {
1509 mAsyncCompletion.wait(mLock);
1510 }
1511
1512 break;
1513 }
1514
1515 default:
1516 {
1517 CHECK(!"should not be here.");
1518 break;
1519 }
1520 }
1521
1522 mSource->stop();
1523
1524 return OK;
1525}
1526
1527sp<MetaData> OMXCodec::getFormat() {
1528 return mOutputFormat;
1529}
1530
1531status_t OMXCodec::read(
1532 MediaBuffer **buffer, const ReadOptions *options) {
1533 *buffer = NULL;
1534
1535 Mutex::Autolock autoLock(mLock);
1536
1537 if (mState != EXECUTING && mState != RECONFIGURING) {
1538 return UNKNOWN_ERROR;
1539 }
1540
1541 int64_t seekTimeUs;
1542 if (options && options->getSeekTo(&seekTimeUs)) {
1543 LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
1544
1545 mSignalledEOS = false;
1546 mNoMoreOutputData = false;
1547
1548 CHECK(seekTimeUs >= 0);
1549 mSeekTimeUs = seekTimeUs;
1550
1551 mFilledBuffers.clear();
1552
1553 CHECK_EQ(mState, EXECUTING);
1554
1555 flushPortAsync(kPortIndexInput);
1556 flushPortAsync(kPortIndexOutput);
1557 }
1558
1559 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
1560 mBufferFilled.wait(mLock);
1561 }
1562
1563 if (mState == ERROR) {
1564 return UNKNOWN_ERROR;
1565 }
1566
1567 if (mFilledBuffers.empty()) {
1568 return ERROR_END_OF_STREAM;
1569 }
1570
1571 size_t index = *mFilledBuffers.begin();
1572 mFilledBuffers.erase(mFilledBuffers.begin());
1573
1574 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1575 info->mMediaBuffer->add_ref();
1576 *buffer = info->mMediaBuffer;
1577
1578 return OK;
1579}
1580
1581void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
1582 Mutex::Autolock autoLock(mLock);
1583
1584 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1585 for (size_t i = 0; i < buffers->size(); ++i) {
1586 BufferInfo *info = &buffers->editItemAt(i);
1587
1588 if (info->mMediaBuffer == buffer) {
1589 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1590 fillOutputBuffer(info);
1591 return;
1592 }
1593 }
1594
1595 CHECK(!"should not be here.");
1596}
1597
1598static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
1599 static const char *kNames[] = {
1600 "OMX_IMAGE_CodingUnused",
1601 "OMX_IMAGE_CodingAutoDetect",
1602 "OMX_IMAGE_CodingJPEG",
1603 "OMX_IMAGE_CodingJPEG2K",
1604 "OMX_IMAGE_CodingEXIF",
1605 "OMX_IMAGE_CodingTIFF",
1606 "OMX_IMAGE_CodingGIF",
1607 "OMX_IMAGE_CodingPNG",
1608 "OMX_IMAGE_CodingLZW",
1609 "OMX_IMAGE_CodingBMP",
1610 };
1611
1612 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1613
1614 if (type < 0 || (size_t)type >= numNames) {
1615 return "UNKNOWN";
1616 } else {
1617 return kNames[type];
1618 }
1619}
1620
1621static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
1622 static const char *kNames[] = {
1623 "OMX_COLOR_FormatUnused",
1624 "OMX_COLOR_FormatMonochrome",
1625 "OMX_COLOR_Format8bitRGB332",
1626 "OMX_COLOR_Format12bitRGB444",
1627 "OMX_COLOR_Format16bitARGB4444",
1628 "OMX_COLOR_Format16bitARGB1555",
1629 "OMX_COLOR_Format16bitRGB565",
1630 "OMX_COLOR_Format16bitBGR565",
1631 "OMX_COLOR_Format18bitRGB666",
1632 "OMX_COLOR_Format18bitARGB1665",
1633 "OMX_COLOR_Format19bitARGB1666",
1634 "OMX_COLOR_Format24bitRGB888",
1635 "OMX_COLOR_Format24bitBGR888",
1636 "OMX_COLOR_Format24bitARGB1887",
1637 "OMX_COLOR_Format25bitARGB1888",
1638 "OMX_COLOR_Format32bitBGRA8888",
1639 "OMX_COLOR_Format32bitARGB8888",
1640 "OMX_COLOR_FormatYUV411Planar",
1641 "OMX_COLOR_FormatYUV411PackedPlanar",
1642 "OMX_COLOR_FormatYUV420Planar",
1643 "OMX_COLOR_FormatYUV420PackedPlanar",
1644 "OMX_COLOR_FormatYUV420SemiPlanar",
1645 "OMX_COLOR_FormatYUV422Planar",
1646 "OMX_COLOR_FormatYUV422PackedPlanar",
1647 "OMX_COLOR_FormatYUV422SemiPlanar",
1648 "OMX_COLOR_FormatYCbYCr",
1649 "OMX_COLOR_FormatYCrYCb",
1650 "OMX_COLOR_FormatCbYCrY",
1651 "OMX_COLOR_FormatCrYCbY",
1652 "OMX_COLOR_FormatYUV444Interleaved",
1653 "OMX_COLOR_FormatRawBayer8bit",
1654 "OMX_COLOR_FormatRawBayer10bit",
1655 "OMX_COLOR_FormatRawBayer8bitcompressed",
1656 "OMX_COLOR_FormatL2",
1657 "OMX_COLOR_FormatL4",
1658 "OMX_COLOR_FormatL8",
1659 "OMX_COLOR_FormatL16",
1660 "OMX_COLOR_FormatL24",
1661 "OMX_COLOR_FormatL32",
1662 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
1663 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
1664 "OMX_COLOR_Format18BitBGR666",
1665 "OMX_COLOR_Format24BitARGB6666",
1666 "OMX_COLOR_Format24BitABGR6666",
1667 };
1668
1669 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1670
1671 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1672
1673 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
1674 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
1675 } else if (type < 0 || (size_t)type >= numNames) {
1676 return "UNKNOWN";
1677 } else {
1678 return kNames[type];
1679 }
1680}
1681
1682static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
1683 static const char *kNames[] = {
1684 "OMX_VIDEO_CodingUnused",
1685 "OMX_VIDEO_CodingAutoDetect",
1686 "OMX_VIDEO_CodingMPEG2",
1687 "OMX_VIDEO_CodingH263",
1688 "OMX_VIDEO_CodingMPEG4",
1689 "OMX_VIDEO_CodingWMV",
1690 "OMX_VIDEO_CodingRV",
1691 "OMX_VIDEO_CodingAVC",
1692 "OMX_VIDEO_CodingMJPEG",
1693 };
1694
1695 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1696
1697 if (type < 0 || (size_t)type >= numNames) {
1698 return "UNKNOWN";
1699 } else {
1700 return kNames[type];
1701 }
1702}
1703
1704static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
1705 static const char *kNames[] = {
1706 "OMX_AUDIO_CodingUnused",
1707 "OMX_AUDIO_CodingAutoDetect",
1708 "OMX_AUDIO_CodingPCM",
1709 "OMX_AUDIO_CodingADPCM",
1710 "OMX_AUDIO_CodingAMR",
1711 "OMX_AUDIO_CodingGSMFR",
1712 "OMX_AUDIO_CodingGSMEFR",
1713 "OMX_AUDIO_CodingGSMHR",
1714 "OMX_AUDIO_CodingPDCFR",
1715 "OMX_AUDIO_CodingPDCEFR",
1716 "OMX_AUDIO_CodingPDCHR",
1717 "OMX_AUDIO_CodingTDMAFR",
1718 "OMX_AUDIO_CodingTDMAEFR",
1719 "OMX_AUDIO_CodingQCELP8",
1720 "OMX_AUDIO_CodingQCELP13",
1721 "OMX_AUDIO_CodingEVRC",
1722 "OMX_AUDIO_CodingSMV",
1723 "OMX_AUDIO_CodingG711",
1724 "OMX_AUDIO_CodingG723",
1725 "OMX_AUDIO_CodingG726",
1726 "OMX_AUDIO_CodingG729",
1727 "OMX_AUDIO_CodingAAC",
1728 "OMX_AUDIO_CodingMP3",
1729 "OMX_AUDIO_CodingSBC",
1730 "OMX_AUDIO_CodingVORBIS",
1731 "OMX_AUDIO_CodingWMA",
1732 "OMX_AUDIO_CodingRA",
1733 "OMX_AUDIO_CodingMIDI",
1734 };
1735
1736 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1737
1738 if (type < 0 || (size_t)type >= numNames) {
1739 return "UNKNOWN";
1740 } else {
1741 return kNames[type];
1742 }
1743}
1744
1745static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
1746 static const char *kNames[] = {
1747 "OMX_AUDIO_PCMModeLinear",
1748 "OMX_AUDIO_PCMModeALaw",
1749 "OMX_AUDIO_PCMModeMULaw",
1750 };
1751
1752 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1753
1754 if (type < 0 || (size_t)type >= numNames) {
1755 return "UNKNOWN";
1756 } else {
1757 return kNames[type];
1758 }
1759}
1760
1761
1762void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
1763 OMX_PARAM_PORTDEFINITIONTYPE def;
1764 def.nSize = sizeof(def);
1765 def.nVersion.s.nVersionMajor = 1;
1766 def.nVersion.s.nVersionMinor = 1;
1767 def.nPortIndex = portIndex;
1768
1769 status_t err = mOMX->get_parameter(
1770 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1771 CHECK_EQ(err, OK);
1772
1773 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
1774
1775 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
1776 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
1777
1778 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
1779 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
1780 printf(" nBufferSize = %ld\n", def.nBufferSize);
1781
1782 switch (def.eDomain) {
1783 case OMX_PortDomainImage:
1784 {
1785 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1786
1787 printf("\n");
1788 printf(" // Image\n");
1789 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
1790 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
1791 printf(" nStride = %ld\n", imageDef->nStride);
1792
1793 printf(" eCompressionFormat = %s\n",
1794 imageCompressionFormatString(imageDef->eCompressionFormat));
1795
1796 printf(" eColorFormat = %s\n",
1797 colorFormatString(imageDef->eColorFormat));
1798
1799 break;
1800 }
1801
1802 case OMX_PortDomainVideo:
1803 {
1804 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1805
1806 printf("\n");
1807 printf(" // Video\n");
1808 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
1809 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
1810 printf(" nStride = %ld\n", videoDef->nStride);
1811
1812 printf(" eCompressionFormat = %s\n",
1813 videoCompressionFormatString(videoDef->eCompressionFormat));
1814
1815 printf(" eColorFormat = %s\n",
1816 colorFormatString(videoDef->eColorFormat));
1817
1818 break;
1819 }
1820
1821 case OMX_PortDomainAudio:
1822 {
1823 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1824
1825 printf("\n");
1826 printf(" // Audio\n");
1827 printf(" eEncoding = %s\n",
1828 audioCodingTypeString(audioDef->eEncoding));
1829
1830 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
1831 OMX_AUDIO_PARAM_PCMMODETYPE params;
1832 params.nSize = sizeof(params);
1833 params.nVersion.s.nVersionMajor = 1;
1834 params.nVersion.s.nVersionMinor = 1;
1835 params.nPortIndex = portIndex;
1836
1837 err = mOMX->get_parameter(
1838 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
1839 CHECK_EQ(err, OK);
1840
1841 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
1842 printf(" nChannels = %ld\n", params.nChannels);
1843 printf(" bInterleaved = %d\n", params.bInterleaved);
1844 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
1845
1846 printf(" eNumData = %s\n",
1847 params.eNumData == OMX_NumericalDataSigned
1848 ? "signed" : "unsigned");
1849
1850 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
1851 }
1852
1853 break;
1854 }
1855
1856 default:
1857 {
1858 printf(" // Unknown\n");
1859 break;
1860 }
1861 }
1862
1863 printf("}\n");
1864}
1865
1866void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
1867 mOutputFormat = new MetaData;
1868 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
1869
1870 OMX_PARAM_PORTDEFINITIONTYPE def;
1871 def.nSize = sizeof(def);
1872 def.nVersion.s.nVersionMajor = 1;
1873 def.nVersion.s.nVersionMinor = 1;
1874 def.nPortIndex = kPortIndexOutput;
1875
1876 status_t err = mOMX->get_parameter(
1877 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1878 CHECK_EQ(err, OK);
1879
1880 switch (def.eDomain) {
1881 case OMX_PortDomainImage:
1882 {
1883 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1884 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1885
1886 mOutputFormat->setCString(kKeyMIMEType, "image/raw");
1887 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
1888 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
1889 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
1890 break;
1891 }
1892
1893 case OMX_PortDomainAudio:
1894 {
1895 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
1896
1897 CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
1898
1899 OMX_AUDIO_PARAM_PCMMODETYPE params;
1900 params.nSize = sizeof(params);
1901 params.nVersion.s.nVersionMajor = 1;
1902 params.nVersion.s.nVersionMinor = 1;
1903 params.nPortIndex = kPortIndexOutput;
1904
1905 err = mOMX->get_parameter(
1906 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
1907 CHECK_EQ(err, OK);
1908
1909 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
1910 CHECK_EQ(params.nBitPerSample, 16);
1911 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
1912
1913 int32_t numChannels, sampleRate;
1914 inputFormat->findInt32(kKeyChannelCount, &numChannels);
1915 inputFormat->findInt32(kKeySampleRate, &sampleRate);
1916
1917 mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
1918 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
1919 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
1920 break;
1921 }
1922
1923 case OMX_PortDomainVideo:
1924 {
1925 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1926
1927 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
1928 mOutputFormat->setCString(kKeyMIMEType, "video/raw");
1929 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
1930 mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es");
1931 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
1932 mOutputFormat->setCString(kKeyMIMEType, "video/3gpp");
1933 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
1934 mOutputFormat->setCString(kKeyMIMEType, "video/avc");
1935 } else {
1936 CHECK(!"Unknown compression format.");
1937 }
1938
1939 if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
1940 // This component appears to be lying to me.
1941 mOutputFormat->setInt32(
1942 kKeyWidth, (video_def->nFrameWidth + 15) & -16);
1943 mOutputFormat->setInt32(
1944 kKeyHeight, (video_def->nFrameHeight + 15) & -16);
1945 } else {
1946 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
1947 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
1948 }
1949
1950 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
1951 break;
1952 }
1953
1954 default:
1955 {
1956 CHECK(!"should not be here, neither audio nor video.");
1957 break;
1958 }
1959 }
1960}
1961
1962} // namespace android