blob: 3cba1424abb1ded96c9cf23e3605f04fb3517dcd [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>
Andreas Huberebf66ea2009-08-19 13:32:58 -070033#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070034#include <utils/Vector.h>
35
36#include <OMX_Audio.h>
37#include <OMX_Component.h>
38
39namespace android {
40
41struct CodecInfo {
42 const char *mime;
43 const char *codec;
44};
45
46static const CodecInfo kDecoderInfo[] = {
47 { "image/jpeg", "OMX.TI.JPEG.decode" },
48 { "audio/mpeg", "OMX.TI.MP3.decode" },
49 { "audio/mpeg", "OMX.PV.mp3dec" },
50 { "audio/3gpp", "OMX.TI.AMR.decode" },
51 { "audio/3gpp", "OMX.PV.amrdec" },
Andreas Huberee606e62009-09-08 10:19:21 -070052 { "audio/amr-wb", "OMX.TI.WBAMR.decode" },
Andreas Huberbe06d262009-08-14 14:37:10 -070053 { "audio/mp4a-latm", "OMX.TI.AAC.decode" },
54 { "audio/mp4a-latm", "OMX.PV.aacdec" },
55 { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" },
56 { "video/mp4v-es", "OMX.TI.Video.Decoder" },
57 { "video/mp4v-es", "OMX.PV.mpeg4dec" },
58 { "video/3gpp", "OMX.qcom.video.decoder.h263" },
59 { "video/3gpp", "OMX.TI.Video.Decoder" },
60 { "video/3gpp", "OMX.PV.h263dec" },
61 { "video/avc", "OMX.qcom.video.decoder.avc" },
62 { "video/avc", "OMX.TI.Video.Decoder" },
63 { "video/avc", "OMX.PV.avcdec" },
64};
65
66static const CodecInfo kEncoderInfo[] = {
67 { "audio/3gpp", "OMX.TI.AMR.encode" },
68 { "audio/3gpp", "OMX.PV.amrencnb" },
Andreas Huberee606e62009-09-08 10:19:21 -070069 { "audio/amr-wb", "OMX.TI.WBAMR.encode" },
Andreas Huberbe06d262009-08-14 14:37:10 -070070 { "audio/mp4a-latm", "OMX.TI.AAC.encode" },
71 { "audio/mp4a-latm", "OMX.PV.aacenc" },
72 { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" },
73 { "video/mp4v-es", "OMX.TI.Video.encoder" },
74 { "video/mp4v-es", "OMX.PV.mpeg4enc" },
75 { "video/3gpp", "OMX.qcom.video.encoder.h263" },
76 { "video/3gpp", "OMX.TI.Video.encoder" },
77 { "video/3gpp", "OMX.PV.h263enc" },
78 { "video/avc", "OMX.TI.Video.encoder" },
79 { "video/avc", "OMX.PV.avcenc" },
80};
81
Andreas Huber4c483422009-09-02 16:05:36 -070082#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
83
Andreas Huberbe06d262009-08-14 14:37:10 -070084struct OMXCodecObserver : public BnOMXObserver {
85 OMXCodecObserver(const wp<OMXCodec> &target)
86 : mTarget(target) {
87 }
88
89 // from IOMXObserver
90 virtual void on_message(const omx_message &msg) {
91 sp<OMXCodec> codec = mTarget.promote();
92
93 if (codec.get() != NULL) {
94 codec->on_message(msg);
95 }
96 }
97
98protected:
99 virtual ~OMXCodecObserver() {}
100
101private:
102 wp<OMXCodec> mTarget;
103
104 OMXCodecObserver(const OMXCodecObserver &);
105 OMXCodecObserver &operator=(const OMXCodecObserver &);
106};
107
108static const char *GetCodec(const CodecInfo *info, size_t numInfos,
109 const char *mime, int index) {
110 CHECK(index >= 0);
111 for(size_t i = 0; i < numInfos; ++i) {
112 if (!strcasecmp(mime, info[i].mime)) {
113 if (index == 0) {
114 return info[i].codec;
115 }
116
117 --index;
118 }
119 }
120
121 return NULL;
122}
123
Andreas Huberebf66ea2009-08-19 13:32:58 -0700124enum {
125 kAVCProfileBaseline = 0x42,
126 kAVCProfileMain = 0x4d,
127 kAVCProfileExtended = 0x58,
128 kAVCProfileHigh = 0x64,
129 kAVCProfileHigh10 = 0x6e,
130 kAVCProfileHigh422 = 0x7a,
131 kAVCProfileHigh444 = 0xf4,
132 kAVCProfileCAVLC444Intra = 0x2c
133};
134
135static const char *AVCProfileToString(uint8_t profile) {
136 switch (profile) {
137 case kAVCProfileBaseline:
138 return "Baseline";
139 case kAVCProfileMain:
140 return "Main";
141 case kAVCProfileExtended:
142 return "Extended";
143 case kAVCProfileHigh:
144 return "High";
145 case kAVCProfileHigh10:
146 return "High 10";
147 case kAVCProfileHigh422:
148 return "High 422";
149 case kAVCProfileHigh444:
150 return "High 444";
151 case kAVCProfileCAVLC444Intra:
152 return "CAVLC 444 Intra";
153 default: return "Unknown";
154 }
155}
156
Andreas Huber4c483422009-09-02 16:05:36 -0700157template<class T>
158static void InitOMXParams(T *params) {
159 params->nSize = sizeof(T);
160 params->nVersion.s.nVersionMajor = 1;
161 params->nVersion.s.nVersionMinor = 0;
162 params->nVersion.s.nRevision = 0;
163 params->nVersion.s.nStep = 0;
164}
165
Andreas Huberbe06d262009-08-14 14:37:10 -0700166// static
167sp<OMXCodec> OMXCodec::Create(
168 const sp<IOMX> &omx,
169 const sp<MetaData> &meta, bool createEncoder,
170 const sp<MediaSource> &source) {
171 const char *mime;
172 bool success = meta->findCString(kKeyMIMEType, &mime);
173 CHECK(success);
174
175 const char *componentName = NULL;
176 IOMX::node_id node = 0;
177 for (int index = 0;; ++index) {
178 if (createEncoder) {
179 componentName = GetCodec(
180 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
181 mime, index);
182 } else {
183 componentName = GetCodec(
184 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
185 mime, index);
186 }
187
188 if (!componentName) {
189 return NULL;
190 }
191
192 LOGV("Attempting to allocate OMX node '%s'", componentName);
193
194 status_t err = omx->allocate_node(componentName, &node);
195 if (err == OK) {
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700196 LOGI("Successfully allocated OMX node '%s'", componentName);
Andreas Huberbe06d262009-08-14 14:37:10 -0700197 break;
198 }
199 }
200
201 uint32_t quirks = 0;
202 if (!strcmp(componentName, "OMX.PV.avcdec")) {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700203 quirks |= kWantsNALFragments;
Andreas Huberbe06d262009-08-14 14:37:10 -0700204 }
205 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
206 quirks |= kNeedsFlushBeforeDisable;
207 }
208 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
209 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700210 quirks |= kRequiresFlushCompleteEmulation;
Andreas Huber127fcdc2009-08-26 16:27:02 -0700211
212 // The following is currently necessary for proper shutdown
213 // behaviour, but NOT enabled by default in order to make the
214 // bug reproducible...
215 // quirks |= kRequiresFlushBeforeShutdown;
Andreas Huberbe06d262009-08-14 14:37:10 -0700216 }
217 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
218 quirks |= kRequiresLoadedToIdleAfterAllocation;
219 quirks |= kRequiresAllocateBufferOnInputPorts;
220 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700221 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
222 // XXX Required on P....on only.
223 quirks |= kRequiresAllocateBufferOnOutputPorts;
224 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700225
226 sp<OMXCodec> codec = new OMXCodec(
227 omx, node, quirks, createEncoder, mime, componentName,
228 source);
229
230 uint32_t type;
231 const void *data;
232 size_t size;
233 if (meta->findData(kKeyESDS, &type, &data, &size)) {
234 ESDS esds((const char *)data, size);
235 CHECK_EQ(esds.InitCheck(), OK);
236
237 const void *codec_specific_data;
238 size_t codec_specific_data_size;
239 esds.getCodecSpecificInfo(
240 &codec_specific_data, &codec_specific_data_size);
241
242 printf("found codec-specific data of size %d\n",
243 codec_specific_data_size);
244
245 codec->addCodecSpecificData(
246 codec_specific_data, codec_specific_data_size);
247 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
248 printf("found avcc of size %d\n", size);
249
Andreas Huberebf66ea2009-08-19 13:32:58 -0700250 // Parse the AVCDecoderConfigurationRecord
251
252 const uint8_t *ptr = (const uint8_t *)data;
253
254 CHECK(size >= 7);
255 CHECK_EQ(ptr[0], 1); // configurationVersion == 1
256 uint8_t profile = ptr[1];
257 uint8_t level = ptr[3];
258
259 CHECK((ptr[4] >> 2) == 0x3f); // reserved
260
261 size_t lengthSize = 1 + (ptr[4] & 3);
262
263 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
264 // violates it...
265 // CHECK((ptr[5] >> 5) == 7); // reserved
266
267 size_t numSeqParameterSets = ptr[5] & 31;
268
269 ptr += 6;
Andreas Huberbe06d262009-08-14 14:37:10 -0700270 size -= 6;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700271
272 for (size_t i = 0; i < numSeqParameterSets; ++i) {
273 CHECK(size >= 2);
274 size_t length = U16_AT(ptr);
Andreas Huberbe06d262009-08-14 14:37:10 -0700275
276 ptr += 2;
277 size -= 2;
278
Andreas Huberbe06d262009-08-14 14:37:10 -0700279 CHECK(size >= length);
280
281 codec->addCodecSpecificData(ptr, length);
282
283 ptr += length;
284 size -= length;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700285 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700286
Andreas Huberebf66ea2009-08-19 13:32:58 -0700287 CHECK(size >= 1);
288 size_t numPictureParameterSets = *ptr;
289 ++ptr;
290 --size;
Andreas Huberbe06d262009-08-14 14:37:10 -0700291
Andreas Huberebf66ea2009-08-19 13:32:58 -0700292 for (size_t i = 0; i < numPictureParameterSets; ++i) {
293 CHECK(size >= 2);
294 size_t length = U16_AT(ptr);
295
296 ptr += 2;
297 size -= 2;
298
299 CHECK(size >= length);
300
301 codec->addCodecSpecificData(ptr, length);
302
303 ptr += length;
304 size -= length;
305 }
306
307 LOGI("AVC profile = %d (%s), level = %d",
308 (int)profile, AVCProfileToString(profile), (int)level / 10);
309
310 if (!strcmp(componentName, "OMX.TI.Video.Decoder")
311 && (profile != kAVCProfileBaseline || level > 39)) {
312 // This stream exceeds the decoder's capabilities.
313
314 LOGE("Profile and/or level exceed the decoder's capabilities.");
315 return NULL;
Andreas Huberbe06d262009-08-14 14:37:10 -0700316 }
317 }
318
319 if (!strcasecmp("audio/3gpp", mime)) {
320 codec->setAMRFormat();
321 }
Andreas Huberee606e62009-09-08 10:19:21 -0700322 if (!strcasecmp("audio/amr-wb", mime)) {
323 codec->setAMRWBFormat();
324 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700325 if (!strcasecmp("audio/mp4a-latm", mime)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700326 int32_t numChannels, sampleRate;
327 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
328 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
329
330 codec->setAACFormat(numChannels, sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700331 }
332 if (!strncasecmp(mime, "video/", 6)) {
333 int32_t width, height;
334 bool success = meta->findInt32(kKeyWidth, &width);
335 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700336 CHECK(success);
Andreas Huberbe06d262009-08-14 14:37:10 -0700337
338 if (createEncoder) {
339 codec->setVideoInputFormat(mime, width, height);
340 } else {
341 codec->setVideoOutputFormat(mime, width, height);
342 }
343 }
344 if (!strcasecmp(mime, "image/jpeg")
345 && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
346 OMX_COLOR_FORMATTYPE format =
347 OMX_COLOR_Format32bitARGB8888;
348 // OMX_COLOR_FormatYUV420PackedPlanar;
349 // OMX_COLOR_FormatCbYCrY;
350 // OMX_COLOR_FormatYUV411Planar;
351
352 int32_t width, height;
353 bool success = meta->findInt32(kKeyWidth, &width);
354 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700355
356 int32_t compressedSize;
357 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700358 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700359
360 CHECK(success);
361 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700362
363 codec->setImageOutputFormat(format, width, height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700364 codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700365 }
366
Andreas Huberda050cf22009-09-02 14:01:43 -0700367 int32_t maxInputSize;
368 if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
369 codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
370 }
371
372 if (!strcmp(componentName, "OMX.TI.AMR.encode")
373 || !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
374 codec->setMinBufferSize(kPortIndexOutput, 8192); // XXX
375 }
376
Andreas Huberbe06d262009-08-14 14:37:10 -0700377 codec->initOutputFormat(meta);
378
379 return codec;
380}
381
Andreas Huberda050cf22009-09-02 14:01:43 -0700382void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
383 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700384 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700385 def.nPortIndex = portIndex;
386
387 status_t err = mOMX->get_parameter(
388 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
389 CHECK_EQ(err, OK);
390
391 if (def.nBufferSize < size) {
392 def.nBufferSize = size;
393
394 }
395
396 err = mOMX->set_parameter(
397 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
398 CHECK_EQ(err, OK);
399}
400
Andreas Huberbe06d262009-08-14 14:37:10 -0700401status_t OMXCodec::setVideoPortFormatType(
402 OMX_U32 portIndex,
403 OMX_VIDEO_CODINGTYPE compressionFormat,
404 OMX_COLOR_FORMATTYPE colorFormat) {
405 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700406 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700407 format.nPortIndex = portIndex;
408 format.nIndex = 0;
409 bool found = false;
410
411 OMX_U32 index = 0;
412 for (;;) {
413 format.nIndex = index;
414 status_t err = mOMX->get_parameter(
415 mNode, OMX_IndexParamVideoPortFormat,
416 &format, sizeof(format));
417
418 if (err != OK) {
419 return err;
420 }
421
422 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700423 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700424
425#if 1
426 LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
427 portIndex,
428 index, format.eCompressionFormat, format.eColorFormat);
429#endif
430
431 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
432 if (portIndex == kPortIndexInput
433 && colorFormat == format.eColorFormat) {
434 // eCompressionFormat does not seem right.
435 found = true;
436 break;
437 }
438 if (portIndex == kPortIndexOutput
439 && compressionFormat == format.eCompressionFormat) {
440 // eColorFormat does not seem right.
441 found = true;
442 break;
443 }
444 }
445
446 if (format.eCompressionFormat == compressionFormat
447 && format.eColorFormat == colorFormat) {
448 found = true;
449 break;
450 }
451
452 ++index;
453 }
454
455 if (!found) {
456 return UNKNOWN_ERROR;
457 }
458
459 LOGI("found a match.");
460 status_t err = mOMX->set_parameter(
461 mNode, OMX_IndexParamVideoPortFormat,
462 &format, sizeof(format));
463
464 return err;
465}
466
467void OMXCodec::setVideoInputFormat(
468 const char *mime, OMX_U32 width, OMX_U32 height) {
469 LOGI("setVideoInputFormat width=%ld, height=%ld", width, height);
470
471 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
472 if (!strcasecmp("video/avc", mime)) {
473 compressionFormat = OMX_VIDEO_CodingAVC;
474 } else if (!strcasecmp("video/mp4v-es", mime)) {
475 compressionFormat = OMX_VIDEO_CodingMPEG4;
476 } else if (!strcasecmp("video/3gpp", mime)) {
477 compressionFormat = OMX_VIDEO_CodingH263;
478 } else {
479 LOGE("Not a supported video mime type: %s", mime);
480 CHECK(!"Should not be here. Not a supported video mime type.");
481 }
482
483 OMX_COLOR_FORMATTYPE colorFormat =
484 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
485
486 if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
487 colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
488 }
489
490 setVideoPortFormatType(
491 kPortIndexInput, OMX_VIDEO_CodingUnused,
492 colorFormat);
493
494 setVideoPortFormatType(
495 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
496
497 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700498 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700499 def.nPortIndex = kPortIndexOutput;
500
Andreas Huber4c483422009-09-02 16:05:36 -0700501 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
502
Andreas Huberbe06d262009-08-14 14:37:10 -0700503 status_t err = mOMX->get_parameter(
504 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
505
506 CHECK_EQ(err, OK);
507 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
508
509 video_def->nFrameWidth = width;
510 video_def->nFrameHeight = height;
511
512 video_def->eCompressionFormat = compressionFormat;
513 video_def->eColorFormat = OMX_COLOR_FormatUnused;
514
515 err = mOMX->set_parameter(
516 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
517 CHECK_EQ(err, OK);
518
519 ////////////////////////////////////////////////////////////////////////////
520
Andreas Huber4c483422009-09-02 16:05:36 -0700521 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700522 def.nPortIndex = kPortIndexInput;
523
524 err = mOMX->get_parameter(
525 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
526 CHECK_EQ(err, OK);
527
528 def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
Andreas Huber4c483422009-09-02 16:05:36 -0700529 LOGI("Setting nBufferSize = %ld", def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700530
531 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
532
533 video_def->nFrameWidth = width;
534 video_def->nFrameHeight = height;
535 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
536 video_def->eColorFormat = colorFormat;
537
538 err = mOMX->set_parameter(
539 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
540 CHECK_EQ(err, OK);
541}
542
543void OMXCodec::setVideoOutputFormat(
544 const char *mime, OMX_U32 width, OMX_U32 height) {
545 LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
546
Andreas Huberbe06d262009-08-14 14:37:10 -0700547 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
548 if (!strcasecmp("video/avc", mime)) {
549 compressionFormat = OMX_VIDEO_CodingAVC;
550 } else if (!strcasecmp("video/mp4v-es", mime)) {
551 compressionFormat = OMX_VIDEO_CodingMPEG4;
552 } else if (!strcasecmp("video/3gpp", mime)) {
553 compressionFormat = OMX_VIDEO_CodingH263;
554 } else {
555 LOGE("Not a supported video mime type: %s", mime);
556 CHECK(!"Should not be here. Not a supported video mime type.");
557 }
558
559 setVideoPortFormatType(
560 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
561
562#if 1
563 {
564 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700565 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700566 format.nPortIndex = kPortIndexOutput;
567 format.nIndex = 0;
568
569 status_t err = mOMX->get_parameter(
570 mNode, OMX_IndexParamVideoPortFormat,
571 &format, sizeof(format));
572 CHECK_EQ(err, OK);
573 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
574
575 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
576
577 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
578 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
579 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
580 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
581
582 err = mOMX->set_parameter(
583 mNode, OMX_IndexParamVideoPortFormat,
584 &format, sizeof(format));
585 CHECK_EQ(err, OK);
586 }
587#endif
588
589 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700590 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700591 def.nPortIndex = kPortIndexInput;
592
Andreas Huber4c483422009-09-02 16:05:36 -0700593 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
594
Andreas Huberbe06d262009-08-14 14:37:10 -0700595 status_t err = mOMX->get_parameter(
596 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
597
598 CHECK_EQ(err, OK);
599
600#if 1
601 // XXX Need a (much) better heuristic to compute input buffer sizes.
602 const size_t X = 64 * 1024;
603 if (def.nBufferSize < X) {
604 def.nBufferSize = X;
605 }
606#endif
607
608 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
609
610 video_def->nFrameWidth = width;
611 video_def->nFrameHeight = height;
612
613 video_def->eColorFormat = OMX_COLOR_FormatUnused;
614
615 err = mOMX->set_parameter(
616 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
617 CHECK_EQ(err, OK);
618
619 ////////////////////////////////////////////////////////////////////////////
620
Andreas Huber4c483422009-09-02 16:05:36 -0700621 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700622 def.nPortIndex = kPortIndexOutput;
623
624 err = mOMX->get_parameter(
625 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
626 CHECK_EQ(err, OK);
627 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
628
629#if 0
630 def.nBufferSize =
631 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
632#endif
633
634 video_def->nFrameWidth = width;
635 video_def->nFrameHeight = height;
636
637 err = mOMX->set_parameter(
638 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
639 CHECK_EQ(err, OK);
640}
641
642
643OMXCodec::OMXCodec(
644 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
Andreas Huberebf66ea2009-08-19 13:32:58 -0700645 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -0700646 const char *mime,
647 const char *componentName,
648 const sp<MediaSource> &source)
649 : mOMX(omx),
650 mNode(node),
651 mQuirks(quirks),
652 mIsEncoder(isEncoder),
653 mMIME(strdup(mime)),
654 mComponentName(strdup(componentName)),
655 mSource(source),
656 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -0700657 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -0700658 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -0700659 mSignalledEOS(false),
660 mNoMoreOutputData(false),
661 mSeekTimeUs(-1) {
662 mPortStatus[kPortIndexInput] = ENABLED;
663 mPortStatus[kPortIndexOutput] = ENABLED;
664
665 mObserver = new OMXCodecObserver(this);
666 mOMX->observe_node(mNode, mObserver);
Andreas Huber4c483422009-09-02 16:05:36 -0700667
668 setComponentRole();
669}
670
671void OMXCodec::setComponentRole() {
672 struct MimeToRole {
673 const char *mime;
674 const char *decoderRole;
675 const char *encoderRole;
676 };
677
678 static const MimeToRole kMimeToRole[] = {
679 { "audio/mpeg", "audio_decoder.mp3", "audio_encoder.mp3" },
680 { "audio/3gpp", "audio_decoder.amrnb", "audio_encoder.amrnb" },
Andreas Huberee606e62009-09-08 10:19:21 -0700681 { "audio/amr-wb", "audio_decoder.amrwb", "audio_encoder.amrwb" },
Andreas Huber4c483422009-09-02 16:05:36 -0700682 { "audio/mp4a-latm", "audio_decoder.aac", "audio_encoder.aac" },
683 { "video/avc", "video_decoder.avc", "video_encoder.avc" },
684 { "video/mp4v-es", "video_decoder.mpeg4", "video_encoder.mpeg4" },
685 { "video/3gpp", "video_decoder.h263", "video_encoder.h263" },
686 };
687
688 static const size_t kNumMimeToRole =
689 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
690
691 size_t i;
692 for (i = 0; i < kNumMimeToRole; ++i) {
693 if (!strcasecmp(mMIME, kMimeToRole[i].mime)) {
694 break;
695 }
696 }
697
698 if (i == kNumMimeToRole) {
699 return;
700 }
701
702 const char *role =
703 mIsEncoder ? kMimeToRole[i].encoderRole
704 : kMimeToRole[i].decoderRole;
705
706 if (role != NULL) {
707 CODEC_LOGV("Setting component role '%s'.", role);
708
709 OMX_PARAM_COMPONENTROLETYPE roleParams;
710 InitOMXParams(&roleParams);
711
712 strncpy((char *)roleParams.cRole,
713 role, OMX_MAX_STRINGNAME_SIZE - 1);
714
715 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
716
717 status_t err = mOMX->set_parameter(
718 mNode, OMX_IndexParamStandardComponentRole,
719 &roleParams, sizeof(roleParams));
720
721 if (err != OK) {
722 LOGW("Failed to set standard component role '%s'.", role);
723 }
724 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700725}
726
727OMXCodec::~OMXCodec() {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700728 CHECK(mState == LOADED || mState == ERROR);
Andreas Huberbe06d262009-08-14 14:37:10 -0700729
730 status_t err = mOMX->observe_node(mNode, NULL);
731 CHECK_EQ(err, OK);
732
733 err = mOMX->free_node(mNode);
734 CHECK_EQ(err, OK);
735
736 mNode = NULL;
737 setState(DEAD);
738
739 clearCodecSpecificData();
740
741 free(mComponentName);
742 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700743
Andreas Huberbe06d262009-08-14 14:37:10 -0700744 free(mMIME);
745 mMIME = NULL;
746}
747
748status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -0700749 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -0700750
751 CHECK_EQ(mState, LOADED);
752
753 status_t err;
754 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
755 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
756 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700757 setState(LOADED_TO_IDLE);
758 }
759
760 err = allocateBuffers();
761 CHECK_EQ(err, OK);
762
763 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
764 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
765 CHECK_EQ(err, OK);
766
767 setState(LOADED_TO_IDLE);
768 }
769
770 while (mState != EXECUTING && mState != ERROR) {
771 mAsyncCompletion.wait(mLock);
772 }
773
774 return mState == ERROR ? UNKNOWN_ERROR : OK;
775}
776
777// static
778bool OMXCodec::isIntermediateState(State state) {
779 return state == LOADED_TO_IDLE
780 || state == IDLE_TO_EXECUTING
781 || state == EXECUTING_TO_IDLE
782 || state == IDLE_TO_LOADED
783 || state == RECONFIGURING;
784}
785
786status_t OMXCodec::allocateBuffers() {
787 status_t err = allocateBuffersOnPort(kPortIndexInput);
788
789 if (err != OK) {
790 return err;
791 }
792
793 return allocateBuffersOnPort(kPortIndexOutput);
794}
795
796status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
797 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700798 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700799 def.nPortIndex = portIndex;
800
801 status_t err = mOMX->get_parameter(
802 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
803
804 if (err != OK) {
805 return err;
806 }
807
Andreas Huber5c0a9132009-08-20 11:16:40 -0700808 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
809 mDealer[portIndex] = new MemoryDealer(totalSize);
810
Andreas Huberbe06d262009-08-14 14:37:10 -0700811 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -0700812 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700813 CHECK(mem.get() != NULL);
814
815 IOMX::buffer_id buffer;
816 if (portIndex == kPortIndexInput
817 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
818 err = mOMX->allocate_buffer_with_backup(
819 mNode, portIndex, mem, &buffer);
Andreas Huber446f44f2009-08-25 17:23:44 -0700820 } else if (portIndex == kPortIndexOutput
821 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
822 err = mOMX->allocate_buffer(
823 mNode, portIndex, def.nBufferSize, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700824 } else {
825 err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
826 }
827
828 if (err != OK) {
829 LOGE("allocate_buffer_with_backup failed");
830 return err;
831 }
832
833 BufferInfo info;
834 info.mBuffer = buffer;
835 info.mOwnedByComponent = false;
836 info.mMem = mem;
837 info.mMediaBuffer = NULL;
838
839 if (portIndex == kPortIndexOutput) {
840 info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
841 info.mMediaBuffer->setObserver(this);
842 }
843
844 mPortBuffers[portIndex].push(info);
845
Andreas Huber4c483422009-09-02 16:05:36 -0700846 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -0700847 portIndex == kPortIndexInput ? "input" : "output");
848 }
849
850 dumpPortStatus(portIndex);
851
852 return OK;
853}
854
855void OMXCodec::on_message(const omx_message &msg) {
856 Mutex::Autolock autoLock(mLock);
857
858 switch (msg.type) {
859 case omx_message::EVENT:
860 {
861 onEvent(
862 msg.u.event_data.event, msg.u.event_data.data1,
863 msg.u.event_data.data2);
864
865 break;
866 }
867
868 case omx_message::EMPTY_BUFFER_DONE:
869 {
870 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
871
Andreas Huber4c483422009-09-02 16:05:36 -0700872 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700873
874 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
875 size_t i = 0;
876 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
877 ++i;
878 }
879
880 CHECK(i < buffers->size());
881 if (!(*buffers)[i].mOwnedByComponent) {
882 LOGW("We already own input buffer %p, yet received "
883 "an EMPTY_BUFFER_DONE.", buffer);
884 }
885
886 buffers->editItemAt(i).mOwnedByComponent = false;
887
888 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -0700889 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700890
891 status_t err =
892 mOMX->free_buffer(mNode, kPortIndexInput, buffer);
893 CHECK_EQ(err, OK);
894
895 buffers->removeAt(i);
896 } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
897 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
898 drainInputBuffer(&buffers->editItemAt(i));
899 }
900
901 break;
902 }
903
904 case omx_message::FILL_BUFFER_DONE:
905 {
906 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
907 OMX_U32 flags = msg.u.extended_buffer_data.flags;
908
Andreas Huber4c483422009-09-02 16:05:36 -0700909 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
Andreas Huberbe06d262009-08-14 14:37:10 -0700910 buffer,
911 msg.u.extended_buffer_data.range_length,
912 flags);
913
Andreas Huber4c483422009-09-02 16:05:36 -0700914 CODEC_LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -0700915 msg.u.extended_buffer_data.timestamp,
916 msg.u.extended_buffer_data.timestamp / 1E6);
917
918 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
919 size_t i = 0;
920 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
921 ++i;
922 }
923
924 CHECK(i < buffers->size());
925 BufferInfo *info = &buffers->editItemAt(i);
926
927 if (!info->mOwnedByComponent) {
928 LOGW("We already own output buffer %p, yet received "
929 "a FILL_BUFFER_DONE.", buffer);
930 }
931
932 info->mOwnedByComponent = false;
933
934 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -0700935 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700936
937 status_t err =
938 mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
939 CHECK_EQ(err, OK);
940
941 buffers->removeAt(i);
Andreas Huberd7795892009-08-26 10:33:47 -0700942 } else if (mPortStatus[kPortIndexOutput] == ENABLED
943 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -0700944 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -0700945 mNoMoreOutputData = true;
946 mBufferFilled.signal();
947 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
948 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700949
Andreas Huberbe06d262009-08-14 14:37:10 -0700950 MediaBuffer *buffer = info->mMediaBuffer;
951
952 buffer->set_range(
953 msg.u.extended_buffer_data.range_offset,
954 msg.u.extended_buffer_data.range_length);
955
956 buffer->meta_data()->clear();
957
958 buffer->meta_data()->setInt32(
959 kKeyTimeUnits,
960 (msg.u.extended_buffer_data.timestamp + 500) / 1000);
961
962 buffer->meta_data()->setInt32(
963 kKeyTimeScale, 1000);
964
965 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
966 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
967 }
968
969 buffer->meta_data()->setPointer(
970 kKeyPlatformPrivate,
971 msg.u.extended_buffer_data.platform_private);
972
973 buffer->meta_data()->setPointer(
974 kKeyBufferID,
975 msg.u.extended_buffer_data.buffer);
976
977 mFilledBuffers.push_back(i);
978 mBufferFilled.signal();
979 }
980
981 break;
982 }
983
984 default:
985 {
986 CHECK(!"should not be here.");
987 break;
988 }
989 }
990}
991
992void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
993 switch (event) {
994 case OMX_EventCmdComplete:
995 {
996 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
997 break;
998 }
999
1000 case OMX_EventError:
1001 {
1002 LOGE("ERROR(%ld, %ld)", data1, data2);
1003
1004 setState(ERROR);
1005 break;
1006 }
1007
1008 case OMX_EventPortSettingsChanged:
1009 {
1010 onPortSettingsChanged(data1);
1011 break;
1012 }
1013
1014 case OMX_EventBufferFlag:
1015 {
Andreas Huber4c483422009-09-02 16:05:36 -07001016 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
Andreas Huberbe06d262009-08-14 14:37:10 -07001017
1018 if (data1 == kPortIndexOutput) {
1019 mNoMoreOutputData = true;
1020 }
1021 break;
1022 }
1023
1024 default:
1025 {
Andreas Huber4c483422009-09-02 16:05:36 -07001026 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001027 break;
1028 }
1029 }
1030}
1031
1032void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1033 switch (cmd) {
1034 case OMX_CommandStateSet:
1035 {
1036 onStateChange((OMX_STATETYPE)data);
1037 break;
1038 }
1039
1040 case OMX_CommandPortDisable:
1041 {
1042 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001043 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001044
1045 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1046 CHECK_EQ(mPortStatus[portIndex], DISABLING);
1047 CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1048
1049 mPortStatus[portIndex] = DISABLED;
1050
1051 if (mState == RECONFIGURING) {
1052 CHECK_EQ(portIndex, kPortIndexOutput);
1053
1054 enablePortAsync(portIndex);
1055
1056 status_t err = allocateBuffersOnPort(portIndex);
1057 CHECK_EQ(err, OK);
1058 }
1059 break;
1060 }
1061
1062 case OMX_CommandPortEnable:
1063 {
1064 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001065 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001066
1067 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1068 CHECK_EQ(mPortStatus[portIndex], ENABLING);
1069
1070 mPortStatus[portIndex] = ENABLED;
1071
1072 if (mState == RECONFIGURING) {
1073 CHECK_EQ(portIndex, kPortIndexOutput);
1074
1075 setState(EXECUTING);
1076
1077 fillOutputBuffers();
1078 }
1079 break;
1080 }
1081
1082 case OMX_CommandFlush:
1083 {
1084 OMX_U32 portIndex = data;
1085
Andreas Huber4c483422009-09-02 16:05:36 -07001086 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001087
1088 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1089 mPortStatus[portIndex] = ENABLED;
1090
1091 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1092 mPortBuffers[portIndex].size());
1093
1094 if (mState == RECONFIGURING) {
1095 CHECK_EQ(portIndex, kPortIndexOutput);
1096
1097 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001098 } else if (mState == EXECUTING_TO_IDLE) {
1099 if (mPortStatus[kPortIndexInput] == ENABLED
1100 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001101 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001102 "transition from EXECUTING to IDLE.");
1103
1104 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1105 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1106
1107 status_t err =
1108 mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
1109 CHECK_EQ(err, OK);
1110 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001111 } else {
1112 // We're flushing both ports in preparation for seeking.
1113
1114 if (mPortStatus[kPortIndexInput] == ENABLED
1115 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001116 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07001117 " seek-time.");
1118
1119 drainInputBuffers();
1120 fillOutputBuffers();
1121 }
1122 }
1123
1124 break;
1125 }
1126
1127 default:
1128 {
Andreas Huber4c483422009-09-02 16:05:36 -07001129 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07001130 break;
1131 }
1132 }
1133}
1134
1135void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1136 switch (newState) {
1137 case OMX_StateIdle:
1138 {
Andreas Huber4c483422009-09-02 16:05:36 -07001139 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001140 if (mState == LOADED_TO_IDLE) {
1141 status_t err = mOMX->send_command(
1142 mNode, OMX_CommandStateSet, OMX_StateExecuting);
1143
1144 CHECK_EQ(err, OK);
1145
1146 setState(IDLE_TO_EXECUTING);
1147 } else {
1148 CHECK_EQ(mState, EXECUTING_TO_IDLE);
1149
1150 CHECK_EQ(
1151 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1152 mPortBuffers[kPortIndexInput].size());
1153
1154 CHECK_EQ(
1155 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1156 mPortBuffers[kPortIndexOutput].size());
1157
1158 status_t err = mOMX->send_command(
1159 mNode, OMX_CommandStateSet, OMX_StateLoaded);
1160
1161 CHECK_EQ(err, OK);
1162
1163 err = freeBuffersOnPort(kPortIndexInput);
1164 CHECK_EQ(err, OK);
1165
1166 err = freeBuffersOnPort(kPortIndexOutput);
1167 CHECK_EQ(err, OK);
1168
1169 mPortStatus[kPortIndexInput] = ENABLED;
1170 mPortStatus[kPortIndexOutput] = ENABLED;
1171
1172 setState(IDLE_TO_LOADED);
1173 }
1174 break;
1175 }
1176
1177 case OMX_StateExecuting:
1178 {
1179 CHECK_EQ(mState, IDLE_TO_EXECUTING);
1180
Andreas Huber4c483422009-09-02 16:05:36 -07001181 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001182
1183 setState(EXECUTING);
1184
Andreas Huber42978e52009-08-27 10:08:39 -07001185 // Buffers will be submitted to the component in the first
1186 // call to OMXCodec::read as mInitialBufferSubmit is true at
1187 // this point. This ensures that this on_message call returns,
1188 // releases the lock and ::init can notice the state change and
1189 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07001190 break;
1191 }
1192
1193 case OMX_StateLoaded:
1194 {
1195 CHECK_EQ(mState, IDLE_TO_LOADED);
1196
Andreas Huber4c483422009-09-02 16:05:36 -07001197 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001198
1199 setState(LOADED);
1200 break;
1201 }
1202
1203 default:
1204 {
1205 CHECK(!"should not be here.");
1206 break;
1207 }
1208 }
1209}
1210
1211// static
1212size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1213 size_t n = 0;
1214 for (size_t i = 0; i < buffers.size(); ++i) {
1215 if (!buffers[i].mOwnedByComponent) {
1216 ++n;
1217 }
1218 }
1219
1220 return n;
1221}
1222
1223status_t OMXCodec::freeBuffersOnPort(
1224 OMX_U32 portIndex, bool onlyThoseWeOwn) {
1225 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1226
1227 status_t stickyErr = OK;
1228
1229 for (size_t i = buffers->size(); i-- > 0;) {
1230 BufferInfo *info = &buffers->editItemAt(i);
1231
1232 if (onlyThoseWeOwn && info->mOwnedByComponent) {
1233 continue;
1234 }
1235
1236 CHECK_EQ(info->mOwnedByComponent, false);
1237
1238 status_t err =
1239 mOMX->free_buffer(mNode, portIndex, info->mBuffer);
1240
1241 if (err != OK) {
1242 stickyErr = err;
1243 }
1244
1245 if (info->mMediaBuffer != NULL) {
1246 info->mMediaBuffer->setObserver(NULL);
1247
1248 // Make sure nobody but us owns this buffer at this point.
1249 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1250
1251 info->mMediaBuffer->release();
1252 }
1253
1254 buffers->removeAt(i);
1255 }
1256
1257 CHECK(onlyThoseWeOwn || buffers->isEmpty());
1258
1259 return stickyErr;
1260}
1261
1262void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07001263 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001264
1265 CHECK_EQ(mState, EXECUTING);
1266 CHECK_EQ(portIndex, kPortIndexOutput);
1267 setState(RECONFIGURING);
1268
1269 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07001270 if (!flushPortAsync(portIndex)) {
1271 onCmdComplete(OMX_CommandFlush, portIndex);
1272 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001273 } else {
1274 disablePortAsync(portIndex);
1275 }
1276}
1277
Andreas Huber404cc412009-08-25 14:26:05 -07001278bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07001279 CHECK(mState == EXECUTING || mState == RECONFIGURING
1280 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001281
Andreas Huber4c483422009-09-02 16:05:36 -07001282 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07001283 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1284 mPortBuffers[portIndex].size());
1285
Andreas Huberbe06d262009-08-14 14:37:10 -07001286 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1287 mPortStatus[portIndex] = SHUTTING_DOWN;
1288
Andreas Huber404cc412009-08-25 14:26:05 -07001289 if ((mQuirks & kRequiresFlushCompleteEmulation)
1290 && countBuffersWeOwn(mPortBuffers[portIndex])
1291 == mPortBuffers[portIndex].size()) {
1292 // No flush is necessary and this component fails to send a
1293 // flush-complete event in this case.
1294
1295 return false;
1296 }
1297
Andreas Huberbe06d262009-08-14 14:37:10 -07001298 status_t err =
1299 mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
1300 CHECK_EQ(err, OK);
Andreas Huber404cc412009-08-25 14:26:05 -07001301
1302 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001303}
1304
1305void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1306 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1307
1308 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1309 mPortStatus[portIndex] = DISABLING;
1310
1311 status_t err =
1312 mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
1313 CHECK_EQ(err, OK);
1314
1315 freeBuffersOnPort(portIndex, true);
1316}
1317
1318void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1319 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1320
1321 CHECK_EQ(mPortStatus[portIndex], DISABLED);
1322 mPortStatus[portIndex] = ENABLING;
1323
1324 status_t err =
1325 mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
1326 CHECK_EQ(err, OK);
1327}
1328
1329void OMXCodec::fillOutputBuffers() {
1330 CHECK_EQ(mState, EXECUTING);
1331
1332 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1333 for (size_t i = 0; i < buffers->size(); ++i) {
1334 fillOutputBuffer(&buffers->editItemAt(i));
1335 }
1336}
1337
1338void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07001339 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07001340
1341 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1342 for (size_t i = 0; i < buffers->size(); ++i) {
1343 drainInputBuffer(&buffers->editItemAt(i));
1344 }
1345}
1346
1347void OMXCodec::drainInputBuffer(BufferInfo *info) {
1348 CHECK_EQ(info->mOwnedByComponent, false);
1349
1350 if (mSignalledEOS) {
1351 return;
1352 }
1353
1354 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1355 const CodecSpecificData *specific =
1356 mCodecSpecificData[mCodecSpecificDataIndex];
1357
1358 size_t size = specific->mSize;
1359
Andreas Huber4f5e6022009-08-19 09:29:34 -07001360 if (!strcasecmp("video/avc", mMIME)
1361 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001362 static const uint8_t kNALStartCode[4] =
1363 { 0x00, 0x00, 0x00, 0x01 };
1364
1365 CHECK(info->mMem->size() >= specific->mSize + 4);
1366
1367 size += 4;
1368
1369 memcpy(info->mMem->pointer(), kNALStartCode, 4);
1370 memcpy((uint8_t *)info->mMem->pointer() + 4,
1371 specific->mData, specific->mSize);
1372 } else {
1373 CHECK(info->mMem->size() >= specific->mSize);
1374 memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1375 }
1376
1377 mOMX->empty_buffer(
1378 mNode, info->mBuffer, 0, size,
1379 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1380 0);
1381
1382 info->mOwnedByComponent = true;
1383
1384 ++mCodecSpecificDataIndex;
1385 return;
1386 }
1387
1388 MediaBuffer *srcBuffer;
1389 status_t err;
1390 if (mSeekTimeUs >= 0) {
1391 MediaSource::ReadOptions options;
1392 options.setSeekTo(mSeekTimeUs);
1393 mSeekTimeUs = -1;
1394
1395 err = mSource->read(&srcBuffer, &options);
1396 } else {
1397 err = mSource->read(&srcBuffer);
1398 }
1399
1400 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1401 OMX_TICKS timestamp = 0;
1402 size_t srcLength = 0;
1403
1404 if (err != OK) {
Andreas Huber4c483422009-09-02 16:05:36 -07001405 CODEC_LOGV("signalling end of input stream.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001406 flags |= OMX_BUFFERFLAG_EOS;
1407
1408 mSignalledEOS = true;
1409 } else {
1410 srcLength = srcBuffer->range_length();
1411
1412 if (info->mMem->size() < srcLength) {
1413 LOGE("info->mMem->size() = %d, srcLength = %d",
1414 info->mMem->size(), srcLength);
1415 }
1416 CHECK(info->mMem->size() >= srcLength);
1417 memcpy(info->mMem->pointer(),
1418 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1419 srcLength);
1420
1421 int32_t units, scale;
1422 if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units)
1423 && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) {
1424 timestamp = ((OMX_TICKS)units * 1000000) / scale;
1425
Andreas Huber4c483422009-09-02 16:05:36 -07001426 CODEC_LOGV("Calling empty_buffer on buffer %p (length %d)",
Andreas Huberbe06d262009-08-14 14:37:10 -07001427 info->mBuffer, srcLength);
Andreas Huber4c483422009-09-02 16:05:36 -07001428 CODEC_LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
Andreas Huberbe06d262009-08-14 14:37:10 -07001429 timestamp, timestamp / 1E6);
1430 }
1431 }
1432
1433 mOMX->empty_buffer(
1434 mNode, info->mBuffer, 0, srcLength,
1435 flags, timestamp);
1436
1437 info->mOwnedByComponent = true;
1438
1439 if (srcBuffer != NULL) {
1440 srcBuffer->release();
1441 srcBuffer = NULL;
1442 }
1443}
1444
1445void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1446 CHECK_EQ(info->mOwnedByComponent, false);
1447
Andreas Huber404cc412009-08-25 14:26:05 -07001448 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07001449 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07001450 "calling fillOutputBuffer");
1451 return;
1452 }
1453
Andreas Huber4c483422009-09-02 16:05:36 -07001454 CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001455 mOMX->fill_buffer(mNode, info->mBuffer);
1456
1457 info->mOwnedByComponent = true;
1458}
1459
1460void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1461 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1462 for (size_t i = 0; i < buffers->size(); ++i) {
1463 if ((*buffers)[i].mBuffer == buffer) {
1464 drainInputBuffer(&buffers->editItemAt(i));
1465 return;
1466 }
1467 }
1468
1469 CHECK(!"should not be here.");
1470}
1471
1472void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1473 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1474 for (size_t i = 0; i < buffers->size(); ++i) {
1475 if ((*buffers)[i].mBuffer == buffer) {
1476 fillOutputBuffer(&buffers->editItemAt(i));
1477 return;
1478 }
1479 }
1480
1481 CHECK(!"should not be here.");
1482}
1483
1484void OMXCodec::setState(State newState) {
1485 mState = newState;
1486 mAsyncCompletion.signal();
1487
1488 // This may cause some spurious wakeups but is necessary to
1489 // unblock the reader if we enter ERROR state.
1490 mBufferFilled.signal();
1491}
1492
Andreas Huberda050cf22009-09-02 14:01:43 -07001493void OMXCodec::setRawAudioFormat(
1494 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1495 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07001496 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07001497 pcmParams.nPortIndex = portIndex;
1498
1499 status_t err = mOMX->get_parameter(
1500 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1501
1502 CHECK_EQ(err, OK);
1503
1504 pcmParams.nChannels = numChannels;
1505 pcmParams.eNumData = OMX_NumericalDataSigned;
1506 pcmParams.bInterleaved = OMX_TRUE;
1507 pcmParams.nBitPerSample = 16;
1508 pcmParams.nSamplingRate = sampleRate;
1509 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1510
1511 if (numChannels == 1) {
1512 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1513 } else {
1514 CHECK_EQ(numChannels, 2);
1515
1516 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1517 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1518 }
1519
1520 err = mOMX->set_parameter(
1521 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1522
1523 CHECK_EQ(err, OK);
1524}
1525
Andreas Huberbe06d262009-08-14 14:37:10 -07001526void OMXCodec::setAMRFormat() {
1527 if (!mIsEncoder) {
1528 OMX_AUDIO_PARAM_AMRTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001529 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001530 def.nPortIndex = kPortIndexInput;
1531
1532 status_t err =
1533 mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1534
1535 CHECK_EQ(err, OK);
1536
1537 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1538 def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1539
1540 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1541 CHECK_EQ(err, OK);
1542 }
1543
1544 ////////////////////////
1545
1546 if (mIsEncoder) {
1547 sp<MetaData> format = mSource->getFormat();
1548 int32_t sampleRate;
1549 int32_t numChannels;
1550 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1551 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1552
Andreas Huberda050cf22009-09-02 14:01:43 -07001553 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
Andreas Huberbe06d262009-08-14 14:37:10 -07001554 }
1555}
1556
Andreas Huberee606e62009-09-08 10:19:21 -07001557void OMXCodec::setAMRWBFormat() {
1558 if (!mIsEncoder) {
1559 OMX_AUDIO_PARAM_AMRTYPE def;
1560 InitOMXParams(&def);
1561 def.nPortIndex = kPortIndexInput;
1562
1563 status_t err =
1564 mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1565
1566 CHECK_EQ(err, OK);
1567
1568 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1569 def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
1570
1571 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1572 CHECK_EQ(err, OK);
1573 }
1574
1575 ////////////////////////
1576
1577 if (mIsEncoder) {
1578 sp<MetaData> format = mSource->getFormat();
1579 int32_t sampleRate;
1580 int32_t numChannels;
1581 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1582 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1583
1584 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1585 }
1586}
1587
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07001588void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
Andreas Huberda050cf22009-09-02 14:01:43 -07001589 if (mIsEncoder) {
1590 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1591 } else {
1592 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07001593 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07001594 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07001595
Andreas Huberda050cf22009-09-02 14:01:43 -07001596 status_t err = mOMX->get_parameter(
1597 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1598 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001599
Andreas Huberda050cf22009-09-02 14:01:43 -07001600 profile.nChannels = numChannels;
1601 profile.nSampleRate = sampleRate;
1602 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07001603
Andreas Huberda050cf22009-09-02 14:01:43 -07001604 err = mOMX->set_parameter(
1605 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1606 CHECK_EQ(err, OK);
1607 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001608}
1609
1610void OMXCodec::setImageOutputFormat(
1611 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07001612 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001613
1614#if 0
1615 OMX_INDEXTYPE index;
1616 status_t err = mOMX->get_extension_index(
1617 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1618 CHECK_EQ(err, OK);
1619
1620 err = mOMX->set_config(mNode, index, &format, sizeof(format));
1621 CHECK_EQ(err, OK);
1622#endif
1623
1624 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001625 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001626 def.nPortIndex = kPortIndexOutput;
1627
1628 status_t err = mOMX->get_parameter(
1629 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1630 CHECK_EQ(err, OK);
1631
1632 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1633
1634 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001635
Andreas Huberbe06d262009-08-14 14:37:10 -07001636 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1637 imageDef->eColorFormat = format;
1638 imageDef->nFrameWidth = width;
1639 imageDef->nFrameHeight = height;
1640
1641 switch (format) {
1642 case OMX_COLOR_FormatYUV420PackedPlanar:
1643 case OMX_COLOR_FormatYUV411Planar:
1644 {
1645 def.nBufferSize = (width * height * 3) / 2;
1646 break;
1647 }
1648
1649 case OMX_COLOR_FormatCbYCrY:
1650 {
1651 def.nBufferSize = width * height * 2;
1652 break;
1653 }
1654
1655 case OMX_COLOR_Format32bitARGB8888:
1656 {
1657 def.nBufferSize = width * height * 4;
1658 break;
1659 }
1660
1661 default:
1662 CHECK(!"Should not be here. Unknown color format.");
1663 break;
1664 }
1665
Andreas Huber5c0a9132009-08-20 11:16:40 -07001666 def.nBufferCountActual = def.nBufferCountMin;
1667
Andreas Huberbe06d262009-08-14 14:37:10 -07001668 err = mOMX->set_parameter(
1669 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1670 CHECK_EQ(err, OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07001671}
Andreas Huberbe06d262009-08-14 14:37:10 -07001672
Andreas Huber5c0a9132009-08-20 11:16:40 -07001673void OMXCodec::setJPEGInputFormat(
1674 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
1675 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001676 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001677 def.nPortIndex = kPortIndexInput;
1678
Andreas Huber5c0a9132009-08-20 11:16:40 -07001679 status_t err = mOMX->get_parameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001680 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1681 CHECK_EQ(err, OK);
1682
Andreas Huber5c0a9132009-08-20 11:16:40 -07001683 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1684 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1685
Andreas Huberbe06d262009-08-14 14:37:10 -07001686 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1687 imageDef->nFrameWidth = width;
1688 imageDef->nFrameHeight = height;
1689
Andreas Huber5c0a9132009-08-20 11:16:40 -07001690 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07001691 def.nBufferCountActual = def.nBufferCountMin;
1692
1693 err = mOMX->set_parameter(
1694 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1695 CHECK_EQ(err, OK);
1696}
1697
1698void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
1699 CodecSpecificData *specific =
1700 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
1701
1702 specific->mSize = size;
1703 memcpy(specific->mData, data, size);
1704
1705 mCodecSpecificData.push(specific);
1706}
1707
1708void OMXCodec::clearCodecSpecificData() {
1709 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
1710 free(mCodecSpecificData.editItemAt(i));
1711 }
1712 mCodecSpecificData.clear();
1713 mCodecSpecificDataIndex = 0;
1714}
1715
1716status_t OMXCodec::start(MetaData *) {
Andreas Huber42978e52009-08-27 10:08:39 -07001717 Mutex::Autolock autoLock(mLock);
1718
Andreas Huberbe06d262009-08-14 14:37:10 -07001719 if (mState != LOADED) {
1720 return UNKNOWN_ERROR;
1721 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07001722
Andreas Huberbe06d262009-08-14 14:37:10 -07001723 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001724 if (mQuirks & kWantsNALFragments) {
1725 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07001726 }
1727 status_t err = mSource->start(params.get());
1728
1729 if (err != OK) {
1730 return err;
1731 }
1732
1733 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07001734 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001735 mSignalledEOS = false;
1736 mNoMoreOutputData = false;
1737 mSeekTimeUs = -1;
1738 mFilledBuffers.clear();
1739
1740 return init();
1741}
1742
1743status_t OMXCodec::stop() {
Andreas Huber4c483422009-09-02 16:05:36 -07001744 CODEC_LOGV("stop");
Andreas Huberbe06d262009-08-14 14:37:10 -07001745
1746 Mutex::Autolock autoLock(mLock);
1747
1748 while (isIntermediateState(mState)) {
1749 mAsyncCompletion.wait(mLock);
1750 }
1751
1752 switch (mState) {
1753 case LOADED:
1754 case ERROR:
1755 break;
1756
1757 case EXECUTING:
1758 {
1759 setState(EXECUTING_TO_IDLE);
1760
Andreas Huber127fcdc2009-08-26 16:27:02 -07001761 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07001762 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001763 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07001764
Andreas Huber127fcdc2009-08-26 16:27:02 -07001765 bool emulateInputFlushCompletion =
1766 !flushPortAsync(kPortIndexInput);
1767
1768 bool emulateOutputFlushCompletion =
1769 !flushPortAsync(kPortIndexOutput);
1770
1771 if (emulateInputFlushCompletion) {
1772 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1773 }
1774
1775 if (emulateOutputFlushCompletion) {
1776 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1777 }
1778 } else {
1779 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1780 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1781
1782 status_t err =
1783 mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
1784 CHECK_EQ(err, OK);
1785 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001786
1787 while (mState != LOADED && mState != ERROR) {
1788 mAsyncCompletion.wait(mLock);
1789 }
1790
1791 break;
1792 }
1793
1794 default:
1795 {
1796 CHECK(!"should not be here.");
1797 break;
1798 }
1799 }
1800
1801 mSource->stop();
1802
1803 return OK;
1804}
1805
1806sp<MetaData> OMXCodec::getFormat() {
1807 return mOutputFormat;
1808}
1809
1810status_t OMXCodec::read(
1811 MediaBuffer **buffer, const ReadOptions *options) {
1812 *buffer = NULL;
1813
1814 Mutex::Autolock autoLock(mLock);
1815
Andreas Huberd06e5b82009-08-28 13:18:14 -07001816 if (mState != EXECUTING && mState != RECONFIGURING) {
1817 return UNKNOWN_ERROR;
1818 }
1819
Andreas Huber42978e52009-08-27 10:08:39 -07001820 if (mInitialBufferSubmit) {
1821 mInitialBufferSubmit = false;
1822
1823 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07001824
Andreas Huberd06e5b82009-08-28 13:18:14 -07001825 if (mState == EXECUTING) {
1826 // Otherwise mState == RECONFIGURING and this code will trigger
1827 // after the output port is reenabled.
1828 fillOutputBuffers();
1829 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001830 }
1831
1832 int64_t seekTimeUs;
1833 if (options && options->getSeekTo(&seekTimeUs)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001834 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07001835
1836 mSignalledEOS = false;
1837 mNoMoreOutputData = false;
1838
1839 CHECK(seekTimeUs >= 0);
1840 mSeekTimeUs = seekTimeUs;
1841
1842 mFilledBuffers.clear();
1843
1844 CHECK_EQ(mState, EXECUTING);
1845
Andreas Huber404cc412009-08-25 14:26:05 -07001846 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
1847 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
1848
1849 if (emulateInputFlushCompletion) {
1850 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1851 }
1852
1853 if (emulateOutputFlushCompletion) {
1854 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1855 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001856 }
1857
1858 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
1859 mBufferFilled.wait(mLock);
1860 }
1861
1862 if (mState == ERROR) {
1863 return UNKNOWN_ERROR;
1864 }
1865
1866 if (mFilledBuffers.empty()) {
1867 return ERROR_END_OF_STREAM;
1868 }
1869
1870 size_t index = *mFilledBuffers.begin();
1871 mFilledBuffers.erase(mFilledBuffers.begin());
1872
1873 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1874 info->mMediaBuffer->add_ref();
1875 *buffer = info->mMediaBuffer;
1876
1877 return OK;
1878}
1879
1880void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
1881 Mutex::Autolock autoLock(mLock);
1882
1883 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1884 for (size_t i = 0; i < buffers->size(); ++i) {
1885 BufferInfo *info = &buffers->editItemAt(i);
1886
1887 if (info->mMediaBuffer == buffer) {
1888 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1889 fillOutputBuffer(info);
1890 return;
1891 }
1892 }
1893
1894 CHECK(!"should not be here.");
1895}
1896
1897static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
1898 static const char *kNames[] = {
1899 "OMX_IMAGE_CodingUnused",
1900 "OMX_IMAGE_CodingAutoDetect",
1901 "OMX_IMAGE_CodingJPEG",
1902 "OMX_IMAGE_CodingJPEG2K",
1903 "OMX_IMAGE_CodingEXIF",
1904 "OMX_IMAGE_CodingTIFF",
1905 "OMX_IMAGE_CodingGIF",
1906 "OMX_IMAGE_CodingPNG",
1907 "OMX_IMAGE_CodingLZW",
1908 "OMX_IMAGE_CodingBMP",
1909 };
1910
1911 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1912
1913 if (type < 0 || (size_t)type >= numNames) {
1914 return "UNKNOWN";
1915 } else {
1916 return kNames[type];
1917 }
1918}
1919
1920static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
1921 static const char *kNames[] = {
1922 "OMX_COLOR_FormatUnused",
1923 "OMX_COLOR_FormatMonochrome",
1924 "OMX_COLOR_Format8bitRGB332",
1925 "OMX_COLOR_Format12bitRGB444",
1926 "OMX_COLOR_Format16bitARGB4444",
1927 "OMX_COLOR_Format16bitARGB1555",
1928 "OMX_COLOR_Format16bitRGB565",
1929 "OMX_COLOR_Format16bitBGR565",
1930 "OMX_COLOR_Format18bitRGB666",
1931 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07001932 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07001933 "OMX_COLOR_Format24bitRGB888",
1934 "OMX_COLOR_Format24bitBGR888",
1935 "OMX_COLOR_Format24bitARGB1887",
1936 "OMX_COLOR_Format25bitARGB1888",
1937 "OMX_COLOR_Format32bitBGRA8888",
1938 "OMX_COLOR_Format32bitARGB8888",
1939 "OMX_COLOR_FormatYUV411Planar",
1940 "OMX_COLOR_FormatYUV411PackedPlanar",
1941 "OMX_COLOR_FormatYUV420Planar",
1942 "OMX_COLOR_FormatYUV420PackedPlanar",
1943 "OMX_COLOR_FormatYUV420SemiPlanar",
1944 "OMX_COLOR_FormatYUV422Planar",
1945 "OMX_COLOR_FormatYUV422PackedPlanar",
1946 "OMX_COLOR_FormatYUV422SemiPlanar",
1947 "OMX_COLOR_FormatYCbYCr",
1948 "OMX_COLOR_FormatYCrYCb",
1949 "OMX_COLOR_FormatCbYCrY",
1950 "OMX_COLOR_FormatCrYCbY",
1951 "OMX_COLOR_FormatYUV444Interleaved",
1952 "OMX_COLOR_FormatRawBayer8bit",
1953 "OMX_COLOR_FormatRawBayer10bit",
1954 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07001955 "OMX_COLOR_FormatL2",
1956 "OMX_COLOR_FormatL4",
1957 "OMX_COLOR_FormatL8",
1958 "OMX_COLOR_FormatL16",
1959 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07001960 "OMX_COLOR_FormatL32",
1961 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
1962 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
1963 "OMX_COLOR_Format18BitBGR666",
1964 "OMX_COLOR_Format24BitARGB6666",
1965 "OMX_COLOR_Format24BitABGR6666",
1966 };
1967
1968 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1969
1970 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1971
1972 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
1973 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
1974 } else if (type < 0 || (size_t)type >= numNames) {
1975 return "UNKNOWN";
1976 } else {
1977 return kNames[type];
1978 }
1979}
1980
1981static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
1982 static const char *kNames[] = {
1983 "OMX_VIDEO_CodingUnused",
1984 "OMX_VIDEO_CodingAutoDetect",
1985 "OMX_VIDEO_CodingMPEG2",
1986 "OMX_VIDEO_CodingH263",
1987 "OMX_VIDEO_CodingMPEG4",
1988 "OMX_VIDEO_CodingWMV",
1989 "OMX_VIDEO_CodingRV",
1990 "OMX_VIDEO_CodingAVC",
1991 "OMX_VIDEO_CodingMJPEG",
1992 };
1993
1994 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1995
1996 if (type < 0 || (size_t)type >= numNames) {
1997 return "UNKNOWN";
1998 } else {
1999 return kNames[type];
2000 }
2001}
2002
2003static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2004 static const char *kNames[] = {
2005 "OMX_AUDIO_CodingUnused",
2006 "OMX_AUDIO_CodingAutoDetect",
2007 "OMX_AUDIO_CodingPCM",
2008 "OMX_AUDIO_CodingADPCM",
2009 "OMX_AUDIO_CodingAMR",
2010 "OMX_AUDIO_CodingGSMFR",
2011 "OMX_AUDIO_CodingGSMEFR",
2012 "OMX_AUDIO_CodingGSMHR",
2013 "OMX_AUDIO_CodingPDCFR",
2014 "OMX_AUDIO_CodingPDCEFR",
2015 "OMX_AUDIO_CodingPDCHR",
2016 "OMX_AUDIO_CodingTDMAFR",
2017 "OMX_AUDIO_CodingTDMAEFR",
2018 "OMX_AUDIO_CodingQCELP8",
2019 "OMX_AUDIO_CodingQCELP13",
2020 "OMX_AUDIO_CodingEVRC",
2021 "OMX_AUDIO_CodingSMV",
2022 "OMX_AUDIO_CodingG711",
2023 "OMX_AUDIO_CodingG723",
2024 "OMX_AUDIO_CodingG726",
2025 "OMX_AUDIO_CodingG729",
2026 "OMX_AUDIO_CodingAAC",
2027 "OMX_AUDIO_CodingMP3",
2028 "OMX_AUDIO_CodingSBC",
2029 "OMX_AUDIO_CodingVORBIS",
2030 "OMX_AUDIO_CodingWMA",
2031 "OMX_AUDIO_CodingRA",
2032 "OMX_AUDIO_CodingMIDI",
2033 };
2034
2035 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2036
2037 if (type < 0 || (size_t)type >= numNames) {
2038 return "UNKNOWN";
2039 } else {
2040 return kNames[type];
2041 }
2042}
2043
2044static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2045 static const char *kNames[] = {
2046 "OMX_AUDIO_PCMModeLinear",
2047 "OMX_AUDIO_PCMModeALaw",
2048 "OMX_AUDIO_PCMModeMULaw",
2049 };
2050
2051 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2052
2053 if (type < 0 || (size_t)type >= numNames) {
2054 return "UNKNOWN";
2055 } else {
2056 return kNames[type];
2057 }
2058}
2059
2060
2061void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2062 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002063 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002064 def.nPortIndex = portIndex;
2065
2066 status_t err = mOMX->get_parameter(
2067 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2068 CHECK_EQ(err, OK);
2069
2070 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2071
2072 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2073 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
2074
2075 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
2076 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
2077 printf(" nBufferSize = %ld\n", def.nBufferSize);
2078
2079 switch (def.eDomain) {
2080 case OMX_PortDomainImage:
2081 {
2082 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2083
2084 printf("\n");
2085 printf(" // Image\n");
2086 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
2087 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
2088 printf(" nStride = %ld\n", imageDef->nStride);
2089
2090 printf(" eCompressionFormat = %s\n",
2091 imageCompressionFormatString(imageDef->eCompressionFormat));
2092
2093 printf(" eColorFormat = %s\n",
2094 colorFormatString(imageDef->eColorFormat));
2095
2096 break;
2097 }
2098
2099 case OMX_PortDomainVideo:
2100 {
2101 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2102
2103 printf("\n");
2104 printf(" // Video\n");
2105 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
2106 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
2107 printf(" nStride = %ld\n", videoDef->nStride);
2108
2109 printf(" eCompressionFormat = %s\n",
2110 videoCompressionFormatString(videoDef->eCompressionFormat));
2111
2112 printf(" eColorFormat = %s\n",
2113 colorFormatString(videoDef->eColorFormat));
2114
2115 break;
2116 }
2117
2118 case OMX_PortDomainAudio:
2119 {
2120 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2121
2122 printf("\n");
2123 printf(" // Audio\n");
2124 printf(" eEncoding = %s\n",
2125 audioCodingTypeString(audioDef->eEncoding));
2126
2127 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2128 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07002129 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07002130 params.nPortIndex = portIndex;
2131
2132 err = mOMX->get_parameter(
2133 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2134 CHECK_EQ(err, OK);
2135
2136 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
2137 printf(" nChannels = %ld\n", params.nChannels);
2138 printf(" bInterleaved = %d\n", params.bInterleaved);
2139 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
2140
2141 printf(" eNumData = %s\n",
2142 params.eNumData == OMX_NumericalDataSigned
2143 ? "signed" : "unsigned");
2144
2145 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
2146 }
2147
2148 break;
2149 }
2150
2151 default:
2152 {
2153 printf(" // Unknown\n");
2154 break;
2155 }
2156 }
2157
2158 printf("}\n");
2159}
2160
2161void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
2162 mOutputFormat = new MetaData;
2163 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
2164
2165 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002166 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002167 def.nPortIndex = kPortIndexOutput;
2168
2169 status_t err = mOMX->get_parameter(
2170 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2171 CHECK_EQ(err, OK);
2172
2173 switch (def.eDomain) {
2174 case OMX_PortDomainImage:
2175 {
2176 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2177 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2178
2179 mOutputFormat->setCString(kKeyMIMEType, "image/raw");
2180 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
2181 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
2182 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
2183 break;
2184 }
2185
2186 case OMX_PortDomainAudio:
2187 {
2188 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
2189
Andreas Huberda050cf22009-09-02 14:01:43 -07002190 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
2191 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07002192 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07002193 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002194
Andreas Huberda050cf22009-09-02 14:01:43 -07002195 err = mOMX->get_parameter(
2196 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2197 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002198
Andreas Huberda050cf22009-09-02 14:01:43 -07002199 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
2200 CHECK_EQ(params.nBitPerSample, 16);
2201 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07002202
Andreas Huberda050cf22009-09-02 14:01:43 -07002203 int32_t numChannels, sampleRate;
2204 inputFormat->findInt32(kKeyChannelCount, &numChannels);
2205 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07002206
Andreas Huberda050cf22009-09-02 14:01:43 -07002207 if ((OMX_U32)numChannels != params.nChannels) {
2208 LOGW("Codec outputs a different number of channels than "
2209 "the input stream contains.");
2210 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002211
Andreas Huberda050cf22009-09-02 14:01:43 -07002212 mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
2213
2214 // Use the codec-advertised number of channels, as some
2215 // codecs appear to output stereo even if the input data is
2216 // mono.
2217 mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
2218
2219 // The codec-reported sampleRate is not reliable...
2220 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
2221 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
2222 mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
2223 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
2224 mOutputFormat->setCString(kKeyMIMEType, "audio/mp4a-latm");
2225 } else {
2226 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07002227 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002228 break;
2229 }
2230
2231 case OMX_PortDomainVideo:
2232 {
2233 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2234
2235 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
2236 mOutputFormat->setCString(kKeyMIMEType, "video/raw");
2237 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
2238 mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es");
2239 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
2240 mOutputFormat->setCString(kKeyMIMEType, "video/3gpp");
2241 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
2242 mOutputFormat->setCString(kKeyMIMEType, "video/avc");
2243 } else {
2244 CHECK(!"Unknown compression format.");
2245 }
2246
2247 if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
2248 // This component appears to be lying to me.
2249 mOutputFormat->setInt32(
2250 kKeyWidth, (video_def->nFrameWidth + 15) & -16);
2251 mOutputFormat->setInt32(
2252 kKeyHeight, (video_def->nFrameHeight + 15) & -16);
2253 } else {
2254 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
2255 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
2256 }
2257
2258 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
2259 break;
2260 }
2261
2262 default:
2263 {
2264 CHECK(!"should not be here, neither audio nor video.");
2265 break;
2266 }
2267 }
2268}
2269
2270} // namespace android