blob: 76c8870207c03099b4e27379290dfd1e363cf37d [file] [log] [blame]
Andreas Huberbe06d262009-08-14 14:37:10 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXCodec"
19#include <utils/Log.h>
20
Andreas Huberdacaa732009-12-07 09:56:32 -080021#include "include/AACDecoder.h"
James Dong17299ab2010-05-14 15:45:22 -070022#include "include/AACEncoder.h"
Andreas Hubera30d4002009-12-08 15:40:06 -080023#include "include/AMRNBDecoder.h"
Andreas Huberd49b526dd2009-12-11 15:07:25 -080024#include "include/AMRNBEncoder.h"
Andreas Hubera30d4002009-12-08 15:40:06 -080025#include "include/AMRWBDecoder.h"
James Dong17299ab2010-05-14 15:45:22 -070026#include "include/AMRWBEncoder.h"
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080027#include "include/AVCDecoder.h"
James Dong1cc31e62010-07-02 17:44:44 -070028#include "include/AVCEncoder.h"
Andreas Huber520b2a72010-08-09 09:54:59 -070029#include "include/G711Decoder.h"
James Dong02f5b542009-12-15 16:26:55 -080030#include "include/M4vH263Decoder.h"
James Dong42ef0c72010-07-12 21:46:25 -070031#include "include/M4vH263Encoder.h"
Andreas Huber250f2432009-12-07 14:22:35 -080032#include "include/MP3Decoder.h"
Andreas Huber388379f2010-05-07 10:35:13 -070033#include "include/VorbisDecoder.h"
Andreas Huber47ba30e2010-05-24 14:38:02 -070034#include "include/VPXDecoder.h"
Andreas Huber8c7ab032009-12-07 11:23:44 -080035
Andreas Huberbd7b43b2009-10-13 10:22:55 -070036#include "include/ESDS.h"
37
Andreas Huberbe06d262009-08-14 14:37:10 -070038#include <binder/IServiceManager.h>
39#include <binder/MemoryDealer.h>
40#include <binder/ProcessState.h>
41#include <media/IMediaPlayerService.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070042#include <media/stagefright/MediaBuffer.h>
43#include <media/stagefright/MediaBufferGroup.h>
44#include <media/stagefright/MediaDebug.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070045#include <media/stagefright/MediaDefs.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070046#include <media/stagefright/MediaExtractor.h>
47#include <media/stagefright/MetaData.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070048#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070049#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070050#include <utils/Vector.h>
51
52#include <OMX_Audio.h>
53#include <OMX_Component.h>
54
Andreas Huber8946ab22010-09-15 16:20:42 -070055#include "include/ThreadedSource.h"
56
Andreas Huberbe06d262009-08-14 14:37:10 -070057namespace android {
58
Andreas Huber8b432b12009-10-07 13:36:52 -070059static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
60
Andreas Huberbe06d262009-08-14 14:37:10 -070061struct CodecInfo {
62 const char *mime;
63 const char *codec;
64};
65
Andreas Huberfb1c2f82009-12-15 13:25:11 -080066#define FACTORY_CREATE(name) \
67static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
68 return new name(source); \
69}
70
James Dong17299ab2010-05-14 15:45:22 -070071#define FACTORY_CREATE_ENCODER(name) \
72static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
73 return new name(source, meta); \
74}
75
Andreas Huberfb1c2f82009-12-15 13:25:11 -080076#define FACTORY_REF(name) { #name, Make##name },
77
78FACTORY_CREATE(MP3Decoder)
79FACTORY_CREATE(AMRNBDecoder)
80FACTORY_CREATE(AMRWBDecoder)
81FACTORY_CREATE(AACDecoder)
82FACTORY_CREATE(AVCDecoder)
Andreas Huber520b2a72010-08-09 09:54:59 -070083FACTORY_CREATE(G711Decoder)
James Dong02f5b542009-12-15 16:26:55 -080084FACTORY_CREATE(M4vH263Decoder)
Andreas Huber388379f2010-05-07 10:35:13 -070085FACTORY_CREATE(VorbisDecoder)
Andreas Huber47ba30e2010-05-24 14:38:02 -070086FACTORY_CREATE(VPXDecoder)
James Dong17299ab2010-05-14 15:45:22 -070087FACTORY_CREATE_ENCODER(AMRNBEncoder)
88FACTORY_CREATE_ENCODER(AMRWBEncoder)
89FACTORY_CREATE_ENCODER(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070090FACTORY_CREATE_ENCODER(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070091FACTORY_CREATE_ENCODER(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070092
93static sp<MediaSource> InstantiateSoftwareEncoder(
94 const char *name, const sp<MediaSource> &source,
95 const sp<MetaData> &meta) {
96 struct FactoryInfo {
97 const char *name;
98 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
99 };
100
101 static const FactoryInfo kFactoryInfo[] = {
102 FACTORY_REF(AMRNBEncoder)
103 FACTORY_REF(AMRWBEncoder)
104 FACTORY_REF(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -0700105 FACTORY_REF(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -0700106 FACTORY_REF(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -0700107 };
108 for (size_t i = 0;
109 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
110 if (!strcmp(name, kFactoryInfo[i].name)) {
111 return (*kFactoryInfo[i].CreateFunc)(source, meta);
112 }
113 }
114
115 return NULL;
116}
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800117
118static sp<MediaSource> InstantiateSoftwareCodec(
119 const char *name, const sp<MediaSource> &source) {
120 struct FactoryInfo {
121 const char *name;
122 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
123 };
124
125 static const FactoryInfo kFactoryInfo[] = {
126 FACTORY_REF(MP3Decoder)
127 FACTORY_REF(AMRNBDecoder)
128 FACTORY_REF(AMRWBDecoder)
129 FACTORY_REF(AACDecoder)
130 FACTORY_REF(AVCDecoder)
Andreas Huber520b2a72010-08-09 09:54:59 -0700131 FACTORY_REF(G711Decoder)
James Dong02f5b542009-12-15 16:26:55 -0800132 FACTORY_REF(M4vH263Decoder)
Andreas Huber388379f2010-05-07 10:35:13 -0700133 FACTORY_REF(VorbisDecoder)
Andreas Huber47ba30e2010-05-24 14:38:02 -0700134 FACTORY_REF(VPXDecoder)
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800135 };
136 for (size_t i = 0;
137 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
138 if (!strcmp(name, kFactoryInfo[i].name)) {
Andreas Huber8946ab22010-09-15 16:20:42 -0700139 if (!strcmp(name, "VPXDecoder")) {
140 return new ThreadedSource(
141 (*kFactoryInfo[i].CreateFunc)(source));
142 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800143 return (*kFactoryInfo[i].CreateFunc)(source);
144 }
145 }
146
147 return NULL;
148}
149
150#undef FACTORY_REF
151#undef FACTORY_CREATE
152
Andreas Huberbe06d262009-08-14 14:37:10 -0700153static const CodecInfo kDecoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700154 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
James Dong374aee62010-04-26 10:23:30 -0700155// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800156 { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700157// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
Andreas Hubera4357ad2010-04-02 12:49:54 -0700158// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800159 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700160// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700161 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800162 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700163// { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700164 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800165 { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700166// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
Andreas Huber520b2a72010-08-09 09:54:59 -0700167 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
168 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700169 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700170 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
171 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700172 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800173 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700174// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700175 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700176 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700177 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800178 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700179// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700180 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700181 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
182 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700183 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800184 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700185// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
Andreas Huber388379f2010-05-07 10:35:13 -0700186 { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
Andreas Huber47ba30e2010-05-24 14:38:02 -0700187 { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700188};
189
190static const CodecInfo kEncoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700191 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800192 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700193 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700194 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700195 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700196 { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700197// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
198 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700199 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
200 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700201 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700202 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700203// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
204 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700205 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
206 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700207 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700208 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700209// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
210 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
Andreas Huber71c27d92010-03-19 11:43:15 -0700211 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700212 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700213 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Encoder" },
James Dong1cc31e62010-07-02 17:44:44 -0700214 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700215// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700216};
217
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800218#undef OPTIONAL
219
Andreas Hubere0873732009-09-10 09:57:53 -0700220#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700221#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber42c444a2010-02-09 10:20:00 -0800222#define CODEC_LOGE(x, ...) LOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700223
Andreas Huberbe06d262009-08-14 14:37:10 -0700224struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -0700225 OMXCodecObserver() {
226 }
227
228 void setCodec(const sp<OMXCodec> &target) {
229 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -0700230 }
231
232 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -0700233 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700234 sp<OMXCodec> codec = mTarget.promote();
235
236 if (codec.get() != NULL) {
237 codec->on_message(msg);
238 }
239 }
240
241protected:
242 virtual ~OMXCodecObserver() {}
243
244private:
245 wp<OMXCodec> mTarget;
246
247 OMXCodecObserver(const OMXCodecObserver &);
248 OMXCodecObserver &operator=(const OMXCodecObserver &);
249};
250
251static const char *GetCodec(const CodecInfo *info, size_t numInfos,
252 const char *mime, int index) {
253 CHECK(index >= 0);
254 for(size_t i = 0; i < numInfos; ++i) {
255 if (!strcasecmp(mime, info[i].mime)) {
256 if (index == 0) {
257 return info[i].codec;
258 }
259
260 --index;
261 }
262 }
263
264 return NULL;
265}
266
Andreas Huberebf66ea2009-08-19 13:32:58 -0700267enum {
268 kAVCProfileBaseline = 0x42,
269 kAVCProfileMain = 0x4d,
270 kAVCProfileExtended = 0x58,
271 kAVCProfileHigh = 0x64,
272 kAVCProfileHigh10 = 0x6e,
273 kAVCProfileHigh422 = 0x7a,
274 kAVCProfileHigh444 = 0xf4,
275 kAVCProfileCAVLC444Intra = 0x2c
276};
277
278static const char *AVCProfileToString(uint8_t profile) {
279 switch (profile) {
280 case kAVCProfileBaseline:
281 return "Baseline";
282 case kAVCProfileMain:
283 return "Main";
284 case kAVCProfileExtended:
285 return "Extended";
286 case kAVCProfileHigh:
287 return "High";
288 case kAVCProfileHigh10:
289 return "High 10";
290 case kAVCProfileHigh422:
291 return "High 422";
292 case kAVCProfileHigh444:
293 return "High 444";
294 case kAVCProfileCAVLC444Intra:
295 return "CAVLC 444 Intra";
296 default: return "Unknown";
297 }
298}
299
Andreas Huber4c483422009-09-02 16:05:36 -0700300template<class T>
301static void InitOMXParams(T *params) {
302 params->nSize = sizeof(T);
303 params->nVersion.s.nVersionMajor = 1;
304 params->nVersion.s.nVersionMinor = 0;
305 params->nVersion.s.nRevision = 0;
306 params->nVersion.s.nStep = 0;
307}
308
Andreas Hubere13526a2009-10-22 10:43:34 -0700309static bool IsSoftwareCodec(const char *componentName) {
310 if (!strncmp("OMX.PV.", componentName, 7)) {
311 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -0700312 }
313
Andreas Hubere13526a2009-10-22 10:43:34 -0700314 return false;
315}
316
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800317// A sort order in which non-OMX components are first,
318// followed by software codecs, i.e. OMX.PV.*, followed
319// by all the others.
Andreas Hubere13526a2009-10-22 10:43:34 -0700320static int CompareSoftwareCodecsFirst(
321 const String8 *elem1, const String8 *elem2) {
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800322 bool isNotOMX1 = strncmp(elem1->string(), "OMX.", 4);
323 bool isNotOMX2 = strncmp(elem2->string(), "OMX.", 4);
324
325 if (isNotOMX1) {
326 if (isNotOMX2) { return 0; }
327 return -1;
328 }
329 if (isNotOMX2) {
330 return 1;
331 }
332
Andreas Hubere13526a2009-10-22 10:43:34 -0700333 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
334 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
335
336 if (isSoftwareCodec1) {
337 if (isSoftwareCodec2) { return 0; }
338 return -1;
339 }
340
341 if (isSoftwareCodec2) {
342 return 1;
343 }
344
345 return 0;
346}
347
348// static
349uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700350 uint32_t quirks = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700351
Andreas Huberbe06d262009-08-14 14:37:10 -0700352 if (!strcmp(componentName, "OMX.PV.avcdec")) {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700353 quirks |= kWantsNALFragments;
Andreas Huberbe06d262009-08-14 14:37:10 -0700354 }
355 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
356 quirks |= kNeedsFlushBeforeDisable;
Andreas Hubere331c7b2010-02-01 10:51:50 -0800357 quirks |= kDecoderLiesAboutNumberOfChannels;
Andreas Huberbe06d262009-08-14 14:37:10 -0700358 }
359 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
360 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700361 quirks |= kRequiresFlushCompleteEmulation;
Andreas Hubera4357ad2010-04-02 12:49:54 -0700362 quirks |= kSupportsMultipleFramesPerInputBuffer;
Andreas Huberbe06d262009-08-14 14:37:10 -0700363 }
364 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
365 quirks |= kRequiresLoadedToIdleAfterAllocation;
366 quirks |= kRequiresAllocateBufferOnInputPorts;
Andreas Huberb482ce82009-10-29 12:02:48 -0700367 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dong90862e22010-08-26 19:12:59 -0700368 if (!strncmp(componentName, "OMX.qcom.video.encoder.avc", 26)) {
369
370 // The AVC encoder advertises the size of output buffers
371 // based on the input video resolution and assumes
372 // the worst/least compression ratio is 0.5. It is found that
373 // sometimes, the output buffer size is larger than
374 // size advertised by the encoder.
375 quirks |= kRequiresLargerEncoderOutputBuffer;
376 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700377 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700378 if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
379 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700380 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700381 quirks |= kRequiresAllocateBufferOnOutputPorts;
Andreas Huber52733b82010-01-25 10:41:35 -0800382 quirks |= kDefersOutputBufferAllocation;
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700383 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700384 if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
385 quirks |= kRequiresAllocateBufferOnInputPorts;
386 quirks |= kRequiresAllocateBufferOnOutputPorts;
387 quirks |= kDefersOutputBufferAllocation;
388 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700389
Andreas Huber2dc64d82009-09-11 12:58:53 -0700390 if (!strncmp(componentName, "OMX.TI.", 7)) {
391 // Apparently I must not use OMX_UseBuffer on either input or
392 // output ports on any of the TI components or quote:
393 // "(I) may have unexpected problem (sic) which can be timing related
394 // and hard to reproduce."
395
396 quirks |= kRequiresAllocateBufferOnInputPorts;
397 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dongdca66e12010-06-14 11:14:38 -0700398 if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
James Dong4f501f02010-06-07 14:41:41 -0700399 quirks |= kAvoidMemcopyInputRecordingFrames;
400 }
Andreas Huber2dc64d82009-09-11 12:58:53 -0700401 }
402
Andreas Huberb8de9572010-02-22 14:58:45 -0800403 if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
404 quirks |= kInputBufferSizesAreBogus;
405 }
406
Andreas Hubere13526a2009-10-22 10:43:34 -0700407 return quirks;
408}
409
410// static
411void OMXCodec::findMatchingCodecs(
412 const char *mime,
413 bool createEncoder, const char *matchComponentName,
414 uint32_t flags,
415 Vector<String8> *matchingCodecs) {
416 matchingCodecs->clear();
417
418 for (int index = 0;; ++index) {
419 const char *componentName;
420
421 if (createEncoder) {
422 componentName = GetCodec(
423 kEncoderInfo,
424 sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
425 mime, index);
426 } else {
427 componentName = GetCodec(
428 kDecoderInfo,
429 sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
430 mime, index);
431 }
432
433 if (!componentName) {
434 break;
435 }
436
437 // If a specific codec is requested, skip the non-matching ones.
438 if (matchComponentName && strcmp(componentName, matchComponentName)) {
439 continue;
440 }
441
442 matchingCodecs->push(String8(componentName));
443 }
444
445 if (flags & kPreferSoftwareCodecs) {
446 matchingCodecs->sort(CompareSoftwareCodecsFirst);
447 }
448}
449
450// static
Andreas Huber91eb0352009-12-07 09:43:00 -0800451sp<MediaSource> OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700452 const sp<IOMX> &omx,
453 const sp<MetaData> &meta, bool createEncoder,
454 const sp<MediaSource> &source,
455 const char *matchComponentName,
456 uint32_t flags) {
457 const char *mime;
458 bool success = meta->findCString(kKeyMIMEType, &mime);
459 CHECK(success);
460
461 Vector<String8> matchingCodecs;
462 findMatchingCodecs(
463 mime, createEncoder, matchComponentName, flags, &matchingCodecs);
464
465 if (matchingCodecs.isEmpty()) {
466 return NULL;
467 }
468
469 sp<OMXCodecObserver> observer = new OMXCodecObserver;
470 IOMX::node_id node = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700471
472 const char *componentName;
473 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
474 componentName = matchingCodecs[i].string();
475
James Dong17299ab2010-05-14 15:45:22 -0700476 sp<MediaSource> softwareCodec = createEncoder?
477 InstantiateSoftwareEncoder(componentName, source, meta):
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800478 InstantiateSoftwareCodec(componentName, source);
479
480 if (softwareCodec != NULL) {
481 LOGV("Successfully allocated software codec '%s'", componentName);
482
483 return softwareCodec;
484 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800485
Andreas Hubere13526a2009-10-22 10:43:34 -0700486 LOGV("Attempting to allocate OMX node '%s'", componentName);
487
488 status_t err = omx->allocateNode(componentName, observer, &node);
489 if (err == OK) {
490 LOGV("Successfully allocated OMX node '%s'", componentName);
491
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700492 sp<OMXCodec> codec = new OMXCodec(
493 omx, node, getComponentQuirks(componentName),
494 createEncoder, mime, componentName,
495 source);
496
497 observer->setCodec(codec);
498
499 err = codec->configureCodec(meta);
500
501 if (err == OK) {
502 return codec;
503 }
504
505 LOGV("Failed to configure codec '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700506 }
507 }
508
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700509 return NULL;
510}
Andreas Hubere13526a2009-10-22 10:43:34 -0700511
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700512status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700513 uint32_t type;
514 const void *data;
515 size_t size;
516 if (meta->findData(kKeyESDS, &type, &data, &size)) {
517 ESDS esds((const char *)data, size);
518 CHECK_EQ(esds.InitCheck(), OK);
519
520 const void *codec_specific_data;
521 size_t codec_specific_data_size;
522 esds.getCodecSpecificInfo(
523 &codec_specific_data, &codec_specific_data_size);
524
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700525 addCodecSpecificData(
Andreas Huberbe06d262009-08-14 14:37:10 -0700526 codec_specific_data, codec_specific_data_size);
527 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
Andreas Huberebf66ea2009-08-19 13:32:58 -0700528 // Parse the AVCDecoderConfigurationRecord
529
530 const uint8_t *ptr = (const uint8_t *)data;
531
532 CHECK(size >= 7);
533 CHECK_EQ(ptr[0], 1); // configurationVersion == 1
534 uint8_t profile = ptr[1];
535 uint8_t level = ptr[3];
536
Andreas Huber44e15c42009-11-23 14:39:38 -0800537 // There is decodable content out there that fails the following
538 // assertion, let's be lenient for now...
539 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
Andreas Huberebf66ea2009-08-19 13:32:58 -0700540
541 size_t lengthSize = 1 + (ptr[4] & 3);
542
543 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
544 // violates it...
545 // CHECK((ptr[5] >> 5) == 7); // reserved
546
547 size_t numSeqParameterSets = ptr[5] & 31;
548
549 ptr += 6;
Andreas Huberbe06d262009-08-14 14:37:10 -0700550 size -= 6;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700551
552 for (size_t i = 0; i < numSeqParameterSets; ++i) {
553 CHECK(size >= 2);
554 size_t length = U16_AT(ptr);
Andreas Huberbe06d262009-08-14 14:37:10 -0700555
556 ptr += 2;
557 size -= 2;
558
Andreas Huberbe06d262009-08-14 14:37:10 -0700559 CHECK(size >= length);
560
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700561 addCodecSpecificData(ptr, length);
Andreas Huberbe06d262009-08-14 14:37:10 -0700562
563 ptr += length;
564 size -= length;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700565 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700566
Andreas Huberebf66ea2009-08-19 13:32:58 -0700567 CHECK(size >= 1);
568 size_t numPictureParameterSets = *ptr;
569 ++ptr;
570 --size;
Andreas Huberbe06d262009-08-14 14:37:10 -0700571
Andreas Huberebf66ea2009-08-19 13:32:58 -0700572 for (size_t i = 0; i < numPictureParameterSets; ++i) {
573 CHECK(size >= 2);
574 size_t length = U16_AT(ptr);
575
576 ptr += 2;
577 size -= 2;
578
579 CHECK(size >= length);
580
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700581 addCodecSpecificData(ptr, length);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700582
583 ptr += length;
584 size -= length;
585 }
586
Andreas Hubere2f85072010-06-10 09:51:27 -0700587 CODEC_LOGV(
588 "AVC profile = %d (%s), level = %d",
589 (int)profile, AVCProfileToString(profile), level);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700590
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700591 if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
Andreas Hubere2f85072010-06-10 09:51:27 -0700592 && (profile != kAVCProfileBaseline || level > 30)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700593 // This stream exceeds the decoder's capabilities. The decoder
594 // does not handle this gracefully and would clobber the heap
595 // and wreak havoc instead...
Andreas Huberebf66ea2009-08-19 13:32:58 -0700596
597 LOGE("Profile and/or level exceed the decoder's capabilities.");
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700598 return ERROR_UNSUPPORTED;
Andreas Huberbe06d262009-08-14 14:37:10 -0700599 }
600 }
601
James Dong17299ab2010-05-14 15:45:22 -0700602 int32_t bitRate = 0;
603 if (mIsEncoder) {
604 CHECK(meta->findInt32(kKeyBitRate, &bitRate));
605 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700606 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700607 setAMRFormat(false /* isWAMR */, bitRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700608 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700609 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700610 setAMRFormat(true /* isWAMR */, bitRate);
Andreas Huberee606e62009-09-08 10:19:21 -0700611 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700612 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700613 int32_t numChannels, sampleRate;
614 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
615 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
616
James Dong17299ab2010-05-14 15:45:22 -0700617 setAACFormat(numChannels, sampleRate, bitRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700618 }
James Dongabed93a2010-04-22 17:27:04 -0700619
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700620 if (!strncasecmp(mMIME, "video/", 6)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700621
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700622 if (mIsEncoder) {
James Dong1244eab2010-06-08 11:58:53 -0700623 setVideoInputFormat(mMIME, meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700624 } else {
James Dong1244eab2010-06-08 11:58:53 -0700625 int32_t width, height;
626 bool success = meta->findInt32(kKeyWidth, &width);
627 success = success && meta->findInt32(kKeyHeight, &height);
628 CHECK(success);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700629 status_t err = setVideoOutputFormat(
630 mMIME, width, height);
631
632 if (err != OK) {
633 return err;
634 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700635 }
636 }
Andreas Hubera4357ad2010-04-02 12:49:54 -0700637
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700638 if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
639 && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700640 OMX_COLOR_FORMATTYPE format =
641 OMX_COLOR_Format32bitARGB8888;
642 // OMX_COLOR_FormatYUV420PackedPlanar;
643 // OMX_COLOR_FormatCbYCrY;
644 // OMX_COLOR_FormatYUV411Planar;
645
646 int32_t width, height;
647 bool success = meta->findInt32(kKeyWidth, &width);
648 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700649
650 int32_t compressedSize;
651 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700652 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700653
654 CHECK(success);
655 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700656
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700657 setImageOutputFormat(format, width, height);
658 setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700659 }
660
Andreas Huberda050cf22009-09-02 14:01:43 -0700661 int32_t maxInputSize;
Andreas Huber1bceff92009-11-23 14:03:32 -0800662 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700663 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
Andreas Huberda050cf22009-09-02 14:01:43 -0700664 }
665
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700666 if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
James Dongabed93a2010-04-22 17:27:04 -0700667 || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
668 || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700669 setMinBufferSize(kPortIndexOutput, 8192); // XXX
Andreas Huberda050cf22009-09-02 14:01:43 -0700670 }
671
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700672 initOutputFormat(meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700673
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700674 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700675}
676
Andreas Huberda050cf22009-09-02 14:01:43 -0700677void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
678 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700679 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700680 def.nPortIndex = portIndex;
681
Andreas Huber784202e2009-10-15 13:46:54 -0700682 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700683 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
684 CHECK_EQ(err, OK);
685
Andreas Huberb8de9572010-02-22 14:58:45 -0800686 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
687 || (def.nBufferSize < size)) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700688 def.nBufferSize = size;
Andreas Huberda050cf22009-09-02 14:01:43 -0700689 }
690
Andreas Huber784202e2009-10-15 13:46:54 -0700691 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700692 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
693 CHECK_EQ(err, OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800694
695 err = mOMX->getParameter(
696 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
697 CHECK_EQ(err, OK);
698
699 // Make sure the setting actually stuck.
Andreas Huberb8de9572010-02-22 14:58:45 -0800700 if (portIndex == kPortIndexInput
701 && (mQuirks & kInputBufferSizesAreBogus)) {
702 CHECK_EQ(def.nBufferSize, size);
703 } else {
704 CHECK(def.nBufferSize >= size);
705 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700706}
707
Andreas Huberbe06d262009-08-14 14:37:10 -0700708status_t OMXCodec::setVideoPortFormatType(
709 OMX_U32 portIndex,
710 OMX_VIDEO_CODINGTYPE compressionFormat,
711 OMX_COLOR_FORMATTYPE colorFormat) {
712 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700713 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700714 format.nPortIndex = portIndex;
715 format.nIndex = 0;
716 bool found = false;
717
718 OMX_U32 index = 0;
719 for (;;) {
720 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700721 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700722 mNode, OMX_IndexParamVideoPortFormat,
723 &format, sizeof(format));
724
725 if (err != OK) {
726 return err;
727 }
728
729 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700730 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700731
732#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700733 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700734 portIndex,
735 index, format.eCompressionFormat, format.eColorFormat);
736#endif
737
738 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
739 if (portIndex == kPortIndexInput
740 && colorFormat == format.eColorFormat) {
741 // eCompressionFormat does not seem right.
742 found = true;
743 break;
744 }
745 if (portIndex == kPortIndexOutput
746 && compressionFormat == format.eCompressionFormat) {
747 // eColorFormat does not seem right.
748 found = true;
749 break;
750 }
751 }
752
753 if (format.eCompressionFormat == compressionFormat
754 && format.eColorFormat == colorFormat) {
755 found = true;
756 break;
757 }
758
759 ++index;
760 }
761
762 if (!found) {
763 return UNKNOWN_ERROR;
764 }
765
Andreas Huber53a76bd2009-10-06 16:20:44 -0700766 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700767 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700768 mNode, OMX_IndexParamVideoPortFormat,
769 &format, sizeof(format));
770
771 return err;
772}
773
Andreas Huberb482ce82009-10-29 12:02:48 -0700774static size_t getFrameSize(
775 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
776 switch (colorFormat) {
777 case OMX_COLOR_FormatYCbYCr:
778 case OMX_COLOR_FormatCbYCrY:
779 return width * height * 2;
780
Andreas Huber71c27d92010-03-19 11:43:15 -0700781 case OMX_COLOR_FormatYUV420Planar:
Andreas Huberb482ce82009-10-29 12:02:48 -0700782 case OMX_COLOR_FormatYUV420SemiPlanar:
783 return (width * height * 3) / 2;
784
785 default:
786 CHECK(!"Should not be here. Unsupported color format.");
787 break;
788 }
789}
790
James Dongafd97e82010-08-03 17:19:23 -0700791status_t OMXCodec::findTargetColorFormat(
792 const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat) {
793 LOGV("findTargetColorFormat");
794 CHECK(mIsEncoder);
795
796 *colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
797 int32_t targetColorFormat;
798 if (meta->findInt32(kKeyColorFormat, &targetColorFormat)) {
799 *colorFormat = (OMX_COLOR_FORMATTYPE) targetColorFormat;
800 } else {
801 if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
802 *colorFormat = OMX_COLOR_FormatYCbYCr;
803 }
804 }
805
806 // Check whether the target color format is supported.
807 return isColorFormatSupported(*colorFormat, kPortIndexInput);
808}
809
810status_t OMXCodec::isColorFormatSupported(
811 OMX_COLOR_FORMATTYPE colorFormat, int portIndex) {
812 LOGV("isColorFormatSupported: %d", static_cast<int>(colorFormat));
813
814 // Enumerate all the color formats supported by
815 // the omx component to see whether the given
816 // color format is supported.
817 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
818 InitOMXParams(&portFormat);
819 portFormat.nPortIndex = portIndex;
820 OMX_U32 index = 0;
821 portFormat.nIndex = index;
822 while (true) {
823 if (OMX_ErrorNone != mOMX->getParameter(
824 mNode, OMX_IndexParamVideoPortFormat,
825 &portFormat, sizeof(portFormat))) {
James Dongb5024da2010-09-13 16:30:51 -0700826 break;
James Dongafd97e82010-08-03 17:19:23 -0700827 }
828 // Make sure that omx component does not overwrite
829 // the incremented index (bug 2897413).
830 CHECK_EQ(index, portFormat.nIndex);
831 if ((portFormat.eColorFormat == colorFormat)) {
832 LOGV("Found supported color format: %d", portFormat.eColorFormat);
833 return OK; // colorFormat is supported!
834 }
835 ++index;
836 portFormat.nIndex = index;
837
838 // OMX Spec defines less than 50 color formats
839 // 1000 is more than enough for us to tell whether the omx
840 // component in question is buggy or not.
841 if (index >= 1000) {
842 LOGE("More than %ld color formats are supported???", index);
843 break;
844 }
845 }
James Dongb5024da2010-09-13 16:30:51 -0700846
847 LOGE("color format %d is not supported", colorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700848 return UNKNOWN_ERROR;
849}
850
Andreas Huberbe06d262009-08-14 14:37:10 -0700851void OMXCodec::setVideoInputFormat(
James Dong1244eab2010-06-08 11:58:53 -0700852 const char *mime, const sp<MetaData>& meta) {
853
854 int32_t width, height, frameRate, bitRate, stride, sliceHeight;
855 bool success = meta->findInt32(kKeyWidth, &width);
856 success = success && meta->findInt32(kKeyHeight, &height);
857 success = success && meta->findInt32(kKeySampleRate, &frameRate);
858 success = success && meta->findInt32(kKeyBitRate, &bitRate);
859 success = success && meta->findInt32(kKeyStride, &stride);
860 success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
861 CHECK(success);
862 CHECK(stride != 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700863
864 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700865 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700866 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700867 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700868 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700869 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700870 compressionFormat = OMX_VIDEO_CodingH263;
871 } else {
872 LOGE("Not a supported video mime type: %s", mime);
873 CHECK(!"Should not be here. Not a supported video mime type.");
874 }
875
James Dongafd97e82010-08-03 17:19:23 -0700876 OMX_COLOR_FORMATTYPE colorFormat;
877 CHECK_EQ(OK, findTargetColorFormat(meta, &colorFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -0700878
James Dongb00e2462010-04-26 17:48:26 -0700879 status_t err;
880 OMX_PARAM_PORTDEFINITIONTYPE def;
881 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
882
883 //////////////////////// Input port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700884 CHECK_EQ(setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -0700885 kPortIndexInput, OMX_VIDEO_CodingUnused,
Andreas Huberb482ce82009-10-29 12:02:48 -0700886 colorFormat), OK);
James Dong4f501f02010-06-07 14:41:41 -0700887
James Dongb00e2462010-04-26 17:48:26 -0700888 InitOMXParams(&def);
889 def.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -0700890
James Dongb00e2462010-04-26 17:48:26 -0700891 err = mOMX->getParameter(
892 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
893 CHECK_EQ(err, OK);
894
James Dong1244eab2010-06-08 11:58:53 -0700895 def.nBufferSize = getFrameSize(colorFormat,
896 stride > 0? stride: -stride, sliceHeight);
James Dongb00e2462010-04-26 17:48:26 -0700897
898 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
899
900 video_def->nFrameWidth = width;
901 video_def->nFrameHeight = height;
James Dong1244eab2010-06-08 11:58:53 -0700902 video_def->nStride = stride;
903 video_def->nSliceHeight = sliceHeight;
James Dong4f501f02010-06-07 14:41:41 -0700904 video_def->xFramerate = (frameRate << 16); // Q16 format
James Dongb00e2462010-04-26 17:48:26 -0700905 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
906 video_def->eColorFormat = colorFormat;
907
James Dongb00e2462010-04-26 17:48:26 -0700908 err = mOMX->setParameter(
909 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
910 CHECK_EQ(err, OK);
911
912 //////////////////////// Output port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700913 CHECK_EQ(setVideoPortFormatType(
914 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
915 OK);
Andreas Huber4c483422009-09-02 16:05:36 -0700916 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700917 def.nPortIndex = kPortIndexOutput;
918
James Dongb00e2462010-04-26 17:48:26 -0700919 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700920 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
921
922 CHECK_EQ(err, OK);
923 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
924
925 video_def->nFrameWidth = width;
926 video_def->nFrameHeight = height;
James Dong81c929a2010-07-01 15:02:14 -0700927 video_def->xFramerate = 0; // No need for output port
James Dong4f501f02010-06-07 14:41:41 -0700928 video_def->nBitrate = bitRate; // Q16 format
Andreas Huberbe06d262009-08-14 14:37:10 -0700929 video_def->eCompressionFormat = compressionFormat;
930 video_def->eColorFormat = OMX_COLOR_FormatUnused;
James Dong90862e22010-08-26 19:12:59 -0700931 if (mQuirks & kRequiresLargerEncoderOutputBuffer) {
932 // Increases the output buffer size
933 def.nBufferSize = ((def.nBufferSize * 3) >> 1);
934 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700935
Andreas Huber784202e2009-10-15 13:46:54 -0700936 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700937 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
938 CHECK_EQ(err, OK);
939
James Dongb00e2462010-04-26 17:48:26 -0700940 /////////////////// Codec-specific ////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700941 switch (compressionFormat) {
942 case OMX_VIDEO_CodingMPEG4:
943 {
James Dong1244eab2010-06-08 11:58:53 -0700944 CHECK_EQ(setupMPEG4EncoderParameters(meta), OK);
Andreas Huberb482ce82009-10-29 12:02:48 -0700945 break;
946 }
947
948 case OMX_VIDEO_CodingH263:
James Dongc0ab2a62010-06-29 16:29:19 -0700949 CHECK_EQ(setupH263EncoderParameters(meta), OK);
Andreas Huberb482ce82009-10-29 12:02:48 -0700950 break;
951
Andreas Huberea6a38c2009-11-16 15:43:38 -0800952 case OMX_VIDEO_CodingAVC:
953 {
James Dong1244eab2010-06-08 11:58:53 -0700954 CHECK_EQ(setupAVCEncoderParameters(meta), OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -0800955 break;
956 }
957
Andreas Huberb482ce82009-10-29 12:02:48 -0700958 default:
959 CHECK(!"Support for this compressionFormat to be implemented.");
960 break;
961 }
962}
963
James Dong1244eab2010-06-08 11:58:53 -0700964static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
965 if (iFramesInterval < 0) {
966 return 0xFFFFFFFF;
967 } else if (iFramesInterval == 0) {
968 return 0;
969 }
970 OMX_U32 ret = frameRate * iFramesInterval;
971 CHECK(ret > 1);
972 return ret;
973}
974
James Dongc0ab2a62010-06-29 16:29:19 -0700975status_t OMXCodec::setupErrorCorrectionParameters() {
976 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
977 InitOMXParams(&errorCorrectionType);
978 errorCorrectionType.nPortIndex = kPortIndexOutput;
979
980 status_t err = mOMX->getParameter(
981 mNode, OMX_IndexParamVideoErrorCorrection,
982 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -0700983 if (err != OK) {
984 LOGW("Error correction param query is not supported");
985 return OK; // Optional feature. Ignore this failure
986 }
James Dongc0ab2a62010-06-29 16:29:19 -0700987
988 errorCorrectionType.bEnableHEC = OMX_FALSE;
989 errorCorrectionType.bEnableResync = OMX_TRUE;
990 errorCorrectionType.nResynchMarkerSpacing = 256;
991 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
992 errorCorrectionType.bEnableRVLC = OMX_FALSE;
993
994 err = mOMX->setParameter(
995 mNode, OMX_IndexParamVideoErrorCorrection,
996 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -0700997 if (err != OK) {
998 LOGW("Error correction param configuration is not supported");
999 }
1000
1001 // Optional feature. Ignore the failure.
James Dongc0ab2a62010-06-29 16:29:19 -07001002 return OK;
1003}
1004
1005status_t OMXCodec::setupBitRate(int32_t bitRate) {
1006 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1007 InitOMXParams(&bitrateType);
1008 bitrateType.nPortIndex = kPortIndexOutput;
1009
1010 status_t err = mOMX->getParameter(
1011 mNode, OMX_IndexParamVideoBitrate,
1012 &bitrateType, sizeof(bitrateType));
1013 CHECK_EQ(err, OK);
1014
1015 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1016 bitrateType.nTargetBitrate = bitRate;
1017
1018 err = mOMX->setParameter(
1019 mNode, OMX_IndexParamVideoBitrate,
1020 &bitrateType, sizeof(bitrateType));
1021 CHECK_EQ(err, OK);
1022 return OK;
1023}
1024
James Dong81c929a2010-07-01 15:02:14 -07001025status_t OMXCodec::getVideoProfileLevel(
1026 const sp<MetaData>& meta,
1027 const CodecProfileLevel& defaultProfileLevel,
1028 CodecProfileLevel &profileLevel) {
1029 CODEC_LOGV("Default profile: %ld, level %ld",
1030 defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
1031
1032 // Are the default profile and level overwriten?
1033 int32_t profile, level;
1034 if (!meta->findInt32(kKeyVideoProfile, &profile)) {
1035 profile = defaultProfileLevel.mProfile;
1036 }
1037 if (!meta->findInt32(kKeyVideoLevel, &level)) {
1038 level = defaultProfileLevel.mLevel;
1039 }
1040 CODEC_LOGV("Target profile: %d, level: %d", profile, level);
1041
1042 // Are the target profile and level supported by the encoder?
1043 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
1044 InitOMXParams(&param);
1045 param.nPortIndex = kPortIndexOutput;
1046 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
1047 status_t err = mOMX->getParameter(
1048 mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
1049 &param, sizeof(param));
1050
James Dongdfb89912010-09-15 21:07:52 -07001051 if (err != OK) break;
James Dong81c929a2010-07-01 15:02:14 -07001052
1053 int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
1054 int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
James Dong929642e2010-07-08 11:16:11 -07001055 CODEC_LOGV("Supported profile: %d, level %d",
James Dong81c929a2010-07-01 15:02:14 -07001056 supportedProfile, supportedLevel);
1057
1058 if (profile == supportedProfile &&
James Dongdfb89912010-09-15 21:07:52 -07001059 level <= supportedLevel) {
1060 // We can further check whether the level is a valid
1061 // value; but we will leave that to the omx encoder component
1062 // via OMX_SetParameter call.
James Dong81c929a2010-07-01 15:02:14 -07001063 profileLevel.mProfile = profile;
1064 profileLevel.mLevel = level;
1065 return OK;
1066 }
1067 }
1068
1069 CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
1070 profile, level);
1071 return BAD_VALUE;
1072}
1073
James Dongc0ab2a62010-06-29 16:29:19 -07001074status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
1075 int32_t iFramesInterval, frameRate, bitRate;
1076 bool success = meta->findInt32(kKeyBitRate, &bitRate);
1077 success = success && meta->findInt32(kKeySampleRate, &frameRate);
1078 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1079 CHECK(success);
1080 OMX_VIDEO_PARAM_H263TYPE h263type;
1081 InitOMXParams(&h263type);
1082 h263type.nPortIndex = kPortIndexOutput;
1083
1084 status_t err = mOMX->getParameter(
1085 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1086 CHECK_EQ(err, OK);
1087
1088 h263type.nAllowedPictureTypes =
1089 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1090
1091 h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1092 if (h263type.nPFrames == 0) {
1093 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1094 }
1095 h263type.nBFrames = 0;
1096
James Dong81c929a2010-07-01 15:02:14 -07001097 // Check profile and level parameters
1098 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001099 defaultProfileLevel.mProfile = h263type.eProfile;
1100 defaultProfileLevel.mLevel = h263type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001101 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1102 if (err != OK) return err;
1103 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
1104 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
James Dongc0ab2a62010-06-29 16:29:19 -07001105
1106 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1107 h263type.bForceRoundingTypeToZero = OMX_FALSE;
1108 h263type.nPictureHeaderRepetition = 0;
1109 h263type.nGOBHeaderInterval = 0;
1110
1111 err = mOMX->setParameter(
1112 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1113 CHECK_EQ(err, OK);
1114
1115 CHECK_EQ(setupBitRate(bitRate), OK);
1116 CHECK_EQ(setupErrorCorrectionParameters(), OK);
1117
1118 return OK;
1119}
1120
James Dong1244eab2010-06-08 11:58:53 -07001121status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
1122 int32_t iFramesInterval, frameRate, bitRate;
1123 bool success = meta->findInt32(kKeyBitRate, &bitRate);
1124 success = success && meta->findInt32(kKeySampleRate, &frameRate);
1125 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1126 CHECK(success);
Andreas Huberb482ce82009-10-29 12:02:48 -07001127 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1128 InitOMXParams(&mpeg4type);
1129 mpeg4type.nPortIndex = kPortIndexOutput;
1130
1131 status_t err = mOMX->getParameter(
1132 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1133 CHECK_EQ(err, OK);
1134
1135 mpeg4type.nSliceHeaderSpacing = 0;
1136 mpeg4type.bSVH = OMX_FALSE;
1137 mpeg4type.bGov = OMX_FALSE;
1138
1139 mpeg4type.nAllowedPictureTypes =
1140 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1141
James Dong1244eab2010-06-08 11:58:53 -07001142 mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1143 if (mpeg4type.nPFrames == 0) {
1144 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1145 }
Andreas Huberb482ce82009-10-29 12:02:48 -07001146 mpeg4type.nBFrames = 0;
Andreas Huberb482ce82009-10-29 12:02:48 -07001147 mpeg4type.nIDCVLCThreshold = 0;
1148 mpeg4type.bACPred = OMX_TRUE;
1149 mpeg4type.nMaxPacketSize = 256;
1150 mpeg4type.nTimeIncRes = 1000;
1151 mpeg4type.nHeaderExtension = 0;
1152 mpeg4type.bReversibleVLC = OMX_FALSE;
1153
James Dong81c929a2010-07-01 15:02:14 -07001154 // Check profile and level parameters
1155 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001156 defaultProfileLevel.mProfile = mpeg4type.eProfile;
1157 defaultProfileLevel.mLevel = mpeg4type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001158 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1159 if (err != OK) return err;
1160 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
1161 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
Andreas Huberb482ce82009-10-29 12:02:48 -07001162
1163 err = mOMX->setParameter(
1164 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1165 CHECK_EQ(err, OK);
1166
James Dongc0ab2a62010-06-29 16:29:19 -07001167 CHECK_EQ(setupBitRate(bitRate), OK);
1168 CHECK_EQ(setupErrorCorrectionParameters(), OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001169
1170 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07001171}
1172
James Dong1244eab2010-06-08 11:58:53 -07001173status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
1174 int32_t iFramesInterval, frameRate, bitRate;
1175 bool success = meta->findInt32(kKeyBitRate, &bitRate);
1176 success = success && meta->findInt32(kKeySampleRate, &frameRate);
1177 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1178 CHECK(success);
1179
Andreas Huberea6a38c2009-11-16 15:43:38 -08001180 OMX_VIDEO_PARAM_AVCTYPE h264type;
1181 InitOMXParams(&h264type);
1182 h264type.nPortIndex = kPortIndexOutput;
1183
1184 status_t err = mOMX->getParameter(
1185 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1186 CHECK_EQ(err, OK);
1187
1188 h264type.nAllowedPictureTypes =
1189 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1190
1191 h264type.nSliceHeaderSpacing = 0;
James Dong1244eab2010-06-08 11:58:53 -07001192 h264type.nBFrames = 0; // No B frames support yet
1193 h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1194 if (h264type.nPFrames == 0) {
1195 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1196 }
James Dong81c929a2010-07-01 15:02:14 -07001197
1198 // Check profile and level parameters
1199 CodecProfileLevel defaultProfileLevel, profileLevel;
1200 defaultProfileLevel.mProfile = h264type.eProfile;
1201 defaultProfileLevel.mLevel = h264type.eLevel;
1202 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1203 if (err != OK) return err;
1204 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
1205 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
1206
1207 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1208 h264type.bUseHadamard = OMX_TRUE;
1209 h264type.nRefFrames = 1;
1210 h264type.nRefIdx10ActiveMinus1 = 0;
1211 h264type.nRefIdx11ActiveMinus1 = 0;
1212 h264type.bEntropyCodingCABAC = OMX_FALSE;
1213 h264type.bWeightedPPrediction = OMX_FALSE;
1214 h264type.bconstIpred = OMX_FALSE;
1215 h264type.bDirect8x8Inference = OMX_FALSE;
1216 h264type.bDirectSpatialTemporal = OMX_FALSE;
1217 h264type.nCabacInitIdc = 0;
1218 }
1219
1220 if (h264type.nBFrames != 0) {
1221 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1222 }
1223
Andreas Huberea6a38c2009-11-16 15:43:38 -08001224 h264type.bEnableUEP = OMX_FALSE;
1225 h264type.bEnableFMO = OMX_FALSE;
1226 h264type.bEnableASO = OMX_FALSE;
1227 h264type.bEnableRS = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001228 h264type.bFrameMBsOnly = OMX_TRUE;
1229 h264type.bMBAFF = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001230 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1231
1232 err = mOMX->setParameter(
1233 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1234 CHECK_EQ(err, OK);
1235
James Dongc0ab2a62010-06-29 16:29:19 -07001236 CHECK_EQ(setupBitRate(bitRate), OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001237
1238 return OK;
1239}
1240
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001241status_t OMXCodec::setVideoOutputFormat(
Andreas Huberbe06d262009-08-14 14:37:10 -07001242 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -07001243 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001244
Andreas Huberbe06d262009-08-14 14:37:10 -07001245 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -07001246 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001247 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -07001248 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001249 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -07001250 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001251 compressionFormat = OMX_VIDEO_CodingH263;
1252 } else {
1253 LOGE("Not a supported video mime type: %s", mime);
1254 CHECK(!"Should not be here. Not a supported video mime type.");
1255 }
1256
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001257 status_t err = setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -07001258 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1259
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001260 if (err != OK) {
1261 return err;
1262 }
1263
Andreas Huberbe06d262009-08-14 14:37:10 -07001264#if 1
1265 {
1266 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -07001267 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -07001268 format.nPortIndex = kPortIndexOutput;
1269 format.nIndex = 0;
1270
Andreas Huber784202e2009-10-15 13:46:54 -07001271 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001272 mNode, OMX_IndexParamVideoPortFormat,
1273 &format, sizeof(format));
1274 CHECK_EQ(err, OK);
1275 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
1276
1277 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1278
1279 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1280 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1281 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1282 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1283
Andreas Huber784202e2009-10-15 13:46:54 -07001284 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001285 mNode, OMX_IndexParamVideoPortFormat,
1286 &format, sizeof(format));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001287
1288 if (err != OK) {
1289 return err;
1290 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001291 }
1292#endif
1293
1294 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001295 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001296 def.nPortIndex = kPortIndexInput;
1297
Andreas Huber4c483422009-09-02 16:05:36 -07001298 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1299
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001300 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001301 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1302
1303 CHECK_EQ(err, OK);
1304
1305#if 1
1306 // XXX Need a (much) better heuristic to compute input buffer sizes.
1307 const size_t X = 64 * 1024;
1308 if (def.nBufferSize < X) {
1309 def.nBufferSize = X;
1310 }
1311#endif
1312
1313 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1314
1315 video_def->nFrameWidth = width;
1316 video_def->nFrameHeight = height;
1317
Andreas Huberb482ce82009-10-29 12:02:48 -07001318 video_def->eCompressionFormat = compressionFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -07001319 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1320
Andreas Huber784202e2009-10-15 13:46:54 -07001321 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001322 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001323
1324 if (err != OK) {
1325 return err;
1326 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001327
1328 ////////////////////////////////////////////////////////////////////////////
1329
Andreas Huber4c483422009-09-02 16:05:36 -07001330 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001331 def.nPortIndex = kPortIndexOutput;
1332
Andreas Huber784202e2009-10-15 13:46:54 -07001333 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001334 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1335 CHECK_EQ(err, OK);
1336 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1337
1338#if 0
1339 def.nBufferSize =
1340 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
1341#endif
1342
1343 video_def->nFrameWidth = width;
1344 video_def->nFrameHeight = height;
1345
Andreas Huber784202e2009-10-15 13:46:54 -07001346 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001347 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001348
1349 return err;
Andreas Huberbe06d262009-08-14 14:37:10 -07001350}
1351
Andreas Huberbe06d262009-08-14 14:37:10 -07001352OMXCodec::OMXCodec(
1353 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
Andreas Huberebf66ea2009-08-19 13:32:58 -07001354 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -07001355 const char *mime,
1356 const char *componentName,
1357 const sp<MediaSource> &source)
1358 : mOMX(omx),
Andreas Huberf1fe0642010-01-15 15:28:19 -08001359 mOMXLivesLocally(omx->livesLocally(getpid())),
Andreas Huberbe06d262009-08-14 14:37:10 -07001360 mNode(node),
1361 mQuirks(quirks),
1362 mIsEncoder(isEncoder),
1363 mMIME(strdup(mime)),
1364 mComponentName(strdup(componentName)),
1365 mSource(source),
1366 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -07001367 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -07001368 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -07001369 mSignalledEOS(false),
1370 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -07001371 mOutputPortSettingsHaveChanged(false),
Andreas Hubera4357ad2010-04-02 12:49:54 -07001372 mSeekTimeUs(-1),
Andreas Huber6624c9f2010-07-20 15:04:28 -07001373 mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
1374 mTargetTimeUs(-1),
James Dong53d4e0d2010-07-21 14:51:35 -07001375 mSkipTimeUs(-1),
Andreas Huber1f24b302010-06-10 11:12:39 -07001376 mLeftOverBuffer(NULL),
1377 mPaused(false) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001378 mPortStatus[kPortIndexInput] = ENABLED;
1379 mPortStatus[kPortIndexOutput] = ENABLED;
1380
Andreas Huber4c483422009-09-02 16:05:36 -07001381 setComponentRole();
1382}
1383
Andreas Hubere6c40962009-09-10 14:13:30 -07001384// static
1385void OMXCodec::setComponentRole(
1386 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1387 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -07001388 struct MimeToRole {
1389 const char *mime;
1390 const char *decoderRole;
1391 const char *encoderRole;
1392 };
1393
1394 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -07001395 { MEDIA_MIMETYPE_AUDIO_MPEG,
1396 "audio_decoder.mp3", "audio_encoder.mp3" },
1397 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1398 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1399 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1400 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1401 { MEDIA_MIMETYPE_AUDIO_AAC,
1402 "audio_decoder.aac", "audio_encoder.aac" },
1403 { MEDIA_MIMETYPE_VIDEO_AVC,
1404 "video_decoder.avc", "video_encoder.avc" },
1405 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1406 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1407 { MEDIA_MIMETYPE_VIDEO_H263,
1408 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber4c483422009-09-02 16:05:36 -07001409 };
1410
1411 static const size_t kNumMimeToRole =
1412 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1413
1414 size_t i;
1415 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001416 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001417 break;
1418 }
1419 }
1420
1421 if (i == kNumMimeToRole) {
1422 return;
1423 }
1424
1425 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -07001426 isEncoder ? kMimeToRole[i].encoderRole
1427 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -07001428
1429 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -07001430 OMX_PARAM_COMPONENTROLETYPE roleParams;
1431 InitOMXParams(&roleParams);
1432
1433 strncpy((char *)roleParams.cRole,
1434 role, OMX_MAX_STRINGNAME_SIZE - 1);
1435
1436 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1437
Andreas Huber784202e2009-10-15 13:46:54 -07001438 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07001439 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -07001440 &roleParams, sizeof(roleParams));
1441
1442 if (err != OK) {
1443 LOGW("Failed to set standard component role '%s'.", role);
1444 }
1445 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001446}
1447
Andreas Hubere6c40962009-09-10 14:13:30 -07001448void OMXCodec::setComponentRole() {
1449 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1450}
1451
Andreas Huberbe06d262009-08-14 14:37:10 -07001452OMXCodec::~OMXCodec() {
Andreas Huberf98197a2010-09-17 11:49:39 -07001453 mSource.clear();
1454
Andreas Huber4f5e6022009-08-19 09:29:34 -07001455 CHECK(mState == LOADED || mState == ERROR);
Andreas Huberbe06d262009-08-14 14:37:10 -07001456
Andreas Huber784202e2009-10-15 13:46:54 -07001457 status_t err = mOMX->freeNode(mNode);
Andreas Huberbe06d262009-08-14 14:37:10 -07001458 CHECK_EQ(err, OK);
1459
1460 mNode = NULL;
1461 setState(DEAD);
1462
1463 clearCodecSpecificData();
1464
1465 free(mComponentName);
1466 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001467
Andreas Huberbe06d262009-08-14 14:37:10 -07001468 free(mMIME);
1469 mMIME = NULL;
1470}
1471
1472status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -07001473 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -07001474
1475 CHECK_EQ(mState, LOADED);
1476
1477 status_t err;
1478 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001479 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -07001480 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001481 setState(LOADED_TO_IDLE);
1482 }
1483
1484 err = allocateBuffers();
1485 CHECK_EQ(err, OK);
1486
1487 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -07001488 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -07001489 CHECK_EQ(err, OK);
1490
1491 setState(LOADED_TO_IDLE);
1492 }
1493
1494 while (mState != EXECUTING && mState != ERROR) {
1495 mAsyncCompletion.wait(mLock);
1496 }
1497
1498 return mState == ERROR ? UNKNOWN_ERROR : OK;
1499}
1500
1501// static
1502bool OMXCodec::isIntermediateState(State state) {
1503 return state == LOADED_TO_IDLE
1504 || state == IDLE_TO_EXECUTING
1505 || state == EXECUTING_TO_IDLE
1506 || state == IDLE_TO_LOADED
1507 || state == RECONFIGURING;
1508}
1509
1510status_t OMXCodec::allocateBuffers() {
1511 status_t err = allocateBuffersOnPort(kPortIndexInput);
1512
1513 if (err != OK) {
1514 return err;
1515 }
1516
1517 return allocateBuffersOnPort(kPortIndexOutput);
1518}
1519
1520status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
1521 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001522 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001523 def.nPortIndex = portIndex;
1524
Andreas Huber784202e2009-10-15 13:46:54 -07001525 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001526 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1527
1528 if (err != OK) {
1529 return err;
1530 }
1531
Andreas Huber57648e42010-08-04 10:14:30 -07001532 CODEC_LOGI("allocating %lu buffers of size %lu on %s port",
1533 def.nBufferCountActual, def.nBufferSize,
1534 portIndex == kPortIndexInput ? "input" : "output");
1535
Andreas Huber5c0a9132009-08-20 11:16:40 -07001536 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
Mathias Agopian6faf7892010-01-25 19:00:00 -08001537 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
Andreas Huber5c0a9132009-08-20 11:16:40 -07001538
Andreas Huberbe06d262009-08-14 14:37:10 -07001539 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -07001540 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07001541 CHECK(mem.get() != NULL);
1542
Andreas Huberc712b9f2010-01-20 15:05:46 -08001543 BufferInfo info;
1544 info.mData = NULL;
1545 info.mSize = def.nBufferSize;
1546
Andreas Huberbe06d262009-08-14 14:37:10 -07001547 IOMX::buffer_id buffer;
1548 if (portIndex == kPortIndexInput
1549 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001550 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001551 mem.clear();
1552
Andreas Huberf1fe0642010-01-15 15:28:19 -08001553 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001554 mNode, portIndex, def.nBufferSize, &buffer,
1555 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001556 } else {
1557 err = mOMX->allocateBufferWithBackup(
1558 mNode, portIndex, mem, &buffer);
1559 }
Andreas Huber446f44f2009-08-25 17:23:44 -07001560 } else if (portIndex == kPortIndexOutput
1561 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001562 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001563 mem.clear();
1564
Andreas Huberf1fe0642010-01-15 15:28:19 -08001565 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001566 mNode, portIndex, def.nBufferSize, &buffer,
1567 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001568 } else {
1569 err = mOMX->allocateBufferWithBackup(
1570 mNode, portIndex, mem, &buffer);
1571 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001572 } else {
Andreas Huber784202e2009-10-15 13:46:54 -07001573 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001574 }
1575
1576 if (err != OK) {
1577 LOGE("allocate_buffer_with_backup failed");
1578 return err;
1579 }
1580
Andreas Huberc712b9f2010-01-20 15:05:46 -08001581 if (mem != NULL) {
1582 info.mData = mem->pointer();
1583 }
1584
Andreas Huberbe06d262009-08-14 14:37:10 -07001585 info.mBuffer = buffer;
1586 info.mOwnedByComponent = false;
1587 info.mMem = mem;
1588 info.mMediaBuffer = NULL;
1589
1590 if (portIndex == kPortIndexOutput) {
Andreas Huber52733b82010-01-25 10:41:35 -08001591 if (!(mOMXLivesLocally
1592 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1593 && (mQuirks & kDefersOutputBufferAllocation))) {
1594 // If the node does not fill in the buffer ptr at this time,
1595 // we will defer creating the MediaBuffer until receiving
1596 // the first FILL_BUFFER_DONE notification instead.
1597 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1598 info.mMediaBuffer->setObserver(this);
1599 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001600 }
1601
1602 mPortBuffers[portIndex].push(info);
1603
Andreas Huber4c483422009-09-02 16:05:36 -07001604 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -07001605 portIndex == kPortIndexInput ? "input" : "output");
1606 }
1607
Andreas Huber2ea14e22009-12-16 09:30:55 -08001608 // dumpPortStatus(portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001609
1610 return OK;
1611}
1612
1613void OMXCodec::on_message(const omx_message &msg) {
1614 Mutex::Autolock autoLock(mLock);
1615
1616 switch (msg.type) {
1617 case omx_message::EVENT:
1618 {
1619 onEvent(
1620 msg.u.event_data.event, msg.u.event_data.data1,
1621 msg.u.event_data.data2);
1622
1623 break;
1624 }
1625
1626 case omx_message::EMPTY_BUFFER_DONE:
1627 {
1628 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1629
Andreas Huber4c483422009-09-02 16:05:36 -07001630 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001631
1632 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1633 size_t i = 0;
1634 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1635 ++i;
1636 }
1637
1638 CHECK(i < buffers->size());
1639 if (!(*buffers)[i].mOwnedByComponent) {
1640 LOGW("We already own input buffer %p, yet received "
1641 "an EMPTY_BUFFER_DONE.", buffer);
1642 }
1643
1644 buffers->editItemAt(i).mOwnedByComponent = false;
1645
1646 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07001647 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001648
1649 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001650 mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001651 CHECK_EQ(err, OK);
1652
1653 buffers->removeAt(i);
Andreas Huber4a9375e2010-02-09 11:54:33 -08001654 } else if (mState != ERROR
1655 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001656 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
1657 drainInputBuffer(&buffers->editItemAt(i));
1658 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001659 break;
1660 }
1661
1662 case omx_message::FILL_BUFFER_DONE:
1663 {
1664 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1665 OMX_U32 flags = msg.u.extended_buffer_data.flags;
1666
Andreas Huber2ea14e22009-12-16 09:30:55 -08001667 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -07001668 buffer,
1669 msg.u.extended_buffer_data.range_length,
Andreas Huber2ea14e22009-12-16 09:30:55 -08001670 flags,
Andreas Huberbe06d262009-08-14 14:37:10 -07001671 msg.u.extended_buffer_data.timestamp,
1672 msg.u.extended_buffer_data.timestamp / 1E6);
1673
1674 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1675 size_t i = 0;
1676 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1677 ++i;
1678 }
1679
1680 CHECK(i < buffers->size());
1681 BufferInfo *info = &buffers->editItemAt(i);
1682
1683 if (!info->mOwnedByComponent) {
1684 LOGW("We already own output buffer %p, yet received "
1685 "a FILL_BUFFER_DONE.", buffer);
1686 }
1687
1688 info->mOwnedByComponent = false;
1689
1690 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07001691 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001692
1693 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001694 mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001695 CHECK_EQ(err, OK);
1696
1697 buffers->removeAt(i);
Andreas Huber2ea14e22009-12-16 09:30:55 -08001698#if 0
Andreas Huberd7795892009-08-26 10:33:47 -07001699 } else if (mPortStatus[kPortIndexOutput] == ENABLED
1700 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001701 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001702 mNoMoreOutputData = true;
1703 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08001704#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07001705 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
1706 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -07001707
Andreas Huber52733b82010-01-25 10:41:35 -08001708 if (info->mMediaBuffer == NULL) {
1709 CHECK(mOMXLivesLocally);
1710 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
1711 CHECK(mQuirks & kDefersOutputBufferAllocation);
1712
1713 // The qcom video decoders on Nexus don't actually allocate
1714 // output buffer memory on a call to OMX_AllocateBuffer
1715 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
1716 // structure is only filled in later.
1717
1718 info->mMediaBuffer = new MediaBuffer(
1719 msg.u.extended_buffer_data.data_ptr,
1720 info->mSize);
1721 info->mMediaBuffer->setObserver(this);
1722 }
1723
Andreas Huberbe06d262009-08-14 14:37:10 -07001724 MediaBuffer *buffer = info->mMediaBuffer;
1725
Andreas Huberf88f8442010-08-10 11:18:36 -07001726 if (msg.u.extended_buffer_data.range_offset
1727 + msg.u.extended_buffer_data.range_length
1728 > buffer->size()) {
1729 CODEC_LOGE(
1730 "Codec lied about its buffer size requirements, "
1731 "sending a buffer larger than the originally "
1732 "advertised size in FILL_BUFFER_DONE!");
1733 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001734 buffer->set_range(
1735 msg.u.extended_buffer_data.range_offset,
1736 msg.u.extended_buffer_data.range_length);
1737
1738 buffer->meta_data()->clear();
1739
Andreas Huberfa8de752009-10-08 10:07:49 -07001740 buffer->meta_data()->setInt64(
1741 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -07001742
1743 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
1744 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
1745 }
Andreas Huberea6a38c2009-11-16 15:43:38 -08001746 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
1747 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
1748 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001749
1750 buffer->meta_data()->setPointer(
1751 kKeyPlatformPrivate,
1752 msg.u.extended_buffer_data.platform_private);
1753
1754 buffer->meta_data()->setPointer(
1755 kKeyBufferID,
1756 msg.u.extended_buffer_data.buffer);
1757
Andreas Huber2ea14e22009-12-16 09:30:55 -08001758 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
1759 CODEC_LOGV("No more output data.");
1760 mNoMoreOutputData = true;
1761 }
Andreas Huber6624c9f2010-07-20 15:04:28 -07001762
1763 if (mTargetTimeUs >= 0) {
1764 CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
1765
1766 if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
1767 CODEC_LOGV(
1768 "skipping output buffer at timestamp %lld us",
1769 msg.u.extended_buffer_data.timestamp);
1770
1771 fillOutputBuffer(info);
1772 break;
1773 }
1774
1775 CODEC_LOGV(
1776 "returning output buffer at target timestamp "
1777 "%lld us",
1778 msg.u.extended_buffer_data.timestamp);
1779
1780 mTargetTimeUs = -1;
1781 }
1782
1783 mFilledBuffers.push_back(i);
1784 mBufferFilled.signal();
Andreas Huberbe06d262009-08-14 14:37:10 -07001785 }
1786
1787 break;
1788 }
1789
1790 default:
1791 {
1792 CHECK(!"should not be here.");
1793 break;
1794 }
1795 }
1796}
1797
1798void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1799 switch (event) {
1800 case OMX_EventCmdComplete:
1801 {
1802 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1803 break;
1804 }
1805
1806 case OMX_EventError:
1807 {
Andreas Huberaf0a1882010-09-21 15:08:52 -07001808 CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001809
1810 setState(ERROR);
1811 break;
1812 }
1813
1814 case OMX_EventPortSettingsChanged:
1815 {
1816 onPortSettingsChanged(data1);
1817 break;
1818 }
1819
Andreas Huber2ea14e22009-12-16 09:30:55 -08001820#if 0
Andreas Huberbe06d262009-08-14 14:37:10 -07001821 case OMX_EventBufferFlag:
1822 {
Andreas Huber4c483422009-09-02 16:05:36 -07001823 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
Andreas Huberbe06d262009-08-14 14:37:10 -07001824
1825 if (data1 == kPortIndexOutput) {
1826 mNoMoreOutputData = true;
1827 }
1828 break;
1829 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08001830#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07001831
1832 default:
1833 {
Andreas Huber4c483422009-09-02 16:05:36 -07001834 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001835 break;
1836 }
1837 }
1838}
1839
Andreas Huberb1678602009-10-19 13:06:40 -07001840// Has the format changed in any way that the client would have to be aware of?
1841static bool formatHasNotablyChanged(
1842 const sp<MetaData> &from, const sp<MetaData> &to) {
1843 if (from.get() == NULL && to.get() == NULL) {
1844 return false;
1845 }
1846
Andreas Huberf68c1682009-10-21 14:01:30 -07001847 if ((from.get() == NULL && to.get() != NULL)
1848 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07001849 return true;
1850 }
1851
1852 const char *mime_from, *mime_to;
1853 CHECK(from->findCString(kKeyMIMEType, &mime_from));
1854 CHECK(to->findCString(kKeyMIMEType, &mime_to));
1855
1856 if (strcasecmp(mime_from, mime_to)) {
1857 return true;
1858 }
1859
1860 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
1861 int32_t colorFormat_from, colorFormat_to;
1862 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
1863 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
1864
1865 if (colorFormat_from != colorFormat_to) {
1866 return true;
1867 }
1868
1869 int32_t width_from, width_to;
1870 CHECK(from->findInt32(kKeyWidth, &width_from));
1871 CHECK(to->findInt32(kKeyWidth, &width_to));
1872
1873 if (width_from != width_to) {
1874 return true;
1875 }
1876
1877 int32_t height_from, height_to;
1878 CHECK(from->findInt32(kKeyHeight, &height_from));
1879 CHECK(to->findInt32(kKeyHeight, &height_to));
1880
1881 if (height_from != height_to) {
1882 return true;
1883 }
1884 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
1885 int32_t numChannels_from, numChannels_to;
1886 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
1887 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
1888
1889 if (numChannels_from != numChannels_to) {
1890 return true;
1891 }
1892
1893 int32_t sampleRate_from, sampleRate_to;
1894 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
1895 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
1896
1897 if (sampleRate_from != sampleRate_to) {
1898 return true;
1899 }
1900 }
1901
1902 return false;
1903}
1904
Andreas Huberbe06d262009-08-14 14:37:10 -07001905void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1906 switch (cmd) {
1907 case OMX_CommandStateSet:
1908 {
1909 onStateChange((OMX_STATETYPE)data);
1910 break;
1911 }
1912
1913 case OMX_CommandPortDisable:
1914 {
1915 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001916 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001917
1918 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1919 CHECK_EQ(mPortStatus[portIndex], DISABLING);
1920 CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1921
1922 mPortStatus[portIndex] = DISABLED;
1923
1924 if (mState == RECONFIGURING) {
1925 CHECK_EQ(portIndex, kPortIndexOutput);
1926
Andreas Huberb1678602009-10-19 13:06:40 -07001927 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07001928 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07001929
1930 // Don't notify clients if the output port settings change
1931 // wasn't of importance to them, i.e. it may be that just the
1932 // number of buffers has changed and nothing else.
1933 mOutputPortSettingsHaveChanged =
1934 formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
Andreas Hubercfd55572009-10-09 14:11:28 -07001935
Andreas Huberbe06d262009-08-14 14:37:10 -07001936 enablePortAsync(portIndex);
1937
1938 status_t err = allocateBuffersOnPort(portIndex);
1939 CHECK_EQ(err, OK);
1940 }
1941 break;
1942 }
1943
1944 case OMX_CommandPortEnable:
1945 {
1946 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001947 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001948
1949 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1950 CHECK_EQ(mPortStatus[portIndex], ENABLING);
1951
1952 mPortStatus[portIndex] = ENABLED;
1953
1954 if (mState == RECONFIGURING) {
1955 CHECK_EQ(portIndex, kPortIndexOutput);
1956
1957 setState(EXECUTING);
1958
1959 fillOutputBuffers();
1960 }
1961 break;
1962 }
1963
1964 case OMX_CommandFlush:
1965 {
1966 OMX_U32 portIndex = data;
1967
Andreas Huber4c483422009-09-02 16:05:36 -07001968 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001969
1970 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1971 mPortStatus[portIndex] = ENABLED;
1972
1973 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1974 mPortBuffers[portIndex].size());
1975
1976 if (mState == RECONFIGURING) {
1977 CHECK_EQ(portIndex, kPortIndexOutput);
1978
1979 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001980 } else if (mState == EXECUTING_TO_IDLE) {
1981 if (mPortStatus[kPortIndexInput] == ENABLED
1982 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001983 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001984 "transition from EXECUTING to IDLE.");
1985
1986 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1987 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1988
1989 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001990 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001991 CHECK_EQ(err, OK);
1992 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001993 } else {
1994 // We're flushing both ports in preparation for seeking.
1995
1996 if (mPortStatus[kPortIndexInput] == ENABLED
1997 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001998 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07001999 " seek-time.");
2000
Andreas Huber1f24b302010-06-10 11:12:39 -07002001 // We implicitly resume pulling on our upstream source.
2002 mPaused = false;
2003
Andreas Huberbe06d262009-08-14 14:37:10 -07002004 drainInputBuffers();
2005 fillOutputBuffers();
2006 }
2007 }
2008
2009 break;
2010 }
2011
2012 default:
2013 {
Andreas Huber4c483422009-09-02 16:05:36 -07002014 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07002015 break;
2016 }
2017 }
2018}
2019
2020void OMXCodec::onStateChange(OMX_STATETYPE newState) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002021 CODEC_LOGV("onStateChange %d", newState);
2022
Andreas Huberbe06d262009-08-14 14:37:10 -07002023 switch (newState) {
2024 case OMX_StateIdle:
2025 {
Andreas Huber4c483422009-09-02 16:05:36 -07002026 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002027 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07002028 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002029 mNode, OMX_CommandStateSet, OMX_StateExecuting);
2030
2031 CHECK_EQ(err, OK);
2032
2033 setState(IDLE_TO_EXECUTING);
2034 } else {
2035 CHECK_EQ(mState, EXECUTING_TO_IDLE);
2036
2037 CHECK_EQ(
2038 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
2039 mPortBuffers[kPortIndexInput].size());
2040
2041 CHECK_EQ(
2042 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
2043 mPortBuffers[kPortIndexOutput].size());
2044
Andreas Huber784202e2009-10-15 13:46:54 -07002045 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002046 mNode, OMX_CommandStateSet, OMX_StateLoaded);
2047
2048 CHECK_EQ(err, OK);
2049
2050 err = freeBuffersOnPort(kPortIndexInput);
2051 CHECK_EQ(err, OK);
2052
2053 err = freeBuffersOnPort(kPortIndexOutput);
2054 CHECK_EQ(err, OK);
2055
2056 mPortStatus[kPortIndexInput] = ENABLED;
2057 mPortStatus[kPortIndexOutput] = ENABLED;
2058
2059 setState(IDLE_TO_LOADED);
2060 }
2061 break;
2062 }
2063
2064 case OMX_StateExecuting:
2065 {
2066 CHECK_EQ(mState, IDLE_TO_EXECUTING);
2067
Andreas Huber4c483422009-09-02 16:05:36 -07002068 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002069
2070 setState(EXECUTING);
2071
Andreas Huber42978e52009-08-27 10:08:39 -07002072 // Buffers will be submitted to the component in the first
2073 // call to OMXCodec::read as mInitialBufferSubmit is true at
2074 // this point. This ensures that this on_message call returns,
2075 // releases the lock and ::init can notice the state change and
2076 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07002077 break;
2078 }
2079
2080 case OMX_StateLoaded:
2081 {
2082 CHECK_EQ(mState, IDLE_TO_LOADED);
2083
Andreas Huber4c483422009-09-02 16:05:36 -07002084 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002085
2086 setState(LOADED);
2087 break;
2088 }
2089
Andreas Huberc712b9f2010-01-20 15:05:46 -08002090 case OMX_StateInvalid:
2091 {
2092 setState(ERROR);
2093 break;
2094 }
2095
Andreas Huberbe06d262009-08-14 14:37:10 -07002096 default:
2097 {
2098 CHECK(!"should not be here.");
2099 break;
2100 }
2101 }
2102}
2103
2104// static
2105size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
2106 size_t n = 0;
2107 for (size_t i = 0; i < buffers.size(); ++i) {
2108 if (!buffers[i].mOwnedByComponent) {
2109 ++n;
2110 }
2111 }
2112
2113 return n;
2114}
2115
2116status_t OMXCodec::freeBuffersOnPort(
2117 OMX_U32 portIndex, bool onlyThoseWeOwn) {
2118 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2119
2120 status_t stickyErr = OK;
2121
2122 for (size_t i = buffers->size(); i-- > 0;) {
2123 BufferInfo *info = &buffers->editItemAt(i);
2124
2125 if (onlyThoseWeOwn && info->mOwnedByComponent) {
2126 continue;
2127 }
2128
2129 CHECK_EQ(info->mOwnedByComponent, false);
2130
Andreas Huber92022852009-09-14 15:24:14 -07002131 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
2132
Andreas Huberbe06d262009-08-14 14:37:10 -07002133 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002134 mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002135
2136 if (err != OK) {
2137 stickyErr = err;
2138 }
2139
2140 if (info->mMediaBuffer != NULL) {
2141 info->mMediaBuffer->setObserver(NULL);
2142
2143 // Make sure nobody but us owns this buffer at this point.
2144 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
2145
2146 info->mMediaBuffer->release();
2147 }
2148
2149 buffers->removeAt(i);
2150 }
2151
2152 CHECK(onlyThoseWeOwn || buffers->isEmpty());
2153
2154 return stickyErr;
2155}
2156
2157void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07002158 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002159
2160 CHECK_EQ(mState, EXECUTING);
2161 CHECK_EQ(portIndex, kPortIndexOutput);
2162 setState(RECONFIGURING);
2163
2164 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07002165 if (!flushPortAsync(portIndex)) {
2166 onCmdComplete(OMX_CommandFlush, portIndex);
2167 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002168 } else {
2169 disablePortAsync(portIndex);
2170 }
2171}
2172
Andreas Huber404cc412009-08-25 14:26:05 -07002173bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07002174 CHECK(mState == EXECUTING || mState == RECONFIGURING
2175 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002176
Andreas Huber4c483422009-09-02 16:05:36 -07002177 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07002178 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
2179 mPortBuffers[portIndex].size());
2180
Andreas Huberbe06d262009-08-14 14:37:10 -07002181 CHECK_EQ(mPortStatus[portIndex], ENABLED);
2182 mPortStatus[portIndex] = SHUTTING_DOWN;
2183
Andreas Huber404cc412009-08-25 14:26:05 -07002184 if ((mQuirks & kRequiresFlushCompleteEmulation)
2185 && countBuffersWeOwn(mPortBuffers[portIndex])
2186 == mPortBuffers[portIndex].size()) {
2187 // No flush is necessary and this component fails to send a
2188 // flush-complete event in this case.
2189
2190 return false;
2191 }
2192
Andreas Huberbe06d262009-08-14 14:37:10 -07002193 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002194 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002195 CHECK_EQ(err, OK);
Andreas Huber404cc412009-08-25 14:26:05 -07002196
2197 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002198}
2199
2200void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
2201 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2202
2203 CHECK_EQ(mPortStatus[portIndex], ENABLED);
2204 mPortStatus[portIndex] = DISABLING;
2205
2206 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002207 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002208 CHECK_EQ(err, OK);
2209
2210 freeBuffersOnPort(portIndex, true);
2211}
2212
2213void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
2214 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2215
2216 CHECK_EQ(mPortStatus[portIndex], DISABLED);
2217 mPortStatus[portIndex] = ENABLING;
2218
2219 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002220 mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002221 CHECK_EQ(err, OK);
2222}
2223
2224void OMXCodec::fillOutputBuffers() {
2225 CHECK_EQ(mState, EXECUTING);
2226
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002227 // This is a workaround for some decoders not properly reporting
2228 // end-of-output-stream. If we own all input buffers and also own
2229 // all output buffers and we already signalled end-of-input-stream,
2230 // the end-of-output-stream is implied.
2231 if (mSignalledEOS
2232 && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
2233 == mPortBuffers[kPortIndexInput].size()
2234 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
2235 == mPortBuffers[kPortIndexOutput].size()) {
2236 mNoMoreOutputData = true;
2237 mBufferFilled.signal();
2238
2239 return;
2240 }
2241
Andreas Huberbe06d262009-08-14 14:37:10 -07002242 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2243 for (size_t i = 0; i < buffers->size(); ++i) {
2244 fillOutputBuffer(&buffers->editItemAt(i));
2245 }
2246}
2247
2248void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07002249 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002250
2251 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2252 for (size_t i = 0; i < buffers->size(); ++i) {
2253 drainInputBuffer(&buffers->editItemAt(i));
2254 }
2255}
2256
2257void OMXCodec::drainInputBuffer(BufferInfo *info) {
2258 CHECK_EQ(info->mOwnedByComponent, false);
2259
2260 if (mSignalledEOS) {
2261 return;
2262 }
2263
2264 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
2265 const CodecSpecificData *specific =
2266 mCodecSpecificData[mCodecSpecificDataIndex];
2267
2268 size_t size = specific->mSize;
2269
Andreas Hubere6c40962009-09-10 14:13:30 -07002270 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07002271 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002272 static const uint8_t kNALStartCode[4] =
2273 { 0x00, 0x00, 0x00, 0x01 };
2274
Andreas Huberc712b9f2010-01-20 15:05:46 -08002275 CHECK(info->mSize >= specific->mSize + 4);
Andreas Huberbe06d262009-08-14 14:37:10 -07002276
2277 size += 4;
2278
Andreas Huberc712b9f2010-01-20 15:05:46 -08002279 memcpy(info->mData, kNALStartCode, 4);
2280 memcpy((uint8_t *)info->mData + 4,
Andreas Huberbe06d262009-08-14 14:37:10 -07002281 specific->mData, specific->mSize);
2282 } else {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002283 CHECK(info->mSize >= specific->mSize);
2284 memcpy(info->mData, specific->mData, specific->mSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07002285 }
2286
Andreas Huber2ea14e22009-12-16 09:30:55 -08002287 mNoMoreOutputData = false;
2288
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002289 CODEC_LOGV("calling emptyBuffer with codec specific data");
2290
Andreas Huber784202e2009-10-15 13:46:54 -07002291 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07002292 mNode, info->mBuffer, 0, size,
2293 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
2294 0);
Andreas Huber3f427072009-10-08 11:02:27 -07002295 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002296
2297 info->mOwnedByComponent = true;
2298
2299 ++mCodecSpecificDataIndex;
2300 return;
2301 }
2302
Andreas Huber1f24b302010-06-10 11:12:39 -07002303 if (mPaused) {
2304 return;
2305 }
2306
Andreas Huberbe06d262009-08-14 14:37:10 -07002307 status_t err;
Andreas Huber2ea14e22009-12-16 09:30:55 -08002308
Andreas Hubera4357ad2010-04-02 12:49:54 -07002309 bool signalEOS = false;
2310 int64_t timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07002311
Andreas Hubera4357ad2010-04-02 12:49:54 -07002312 size_t offset = 0;
2313 int32_t n = 0;
2314 for (;;) {
2315 MediaBuffer *srcBuffer;
James Dong53d4e0d2010-07-21 14:51:35 -07002316 MediaSource::ReadOptions options;
2317 if (mSkipTimeUs >= 0) {
2318 options.setSkipFrame(mSkipTimeUs);
2319 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002320 if (mSeekTimeUs >= 0) {
2321 if (mLeftOverBuffer) {
2322 mLeftOverBuffer->release();
2323 mLeftOverBuffer = NULL;
2324 }
Andreas Huber6624c9f2010-07-20 15:04:28 -07002325 options.setSeekTo(mSeekTimeUs, mSeekMode);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002326
2327 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002328 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002329 mBufferFilled.signal();
2330
2331 err = mSource->read(&srcBuffer, &options);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002332
2333 if (err == OK) {
2334 int64_t targetTimeUs;
2335 if (srcBuffer->meta_data()->findInt64(
2336 kKeyTargetTime, &targetTimeUs)
2337 && targetTimeUs >= 0) {
2338 mTargetTimeUs = targetTimeUs;
2339 } else {
2340 mTargetTimeUs = -1;
2341 }
2342 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002343 } else if (mLeftOverBuffer) {
2344 srcBuffer = mLeftOverBuffer;
2345 mLeftOverBuffer = NULL;
2346
2347 err = OK;
2348 } else {
James Dong53d4e0d2010-07-21 14:51:35 -07002349 err = mSource->read(&srcBuffer, &options);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002350 }
2351
2352 if (err != OK) {
2353 signalEOS = true;
2354 mFinalStatus = err;
2355 mSignalledEOS = true;
2356 break;
2357 }
2358
2359 size_t remainingBytes = info->mSize - offset;
2360
2361 if (srcBuffer->range_length() > remainingBytes) {
2362 if (offset == 0) {
2363 CODEC_LOGE(
2364 "Codec's input buffers are too small to accomodate "
2365 "buffer read from source (info->mSize = %d, srcLength = %d)",
2366 info->mSize, srcBuffer->range_length());
2367
2368 srcBuffer->release();
2369 srcBuffer = NULL;
2370
2371 setState(ERROR);
2372 return;
2373 }
2374
2375 mLeftOverBuffer = srcBuffer;
2376 break;
2377 }
2378
James Dong4f501f02010-06-07 14:41:41 -07002379 if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2380 CHECK(mOMXLivesLocally && offset == 0);
2381 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
2382 header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
2383 } else {
2384 memcpy((uint8_t *)info->mData + offset,
2385 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
2386 srcBuffer->range_length());
2387 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002388
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002389 int64_t lastBufferTimeUs;
2390 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
Andreas Huber6624c9f2010-07-20 15:04:28 -07002391 CHECK(lastBufferTimeUs >= 0);
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002392
Andreas Hubera4357ad2010-04-02 12:49:54 -07002393 if (offset == 0) {
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002394 timestampUs = lastBufferTimeUs;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002395 }
2396
2397 offset += srcBuffer->range_length();
2398
2399 srcBuffer->release();
2400 srcBuffer = NULL;
2401
2402 ++n;
2403
2404 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
2405 break;
2406 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002407
2408 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
2409
2410 if (coalescedDurationUs > 250000ll) {
2411 // Don't coalesce more than 250ms worth of encoded data at once.
2412 break;
2413 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002414 }
2415
2416 if (n > 1) {
2417 LOGV("coalesced %d frames into one input buffer", n);
Andreas Huberbe06d262009-08-14 14:37:10 -07002418 }
2419
2420 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberbe06d262009-08-14 14:37:10 -07002421
Andreas Hubera4357ad2010-04-02 12:49:54 -07002422 if (signalEOS) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002423 flags |= OMX_BUFFERFLAG_EOS;
Andreas Huberbe06d262009-08-14 14:37:10 -07002424 } else {
Andreas Huber2ea14e22009-12-16 09:30:55 -08002425 mNoMoreOutputData = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002426 }
2427
Andreas Hubera4357ad2010-04-02 12:49:54 -07002428 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
2429 "timestamp %lld us (%.2f secs)",
2430 info->mBuffer, offset,
2431 timestampUs, timestampUs / 1E6);
Andreas Huber3f427072009-10-08 11:02:27 -07002432
Andreas Huber784202e2009-10-15 13:46:54 -07002433 err = mOMX->emptyBuffer(
Andreas Hubera4357ad2010-04-02 12:49:54 -07002434 mNode, info->mBuffer, 0, offset,
Andreas Huberfa8de752009-10-08 10:07:49 -07002435 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07002436
2437 if (err != OK) {
2438 setState(ERROR);
2439 return;
2440 }
2441
2442 info->mOwnedByComponent = true;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002443
2444 // This component does not ever signal the EOS flag on output buffers,
2445 // Thanks for nothing.
2446 if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) {
2447 mNoMoreOutputData = true;
2448 mBufferFilled.signal();
2449 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002450}
2451
2452void OMXCodec::fillOutputBuffer(BufferInfo *info) {
2453 CHECK_EQ(info->mOwnedByComponent, false);
2454
Andreas Huber404cc412009-08-25 14:26:05 -07002455 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07002456 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07002457 "calling fillOutputBuffer");
2458 return;
2459 }
2460
Andreas Huber4c483422009-09-02 16:05:36 -07002461 CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07002462 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber8f14c552010-04-12 10:20:12 -07002463
2464 if (err != OK) {
2465 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
2466
2467 setState(ERROR);
2468 return;
2469 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002470
2471 info->mOwnedByComponent = true;
2472}
2473
2474void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
2475 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2476 for (size_t i = 0; i < buffers->size(); ++i) {
2477 if ((*buffers)[i].mBuffer == buffer) {
2478 drainInputBuffer(&buffers->editItemAt(i));
2479 return;
2480 }
2481 }
2482
2483 CHECK(!"should not be here.");
2484}
2485
2486void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
2487 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2488 for (size_t i = 0; i < buffers->size(); ++i) {
2489 if ((*buffers)[i].mBuffer == buffer) {
2490 fillOutputBuffer(&buffers->editItemAt(i));
2491 return;
2492 }
2493 }
2494
2495 CHECK(!"should not be here.");
2496}
2497
2498void OMXCodec::setState(State newState) {
2499 mState = newState;
2500 mAsyncCompletion.signal();
2501
2502 // This may cause some spurious wakeups but is necessary to
2503 // unblock the reader if we enter ERROR state.
2504 mBufferFilled.signal();
2505}
2506
Andreas Huberda050cf22009-09-02 14:01:43 -07002507void OMXCodec::setRawAudioFormat(
2508 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
James Dongabed93a2010-04-22 17:27:04 -07002509
2510 // port definition
2511 OMX_PARAM_PORTDEFINITIONTYPE def;
2512 InitOMXParams(&def);
2513 def.nPortIndex = portIndex;
2514 status_t err = mOMX->getParameter(
2515 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2516 CHECK_EQ(err, OK);
2517 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2518 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2519 &def, sizeof(def)), OK);
2520
2521 // pcm param
Andreas Huberda050cf22009-09-02 14:01:43 -07002522 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07002523 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07002524 pcmParams.nPortIndex = portIndex;
2525
James Dongabed93a2010-04-22 17:27:04 -07002526 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002527 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2528
2529 CHECK_EQ(err, OK);
2530
2531 pcmParams.nChannels = numChannels;
2532 pcmParams.eNumData = OMX_NumericalDataSigned;
2533 pcmParams.bInterleaved = OMX_TRUE;
2534 pcmParams.nBitPerSample = 16;
2535 pcmParams.nSamplingRate = sampleRate;
2536 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2537
2538 if (numChannels == 1) {
2539 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
2540 } else {
2541 CHECK_EQ(numChannels, 2);
2542
2543 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2544 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2545 }
2546
Andreas Huber784202e2009-10-15 13:46:54 -07002547 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002548 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2549
2550 CHECK_EQ(err, OK);
2551}
2552
James Dong17299ab2010-05-14 15:45:22 -07002553static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
2554 if (isAMRWB) {
2555 if (bps <= 6600) {
2556 return OMX_AUDIO_AMRBandModeWB0;
2557 } else if (bps <= 8850) {
2558 return OMX_AUDIO_AMRBandModeWB1;
2559 } else if (bps <= 12650) {
2560 return OMX_AUDIO_AMRBandModeWB2;
2561 } else if (bps <= 14250) {
2562 return OMX_AUDIO_AMRBandModeWB3;
2563 } else if (bps <= 15850) {
2564 return OMX_AUDIO_AMRBandModeWB4;
2565 } else if (bps <= 18250) {
2566 return OMX_AUDIO_AMRBandModeWB5;
2567 } else if (bps <= 19850) {
2568 return OMX_AUDIO_AMRBandModeWB6;
2569 } else if (bps <= 23050) {
2570 return OMX_AUDIO_AMRBandModeWB7;
2571 }
2572
2573 // 23850 bps
2574 return OMX_AUDIO_AMRBandModeWB8;
2575 } else { // AMRNB
2576 if (bps <= 4750) {
2577 return OMX_AUDIO_AMRBandModeNB0;
2578 } else if (bps <= 5150) {
2579 return OMX_AUDIO_AMRBandModeNB1;
2580 } else if (bps <= 5900) {
2581 return OMX_AUDIO_AMRBandModeNB2;
2582 } else if (bps <= 6700) {
2583 return OMX_AUDIO_AMRBandModeNB3;
2584 } else if (bps <= 7400) {
2585 return OMX_AUDIO_AMRBandModeNB4;
2586 } else if (bps <= 7950) {
2587 return OMX_AUDIO_AMRBandModeNB5;
2588 } else if (bps <= 10200) {
2589 return OMX_AUDIO_AMRBandModeNB6;
2590 }
2591
2592 // 12200 bps
2593 return OMX_AUDIO_AMRBandModeNB7;
2594 }
2595}
2596
2597void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
Andreas Huber8768f2c2009-12-01 15:26:54 -08002598 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002599
Andreas Huber8768f2c2009-12-01 15:26:54 -08002600 OMX_AUDIO_PARAM_AMRTYPE def;
2601 InitOMXParams(&def);
2602 def.nPortIndex = portIndex;
Andreas Huberbe06d262009-08-14 14:37:10 -07002603
Andreas Huber8768f2c2009-12-01 15:26:54 -08002604 status_t err =
2605 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07002606
Andreas Huber8768f2c2009-12-01 15:26:54 -08002607 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002608
Andreas Huber8768f2c2009-12-01 15:26:54 -08002609 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
James Dongabed93a2010-04-22 17:27:04 -07002610
James Dong17299ab2010-05-14 15:45:22 -07002611 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
Andreas Huber8768f2c2009-12-01 15:26:54 -08002612 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2613 CHECK_EQ(err, OK);
Andreas Huberee606e62009-09-08 10:19:21 -07002614
2615 ////////////////////////
2616
2617 if (mIsEncoder) {
2618 sp<MetaData> format = mSource->getFormat();
2619 int32_t sampleRate;
2620 int32_t numChannels;
2621 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
2622 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
2623
2624 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2625 }
2626}
2627
James Dong17299ab2010-05-14 15:45:22 -07002628void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
James Dongabed93a2010-04-22 17:27:04 -07002629 CHECK(numChannels == 1 || numChannels == 2);
Andreas Huberda050cf22009-09-02 14:01:43 -07002630 if (mIsEncoder) {
James Dongabed93a2010-04-22 17:27:04 -07002631 //////////////// input port ////////////////////
Andreas Huberda050cf22009-09-02 14:01:43 -07002632 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
James Dongabed93a2010-04-22 17:27:04 -07002633
2634 //////////////// output port ////////////////////
2635 // format
2636 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2637 format.nPortIndex = kPortIndexOutput;
2638 format.nIndex = 0;
2639 status_t err = OMX_ErrorNone;
2640 while (OMX_ErrorNone == err) {
2641 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
2642 &format, sizeof(format)), OK);
2643 if (format.eEncoding == OMX_AUDIO_CodingAAC) {
2644 break;
2645 }
2646 format.nIndex++;
2647 }
2648 CHECK_EQ(OK, err);
2649 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
2650 &format, sizeof(format)), OK);
2651
2652 // port definition
2653 OMX_PARAM_PORTDEFINITIONTYPE def;
2654 InitOMXParams(&def);
2655 def.nPortIndex = kPortIndexOutput;
2656 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
2657 &def, sizeof(def)), OK);
2658 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2659 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2660 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2661 &def, sizeof(def)), OK);
2662
2663 // profile
2664 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2665 InitOMXParams(&profile);
2666 profile.nPortIndex = kPortIndexOutput;
2667 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
2668 &profile, sizeof(profile)), OK);
2669 profile.nChannels = numChannels;
2670 profile.eChannelMode = (numChannels == 1?
2671 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
2672 profile.nSampleRate = sampleRate;
James Dong17299ab2010-05-14 15:45:22 -07002673 profile.nBitRate = bitRate;
James Dongabed93a2010-04-22 17:27:04 -07002674 profile.nAudioBandWidth = 0;
2675 profile.nFrameLength = 0;
2676 profile.nAACtools = OMX_AUDIO_AACToolAll;
2677 profile.nAACERtools = OMX_AUDIO_AACERNone;
2678 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
2679 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2680 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
2681 &profile, sizeof(profile)), OK);
2682
Andreas Huberda050cf22009-09-02 14:01:43 -07002683 } else {
2684 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07002685 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07002686 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002687
Andreas Huber784202e2009-10-15 13:46:54 -07002688 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002689 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2690 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002691
Andreas Huberda050cf22009-09-02 14:01:43 -07002692 profile.nChannels = numChannels;
2693 profile.nSampleRate = sampleRate;
2694 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07002695
Andreas Huber784202e2009-10-15 13:46:54 -07002696 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002697 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2698 CHECK_EQ(err, OK);
2699 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002700}
2701
2702void OMXCodec::setImageOutputFormat(
2703 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07002704 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07002705
2706#if 0
2707 OMX_INDEXTYPE index;
2708 status_t err = mOMX->get_extension_index(
2709 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
2710 CHECK_EQ(err, OK);
2711
2712 err = mOMX->set_config(mNode, index, &format, sizeof(format));
2713 CHECK_EQ(err, OK);
2714#endif
2715
2716 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002717 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002718 def.nPortIndex = kPortIndexOutput;
2719
Andreas Huber784202e2009-10-15 13:46:54 -07002720 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002721 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2722 CHECK_EQ(err, OK);
2723
2724 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2725
2726 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07002727
Andreas Huberbe06d262009-08-14 14:37:10 -07002728 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2729 imageDef->eColorFormat = format;
2730 imageDef->nFrameWidth = width;
2731 imageDef->nFrameHeight = height;
2732
2733 switch (format) {
2734 case OMX_COLOR_FormatYUV420PackedPlanar:
2735 case OMX_COLOR_FormatYUV411Planar:
2736 {
2737 def.nBufferSize = (width * height * 3) / 2;
2738 break;
2739 }
2740
2741 case OMX_COLOR_FormatCbYCrY:
2742 {
2743 def.nBufferSize = width * height * 2;
2744 break;
2745 }
2746
2747 case OMX_COLOR_Format32bitARGB8888:
2748 {
2749 def.nBufferSize = width * height * 4;
2750 break;
2751 }
2752
Andreas Huber201511c2009-09-08 14:01:44 -07002753 case OMX_COLOR_Format16bitARGB4444:
2754 case OMX_COLOR_Format16bitARGB1555:
2755 case OMX_COLOR_Format16bitRGB565:
2756 case OMX_COLOR_Format16bitBGR565:
2757 {
2758 def.nBufferSize = width * height * 2;
2759 break;
2760 }
2761
Andreas Huberbe06d262009-08-14 14:37:10 -07002762 default:
2763 CHECK(!"Should not be here. Unknown color format.");
2764 break;
2765 }
2766
Andreas Huber5c0a9132009-08-20 11:16:40 -07002767 def.nBufferCountActual = def.nBufferCountMin;
2768
Andreas Huber784202e2009-10-15 13:46:54 -07002769 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002770 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2771 CHECK_EQ(err, OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07002772}
Andreas Huberbe06d262009-08-14 14:37:10 -07002773
Andreas Huber5c0a9132009-08-20 11:16:40 -07002774void OMXCodec::setJPEGInputFormat(
2775 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
2776 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002777 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002778 def.nPortIndex = kPortIndexInput;
2779
Andreas Huber784202e2009-10-15 13:46:54 -07002780 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002781 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2782 CHECK_EQ(err, OK);
2783
Andreas Huber5c0a9132009-08-20 11:16:40 -07002784 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2785 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2786
Andreas Huberbe06d262009-08-14 14:37:10 -07002787 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
2788 imageDef->nFrameWidth = width;
2789 imageDef->nFrameHeight = height;
2790
Andreas Huber5c0a9132009-08-20 11:16:40 -07002791 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07002792 def.nBufferCountActual = def.nBufferCountMin;
2793
Andreas Huber784202e2009-10-15 13:46:54 -07002794 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002795 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2796 CHECK_EQ(err, OK);
2797}
2798
2799void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
2800 CodecSpecificData *specific =
2801 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
2802
2803 specific->mSize = size;
2804 memcpy(specific->mData, data, size);
2805
2806 mCodecSpecificData.push(specific);
2807}
2808
2809void OMXCodec::clearCodecSpecificData() {
2810 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
2811 free(mCodecSpecificData.editItemAt(i));
2812 }
2813 mCodecSpecificData.clear();
2814 mCodecSpecificDataIndex = 0;
2815}
2816
James Dong36e573b2010-06-19 09:04:18 -07002817status_t OMXCodec::start(MetaData *meta) {
Andreas Huber42978e52009-08-27 10:08:39 -07002818 Mutex::Autolock autoLock(mLock);
2819
Andreas Huberbe06d262009-08-14 14:37:10 -07002820 if (mState != LOADED) {
2821 return UNKNOWN_ERROR;
2822 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07002823
Andreas Huberbe06d262009-08-14 14:37:10 -07002824 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07002825 if (mQuirks & kWantsNALFragments) {
2826 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07002827 }
James Dong36e573b2010-06-19 09:04:18 -07002828 if (meta) {
2829 int64_t startTimeUs = 0;
2830 int64_t timeUs;
2831 if (meta->findInt64(kKeyTime, &timeUs)) {
2832 startTimeUs = timeUs;
2833 }
2834 params->setInt64(kKeyTime, startTimeUs);
2835 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002836 status_t err = mSource->start(params.get());
2837
2838 if (err != OK) {
2839 return err;
2840 }
2841
2842 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07002843 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002844 mSignalledEOS = false;
2845 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07002846 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002847 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002848 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
2849 mTargetTimeUs = -1;
Andreas Huberbe06d262009-08-14 14:37:10 -07002850 mFilledBuffers.clear();
Andreas Huber1f24b302010-06-10 11:12:39 -07002851 mPaused = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002852
2853 return init();
2854}
2855
2856status_t OMXCodec::stop() {
Andreas Huber4a9375e2010-02-09 11:54:33 -08002857 CODEC_LOGV("stop mState=%d", mState);
Andreas Huberbe06d262009-08-14 14:37:10 -07002858
2859 Mutex::Autolock autoLock(mLock);
2860
2861 while (isIntermediateState(mState)) {
2862 mAsyncCompletion.wait(mLock);
2863 }
2864
2865 switch (mState) {
2866 case LOADED:
2867 case ERROR:
2868 break;
2869
2870 case EXECUTING:
2871 {
2872 setState(EXECUTING_TO_IDLE);
2873
Andreas Huber127fcdc2009-08-26 16:27:02 -07002874 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07002875 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07002876 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07002877
Andreas Huber127fcdc2009-08-26 16:27:02 -07002878 bool emulateInputFlushCompletion =
2879 !flushPortAsync(kPortIndexInput);
2880
2881 bool emulateOutputFlushCompletion =
2882 !flushPortAsync(kPortIndexOutput);
2883
2884 if (emulateInputFlushCompletion) {
2885 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2886 }
2887
2888 if (emulateOutputFlushCompletion) {
2889 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2890 }
2891 } else {
2892 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2893 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2894
2895 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002896 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002897 CHECK_EQ(err, OK);
2898 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002899
2900 while (mState != LOADED && mState != ERROR) {
2901 mAsyncCompletion.wait(mLock);
2902 }
2903
2904 break;
2905 }
2906
2907 default:
2908 {
2909 CHECK(!"should not be here.");
2910 break;
2911 }
2912 }
2913
Andreas Hubera4357ad2010-04-02 12:49:54 -07002914 if (mLeftOverBuffer) {
2915 mLeftOverBuffer->release();
2916 mLeftOverBuffer = NULL;
2917 }
2918
Andreas Huberbe06d262009-08-14 14:37:10 -07002919 mSource->stop();
2920
Andreas Huber4a9375e2010-02-09 11:54:33 -08002921 CODEC_LOGV("stopped");
2922
Andreas Huberbe06d262009-08-14 14:37:10 -07002923 return OK;
2924}
2925
2926sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07002927 Mutex::Autolock autoLock(mLock);
2928
Andreas Huberbe06d262009-08-14 14:37:10 -07002929 return mOutputFormat;
2930}
2931
2932status_t OMXCodec::read(
2933 MediaBuffer **buffer, const ReadOptions *options) {
2934 *buffer = NULL;
2935
2936 Mutex::Autolock autoLock(mLock);
2937
Andreas Huberd06e5b82009-08-28 13:18:14 -07002938 if (mState != EXECUTING && mState != RECONFIGURING) {
2939 return UNKNOWN_ERROR;
2940 }
2941
Andreas Hubere981c332009-10-22 13:49:30 -07002942 bool seeking = false;
2943 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002944 ReadOptions::SeekMode seekMode;
2945 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
Andreas Hubere981c332009-10-22 13:49:30 -07002946 seeking = true;
2947 }
James Dong53d4e0d2010-07-21 14:51:35 -07002948 int64_t skipTimeUs;
2949 if (options && options->getSkipFrame(&skipTimeUs)) {
2950 mSkipTimeUs = skipTimeUs;
2951 } else {
2952 mSkipTimeUs = -1;
2953 }
Andreas Hubere981c332009-10-22 13:49:30 -07002954
Andreas Huber42978e52009-08-27 10:08:39 -07002955 if (mInitialBufferSubmit) {
2956 mInitialBufferSubmit = false;
2957
Andreas Hubere981c332009-10-22 13:49:30 -07002958 if (seeking) {
2959 CHECK(seekTimeUs >= 0);
2960 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002961 mSeekMode = seekMode;
Andreas Hubere981c332009-10-22 13:49:30 -07002962
2963 // There's no reason to trigger the code below, there's
2964 // nothing to flush yet.
2965 seeking = false;
Andreas Huber1f24b302010-06-10 11:12:39 -07002966 mPaused = false;
Andreas Hubere981c332009-10-22 13:49:30 -07002967 }
2968
Andreas Huber42978e52009-08-27 10:08:39 -07002969 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07002970
Andreas Huberd06e5b82009-08-28 13:18:14 -07002971 if (mState == EXECUTING) {
2972 // Otherwise mState == RECONFIGURING and this code will trigger
2973 // after the output port is reenabled.
2974 fillOutputBuffers();
2975 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002976 }
2977
Andreas Hubere981c332009-10-22 13:49:30 -07002978 if (seeking) {
Andreas Huber4c483422009-09-02 16:05:36 -07002979 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07002980
2981 mSignalledEOS = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002982
2983 CHECK(seekTimeUs >= 0);
2984 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002985 mSeekMode = seekMode;
Andreas Huberbe06d262009-08-14 14:37:10 -07002986
2987 mFilledBuffers.clear();
2988
2989 CHECK_EQ(mState, EXECUTING);
2990
Andreas Huber404cc412009-08-25 14:26:05 -07002991 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
2992 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
2993
2994 if (emulateInputFlushCompletion) {
2995 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2996 }
2997
2998 if (emulateOutputFlushCompletion) {
2999 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3000 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003001
3002 while (mSeekTimeUs >= 0) {
3003 mBufferFilled.wait(mLock);
3004 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003005 }
3006
3007 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
3008 mBufferFilled.wait(mLock);
3009 }
3010
3011 if (mState == ERROR) {
3012 return UNKNOWN_ERROR;
3013 }
3014
3015 if (mFilledBuffers.empty()) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08003016 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
Andreas Huberbe06d262009-08-14 14:37:10 -07003017 }
3018
Andreas Hubercfd55572009-10-09 14:11:28 -07003019 if (mOutputPortSettingsHaveChanged) {
3020 mOutputPortSettingsHaveChanged = false;
3021
3022 return INFO_FORMAT_CHANGED;
3023 }
3024
Andreas Huberbe06d262009-08-14 14:37:10 -07003025 size_t index = *mFilledBuffers.begin();
3026 mFilledBuffers.erase(mFilledBuffers.begin());
3027
3028 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
3029 info->mMediaBuffer->add_ref();
3030 *buffer = info->mMediaBuffer;
3031
3032 return OK;
3033}
3034
3035void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
3036 Mutex::Autolock autoLock(mLock);
3037
3038 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3039 for (size_t i = 0; i < buffers->size(); ++i) {
3040 BufferInfo *info = &buffers->editItemAt(i);
3041
3042 if (info->mMediaBuffer == buffer) {
3043 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
3044 fillOutputBuffer(info);
3045 return;
3046 }
3047 }
3048
3049 CHECK(!"should not be here.");
3050}
3051
3052static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
3053 static const char *kNames[] = {
3054 "OMX_IMAGE_CodingUnused",
3055 "OMX_IMAGE_CodingAutoDetect",
3056 "OMX_IMAGE_CodingJPEG",
3057 "OMX_IMAGE_CodingJPEG2K",
3058 "OMX_IMAGE_CodingEXIF",
3059 "OMX_IMAGE_CodingTIFF",
3060 "OMX_IMAGE_CodingGIF",
3061 "OMX_IMAGE_CodingPNG",
3062 "OMX_IMAGE_CodingLZW",
3063 "OMX_IMAGE_CodingBMP",
3064 };
3065
3066 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3067
3068 if (type < 0 || (size_t)type >= numNames) {
3069 return "UNKNOWN";
3070 } else {
3071 return kNames[type];
3072 }
3073}
3074
3075static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
3076 static const char *kNames[] = {
3077 "OMX_COLOR_FormatUnused",
3078 "OMX_COLOR_FormatMonochrome",
3079 "OMX_COLOR_Format8bitRGB332",
3080 "OMX_COLOR_Format12bitRGB444",
3081 "OMX_COLOR_Format16bitARGB4444",
3082 "OMX_COLOR_Format16bitARGB1555",
3083 "OMX_COLOR_Format16bitRGB565",
3084 "OMX_COLOR_Format16bitBGR565",
3085 "OMX_COLOR_Format18bitRGB666",
3086 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003087 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07003088 "OMX_COLOR_Format24bitRGB888",
3089 "OMX_COLOR_Format24bitBGR888",
3090 "OMX_COLOR_Format24bitARGB1887",
3091 "OMX_COLOR_Format25bitARGB1888",
3092 "OMX_COLOR_Format32bitBGRA8888",
3093 "OMX_COLOR_Format32bitARGB8888",
3094 "OMX_COLOR_FormatYUV411Planar",
3095 "OMX_COLOR_FormatYUV411PackedPlanar",
3096 "OMX_COLOR_FormatYUV420Planar",
3097 "OMX_COLOR_FormatYUV420PackedPlanar",
3098 "OMX_COLOR_FormatYUV420SemiPlanar",
3099 "OMX_COLOR_FormatYUV422Planar",
3100 "OMX_COLOR_FormatYUV422PackedPlanar",
3101 "OMX_COLOR_FormatYUV422SemiPlanar",
3102 "OMX_COLOR_FormatYCbYCr",
3103 "OMX_COLOR_FormatYCrYCb",
3104 "OMX_COLOR_FormatCbYCrY",
3105 "OMX_COLOR_FormatCrYCbY",
3106 "OMX_COLOR_FormatYUV444Interleaved",
3107 "OMX_COLOR_FormatRawBayer8bit",
3108 "OMX_COLOR_FormatRawBayer10bit",
3109 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003110 "OMX_COLOR_FormatL2",
3111 "OMX_COLOR_FormatL4",
3112 "OMX_COLOR_FormatL8",
3113 "OMX_COLOR_FormatL16",
3114 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07003115 "OMX_COLOR_FormatL32",
3116 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
3117 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
3118 "OMX_COLOR_Format18BitBGR666",
3119 "OMX_COLOR_Format24BitARGB6666",
3120 "OMX_COLOR_Format24BitABGR6666",
3121 };
3122
3123 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3124
Andreas Huberbe06d262009-08-14 14:37:10 -07003125 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
3126 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
3127 } else if (type < 0 || (size_t)type >= numNames) {
3128 return "UNKNOWN";
3129 } else {
3130 return kNames[type];
3131 }
3132}
3133
3134static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
3135 static const char *kNames[] = {
3136 "OMX_VIDEO_CodingUnused",
3137 "OMX_VIDEO_CodingAutoDetect",
3138 "OMX_VIDEO_CodingMPEG2",
3139 "OMX_VIDEO_CodingH263",
3140 "OMX_VIDEO_CodingMPEG4",
3141 "OMX_VIDEO_CodingWMV",
3142 "OMX_VIDEO_CodingRV",
3143 "OMX_VIDEO_CodingAVC",
3144 "OMX_VIDEO_CodingMJPEG",
3145 };
3146
3147 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3148
3149 if (type < 0 || (size_t)type >= numNames) {
3150 return "UNKNOWN";
3151 } else {
3152 return kNames[type];
3153 }
3154}
3155
3156static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
3157 static const char *kNames[] = {
3158 "OMX_AUDIO_CodingUnused",
3159 "OMX_AUDIO_CodingAutoDetect",
3160 "OMX_AUDIO_CodingPCM",
3161 "OMX_AUDIO_CodingADPCM",
3162 "OMX_AUDIO_CodingAMR",
3163 "OMX_AUDIO_CodingGSMFR",
3164 "OMX_AUDIO_CodingGSMEFR",
3165 "OMX_AUDIO_CodingGSMHR",
3166 "OMX_AUDIO_CodingPDCFR",
3167 "OMX_AUDIO_CodingPDCEFR",
3168 "OMX_AUDIO_CodingPDCHR",
3169 "OMX_AUDIO_CodingTDMAFR",
3170 "OMX_AUDIO_CodingTDMAEFR",
3171 "OMX_AUDIO_CodingQCELP8",
3172 "OMX_AUDIO_CodingQCELP13",
3173 "OMX_AUDIO_CodingEVRC",
3174 "OMX_AUDIO_CodingSMV",
3175 "OMX_AUDIO_CodingG711",
3176 "OMX_AUDIO_CodingG723",
3177 "OMX_AUDIO_CodingG726",
3178 "OMX_AUDIO_CodingG729",
3179 "OMX_AUDIO_CodingAAC",
3180 "OMX_AUDIO_CodingMP3",
3181 "OMX_AUDIO_CodingSBC",
3182 "OMX_AUDIO_CodingVORBIS",
3183 "OMX_AUDIO_CodingWMA",
3184 "OMX_AUDIO_CodingRA",
3185 "OMX_AUDIO_CodingMIDI",
3186 };
3187
3188 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3189
3190 if (type < 0 || (size_t)type >= numNames) {
3191 return "UNKNOWN";
3192 } else {
3193 return kNames[type];
3194 }
3195}
3196
3197static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
3198 static const char *kNames[] = {
3199 "OMX_AUDIO_PCMModeLinear",
3200 "OMX_AUDIO_PCMModeALaw",
3201 "OMX_AUDIO_PCMModeMULaw",
3202 };
3203
3204 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3205
3206 if (type < 0 || (size_t)type >= numNames) {
3207 return "UNKNOWN";
3208 } else {
3209 return kNames[type];
3210 }
3211}
3212
Andreas Huber7ae02c82009-09-09 16:29:47 -07003213static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
3214 static const char *kNames[] = {
3215 "OMX_AUDIO_AMRBandModeUnused",
3216 "OMX_AUDIO_AMRBandModeNB0",
3217 "OMX_AUDIO_AMRBandModeNB1",
3218 "OMX_AUDIO_AMRBandModeNB2",
3219 "OMX_AUDIO_AMRBandModeNB3",
3220 "OMX_AUDIO_AMRBandModeNB4",
3221 "OMX_AUDIO_AMRBandModeNB5",
3222 "OMX_AUDIO_AMRBandModeNB6",
3223 "OMX_AUDIO_AMRBandModeNB7",
3224 "OMX_AUDIO_AMRBandModeWB0",
3225 "OMX_AUDIO_AMRBandModeWB1",
3226 "OMX_AUDIO_AMRBandModeWB2",
3227 "OMX_AUDIO_AMRBandModeWB3",
3228 "OMX_AUDIO_AMRBandModeWB4",
3229 "OMX_AUDIO_AMRBandModeWB5",
3230 "OMX_AUDIO_AMRBandModeWB6",
3231 "OMX_AUDIO_AMRBandModeWB7",
3232 "OMX_AUDIO_AMRBandModeWB8",
3233 };
3234
3235 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3236
3237 if (type < 0 || (size_t)type >= numNames) {
3238 return "UNKNOWN";
3239 } else {
3240 return kNames[type];
3241 }
3242}
3243
3244static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
3245 static const char *kNames[] = {
3246 "OMX_AUDIO_AMRFrameFormatConformance",
3247 "OMX_AUDIO_AMRFrameFormatIF1",
3248 "OMX_AUDIO_AMRFrameFormatIF2",
3249 "OMX_AUDIO_AMRFrameFormatFSF",
3250 "OMX_AUDIO_AMRFrameFormatRTPPayload",
3251 "OMX_AUDIO_AMRFrameFormatITU",
3252 };
3253
3254 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3255
3256 if (type < 0 || (size_t)type >= numNames) {
3257 return "UNKNOWN";
3258 } else {
3259 return kNames[type];
3260 }
3261}
Andreas Huberbe06d262009-08-14 14:37:10 -07003262
3263void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
3264 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003265 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003266 def.nPortIndex = portIndex;
3267
Andreas Huber784202e2009-10-15 13:46:54 -07003268 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003269 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3270 CHECK_EQ(err, OK);
3271
3272 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
3273
3274 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
3275 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
3276
3277 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
3278 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
3279 printf(" nBufferSize = %ld\n", def.nBufferSize);
3280
3281 switch (def.eDomain) {
3282 case OMX_PortDomainImage:
3283 {
3284 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3285
3286 printf("\n");
3287 printf(" // Image\n");
3288 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
3289 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
3290 printf(" nStride = %ld\n", imageDef->nStride);
3291
3292 printf(" eCompressionFormat = %s\n",
3293 imageCompressionFormatString(imageDef->eCompressionFormat));
3294
3295 printf(" eColorFormat = %s\n",
3296 colorFormatString(imageDef->eColorFormat));
3297
3298 break;
3299 }
3300
3301 case OMX_PortDomainVideo:
3302 {
3303 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3304
3305 printf("\n");
3306 printf(" // Video\n");
3307 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
3308 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
3309 printf(" nStride = %ld\n", videoDef->nStride);
3310
3311 printf(" eCompressionFormat = %s\n",
3312 videoCompressionFormatString(videoDef->eCompressionFormat));
3313
3314 printf(" eColorFormat = %s\n",
3315 colorFormatString(videoDef->eColorFormat));
3316
3317 break;
3318 }
3319
3320 case OMX_PortDomainAudio:
3321 {
3322 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3323
3324 printf("\n");
3325 printf(" // Audio\n");
3326 printf(" eEncoding = %s\n",
3327 audioCodingTypeString(audioDef->eEncoding));
3328
3329 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
3330 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07003331 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07003332 params.nPortIndex = portIndex;
3333
Andreas Huber784202e2009-10-15 13:46:54 -07003334 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003335 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3336 CHECK_EQ(err, OK);
3337
3338 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
3339 printf(" nChannels = %ld\n", params.nChannels);
3340 printf(" bInterleaved = %d\n", params.bInterleaved);
3341 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
3342
3343 printf(" eNumData = %s\n",
3344 params.eNumData == OMX_NumericalDataSigned
3345 ? "signed" : "unsigned");
3346
3347 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07003348 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
3349 OMX_AUDIO_PARAM_AMRTYPE amr;
3350 InitOMXParams(&amr);
3351 amr.nPortIndex = portIndex;
3352
Andreas Huber784202e2009-10-15 13:46:54 -07003353 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07003354 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
3355 CHECK_EQ(err, OK);
3356
3357 printf(" nChannels = %ld\n", amr.nChannels);
3358 printf(" eAMRBandMode = %s\n",
3359 amrBandModeString(amr.eAMRBandMode));
3360 printf(" eAMRFrameFormat = %s\n",
3361 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07003362 }
3363
3364 break;
3365 }
3366
3367 default:
3368 {
3369 printf(" // Unknown\n");
3370 break;
3371 }
3372 }
3373
3374 printf("}\n");
3375}
3376
3377void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
3378 mOutputFormat = new MetaData;
3379 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
James Dong52d13f02010-07-02 11:39:06 -07003380 if (mIsEncoder) {
3381 int32_t timeScale;
3382 if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
3383 mOutputFormat->setInt32(kKeyTimeScale, timeScale);
3384 }
3385 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003386
3387 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003388 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003389 def.nPortIndex = kPortIndexOutput;
3390
Andreas Huber784202e2009-10-15 13:46:54 -07003391 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003392 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3393 CHECK_EQ(err, OK);
3394
3395 switch (def.eDomain) {
3396 case OMX_PortDomainImage:
3397 {
3398 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3399 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
3400
Andreas Hubere6c40962009-09-10 14:13:30 -07003401 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07003402 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
3403 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
3404 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
3405 break;
3406 }
3407
3408 case OMX_PortDomainAudio:
3409 {
3410 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
3411
Andreas Huberda050cf22009-09-02 14:01:43 -07003412 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
3413 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07003414 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07003415 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003416
Andreas Huber784202e2009-10-15 13:46:54 -07003417 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003418 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3419 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003420
Andreas Huberda050cf22009-09-02 14:01:43 -07003421 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
3422 CHECK_EQ(params.nBitPerSample, 16);
3423 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07003424
Andreas Huberda050cf22009-09-02 14:01:43 -07003425 int32_t numChannels, sampleRate;
3426 inputFormat->findInt32(kKeyChannelCount, &numChannels);
3427 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07003428
Andreas Huberda050cf22009-09-02 14:01:43 -07003429 if ((OMX_U32)numChannels != params.nChannels) {
3430 LOGW("Codec outputs a different number of channels than "
Andreas Hubere331c7b2010-02-01 10:51:50 -08003431 "the input stream contains (contains %d channels, "
3432 "codec outputs %ld channels).",
3433 numChannels, params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07003434 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003435
Andreas Hubere6c40962009-09-10 14:13:30 -07003436 mOutputFormat->setCString(
3437 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07003438
3439 // Use the codec-advertised number of channels, as some
3440 // codecs appear to output stereo even if the input data is
Andreas Hubere331c7b2010-02-01 10:51:50 -08003441 // mono. If we know the codec lies about this information,
3442 // use the actual number of channels instead.
3443 mOutputFormat->setInt32(
3444 kKeyChannelCount,
3445 (mQuirks & kDecoderLiesAboutNumberOfChannels)
3446 ? numChannels : params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07003447
3448 // The codec-reported sampleRate is not reliable...
3449 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
3450 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07003451 OMX_AUDIO_PARAM_AMRTYPE amr;
3452 InitOMXParams(&amr);
3453 amr.nPortIndex = kPortIndexOutput;
3454
Andreas Huber784202e2009-10-15 13:46:54 -07003455 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07003456 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
3457 CHECK_EQ(err, OK);
3458
3459 CHECK_EQ(amr.nChannels, 1);
3460 mOutputFormat->setInt32(kKeyChannelCount, 1);
3461
3462 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
3463 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003464 mOutputFormat->setCString(
3465 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07003466 mOutputFormat->setInt32(kKeySampleRate, 8000);
3467 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
3468 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003469 mOutputFormat->setCString(
3470 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07003471 mOutputFormat->setInt32(kKeySampleRate, 16000);
3472 } else {
3473 CHECK(!"Unknown AMR band mode.");
3474 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003475 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003476 mOutputFormat->setCString(
3477 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
James Dong17299ab2010-05-14 15:45:22 -07003478 int32_t numChannels, sampleRate, bitRate;
James Dongabed93a2010-04-22 17:27:04 -07003479 inputFormat->findInt32(kKeyChannelCount, &numChannels);
3480 inputFormat->findInt32(kKeySampleRate, &sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07003481 inputFormat->findInt32(kKeyBitRate, &bitRate);
James Dongabed93a2010-04-22 17:27:04 -07003482 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
3483 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07003484 mOutputFormat->setInt32(kKeyBitRate, bitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07003485 } else {
3486 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07003487 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003488 break;
3489 }
3490
3491 case OMX_PortDomainVideo:
3492 {
3493 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3494
3495 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003496 mOutputFormat->setCString(
3497 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07003498 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003499 mOutputFormat->setCString(
3500 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07003501 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003502 mOutputFormat->setCString(
3503 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07003504 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003505 mOutputFormat->setCString(
3506 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07003507 } else {
3508 CHECK(!"Unknown compression format.");
3509 }
3510
3511 if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
3512 // This component appears to be lying to me.
3513 mOutputFormat->setInt32(
3514 kKeyWidth, (video_def->nFrameWidth + 15) & -16);
3515 mOutputFormat->setInt32(
3516 kKeyHeight, (video_def->nFrameHeight + 15) & -16);
3517 } else {
3518 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
3519 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
3520 }
3521
3522 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
3523 break;
3524 }
3525
3526 default:
3527 {
3528 CHECK(!"should not be here, neither audio nor video.");
3529 break;
3530 }
3531 }
3532}
3533
Andreas Huber1f24b302010-06-10 11:12:39 -07003534status_t OMXCodec::pause() {
3535 Mutex::Autolock autoLock(mLock);
3536
3537 mPaused = true;
3538
3539 return OK;
3540}
3541
Andreas Hubere6c40962009-09-10 14:13:30 -07003542////////////////////////////////////////////////////////////////////////////////
3543
3544status_t QueryCodecs(
3545 const sp<IOMX> &omx,
3546 const char *mime, bool queryDecoders,
3547 Vector<CodecCapabilities> *results) {
3548 results->clear();
3549
3550 for (int index = 0;; ++index) {
3551 const char *componentName;
3552
3553 if (!queryDecoders) {
3554 componentName = GetCodec(
3555 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
3556 mime, index);
3557 } else {
3558 componentName = GetCodec(
3559 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
3560 mime, index);
3561 }
3562
3563 if (!componentName) {
3564 return OK;
3565 }
3566
Andreas Huber1a189a82010-03-24 13:49:20 -07003567 if (strncmp(componentName, "OMX.", 4)) {
3568 // Not an OpenMax component but a software codec.
3569
3570 results->push();
3571 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3572 caps->mComponentName = componentName;
3573
3574 continue;
3575 }
3576
Andreas Huber784202e2009-10-15 13:46:54 -07003577 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07003578 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07003579 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07003580
3581 if (err != OK) {
3582 continue;
3583 }
3584
James Dong722d5912010-04-13 10:56:59 -07003585 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
Andreas Hubere6c40962009-09-10 14:13:30 -07003586
3587 results->push();
3588 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3589 caps->mComponentName = componentName;
3590
3591 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
3592 InitOMXParams(&param);
3593
3594 param.nPortIndex = queryDecoders ? 0 : 1;
3595
3596 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07003597 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07003598 node, OMX_IndexParamVideoProfileLevelQuerySupported,
3599 &param, sizeof(param));
3600
3601 if (err != OK) {
3602 break;
3603 }
3604
3605 CodecProfileLevel profileLevel;
3606 profileLevel.mProfile = param.eProfile;
3607 profileLevel.mLevel = param.eLevel;
3608
3609 caps->mProfileLevels.push(profileLevel);
3610 }
3611
Andreas Huber784202e2009-10-15 13:46:54 -07003612 CHECK_EQ(omx->freeNode(node), OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07003613 }
3614}
3615
Andreas Huberbe06d262009-08-14 14:37:10 -07003616} // namespace android