blob: d692820c16c916142868655eb8f4879a781f7acd [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
Andreas Huberbd7b43b2009-10-13 10:22:55 -070021#include "include/ESDS.h"
22
Andreas Huberbe06d262009-08-14 14:37:10 -070023#include <binder/IServiceManager.h>
24#include <binder/MemoryDealer.h>
25#include <binder/ProcessState.h>
26#include <media/IMediaPlayerService.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070027#include <media/stagefright/MediaBuffer.h>
28#include <media/stagefright/MediaBufferGroup.h>
29#include <media/stagefright/MediaDebug.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070030#include <media/stagefright/MediaDefs.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070031#include <media/stagefright/MediaExtractor.h>
32#include <media/stagefright/MetaData.h>
33#include <media/stagefright/MmapSource.h>
34#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070035#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070036#include <utils/Vector.h>
37
38#include <OMX_Audio.h>
39#include <OMX_Component.h>
40
41namespace android {
42
Andreas Huber8b432b12009-10-07 13:36:52 -070043static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
44
Andreas Huberbe06d262009-08-14 14:37:10 -070045struct CodecInfo {
46 const char *mime;
47 const char *codec;
48};
49
50static const CodecInfo kDecoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -070051 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
52 { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
53 { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
54 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
55 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
56 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
57 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" },
58 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
59 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
60 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
61 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
62 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
63 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
64 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.Decoder" },
65 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
66 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
67 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
68 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
Andreas Huberbe06d262009-08-14 14:37:10 -070069};
70
71static const CodecInfo kEncoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -070072 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
73 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrencnb" },
74 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
75 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
76 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
77 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
78 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
79 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
80 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
81 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
82 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
83 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
84 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
Andreas Huberbe06d262009-08-14 14:37:10 -070085};
86
Andreas Hubere0873732009-09-10 09:57:53 -070087#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -070088#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
89
Andreas Huberbe06d262009-08-14 14:37:10 -070090struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -070091 OMXCodecObserver() {
92 }
93
94 void setCodec(const sp<OMXCodec> &target) {
95 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -070096 }
97
98 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -070099 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700100 sp<OMXCodec> codec = mTarget.promote();
101
102 if (codec.get() != NULL) {
103 codec->on_message(msg);
104 }
105 }
106
107protected:
108 virtual ~OMXCodecObserver() {}
109
110private:
111 wp<OMXCodec> mTarget;
112
113 OMXCodecObserver(const OMXCodecObserver &);
114 OMXCodecObserver &operator=(const OMXCodecObserver &);
115};
116
117static const char *GetCodec(const CodecInfo *info, size_t numInfos,
118 const char *mime, int index) {
119 CHECK(index >= 0);
120 for(size_t i = 0; i < numInfos; ++i) {
121 if (!strcasecmp(mime, info[i].mime)) {
122 if (index == 0) {
123 return info[i].codec;
124 }
125
126 --index;
127 }
128 }
129
130 return NULL;
131}
132
Andreas Huberebf66ea2009-08-19 13:32:58 -0700133enum {
134 kAVCProfileBaseline = 0x42,
135 kAVCProfileMain = 0x4d,
136 kAVCProfileExtended = 0x58,
137 kAVCProfileHigh = 0x64,
138 kAVCProfileHigh10 = 0x6e,
139 kAVCProfileHigh422 = 0x7a,
140 kAVCProfileHigh444 = 0xf4,
141 kAVCProfileCAVLC444Intra = 0x2c
142};
143
144static const char *AVCProfileToString(uint8_t profile) {
145 switch (profile) {
146 case kAVCProfileBaseline:
147 return "Baseline";
148 case kAVCProfileMain:
149 return "Main";
150 case kAVCProfileExtended:
151 return "Extended";
152 case kAVCProfileHigh:
153 return "High";
154 case kAVCProfileHigh10:
155 return "High 10";
156 case kAVCProfileHigh422:
157 return "High 422";
158 case kAVCProfileHigh444:
159 return "High 444";
160 case kAVCProfileCAVLC444Intra:
161 return "CAVLC 444 Intra";
162 default: return "Unknown";
163 }
164}
165
Andreas Huber4c483422009-09-02 16:05:36 -0700166template<class T>
167static void InitOMXParams(T *params) {
168 params->nSize = sizeof(T);
169 params->nVersion.s.nVersionMajor = 1;
170 params->nVersion.s.nVersionMinor = 0;
171 params->nVersion.s.nRevision = 0;
172 params->nVersion.s.nStep = 0;
173}
174
Andreas Huberbe06d262009-08-14 14:37:10 -0700175// static
176sp<OMXCodec> OMXCodec::Create(
177 const sp<IOMX> &omx,
178 const sp<MetaData> &meta, bool createEncoder,
Andreas Hubere6c40962009-09-10 14:13:30 -0700179 const sp<MediaSource> &source,
180 const char *matchComponentName) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700181 const char *mime;
182 bool success = meta->findCString(kKeyMIMEType, &mime);
183 CHECK(success);
184
185 const char *componentName = NULL;
Andreas Huber784202e2009-10-15 13:46:54 -0700186 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Huberbe06d262009-08-14 14:37:10 -0700187 IOMX::node_id node = 0;
188 for (int index = 0;; ++index) {
189 if (createEncoder) {
190 componentName = GetCodec(
191 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
192 mime, index);
193 } else {
194 componentName = GetCodec(
195 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
196 mime, index);
197 }
198
199 if (!componentName) {
200 return NULL;
201 }
202
Andreas Hubere6c40962009-09-10 14:13:30 -0700203 // If a specific codec is requested, skip the non-matching ones.
204 if (matchComponentName && strcmp(componentName, matchComponentName)) {
205 continue;
206 }
207
Andreas Huberbe06d262009-08-14 14:37:10 -0700208 LOGV("Attempting to allocate OMX node '%s'", componentName);
209
Andreas Huber784202e2009-10-15 13:46:54 -0700210 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Huberbe06d262009-08-14 14:37:10 -0700211 if (err == OK) {
Andreas Huber53a76bd2009-10-06 16:20:44 -0700212 LOGV("Successfully allocated OMX node '%s'", componentName);
Andreas Huberbe06d262009-08-14 14:37:10 -0700213 break;
214 }
215 }
216
217 uint32_t quirks = 0;
218 if (!strcmp(componentName, "OMX.PV.avcdec")) {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700219 quirks |= kWantsNALFragments;
Andreas Huberbe06d262009-08-14 14:37:10 -0700220 }
221 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
222 quirks |= kNeedsFlushBeforeDisable;
223 }
224 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
225 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700226 quirks |= kRequiresFlushCompleteEmulation;
Andreas Huberbe06d262009-08-14 14:37:10 -0700227 }
228 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
229 quirks |= kRequiresLoadedToIdleAfterAllocation;
230 quirks |= kRequiresAllocateBufferOnInputPorts;
231 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700232 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
233 // XXX Required on P....on only.
Andreas Huber0446b822009-09-15 15:50:31 -0700234 quirks |= kRequiresAllocateBufferOnInputPorts;
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700235 quirks |= kRequiresAllocateBufferOnOutputPorts;
236 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700237
Andreas Huber2dc64d82009-09-11 12:58:53 -0700238 if (!strncmp(componentName, "OMX.TI.", 7)) {
239 // Apparently I must not use OMX_UseBuffer on either input or
240 // output ports on any of the TI components or quote:
241 // "(I) may have unexpected problem (sic) which can be timing related
242 // and hard to reproduce."
243
244 quirks |= kRequiresAllocateBufferOnInputPorts;
245 quirks |= kRequiresAllocateBufferOnOutputPorts;
246 }
247
Andreas Huberbe06d262009-08-14 14:37:10 -0700248 sp<OMXCodec> codec = new OMXCodec(
249 omx, node, quirks, createEncoder, mime, componentName,
250 source);
251
Andreas Huber784202e2009-10-15 13:46:54 -0700252 observer->setCodec(codec);
253
Andreas Huberbe06d262009-08-14 14:37:10 -0700254 uint32_t type;
255 const void *data;
256 size_t size;
257 if (meta->findData(kKeyESDS, &type, &data, &size)) {
258 ESDS esds((const char *)data, size);
259 CHECK_EQ(esds.InitCheck(), OK);
260
261 const void *codec_specific_data;
262 size_t codec_specific_data_size;
263 esds.getCodecSpecificInfo(
264 &codec_specific_data, &codec_specific_data_size);
265
266 printf("found codec-specific data of size %d\n",
267 codec_specific_data_size);
268
269 codec->addCodecSpecificData(
270 codec_specific_data, codec_specific_data_size);
271 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
272 printf("found avcc of size %d\n", size);
273
Andreas Huberebf66ea2009-08-19 13:32:58 -0700274 // Parse the AVCDecoderConfigurationRecord
275
276 const uint8_t *ptr = (const uint8_t *)data;
277
278 CHECK(size >= 7);
279 CHECK_EQ(ptr[0], 1); // configurationVersion == 1
280 uint8_t profile = ptr[1];
281 uint8_t level = ptr[3];
282
283 CHECK((ptr[4] >> 2) == 0x3f); // reserved
284
285 size_t lengthSize = 1 + (ptr[4] & 3);
286
287 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
288 // violates it...
289 // CHECK((ptr[5] >> 5) == 7); // reserved
290
291 size_t numSeqParameterSets = ptr[5] & 31;
292
293 ptr += 6;
Andreas Huberbe06d262009-08-14 14:37:10 -0700294 size -= 6;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700295
296 for (size_t i = 0; i < numSeqParameterSets; ++i) {
297 CHECK(size >= 2);
298 size_t length = U16_AT(ptr);
Andreas Huberbe06d262009-08-14 14:37:10 -0700299
300 ptr += 2;
301 size -= 2;
302
Andreas Huberbe06d262009-08-14 14:37:10 -0700303 CHECK(size >= length);
304
305 codec->addCodecSpecificData(ptr, length);
306
307 ptr += length;
308 size -= length;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700309 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700310
Andreas Huberebf66ea2009-08-19 13:32:58 -0700311 CHECK(size >= 1);
312 size_t numPictureParameterSets = *ptr;
313 ++ptr;
314 --size;
Andreas Huberbe06d262009-08-14 14:37:10 -0700315
Andreas Huberebf66ea2009-08-19 13:32:58 -0700316 for (size_t i = 0; i < numPictureParameterSets; ++i) {
317 CHECK(size >= 2);
318 size_t length = U16_AT(ptr);
319
320 ptr += 2;
321 size -= 2;
322
323 CHECK(size >= length);
324
325 codec->addCodecSpecificData(ptr, length);
326
327 ptr += length;
328 size -= length;
329 }
330
Andreas Huber53a76bd2009-10-06 16:20:44 -0700331 LOGV("AVC profile = %d (%s), level = %d",
Andreas Huberebf66ea2009-08-19 13:32:58 -0700332 (int)profile, AVCProfileToString(profile), (int)level / 10);
333
334 if (!strcmp(componentName, "OMX.TI.Video.Decoder")
335 && (profile != kAVCProfileBaseline || level > 39)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700336 // This stream exceeds the decoder's capabilities. The decoder
337 // does not handle this gracefully and would clobber the heap
338 // and wreak havoc instead...
Andreas Huberebf66ea2009-08-19 13:32:58 -0700339
340 LOGE("Profile and/or level exceed the decoder's capabilities.");
341 return NULL;
Andreas Huberbe06d262009-08-14 14:37:10 -0700342 }
343 }
344
Andreas Hubere6c40962009-09-10 14:13:30 -0700345 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700346 codec->setAMRFormat();
347 }
Andreas Hubere6c40962009-09-10 14:13:30 -0700348 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
Andreas Huberee606e62009-09-08 10:19:21 -0700349 codec->setAMRWBFormat();
350 }
Andreas Hubere6c40962009-09-10 14:13:30 -0700351 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700352 int32_t numChannels, sampleRate;
353 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
354 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
355
356 codec->setAACFormat(numChannels, sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700357 }
358 if (!strncasecmp(mime, "video/", 6)) {
359 int32_t width, height;
360 bool success = meta->findInt32(kKeyWidth, &width);
361 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700362 CHECK(success);
Andreas Huberbe06d262009-08-14 14:37:10 -0700363
364 if (createEncoder) {
365 codec->setVideoInputFormat(mime, width, height);
366 } else {
367 codec->setVideoOutputFormat(mime, width, height);
368 }
369 }
Andreas Hubere6c40962009-09-10 14:13:30 -0700370 if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_JPEG)
Andreas Huberbe06d262009-08-14 14:37:10 -0700371 && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
372 OMX_COLOR_FORMATTYPE format =
373 OMX_COLOR_Format32bitARGB8888;
374 // OMX_COLOR_FormatYUV420PackedPlanar;
375 // OMX_COLOR_FormatCbYCrY;
376 // OMX_COLOR_FormatYUV411Planar;
377
378 int32_t width, height;
379 bool success = meta->findInt32(kKeyWidth, &width);
380 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700381
382 int32_t compressedSize;
383 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700384 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700385
386 CHECK(success);
387 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700388
389 codec->setImageOutputFormat(format, width, height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700390 codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700391 }
392
Andreas Huberda050cf22009-09-02 14:01:43 -0700393 int32_t maxInputSize;
394 if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
395 codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
396 }
397
398 if (!strcmp(componentName, "OMX.TI.AMR.encode")
399 || !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
400 codec->setMinBufferSize(kPortIndexOutput, 8192); // XXX
401 }
402
Andreas Huberbe06d262009-08-14 14:37:10 -0700403 codec->initOutputFormat(meta);
404
405 return codec;
406}
407
Andreas Huberda050cf22009-09-02 14:01:43 -0700408void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
409 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700410 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700411 def.nPortIndex = portIndex;
412
Andreas Huber784202e2009-10-15 13:46:54 -0700413 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700414 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
415 CHECK_EQ(err, OK);
416
417 if (def.nBufferSize < size) {
418 def.nBufferSize = size;
419
420 }
421
Andreas Huber784202e2009-10-15 13:46:54 -0700422 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700423 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
424 CHECK_EQ(err, OK);
425}
426
Andreas Huberbe06d262009-08-14 14:37:10 -0700427status_t OMXCodec::setVideoPortFormatType(
428 OMX_U32 portIndex,
429 OMX_VIDEO_CODINGTYPE compressionFormat,
430 OMX_COLOR_FORMATTYPE colorFormat) {
431 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700432 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700433 format.nPortIndex = portIndex;
434 format.nIndex = 0;
435 bool found = false;
436
437 OMX_U32 index = 0;
438 for (;;) {
439 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700440 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700441 mNode, OMX_IndexParamVideoPortFormat,
442 &format, sizeof(format));
443
444 if (err != OK) {
445 return err;
446 }
447
448 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700449 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700450
451#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700452 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700453 portIndex,
454 index, format.eCompressionFormat, format.eColorFormat);
455#endif
456
457 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
458 if (portIndex == kPortIndexInput
459 && colorFormat == format.eColorFormat) {
460 // eCompressionFormat does not seem right.
461 found = true;
462 break;
463 }
464 if (portIndex == kPortIndexOutput
465 && compressionFormat == format.eCompressionFormat) {
466 // eColorFormat does not seem right.
467 found = true;
468 break;
469 }
470 }
471
472 if (format.eCompressionFormat == compressionFormat
473 && format.eColorFormat == colorFormat) {
474 found = true;
475 break;
476 }
477
478 ++index;
479 }
480
481 if (!found) {
482 return UNKNOWN_ERROR;
483 }
484
Andreas Huber53a76bd2009-10-06 16:20:44 -0700485 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700486 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700487 mNode, OMX_IndexParamVideoPortFormat,
488 &format, sizeof(format));
489
490 return err;
491}
492
493void OMXCodec::setVideoInputFormat(
494 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -0700495 CODEC_LOGV("setVideoInputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -0700496
497 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700498 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700499 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700500 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700501 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700502 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700503 compressionFormat = OMX_VIDEO_CodingH263;
504 } else {
505 LOGE("Not a supported video mime type: %s", mime);
506 CHECK(!"Should not be here. Not a supported video mime type.");
507 }
508
509 OMX_COLOR_FORMATTYPE colorFormat =
510 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
511
512 if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
513 colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
514 }
515
516 setVideoPortFormatType(
517 kPortIndexInput, OMX_VIDEO_CodingUnused,
518 colorFormat);
519
520 setVideoPortFormatType(
521 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
522
523 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700524 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700525 def.nPortIndex = kPortIndexOutput;
526
Andreas Huber4c483422009-09-02 16:05:36 -0700527 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
528
Andreas Huber784202e2009-10-15 13:46:54 -0700529 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700530 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
531
532 CHECK_EQ(err, OK);
533 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
534
535 video_def->nFrameWidth = width;
536 video_def->nFrameHeight = height;
537
538 video_def->eCompressionFormat = compressionFormat;
539 video_def->eColorFormat = OMX_COLOR_FormatUnused;
540
Andreas Huber784202e2009-10-15 13:46:54 -0700541 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700542 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
543 CHECK_EQ(err, OK);
544
545 ////////////////////////////////////////////////////////////////////////////
546
Andreas Huber4c483422009-09-02 16:05:36 -0700547 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700548 def.nPortIndex = kPortIndexInput;
549
Andreas Huber784202e2009-10-15 13:46:54 -0700550 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700551 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
552 CHECK_EQ(err, OK);
553
554 def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
Andreas Huber53a76bd2009-10-06 16:20:44 -0700555 CODEC_LOGV("Setting nBufferSize = %ld", def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700556
557 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
558
559 video_def->nFrameWidth = width;
560 video_def->nFrameHeight = height;
561 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
562 video_def->eColorFormat = colorFormat;
563
Andreas Huber784202e2009-10-15 13:46:54 -0700564 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700565 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
566 CHECK_EQ(err, OK);
567}
568
569void OMXCodec::setVideoOutputFormat(
570 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -0700571 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -0700572
Andreas Huberbe06d262009-08-14 14:37:10 -0700573 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700574 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700575 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700576 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700577 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700578 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700579 compressionFormat = OMX_VIDEO_CodingH263;
580 } else {
581 LOGE("Not a supported video mime type: %s", mime);
582 CHECK(!"Should not be here. Not a supported video mime type.");
583 }
584
585 setVideoPortFormatType(
586 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
587
588#if 1
589 {
590 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700591 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700592 format.nPortIndex = kPortIndexOutput;
593 format.nIndex = 0;
594
Andreas Huber784202e2009-10-15 13:46:54 -0700595 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700596 mNode, OMX_IndexParamVideoPortFormat,
597 &format, sizeof(format));
598 CHECK_EQ(err, OK);
599 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
600
601 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
602
603 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
604 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
605 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
606 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
607
Andreas Huber784202e2009-10-15 13:46:54 -0700608 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700609 mNode, OMX_IndexParamVideoPortFormat,
610 &format, sizeof(format));
611 CHECK_EQ(err, OK);
612 }
613#endif
614
615 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700616 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700617 def.nPortIndex = kPortIndexInput;
618
Andreas Huber4c483422009-09-02 16:05:36 -0700619 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
620
Andreas Huber784202e2009-10-15 13:46:54 -0700621 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700622 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
623
624 CHECK_EQ(err, OK);
625
626#if 1
627 // XXX Need a (much) better heuristic to compute input buffer sizes.
628 const size_t X = 64 * 1024;
629 if (def.nBufferSize < X) {
630 def.nBufferSize = X;
631 }
632#endif
633
634 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
635
636 video_def->nFrameWidth = width;
637 video_def->nFrameHeight = height;
638
639 video_def->eColorFormat = OMX_COLOR_FormatUnused;
640
Andreas Huber784202e2009-10-15 13:46:54 -0700641 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700642 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
643 CHECK_EQ(err, OK);
644
645 ////////////////////////////////////////////////////////////////////////////
646
Andreas Huber4c483422009-09-02 16:05:36 -0700647 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700648 def.nPortIndex = kPortIndexOutput;
649
Andreas Huber784202e2009-10-15 13:46:54 -0700650 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700651 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
652 CHECK_EQ(err, OK);
653 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
654
655#if 0
656 def.nBufferSize =
657 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
658#endif
659
660 video_def->nFrameWidth = width;
661 video_def->nFrameHeight = height;
662
Andreas Huber784202e2009-10-15 13:46:54 -0700663 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700664 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
665 CHECK_EQ(err, OK);
666}
667
668
669OMXCodec::OMXCodec(
670 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
Andreas Huberebf66ea2009-08-19 13:32:58 -0700671 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -0700672 const char *mime,
673 const char *componentName,
674 const sp<MediaSource> &source)
675 : mOMX(omx),
676 mNode(node),
677 mQuirks(quirks),
678 mIsEncoder(isEncoder),
679 mMIME(strdup(mime)),
680 mComponentName(strdup(componentName)),
681 mSource(source),
682 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -0700683 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -0700684 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -0700685 mSignalledEOS(false),
686 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -0700687 mOutputPortSettingsHaveChanged(false),
Andreas Huberbe06d262009-08-14 14:37:10 -0700688 mSeekTimeUs(-1) {
689 mPortStatus[kPortIndexInput] = ENABLED;
690 mPortStatus[kPortIndexOutput] = ENABLED;
691
Andreas Huber4c483422009-09-02 16:05:36 -0700692 setComponentRole();
693}
694
Andreas Hubere6c40962009-09-10 14:13:30 -0700695// static
696void OMXCodec::setComponentRole(
697 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
698 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -0700699 struct MimeToRole {
700 const char *mime;
701 const char *decoderRole;
702 const char *encoderRole;
703 };
704
705 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700706 { MEDIA_MIMETYPE_AUDIO_MPEG,
707 "audio_decoder.mp3", "audio_encoder.mp3" },
708 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
709 "audio_decoder.amrnb", "audio_encoder.amrnb" },
710 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
711 "audio_decoder.amrwb", "audio_encoder.amrwb" },
712 { MEDIA_MIMETYPE_AUDIO_AAC,
713 "audio_decoder.aac", "audio_encoder.aac" },
714 { MEDIA_MIMETYPE_VIDEO_AVC,
715 "video_decoder.avc", "video_encoder.avc" },
716 { MEDIA_MIMETYPE_VIDEO_MPEG4,
717 "video_decoder.mpeg4", "video_encoder.mpeg4" },
718 { MEDIA_MIMETYPE_VIDEO_H263,
719 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber4c483422009-09-02 16:05:36 -0700720 };
721
722 static const size_t kNumMimeToRole =
723 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
724
725 size_t i;
726 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -0700727 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -0700728 break;
729 }
730 }
731
732 if (i == kNumMimeToRole) {
733 return;
734 }
735
736 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -0700737 isEncoder ? kMimeToRole[i].encoderRole
738 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -0700739
740 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -0700741 OMX_PARAM_COMPONENTROLETYPE roleParams;
742 InitOMXParams(&roleParams);
743
744 strncpy((char *)roleParams.cRole,
745 role, OMX_MAX_STRINGNAME_SIZE - 1);
746
747 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
748
Andreas Huber784202e2009-10-15 13:46:54 -0700749 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -0700750 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -0700751 &roleParams, sizeof(roleParams));
752
753 if (err != OK) {
754 LOGW("Failed to set standard component role '%s'.", role);
755 }
756 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700757}
758
Andreas Hubere6c40962009-09-10 14:13:30 -0700759void OMXCodec::setComponentRole() {
760 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
761}
762
Andreas Huberbe06d262009-08-14 14:37:10 -0700763OMXCodec::~OMXCodec() {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700764 CHECK(mState == LOADED || mState == ERROR);
Andreas Huberbe06d262009-08-14 14:37:10 -0700765
Andreas Huber784202e2009-10-15 13:46:54 -0700766 status_t err = mOMX->freeNode(mNode);
Andreas Huberbe06d262009-08-14 14:37:10 -0700767 CHECK_EQ(err, OK);
768
769 mNode = NULL;
770 setState(DEAD);
771
772 clearCodecSpecificData();
773
774 free(mComponentName);
775 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700776
Andreas Huberbe06d262009-08-14 14:37:10 -0700777 free(mMIME);
778 mMIME = NULL;
779}
780
781status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -0700782 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -0700783
784 CHECK_EQ(mState, LOADED);
785
786 status_t err;
787 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700788 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -0700789 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700790 setState(LOADED_TO_IDLE);
791 }
792
793 err = allocateBuffers();
794 CHECK_EQ(err, OK);
795
796 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -0700797 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -0700798 CHECK_EQ(err, OK);
799
800 setState(LOADED_TO_IDLE);
801 }
802
803 while (mState != EXECUTING && mState != ERROR) {
804 mAsyncCompletion.wait(mLock);
805 }
806
807 return mState == ERROR ? UNKNOWN_ERROR : OK;
808}
809
810// static
811bool OMXCodec::isIntermediateState(State state) {
812 return state == LOADED_TO_IDLE
813 || state == IDLE_TO_EXECUTING
814 || state == EXECUTING_TO_IDLE
815 || state == IDLE_TO_LOADED
816 || state == RECONFIGURING;
817}
818
819status_t OMXCodec::allocateBuffers() {
820 status_t err = allocateBuffersOnPort(kPortIndexInput);
821
822 if (err != OK) {
823 return err;
824 }
825
826 return allocateBuffersOnPort(kPortIndexOutput);
827}
828
829status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
830 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700831 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700832 def.nPortIndex = portIndex;
833
Andreas Huber784202e2009-10-15 13:46:54 -0700834 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700835 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
836
837 if (err != OK) {
838 return err;
839 }
840
Andreas Huber5c0a9132009-08-20 11:16:40 -0700841 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
842 mDealer[portIndex] = new MemoryDealer(totalSize);
843
Andreas Huberbe06d262009-08-14 14:37:10 -0700844 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -0700845 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700846 CHECK(mem.get() != NULL);
847
848 IOMX::buffer_id buffer;
849 if (portIndex == kPortIndexInput
850 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700851 err = mOMX->allocateBufferWithBackup(
Andreas Huberbe06d262009-08-14 14:37:10 -0700852 mNode, portIndex, mem, &buffer);
Andreas Huber446f44f2009-08-25 17:23:44 -0700853 } else if (portIndex == kPortIndexOutput
854 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700855 err = mOMX->allocateBufferWithBackup(
Andreas Huber2dc64d82009-09-11 12:58:53 -0700856 mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700857 } else {
Andreas Huber784202e2009-10-15 13:46:54 -0700858 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700859 }
860
861 if (err != OK) {
862 LOGE("allocate_buffer_with_backup failed");
863 return err;
864 }
865
866 BufferInfo info;
867 info.mBuffer = buffer;
868 info.mOwnedByComponent = false;
869 info.mMem = mem;
870 info.mMediaBuffer = NULL;
871
872 if (portIndex == kPortIndexOutput) {
873 info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
874 info.mMediaBuffer->setObserver(this);
875 }
876
877 mPortBuffers[portIndex].push(info);
878
Andreas Huber4c483422009-09-02 16:05:36 -0700879 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -0700880 portIndex == kPortIndexInput ? "input" : "output");
881 }
882
883 dumpPortStatus(portIndex);
884
885 return OK;
886}
887
888void OMXCodec::on_message(const omx_message &msg) {
889 Mutex::Autolock autoLock(mLock);
890
891 switch (msg.type) {
892 case omx_message::EVENT:
893 {
894 onEvent(
895 msg.u.event_data.event, msg.u.event_data.data1,
896 msg.u.event_data.data2);
897
898 break;
899 }
900
901 case omx_message::EMPTY_BUFFER_DONE:
902 {
903 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
904
Andreas Huber4c483422009-09-02 16:05:36 -0700905 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700906
907 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
908 size_t i = 0;
909 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
910 ++i;
911 }
912
913 CHECK(i < buffers->size());
914 if (!(*buffers)[i].mOwnedByComponent) {
915 LOGW("We already own input buffer %p, yet received "
916 "an EMPTY_BUFFER_DONE.", buffer);
917 }
918
919 buffers->editItemAt(i).mOwnedByComponent = false;
920
921 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -0700922 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700923
924 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -0700925 mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700926 CHECK_EQ(err, OK);
927
928 buffers->removeAt(i);
929 } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
930 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
931 drainInputBuffer(&buffers->editItemAt(i));
932 }
933
934 break;
935 }
936
937 case omx_message::FILL_BUFFER_DONE:
938 {
939 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
940 OMX_U32 flags = msg.u.extended_buffer_data.flags;
941
Andreas Huber4c483422009-09-02 16:05:36 -0700942 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
Andreas Huberbe06d262009-08-14 14:37:10 -0700943 buffer,
944 msg.u.extended_buffer_data.range_length,
945 flags);
946
Andreas Huber4c483422009-09-02 16:05:36 -0700947 CODEC_LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -0700948 msg.u.extended_buffer_data.timestamp,
949 msg.u.extended_buffer_data.timestamp / 1E6);
950
951 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
952 size_t i = 0;
953 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
954 ++i;
955 }
956
957 CHECK(i < buffers->size());
958 BufferInfo *info = &buffers->editItemAt(i);
959
960 if (!info->mOwnedByComponent) {
961 LOGW("We already own output buffer %p, yet received "
962 "a FILL_BUFFER_DONE.", buffer);
963 }
964
965 info->mOwnedByComponent = false;
966
967 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -0700968 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700969
970 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -0700971 mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -0700972 CHECK_EQ(err, OK);
973
974 buffers->removeAt(i);
Andreas Huberd7795892009-08-26 10:33:47 -0700975 } else if (mPortStatus[kPortIndexOutput] == ENABLED
976 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -0700977 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -0700978 mNoMoreOutputData = true;
979 mBufferFilled.signal();
980 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
981 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700982
Andreas Huberbe06d262009-08-14 14:37:10 -0700983 MediaBuffer *buffer = info->mMediaBuffer;
984
985 buffer->set_range(
986 msg.u.extended_buffer_data.range_offset,
987 msg.u.extended_buffer_data.range_length);
988
989 buffer->meta_data()->clear();
990
Andreas Huberfa8de752009-10-08 10:07:49 -0700991 buffer->meta_data()->setInt64(
992 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -0700993
994 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
995 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
996 }
997
998 buffer->meta_data()->setPointer(
999 kKeyPlatformPrivate,
1000 msg.u.extended_buffer_data.platform_private);
1001
1002 buffer->meta_data()->setPointer(
1003 kKeyBufferID,
1004 msg.u.extended_buffer_data.buffer);
1005
1006 mFilledBuffers.push_back(i);
1007 mBufferFilled.signal();
1008 }
1009
1010 break;
1011 }
1012
1013 default:
1014 {
1015 CHECK(!"should not be here.");
1016 break;
1017 }
1018 }
1019}
1020
1021void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1022 switch (event) {
1023 case OMX_EventCmdComplete:
1024 {
1025 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1026 break;
1027 }
1028
1029 case OMX_EventError:
1030 {
1031 LOGE("ERROR(%ld, %ld)", data1, data2);
1032
1033 setState(ERROR);
1034 break;
1035 }
1036
1037 case OMX_EventPortSettingsChanged:
1038 {
1039 onPortSettingsChanged(data1);
1040 break;
1041 }
1042
1043 case OMX_EventBufferFlag:
1044 {
Andreas Huber4c483422009-09-02 16:05:36 -07001045 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
Andreas Huberbe06d262009-08-14 14:37:10 -07001046
1047 if (data1 == kPortIndexOutput) {
1048 mNoMoreOutputData = true;
1049 }
1050 break;
1051 }
1052
1053 default:
1054 {
Andreas Huber4c483422009-09-02 16:05:36 -07001055 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001056 break;
1057 }
1058 }
1059}
1060
Andreas Huberb1678602009-10-19 13:06:40 -07001061// Has the format changed in any way that the client would have to be aware of?
1062static bool formatHasNotablyChanged(
1063 const sp<MetaData> &from, const sp<MetaData> &to) {
1064 if (from.get() == NULL && to.get() == NULL) {
1065 return false;
1066 }
1067
Andreas Huberf68c1682009-10-21 14:01:30 -07001068 if ((from.get() == NULL && to.get() != NULL)
1069 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07001070 return true;
1071 }
1072
1073 const char *mime_from, *mime_to;
1074 CHECK(from->findCString(kKeyMIMEType, &mime_from));
1075 CHECK(to->findCString(kKeyMIMEType, &mime_to));
1076
1077 if (strcasecmp(mime_from, mime_to)) {
1078 return true;
1079 }
1080
1081 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
1082 int32_t colorFormat_from, colorFormat_to;
1083 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
1084 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
1085
1086 if (colorFormat_from != colorFormat_to) {
1087 return true;
1088 }
1089
1090 int32_t width_from, width_to;
1091 CHECK(from->findInt32(kKeyWidth, &width_from));
1092 CHECK(to->findInt32(kKeyWidth, &width_to));
1093
1094 if (width_from != width_to) {
1095 return true;
1096 }
1097
1098 int32_t height_from, height_to;
1099 CHECK(from->findInt32(kKeyHeight, &height_from));
1100 CHECK(to->findInt32(kKeyHeight, &height_to));
1101
1102 if (height_from != height_to) {
1103 return true;
1104 }
1105 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
1106 int32_t numChannels_from, numChannels_to;
1107 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
1108 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
1109
1110 if (numChannels_from != numChannels_to) {
1111 return true;
1112 }
1113
1114 int32_t sampleRate_from, sampleRate_to;
1115 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
1116 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
1117
1118 if (sampleRate_from != sampleRate_to) {
1119 return true;
1120 }
1121 }
1122
1123 return false;
1124}
1125
Andreas Huberbe06d262009-08-14 14:37:10 -07001126void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1127 switch (cmd) {
1128 case OMX_CommandStateSet:
1129 {
1130 onStateChange((OMX_STATETYPE)data);
1131 break;
1132 }
1133
1134 case OMX_CommandPortDisable:
1135 {
1136 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001137 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001138
1139 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1140 CHECK_EQ(mPortStatus[portIndex], DISABLING);
1141 CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1142
1143 mPortStatus[portIndex] = DISABLED;
1144
1145 if (mState == RECONFIGURING) {
1146 CHECK_EQ(portIndex, kPortIndexOutput);
1147
Andreas Huberb1678602009-10-19 13:06:40 -07001148 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07001149 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07001150
1151 // Don't notify clients if the output port settings change
1152 // wasn't of importance to them, i.e. it may be that just the
1153 // number of buffers has changed and nothing else.
1154 mOutputPortSettingsHaveChanged =
1155 formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
Andreas Hubercfd55572009-10-09 14:11:28 -07001156
Andreas Huberbe06d262009-08-14 14:37:10 -07001157 enablePortAsync(portIndex);
1158
1159 status_t err = allocateBuffersOnPort(portIndex);
1160 CHECK_EQ(err, OK);
1161 }
1162 break;
1163 }
1164
1165 case OMX_CommandPortEnable:
1166 {
1167 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001168 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001169
1170 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1171 CHECK_EQ(mPortStatus[portIndex], ENABLING);
1172
1173 mPortStatus[portIndex] = ENABLED;
1174
1175 if (mState == RECONFIGURING) {
1176 CHECK_EQ(portIndex, kPortIndexOutput);
1177
1178 setState(EXECUTING);
1179
1180 fillOutputBuffers();
1181 }
1182 break;
1183 }
1184
1185 case OMX_CommandFlush:
1186 {
1187 OMX_U32 portIndex = data;
1188
Andreas Huber4c483422009-09-02 16:05:36 -07001189 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001190
1191 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1192 mPortStatus[portIndex] = ENABLED;
1193
1194 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1195 mPortBuffers[portIndex].size());
1196
1197 if (mState == RECONFIGURING) {
1198 CHECK_EQ(portIndex, kPortIndexOutput);
1199
1200 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001201 } else if (mState == EXECUTING_TO_IDLE) {
1202 if (mPortStatus[kPortIndexInput] == ENABLED
1203 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001204 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001205 "transition from EXECUTING to IDLE.");
1206
1207 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1208 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1209
1210 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001211 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001212 CHECK_EQ(err, OK);
1213 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001214 } else {
1215 // We're flushing both ports in preparation for seeking.
1216
1217 if (mPortStatus[kPortIndexInput] == ENABLED
1218 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001219 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07001220 " seek-time.");
1221
Andreas Huber1a77b68e2009-09-17 11:16:52 -07001222 // Clear this flag in case the decoder sent us either
1223 // the EVENT_BUFFER_FLAG(1) or an output buffer with
1224 // the EOS flag set _while_ flushing. Since we're going
1225 // to submit "fresh" input data now, this flag no longer
1226 // applies to our future.
1227 mNoMoreOutputData = false;
1228
Andreas Huberbe06d262009-08-14 14:37:10 -07001229 drainInputBuffers();
1230 fillOutputBuffers();
1231 }
1232 }
1233
1234 break;
1235 }
1236
1237 default:
1238 {
Andreas Huber4c483422009-09-02 16:05:36 -07001239 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07001240 break;
1241 }
1242 }
1243}
1244
1245void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1246 switch (newState) {
1247 case OMX_StateIdle:
1248 {
Andreas Huber4c483422009-09-02 16:05:36 -07001249 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001250 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07001251 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07001252 mNode, OMX_CommandStateSet, OMX_StateExecuting);
1253
1254 CHECK_EQ(err, OK);
1255
1256 setState(IDLE_TO_EXECUTING);
1257 } else {
1258 CHECK_EQ(mState, EXECUTING_TO_IDLE);
1259
1260 CHECK_EQ(
1261 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1262 mPortBuffers[kPortIndexInput].size());
1263
1264 CHECK_EQ(
1265 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1266 mPortBuffers[kPortIndexOutput].size());
1267
Andreas Huber784202e2009-10-15 13:46:54 -07001268 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07001269 mNode, OMX_CommandStateSet, OMX_StateLoaded);
1270
1271 CHECK_EQ(err, OK);
1272
1273 err = freeBuffersOnPort(kPortIndexInput);
1274 CHECK_EQ(err, OK);
1275
1276 err = freeBuffersOnPort(kPortIndexOutput);
1277 CHECK_EQ(err, OK);
1278
1279 mPortStatus[kPortIndexInput] = ENABLED;
1280 mPortStatus[kPortIndexOutput] = ENABLED;
1281
1282 setState(IDLE_TO_LOADED);
1283 }
1284 break;
1285 }
1286
1287 case OMX_StateExecuting:
1288 {
1289 CHECK_EQ(mState, IDLE_TO_EXECUTING);
1290
Andreas Huber4c483422009-09-02 16:05:36 -07001291 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001292
1293 setState(EXECUTING);
1294
Andreas Huber42978e52009-08-27 10:08:39 -07001295 // Buffers will be submitted to the component in the first
1296 // call to OMXCodec::read as mInitialBufferSubmit is true at
1297 // this point. This ensures that this on_message call returns,
1298 // releases the lock and ::init can notice the state change and
1299 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07001300 break;
1301 }
1302
1303 case OMX_StateLoaded:
1304 {
1305 CHECK_EQ(mState, IDLE_TO_LOADED);
1306
Andreas Huber4c483422009-09-02 16:05:36 -07001307 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001308
1309 setState(LOADED);
1310 break;
1311 }
1312
1313 default:
1314 {
1315 CHECK(!"should not be here.");
1316 break;
1317 }
1318 }
1319}
1320
1321// static
1322size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1323 size_t n = 0;
1324 for (size_t i = 0; i < buffers.size(); ++i) {
1325 if (!buffers[i].mOwnedByComponent) {
1326 ++n;
1327 }
1328 }
1329
1330 return n;
1331}
1332
1333status_t OMXCodec::freeBuffersOnPort(
1334 OMX_U32 portIndex, bool onlyThoseWeOwn) {
1335 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1336
1337 status_t stickyErr = OK;
1338
1339 for (size_t i = buffers->size(); i-- > 0;) {
1340 BufferInfo *info = &buffers->editItemAt(i);
1341
1342 if (onlyThoseWeOwn && info->mOwnedByComponent) {
1343 continue;
1344 }
1345
1346 CHECK_EQ(info->mOwnedByComponent, false);
1347
Andreas Huber92022852009-09-14 15:24:14 -07001348 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
1349
Andreas Huberbe06d262009-08-14 14:37:10 -07001350 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001351 mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001352
1353 if (err != OK) {
1354 stickyErr = err;
1355 }
1356
1357 if (info->mMediaBuffer != NULL) {
1358 info->mMediaBuffer->setObserver(NULL);
1359
1360 // Make sure nobody but us owns this buffer at this point.
1361 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1362
1363 info->mMediaBuffer->release();
1364 }
1365
1366 buffers->removeAt(i);
1367 }
1368
1369 CHECK(onlyThoseWeOwn || buffers->isEmpty());
1370
1371 return stickyErr;
1372}
1373
1374void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07001375 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001376
1377 CHECK_EQ(mState, EXECUTING);
1378 CHECK_EQ(portIndex, kPortIndexOutput);
1379 setState(RECONFIGURING);
1380
1381 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07001382 if (!flushPortAsync(portIndex)) {
1383 onCmdComplete(OMX_CommandFlush, portIndex);
1384 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001385 } else {
1386 disablePortAsync(portIndex);
1387 }
1388}
1389
Andreas Huber404cc412009-08-25 14:26:05 -07001390bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07001391 CHECK(mState == EXECUTING || mState == RECONFIGURING
1392 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001393
Andreas Huber4c483422009-09-02 16:05:36 -07001394 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07001395 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1396 mPortBuffers[portIndex].size());
1397
Andreas Huberbe06d262009-08-14 14:37:10 -07001398 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1399 mPortStatus[portIndex] = SHUTTING_DOWN;
1400
Andreas Huber404cc412009-08-25 14:26:05 -07001401 if ((mQuirks & kRequiresFlushCompleteEmulation)
1402 && countBuffersWeOwn(mPortBuffers[portIndex])
1403 == mPortBuffers[portIndex].size()) {
1404 // No flush is necessary and this component fails to send a
1405 // flush-complete event in this case.
1406
1407 return false;
1408 }
1409
Andreas Huberbe06d262009-08-14 14:37:10 -07001410 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001411 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001412 CHECK_EQ(err, OK);
Andreas Huber404cc412009-08-25 14:26:05 -07001413
1414 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001415}
1416
1417void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1418 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1419
1420 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1421 mPortStatus[portIndex] = DISABLING;
1422
1423 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001424 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001425 CHECK_EQ(err, OK);
1426
1427 freeBuffersOnPort(portIndex, true);
1428}
1429
1430void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1431 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1432
1433 CHECK_EQ(mPortStatus[portIndex], DISABLED);
1434 mPortStatus[portIndex] = ENABLING;
1435
1436 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001437 mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001438 CHECK_EQ(err, OK);
1439}
1440
1441void OMXCodec::fillOutputBuffers() {
1442 CHECK_EQ(mState, EXECUTING);
1443
1444 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1445 for (size_t i = 0; i < buffers->size(); ++i) {
1446 fillOutputBuffer(&buffers->editItemAt(i));
1447 }
1448}
1449
1450void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07001451 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07001452
1453 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1454 for (size_t i = 0; i < buffers->size(); ++i) {
1455 drainInputBuffer(&buffers->editItemAt(i));
1456 }
1457}
1458
1459void OMXCodec::drainInputBuffer(BufferInfo *info) {
1460 CHECK_EQ(info->mOwnedByComponent, false);
1461
1462 if (mSignalledEOS) {
1463 return;
1464 }
1465
1466 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1467 const CodecSpecificData *specific =
1468 mCodecSpecificData[mCodecSpecificDataIndex];
1469
1470 size_t size = specific->mSize;
1471
Andreas Hubere6c40962009-09-10 14:13:30 -07001472 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07001473 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001474 static const uint8_t kNALStartCode[4] =
1475 { 0x00, 0x00, 0x00, 0x01 };
1476
1477 CHECK(info->mMem->size() >= specific->mSize + 4);
1478
1479 size += 4;
1480
1481 memcpy(info->mMem->pointer(), kNALStartCode, 4);
1482 memcpy((uint8_t *)info->mMem->pointer() + 4,
1483 specific->mData, specific->mSize);
1484 } else {
1485 CHECK(info->mMem->size() >= specific->mSize);
1486 memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1487 }
1488
Andreas Huber784202e2009-10-15 13:46:54 -07001489 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07001490 mNode, info->mBuffer, 0, size,
1491 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1492 0);
Andreas Huber3f427072009-10-08 11:02:27 -07001493 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001494
1495 info->mOwnedByComponent = true;
1496
1497 ++mCodecSpecificDataIndex;
1498 return;
1499 }
1500
1501 MediaBuffer *srcBuffer;
1502 status_t err;
1503 if (mSeekTimeUs >= 0) {
1504 MediaSource::ReadOptions options;
1505 options.setSeekTo(mSeekTimeUs);
1506 mSeekTimeUs = -1;
1507
1508 err = mSource->read(&srcBuffer, &options);
1509 } else {
1510 err = mSource->read(&srcBuffer);
1511 }
1512
1513 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberfa8de752009-10-08 10:07:49 -07001514 OMX_TICKS timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07001515 size_t srcLength = 0;
1516
1517 if (err != OK) {
Andreas Huber4c483422009-09-02 16:05:36 -07001518 CODEC_LOGV("signalling end of input stream.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001519 flags |= OMX_BUFFERFLAG_EOS;
1520
1521 mSignalledEOS = true;
1522 } else {
1523 srcLength = srcBuffer->range_length();
1524
1525 if (info->mMem->size() < srcLength) {
1526 LOGE("info->mMem->size() = %d, srcLength = %d",
1527 info->mMem->size(), srcLength);
1528 }
1529 CHECK(info->mMem->size() >= srcLength);
1530 memcpy(info->mMem->pointer(),
1531 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1532 srcLength);
1533
Andreas Huberfa8de752009-10-08 10:07:49 -07001534 if (srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001535 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d)",
Andreas Huberbe06d262009-08-14 14:37:10 -07001536 info->mBuffer, srcLength);
Andreas Huber784202e2009-10-15 13:46:54 -07001537 CODEC_LOGV("Calling emptyBuffer with timestamp %lld us (%.2f secs)",
Andreas Huberfa8de752009-10-08 10:07:49 -07001538 timestampUs, timestampUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07001539 }
1540 }
1541
Andreas Huberbe06d262009-08-14 14:37:10 -07001542 if (srcBuffer != NULL) {
1543 srcBuffer->release();
1544 srcBuffer = NULL;
1545 }
Andreas Huber3f427072009-10-08 11:02:27 -07001546
Andreas Huber784202e2009-10-15 13:46:54 -07001547 err = mOMX->emptyBuffer(
Andreas Huber3f427072009-10-08 11:02:27 -07001548 mNode, info->mBuffer, 0, srcLength,
Andreas Huberfa8de752009-10-08 10:07:49 -07001549 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07001550
1551 if (err != OK) {
1552 setState(ERROR);
1553 return;
1554 }
1555
1556 info->mOwnedByComponent = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001557}
1558
1559void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1560 CHECK_EQ(info->mOwnedByComponent, false);
1561
Andreas Huber404cc412009-08-25 14:26:05 -07001562 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07001563 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07001564 "calling fillOutputBuffer");
1565 return;
1566 }
1567
Andreas Huber4c483422009-09-02 16:05:36 -07001568 CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07001569 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber3f427072009-10-08 11:02:27 -07001570 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001571
1572 info->mOwnedByComponent = true;
1573}
1574
1575void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1576 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1577 for (size_t i = 0; i < buffers->size(); ++i) {
1578 if ((*buffers)[i].mBuffer == buffer) {
1579 drainInputBuffer(&buffers->editItemAt(i));
1580 return;
1581 }
1582 }
1583
1584 CHECK(!"should not be here.");
1585}
1586
1587void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1588 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1589 for (size_t i = 0; i < buffers->size(); ++i) {
1590 if ((*buffers)[i].mBuffer == buffer) {
1591 fillOutputBuffer(&buffers->editItemAt(i));
1592 return;
1593 }
1594 }
1595
1596 CHECK(!"should not be here.");
1597}
1598
1599void OMXCodec::setState(State newState) {
1600 mState = newState;
1601 mAsyncCompletion.signal();
1602
1603 // This may cause some spurious wakeups but is necessary to
1604 // unblock the reader if we enter ERROR state.
1605 mBufferFilled.signal();
1606}
1607
Andreas Huberda050cf22009-09-02 14:01:43 -07001608void OMXCodec::setRawAudioFormat(
1609 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1610 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07001611 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07001612 pcmParams.nPortIndex = portIndex;
1613
Andreas Huber784202e2009-10-15 13:46:54 -07001614 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07001615 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1616
1617 CHECK_EQ(err, OK);
1618
1619 pcmParams.nChannels = numChannels;
1620 pcmParams.eNumData = OMX_NumericalDataSigned;
1621 pcmParams.bInterleaved = OMX_TRUE;
1622 pcmParams.nBitPerSample = 16;
1623 pcmParams.nSamplingRate = sampleRate;
1624 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1625
1626 if (numChannels == 1) {
1627 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1628 } else {
1629 CHECK_EQ(numChannels, 2);
1630
1631 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1632 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1633 }
1634
Andreas Huber784202e2009-10-15 13:46:54 -07001635 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07001636 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1637
1638 CHECK_EQ(err, OK);
1639}
1640
Andreas Huberbe06d262009-08-14 14:37:10 -07001641void OMXCodec::setAMRFormat() {
1642 if (!mIsEncoder) {
1643 OMX_AUDIO_PARAM_AMRTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001644 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001645 def.nPortIndex = kPortIndexInput;
1646
1647 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001648 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07001649
1650 CHECK_EQ(err, OK);
1651
1652 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1653 def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1654
Andreas Huber784202e2009-10-15 13:46:54 -07001655 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07001656 CHECK_EQ(err, OK);
1657 }
1658
1659 ////////////////////////
1660
1661 if (mIsEncoder) {
1662 sp<MetaData> format = mSource->getFormat();
1663 int32_t sampleRate;
1664 int32_t numChannels;
1665 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1666 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1667
Andreas Huberda050cf22009-09-02 14:01:43 -07001668 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
Andreas Huberbe06d262009-08-14 14:37:10 -07001669 }
1670}
1671
Andreas Huberee606e62009-09-08 10:19:21 -07001672void OMXCodec::setAMRWBFormat() {
1673 if (!mIsEncoder) {
1674 OMX_AUDIO_PARAM_AMRTYPE def;
1675 InitOMXParams(&def);
1676 def.nPortIndex = kPortIndexInput;
1677
1678 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001679 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberee606e62009-09-08 10:19:21 -07001680
1681 CHECK_EQ(err, OK);
1682
1683 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1684 def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
1685
Andreas Huber784202e2009-10-15 13:46:54 -07001686 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberee606e62009-09-08 10:19:21 -07001687 CHECK_EQ(err, OK);
1688 }
1689
1690 ////////////////////////
1691
1692 if (mIsEncoder) {
1693 sp<MetaData> format = mSource->getFormat();
1694 int32_t sampleRate;
1695 int32_t numChannels;
1696 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1697 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1698
1699 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1700 }
1701}
1702
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07001703void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
Andreas Huberda050cf22009-09-02 14:01:43 -07001704 if (mIsEncoder) {
1705 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1706 } else {
1707 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07001708 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07001709 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07001710
Andreas Huber784202e2009-10-15 13:46:54 -07001711 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07001712 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1713 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001714
Andreas Huberda050cf22009-09-02 14:01:43 -07001715 profile.nChannels = numChannels;
1716 profile.nSampleRate = sampleRate;
1717 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07001718
Andreas Huber784202e2009-10-15 13:46:54 -07001719 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07001720 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1721 CHECK_EQ(err, OK);
1722 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001723}
1724
1725void OMXCodec::setImageOutputFormat(
1726 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07001727 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001728
1729#if 0
1730 OMX_INDEXTYPE index;
1731 status_t err = mOMX->get_extension_index(
1732 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1733 CHECK_EQ(err, OK);
1734
1735 err = mOMX->set_config(mNode, index, &format, sizeof(format));
1736 CHECK_EQ(err, OK);
1737#endif
1738
1739 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001740 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001741 def.nPortIndex = kPortIndexOutput;
1742
Andreas Huber784202e2009-10-15 13:46:54 -07001743 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001744 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1745 CHECK_EQ(err, OK);
1746
1747 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1748
1749 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001750
Andreas Huberbe06d262009-08-14 14:37:10 -07001751 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1752 imageDef->eColorFormat = format;
1753 imageDef->nFrameWidth = width;
1754 imageDef->nFrameHeight = height;
1755
1756 switch (format) {
1757 case OMX_COLOR_FormatYUV420PackedPlanar:
1758 case OMX_COLOR_FormatYUV411Planar:
1759 {
1760 def.nBufferSize = (width * height * 3) / 2;
1761 break;
1762 }
1763
1764 case OMX_COLOR_FormatCbYCrY:
1765 {
1766 def.nBufferSize = width * height * 2;
1767 break;
1768 }
1769
1770 case OMX_COLOR_Format32bitARGB8888:
1771 {
1772 def.nBufferSize = width * height * 4;
1773 break;
1774 }
1775
Andreas Huber201511c2009-09-08 14:01:44 -07001776 case OMX_COLOR_Format16bitARGB4444:
1777 case OMX_COLOR_Format16bitARGB1555:
1778 case OMX_COLOR_Format16bitRGB565:
1779 case OMX_COLOR_Format16bitBGR565:
1780 {
1781 def.nBufferSize = width * height * 2;
1782 break;
1783 }
1784
Andreas Huberbe06d262009-08-14 14:37:10 -07001785 default:
1786 CHECK(!"Should not be here. Unknown color format.");
1787 break;
1788 }
1789
Andreas Huber5c0a9132009-08-20 11:16:40 -07001790 def.nBufferCountActual = def.nBufferCountMin;
1791
Andreas Huber784202e2009-10-15 13:46:54 -07001792 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001793 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1794 CHECK_EQ(err, OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07001795}
Andreas Huberbe06d262009-08-14 14:37:10 -07001796
Andreas Huber5c0a9132009-08-20 11:16:40 -07001797void OMXCodec::setJPEGInputFormat(
1798 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
1799 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001800 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001801 def.nPortIndex = kPortIndexInput;
1802
Andreas Huber784202e2009-10-15 13:46:54 -07001803 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001804 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1805 CHECK_EQ(err, OK);
1806
Andreas Huber5c0a9132009-08-20 11:16:40 -07001807 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1808 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1809
Andreas Huberbe06d262009-08-14 14:37:10 -07001810 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1811 imageDef->nFrameWidth = width;
1812 imageDef->nFrameHeight = height;
1813
Andreas Huber5c0a9132009-08-20 11:16:40 -07001814 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07001815 def.nBufferCountActual = def.nBufferCountMin;
1816
Andreas Huber784202e2009-10-15 13:46:54 -07001817 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001818 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1819 CHECK_EQ(err, OK);
1820}
1821
1822void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
1823 CodecSpecificData *specific =
1824 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
1825
1826 specific->mSize = size;
1827 memcpy(specific->mData, data, size);
1828
1829 mCodecSpecificData.push(specific);
1830}
1831
1832void OMXCodec::clearCodecSpecificData() {
1833 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
1834 free(mCodecSpecificData.editItemAt(i));
1835 }
1836 mCodecSpecificData.clear();
1837 mCodecSpecificDataIndex = 0;
1838}
1839
1840status_t OMXCodec::start(MetaData *) {
Andreas Huber42978e52009-08-27 10:08:39 -07001841 Mutex::Autolock autoLock(mLock);
1842
Andreas Huberbe06d262009-08-14 14:37:10 -07001843 if (mState != LOADED) {
1844 return UNKNOWN_ERROR;
1845 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07001846
Andreas Huberbe06d262009-08-14 14:37:10 -07001847 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07001848 if (mQuirks & kWantsNALFragments) {
1849 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07001850 }
1851 status_t err = mSource->start(params.get());
1852
1853 if (err != OK) {
1854 return err;
1855 }
1856
1857 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07001858 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001859 mSignalledEOS = false;
1860 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07001861 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07001862 mSeekTimeUs = -1;
1863 mFilledBuffers.clear();
1864
1865 return init();
1866}
1867
1868status_t OMXCodec::stop() {
Andreas Huber4c483422009-09-02 16:05:36 -07001869 CODEC_LOGV("stop");
Andreas Huberbe06d262009-08-14 14:37:10 -07001870
1871 Mutex::Autolock autoLock(mLock);
1872
1873 while (isIntermediateState(mState)) {
1874 mAsyncCompletion.wait(mLock);
1875 }
1876
1877 switch (mState) {
1878 case LOADED:
1879 case ERROR:
1880 break;
1881
1882 case EXECUTING:
1883 {
1884 setState(EXECUTING_TO_IDLE);
1885
Andreas Huber127fcdc2009-08-26 16:27:02 -07001886 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07001887 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001888 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07001889
Andreas Huber127fcdc2009-08-26 16:27:02 -07001890 bool emulateInputFlushCompletion =
1891 !flushPortAsync(kPortIndexInput);
1892
1893 bool emulateOutputFlushCompletion =
1894 !flushPortAsync(kPortIndexOutput);
1895
1896 if (emulateInputFlushCompletion) {
1897 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1898 }
1899
1900 if (emulateOutputFlushCompletion) {
1901 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1902 }
1903 } else {
1904 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1905 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1906
1907 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001908 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001909 CHECK_EQ(err, OK);
1910 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001911
1912 while (mState != LOADED && mState != ERROR) {
1913 mAsyncCompletion.wait(mLock);
1914 }
1915
1916 break;
1917 }
1918
1919 default:
1920 {
1921 CHECK(!"should not be here.");
1922 break;
1923 }
1924 }
1925
1926 mSource->stop();
1927
1928 return OK;
1929}
1930
1931sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07001932 Mutex::Autolock autoLock(mLock);
1933
Andreas Huberbe06d262009-08-14 14:37:10 -07001934 return mOutputFormat;
1935}
1936
1937status_t OMXCodec::read(
1938 MediaBuffer **buffer, const ReadOptions *options) {
1939 *buffer = NULL;
1940
1941 Mutex::Autolock autoLock(mLock);
1942
Andreas Huberd06e5b82009-08-28 13:18:14 -07001943 if (mState != EXECUTING && mState != RECONFIGURING) {
1944 return UNKNOWN_ERROR;
1945 }
1946
Andreas Huber42978e52009-08-27 10:08:39 -07001947 if (mInitialBufferSubmit) {
1948 mInitialBufferSubmit = false;
1949
1950 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07001951
Andreas Huberd06e5b82009-08-28 13:18:14 -07001952 if (mState == EXECUTING) {
1953 // Otherwise mState == RECONFIGURING and this code will trigger
1954 // after the output port is reenabled.
1955 fillOutputBuffers();
1956 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001957 }
1958
1959 int64_t seekTimeUs;
1960 if (options && options->getSeekTo(&seekTimeUs)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001961 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07001962
1963 mSignalledEOS = false;
1964 mNoMoreOutputData = false;
1965
1966 CHECK(seekTimeUs >= 0);
1967 mSeekTimeUs = seekTimeUs;
1968
1969 mFilledBuffers.clear();
1970
1971 CHECK_EQ(mState, EXECUTING);
1972
Andreas Huber404cc412009-08-25 14:26:05 -07001973 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
1974 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
1975
1976 if (emulateInputFlushCompletion) {
1977 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1978 }
1979
1980 if (emulateOutputFlushCompletion) {
1981 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1982 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001983 }
1984
1985 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
1986 mBufferFilled.wait(mLock);
1987 }
1988
1989 if (mState == ERROR) {
1990 return UNKNOWN_ERROR;
1991 }
1992
1993 if (mFilledBuffers.empty()) {
1994 return ERROR_END_OF_STREAM;
1995 }
1996
Andreas Hubercfd55572009-10-09 14:11:28 -07001997 if (mOutputPortSettingsHaveChanged) {
1998 mOutputPortSettingsHaveChanged = false;
1999
2000 return INFO_FORMAT_CHANGED;
2001 }
2002
Andreas Huberbe06d262009-08-14 14:37:10 -07002003 size_t index = *mFilledBuffers.begin();
2004 mFilledBuffers.erase(mFilledBuffers.begin());
2005
2006 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2007 info->mMediaBuffer->add_ref();
2008 *buffer = info->mMediaBuffer;
2009
2010 return OK;
2011}
2012
2013void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
2014 Mutex::Autolock autoLock(mLock);
2015
2016 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2017 for (size_t i = 0; i < buffers->size(); ++i) {
2018 BufferInfo *info = &buffers->editItemAt(i);
2019
2020 if (info->mMediaBuffer == buffer) {
2021 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
2022 fillOutputBuffer(info);
2023 return;
2024 }
2025 }
2026
2027 CHECK(!"should not be here.");
2028}
2029
2030static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
2031 static const char *kNames[] = {
2032 "OMX_IMAGE_CodingUnused",
2033 "OMX_IMAGE_CodingAutoDetect",
2034 "OMX_IMAGE_CodingJPEG",
2035 "OMX_IMAGE_CodingJPEG2K",
2036 "OMX_IMAGE_CodingEXIF",
2037 "OMX_IMAGE_CodingTIFF",
2038 "OMX_IMAGE_CodingGIF",
2039 "OMX_IMAGE_CodingPNG",
2040 "OMX_IMAGE_CodingLZW",
2041 "OMX_IMAGE_CodingBMP",
2042 };
2043
2044 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2045
2046 if (type < 0 || (size_t)type >= numNames) {
2047 return "UNKNOWN";
2048 } else {
2049 return kNames[type];
2050 }
2051}
2052
2053static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
2054 static const char *kNames[] = {
2055 "OMX_COLOR_FormatUnused",
2056 "OMX_COLOR_FormatMonochrome",
2057 "OMX_COLOR_Format8bitRGB332",
2058 "OMX_COLOR_Format12bitRGB444",
2059 "OMX_COLOR_Format16bitARGB4444",
2060 "OMX_COLOR_Format16bitARGB1555",
2061 "OMX_COLOR_Format16bitRGB565",
2062 "OMX_COLOR_Format16bitBGR565",
2063 "OMX_COLOR_Format18bitRGB666",
2064 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07002065 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07002066 "OMX_COLOR_Format24bitRGB888",
2067 "OMX_COLOR_Format24bitBGR888",
2068 "OMX_COLOR_Format24bitARGB1887",
2069 "OMX_COLOR_Format25bitARGB1888",
2070 "OMX_COLOR_Format32bitBGRA8888",
2071 "OMX_COLOR_Format32bitARGB8888",
2072 "OMX_COLOR_FormatYUV411Planar",
2073 "OMX_COLOR_FormatYUV411PackedPlanar",
2074 "OMX_COLOR_FormatYUV420Planar",
2075 "OMX_COLOR_FormatYUV420PackedPlanar",
2076 "OMX_COLOR_FormatYUV420SemiPlanar",
2077 "OMX_COLOR_FormatYUV422Planar",
2078 "OMX_COLOR_FormatYUV422PackedPlanar",
2079 "OMX_COLOR_FormatYUV422SemiPlanar",
2080 "OMX_COLOR_FormatYCbYCr",
2081 "OMX_COLOR_FormatYCrYCb",
2082 "OMX_COLOR_FormatCbYCrY",
2083 "OMX_COLOR_FormatCrYCbY",
2084 "OMX_COLOR_FormatYUV444Interleaved",
2085 "OMX_COLOR_FormatRawBayer8bit",
2086 "OMX_COLOR_FormatRawBayer10bit",
2087 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07002088 "OMX_COLOR_FormatL2",
2089 "OMX_COLOR_FormatL4",
2090 "OMX_COLOR_FormatL8",
2091 "OMX_COLOR_FormatL16",
2092 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07002093 "OMX_COLOR_FormatL32",
2094 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
2095 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
2096 "OMX_COLOR_Format18BitBGR666",
2097 "OMX_COLOR_Format24BitARGB6666",
2098 "OMX_COLOR_Format24BitABGR6666",
2099 };
2100
2101 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2102
Andreas Huberbe06d262009-08-14 14:37:10 -07002103 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
2104 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
2105 } else if (type < 0 || (size_t)type >= numNames) {
2106 return "UNKNOWN";
2107 } else {
2108 return kNames[type];
2109 }
2110}
2111
2112static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
2113 static const char *kNames[] = {
2114 "OMX_VIDEO_CodingUnused",
2115 "OMX_VIDEO_CodingAutoDetect",
2116 "OMX_VIDEO_CodingMPEG2",
2117 "OMX_VIDEO_CodingH263",
2118 "OMX_VIDEO_CodingMPEG4",
2119 "OMX_VIDEO_CodingWMV",
2120 "OMX_VIDEO_CodingRV",
2121 "OMX_VIDEO_CodingAVC",
2122 "OMX_VIDEO_CodingMJPEG",
2123 };
2124
2125 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2126
2127 if (type < 0 || (size_t)type >= numNames) {
2128 return "UNKNOWN";
2129 } else {
2130 return kNames[type];
2131 }
2132}
2133
2134static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2135 static const char *kNames[] = {
2136 "OMX_AUDIO_CodingUnused",
2137 "OMX_AUDIO_CodingAutoDetect",
2138 "OMX_AUDIO_CodingPCM",
2139 "OMX_AUDIO_CodingADPCM",
2140 "OMX_AUDIO_CodingAMR",
2141 "OMX_AUDIO_CodingGSMFR",
2142 "OMX_AUDIO_CodingGSMEFR",
2143 "OMX_AUDIO_CodingGSMHR",
2144 "OMX_AUDIO_CodingPDCFR",
2145 "OMX_AUDIO_CodingPDCEFR",
2146 "OMX_AUDIO_CodingPDCHR",
2147 "OMX_AUDIO_CodingTDMAFR",
2148 "OMX_AUDIO_CodingTDMAEFR",
2149 "OMX_AUDIO_CodingQCELP8",
2150 "OMX_AUDIO_CodingQCELP13",
2151 "OMX_AUDIO_CodingEVRC",
2152 "OMX_AUDIO_CodingSMV",
2153 "OMX_AUDIO_CodingG711",
2154 "OMX_AUDIO_CodingG723",
2155 "OMX_AUDIO_CodingG726",
2156 "OMX_AUDIO_CodingG729",
2157 "OMX_AUDIO_CodingAAC",
2158 "OMX_AUDIO_CodingMP3",
2159 "OMX_AUDIO_CodingSBC",
2160 "OMX_AUDIO_CodingVORBIS",
2161 "OMX_AUDIO_CodingWMA",
2162 "OMX_AUDIO_CodingRA",
2163 "OMX_AUDIO_CodingMIDI",
2164 };
2165
2166 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2167
2168 if (type < 0 || (size_t)type >= numNames) {
2169 return "UNKNOWN";
2170 } else {
2171 return kNames[type];
2172 }
2173}
2174
2175static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2176 static const char *kNames[] = {
2177 "OMX_AUDIO_PCMModeLinear",
2178 "OMX_AUDIO_PCMModeALaw",
2179 "OMX_AUDIO_PCMModeMULaw",
2180 };
2181
2182 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2183
2184 if (type < 0 || (size_t)type >= numNames) {
2185 return "UNKNOWN";
2186 } else {
2187 return kNames[type];
2188 }
2189}
2190
Andreas Huber7ae02c82009-09-09 16:29:47 -07002191static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
2192 static const char *kNames[] = {
2193 "OMX_AUDIO_AMRBandModeUnused",
2194 "OMX_AUDIO_AMRBandModeNB0",
2195 "OMX_AUDIO_AMRBandModeNB1",
2196 "OMX_AUDIO_AMRBandModeNB2",
2197 "OMX_AUDIO_AMRBandModeNB3",
2198 "OMX_AUDIO_AMRBandModeNB4",
2199 "OMX_AUDIO_AMRBandModeNB5",
2200 "OMX_AUDIO_AMRBandModeNB6",
2201 "OMX_AUDIO_AMRBandModeNB7",
2202 "OMX_AUDIO_AMRBandModeWB0",
2203 "OMX_AUDIO_AMRBandModeWB1",
2204 "OMX_AUDIO_AMRBandModeWB2",
2205 "OMX_AUDIO_AMRBandModeWB3",
2206 "OMX_AUDIO_AMRBandModeWB4",
2207 "OMX_AUDIO_AMRBandModeWB5",
2208 "OMX_AUDIO_AMRBandModeWB6",
2209 "OMX_AUDIO_AMRBandModeWB7",
2210 "OMX_AUDIO_AMRBandModeWB8",
2211 };
2212
2213 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2214
2215 if (type < 0 || (size_t)type >= numNames) {
2216 return "UNKNOWN";
2217 } else {
2218 return kNames[type];
2219 }
2220}
2221
2222static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
2223 static const char *kNames[] = {
2224 "OMX_AUDIO_AMRFrameFormatConformance",
2225 "OMX_AUDIO_AMRFrameFormatIF1",
2226 "OMX_AUDIO_AMRFrameFormatIF2",
2227 "OMX_AUDIO_AMRFrameFormatFSF",
2228 "OMX_AUDIO_AMRFrameFormatRTPPayload",
2229 "OMX_AUDIO_AMRFrameFormatITU",
2230 };
2231
2232 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2233
2234 if (type < 0 || (size_t)type >= numNames) {
2235 return "UNKNOWN";
2236 } else {
2237 return kNames[type];
2238 }
2239}
Andreas Huberbe06d262009-08-14 14:37:10 -07002240
2241void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2242 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002243 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002244 def.nPortIndex = portIndex;
2245
Andreas Huber784202e2009-10-15 13:46:54 -07002246 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002247 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2248 CHECK_EQ(err, OK);
2249
2250 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2251
2252 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2253 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
2254
2255 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
2256 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
2257 printf(" nBufferSize = %ld\n", def.nBufferSize);
2258
2259 switch (def.eDomain) {
2260 case OMX_PortDomainImage:
2261 {
2262 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2263
2264 printf("\n");
2265 printf(" // Image\n");
2266 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
2267 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
2268 printf(" nStride = %ld\n", imageDef->nStride);
2269
2270 printf(" eCompressionFormat = %s\n",
2271 imageCompressionFormatString(imageDef->eCompressionFormat));
2272
2273 printf(" eColorFormat = %s\n",
2274 colorFormatString(imageDef->eColorFormat));
2275
2276 break;
2277 }
2278
2279 case OMX_PortDomainVideo:
2280 {
2281 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2282
2283 printf("\n");
2284 printf(" // Video\n");
2285 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
2286 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
2287 printf(" nStride = %ld\n", videoDef->nStride);
2288
2289 printf(" eCompressionFormat = %s\n",
2290 videoCompressionFormatString(videoDef->eCompressionFormat));
2291
2292 printf(" eColorFormat = %s\n",
2293 colorFormatString(videoDef->eColorFormat));
2294
2295 break;
2296 }
2297
2298 case OMX_PortDomainAudio:
2299 {
2300 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2301
2302 printf("\n");
2303 printf(" // Audio\n");
2304 printf(" eEncoding = %s\n",
2305 audioCodingTypeString(audioDef->eEncoding));
2306
2307 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2308 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07002309 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07002310 params.nPortIndex = portIndex;
2311
Andreas Huber784202e2009-10-15 13:46:54 -07002312 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002313 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2314 CHECK_EQ(err, OK);
2315
2316 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
2317 printf(" nChannels = %ld\n", params.nChannels);
2318 printf(" bInterleaved = %d\n", params.bInterleaved);
2319 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
2320
2321 printf(" eNumData = %s\n",
2322 params.eNumData == OMX_NumericalDataSigned
2323 ? "signed" : "unsigned");
2324
2325 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07002326 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
2327 OMX_AUDIO_PARAM_AMRTYPE amr;
2328 InitOMXParams(&amr);
2329 amr.nPortIndex = portIndex;
2330
Andreas Huber784202e2009-10-15 13:46:54 -07002331 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07002332 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2333 CHECK_EQ(err, OK);
2334
2335 printf(" nChannels = %ld\n", amr.nChannels);
2336 printf(" eAMRBandMode = %s\n",
2337 amrBandModeString(amr.eAMRBandMode));
2338 printf(" eAMRFrameFormat = %s\n",
2339 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07002340 }
2341
2342 break;
2343 }
2344
2345 default:
2346 {
2347 printf(" // Unknown\n");
2348 break;
2349 }
2350 }
2351
2352 printf("}\n");
2353}
2354
2355void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
2356 mOutputFormat = new MetaData;
2357 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
2358
2359 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002360 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002361 def.nPortIndex = kPortIndexOutput;
2362
Andreas Huber784202e2009-10-15 13:46:54 -07002363 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002364 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2365 CHECK_EQ(err, OK);
2366
2367 switch (def.eDomain) {
2368 case OMX_PortDomainImage:
2369 {
2370 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2371 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2372
Andreas Hubere6c40962009-09-10 14:13:30 -07002373 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07002374 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
2375 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
2376 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
2377 break;
2378 }
2379
2380 case OMX_PortDomainAudio:
2381 {
2382 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
2383
Andreas Huberda050cf22009-09-02 14:01:43 -07002384 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
2385 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07002386 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07002387 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002388
Andreas Huber784202e2009-10-15 13:46:54 -07002389 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002390 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2391 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002392
Andreas Huberda050cf22009-09-02 14:01:43 -07002393 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
2394 CHECK_EQ(params.nBitPerSample, 16);
2395 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07002396
Andreas Huberda050cf22009-09-02 14:01:43 -07002397 int32_t numChannels, sampleRate;
2398 inputFormat->findInt32(kKeyChannelCount, &numChannels);
2399 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07002400
Andreas Huberda050cf22009-09-02 14:01:43 -07002401 if ((OMX_U32)numChannels != params.nChannels) {
2402 LOGW("Codec outputs a different number of channels than "
2403 "the input stream contains.");
2404 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002405
Andreas Hubere6c40962009-09-10 14:13:30 -07002406 mOutputFormat->setCString(
2407 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07002408
2409 // Use the codec-advertised number of channels, as some
2410 // codecs appear to output stereo even if the input data is
2411 // mono.
2412 mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
2413
2414 // The codec-reported sampleRate is not reliable...
2415 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
2416 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07002417 OMX_AUDIO_PARAM_AMRTYPE amr;
2418 InitOMXParams(&amr);
2419 amr.nPortIndex = kPortIndexOutput;
2420
Andreas Huber784202e2009-10-15 13:46:54 -07002421 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07002422 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2423 CHECK_EQ(err, OK);
2424
2425 CHECK_EQ(amr.nChannels, 1);
2426 mOutputFormat->setInt32(kKeyChannelCount, 1);
2427
2428 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
2429 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002430 mOutputFormat->setCString(
2431 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07002432 mOutputFormat->setInt32(kKeySampleRate, 8000);
2433 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
2434 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002435 mOutputFormat->setCString(
2436 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07002437 mOutputFormat->setInt32(kKeySampleRate, 16000);
2438 } else {
2439 CHECK(!"Unknown AMR band mode.");
2440 }
Andreas Huberda050cf22009-09-02 14:01:43 -07002441 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002442 mOutputFormat->setCString(
2443 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
Andreas Huberda050cf22009-09-02 14:01:43 -07002444 } else {
2445 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07002446 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002447 break;
2448 }
2449
2450 case OMX_PortDomainVideo:
2451 {
2452 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2453
2454 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002455 mOutputFormat->setCString(
2456 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07002457 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002458 mOutputFormat->setCString(
2459 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07002460 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002461 mOutputFormat->setCString(
2462 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07002463 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07002464 mOutputFormat->setCString(
2465 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07002466 } else {
2467 CHECK(!"Unknown compression format.");
2468 }
2469
2470 if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
2471 // This component appears to be lying to me.
2472 mOutputFormat->setInt32(
2473 kKeyWidth, (video_def->nFrameWidth + 15) & -16);
2474 mOutputFormat->setInt32(
2475 kKeyHeight, (video_def->nFrameHeight + 15) & -16);
2476 } else {
2477 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
2478 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
2479 }
2480
2481 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
2482 break;
2483 }
2484
2485 default:
2486 {
2487 CHECK(!"should not be here, neither audio nor video.");
2488 break;
2489 }
2490 }
2491}
2492
Andreas Hubere6c40962009-09-10 14:13:30 -07002493////////////////////////////////////////////////////////////////////////////////
2494
2495status_t QueryCodecs(
2496 const sp<IOMX> &omx,
2497 const char *mime, bool queryDecoders,
2498 Vector<CodecCapabilities> *results) {
2499 results->clear();
2500
2501 for (int index = 0;; ++index) {
2502 const char *componentName;
2503
2504 if (!queryDecoders) {
2505 componentName = GetCodec(
2506 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
2507 mime, index);
2508 } else {
2509 componentName = GetCodec(
2510 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
2511 mime, index);
2512 }
2513
2514 if (!componentName) {
2515 return OK;
2516 }
2517
Andreas Huber784202e2009-10-15 13:46:54 -07002518 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07002519 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07002520 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07002521
2522 if (err != OK) {
2523 continue;
2524 }
2525
2526 OMXCodec::setComponentRole(omx, node, queryDecoders, mime);
2527
2528 results->push();
2529 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
2530 caps->mComponentName = componentName;
2531
2532 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
2533 InitOMXParams(&param);
2534
2535 param.nPortIndex = queryDecoders ? 0 : 1;
2536
2537 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07002538 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07002539 node, OMX_IndexParamVideoProfileLevelQuerySupported,
2540 &param, sizeof(param));
2541
2542 if (err != OK) {
2543 break;
2544 }
2545
2546 CodecProfileLevel profileLevel;
2547 profileLevel.mProfile = param.eProfile;
2548 profileLevel.mLevel = param.eLevel;
2549
2550 caps->mProfileLevels.push(profileLevel);
2551 }
2552
Andreas Huber784202e2009-10-15 13:46:54 -07002553 CHECK_EQ(omx->freeNode(node), OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07002554 }
2555}
2556
Andreas Huberbe06d262009-08-14 14:37:10 -07002557} // namespace android