blob: 278e3a2228399f95b4ef11b5dcb39682986e0ef6 [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
James Dong9989f3c2012-02-03 11:03:56 -080021#include "include/AACEncoder.h"
James Dong1cc31e62010-07-02 17:44:44 -070022#include "include/AVCEncoder.h"
James Dong42ef0c72010-07-12 21:46:25 -070023#include "include/M4vH263Encoder.h"
Andreas Huber8c7ab032009-12-07 11:23:44 -080024
Andreas Huberbd7b43b2009-10-13 10:22:55 -070025#include "include/ESDS.h"
26
Andreas Huberbe06d262009-08-14 14:37:10 -070027#include <binder/IServiceManager.h>
28#include <binder/MemoryDealer.h>
29#include <binder/ProcessState.h>
James Donge1dea482012-03-12 14:37:53 -070030#include <HardwareAPI.h>
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080031#include <media/stagefright/foundation/ADebug.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070032#include <media/IMediaPlayerService.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070033#include <media/stagefright/MediaBuffer.h>
34#include <media/stagefright/MediaBufferGroup.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070035#include <media/stagefright/MediaDefs.h>
Andreas Huber3d3864f2012-02-29 15:47:17 -080036#include <media/stagefright/MediaCodecList.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070037#include <media/stagefright/MediaExtractor.h>
38#include <media/stagefright/MetaData.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070039#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070040#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070041#include <utils/Vector.h>
42
43#include <OMX_Audio.h>
44#include <OMX_Component.h>
45
Andreas Huberf7e2e312010-11-15 09:01:13 -080046#include "include/avc_utils.h"
Andreas Huber8946ab22010-09-15 16:20:42 -070047
Andreas Huberbe06d262009-08-14 14:37:10 -070048namespace android {
49
James Dongd9ac6212011-07-15 15:25:36 -070050// Treat time out as an error if we have not received any output
51// buffers after 3 seconds.
James Dong4a0c91f2011-09-09 13:19:59 -070052const static int64_t kBufferFilledEventTimeOutNs = 3000000000LL;
James Dongd9ac6212011-07-15 15:25:36 -070053
James Dong5a37afa2011-10-18 16:21:52 -070054// OMX Spec defines less than 50 color formats. If the query for
55// color format is executed for more than kMaxColorFormatSupported,
56// the query will fail to avoid looping forever.
57// 1000 is more than enough for us to tell whether the omx
58// component in question is buggy or not.
59const static uint32_t kMaxColorFormatSupported = 1000;
60
James Dong17299ab2010-05-14 15:45:22 -070061#define FACTORY_CREATE_ENCODER(name) \
62static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
63 return new name(source, meta); \
64}
65
Andreas Huberfb1c2f82009-12-15 13:25:11 -080066#define FACTORY_REF(name) { #name, Make##name },
67
James Dong9989f3c2012-02-03 11:03:56 -080068FACTORY_CREATE_ENCODER(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070069FACTORY_CREATE_ENCODER(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070070FACTORY_CREATE_ENCODER(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070071
72static sp<MediaSource> InstantiateSoftwareEncoder(
73 const char *name, const sp<MediaSource> &source,
74 const sp<MetaData> &meta) {
75 struct FactoryInfo {
76 const char *name;
77 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
78 };
79
80 static const FactoryInfo kFactoryInfo[] = {
James Dong9989f3c2012-02-03 11:03:56 -080081 FACTORY_REF(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070082 FACTORY_REF(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070083 FACTORY_REF(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070084 };
85 for (size_t i = 0;
86 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
87 if (!strcmp(name, kFactoryInfo[i].name)) {
88 return (*kFactoryInfo[i].CreateFunc)(source, meta);
89 }
90 }
91
92 return NULL;
93}
Andreas Huberfb1c2f82009-12-15 13:25:11 -080094
Andreas Huber3d3864f2012-02-29 15:47:17 -080095#undef FACTORY_CREATE_ENCODER
Andreas Huberfb1c2f82009-12-15 13:25:11 -080096#undef FACTORY_REF
Andreas Huberfb1c2f82009-12-15 13:25:11 -080097
Steve Block6215d3f2012-01-04 20:05:49 +000098#define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Steve Block71f2cf12011-10-20 11:56:00 +010099#define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
Steve Block3762c312012-01-06 19:20:56 +0000100#define CODEC_LOGE(x, ...) ALOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700101
Andreas Huberbe06d262009-08-14 14:37:10 -0700102struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -0700103 OMXCodecObserver() {
104 }
105
106 void setCodec(const sp<OMXCodec> &target) {
107 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -0700108 }
109
110 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -0700111 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700112 sp<OMXCodec> codec = mTarget.promote();
113
114 if (codec.get() != NULL) {
James Dong681e89c2011-01-10 08:55:02 -0800115 Mutex::Autolock autoLock(codec->mLock);
Andreas Huberbe06d262009-08-14 14:37:10 -0700116 codec->on_message(msg);
James Dong681e89c2011-01-10 08:55:02 -0800117 codec.clear();
Andreas Huberbe06d262009-08-14 14:37:10 -0700118 }
119 }
120
121protected:
122 virtual ~OMXCodecObserver() {}
123
124private:
125 wp<OMXCodec> mTarget;
126
127 OMXCodecObserver(const OMXCodecObserver &);
128 OMXCodecObserver &operator=(const OMXCodecObserver &);
129};
130
Andreas Huber4c483422009-09-02 16:05:36 -0700131template<class T>
132static void InitOMXParams(T *params) {
133 params->nSize = sizeof(T);
134 params->nVersion.s.nVersionMajor = 1;
135 params->nVersion.s.nVersionMinor = 0;
136 params->nVersion.s.nRevision = 0;
137 params->nVersion.s.nStep = 0;
138}
139
Andreas Hubere13526a2009-10-22 10:43:34 -0700140static bool IsSoftwareCodec(const char *componentName) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700141 if (!strncmp("OMX.google.", componentName, 11)) {
142 return true;
143 }
144
James Dong5592bcc2010-10-22 17:10:43 -0700145 if (!strncmp("OMX.", componentName, 4)) {
146 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -0700147 }
148
James Dong5592bcc2010-10-22 17:10:43 -0700149 return true;
Andreas Hubere13526a2009-10-22 10:43:34 -0700150}
151
Andreas Huber4b3913a2011-05-11 14:13:42 -0700152// A sort order in which OMX software codecs are first, followed
153// by other (non-OMX) software codecs, followed by everything else.
Andreas Hubere13526a2009-10-22 10:43:34 -0700154static int CompareSoftwareCodecsFirst(
155 const String8 *elem1, const String8 *elem2) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700156 bool isOMX1 = !strncmp(elem1->string(), "OMX.", 4);
157 bool isOMX2 = !strncmp(elem2->string(), "OMX.", 4);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800158
Andreas Hubere13526a2009-10-22 10:43:34 -0700159 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
160 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
161
162 if (isSoftwareCodec1) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700163 if (!isSoftwareCodec2) { return -1; }
164
165 if (isOMX1) {
166 if (isOMX2) { return 0; }
167
168 return -1;
169 } else {
170 if (isOMX2) { return 0; }
171
172 return 1;
173 }
174
Andreas Hubere13526a2009-10-22 10:43:34 -0700175 return -1;
176 }
177
178 if (isSoftwareCodec2) {
179 return 1;
180 }
181
182 return 0;
183}
184
185// static
Andreas Hubere13526a2009-10-22 10:43:34 -0700186void OMXCodec::findMatchingCodecs(
187 const char *mime,
188 bool createEncoder, const char *matchComponentName,
189 uint32_t flags,
Andreas Huber3d3864f2012-02-29 15:47:17 -0800190 Vector<String8> *matchingCodecs,
191 Vector<uint32_t> *matchingCodecQuirks) {
Andreas Hubere13526a2009-10-22 10:43:34 -0700192 matchingCodecs->clear();
193
Andreas Huber3d3864f2012-02-29 15:47:17 -0800194 if (matchingCodecQuirks) {
195 matchingCodecQuirks->clear();
196 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700197
Andreas Huber3d3864f2012-02-29 15:47:17 -0800198 const MediaCodecList *list = MediaCodecList::getInstance();
199 if (list == NULL) {
200 return;
201 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700202
Andreas Huber3d3864f2012-02-29 15:47:17 -0800203 size_t index = 0;
204 for (;;) {
205 ssize_t matchIndex =
206 list->findCodecByType(mime, createEncoder, index);
207
208 if (matchIndex < 0) {
Andreas Hubere13526a2009-10-22 10:43:34 -0700209 break;
210 }
211
Andreas Huber3d3864f2012-02-29 15:47:17 -0800212 index = matchIndex + 1;
213
214 const char *componentName = list->getCodecName(matchIndex);
215
Andreas Hubere13526a2009-10-22 10:43:34 -0700216 // If a specific codec is requested, skip the non-matching ones.
217 if (matchComponentName && strcmp(componentName, matchComponentName)) {
218 continue;
219 }
220
James Dong170a9292010-10-22 17:28:15 -0700221 // When requesting software-only codecs, only push software codecs
222 // When requesting hardware-only codecs, only push hardware codecs
223 // When there is request neither for software-only nor for
224 // hardware-only codecs, push all codecs
225 if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
226 ((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
227 (!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
228
229 matchingCodecs->push(String8(componentName));
Andreas Huber3d3864f2012-02-29 15:47:17 -0800230
231 if (matchingCodecQuirks) {
232 matchingCodecQuirks->push(getComponentQuirks(list, matchIndex));
233 }
James Dong170a9292010-10-22 17:28:15 -0700234 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700235 }
236
237 if (flags & kPreferSoftwareCodecs) {
238 matchingCodecs->sort(CompareSoftwareCodecsFirst);
239 }
240}
241
242// static
Andreas Huber3d3864f2012-02-29 15:47:17 -0800243uint32_t OMXCodec::getComponentQuirks(
244 const MediaCodecList *list, size_t index) {
245 uint32_t quirks = 0;
246 if (list->codecHasQuirk(
247 index, "requires-allocate-on-input-ports")) {
248 quirks |= kRequiresAllocateBufferOnInputPorts;
249 }
250 if (list->codecHasQuirk(
251 index, "requires-allocate-on-output-ports")) {
252 quirks |= kRequiresAllocateBufferOnOutputPorts;
253 }
254 if (list->codecHasQuirk(
255 index, "output-buffers-are-unreadable")) {
256 quirks |= kOutputBuffersAreUnreadable;
257 }
258
259 return quirks;
260}
261
262// static
263bool OMXCodec::findCodecQuirks(const char *componentName, uint32_t *quirks) {
264 const MediaCodecList *list = MediaCodecList::getInstance();
265
266 if (list == NULL) {
267 return false;
268 }
269
270 ssize_t index = list->findCodecByName(componentName);
271
272 if (index < 0) {
273 return false;
274 }
275
276 *quirks = getComponentQuirks(list, index);
277
278 return true;
279}
280
281// static
Andreas Huber91eb0352009-12-07 09:43:00 -0800282sp<MediaSource> OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700283 const sp<IOMX> &omx,
284 const sp<MetaData> &meta, bool createEncoder,
285 const sp<MediaSource> &source,
286 const char *matchComponentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700287 uint32_t flags,
288 const sp<ANativeWindow> &nativeWindow) {
Andreas Huber42fb5d62011-06-29 15:53:28 -0700289 int32_t requiresSecureBuffers;
290 if (source->getFormat()->findInt32(
291 kKeyRequiresSecureBuffers,
292 &requiresSecureBuffers)
293 && requiresSecureBuffers) {
294 flags |= kIgnoreCodecSpecificData;
295 flags |= kUseSecureInputBuffers;
296 }
297
Andreas Hubere13526a2009-10-22 10:43:34 -0700298 const char *mime;
299 bool success = meta->findCString(kKeyMIMEType, &mime);
300 CHECK(success);
301
302 Vector<String8> matchingCodecs;
Andreas Huber3d3864f2012-02-29 15:47:17 -0800303 Vector<uint32_t> matchingCodecQuirks;
Andreas Hubere13526a2009-10-22 10:43:34 -0700304 findMatchingCodecs(
Andreas Huber3d3864f2012-02-29 15:47:17 -0800305 mime, createEncoder, matchComponentName, flags,
306 &matchingCodecs, &matchingCodecQuirks);
Andreas Hubere13526a2009-10-22 10:43:34 -0700307
308 if (matchingCodecs.isEmpty()) {
309 return NULL;
310 }
311
312 sp<OMXCodecObserver> observer = new OMXCodecObserver;
313 IOMX::node_id node = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700314
Andreas Hubere13526a2009-10-22 10:43:34 -0700315 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
Andreas Huber753fd9a2011-08-10 12:53:59 -0700316 const char *componentNameBase = matchingCodecs[i].string();
Andreas Huber3d3864f2012-02-29 15:47:17 -0800317 uint32_t quirks = matchingCodecQuirks[i];
Andreas Huber753fd9a2011-08-10 12:53:59 -0700318 const char *componentName = componentNameBase;
319
320 AString tmp;
321 if (flags & kUseSecureInputBuffers) {
322 tmp = componentNameBase;
323 tmp.append(".secure");
324
325 componentName = tmp.c_str();
326 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700327
Andreas Hubera8ccc502011-07-13 12:38:46 -0700328 if (createEncoder) {
329 sp<MediaSource> softwareCodec =
330 InstantiateSoftwareEncoder(componentName, source, meta);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800331
Andreas Hubera8ccc502011-07-13 12:38:46 -0700332 if (softwareCodec != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100333 ALOGV("Successfully allocated software codec '%s'", componentName);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800334
Andreas Hubera8ccc502011-07-13 12:38:46 -0700335 return softwareCodec;
336 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800337 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800338
Steve Block71f2cf12011-10-20 11:56:00 +0100339 ALOGV("Attempting to allocate OMX node '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700340
Andreas Huber5a40e392010-10-18 09:57:42 -0700341 if (!createEncoder
342 && (quirks & kOutputBuffersAreUnreadable)
343 && (flags & kClientNeedsFramebuffer)) {
344 if (strncmp(componentName, "OMX.SEC.", 8)) {
345 // For OMX.SEC.* decoders we can enable a special mode that
346 // gives the client access to the framebuffer contents.
347
Steve Block8564c8d2012-01-05 23:22:43 +0000348 ALOGW("Component '%s' does not give the client access to "
Andreas Huber5a40e392010-10-18 09:57:42 -0700349 "the framebuffer contents. Skipping.",
350 componentName);
351
352 continue;
353 }
354 }
355
Andreas Hubere13526a2009-10-22 10:43:34 -0700356 status_t err = omx->allocateNode(componentName, observer, &node);
357 if (err == OK) {
Steve Block71f2cf12011-10-20 11:56:00 +0100358 ALOGV("Successfully allocated OMX node '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700359
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700360 sp<OMXCodec> codec = new OMXCodec(
Andreas Huber42fb5d62011-06-29 15:53:28 -0700361 omx, node, quirks, flags,
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700362 createEncoder, mime, componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700363 source, nativeWindow);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700364
365 observer->setCodec(codec);
366
Andreas Huber42fb5d62011-06-29 15:53:28 -0700367 err = codec->configureCodec(meta);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700368
369 if (err == OK) {
Andreas Hubereb2f9c12011-05-19 08:37:39 -0700370 if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) {
Andreas Huber42fb5d62011-06-29 15:53:28 -0700371 codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime;
Andreas Hubereb2f9c12011-05-19 08:37:39 -0700372 }
373
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700374 return codec;
375 }
376
Steve Block71f2cf12011-10-20 11:56:00 +0100377 ALOGV("Failed to configure codec '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700378 }
379 }
380
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700381 return NULL;
382}
Andreas Hubere13526a2009-10-22 10:43:34 -0700383
Andreas Huber0ba86602011-11-18 12:22:59 -0800384status_t OMXCodec::parseAVCCodecSpecificData(
385 const void *data, size_t size,
386 unsigned *profile, unsigned *level) {
387 const uint8_t *ptr = (const uint8_t *)data;
388
389 // verify minimum size and configurationVersion == 1.
390 if (size < 7 || ptr[0] != 1) {
391 return ERROR_MALFORMED;
392 }
393
394 *profile = ptr[1];
395 *level = ptr[3];
396
397 // There is decodable content out there that fails the following
398 // assertion, let's be lenient for now...
399 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
400
401 size_t lengthSize = 1 + (ptr[4] & 3);
402
403 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
404 // violates it...
405 // CHECK((ptr[5] >> 5) == 7); // reserved
406
407 size_t numSeqParameterSets = ptr[5] & 31;
408
409 ptr += 6;
410 size -= 6;
411
412 for (size_t i = 0; i < numSeqParameterSets; ++i) {
413 if (size < 2) {
414 return ERROR_MALFORMED;
415 }
416
417 size_t length = U16_AT(ptr);
418
419 ptr += 2;
420 size -= 2;
421
422 if (size < length) {
423 return ERROR_MALFORMED;
424 }
425
426 addCodecSpecificData(ptr, length);
427
428 ptr += length;
429 size -= length;
430 }
431
432 if (size < 1) {
433 return ERROR_MALFORMED;
434 }
435
436 size_t numPictureParameterSets = *ptr;
437 ++ptr;
438 --size;
439
440 for (size_t i = 0; i < numPictureParameterSets; ++i) {
441 if (size < 2) {
442 return ERROR_MALFORMED;
443 }
444
445 size_t length = U16_AT(ptr);
446
447 ptr += 2;
448 size -= 2;
449
450 if (size < length) {
451 return ERROR_MALFORMED;
452 }
453
454 addCodecSpecificData(ptr, length);
455
456 ptr += length;
457 size -= length;
458 }
459
460 return OK;
461}
462
Andreas Huber42fb5d62011-06-29 15:53:28 -0700463status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
Steve Block71f2cf12011-10-20 11:56:00 +0100464 ALOGV("configureCodec protected=%d",
Andreas Huber42fb5d62011-06-29 15:53:28 -0700465 (mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
James Dong5f3ab062011-01-25 16:31:28 -0800466
Andreas Huber42fb5d62011-06-29 15:53:28 -0700467 if (!(mFlags & kIgnoreCodecSpecificData)) {
Andreas Huber4c19bf92010-09-08 14:32:20 -0700468 uint32_t type;
469 const void *data;
470 size_t size;
471 if (meta->findData(kKeyESDS, &type, &data, &size)) {
472 ESDS esds((const char *)data, size);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800473 CHECK_EQ(esds.InitCheck(), (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700474
Andreas Huber4c19bf92010-09-08 14:32:20 -0700475 const void *codec_specific_data;
476 size_t codec_specific_data_size;
477 esds.getCodecSpecificInfo(
478 &codec_specific_data, &codec_specific_data_size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700479
Andreas Huber4c19bf92010-09-08 14:32:20 -0700480 addCodecSpecificData(
481 codec_specific_data, codec_specific_data_size);
482 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
483 // Parse the AVCDecoderConfigurationRecord
Andreas Huberebf66ea2009-08-19 13:32:58 -0700484
Andreas Huber0ba86602011-11-18 12:22:59 -0800485 unsigned profile, level;
486 status_t err;
487 if ((err = parseAVCCodecSpecificData(
488 data, size, &profile, &level)) != OK) {
Steve Block3762c312012-01-06 19:20:56 +0000489 ALOGE("Malformed AVC codec specific data.");
Andreas Huber0ba86602011-11-18 12:22:59 -0800490 return err;
Andreas Huber4c19bf92010-09-08 14:32:20 -0700491 }
Andreas Huberebf66ea2009-08-19 13:32:58 -0700492
Andreas Huber6ac2cb22010-11-18 14:06:07 -0800493 CODEC_LOGI(
Andreas Huber0ba86602011-11-18 12:22:59 -0800494 "AVC profile = %u (%s), level = %u",
495 profile, AVCProfileToString(profile), level);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700496 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
497 addCodecSpecificData(data, size);
498
499 CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
500 addCodecSpecificData(data, size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700501 }
502 }
503
James Dong17299ab2010-05-14 15:45:22 -0700504 int32_t bitRate = 0;
505 if (mIsEncoder) {
506 CHECK(meta->findInt32(kKeyBitRate, &bitRate));
507 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700508 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700509 setAMRFormat(false /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700510 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700511 setAMRFormat(true /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700512 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700513 int32_t numChannels, sampleRate;
514 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
515 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
516
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -0500517 status_t err = setAACFormat(numChannels, sampleRate, bitRate);
518 if (err != OK) {
519 CODEC_LOGE("setAACFormat() failed (err = %d)", err);
520 return err;
521 }
Andreas Huber4b3913a2011-05-11 14:13:42 -0700522 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
523 || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
524 // These are PCM-like formats with a fixed sample rate but
525 // a variable number of channels.
526
527 int32_t numChannels;
528 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
529
530 setG711Format(numChannels);
Andreas Huberbe06d262009-08-14 14:37:10 -0700531 }
James Dongabed93a2010-04-22 17:27:04 -0700532
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700533 if (!strncasecmp(mMIME, "video/", 6)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700534
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700535 if (mIsEncoder) {
James Dong1244eab2010-06-08 11:58:53 -0700536 setVideoInputFormat(mMIME, meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700537 } else {
James Dong1244eab2010-06-08 11:58:53 -0700538 int32_t width, height;
539 bool success = meta->findInt32(kKeyWidth, &width);
540 success = success && meta->findInt32(kKeyHeight, &height);
541 CHECK(success);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700542 status_t err = setVideoOutputFormat(
543 mMIME, width, height);
544
545 if (err != OK) {
546 return err;
547 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700548 }
549 }
Andreas Hubera4357ad2010-04-02 12:49:54 -0700550
Andreas Huberda050cf22009-09-02 14:01:43 -0700551 int32_t maxInputSize;
Andreas Huber1bceff92009-11-23 14:03:32 -0800552 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700553 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
Andreas Huberda050cf22009-09-02 14:01:43 -0700554 }
555
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700556 initOutputFormat(meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700557
Andreas Huber42fb5d62011-06-29 15:53:28 -0700558 if ((mFlags & kClientNeedsFramebuffer)
Andreas Huber5a40e392010-10-18 09:57:42 -0700559 && !strncmp(mComponentName, "OMX.SEC.", 8)) {
560 OMX_INDEXTYPE index;
561
562 status_t err =
563 mOMX->getExtensionIndex(
564 mNode,
565 "OMX.SEC.index.ThumbnailMode",
566 &index);
567
568 if (err != OK) {
569 return err;
570 }
571
572 OMX_BOOL enable = OMX_TRUE;
573 err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
574
575 if (err != OK) {
576 CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
577 "returned error 0x%08x", err);
578
579 return err;
580 }
581
582 mQuirks &= ~kOutputBuffersAreUnreadable;
583 }
584
Jamie Gennisdbfb32e2010-10-20 15:53:59 -0700585 if (mNativeWindow != NULL
586 && !mIsEncoder
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700587 && !strncasecmp(mMIME, "video/", 6)
588 && !strncmp(mComponentName, "OMX.", 4)) {
589 status_t err = initNativeWindow();
590 if (err != OK) {
591 return err;
592 }
593 }
594
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700595 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700596}
597
Andreas Huberda050cf22009-09-02 14:01:43 -0700598void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
599 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700600 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700601 def.nPortIndex = portIndex;
602
Andreas Huber784202e2009-10-15 13:46:54 -0700603 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700604 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800605 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -0700606
Andreas Huberb8de9572010-02-22 14:58:45 -0800607 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
608 || (def.nBufferSize < size)) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700609 def.nBufferSize = size;
Andreas Huberda050cf22009-09-02 14:01:43 -0700610 }
611
Andreas Huber784202e2009-10-15 13:46:54 -0700612 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700613 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800614 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800615
616 err = mOMX->getParameter(
617 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800618 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800619
620 // Make sure the setting actually stuck.
Andreas Huberb8de9572010-02-22 14:58:45 -0800621 if (portIndex == kPortIndexInput
622 && (mQuirks & kInputBufferSizesAreBogus)) {
623 CHECK_EQ(def.nBufferSize, size);
624 } else {
625 CHECK(def.nBufferSize >= size);
626 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700627}
628
Andreas Huberbe06d262009-08-14 14:37:10 -0700629status_t OMXCodec::setVideoPortFormatType(
630 OMX_U32 portIndex,
631 OMX_VIDEO_CODINGTYPE compressionFormat,
632 OMX_COLOR_FORMATTYPE colorFormat) {
633 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700634 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700635 format.nPortIndex = portIndex;
636 format.nIndex = 0;
637 bool found = false;
638
639 OMX_U32 index = 0;
640 for (;;) {
641 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700642 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700643 mNode, OMX_IndexParamVideoPortFormat,
644 &format, sizeof(format));
645
646 if (err != OK) {
647 return err;
648 }
649
650 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700651 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700652
653#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700654 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700655 portIndex,
656 index, format.eCompressionFormat, format.eColorFormat);
657#endif
658
Andreas Huberbe06d262009-08-14 14:37:10 -0700659 if (format.eCompressionFormat == compressionFormat
Pannag Sanketi557b7092011-08-18 21:53:02 -0700660 && format.eColorFormat == colorFormat) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700661 found = true;
662 break;
663 }
664
665 ++index;
James Dong5a37afa2011-10-18 16:21:52 -0700666 if (index >= kMaxColorFormatSupported) {
667 CODEC_LOGE("color format %d or compression format %d is not supported",
668 colorFormat, compressionFormat);
669 return UNKNOWN_ERROR;
670 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700671 }
672
673 if (!found) {
674 return UNKNOWN_ERROR;
675 }
676
Andreas Huber53a76bd2009-10-06 16:20:44 -0700677 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700678 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700679 mNode, OMX_IndexParamVideoPortFormat,
680 &format, sizeof(format));
681
682 return err;
683}
684
Andreas Huberb482ce82009-10-29 12:02:48 -0700685static size_t getFrameSize(
686 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
687 switch (colorFormat) {
688 case OMX_COLOR_FormatYCbYCr:
689 case OMX_COLOR_FormatCbYCrY:
690 return width * height * 2;
691
Andreas Huber71c27d92010-03-19 11:43:15 -0700692 case OMX_COLOR_FormatYUV420Planar:
Andreas Huberb482ce82009-10-29 12:02:48 -0700693 case OMX_COLOR_FormatYUV420SemiPlanar:
Dandawate Sakete641dc52011-07-11 19:12:57 -0700694 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
Pannag Sanketi557b7092011-08-18 21:53:02 -0700695 /*
696 * FIXME: For the Opaque color format, the frame size does not
697 * need to be (w*h*3)/2. It just needs to
698 * be larger than certain minimum buffer size. However,
699 * currently, this opaque foramt has been tested only on
700 * YUV420 formats. If that is changed, then we need to revisit
701 * this part in the future
702 */
703 case OMX_COLOR_FormatAndroidOpaque:
Andreas Huberb482ce82009-10-29 12:02:48 -0700704 return (width * height * 3) / 2;
705
706 default:
707 CHECK(!"Should not be here. Unsupported color format.");
708 break;
709 }
710}
711
James Dongafd97e82010-08-03 17:19:23 -0700712status_t OMXCodec::findTargetColorFormat(
713 const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat) {
Steve Block71f2cf12011-10-20 11:56:00 +0100714 ALOGV("findTargetColorFormat");
James Dongafd97e82010-08-03 17:19:23 -0700715 CHECK(mIsEncoder);
716
717 *colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
718 int32_t targetColorFormat;
719 if (meta->findInt32(kKeyColorFormat, &targetColorFormat)) {
720 *colorFormat = (OMX_COLOR_FORMATTYPE) targetColorFormat;
James Dongafd97e82010-08-03 17:19:23 -0700721 }
722
723 // Check whether the target color format is supported.
724 return isColorFormatSupported(*colorFormat, kPortIndexInput);
725}
726
727status_t OMXCodec::isColorFormatSupported(
728 OMX_COLOR_FORMATTYPE colorFormat, int portIndex) {
Steve Block71f2cf12011-10-20 11:56:00 +0100729 ALOGV("isColorFormatSupported: %d", static_cast<int>(colorFormat));
James Dongafd97e82010-08-03 17:19:23 -0700730
731 // Enumerate all the color formats supported by
732 // the omx component to see whether the given
733 // color format is supported.
734 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
735 InitOMXParams(&portFormat);
736 portFormat.nPortIndex = portIndex;
737 OMX_U32 index = 0;
738 portFormat.nIndex = index;
739 while (true) {
740 if (OMX_ErrorNone != mOMX->getParameter(
741 mNode, OMX_IndexParamVideoPortFormat,
742 &portFormat, sizeof(portFormat))) {
James Dongb5024da2010-09-13 16:30:51 -0700743 break;
James Dongafd97e82010-08-03 17:19:23 -0700744 }
745 // Make sure that omx component does not overwrite
746 // the incremented index (bug 2897413).
747 CHECK_EQ(index, portFormat.nIndex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700748 if (portFormat.eColorFormat == colorFormat) {
James Dong5a37afa2011-10-18 16:21:52 -0700749 CODEC_LOGV("Found supported color format: %d", portFormat.eColorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700750 return OK; // colorFormat is supported!
751 }
752 ++index;
753 portFormat.nIndex = index;
754
James Dong5a37afa2011-10-18 16:21:52 -0700755 if (index >= kMaxColorFormatSupported) {
756 CODEC_LOGE("More than %ld color formats are supported???", index);
James Dongafd97e82010-08-03 17:19:23 -0700757 break;
758 }
759 }
James Dongb5024da2010-09-13 16:30:51 -0700760
James Dong5a37afa2011-10-18 16:21:52 -0700761 CODEC_LOGE("color format %d is not supported", colorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700762 return UNKNOWN_ERROR;
763}
764
Andreas Huberbe06d262009-08-14 14:37:10 -0700765void OMXCodec::setVideoInputFormat(
James Dong1244eab2010-06-08 11:58:53 -0700766 const char *mime, const sp<MetaData>& meta) {
767
768 int32_t width, height, frameRate, bitRate, stride, sliceHeight;
769 bool success = meta->findInt32(kKeyWidth, &width);
770 success = success && meta->findInt32(kKeyHeight, &height);
James Dongaac193c2010-11-10 20:43:53 -0800771 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -0700772 success = success && meta->findInt32(kKeyBitRate, &bitRate);
773 success = success && meta->findInt32(kKeyStride, &stride);
774 success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
775 CHECK(success);
776 CHECK(stride != 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700777
778 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700779 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700780 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700781 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700782 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700783 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700784 compressionFormat = OMX_VIDEO_CodingH263;
785 } else {
Steve Block3762c312012-01-06 19:20:56 +0000786 ALOGE("Not a supported video mime type: %s", mime);
Andreas Huberbe06d262009-08-14 14:37:10 -0700787 CHECK(!"Should not be here. Not a supported video mime type.");
788 }
789
James Dongafd97e82010-08-03 17:19:23 -0700790 OMX_COLOR_FORMATTYPE colorFormat;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800791 CHECK_EQ((status_t)OK, findTargetColorFormat(meta, &colorFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -0700792
James Dongb00e2462010-04-26 17:48:26 -0700793 status_t err;
794 OMX_PARAM_PORTDEFINITIONTYPE def;
795 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
796
797 //////////////////////// Input port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700798 CHECK_EQ(setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -0700799 kPortIndexInput, OMX_VIDEO_CodingUnused,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800800 colorFormat), (status_t)OK);
James Dong4f501f02010-06-07 14:41:41 -0700801
James Dongb00e2462010-04-26 17:48:26 -0700802 InitOMXParams(&def);
803 def.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -0700804
James Dongb00e2462010-04-26 17:48:26 -0700805 err = mOMX->getParameter(
806 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800807 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -0700808
James Dong1244eab2010-06-08 11:58:53 -0700809 def.nBufferSize = getFrameSize(colorFormat,
810 stride > 0? stride: -stride, sliceHeight);
James Dongb00e2462010-04-26 17:48:26 -0700811
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800812 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
James Dongb00e2462010-04-26 17:48:26 -0700813
814 video_def->nFrameWidth = width;
815 video_def->nFrameHeight = height;
James Dong1244eab2010-06-08 11:58:53 -0700816 video_def->nStride = stride;
817 video_def->nSliceHeight = sliceHeight;
James Dong4f501f02010-06-07 14:41:41 -0700818 video_def->xFramerate = (frameRate << 16); // Q16 format
James Dongb00e2462010-04-26 17:48:26 -0700819 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
820 video_def->eColorFormat = colorFormat;
821
James Dongb00e2462010-04-26 17:48:26 -0700822 err = mOMX->setParameter(
823 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800824 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -0700825
826 //////////////////////// Output port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700827 CHECK_EQ(setVideoPortFormatType(
828 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800829 (status_t)OK);
Andreas Huber4c483422009-09-02 16:05:36 -0700830 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700831 def.nPortIndex = kPortIndexOutput;
832
James Dongb00e2462010-04-26 17:48:26 -0700833 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700834 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
835
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800836 CHECK_EQ(err, (status_t)OK);
837 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -0700838
839 video_def->nFrameWidth = width;
840 video_def->nFrameHeight = height;
James Dong81c929a2010-07-01 15:02:14 -0700841 video_def->xFramerate = 0; // No need for output port
James Dong4f501f02010-06-07 14:41:41 -0700842 video_def->nBitrate = bitRate; // Q16 format
Andreas Huberbe06d262009-08-14 14:37:10 -0700843 video_def->eCompressionFormat = compressionFormat;
844 video_def->eColorFormat = OMX_COLOR_FormatUnused;
James Dong90862e22010-08-26 19:12:59 -0700845 if (mQuirks & kRequiresLargerEncoderOutputBuffer) {
846 // Increases the output buffer size
847 def.nBufferSize = ((def.nBufferSize * 3) >> 1);
848 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700849
Andreas Huber784202e2009-10-15 13:46:54 -0700850 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700851 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800852 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700853
James Dongb00e2462010-04-26 17:48:26 -0700854 /////////////////// Codec-specific ////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700855 switch (compressionFormat) {
856 case OMX_VIDEO_CodingMPEG4:
857 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800858 CHECK_EQ(setupMPEG4EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -0700859 break;
860 }
861
862 case OMX_VIDEO_CodingH263:
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800863 CHECK_EQ(setupH263EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -0700864 break;
865
Andreas Huberea6a38c2009-11-16 15:43:38 -0800866 case OMX_VIDEO_CodingAVC:
867 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800868 CHECK_EQ(setupAVCEncoderParameters(meta), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -0800869 break;
870 }
871
Andreas Huberb482ce82009-10-29 12:02:48 -0700872 default:
873 CHECK(!"Support for this compressionFormat to be implemented.");
874 break;
875 }
876}
877
James Dong1244eab2010-06-08 11:58:53 -0700878static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
879 if (iFramesInterval < 0) {
880 return 0xFFFFFFFF;
881 } else if (iFramesInterval == 0) {
882 return 0;
883 }
884 OMX_U32 ret = frameRate * iFramesInterval;
885 CHECK(ret > 1);
886 return ret;
887}
888
James Dongc0ab2a62010-06-29 16:29:19 -0700889status_t OMXCodec::setupErrorCorrectionParameters() {
890 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
891 InitOMXParams(&errorCorrectionType);
892 errorCorrectionType.nPortIndex = kPortIndexOutput;
893
894 status_t err = mOMX->getParameter(
895 mNode, OMX_IndexParamVideoErrorCorrection,
896 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -0700897 if (err != OK) {
Steve Block8564c8d2012-01-05 23:22:43 +0000898 ALOGW("Error correction param query is not supported");
James Dong903fc222010-09-22 17:37:42 -0700899 return OK; // Optional feature. Ignore this failure
900 }
James Dongc0ab2a62010-06-29 16:29:19 -0700901
902 errorCorrectionType.bEnableHEC = OMX_FALSE;
903 errorCorrectionType.bEnableResync = OMX_TRUE;
904 errorCorrectionType.nResynchMarkerSpacing = 256;
905 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
906 errorCorrectionType.bEnableRVLC = OMX_FALSE;
907
908 err = mOMX->setParameter(
909 mNode, OMX_IndexParamVideoErrorCorrection,
910 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -0700911 if (err != OK) {
Steve Block8564c8d2012-01-05 23:22:43 +0000912 ALOGW("Error correction param configuration is not supported");
James Dong903fc222010-09-22 17:37:42 -0700913 }
914
915 // Optional feature. Ignore the failure.
James Dongc0ab2a62010-06-29 16:29:19 -0700916 return OK;
917}
918
919status_t OMXCodec::setupBitRate(int32_t bitRate) {
920 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
921 InitOMXParams(&bitrateType);
922 bitrateType.nPortIndex = kPortIndexOutput;
923
924 status_t err = mOMX->getParameter(
925 mNode, OMX_IndexParamVideoBitrate,
926 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800927 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -0700928
929 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
930 bitrateType.nTargetBitrate = bitRate;
931
932 err = mOMX->setParameter(
933 mNode, OMX_IndexParamVideoBitrate,
934 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800935 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -0700936 return OK;
937}
938
James Dong81c929a2010-07-01 15:02:14 -0700939status_t OMXCodec::getVideoProfileLevel(
940 const sp<MetaData>& meta,
941 const CodecProfileLevel& defaultProfileLevel,
942 CodecProfileLevel &profileLevel) {
943 CODEC_LOGV("Default profile: %ld, level %ld",
944 defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
945
946 // Are the default profile and level overwriten?
947 int32_t profile, level;
948 if (!meta->findInt32(kKeyVideoProfile, &profile)) {
949 profile = defaultProfileLevel.mProfile;
950 }
951 if (!meta->findInt32(kKeyVideoLevel, &level)) {
952 level = defaultProfileLevel.mLevel;
953 }
954 CODEC_LOGV("Target profile: %d, level: %d", profile, level);
955
956 // Are the target profile and level supported by the encoder?
957 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
958 InitOMXParams(&param);
959 param.nPortIndex = kPortIndexOutput;
960 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
961 status_t err = mOMX->getParameter(
962 mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
963 &param, sizeof(param));
964
James Dongdfb89912010-09-15 21:07:52 -0700965 if (err != OK) break;
James Dong81c929a2010-07-01 15:02:14 -0700966
967 int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
968 int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
James Dong929642e2010-07-08 11:16:11 -0700969 CODEC_LOGV("Supported profile: %d, level %d",
James Dong81c929a2010-07-01 15:02:14 -0700970 supportedProfile, supportedLevel);
971
972 if (profile == supportedProfile &&
James Dongdfb89912010-09-15 21:07:52 -0700973 level <= supportedLevel) {
974 // We can further check whether the level is a valid
975 // value; but we will leave that to the omx encoder component
976 // via OMX_SetParameter call.
James Dong81c929a2010-07-01 15:02:14 -0700977 profileLevel.mProfile = profile;
978 profileLevel.mLevel = level;
979 return OK;
980 }
981 }
982
983 CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
984 profile, level);
985 return BAD_VALUE;
986}
987
James Dongc0ab2a62010-06-29 16:29:19 -0700988status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
989 int32_t iFramesInterval, frameRate, bitRate;
990 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -0800991 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dongc0ab2a62010-06-29 16:29:19 -0700992 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
993 CHECK(success);
994 OMX_VIDEO_PARAM_H263TYPE h263type;
995 InitOMXParams(&h263type);
996 h263type.nPortIndex = kPortIndexOutput;
997
998 status_t err = mOMX->getParameter(
999 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001000 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001001
1002 h263type.nAllowedPictureTypes =
1003 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1004
1005 h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1006 if (h263type.nPFrames == 0) {
1007 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1008 }
1009 h263type.nBFrames = 0;
1010
James Dong81c929a2010-07-01 15:02:14 -07001011 // Check profile and level parameters
1012 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001013 defaultProfileLevel.mProfile = h263type.eProfile;
1014 defaultProfileLevel.mLevel = h263type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001015 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1016 if (err != OK) return err;
1017 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
1018 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
James Dongc0ab2a62010-06-29 16:29:19 -07001019
1020 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1021 h263type.bForceRoundingTypeToZero = OMX_FALSE;
1022 h263type.nPictureHeaderRepetition = 0;
1023 h263type.nGOBHeaderInterval = 0;
1024
1025 err = mOMX->setParameter(
1026 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001027 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001028
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001029 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1030 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001031
1032 return OK;
1033}
1034
James Dong1244eab2010-06-08 11:58:53 -07001035status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
1036 int32_t iFramesInterval, frameRate, bitRate;
1037 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001038 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001039 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1040 CHECK(success);
Andreas Huberb482ce82009-10-29 12:02:48 -07001041 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1042 InitOMXParams(&mpeg4type);
1043 mpeg4type.nPortIndex = kPortIndexOutput;
1044
1045 status_t err = mOMX->getParameter(
1046 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001047 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001048
1049 mpeg4type.nSliceHeaderSpacing = 0;
1050 mpeg4type.bSVH = OMX_FALSE;
1051 mpeg4type.bGov = OMX_FALSE;
1052
1053 mpeg4type.nAllowedPictureTypes =
1054 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1055
James Dong1244eab2010-06-08 11:58:53 -07001056 mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1057 if (mpeg4type.nPFrames == 0) {
1058 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1059 }
Andreas Huberb482ce82009-10-29 12:02:48 -07001060 mpeg4type.nBFrames = 0;
Andreas Huberb482ce82009-10-29 12:02:48 -07001061 mpeg4type.nIDCVLCThreshold = 0;
1062 mpeg4type.bACPred = OMX_TRUE;
1063 mpeg4type.nMaxPacketSize = 256;
1064 mpeg4type.nTimeIncRes = 1000;
1065 mpeg4type.nHeaderExtension = 0;
1066 mpeg4type.bReversibleVLC = OMX_FALSE;
1067
James Dong81c929a2010-07-01 15:02:14 -07001068 // Check profile and level parameters
1069 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001070 defaultProfileLevel.mProfile = mpeg4type.eProfile;
1071 defaultProfileLevel.mLevel = mpeg4type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001072 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1073 if (err != OK) return err;
1074 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
1075 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
Andreas Huberb482ce82009-10-29 12:02:48 -07001076
1077 err = mOMX->setParameter(
1078 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001079 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001080
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001081 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1082 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001083
1084 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07001085}
1086
James Dong1244eab2010-06-08 11:58:53 -07001087status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
1088 int32_t iFramesInterval, frameRate, bitRate;
1089 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001090 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001091 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1092 CHECK(success);
1093
Andreas Huberea6a38c2009-11-16 15:43:38 -08001094 OMX_VIDEO_PARAM_AVCTYPE h264type;
1095 InitOMXParams(&h264type);
1096 h264type.nPortIndex = kPortIndexOutput;
1097
1098 status_t err = mOMX->getParameter(
1099 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001100 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001101
1102 h264type.nAllowedPictureTypes =
1103 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1104
James Dong81c929a2010-07-01 15:02:14 -07001105 // Check profile and level parameters
1106 CodecProfileLevel defaultProfileLevel, profileLevel;
1107 defaultProfileLevel.mProfile = h264type.eProfile;
1108 defaultProfileLevel.mLevel = h264type.eLevel;
1109 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1110 if (err != OK) return err;
1111 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
1112 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
1113
Dandawate Sakete641dc52011-07-11 19:12:57 -07001114 // FIXME:
1115 // Remove the workaround after the work in done.
1116 if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
1117 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1118 }
1119
James Dong81c929a2010-07-01 15:02:14 -07001120 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
James Dongbe650872011-07-07 16:41:25 -07001121 h264type.nSliceHeaderSpacing = 0;
James Dong81c929a2010-07-01 15:02:14 -07001122 h264type.bUseHadamard = OMX_TRUE;
1123 h264type.nRefFrames = 1;
James Dongbe650872011-07-07 16:41:25 -07001124 h264type.nBFrames = 0;
1125 h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1126 if (h264type.nPFrames == 0) {
1127 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1128 }
James Dong81c929a2010-07-01 15:02:14 -07001129 h264type.nRefIdx10ActiveMinus1 = 0;
1130 h264type.nRefIdx11ActiveMinus1 = 0;
1131 h264type.bEntropyCodingCABAC = OMX_FALSE;
1132 h264type.bWeightedPPrediction = OMX_FALSE;
1133 h264type.bconstIpred = OMX_FALSE;
1134 h264type.bDirect8x8Inference = OMX_FALSE;
1135 h264type.bDirectSpatialTemporal = OMX_FALSE;
1136 h264type.nCabacInitIdc = 0;
1137 }
1138
1139 if (h264type.nBFrames != 0) {
1140 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1141 }
1142
Andreas Huberea6a38c2009-11-16 15:43:38 -08001143 h264type.bEnableUEP = OMX_FALSE;
1144 h264type.bEnableFMO = OMX_FALSE;
1145 h264type.bEnableASO = OMX_FALSE;
1146 h264type.bEnableRS = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001147 h264type.bFrameMBsOnly = OMX_TRUE;
1148 h264type.bMBAFF = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001149 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1150
pgudadhe9c305322010-07-26 13:59:29 -07001151 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
1152 h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1153 }
1154
Andreas Huberea6a38c2009-11-16 15:43:38 -08001155 err = mOMX->setParameter(
1156 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001157 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001158
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001159 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001160
1161 return OK;
1162}
1163
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001164status_t OMXCodec::setVideoOutputFormat(
Andreas Huberbe06d262009-08-14 14:37:10 -07001165 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -07001166 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001167
Andreas Huberbe06d262009-08-14 14:37:10 -07001168 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -07001169 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001170 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -07001171 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001172 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -07001173 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001174 compressionFormat = OMX_VIDEO_CodingH263;
Andreas Huber4b3913a2011-05-11 14:13:42 -07001175 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1176 compressionFormat = OMX_VIDEO_CodingVPX;
Andreas Hubereb2f9c12011-05-19 08:37:39 -07001177 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1178 compressionFormat = OMX_VIDEO_CodingMPEG2;
Andreas Huberbe06d262009-08-14 14:37:10 -07001179 } else {
Steve Block3762c312012-01-06 19:20:56 +00001180 ALOGE("Not a supported video mime type: %s", mime);
Andreas Huberbe06d262009-08-14 14:37:10 -07001181 CHECK(!"Should not be here. Not a supported video mime type.");
1182 }
1183
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001184 status_t err = setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -07001185 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1186
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001187 if (err != OK) {
1188 return err;
1189 }
1190
Andreas Huberbe06d262009-08-14 14:37:10 -07001191#if 1
1192 {
1193 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -07001194 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -07001195 format.nPortIndex = kPortIndexOutput;
1196 format.nIndex = 0;
1197
Andreas Huber784202e2009-10-15 13:46:54 -07001198 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001199 mNode, OMX_IndexParamVideoPortFormat,
1200 &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001201 CHECK_EQ(err, (status_t)OK);
1202 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07001203
Andreas Huberbe06d262009-08-14 14:37:10 -07001204 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1205 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1206 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
Anu Sundararajand35df442011-06-22 12:24:46 -05001207 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
Andreas Huberbe06d262009-08-14 14:37:10 -07001208 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1209
Andreas Huber784202e2009-10-15 13:46:54 -07001210 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001211 mNode, OMX_IndexParamVideoPortFormat,
1212 &format, sizeof(format));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001213
1214 if (err != OK) {
1215 return err;
1216 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001217 }
1218#endif
1219
1220 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001221 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001222 def.nPortIndex = kPortIndexInput;
1223
Andreas Huber4c483422009-09-02 16:05:36 -07001224 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1225
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001226 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001227 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1228
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001229 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001230
1231#if 1
1232 // XXX Need a (much) better heuristic to compute input buffer sizes.
1233 const size_t X = 64 * 1024;
1234 if (def.nBufferSize < X) {
1235 def.nBufferSize = X;
1236 }
1237#endif
1238
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001239 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001240
1241 video_def->nFrameWidth = width;
1242 video_def->nFrameHeight = height;
1243
Andreas Huberb482ce82009-10-29 12:02:48 -07001244 video_def->eCompressionFormat = compressionFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -07001245 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1246
Andreas Huber784202e2009-10-15 13:46:54 -07001247 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001248 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001249
1250 if (err != OK) {
1251 return err;
1252 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001253
1254 ////////////////////////////////////////////////////////////////////////////
1255
Andreas Huber4c483422009-09-02 16:05:36 -07001256 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001257 def.nPortIndex = kPortIndexOutput;
1258
Andreas Huber784202e2009-10-15 13:46:54 -07001259 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001260 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001261 CHECK_EQ(err, (status_t)OK);
1262 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001263
1264#if 0
1265 def.nBufferSize =
1266 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
1267#endif
1268
1269 video_def->nFrameWidth = width;
1270 video_def->nFrameHeight = height;
1271
Andreas Huber784202e2009-10-15 13:46:54 -07001272 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001273 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001274
1275 return err;
Andreas Huberbe06d262009-08-14 14:37:10 -07001276}
1277
Andreas Huberbe06d262009-08-14 14:37:10 -07001278OMXCodec::OMXCodec(
Andreas Huber42fb5d62011-06-29 15:53:28 -07001279 const sp<IOMX> &omx, IOMX::node_id node,
1280 uint32_t quirks, uint32_t flags,
Andreas Huberebf66ea2009-08-19 13:32:58 -07001281 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -07001282 const char *mime,
1283 const char *componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001284 const sp<MediaSource> &source,
1285 const sp<ANativeWindow> &nativeWindow)
Andreas Huberbe06d262009-08-14 14:37:10 -07001286 : mOMX(omx),
Andreas Huberf6b4ca42012-01-31 11:16:24 -08001287 mOMXLivesLocally(omx->livesLocally(node, getpid())),
Andreas Huberbe06d262009-08-14 14:37:10 -07001288 mNode(node),
1289 mQuirks(quirks),
Andreas Huber42fb5d62011-06-29 15:53:28 -07001290 mFlags(flags),
Andreas Huberbe06d262009-08-14 14:37:10 -07001291 mIsEncoder(isEncoder),
Andreas Huberafe02df2012-01-26 14:39:50 -08001292 mIsVideo(!strncasecmp("video/", mime, 6)),
Andreas Huberbe06d262009-08-14 14:37:10 -07001293 mMIME(strdup(mime)),
1294 mComponentName(strdup(componentName)),
1295 mSource(source),
1296 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -07001297 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -07001298 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -07001299 mSignalledEOS(false),
1300 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -07001301 mOutputPortSettingsHaveChanged(false),
Andreas Hubera4357ad2010-04-02 12:49:54 -07001302 mSeekTimeUs(-1),
Andreas Huber6624c9f2010-07-20 15:04:28 -07001303 mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
1304 mTargetTimeUs(-1),
Andreas Huberb9289832011-02-08 13:10:25 -08001305 mOutputPortSettingsChangedPending(false),
Andreas Huber1f24b302010-06-10 11:12:39 -07001306 mLeftOverBuffer(NULL),
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001307 mPaused(false),
Andreas Huberbc554952011-09-08 14:12:44 -07001308 mNativeWindow(
1309 (!strncmp(componentName, "OMX.google.", 11)
1310 || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode"))
Andreas Huber4b3913a2011-05-11 14:13:42 -07001311 ? NULL : nativeWindow) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001312 mPortStatus[kPortIndexInput] = ENABLED;
1313 mPortStatus[kPortIndexOutput] = ENABLED;
1314
Andreas Huber4c483422009-09-02 16:05:36 -07001315 setComponentRole();
1316}
1317
Andreas Hubere6c40962009-09-10 14:13:30 -07001318// static
1319void OMXCodec::setComponentRole(
1320 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1321 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -07001322 struct MimeToRole {
1323 const char *mime;
1324 const char *decoderRole;
1325 const char *encoderRole;
1326 };
1327
1328 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -07001329 { MEDIA_MIMETYPE_AUDIO_MPEG,
1330 "audio_decoder.mp3", "audio_encoder.mp3" },
Andreas Huberbc554952011-09-08 14:12:44 -07001331 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1332 "audio_decoder.mp1", "audio_encoder.mp1" },
1333 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1334 "audio_decoder.mp2", "audio_encoder.mp2" },
1335 { MEDIA_MIMETYPE_AUDIO_MPEG,
1336 "audio_decoder.mp3", "audio_encoder.mp3" },
Andreas Hubere6c40962009-09-10 14:13:30 -07001337 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1338 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1339 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1340 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1341 { MEDIA_MIMETYPE_AUDIO_AAC,
1342 "audio_decoder.aac", "audio_encoder.aac" },
Andreas Huber3e408f32011-09-28 12:37:36 -07001343 { MEDIA_MIMETYPE_AUDIO_VORBIS,
1344 "audio_decoder.vorbis", "audio_encoder.vorbis" },
Andreas Hubere6c40962009-09-10 14:13:30 -07001345 { MEDIA_MIMETYPE_VIDEO_AVC,
1346 "video_decoder.avc", "video_encoder.avc" },
1347 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1348 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1349 { MEDIA_MIMETYPE_VIDEO_H263,
1350 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber88572f72012-02-21 11:47:18 -08001351 { MEDIA_MIMETYPE_VIDEO_VPX,
1352 "video_decoder.vpx", "video_encoder.vpx" },
Andreas Huber4c483422009-09-02 16:05:36 -07001353 };
1354
1355 static const size_t kNumMimeToRole =
1356 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1357
1358 size_t i;
1359 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001360 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001361 break;
1362 }
1363 }
1364
1365 if (i == kNumMimeToRole) {
1366 return;
1367 }
1368
1369 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -07001370 isEncoder ? kMimeToRole[i].encoderRole
1371 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -07001372
1373 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -07001374 OMX_PARAM_COMPONENTROLETYPE roleParams;
1375 InitOMXParams(&roleParams);
1376
1377 strncpy((char *)roleParams.cRole,
1378 role, OMX_MAX_STRINGNAME_SIZE - 1);
1379
1380 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1381
Andreas Huber784202e2009-10-15 13:46:54 -07001382 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07001383 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -07001384 &roleParams, sizeof(roleParams));
1385
1386 if (err != OK) {
Steve Block8564c8d2012-01-05 23:22:43 +00001387 ALOGW("Failed to set standard component role '%s'.", role);
Andreas Huber4c483422009-09-02 16:05:36 -07001388 }
1389 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001390}
1391
Andreas Hubere6c40962009-09-10 14:13:30 -07001392void OMXCodec::setComponentRole() {
1393 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1394}
1395
Andreas Huberbe06d262009-08-14 14:37:10 -07001396OMXCodec::~OMXCodec() {
Andreas Huberf98197a2010-09-17 11:49:39 -07001397 mSource.clear();
1398
Andreas Hubereec06d32011-01-06 10:26:36 -08001399 CHECK(mState == LOADED || mState == ERROR || mState == LOADED_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001400
Andreas Huber784202e2009-10-15 13:46:54 -07001401 status_t err = mOMX->freeNode(mNode);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001402 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001403
1404 mNode = NULL;
1405 setState(DEAD);
1406
1407 clearCodecSpecificData();
1408
1409 free(mComponentName);
1410 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001411
Andreas Huberbe06d262009-08-14 14:37:10 -07001412 free(mMIME);
1413 mMIME = NULL;
1414}
1415
1416status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -07001417 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -07001418
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001419 CHECK_EQ((int)mState, (int)LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07001420
1421 status_t err;
1422 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001423 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001424 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001425 setState(LOADED_TO_IDLE);
1426 }
1427
1428 err = allocateBuffers();
Jamie Gennisfd8b75a2010-12-17 15:07:02 -08001429 if (err != (status_t)OK) {
1430 return err;
1431 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001432
1433 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -07001434 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001435 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001436
1437 setState(LOADED_TO_IDLE);
1438 }
1439
1440 while (mState != EXECUTING && mState != ERROR) {
1441 mAsyncCompletion.wait(mLock);
1442 }
1443
1444 return mState == ERROR ? UNKNOWN_ERROR : OK;
1445}
1446
1447// static
1448bool OMXCodec::isIntermediateState(State state) {
1449 return state == LOADED_TO_IDLE
1450 || state == IDLE_TO_EXECUTING
1451 || state == EXECUTING_TO_IDLE
1452 || state == IDLE_TO_LOADED
1453 || state == RECONFIGURING;
1454}
1455
1456status_t OMXCodec::allocateBuffers() {
1457 status_t err = allocateBuffersOnPort(kPortIndexInput);
1458
1459 if (err != OK) {
1460 return err;
1461 }
1462
1463 return allocateBuffersOnPort(kPortIndexOutput);
1464}
1465
1466status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
Jamie Gennisdbfb32e2010-10-20 15:53:59 -07001467 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001468 return allocateOutputBuffersFromNativeWindow();
1469 }
1470
Andreas Huber42fb5d62011-06-29 15:53:28 -07001471 if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
Steve Block3762c312012-01-06 19:20:56 +00001472 ALOGE("protected output buffers must be stent to an ANativeWindow");
Jamie Gennis66380f72011-04-07 19:03:56 -07001473 return PERMISSION_DENIED;
1474 }
1475
James Dong7d6143a2011-06-08 10:35:19 -07001476 status_t err = OK;
Andreas Huber42fb5d62011-06-29 15:53:28 -07001477 if ((mFlags & kStoreMetaDataInVideoBuffers)
1478 && portIndex == kPortIndexInput) {
James Dong05c2fd52010-11-02 13:20:11 -07001479 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1480 if (err != OK) {
Steve Block3762c312012-01-06 19:20:56 +00001481 ALOGE("Storing meta data in video buffers is not supported");
James Dong05c2fd52010-11-02 13:20:11 -07001482 return err;
1483 }
1484 }
1485
James Dong7d6143a2011-06-08 10:35:19 -07001486 OMX_PARAM_PORTDEFINITIONTYPE def;
1487 InitOMXParams(&def);
1488 def.nPortIndex = portIndex;
1489
1490 err = mOMX->getParameter(
1491 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1492
1493 if (err != OK) {
1494 return err;
1495 }
1496
Andreas Huber262d7e82011-09-27 15:05:40 -07001497 CODEC_LOGV("allocating %lu buffers of size %lu on %s port",
Andreas Huber57648e42010-08-04 10:14:30 -07001498 def.nBufferCountActual, def.nBufferSize,
1499 portIndex == kPortIndexInput ? "input" : "output");
1500
Andreas Huber5c0a9132009-08-20 11:16:40 -07001501 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
Mathias Agopian6faf7892010-01-25 19:00:00 -08001502 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
Andreas Huber5c0a9132009-08-20 11:16:40 -07001503
Andreas Huberbe06d262009-08-14 14:37:10 -07001504 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -07001505 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07001506 CHECK(mem.get() != NULL);
1507
Andreas Huberc712b9f2010-01-20 15:05:46 -08001508 BufferInfo info;
1509 info.mData = NULL;
1510 info.mSize = def.nBufferSize;
1511
Andreas Huberbe06d262009-08-14 14:37:10 -07001512 IOMX::buffer_id buffer;
1513 if (portIndex == kPortIndexInput
Andreas Huber42fb5d62011-06-29 15:53:28 -07001514 && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
1515 || (mFlags & kUseSecureInputBuffers))) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001516 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001517 mem.clear();
1518
Andreas Huberf1fe0642010-01-15 15:28:19 -08001519 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001520 mNode, portIndex, def.nBufferSize, &buffer,
1521 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001522 } else {
1523 err = mOMX->allocateBufferWithBackup(
1524 mNode, portIndex, mem, &buffer);
1525 }
Andreas Huber446f44f2009-08-25 17:23:44 -07001526 } else if (portIndex == kPortIndexOutput
1527 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001528 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001529 mem.clear();
1530
Andreas Huberf1fe0642010-01-15 15:28:19 -08001531 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001532 mNode, portIndex, def.nBufferSize, &buffer,
1533 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001534 } else {
1535 err = mOMX->allocateBufferWithBackup(
1536 mNode, portIndex, mem, &buffer);
1537 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001538 } else {
Andreas Huber784202e2009-10-15 13:46:54 -07001539 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001540 }
1541
1542 if (err != OK) {
Steve Block3762c312012-01-06 19:20:56 +00001543 ALOGE("allocate_buffer_with_backup failed");
Andreas Huberbe06d262009-08-14 14:37:10 -07001544 return err;
1545 }
1546
Andreas Huberc712b9f2010-01-20 15:05:46 -08001547 if (mem != NULL) {
1548 info.mData = mem->pointer();
1549 }
1550
Andreas Huberbe06d262009-08-14 14:37:10 -07001551 info.mBuffer = buffer;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001552 info.mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07001553 info.mMem = mem;
1554 info.mMediaBuffer = NULL;
1555
1556 if (portIndex == kPortIndexOutput) {
Andreas Huber52733b82010-01-25 10:41:35 -08001557 if (!(mOMXLivesLocally
1558 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1559 && (mQuirks & kDefersOutputBufferAllocation))) {
1560 // If the node does not fill in the buffer ptr at this time,
1561 // we will defer creating the MediaBuffer until receiving
1562 // the first FILL_BUFFER_DONE notification instead.
1563 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1564 info.mMediaBuffer->setObserver(this);
1565 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001566 }
1567
1568 mPortBuffers[portIndex].push(info);
1569
Andreas Huber4c483422009-09-02 16:05:36 -07001570 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -07001571 portIndex == kPortIndexInput ? "input" : "output");
1572 }
1573
Andreas Huber2ea14e22009-12-16 09:30:55 -08001574 // dumpPortStatus(portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001575
Andreas Huber42fb5d62011-06-29 15:53:28 -07001576 if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
1577 Vector<MediaBuffer *> buffers;
1578 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
1579 const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);
1580
1581 MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
1582 buffers.push(mbuf);
1583 }
1584
1585 status_t err = mSource->setBuffers(buffers);
1586
1587 if (err != OK) {
1588 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
1589 buffers.editItemAt(i)->release();
1590 }
1591 buffers.clear();
1592
1593 CODEC_LOGE(
1594 "Codec requested to use secure input buffers but "
1595 "upstream source didn't support that.");
1596
1597 return err;
1598 }
1599 }
1600
Andreas Huberbe06d262009-08-14 14:37:10 -07001601 return OK;
1602}
1603
Andreas Huber5e9dc942011-01-21 14:32:31 -08001604status_t OMXCodec::applyRotation() {
1605 sp<MetaData> meta = mSource->getFormat();
1606
1607 int32_t rotationDegrees;
1608 if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
1609 rotationDegrees = 0;
1610 }
1611
1612 uint32_t transform;
1613 switch (rotationDegrees) {
1614 case 0: transform = 0; break;
1615 case 90: transform = HAL_TRANSFORM_ROT_90; break;
1616 case 180: transform = HAL_TRANSFORM_ROT_180; break;
1617 case 270: transform = HAL_TRANSFORM_ROT_270; break;
1618 default: transform = 0; break;
1619 }
1620
1621 status_t err = OK;
1622
1623 if (transform) {
1624 err = native_window_set_buffers_transform(
1625 mNativeWindow.get(), transform);
1626 }
1627
1628 return err;
1629}
1630
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001631status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
1632 // Get the number of buffers needed.
1633 OMX_PARAM_PORTDEFINITIONTYPE def;
1634 InitOMXParams(&def);
1635 def.nPortIndex = kPortIndexOutput;
1636
1637 status_t err = mOMX->getParameter(
1638 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1639 if (err != OK) {
1640 return err;
1641 }
1642
Mathias Agopianff86f372011-07-18 16:15:08 -07001643 err = native_window_set_scaling_mode(mNativeWindow.get(),
1644 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1645
1646 if (err != OK) {
1647 return err;
1648 }
1649
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001650 err = native_window_set_buffers_geometry(
1651 mNativeWindow.get(),
1652 def.format.video.nFrameWidth,
1653 def.format.video.nFrameHeight,
Jamie Gennis044ace62010-10-29 15:19:29 -07001654 def.format.video.eColorFormat);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001655
1656 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001657 ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001658 strerror(-err), -err);
1659 return err;
1660 }
1661
Andreas Huber5e9dc942011-01-21 14:32:31 -08001662 err = applyRotation();
1663 if (err != OK) {
1664 return err;
1665 }
1666
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001667 // Set up the native window.
Jamie Gennis94c59802011-02-24 12:48:17 -08001668 OMX_U32 usage = 0;
1669 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
1670 if (err != 0) {
Steve Block8564c8d2012-01-05 23:22:43 +00001671 ALOGW("querying usage flags from OMX IL component failed: %d", err);
Jamie Gennis94c59802011-02-24 12:48:17 -08001672 // XXX: Currently this error is logged, but not fatal.
1673 usage = 0;
1674 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07001675 if (mFlags & kEnableGrallocUsageProtected) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001676 usage |= GRALLOC_USAGE_PROTECTED;
1677 }
Jamie Gennis94c59802011-02-24 12:48:17 -08001678
Jamie Gennis66380f72011-04-07 19:03:56 -07001679 // Make sure to check whether either Stagefright or the video decoder
1680 // requested protected buffers.
1681 if (usage & GRALLOC_USAGE_PROTECTED) {
1682 // Verify that the ANativeWindow sends images directly to
1683 // SurfaceFlinger.
1684 int queuesToNativeWindow = 0;
1685 err = mNativeWindow->query(
1686 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
1687 &queuesToNativeWindow);
1688 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001689 ALOGE("error authenticating native window: %d", err);
Jamie Gennis66380f72011-04-07 19:03:56 -07001690 return err;
1691 }
1692 if (queuesToNativeWindow != 1) {
Steve Block3762c312012-01-06 19:20:56 +00001693 ALOGE("native window could not be authenticated");
Jamie Gennis66380f72011-04-07 19:03:56 -07001694 return PERMISSION_DENIED;
1695 }
1696 }
1697
Steve Block71f2cf12011-10-20 11:56:00 +01001698 ALOGV("native_window_set_usage usage=0x%lx", usage);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001699 err = native_window_set_usage(
Jamie Gennis94c59802011-02-24 12:48:17 -08001700 mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001701 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001702 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001703 return err;
1704 }
1705
Jamie Gennis01951fd2011-02-27 15:10:34 -08001706 int minUndequeuedBufs = 0;
1707 err = mNativeWindow->query(mNativeWindow.get(),
1708 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
1709 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001710 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
Jamie Gennis01951fd2011-02-27 15:10:34 -08001711 strerror(-err), -err);
1712 return err;
1713 }
1714
1715 // XXX: Is this the right logic to use? It's not clear to me what the OMX
1716 // buffer counts refer to - how do they account for the renderer holding on
1717 // to buffers?
1718 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
1719 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
1720 def.nBufferCountActual = newBufferCount;
1721 err = mOMX->setParameter(
1722 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1723 if (err != OK) {
1724 CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
1725 newBufferCount, err);
1726 return err;
1727 }
1728 }
1729
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001730 err = native_window_set_buffer_count(
1731 mNativeWindow.get(), def.nBufferCountActual);
1732 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001733 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001734 -err);
1735 return err;
1736 }
1737
Andreas Huber262d7e82011-09-27 15:05:40 -07001738 CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001739 "output port", def.nBufferCountActual, def.nBufferSize);
1740
1741 // Dequeue buffers and send them to OMX
Jamie Gennis42024642011-02-22 18:33:06 -08001742 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07001743 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001744 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
1745 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +00001746 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001747 break;
1748 }
1749
1750 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001751 BufferInfo info;
1752 info.mData = NULL;
1753 info.mSize = def.nBufferSize;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001754 info.mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001755 info.mMem = NULL;
1756 info.mMediaBuffer = new MediaBuffer(graphicBuffer);
1757 info.mMediaBuffer->setObserver(this);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001758 mPortBuffers[kPortIndexOutput].push(info);
Jamie Gennis42024642011-02-22 18:33:06 -08001759
1760 IOMX::buffer_id bufferId;
1761 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1762 &bufferId);
1763 if (err != 0) {
1764 CODEC_LOGE("registering GraphicBuffer with OMX IL component "
1765 "failed: %d", err);
1766 break;
1767 }
1768
1769 mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId;
1770
1771 CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
1772 bufferId, graphicBuffer.get());
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001773 }
1774
1775 OMX_U32 cancelStart;
1776 OMX_U32 cancelEnd;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001777 if (err != 0) {
1778 // If an error occurred while dequeuing we need to cancel any buffers
1779 // that were dequeued.
1780 cancelStart = 0;
Jamie Gennis42024642011-02-22 18:33:06 -08001781 cancelEnd = mPortBuffers[kPortIndexOutput].size();
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001782 } else {
1783 // Return the last two buffers to the native window.
Jamie Gennis01951fd2011-02-27 15:10:34 -08001784 cancelStart = def.nBufferCountActual - minUndequeuedBufs;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001785 cancelEnd = def.nBufferCountActual;
1786 }
1787
1788 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1789 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
1790 cancelBufferToNativeWindow(info);
1791 }
1792
1793 return err;
1794}
1795
1796status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08001797 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001798 CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
1799 int err = mNativeWindow->cancelBuffer(
1800 mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
1801 if (err != 0) {
1802 CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
1803
1804 setState(ERROR);
1805 return err;
1806 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08001807 info->mStatus = OWNED_BY_NATIVE_WINDOW;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001808 return OK;
1809}
1810
1811OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
1812 // Dequeue the next buffer from the native window.
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07001813 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001814 int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
1815 if (err != 0) {
1816 CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
1817
1818 setState(ERROR);
1819 return 0;
1820 }
1821
1822 // Determine which buffer we just dequeued.
1823 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1824 BufferInfo *bufInfo = 0;
1825 for (size_t i = 0; i < buffers->size(); i++) {
1826 sp<GraphicBuffer> graphicBuffer = buffers->itemAt(i).
1827 mMediaBuffer->graphicBuffer();
1828 if (graphicBuffer->handle == buf->handle) {
1829 bufInfo = &buffers->editItemAt(i);
1830 break;
1831 }
1832 }
1833
1834 if (bufInfo == 0) {
1835 CODEC_LOGE("dequeued unrecognized buffer: %p", buf);
1836
1837 setState(ERROR);
1838 return 0;
1839 }
1840
1841 // The native window no longer owns the buffer.
Andreas Huberbbbcf652010-12-07 14:25:54 -08001842 CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
1843 bufInfo->mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001844
1845 return bufInfo;
1846}
1847
Jamie Gennisc0e42932011-10-25 14:50:16 -07001848status_t OMXCodec::pushBlankBuffersToNativeWindow() {
1849 status_t err = NO_ERROR;
1850 ANativeWindowBuffer* anb = NULL;
1851 int numBufs = 0;
1852 int minUndequeuedBufs = 0;
1853
1854 // We need to reconnect to the ANativeWindow as a CPU client to ensure that
1855 // no frames get dropped by SurfaceFlinger assuming that these are video
1856 // frames.
1857 err = native_window_api_disconnect(mNativeWindow.get(),
1858 NATIVE_WINDOW_API_MEDIA);
1859 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001860 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001861 strerror(-err), -err);
1862 return err;
1863 }
1864
1865 err = native_window_api_connect(mNativeWindow.get(),
1866 NATIVE_WINDOW_API_CPU);
1867 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001868 ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001869 strerror(-err), -err);
1870 return err;
1871 }
1872
1873 err = native_window_set_scaling_mode(mNativeWindow.get(),
1874 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1875 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001876 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001877 strerror(-err), -err);
1878 goto error;
1879 }
1880
1881 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
1882 HAL_PIXEL_FORMAT_RGBX_8888);
1883 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001884 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001885 strerror(-err), -err);
1886 goto error;
1887 }
1888
1889 err = native_window_set_usage(mNativeWindow.get(),
1890 GRALLOC_USAGE_SW_WRITE_OFTEN);
1891 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001892 ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001893 strerror(-err), -err);
1894 goto error;
1895 }
1896
1897 err = mNativeWindow->query(mNativeWindow.get(),
1898 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
1899 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001900 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
Jamie Gennisc0e42932011-10-25 14:50:16 -07001901 "failed: %s (%d)", strerror(-err), -err);
1902 goto error;
1903 }
1904
1905 numBufs = minUndequeuedBufs + 1;
1906 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
1907 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001908 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001909 strerror(-err), -err);
1910 goto error;
1911 }
1912
1913 // We push numBufs + 1 buffers to ensure that we've drawn into the same
1914 // buffer twice. This should guarantee that the buffer has been displayed
1915 // on the screen and then been replaced, so an previous video frames are
1916 // guaranteed NOT to be currently displayed.
1917 for (int i = 0; i < numBufs + 1; i++) {
1918 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
1919 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001920 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001921 strerror(-err), -err);
1922 goto error;
1923 }
1924
1925 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
1926 err = mNativeWindow->lockBuffer(mNativeWindow.get(),
1927 buf->getNativeBuffer());
1928 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001929 ALOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001930 strerror(-err), -err);
1931 goto error;
1932 }
1933
1934 // Fill the buffer with the a 1x1 checkerboard pattern ;)
1935 uint32_t* img = NULL;
1936 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
1937 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001938 ALOGE("error pushing blank frames: lock failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001939 strerror(-err), -err);
1940 goto error;
1941 }
1942
1943 *img = 0;
1944
1945 err = buf->unlock();
1946 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001947 ALOGE("error pushing blank frames: unlock failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001948 strerror(-err), -err);
1949 goto error;
1950 }
1951
1952 err = mNativeWindow->queueBuffer(mNativeWindow.get(),
1953 buf->getNativeBuffer());
1954 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001955 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001956 strerror(-err), -err);
1957 goto error;
1958 }
1959
1960 anb = NULL;
1961 }
1962
1963error:
1964
1965 if (err != NO_ERROR) {
1966 // Clean up after an error.
1967 if (anb != NULL) {
1968 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
1969 }
1970
1971 native_window_api_disconnect(mNativeWindow.get(),
1972 NATIVE_WINDOW_API_CPU);
1973 native_window_api_connect(mNativeWindow.get(),
1974 NATIVE_WINDOW_API_MEDIA);
1975
1976 return err;
1977 } else {
1978 // Clean up after success.
1979 err = native_window_api_disconnect(mNativeWindow.get(),
1980 NATIVE_WINDOW_API_CPU);
1981 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001982 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001983 strerror(-err), -err);
1984 return err;
1985 }
1986
1987 err = native_window_api_connect(mNativeWindow.get(),
1988 NATIVE_WINDOW_API_MEDIA);
1989 if (err != NO_ERROR) {
Steve Block3762c312012-01-06 19:20:56 +00001990 ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
Jamie Gennisc0e42932011-10-25 14:50:16 -07001991 strerror(-err), -err);
1992 return err;
1993 }
1994
1995 return NO_ERROR;
1996 }
1997}
1998
James Dong72516732012-02-06 23:46:37 -08001999int64_t OMXCodec::getDecodingTimeUs() {
Andreas Huberafe02df2012-01-26 14:39:50 -08002000 CHECK(mIsEncoder && mIsVideo);
James Dong32bb368a52011-06-20 11:40:52 -07002001
2002 if (mDecodingTimeList.empty()) {
James Dong58c524e2011-08-30 17:06:10 -07002003 CHECK(mSignalledEOS || mNoMoreOutputData);
James Dong32bb368a52011-06-20 11:40:52 -07002004 // No corresponding input frame available.
2005 // This could happen when EOS is reached.
2006 return 0;
2007 }
2008
James Dong4108b1ed2011-06-07 19:45:54 -07002009 List<int64_t>::iterator it = mDecodingTimeList.begin();
2010 int64_t timeUs = *it;
James Dong72516732012-02-06 23:46:37 -08002011 mDecodingTimeList.erase(it);
James Dong4108b1ed2011-06-07 19:45:54 -07002012 return timeUs;
2013}
2014
Andreas Huberbe06d262009-08-14 14:37:10 -07002015void OMXCodec::on_message(const omx_message &msg) {
Andreas Huber3a28b022011-03-28 14:48:28 -07002016 if (mState == ERROR) {
Steve Block8564c8d2012-01-05 23:22:43 +00002017 ALOGW("Dropping OMX message - we're in ERROR state.");
Andreas Huber3a28b022011-03-28 14:48:28 -07002018 return;
2019 }
2020
Andreas Huberbe06d262009-08-14 14:37:10 -07002021 switch (msg.type) {
2022 case omx_message::EVENT:
2023 {
2024 onEvent(
2025 msg.u.event_data.event, msg.u.event_data.data1,
2026 msg.u.event_data.data2);
2027
2028 break;
2029 }
2030
2031 case omx_message::EMPTY_BUFFER_DONE:
2032 {
2033 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
2034
Andreas Huber4c483422009-09-02 16:05:36 -07002035 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002036
2037 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2038 size_t i = 0;
2039 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2040 ++i;
2041 }
2042
2043 CHECK(i < buffers->size());
Andreas Huberbbbcf652010-12-07 14:25:54 -08002044 if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
Steve Block8564c8d2012-01-05 23:22:43 +00002045 ALOGW("We already own input buffer %p, yet received "
Andreas Huberbe06d262009-08-14 14:37:10 -07002046 "an EMPTY_BUFFER_DONE.", buffer);
2047 }
2048
James Dong05c2fd52010-11-02 13:20:11 -07002049 BufferInfo* info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002050 info->mStatus = OWNED_BY_US;
James Dong05c2fd52010-11-02 13:20:11 -07002051
2052 // Buffer could not be released until empty buffer done is called.
2053 if (info->mMediaBuffer != NULL) {
James Dong31b9375f2010-11-10 21:11:41 -08002054 if (mIsEncoder &&
2055 (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2056 // If zero-copy mode is enabled this will send the
2057 // input buffer back to the upstream source.
2058 restorePatchedDataPointer(info);
2059 }
2060
James Dong05c2fd52010-11-02 13:20:11 -07002061 info->mMediaBuffer->release();
2062 info->mMediaBuffer = NULL;
2063 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002064
2065 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002066 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002067
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002068 status_t err = freeBuffer(kPortIndexInput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002069 CHECK_EQ(err, (status_t)OK);
Andreas Huber4a9375e2010-02-09 11:54:33 -08002070 } else if (mState != ERROR
2071 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002072 CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
Andreas Huber42fb5d62011-06-29 15:53:28 -07002073
2074 if (mFlags & kUseSecureInputBuffers) {
2075 drainAnyInputBuffer();
2076 } else {
2077 drainInputBuffer(&buffers->editItemAt(i));
2078 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002079 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002080 break;
2081 }
2082
2083 case omx_message::FILL_BUFFER_DONE:
2084 {
2085 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
2086 OMX_U32 flags = msg.u.extended_buffer_data.flags;
2087
Andreas Huber2ea14e22009-12-16 09:30:55 -08002088 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -07002089 buffer,
2090 msg.u.extended_buffer_data.range_length,
Andreas Huber2ea14e22009-12-16 09:30:55 -08002091 flags,
Andreas Huberbe06d262009-08-14 14:37:10 -07002092 msg.u.extended_buffer_data.timestamp,
2093 msg.u.extended_buffer_data.timestamp / 1E6);
2094
2095 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2096 size_t i = 0;
2097 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2098 ++i;
2099 }
2100
2101 CHECK(i < buffers->size());
2102 BufferInfo *info = &buffers->editItemAt(i);
2103
Andreas Huberbbbcf652010-12-07 14:25:54 -08002104 if (info->mStatus != OWNED_BY_COMPONENT) {
Steve Block8564c8d2012-01-05 23:22:43 +00002105 ALOGW("We already own output buffer %p, yet received "
Andreas Huberbe06d262009-08-14 14:37:10 -07002106 "a FILL_BUFFER_DONE.", buffer);
2107 }
2108
Andreas Huberbbbcf652010-12-07 14:25:54 -08002109 info->mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07002110
2111 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002112 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002113
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002114 status_t err = freeBuffer(kPortIndexOutput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002115 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002116
Andreas Huber2ea14e22009-12-16 09:30:55 -08002117#if 0
Andreas Huberd7795892009-08-26 10:33:47 -07002118 } else if (mPortStatus[kPortIndexOutput] == ENABLED
2119 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -07002120 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002121 mNoMoreOutputData = true;
2122 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08002123#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07002124 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002125 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -07002126
Andreas Huber52733b82010-01-25 10:41:35 -08002127 if (info->mMediaBuffer == NULL) {
2128 CHECK(mOMXLivesLocally);
2129 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
2130 CHECK(mQuirks & kDefersOutputBufferAllocation);
2131
2132 // The qcom video decoders on Nexus don't actually allocate
2133 // output buffer memory on a call to OMX_AllocateBuffer
2134 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
2135 // structure is only filled in later.
2136
2137 info->mMediaBuffer = new MediaBuffer(
2138 msg.u.extended_buffer_data.data_ptr,
2139 info->mSize);
2140 info->mMediaBuffer->setObserver(this);
2141 }
2142
Andreas Huberbe06d262009-08-14 14:37:10 -07002143 MediaBuffer *buffer = info->mMediaBuffer;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002144 bool isGraphicBuffer = buffer->graphicBuffer() != NULL;
Andreas Huberbe06d262009-08-14 14:37:10 -07002145
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002146 if (!isGraphicBuffer
2147 && msg.u.extended_buffer_data.range_offset
Andreas Huberf88f8442010-08-10 11:18:36 -07002148 + msg.u.extended_buffer_data.range_length
2149 > buffer->size()) {
2150 CODEC_LOGE(
2151 "Codec lied about its buffer size requirements, "
2152 "sending a buffer larger than the originally "
2153 "advertised size in FILL_BUFFER_DONE!");
2154 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002155 buffer->set_range(
2156 msg.u.extended_buffer_data.range_offset,
2157 msg.u.extended_buffer_data.range_length);
2158
2159 buffer->meta_data()->clear();
2160
Andreas Huberfa8de752009-10-08 10:07:49 -07002161 buffer->meta_data()->setInt64(
2162 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -07002163
2164 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
2165 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
2166 }
James Dong4108b1ed2011-06-07 19:45:54 -07002167 bool isCodecSpecific = false;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002168 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
2169 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
James Dong4108b1ed2011-06-07 19:45:54 -07002170 isCodecSpecific = true;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002171 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002172
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002173 if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
Andreas Huber1e194162010-10-06 16:43:57 -07002174 buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
2175 }
2176
Andreas Huberbe06d262009-08-14 14:37:10 -07002177 buffer->meta_data()->setPointer(
2178 kKeyPlatformPrivate,
2179 msg.u.extended_buffer_data.platform_private);
2180
2181 buffer->meta_data()->setPointer(
2182 kKeyBufferID,
2183 msg.u.extended_buffer_data.buffer);
2184
Andreas Huber2ea14e22009-12-16 09:30:55 -08002185 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
2186 CODEC_LOGV("No more output data.");
2187 mNoMoreOutputData = true;
2188 }
Andreas Huber6624c9f2010-07-20 15:04:28 -07002189
Andreas Huberafe02df2012-01-26 14:39:50 -08002190 if (mIsEncoder && mIsVideo) {
James Dong72516732012-02-06 23:46:37 -08002191 int64_t decodingTimeUs = isCodecSpecific? 0: getDecodingTimeUs();
James Dong32bb368a52011-06-20 11:40:52 -07002192 buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
2193 }
2194
Andreas Huber6624c9f2010-07-20 15:04:28 -07002195 if (mTargetTimeUs >= 0) {
2196 CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
2197
2198 if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
2199 CODEC_LOGV(
2200 "skipping output buffer at timestamp %lld us",
2201 msg.u.extended_buffer_data.timestamp);
2202
2203 fillOutputBuffer(info);
2204 break;
2205 }
2206
2207 CODEC_LOGV(
2208 "returning output buffer at target timestamp "
2209 "%lld us",
2210 msg.u.extended_buffer_data.timestamp);
2211
2212 mTargetTimeUs = -1;
2213 }
2214
2215 mFilledBuffers.push_back(i);
2216 mBufferFilled.signal();
James Dongfc8b7c92010-12-07 14:37:27 -08002217 if (mIsEncoder) {
2218 sched_yield();
2219 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002220 }
2221
2222 break;
2223 }
2224
2225 default:
2226 {
2227 CHECK(!"should not be here.");
2228 break;
2229 }
2230 }
2231}
2232
Andreas Huberb1678602009-10-19 13:06:40 -07002233// Has the format changed in any way that the client would have to be aware of?
2234static bool formatHasNotablyChanged(
2235 const sp<MetaData> &from, const sp<MetaData> &to) {
2236 if (from.get() == NULL && to.get() == NULL) {
2237 return false;
2238 }
2239
Andreas Huberf68c1682009-10-21 14:01:30 -07002240 if ((from.get() == NULL && to.get() != NULL)
2241 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07002242 return true;
2243 }
2244
2245 const char *mime_from, *mime_to;
2246 CHECK(from->findCString(kKeyMIMEType, &mime_from));
2247 CHECK(to->findCString(kKeyMIMEType, &mime_to));
2248
2249 if (strcasecmp(mime_from, mime_to)) {
2250 return true;
2251 }
2252
2253 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
2254 int32_t colorFormat_from, colorFormat_to;
2255 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
2256 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
2257
2258 if (colorFormat_from != colorFormat_to) {
2259 return true;
2260 }
2261
2262 int32_t width_from, width_to;
2263 CHECK(from->findInt32(kKeyWidth, &width_from));
2264 CHECK(to->findInt32(kKeyWidth, &width_to));
2265
2266 if (width_from != width_to) {
2267 return true;
2268 }
2269
2270 int32_t height_from, height_to;
2271 CHECK(from->findInt32(kKeyHeight, &height_from));
2272 CHECK(to->findInt32(kKeyHeight, &height_to));
2273
2274 if (height_from != height_to) {
2275 return true;
2276 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002277
2278 int32_t left_from, top_from, right_from, bottom_from;
2279 CHECK(from->findRect(
2280 kKeyCropRect,
2281 &left_from, &top_from, &right_from, &bottom_from));
2282
2283 int32_t left_to, top_to, right_to, bottom_to;
2284 CHECK(to->findRect(
2285 kKeyCropRect,
2286 &left_to, &top_to, &right_to, &bottom_to));
2287
2288 if (left_to != left_from || top_to != top_from
2289 || right_to != right_from || bottom_to != bottom_from) {
2290 return true;
2291 }
Andreas Huberb1678602009-10-19 13:06:40 -07002292 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
2293 int32_t numChannels_from, numChannels_to;
2294 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
2295 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
2296
2297 if (numChannels_from != numChannels_to) {
2298 return true;
2299 }
2300
2301 int32_t sampleRate_from, sampleRate_to;
2302 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
2303 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
2304
2305 if (sampleRate_from != sampleRate_to) {
2306 return true;
2307 }
2308 }
2309
2310 return false;
2311}
2312
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002313void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2314 switch (event) {
2315 case OMX_EventCmdComplete:
2316 {
2317 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
2318 break;
2319 }
2320
2321 case OMX_EventError:
2322 {
2323 CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
2324
2325 setState(ERROR);
2326 break;
2327 }
2328
2329 case OMX_EventPortSettingsChanged:
2330 {
2331 CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
2332 data1, data2);
2333
2334 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
James Dong4a0c91f2011-09-09 13:19:59 -07002335 // There is no need to check whether mFilledBuffers is empty or not
2336 // when the OMX_EventPortSettingsChanged is not meant for reallocating
2337 // the output buffers.
2338 if (data1 == kPortIndexOutput) {
2339 CHECK(mFilledBuffers.empty());
2340 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002341 onPortSettingsChanged(data1);
James Dong7e91d912011-03-18 12:19:43 -07002342 } else if (data1 == kPortIndexOutput &&
2343 (data2 == OMX_IndexConfigCommonOutputCrop ||
2344 data2 == OMX_IndexConfigCommonScale)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002345
2346 sp<MetaData> oldOutputFormat = mOutputFormat;
2347 initOutputFormat(mSource->getFormat());
2348
James Dong7e91d912011-03-18 12:19:43 -07002349 if (data2 == OMX_IndexConfigCommonOutputCrop &&
2350 formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002351 mOutputPortSettingsHaveChanged = true;
2352
James Dong7e91d912011-03-18 12:19:43 -07002353 } else if (data2 == OMX_IndexConfigCommonScale) {
2354 OMX_CONFIG_SCALEFACTORTYPE scale;
2355 InitOMXParams(&scale);
2356 scale.nPortIndex = kPortIndexOutput;
2357
2358 // Change display dimension only when necessary.
2359 if (OK == mOMX->getConfig(
2360 mNode,
2361 OMX_IndexConfigCommonScale,
2362 &scale, sizeof(scale))) {
2363 int32_t left, top, right, bottom;
2364 CHECK(mOutputFormat->findRect(kKeyCropRect,
2365 &left, &top,
2366 &right, &bottom));
2367
2368 // The scale is in 16.16 format.
2369 // scale 1.0 = 0x010000. When there is no
2370 // need to change the display, skip it.
Steve Block71f2cf12011-10-20 11:56:00 +01002371 ALOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
James Dong7e91d912011-03-18 12:19:43 -07002372 scale.xWidth, scale.xHeight);
2373
2374 if (scale.xWidth != 0x010000) {
2375 mOutputFormat->setInt32(kKeyDisplayWidth,
2376 ((right - left + 1) * scale.xWidth) >> 16);
2377 mOutputPortSettingsHaveChanged = true;
2378 }
2379
2380 if (scale.xHeight != 0x010000) {
2381 mOutputFormat->setInt32(kKeyDisplayHeight,
2382 ((bottom - top + 1) * scale.xHeight) >> 16);
2383 mOutputPortSettingsHaveChanged = true;
2384 }
2385 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002386 }
2387 }
2388 break;
2389 }
2390
2391#if 0
2392 case OMX_EventBufferFlag:
2393 {
2394 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
2395
2396 if (data1 == kPortIndexOutput) {
2397 mNoMoreOutputData = true;
2398 }
2399 break;
2400 }
2401#endif
2402
2403 default:
2404 {
2405 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
2406 break;
2407 }
2408 }
2409}
2410
Andreas Huberbe06d262009-08-14 14:37:10 -07002411void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
2412 switch (cmd) {
2413 case OMX_CommandStateSet:
2414 {
2415 onStateChange((OMX_STATETYPE)data);
2416 break;
2417 }
2418
2419 case OMX_CommandPortDisable:
2420 {
2421 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002422 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002423
2424 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002425 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING);
2426 CHECK_EQ(mPortBuffers[portIndex].size(), 0u);
Andreas Huberbe06d262009-08-14 14:37:10 -07002427
2428 mPortStatus[portIndex] = DISABLED;
2429
2430 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002431 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002432
Andreas Huberb1678602009-10-19 13:06:40 -07002433 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07002434 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07002435
2436 // Don't notify clients if the output port settings change
2437 // wasn't of importance to them, i.e. it may be that just the
2438 // number of buffers has changed and nothing else.
James Dongbd9d0302011-09-01 19:31:01 -07002439 bool formatChanged = formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
2440 if (!mOutputPortSettingsHaveChanged) {
2441 mOutputPortSettingsHaveChanged = formatChanged;
2442 }
Andreas Hubercfd55572009-10-09 14:11:28 -07002443
James Dong0209da12011-09-12 19:56:23 -07002444 status_t err = enablePortAsync(portIndex);
Andreas Huberba1b16792011-01-19 09:20:58 -08002445 if (err != OK) {
James Dong0209da12011-09-12 19:56:23 -07002446 CODEC_LOGE("enablePortAsync(%ld) failed (err = %d)", portIndex, err);
Andreas Huberba1b16792011-01-19 09:20:58 -08002447 setState(ERROR);
James Dong0209da12011-09-12 19:56:23 -07002448 } else {
2449 err = allocateBuffersOnPort(portIndex);
2450 if (err != OK) {
2451 CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
2452 setState(ERROR);
2453 }
Andreas Huberba1b16792011-01-19 09:20:58 -08002454 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002455 }
2456 break;
2457 }
2458
2459 case OMX_CommandPortEnable:
2460 {
2461 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002462 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002463
2464 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002465 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002466
2467 mPortStatus[portIndex] = ENABLED;
2468
2469 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002470 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002471
2472 setState(EXECUTING);
2473
2474 fillOutputBuffers();
2475 }
2476 break;
2477 }
2478
2479 case OMX_CommandFlush:
2480 {
2481 OMX_U32 portIndex = data;
2482
Andreas Huber4c483422009-09-02 16:05:36 -07002483 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002484
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002485 CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN);
Andreas Huberbe06d262009-08-14 14:37:10 -07002486 mPortStatus[portIndex] = ENABLED;
2487
2488 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
2489 mPortBuffers[portIndex].size());
2490
2491 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002492 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002493
2494 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002495 } else if (mState == EXECUTING_TO_IDLE) {
2496 if (mPortStatus[kPortIndexInput] == ENABLED
2497 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002498 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07002499 "transition from EXECUTING to IDLE.");
2500
2501 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2502 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2503
2504 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002505 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002506 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002507 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002508 } else {
2509 // We're flushing both ports in preparation for seeking.
2510
2511 if (mPortStatus[kPortIndexInput] == ENABLED
2512 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002513 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07002514 " seek-time.");
2515
Andreas Huber1f24b302010-06-10 11:12:39 -07002516 // We implicitly resume pulling on our upstream source.
2517 mPaused = false;
2518
Andreas Huberbe06d262009-08-14 14:37:10 -07002519 drainInputBuffers();
2520 fillOutputBuffers();
2521 }
Andreas Huberb9289832011-02-08 13:10:25 -08002522
2523 if (mOutputPortSettingsChangedPending) {
2524 CODEC_LOGV(
2525 "Honoring deferred output port settings change.");
2526
2527 mOutputPortSettingsChangedPending = false;
2528 onPortSettingsChanged(kPortIndexOutput);
2529 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002530 }
2531
2532 break;
2533 }
2534
2535 default:
2536 {
Andreas Huber4c483422009-09-02 16:05:36 -07002537 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07002538 break;
2539 }
2540 }
2541}
2542
2543void OMXCodec::onStateChange(OMX_STATETYPE newState) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002544 CODEC_LOGV("onStateChange %d", newState);
2545
Andreas Huberbe06d262009-08-14 14:37:10 -07002546 switch (newState) {
2547 case OMX_StateIdle:
2548 {
Andreas Huber4c483422009-09-02 16:05:36 -07002549 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002550 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07002551 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002552 mNode, OMX_CommandStateSet, OMX_StateExecuting);
2553
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002554 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002555
2556 setState(IDLE_TO_EXECUTING);
2557 } else {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002558 CHECK_EQ((int)mState, (int)EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002559
2560 CHECK_EQ(
2561 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
2562 mPortBuffers[kPortIndexInput].size());
2563
2564 CHECK_EQ(
2565 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
2566 mPortBuffers[kPortIndexOutput].size());
2567
Andreas Huber784202e2009-10-15 13:46:54 -07002568 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002569 mNode, OMX_CommandStateSet, OMX_StateLoaded);
2570
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002571 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002572
2573 err = freeBuffersOnPort(kPortIndexInput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002574 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002575
2576 err = freeBuffersOnPort(kPortIndexOutput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002577 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002578
2579 mPortStatus[kPortIndexInput] = ENABLED;
2580 mPortStatus[kPortIndexOutput] = ENABLED;
2581
Jamie Gennisc0e42932011-10-25 14:50:16 -07002582 if ((mFlags & kEnableGrallocUsageProtected) &&
2583 mNativeWindow != NULL) {
2584 // We push enough 1x1 blank buffers to ensure that one of
2585 // them has made it to the display. This allows the OMX
2586 // component teardown to zero out any protected buffers
2587 // without the risk of scanning out one of those buffers.
2588 pushBlankBuffersToNativeWindow();
2589 }
2590
Andreas Huberbe06d262009-08-14 14:37:10 -07002591 setState(IDLE_TO_LOADED);
2592 }
2593 break;
2594 }
2595
2596 case OMX_StateExecuting:
2597 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002598 CHECK_EQ((int)mState, (int)IDLE_TO_EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002599
Andreas Huber4c483422009-09-02 16:05:36 -07002600 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002601
Andreas Huberb9289832011-02-08 13:10:25 -08002602 mOutputPortSettingsChangedPending = false;
2603
Andreas Huberbe06d262009-08-14 14:37:10 -07002604 setState(EXECUTING);
2605
Andreas Huber42978e52009-08-27 10:08:39 -07002606 // Buffers will be submitted to the component in the first
2607 // call to OMXCodec::read as mInitialBufferSubmit is true at
2608 // this point. This ensures that this on_message call returns,
2609 // releases the lock and ::init can notice the state change and
2610 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07002611 break;
2612 }
2613
2614 case OMX_StateLoaded:
2615 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002616 CHECK_EQ((int)mState, (int)IDLE_TO_LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002617
Andreas Huber4c483422009-09-02 16:05:36 -07002618 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002619
2620 setState(LOADED);
2621 break;
2622 }
2623
Andreas Huberc712b9f2010-01-20 15:05:46 -08002624 case OMX_StateInvalid:
2625 {
2626 setState(ERROR);
2627 break;
2628 }
2629
Andreas Huberbe06d262009-08-14 14:37:10 -07002630 default:
2631 {
2632 CHECK(!"should not be here.");
2633 break;
2634 }
2635 }
2636}
2637
2638// static
2639size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
2640 size_t n = 0;
2641 for (size_t i = 0; i < buffers.size(); ++i) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002642 if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002643 ++n;
2644 }
2645 }
2646
2647 return n;
2648}
2649
2650status_t OMXCodec::freeBuffersOnPort(
2651 OMX_U32 portIndex, bool onlyThoseWeOwn) {
2652 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2653
2654 status_t stickyErr = OK;
2655
2656 for (size_t i = buffers->size(); i-- > 0;) {
2657 BufferInfo *info = &buffers->editItemAt(i);
2658
Andreas Huberbbbcf652010-12-07 14:25:54 -08002659 if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002660 continue;
2661 }
2662
Andreas Huberbbbcf652010-12-07 14:25:54 -08002663 CHECK(info->mStatus == OWNED_BY_US
2664 || info->mStatus == OWNED_BY_NATIVE_WINDOW);
Andreas Huberbe06d262009-08-14 14:37:10 -07002665
Andreas Huber92022852009-09-14 15:24:14 -07002666 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
2667
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002668 status_t err = freeBuffer(portIndex, i);
Andreas Huberbe06d262009-08-14 14:37:10 -07002669
2670 if (err != OK) {
2671 stickyErr = err;
2672 }
2673
Andreas Huberbe06d262009-08-14 14:37:10 -07002674 }
2675
2676 CHECK(onlyThoseWeOwn || buffers->isEmpty());
2677
2678 return stickyErr;
2679}
2680
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002681status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) {
2682 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2683
2684 BufferInfo *info = &buffers->editItemAt(bufIndex);
2685
2686 status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
2687
2688 if (err == OK && info->mMediaBuffer != NULL) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002689 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002690 info->mMediaBuffer->setObserver(NULL);
2691
2692 // Make sure nobody but us owns this buffer at this point.
2693 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
2694
2695 // Cancel the buffer if it belongs to an ANativeWindow.
2696 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
Andreas Huberbbbcf652010-12-07 14:25:54 -08002697 if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002698 err = cancelBufferToNativeWindow(info);
2699 }
2700
2701 info->mMediaBuffer->release();
James Dong31b9375f2010-11-10 21:11:41 -08002702 info->mMediaBuffer = NULL;
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002703 }
2704
2705 if (err == OK) {
2706 buffers->removeAt(bufIndex);
2707 }
2708
2709 return err;
2710}
2711
Andreas Huberbe06d262009-08-14 14:37:10 -07002712void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07002713 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002714
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002715 CHECK_EQ((int)mState, (int)EXECUTING);
2716 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberb9289832011-02-08 13:10:25 -08002717 CHECK(!mOutputPortSettingsChangedPending);
2718
2719 if (mPortStatus[kPortIndexOutput] != ENABLED) {
2720 CODEC_LOGV("Deferring output port settings change.");
2721 mOutputPortSettingsChangedPending = true;
2722 return;
2723 }
2724
Andreas Huberbe06d262009-08-14 14:37:10 -07002725 setState(RECONFIGURING);
2726
2727 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07002728 if (!flushPortAsync(portIndex)) {
2729 onCmdComplete(OMX_CommandFlush, portIndex);
2730 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002731 } else {
2732 disablePortAsync(portIndex);
2733 }
2734}
2735
Andreas Huber404cc412009-08-25 14:26:05 -07002736bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07002737 CHECK(mState == EXECUTING || mState == RECONFIGURING
2738 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002739
Andreas Huber4c483422009-09-02 16:05:36 -07002740 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07002741 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
2742 mPortBuffers[portIndex].size());
2743
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002744 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002745 mPortStatus[portIndex] = SHUTTING_DOWN;
2746
Andreas Huber404cc412009-08-25 14:26:05 -07002747 if ((mQuirks & kRequiresFlushCompleteEmulation)
2748 && countBuffersWeOwn(mPortBuffers[portIndex])
2749 == mPortBuffers[portIndex].size()) {
2750 // No flush is necessary and this component fails to send a
2751 // flush-complete event in this case.
2752
2753 return false;
2754 }
2755
Andreas Huberbe06d262009-08-14 14:37:10 -07002756 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002757 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002758 CHECK_EQ(err, (status_t)OK);
Andreas Huber404cc412009-08-25 14:26:05 -07002759
2760 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002761}
2762
2763void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
2764 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2765
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002766 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002767 mPortStatus[portIndex] = DISABLING;
2768
Andreas Huberd222c842010-08-26 14:29:34 -07002769 CODEC_LOGV("sending OMX_CommandPortDisable(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002770 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002771 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002772 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002773
2774 freeBuffersOnPort(portIndex, true);
2775}
2776
James Dong0209da12011-09-12 19:56:23 -07002777status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002778 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2779
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002780 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002781 mPortStatus[portIndex] = ENABLING;
2782
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002783 CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
James Dong0209da12011-09-12 19:56:23 -07002784 return mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002785}
2786
2787void OMXCodec::fillOutputBuffers() {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002788 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002789
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002790 // This is a workaround for some decoders not properly reporting
2791 // end-of-output-stream. If we own all input buffers and also own
2792 // all output buffers and we already signalled end-of-input-stream,
2793 // the end-of-output-stream is implied.
2794 if (mSignalledEOS
2795 && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
2796 == mPortBuffers[kPortIndexInput].size()
2797 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
2798 == mPortBuffers[kPortIndexOutput].size()) {
2799 mNoMoreOutputData = true;
2800 mBufferFilled.signal();
2801
2802 return;
2803 }
2804
Andreas Huberbe06d262009-08-14 14:37:10 -07002805 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2806 for (size_t i = 0; i < buffers->size(); ++i) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002807 BufferInfo *info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002808 if (info->mStatus == OWNED_BY_US) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002809 fillOutputBuffer(&buffers->editItemAt(i));
2810 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002811 }
2812}
2813
2814void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07002815 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002816
Andreas Huber42fb5d62011-06-29 15:53:28 -07002817 if (mFlags & kUseSecureInputBuffers) {
2818 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2819 for (size_t i = 0; i < buffers->size(); ++i) {
2820 if (!drainAnyInputBuffer()
2821 || (mFlags & kOnlySubmitOneInputBufferAtOneTime)) {
2822 break;
2823 }
James Dong5f3ab062011-01-25 16:31:28 -08002824 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07002825 } else {
2826 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2827 for (size_t i = 0; i < buffers->size(); ++i) {
2828 BufferInfo *info = &buffers->editItemAt(i);
James Dong5f3ab062011-01-25 16:31:28 -08002829
Andreas Huber42fb5d62011-06-29 15:53:28 -07002830 if (info->mStatus != OWNED_BY_US) {
2831 continue;
2832 }
James Dong5f3ab062011-01-25 16:31:28 -08002833
Andreas Huber42fb5d62011-06-29 15:53:28 -07002834 if (!drainInputBuffer(info)) {
2835 break;
2836 }
2837
2838 if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
2839 break;
2840 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08002841 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002842 }
2843}
2844
Andreas Huber42fb5d62011-06-29 15:53:28 -07002845bool OMXCodec::drainAnyInputBuffer() {
2846 return drainInputBuffer((BufferInfo *)NULL);
2847}
2848
2849OMXCodec::BufferInfo *OMXCodec::findInputBufferByDataPointer(void *ptr) {
2850 Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
2851 for (size_t i = 0; i < infos->size(); ++i) {
2852 BufferInfo *info = &infos->editItemAt(i);
2853
2854 if (info->mData == ptr) {
2855 CODEC_LOGV(
2856 "input buffer data ptr = %p, buffer_id = %p",
2857 ptr,
2858 info->mBuffer);
2859
2860 return info;
2861 }
2862 }
2863
2864 TRESPASS();
2865}
2866
2867OMXCodec::BufferInfo *OMXCodec::findEmptyInputBuffer() {
2868 Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
2869 for (size_t i = 0; i < infos->size(); ++i) {
2870 BufferInfo *info = &infos->editItemAt(i);
2871
2872 if (info->mStatus == OWNED_BY_US) {
2873 return info;
2874 }
2875 }
2876
2877 TRESPASS();
2878}
2879
Andreas Huberbbbcf652010-12-07 14:25:54 -08002880bool OMXCodec::drainInputBuffer(BufferInfo *info) {
Andreas Huber42fb5d62011-06-29 15:53:28 -07002881 if (info != NULL) {
2882 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
2883 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002884
2885 if (mSignalledEOS) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002886 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002887 }
2888
2889 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
Andreas Huber42fb5d62011-06-29 15:53:28 -07002890 CHECK(!(mFlags & kUseSecureInputBuffers));
2891
Andreas Huberbe06d262009-08-14 14:37:10 -07002892 const CodecSpecificData *specific =
2893 mCodecSpecificData[mCodecSpecificDataIndex];
2894
2895 size_t size = specific->mSize;
2896
Andreas Hubere6c40962009-09-10 14:13:30 -07002897 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07002898 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002899 static const uint8_t kNALStartCode[4] =
2900 { 0x00, 0x00, 0x00, 0x01 };
2901
Andreas Huberc712b9f2010-01-20 15:05:46 -08002902 CHECK(info->mSize >= specific->mSize + 4);
Andreas Huberbe06d262009-08-14 14:37:10 -07002903
2904 size += 4;
2905
Andreas Huberc712b9f2010-01-20 15:05:46 -08002906 memcpy(info->mData, kNALStartCode, 4);
2907 memcpy((uint8_t *)info->mData + 4,
Andreas Huberbe06d262009-08-14 14:37:10 -07002908 specific->mData, specific->mSize);
2909 } else {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002910 CHECK(info->mSize >= specific->mSize);
2911 memcpy(info->mData, specific->mData, specific->mSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07002912 }
2913
Andreas Huber2ea14e22009-12-16 09:30:55 -08002914 mNoMoreOutputData = false;
2915
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002916 CODEC_LOGV("calling emptyBuffer with codec specific data");
2917
Andreas Huber784202e2009-10-15 13:46:54 -07002918 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07002919 mNode, info->mBuffer, 0, size,
2920 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
2921 0);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002922 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002923
Andreas Huberbbbcf652010-12-07 14:25:54 -08002924 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07002925
2926 ++mCodecSpecificDataIndex;
Andreas Huberbbbcf652010-12-07 14:25:54 -08002927 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002928 }
2929
Andreas Huber1f24b302010-06-10 11:12:39 -07002930 if (mPaused) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002931 return false;
Andreas Huber1f24b302010-06-10 11:12:39 -07002932 }
2933
Andreas Huberbe06d262009-08-14 14:37:10 -07002934 status_t err;
Andreas Huber2ea14e22009-12-16 09:30:55 -08002935
Andreas Hubera4357ad2010-04-02 12:49:54 -07002936 bool signalEOS = false;
2937 int64_t timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07002938
Andreas Hubera4357ad2010-04-02 12:49:54 -07002939 size_t offset = 0;
2940 int32_t n = 0;
Andreas Huberbbbcf652010-12-07 14:25:54 -08002941
Pannag Sanketi557b7092011-08-18 21:53:02 -07002942
Andreas Hubera4357ad2010-04-02 12:49:54 -07002943 for (;;) {
2944 MediaBuffer *srcBuffer;
2945 if (mSeekTimeUs >= 0) {
2946 if (mLeftOverBuffer) {
2947 mLeftOverBuffer->release();
2948 mLeftOverBuffer = NULL;
2949 }
James Dong2144f632010-12-11 10:43:41 -08002950
2951 MediaSource::ReadOptions options;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002952 options.setSeekTo(mSeekTimeUs, mSeekMode);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002953
2954 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002955 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002956 mBufferFilled.signal();
2957
2958 err = mSource->read(&srcBuffer, &options);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002959
2960 if (err == OK) {
2961 int64_t targetTimeUs;
2962 if (srcBuffer->meta_data()->findInt64(
2963 kKeyTargetTime, &targetTimeUs)
2964 && targetTimeUs >= 0) {
Andreas Huberb9289832011-02-08 13:10:25 -08002965 CODEC_LOGV("targetTimeUs = %lld us", targetTimeUs);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002966 mTargetTimeUs = targetTimeUs;
2967 } else {
2968 mTargetTimeUs = -1;
2969 }
2970 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002971 } else if (mLeftOverBuffer) {
2972 srcBuffer = mLeftOverBuffer;
2973 mLeftOverBuffer = NULL;
2974
2975 err = OK;
2976 } else {
James Dong2144f632010-12-11 10:43:41 -08002977 err = mSource->read(&srcBuffer);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002978 }
2979
2980 if (err != OK) {
2981 signalEOS = true;
2982 mFinalStatus = err;
2983 mSignalledEOS = true;
Andreas Huber94bced12010-12-14 09:50:46 -08002984 mBufferFilled.signal();
Andreas Hubera4357ad2010-04-02 12:49:54 -07002985 break;
2986 }
2987
Andreas Huber42fb5d62011-06-29 15:53:28 -07002988 if (mFlags & kUseSecureInputBuffers) {
2989 info = findInputBufferByDataPointer(srcBuffer->data());
2990 CHECK(info != NULL);
2991 }
2992
Andreas Hubera4357ad2010-04-02 12:49:54 -07002993 size_t remainingBytes = info->mSize - offset;
2994
2995 if (srcBuffer->range_length() > remainingBytes) {
2996 if (offset == 0) {
2997 CODEC_LOGE(
2998 "Codec's input buffers are too small to accomodate "
2999 "buffer read from source (info->mSize = %d, srcLength = %d)",
3000 info->mSize, srcBuffer->range_length());
3001
3002 srcBuffer->release();
3003 srcBuffer = NULL;
3004
3005 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003006 return false;
Andreas Hubera4357ad2010-04-02 12:49:54 -07003007 }
3008
3009 mLeftOverBuffer = srcBuffer;
3010 break;
3011 }
3012
James Dong05c2fd52010-11-02 13:20:11 -07003013 bool releaseBuffer = true;
James Dong4f501f02010-06-07 14:41:41 -07003014 if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
3015 CHECK(mOMXLivesLocally && offset == 0);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003016
3017 OMX_BUFFERHEADERTYPE *header =
3018 (OMX_BUFFERHEADERTYPE *)info->mBuffer;
3019
James Dong31b9375f2010-11-10 21:11:41 -08003020 CHECK(header->pBuffer == info->mData);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003021
3022 header->pBuffer =
3023 (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
3024
James Dong05c2fd52010-11-02 13:20:11 -07003025 releaseBuffer = false;
3026 info->mMediaBuffer = srcBuffer;
James Dong4f501f02010-06-07 14:41:41 -07003027 } else {
Andreas Huber42fb5d62011-06-29 15:53:28 -07003028 if (mFlags & kStoreMetaDataInVideoBuffers) {
James Dong05c2fd52010-11-02 13:20:11 -07003029 releaseBuffer = false;
3030 info->mMediaBuffer = srcBuffer;
3031 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07003032
3033 if (mFlags & kUseSecureInputBuffers) {
3034 // Data in "info" is already provided at this time.
3035
3036 releaseBuffer = false;
3037
3038 CHECK(info->mMediaBuffer == NULL);
3039 info->mMediaBuffer = srcBuffer;
3040 } else {
Pannag Sanketi557b7092011-08-18 21:53:02 -07003041 CHECK(srcBuffer->data() != NULL) ;
Andreas Huber42fb5d62011-06-29 15:53:28 -07003042 memcpy((uint8_t *)info->mData + offset,
3043 (const uint8_t *)srcBuffer->data()
3044 + srcBuffer->range_offset(),
3045 srcBuffer->range_length());
3046 }
James Dong4f501f02010-06-07 14:41:41 -07003047 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003048
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003049 int64_t lastBufferTimeUs;
3050 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
Andreas Huber6624c9f2010-07-20 15:04:28 -07003051 CHECK(lastBufferTimeUs >= 0);
Andreas Huberafe02df2012-01-26 14:39:50 -08003052 if (mIsEncoder && mIsVideo) {
James Dong4108b1ed2011-06-07 19:45:54 -07003053 mDecodingTimeList.push_back(lastBufferTimeUs);
3054 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003055
Andreas Hubera4357ad2010-04-02 12:49:54 -07003056 if (offset == 0) {
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003057 timestampUs = lastBufferTimeUs;
Andreas Hubera4357ad2010-04-02 12:49:54 -07003058 }
3059
3060 offset += srcBuffer->range_length();
3061
Andreas Huber4b3913a2011-05-11 14:13:42 -07003062 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mMIME)) {
3063 CHECK(!(mQuirks & kSupportsMultipleFramesPerInputBuffer));
3064 CHECK_GE(info->mSize, offset + sizeof(int32_t));
3065
3066 int32_t numPageSamples;
3067 if (!srcBuffer->meta_data()->findInt32(
3068 kKeyValidSamples, &numPageSamples)) {
3069 numPageSamples = -1;
3070 }
3071
3072 memcpy((uint8_t *)info->mData + offset,
3073 &numPageSamples,
3074 sizeof(numPageSamples));
3075
3076 offset += sizeof(numPageSamples);
3077 }
3078
James Dong05c2fd52010-11-02 13:20:11 -07003079 if (releaseBuffer) {
3080 srcBuffer->release();
3081 srcBuffer = NULL;
3082 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003083
3084 ++n;
3085
3086 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
3087 break;
3088 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003089
3090 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
3091
3092 if (coalescedDurationUs > 250000ll) {
3093 // Don't coalesce more than 250ms worth of encoded data at once.
3094 break;
3095 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003096 }
3097
3098 if (n > 1) {
Steve Block71f2cf12011-10-20 11:56:00 +01003099 ALOGV("coalesced %d frames into one input buffer", n);
Andreas Huberbe06d262009-08-14 14:37:10 -07003100 }
3101
3102 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberbe06d262009-08-14 14:37:10 -07003103
Andreas Hubera4357ad2010-04-02 12:49:54 -07003104 if (signalEOS) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003105 flags |= OMX_BUFFERFLAG_EOS;
Andreas Huberbe06d262009-08-14 14:37:10 -07003106 } else {
Andreas Huber2ea14e22009-12-16 09:30:55 -08003107 mNoMoreOutputData = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003108 }
3109
Andreas Hubera4357ad2010-04-02 12:49:54 -07003110 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
3111 "timestamp %lld us (%.2f secs)",
3112 info->mBuffer, offset,
3113 timestampUs, timestampUs / 1E6);
Andreas Huber3f427072009-10-08 11:02:27 -07003114
Andreas Huber42fb5d62011-06-29 15:53:28 -07003115 if (info == NULL) {
3116 CHECK(mFlags & kUseSecureInputBuffers);
3117 CHECK(signalEOS);
3118
3119 // This is fishy, there's still a MediaBuffer corresponding to this
3120 // info available to the source at this point even though we're going
3121 // to use it to signal EOS to the codec.
3122 info = findEmptyInputBuffer();
3123 }
3124
Andreas Huber784202e2009-10-15 13:46:54 -07003125 err = mOMX->emptyBuffer(
Andreas Hubera4357ad2010-04-02 12:49:54 -07003126 mNode, info->mBuffer, 0, offset,
Andreas Huberfa8de752009-10-08 10:07:49 -07003127 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07003128
3129 if (err != OK) {
3130 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003131 return false;
Andreas Huber3f427072009-10-08 11:02:27 -07003132 }
3133
Andreas Huberbbbcf652010-12-07 14:25:54 -08003134 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberea6a38c2009-11-16 15:43:38 -08003135
Andreas Huberbbbcf652010-12-07 14:25:54 -08003136 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003137}
3138
3139void OMXCodec::fillOutputBuffer(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003140 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Andreas Huberbe06d262009-08-14 14:37:10 -07003141
Andreas Huber404cc412009-08-25 14:26:05 -07003142 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07003143 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07003144 "calling fillOutputBuffer");
3145 return;
3146 }
3147
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003148 if (info->mMediaBuffer != NULL) {
3149 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
3150 if (graphicBuffer != 0) {
3151 // When using a native buffer we need to lock the buffer before
3152 // giving it to OMX.
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003153 CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
3154 int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
3155 graphicBuffer.get());
3156 if (err != 0) {
3157 CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003158
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003159 setState(ERROR);
3160 return;
3161 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003162 }
3163 }
3164
3165 CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07003166 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber8f14c552010-04-12 10:20:12 -07003167
3168 if (err != OK) {
3169 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
3170
3171 setState(ERROR);
3172 return;
3173 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003174
Andreas Huberbbbcf652010-12-07 14:25:54 -08003175 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07003176}
3177
Andreas Huberbbbcf652010-12-07 14:25:54 -08003178bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003179 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
3180 for (size_t i = 0; i < buffers->size(); ++i) {
3181 if ((*buffers)[i].mBuffer == buffer) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003182 return drainInputBuffer(&buffers->editItemAt(i));
Andreas Huberbe06d262009-08-14 14:37:10 -07003183 }
3184 }
3185
3186 CHECK(!"should not be here.");
Andreas Huberbbbcf652010-12-07 14:25:54 -08003187
3188 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003189}
3190
3191void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
3192 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3193 for (size_t i = 0; i < buffers->size(); ++i) {
3194 if ((*buffers)[i].mBuffer == buffer) {
3195 fillOutputBuffer(&buffers->editItemAt(i));
3196 return;
3197 }
3198 }
3199
3200 CHECK(!"should not be here.");
3201}
3202
3203void OMXCodec::setState(State newState) {
3204 mState = newState;
3205 mAsyncCompletion.signal();
3206
3207 // This may cause some spurious wakeups but is necessary to
3208 // unblock the reader if we enter ERROR state.
3209 mBufferFilled.signal();
3210}
3211
James Dongd9ac6212011-07-15 15:25:36 -07003212status_t OMXCodec::waitForBufferFilled_l() {
James Dong92d6ea32011-08-14 16:14:12 -07003213
3214 if (mIsEncoder) {
3215 // For timelapse video recording, the timelapse video recording may
3216 // not send an input frame for a _long_ time. Do not use timeout
3217 // for video encoding.
3218 return mBufferFilled.wait(mLock);
3219 }
James Dong4a0c91f2011-09-09 13:19:59 -07003220 status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutNs);
James Dongd9ac6212011-07-15 15:25:36 -07003221 if (err != OK) {
James Dong92d6ea32011-08-14 16:14:12 -07003222 CODEC_LOGE("Timed out waiting for output buffers: %d/%d",
James Dongd9ac6212011-07-15 15:25:36 -07003223 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
3224 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
3225 }
3226 return err;
3227}
3228
Andreas Huberda050cf22009-09-02 14:01:43 -07003229void OMXCodec::setRawAudioFormat(
3230 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
James Dongabed93a2010-04-22 17:27:04 -07003231
3232 // port definition
3233 OMX_PARAM_PORTDEFINITIONTYPE def;
3234 InitOMXParams(&def);
3235 def.nPortIndex = portIndex;
3236 status_t err = mOMX->getParameter(
3237 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003238 CHECK_EQ(err, (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003239 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
3240 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003241 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003242
3243 // pcm param
Andreas Huberda050cf22009-09-02 14:01:43 -07003244 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07003245 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07003246 pcmParams.nPortIndex = portIndex;
3247
James Dongabed93a2010-04-22 17:27:04 -07003248 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003249 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3250
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003251 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003252
3253 pcmParams.nChannels = numChannels;
3254 pcmParams.eNumData = OMX_NumericalDataSigned;
3255 pcmParams.bInterleaved = OMX_TRUE;
3256 pcmParams.nBitPerSample = 16;
3257 pcmParams.nSamplingRate = sampleRate;
3258 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3259
3260 if (numChannels == 1) {
3261 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
3262 } else {
3263 CHECK_EQ(numChannels, 2);
3264
3265 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
3266 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
3267 }
3268
Andreas Huber784202e2009-10-15 13:46:54 -07003269 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003270 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3271
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003272 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003273}
3274
James Dong17299ab2010-05-14 15:45:22 -07003275static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
3276 if (isAMRWB) {
3277 if (bps <= 6600) {
3278 return OMX_AUDIO_AMRBandModeWB0;
3279 } else if (bps <= 8850) {
3280 return OMX_AUDIO_AMRBandModeWB1;
3281 } else if (bps <= 12650) {
3282 return OMX_AUDIO_AMRBandModeWB2;
3283 } else if (bps <= 14250) {
3284 return OMX_AUDIO_AMRBandModeWB3;
3285 } else if (bps <= 15850) {
3286 return OMX_AUDIO_AMRBandModeWB4;
3287 } else if (bps <= 18250) {
3288 return OMX_AUDIO_AMRBandModeWB5;
3289 } else if (bps <= 19850) {
3290 return OMX_AUDIO_AMRBandModeWB6;
3291 } else if (bps <= 23050) {
3292 return OMX_AUDIO_AMRBandModeWB7;
3293 }
3294
3295 // 23850 bps
3296 return OMX_AUDIO_AMRBandModeWB8;
3297 } else { // AMRNB
3298 if (bps <= 4750) {
3299 return OMX_AUDIO_AMRBandModeNB0;
3300 } else if (bps <= 5150) {
3301 return OMX_AUDIO_AMRBandModeNB1;
3302 } else if (bps <= 5900) {
3303 return OMX_AUDIO_AMRBandModeNB2;
3304 } else if (bps <= 6700) {
3305 return OMX_AUDIO_AMRBandModeNB3;
3306 } else if (bps <= 7400) {
3307 return OMX_AUDIO_AMRBandModeNB4;
3308 } else if (bps <= 7950) {
3309 return OMX_AUDIO_AMRBandModeNB5;
3310 } else if (bps <= 10200) {
3311 return OMX_AUDIO_AMRBandModeNB6;
3312 }
3313
3314 // 12200 bps
3315 return OMX_AUDIO_AMRBandModeNB7;
3316 }
3317}
3318
3319void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
Andreas Huber8768f2c2009-12-01 15:26:54 -08003320 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003321
Andreas Huber8768f2c2009-12-01 15:26:54 -08003322 OMX_AUDIO_PARAM_AMRTYPE def;
3323 InitOMXParams(&def);
3324 def.nPortIndex = portIndex;
Andreas Huberbe06d262009-08-14 14:37:10 -07003325
Andreas Huber8768f2c2009-12-01 15:26:54 -08003326 status_t err =
3327 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07003328
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003329 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003330
Andreas Huber8768f2c2009-12-01 15:26:54 -08003331 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
James Dongabed93a2010-04-22 17:27:04 -07003332
James Dong17299ab2010-05-14 15:45:22 -07003333 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
Andreas Huber8768f2c2009-12-01 15:26:54 -08003334 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003335 CHECK_EQ(err, (status_t)OK);
Andreas Huberee606e62009-09-08 10:19:21 -07003336
3337 ////////////////////////
3338
3339 if (mIsEncoder) {
3340 sp<MetaData> format = mSource->getFormat();
3341 int32_t sampleRate;
3342 int32_t numChannels;
3343 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
3344 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
3345
3346 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
3347 }
3348}
3349
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003350status_t OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
3351 if (numChannels > 2)
Steve Block8564c8d2012-01-05 23:22:43 +00003352 ALOGW("Number of channels: (%d) \n", numChannels);
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003353
Andreas Huberda050cf22009-09-02 14:01:43 -07003354 if (mIsEncoder) {
James Dongabed93a2010-04-22 17:27:04 -07003355 //////////////// input port ////////////////////
Andreas Huberda050cf22009-09-02 14:01:43 -07003356 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
James Dongabed93a2010-04-22 17:27:04 -07003357
3358 //////////////// output port ////////////////////
3359 // format
3360 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
Andreas Huber88572f72012-02-21 11:47:18 -08003361 InitOMXParams(&format);
James Dongabed93a2010-04-22 17:27:04 -07003362 format.nPortIndex = kPortIndexOutput;
3363 format.nIndex = 0;
3364 status_t err = OMX_ErrorNone;
3365 while (OMX_ErrorNone == err) {
3366 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003367 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003368 if (format.eEncoding == OMX_AUDIO_CodingAAC) {
3369 break;
3370 }
3371 format.nIndex++;
3372 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003373 CHECK_EQ((status_t)OK, err);
James Dongabed93a2010-04-22 17:27:04 -07003374 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003375 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003376
3377 // port definition
3378 OMX_PARAM_PORTDEFINITIONTYPE def;
3379 InitOMXParams(&def);
3380 def.nPortIndex = kPortIndexOutput;
3381 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003382 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003383 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
3384 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
3385 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003386 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003387
3388 // profile
3389 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
3390 InitOMXParams(&profile);
3391 profile.nPortIndex = kPortIndexOutput;
3392 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003393 &profile, sizeof(profile)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003394 profile.nChannels = numChannels;
3395 profile.eChannelMode = (numChannels == 1?
3396 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
3397 profile.nSampleRate = sampleRate;
James Dong17299ab2010-05-14 15:45:22 -07003398 profile.nBitRate = bitRate;
James Dongabed93a2010-04-22 17:27:04 -07003399 profile.nAudioBandWidth = 0;
3400 profile.nFrameLength = 0;
3401 profile.nAACtools = OMX_AUDIO_AACToolAll;
3402 profile.nAACERtools = OMX_AUDIO_AACERNone;
3403 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
3404 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003405 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
3406 &profile, sizeof(profile));
James Dongabed93a2010-04-22 17:27:04 -07003407
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003408 if (err != OK) {
3409 CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err);
3410 return err;
3411 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003412 } else {
3413 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07003414 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07003415 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003416
Andreas Huber784202e2009-10-15 13:46:54 -07003417 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003418 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003419 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003420
Andreas Huberda050cf22009-09-02 14:01:43 -07003421 profile.nChannels = numChannels;
3422 profile.nSampleRate = sampleRate;
3423 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07003424
Andreas Huber784202e2009-10-15 13:46:54 -07003425 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003426 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003427
3428 if (err != OK) {
3429 CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err);
3430 return err;
3431 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003432 }
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003433
3434 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07003435}
3436
Andreas Huber4b3913a2011-05-11 14:13:42 -07003437void OMXCodec::setG711Format(int32_t numChannels) {
3438 CHECK(!mIsEncoder);
3439 setRawAudioFormat(kPortIndexInput, 8000, numChannels);
3440}
3441
Andreas Huberbe06d262009-08-14 14:37:10 -07003442void OMXCodec::setImageOutputFormat(
3443 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07003444 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07003445
3446#if 0
3447 OMX_INDEXTYPE index;
3448 status_t err = mOMX->get_extension_index(
3449 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003450 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003451
3452 err = mOMX->set_config(mNode, index, &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003453 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003454#endif
3455
3456 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003457 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003458 def.nPortIndex = kPortIndexOutput;
3459
Andreas Huber784202e2009-10-15 13:46:54 -07003460 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003461 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003462 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003463
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003464 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huberbe06d262009-08-14 14:37:10 -07003465
3466 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07003467
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003468 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07003469 imageDef->eColorFormat = format;
3470 imageDef->nFrameWidth = width;
3471 imageDef->nFrameHeight = height;
3472
3473 switch (format) {
3474 case OMX_COLOR_FormatYUV420PackedPlanar:
3475 case OMX_COLOR_FormatYUV411Planar:
3476 {
3477 def.nBufferSize = (width * height * 3) / 2;
3478 break;
3479 }
3480
3481 case OMX_COLOR_FormatCbYCrY:
3482 {
3483 def.nBufferSize = width * height * 2;
3484 break;
3485 }
3486
3487 case OMX_COLOR_Format32bitARGB8888:
3488 {
3489 def.nBufferSize = width * height * 4;
3490 break;
3491 }
3492
Andreas Huber201511c2009-09-08 14:01:44 -07003493 case OMX_COLOR_Format16bitARGB4444:
3494 case OMX_COLOR_Format16bitARGB1555:
3495 case OMX_COLOR_Format16bitRGB565:
3496 case OMX_COLOR_Format16bitBGR565:
3497 {
3498 def.nBufferSize = width * height * 2;
3499 break;
3500 }
3501
Andreas Huberbe06d262009-08-14 14:37:10 -07003502 default:
3503 CHECK(!"Should not be here. Unknown color format.");
3504 break;
3505 }
3506
Andreas Huber5c0a9132009-08-20 11:16:40 -07003507 def.nBufferCountActual = def.nBufferCountMin;
3508
Andreas Huber784202e2009-10-15 13:46:54 -07003509 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003510 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003511 CHECK_EQ(err, (status_t)OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003512}
Andreas Huberbe06d262009-08-14 14:37:10 -07003513
Andreas Huber5c0a9132009-08-20 11:16:40 -07003514void OMXCodec::setJPEGInputFormat(
3515 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
3516 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003517 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003518 def.nPortIndex = kPortIndexInput;
3519
Andreas Huber784202e2009-10-15 13:46:54 -07003520 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003521 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003522 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003523
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003524 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003525 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3526
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003527 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingJPEG);
Andreas Huberbe06d262009-08-14 14:37:10 -07003528 imageDef->nFrameWidth = width;
3529 imageDef->nFrameHeight = height;
3530
Andreas Huber5c0a9132009-08-20 11:16:40 -07003531 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07003532 def.nBufferCountActual = def.nBufferCountMin;
3533
Andreas Huber784202e2009-10-15 13:46:54 -07003534 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003535 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003536 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003537}
3538
3539void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
3540 CodecSpecificData *specific =
3541 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
3542
3543 specific->mSize = size;
3544 memcpy(specific->mData, data, size);
3545
3546 mCodecSpecificData.push(specific);
3547}
3548
3549void OMXCodec::clearCodecSpecificData() {
3550 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
3551 free(mCodecSpecificData.editItemAt(i));
3552 }
3553 mCodecSpecificData.clear();
3554 mCodecSpecificDataIndex = 0;
3555}
3556
James Dong36e573b2010-06-19 09:04:18 -07003557status_t OMXCodec::start(MetaData *meta) {
Andreas Huber42978e52009-08-27 10:08:39 -07003558 Mutex::Autolock autoLock(mLock);
3559
Andreas Huberbe06d262009-08-14 14:37:10 -07003560 if (mState != LOADED) {
3561 return UNKNOWN_ERROR;
3562 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07003563
Andreas Huberbe06d262009-08-14 14:37:10 -07003564 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07003565 if (mQuirks & kWantsNALFragments) {
3566 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07003567 }
James Dong36e573b2010-06-19 09:04:18 -07003568 if (meta) {
3569 int64_t startTimeUs = 0;
3570 int64_t timeUs;
3571 if (meta->findInt64(kKeyTime, &timeUs)) {
3572 startTimeUs = timeUs;
3573 }
3574 params->setInt64(kKeyTime, startTimeUs);
3575 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003576 status_t err = mSource->start(params.get());
3577
3578 if (err != OK) {
3579 return err;
3580 }
3581
3582 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07003583 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003584 mSignalledEOS = false;
3585 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07003586 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003587 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003588 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
3589 mTargetTimeUs = -1;
Andreas Huberbe06d262009-08-14 14:37:10 -07003590 mFilledBuffers.clear();
Andreas Huber1f24b302010-06-10 11:12:39 -07003591 mPaused = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003592
3593 return init();
3594}
3595
3596status_t OMXCodec::stop() {
James Dong2c17f052011-07-14 16:22:47 -07003597 CODEC_LOGV("stop mState=%d", mState);
Andreas Huberbe06d262009-08-14 14:37:10 -07003598
3599 Mutex::Autolock autoLock(mLock);
3600
3601 while (isIntermediateState(mState)) {
3602 mAsyncCompletion.wait(mLock);
3603 }
3604
Jamie Gennis6607b392011-10-19 21:14:13 -07003605 bool isError = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003606 switch (mState) {
3607 case LOADED:
Andreas Huberbe06d262009-08-14 14:37:10 -07003608 break;
3609
Jamie Gennis6607b392011-10-19 21:14:13 -07003610 case ERROR:
3611 {
3612 OMX_STATETYPE state = OMX_StateInvalid;
3613 status_t err = mOMX->getState(mNode, &state);
3614 CHECK_EQ(err, (status_t)OK);
3615
3616 if (state != OMX_StateExecuting) {
3617 break;
3618 }
3619 // else fall through to the idling code
3620 isError = true;
3621 }
3622
Andreas Huberbe06d262009-08-14 14:37:10 -07003623 case EXECUTING:
3624 {
3625 setState(EXECUTING_TO_IDLE);
3626
Andreas Huber127fcdc2009-08-26 16:27:02 -07003627 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07003628 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07003629 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07003630
Andreas Huber127fcdc2009-08-26 16:27:02 -07003631 bool emulateInputFlushCompletion =
3632 !flushPortAsync(kPortIndexInput);
3633
3634 bool emulateOutputFlushCompletion =
3635 !flushPortAsync(kPortIndexOutput);
3636
3637 if (emulateInputFlushCompletion) {
3638 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3639 }
3640
3641 if (emulateOutputFlushCompletion) {
3642 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3643 }
3644 } else {
3645 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
3646 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
3647
3648 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07003649 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003650 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07003651 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003652
3653 while (mState != LOADED && mState != ERROR) {
3654 mAsyncCompletion.wait(mLock);
3655 }
3656
Jamie Gennis6607b392011-10-19 21:14:13 -07003657 if (isError) {
3658 // We were in the ERROR state coming in, so restore that now
3659 // that we've idled the OMX component.
3660 setState(ERROR);
3661 }
3662
Andreas Huberbe06d262009-08-14 14:37:10 -07003663 break;
3664 }
3665
3666 default:
3667 {
3668 CHECK(!"should not be here.");
3669 break;
3670 }
3671 }
3672
Andreas Hubera4357ad2010-04-02 12:49:54 -07003673 if (mLeftOverBuffer) {
3674 mLeftOverBuffer->release();
3675 mLeftOverBuffer = NULL;
3676 }
3677
Andreas Huberbe06d262009-08-14 14:37:10 -07003678 mSource->stop();
3679
Andreas Huber262d7e82011-09-27 15:05:40 -07003680 CODEC_LOGV("stopped in state %d", mState);
Andreas Huber4a9375e2010-02-09 11:54:33 -08003681
Andreas Huberbe06d262009-08-14 14:37:10 -07003682 return OK;
3683}
3684
3685sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07003686 Mutex::Autolock autoLock(mLock);
3687
Andreas Huberbe06d262009-08-14 14:37:10 -07003688 return mOutputFormat;
3689}
3690
3691status_t OMXCodec::read(
3692 MediaBuffer **buffer, const ReadOptions *options) {
James Dongd9ac6212011-07-15 15:25:36 -07003693 status_t err = OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07003694 *buffer = NULL;
3695
3696 Mutex::Autolock autoLock(mLock);
3697
Andreas Huberd06e5b82009-08-28 13:18:14 -07003698 if (mState != EXECUTING && mState != RECONFIGURING) {
3699 return UNKNOWN_ERROR;
3700 }
3701
Andreas Hubere981c332009-10-22 13:49:30 -07003702 bool seeking = false;
3703 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003704 ReadOptions::SeekMode seekMode;
3705 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
Andreas Hubere981c332009-10-22 13:49:30 -07003706 seeking = true;
3707 }
3708
Andreas Huber42978e52009-08-27 10:08:39 -07003709 if (mInitialBufferSubmit) {
3710 mInitialBufferSubmit = false;
3711
Andreas Hubere981c332009-10-22 13:49:30 -07003712 if (seeking) {
3713 CHECK(seekTimeUs >= 0);
3714 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003715 mSeekMode = seekMode;
Andreas Hubere981c332009-10-22 13:49:30 -07003716
3717 // There's no reason to trigger the code below, there's
3718 // nothing to flush yet.
3719 seeking = false;
Andreas Huber1f24b302010-06-10 11:12:39 -07003720 mPaused = false;
Andreas Hubere981c332009-10-22 13:49:30 -07003721 }
3722
Andreas Huber42978e52009-08-27 10:08:39 -07003723 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07003724
Andreas Huberd06e5b82009-08-28 13:18:14 -07003725 if (mState == EXECUTING) {
3726 // Otherwise mState == RECONFIGURING and this code will trigger
3727 // after the output port is reenabled.
3728 fillOutputBuffers();
3729 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003730 }
3731
Andreas Hubere981c332009-10-22 13:49:30 -07003732 if (seeking) {
Andreas Huberb9289832011-02-08 13:10:25 -08003733 while (mState == RECONFIGURING) {
James Dongd9ac6212011-07-15 15:25:36 -07003734 if ((err = waitForBufferFilled_l()) != OK) {
3735 return err;
3736 }
Andreas Huberb9289832011-02-08 13:10:25 -08003737 }
3738
3739 if (mState != EXECUTING) {
3740 return UNKNOWN_ERROR;
3741 }
3742
Andreas Huber4c483422009-09-02 16:05:36 -07003743 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07003744
3745 mSignalledEOS = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003746
3747 CHECK(seekTimeUs >= 0);
3748 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003749 mSeekMode = seekMode;
Andreas Huberbe06d262009-08-14 14:37:10 -07003750
3751 mFilledBuffers.clear();
3752
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003753 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07003754
Andreas Huber404cc412009-08-25 14:26:05 -07003755 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
3756 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
3757
3758 if (emulateInputFlushCompletion) {
3759 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3760 }
3761
3762 if (emulateOutputFlushCompletion) {
3763 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3764 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003765
3766 while (mSeekTimeUs >= 0) {
James Dongd9ac6212011-07-15 15:25:36 -07003767 if ((err = waitForBufferFilled_l()) != OK) {
3768 return err;
3769 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003770 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003771 }
3772
3773 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
James Dongd9ac6212011-07-15 15:25:36 -07003774 if ((err = waitForBufferFilled_l()) != OK) {
3775 return err;
James Dong74556302010-12-20 21:29:12 -08003776 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003777 }
3778
3779 if (mState == ERROR) {
3780 return UNKNOWN_ERROR;
3781 }
3782
3783 if (mFilledBuffers.empty()) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08003784 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
Andreas Huberbe06d262009-08-14 14:37:10 -07003785 }
3786
Andreas Hubercfd55572009-10-09 14:11:28 -07003787 if (mOutputPortSettingsHaveChanged) {
3788 mOutputPortSettingsHaveChanged = false;
3789
3790 return INFO_FORMAT_CHANGED;
3791 }
3792
Andreas Huberbe06d262009-08-14 14:37:10 -07003793 size_t index = *mFilledBuffers.begin();
3794 mFilledBuffers.erase(mFilledBuffers.begin());
3795
3796 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003797 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
3798 info->mStatus = OWNED_BY_CLIENT;
3799
Andreas Huberbe06d262009-08-14 14:37:10 -07003800 info->mMediaBuffer->add_ref();
3801 *buffer = info->mMediaBuffer;
3802
3803 return OK;
3804}
3805
3806void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
3807 Mutex::Autolock autoLock(mLock);
3808
3809 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3810 for (size_t i = 0; i < buffers->size(); ++i) {
3811 BufferInfo *info = &buffers->editItemAt(i);
3812
3813 if (info->mMediaBuffer == buffer) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003814 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003815 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
3816
3817 info->mStatus = OWNED_BY_US;
3818
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003819 if (buffer->graphicBuffer() == 0) {
3820 fillOutputBuffer(info);
3821 } else {
3822 sp<MetaData> metaData = info->mMediaBuffer->meta_data();
3823 int32_t rendered = 0;
3824 if (!metaData->findInt32(kKeyRendered, &rendered)) {
3825 rendered = 0;
3826 }
3827 if (!rendered) {
3828 status_t err = cancelBufferToNativeWindow(info);
3829 if (err < 0) {
3830 return;
3831 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003832 }
3833
Andreas Huberbbbcf652010-12-07 14:25:54 -08003834 info->mStatus = OWNED_BY_NATIVE_WINDOW;
3835
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003836 // Dequeue the next buffer from the native window.
3837 BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
3838 if (nextBufInfo == 0) {
3839 return;
3840 }
3841
3842 // Give the buffer to the OMX node to fill.
3843 fillOutputBuffer(nextBufInfo);
3844 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003845 return;
3846 }
3847 }
3848
3849 CHECK(!"should not be here.");
3850}
3851
3852static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
3853 static const char *kNames[] = {
3854 "OMX_IMAGE_CodingUnused",
3855 "OMX_IMAGE_CodingAutoDetect",
3856 "OMX_IMAGE_CodingJPEG",
3857 "OMX_IMAGE_CodingJPEG2K",
3858 "OMX_IMAGE_CodingEXIF",
3859 "OMX_IMAGE_CodingTIFF",
3860 "OMX_IMAGE_CodingGIF",
3861 "OMX_IMAGE_CodingPNG",
3862 "OMX_IMAGE_CodingLZW",
3863 "OMX_IMAGE_CodingBMP",
3864 };
3865
3866 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3867
3868 if (type < 0 || (size_t)type >= numNames) {
3869 return "UNKNOWN";
3870 } else {
3871 return kNames[type];
3872 }
3873}
3874
3875static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
3876 static const char *kNames[] = {
3877 "OMX_COLOR_FormatUnused",
3878 "OMX_COLOR_FormatMonochrome",
3879 "OMX_COLOR_Format8bitRGB332",
3880 "OMX_COLOR_Format12bitRGB444",
3881 "OMX_COLOR_Format16bitARGB4444",
3882 "OMX_COLOR_Format16bitARGB1555",
3883 "OMX_COLOR_Format16bitRGB565",
3884 "OMX_COLOR_Format16bitBGR565",
3885 "OMX_COLOR_Format18bitRGB666",
3886 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003887 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07003888 "OMX_COLOR_Format24bitRGB888",
3889 "OMX_COLOR_Format24bitBGR888",
3890 "OMX_COLOR_Format24bitARGB1887",
3891 "OMX_COLOR_Format25bitARGB1888",
3892 "OMX_COLOR_Format32bitBGRA8888",
3893 "OMX_COLOR_Format32bitARGB8888",
3894 "OMX_COLOR_FormatYUV411Planar",
3895 "OMX_COLOR_FormatYUV411PackedPlanar",
3896 "OMX_COLOR_FormatYUV420Planar",
3897 "OMX_COLOR_FormatYUV420PackedPlanar",
3898 "OMX_COLOR_FormatYUV420SemiPlanar",
3899 "OMX_COLOR_FormatYUV422Planar",
3900 "OMX_COLOR_FormatYUV422PackedPlanar",
3901 "OMX_COLOR_FormatYUV422SemiPlanar",
3902 "OMX_COLOR_FormatYCbYCr",
3903 "OMX_COLOR_FormatYCrYCb",
3904 "OMX_COLOR_FormatCbYCrY",
3905 "OMX_COLOR_FormatCrYCbY",
3906 "OMX_COLOR_FormatYUV444Interleaved",
3907 "OMX_COLOR_FormatRawBayer8bit",
3908 "OMX_COLOR_FormatRawBayer10bit",
3909 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003910 "OMX_COLOR_FormatL2",
3911 "OMX_COLOR_FormatL4",
3912 "OMX_COLOR_FormatL8",
3913 "OMX_COLOR_FormatL16",
3914 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07003915 "OMX_COLOR_FormatL32",
3916 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
3917 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
3918 "OMX_COLOR_Format18BitBGR666",
3919 "OMX_COLOR_Format24BitARGB6666",
3920 "OMX_COLOR_Format24BitABGR6666",
3921 };
3922
3923 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3924
Anu Sundararajand35df442011-06-22 12:24:46 -05003925 if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
3926 return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
3927 } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003928 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
3929 } else if (type < 0 || (size_t)type >= numNames) {
3930 return "UNKNOWN";
3931 } else {
3932 return kNames[type];
3933 }
3934}
3935
3936static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
3937 static const char *kNames[] = {
3938 "OMX_VIDEO_CodingUnused",
3939 "OMX_VIDEO_CodingAutoDetect",
3940 "OMX_VIDEO_CodingMPEG2",
3941 "OMX_VIDEO_CodingH263",
3942 "OMX_VIDEO_CodingMPEG4",
3943 "OMX_VIDEO_CodingWMV",
3944 "OMX_VIDEO_CodingRV",
3945 "OMX_VIDEO_CodingAVC",
3946 "OMX_VIDEO_CodingMJPEG",
3947 };
3948
3949 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3950
3951 if (type < 0 || (size_t)type >= numNames) {
3952 return "UNKNOWN";
3953 } else {
3954 return kNames[type];
3955 }
3956}
3957
3958static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
3959 static const char *kNames[] = {
3960 "OMX_AUDIO_CodingUnused",
3961 "OMX_AUDIO_CodingAutoDetect",
3962 "OMX_AUDIO_CodingPCM",
3963 "OMX_AUDIO_CodingADPCM",
3964 "OMX_AUDIO_CodingAMR",
3965 "OMX_AUDIO_CodingGSMFR",
3966 "OMX_AUDIO_CodingGSMEFR",
3967 "OMX_AUDIO_CodingGSMHR",
3968 "OMX_AUDIO_CodingPDCFR",
3969 "OMX_AUDIO_CodingPDCEFR",
3970 "OMX_AUDIO_CodingPDCHR",
3971 "OMX_AUDIO_CodingTDMAFR",
3972 "OMX_AUDIO_CodingTDMAEFR",
3973 "OMX_AUDIO_CodingQCELP8",
3974 "OMX_AUDIO_CodingQCELP13",
3975 "OMX_AUDIO_CodingEVRC",
3976 "OMX_AUDIO_CodingSMV",
3977 "OMX_AUDIO_CodingG711",
3978 "OMX_AUDIO_CodingG723",
3979 "OMX_AUDIO_CodingG726",
3980 "OMX_AUDIO_CodingG729",
3981 "OMX_AUDIO_CodingAAC",
3982 "OMX_AUDIO_CodingMP3",
3983 "OMX_AUDIO_CodingSBC",
3984 "OMX_AUDIO_CodingVORBIS",
3985 "OMX_AUDIO_CodingWMA",
3986 "OMX_AUDIO_CodingRA",
3987 "OMX_AUDIO_CodingMIDI",
3988 };
3989
3990 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3991
3992 if (type < 0 || (size_t)type >= numNames) {
3993 return "UNKNOWN";
3994 } else {
3995 return kNames[type];
3996 }
3997}
3998
3999static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
4000 static const char *kNames[] = {
4001 "OMX_AUDIO_PCMModeLinear",
4002 "OMX_AUDIO_PCMModeALaw",
4003 "OMX_AUDIO_PCMModeMULaw",
4004 };
4005
4006 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4007
4008 if (type < 0 || (size_t)type >= numNames) {
4009 return "UNKNOWN";
4010 } else {
4011 return kNames[type];
4012 }
4013}
4014
Andreas Huber7ae02c82009-09-09 16:29:47 -07004015static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
4016 static const char *kNames[] = {
4017 "OMX_AUDIO_AMRBandModeUnused",
4018 "OMX_AUDIO_AMRBandModeNB0",
4019 "OMX_AUDIO_AMRBandModeNB1",
4020 "OMX_AUDIO_AMRBandModeNB2",
4021 "OMX_AUDIO_AMRBandModeNB3",
4022 "OMX_AUDIO_AMRBandModeNB4",
4023 "OMX_AUDIO_AMRBandModeNB5",
4024 "OMX_AUDIO_AMRBandModeNB6",
4025 "OMX_AUDIO_AMRBandModeNB7",
4026 "OMX_AUDIO_AMRBandModeWB0",
4027 "OMX_AUDIO_AMRBandModeWB1",
4028 "OMX_AUDIO_AMRBandModeWB2",
4029 "OMX_AUDIO_AMRBandModeWB3",
4030 "OMX_AUDIO_AMRBandModeWB4",
4031 "OMX_AUDIO_AMRBandModeWB5",
4032 "OMX_AUDIO_AMRBandModeWB6",
4033 "OMX_AUDIO_AMRBandModeWB7",
4034 "OMX_AUDIO_AMRBandModeWB8",
4035 };
4036
4037 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4038
4039 if (type < 0 || (size_t)type >= numNames) {
4040 return "UNKNOWN";
4041 } else {
4042 return kNames[type];
4043 }
4044}
4045
4046static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
4047 static const char *kNames[] = {
4048 "OMX_AUDIO_AMRFrameFormatConformance",
4049 "OMX_AUDIO_AMRFrameFormatIF1",
4050 "OMX_AUDIO_AMRFrameFormatIF2",
4051 "OMX_AUDIO_AMRFrameFormatFSF",
4052 "OMX_AUDIO_AMRFrameFormatRTPPayload",
4053 "OMX_AUDIO_AMRFrameFormatITU",
4054 };
4055
4056 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4057
4058 if (type < 0 || (size_t)type >= numNames) {
4059 return "UNKNOWN";
4060 } else {
4061 return kNames[type];
4062 }
4063}
Andreas Huberbe06d262009-08-14 14:37:10 -07004064
4065void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
4066 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07004067 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07004068 def.nPortIndex = portIndex;
4069
Andreas Huber784202e2009-10-15 13:46:54 -07004070 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004071 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004072 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004073
4074 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
4075
4076 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
4077 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
4078
4079 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
4080 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
4081 printf(" nBufferSize = %ld\n", def.nBufferSize);
4082
4083 switch (def.eDomain) {
4084 case OMX_PortDomainImage:
4085 {
4086 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
4087
4088 printf("\n");
4089 printf(" // Image\n");
4090 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
4091 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
4092 printf(" nStride = %ld\n", imageDef->nStride);
4093
4094 printf(" eCompressionFormat = %s\n",
4095 imageCompressionFormatString(imageDef->eCompressionFormat));
4096
4097 printf(" eColorFormat = %s\n",
4098 colorFormatString(imageDef->eColorFormat));
4099
4100 break;
4101 }
4102
4103 case OMX_PortDomainVideo:
4104 {
4105 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4106
4107 printf("\n");
4108 printf(" // Video\n");
4109 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
4110 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
4111 printf(" nStride = %ld\n", videoDef->nStride);
4112
4113 printf(" eCompressionFormat = %s\n",
4114 videoCompressionFormatString(videoDef->eCompressionFormat));
4115
4116 printf(" eColorFormat = %s\n",
4117 colorFormatString(videoDef->eColorFormat));
4118
4119 break;
4120 }
4121
4122 case OMX_PortDomainAudio:
4123 {
4124 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4125
4126 printf("\n");
4127 printf(" // Audio\n");
4128 printf(" eEncoding = %s\n",
4129 audioCodingTypeString(audioDef->eEncoding));
4130
4131 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
4132 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07004133 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07004134 params.nPortIndex = portIndex;
4135
Andreas Huber784202e2009-10-15 13:46:54 -07004136 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004137 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004138 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004139
4140 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
4141 printf(" nChannels = %ld\n", params.nChannels);
4142 printf(" bInterleaved = %d\n", params.bInterleaved);
4143 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
4144
4145 printf(" eNumData = %s\n",
4146 params.eNumData == OMX_NumericalDataSigned
4147 ? "signed" : "unsigned");
4148
4149 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07004150 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
4151 OMX_AUDIO_PARAM_AMRTYPE amr;
4152 InitOMXParams(&amr);
4153 amr.nPortIndex = portIndex;
4154
Andreas Huber784202e2009-10-15 13:46:54 -07004155 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07004156 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004157 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004158
4159 printf(" nChannels = %ld\n", amr.nChannels);
4160 printf(" eAMRBandMode = %s\n",
4161 amrBandModeString(amr.eAMRBandMode));
4162 printf(" eAMRFrameFormat = %s\n",
4163 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07004164 }
4165
4166 break;
4167 }
4168
4169 default:
4170 {
4171 printf(" // Unknown\n");
4172 break;
4173 }
4174 }
4175
4176 printf("}\n");
4177}
4178
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004179status_t OMXCodec::initNativeWindow() {
4180 // Enable use of a GraphicBuffer as the output for this node. This must
4181 // happen before getting the IndexParamPortDefinition parameter because it
4182 // will affect the pixel format that the node reports.
4183 status_t err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
4184 if (err != 0) {
4185 return err;
4186 }
4187
4188 return OK;
4189}
4190
Lakshman Gowdadb62a242011-09-29 17:47:35 -07004191void OMXCodec::initNativeWindowCrop() {
4192 int32_t left, top, right, bottom;
4193
4194 CHECK(mOutputFormat->findRect(
4195 kKeyCropRect,
4196 &left, &top, &right, &bottom));
4197
4198 android_native_rect_t crop;
4199 crop.left = left;
4200 crop.top = top;
4201 crop.right = right + 1;
4202 crop.bottom = bottom + 1;
4203
4204 // We'll ignore any errors here, if the surface is
4205 // already invalid, we'll know soon enough.
4206 native_window_set_crop(mNativeWindow.get(), &crop);
4207}
4208
Andreas Huberbe06d262009-08-14 14:37:10 -07004209void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
4210 mOutputFormat = new MetaData;
4211 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
James Dong52d13f02010-07-02 11:39:06 -07004212 if (mIsEncoder) {
4213 int32_t timeScale;
4214 if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
4215 mOutputFormat->setInt32(kKeyTimeScale, timeScale);
4216 }
4217 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004218
4219 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07004220 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07004221 def.nPortIndex = kPortIndexOutput;
4222
Andreas Huber784202e2009-10-15 13:46:54 -07004223 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004224 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004225 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004226
4227 switch (def.eDomain) {
4228 case OMX_PortDomainImage:
4229 {
4230 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004231 CHECK_EQ((int)imageDef->eCompressionFormat,
4232 (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07004233
Andreas Hubere6c40962009-09-10 14:13:30 -07004234 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004235 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
4236 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
4237 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
4238 break;
4239 }
4240
4241 case OMX_PortDomainAudio:
4242 {
4243 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
4244
Andreas Huberda050cf22009-09-02 14:01:43 -07004245 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
4246 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07004247 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07004248 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07004249
Andreas Huber784202e2009-10-15 13:46:54 -07004250 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07004251 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004252 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004253
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004254 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
4255 CHECK_EQ(params.nBitPerSample, 16u);
4256 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07004257
Andreas Huberda050cf22009-09-02 14:01:43 -07004258 int32_t numChannels, sampleRate;
4259 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4260 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07004261
Andreas Huberda050cf22009-09-02 14:01:43 -07004262 if ((OMX_U32)numChannels != params.nChannels) {
Steve Block71f2cf12011-10-20 11:56:00 +01004263 ALOGV("Codec outputs a different number of channels than "
Andreas Hubere331c7b2010-02-01 10:51:50 -08004264 "the input stream contains (contains %d channels, "
4265 "codec outputs %ld channels).",
4266 numChannels, params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004267 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004268
Andreas Huber0920bca2011-05-18 09:31:22 -07004269 if (sampleRate != (int32_t)params.nSamplingRate) {
Steve Block71f2cf12011-10-20 11:56:00 +01004270 ALOGV("Codec outputs at different sampling rate than "
Andreas Huber4b3913a2011-05-11 14:13:42 -07004271 "what the input stream contains (contains data at "
Andreas Huber0920bca2011-05-18 09:31:22 -07004272 "%d Hz, codec outputs %lu Hz)",
Andreas Huber4b3913a2011-05-11 14:13:42 -07004273 sampleRate, params.nSamplingRate);
4274 }
4275
Andreas Hubere6c40962009-09-10 14:13:30 -07004276 mOutputFormat->setCString(
4277 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07004278
4279 // Use the codec-advertised number of channels, as some
4280 // codecs appear to output stereo even if the input data is
Andreas Hubere331c7b2010-02-01 10:51:50 -08004281 // mono. If we know the codec lies about this information,
4282 // use the actual number of channels instead.
4283 mOutputFormat->setInt32(
4284 kKeyChannelCount,
4285 (mQuirks & kDecoderLiesAboutNumberOfChannels)
4286 ? numChannels : params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004287
Andreas Huber4b3913a2011-05-11 14:13:42 -07004288 mOutputFormat->setInt32(kKeySampleRate, params.nSamplingRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004289 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07004290 OMX_AUDIO_PARAM_AMRTYPE amr;
4291 InitOMXParams(&amr);
4292 amr.nPortIndex = kPortIndexOutput;
4293
Andreas Huber784202e2009-10-15 13:46:54 -07004294 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07004295 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004296 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004297
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004298 CHECK_EQ(amr.nChannels, 1u);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004299 mOutputFormat->setInt32(kKeyChannelCount, 1);
4300
4301 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
4302 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004303 mOutputFormat->setCString(
4304 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004305 mOutputFormat->setInt32(kKeySampleRate, 8000);
4306 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
4307 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004308 mOutputFormat->setCString(
4309 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004310 mOutputFormat->setInt32(kKeySampleRate, 16000);
4311 } else {
4312 CHECK(!"Unknown AMR band mode.");
4313 }
Andreas Huberda050cf22009-09-02 14:01:43 -07004314 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004315 mOutputFormat->setCString(
4316 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
James Dong17299ab2010-05-14 15:45:22 -07004317 int32_t numChannels, sampleRate, bitRate;
James Dongabed93a2010-04-22 17:27:04 -07004318 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4319 inputFormat->findInt32(kKeySampleRate, &sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004320 inputFormat->findInt32(kKeyBitRate, &bitRate);
James Dongabed93a2010-04-22 17:27:04 -07004321 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
4322 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004323 mOutputFormat->setInt32(kKeyBitRate, bitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004324 } else {
4325 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07004326 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004327 break;
4328 }
4329
4330 case OMX_PortDomainVideo:
4331 {
4332 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4333
4334 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004335 mOutputFormat->setCString(
4336 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004337 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004338 mOutputFormat->setCString(
4339 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07004340 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004341 mOutputFormat->setCString(
4342 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07004343 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004344 mOutputFormat->setCString(
4345 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07004346 } else {
4347 CHECK(!"Unknown compression format.");
4348 }
4349
James Dong5592bcc2010-10-22 17:10:43 -07004350 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
4351 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
Andreas Huberbe06d262009-08-14 14:37:10 -07004352 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004353
James Dong0c9153d2010-11-23 11:30:21 -08004354 if (!mIsEncoder) {
4355 OMX_CONFIG_RECTTYPE rect;
James Donga1735412011-01-07 14:56:34 -08004356 InitOMXParams(&rect);
4357 rect.nPortIndex = kPortIndexOutput;
James Dong0c9153d2010-11-23 11:30:21 -08004358 status_t err =
4359 mOMX->getConfig(
4360 mNode, OMX_IndexConfigCommonOutputCrop,
4361 &rect, sizeof(rect));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004362
Andreas Huberf167f502011-06-24 13:15:30 -07004363 CODEC_LOGI(
4364 "video dimensions are %ld x %ld",
4365 video_def->nFrameWidth, video_def->nFrameHeight);
4366
James Dong0c9153d2010-11-23 11:30:21 -08004367 if (err == OK) {
4368 CHECK_GE(rect.nLeft, 0);
4369 CHECK_GE(rect.nTop, 0);
4370 CHECK_GE(rect.nWidth, 0u);
4371 CHECK_GE(rect.nHeight, 0u);
4372 CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
4373 CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004374
James Dong0c9153d2010-11-23 11:30:21 -08004375 mOutputFormat->setRect(
4376 kKeyCropRect,
4377 rect.nLeft,
4378 rect.nTop,
4379 rect.nLeft + rect.nWidth - 1,
4380 rect.nTop + rect.nHeight - 1);
Andreas Huberf167f502011-06-24 13:15:30 -07004381
4382 CODEC_LOGI(
4383 "Crop rect is %ld x %ld @ (%ld, %ld)",
4384 rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
James Dong0c9153d2010-11-23 11:30:21 -08004385 } else {
4386 mOutputFormat->setRect(
4387 kKeyCropRect,
4388 0, 0,
4389 video_def->nFrameWidth - 1,
4390 video_def->nFrameHeight - 1);
4391 }
Lakshman Gowdadb62a242011-09-29 17:47:35 -07004392
4393 if (mNativeWindow != NULL) {
4394 initNativeWindowCrop();
4395 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004396 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004397 break;
4398 }
4399
4400 default:
4401 {
4402 CHECK(!"should not be here, neither audio nor video.");
4403 break;
4404 }
4405 }
Andreas Huber0920bca2011-05-18 09:31:22 -07004406
4407 // If the input format contains rotation information, flag the output
4408 // format accordingly.
4409
4410 int32_t rotationDegrees;
4411 if (mSource->getFormat()->findInt32(kKeyRotation, &rotationDegrees)) {
4412 mOutputFormat->setInt32(kKeyRotation, rotationDegrees);
4413 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004414}
4415
Andreas Huber1f24b302010-06-10 11:12:39 -07004416status_t OMXCodec::pause() {
4417 Mutex::Autolock autoLock(mLock);
4418
4419 mPaused = true;
4420
4421 return OK;
4422}
4423
Andreas Hubere6c40962009-09-10 14:13:30 -07004424////////////////////////////////////////////////////////////////////////////////
4425
4426status_t QueryCodecs(
4427 const sp<IOMX> &omx,
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004428 const char *mime, bool queryDecoders, bool hwCodecOnly,
Andreas Hubere6c40962009-09-10 14:13:30 -07004429 Vector<CodecCapabilities> *results) {
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004430 Vector<String8> matchingCodecs;
Andreas Hubere6c40962009-09-10 14:13:30 -07004431 results->clear();
4432
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004433 OMXCodec::findMatchingCodecs(mime,
4434 !queryDecoders /*createEncoder*/,
4435 NULL /*matchComponentName*/,
4436 hwCodecOnly ? OMXCodec::kHardwareCodecsOnly : 0 /*flags*/,
4437 &matchingCodecs);
Andreas Hubere6c40962009-09-10 14:13:30 -07004438
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004439 for (size_t c = 0; c < matchingCodecs.size(); c++) {
4440 const char *componentName = matchingCodecs.itemAt(c).string();
Andreas Hubere6c40962009-09-10 14:13:30 -07004441
Andreas Huber1a189a82010-03-24 13:49:20 -07004442 if (strncmp(componentName, "OMX.", 4)) {
4443 // Not an OpenMax component but a software codec.
4444
4445 results->push();
4446 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4447 caps->mComponentName = componentName;
Andreas Huber1a189a82010-03-24 13:49:20 -07004448 continue;
4449 }
4450
Andreas Huber784202e2009-10-15 13:46:54 -07004451 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07004452 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07004453 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07004454
4455 if (err != OK) {
4456 continue;
4457 }
4458
James Dong722d5912010-04-13 10:56:59 -07004459 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
Andreas Hubere6c40962009-09-10 14:13:30 -07004460
4461 results->push();
4462 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4463 caps->mComponentName = componentName;
4464
4465 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
4466 InitOMXParams(&param);
4467
4468 param.nPortIndex = queryDecoders ? 0 : 1;
4469
4470 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07004471 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07004472 node, OMX_IndexParamVideoProfileLevelQuerySupported,
4473 &param, sizeof(param));
4474
4475 if (err != OK) {
4476 break;
4477 }
4478
4479 CodecProfileLevel profileLevel;
4480 profileLevel.mProfile = param.eProfile;
4481 profileLevel.mLevel = param.eLevel;
4482
4483 caps->mProfileLevels.push(profileLevel);
4484 }
4485
James Dongd7810892010-11-11 00:33:05 -08004486 // Color format query
4487 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
4488 InitOMXParams(&portFormat);
4489 portFormat.nPortIndex = queryDecoders ? 1 : 0;
4490 for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
4491 err = omx->getParameter(
4492 node, OMX_IndexParamVideoPortFormat,
4493 &portFormat, sizeof(portFormat));
4494 if (err != OK) {
4495 break;
4496 }
4497 caps->mColorFormats.push(portFormat.eColorFormat);
4498 }
4499
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004500 CHECK_EQ(omx->freeNode(node), (status_t)OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07004501 }
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004502
4503 return OK;
Andreas Hubere6c40962009-09-10 14:13:30 -07004504}
4505
Jean-Michel Trivia05f0992011-07-22 09:52:39 -07004506status_t QueryCodecs(
4507 const sp<IOMX> &omx,
4508 const char *mimeType, bool queryDecoders,
4509 Vector<CodecCapabilities> *results) {
4510 return QueryCodecs(omx, mimeType, queryDecoders, false /*hwCodecOnly*/, results);
4511}
4512
James Dong31b9375f2010-11-10 21:11:41 -08004513void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
4514 CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
4515 CHECK(mOMXLivesLocally);
4516
4517 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
4518 header->pBuffer = (OMX_U8 *)info->mData;
4519}
4520
Andreas Huberbe06d262009-08-14 14:37:10 -07004521} // namespace android