blob: c01ea10510895a6f4857f2efdde6e90991c0d779 [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 Dong02f5b542009-12-15 16:26:55 -080028#include "include/M4vH263Decoder.h"
Andreas Huber250f2432009-12-07 14:22:35 -080029#include "include/MP3Decoder.h"
Andreas Huber388379f2010-05-07 10:35:13 -070030#include "include/VorbisDecoder.h"
Andreas Huber47ba30e2010-05-24 14:38:02 -070031#include "include/VPXDecoder.h"
Andreas Huber8c7ab032009-12-07 11:23:44 -080032
Andreas Huberbd7b43b2009-10-13 10:22:55 -070033#include "include/ESDS.h"
34
Andreas Huberbe06d262009-08-14 14:37:10 -070035#include <binder/IServiceManager.h>
36#include <binder/MemoryDealer.h>
37#include <binder/ProcessState.h>
38#include <media/IMediaPlayerService.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070039#include <media/stagefright/MediaBuffer.h>
40#include <media/stagefright/MediaBufferGroup.h>
41#include <media/stagefright/MediaDebug.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070042#include <media/stagefright/MediaDefs.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070043#include <media/stagefright/MediaExtractor.h>
44#include <media/stagefright/MetaData.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070045#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070046#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070047#include <utils/Vector.h>
48
49#include <OMX_Audio.h>
50#include <OMX_Component.h>
51
52namespace android {
53
Andreas Huber8b432b12009-10-07 13:36:52 -070054static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
55
Andreas Huberbe06d262009-08-14 14:37:10 -070056struct CodecInfo {
57 const char *mime;
58 const char *codec;
59};
60
Andreas Huberfb1c2f82009-12-15 13:25:11 -080061#define FACTORY_CREATE(name) \
62static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
63 return new name(source); \
64}
65
James Dong17299ab2010-05-14 15:45:22 -070066#define FACTORY_CREATE_ENCODER(name) \
67static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
68 return new name(source, meta); \
69}
70
Andreas Huberfb1c2f82009-12-15 13:25:11 -080071#define FACTORY_REF(name) { #name, Make##name },
72
73FACTORY_CREATE(MP3Decoder)
74FACTORY_CREATE(AMRNBDecoder)
75FACTORY_CREATE(AMRWBDecoder)
76FACTORY_CREATE(AACDecoder)
77FACTORY_CREATE(AVCDecoder)
James Dong02f5b542009-12-15 16:26:55 -080078FACTORY_CREATE(M4vH263Decoder)
Andreas Huber388379f2010-05-07 10:35:13 -070079FACTORY_CREATE(VorbisDecoder)
Andreas Huber47ba30e2010-05-24 14:38:02 -070080FACTORY_CREATE(VPXDecoder)
James Dong17299ab2010-05-14 15:45:22 -070081FACTORY_CREATE_ENCODER(AMRNBEncoder)
82FACTORY_CREATE_ENCODER(AMRWBEncoder)
83FACTORY_CREATE_ENCODER(AACEncoder)
84
85static sp<MediaSource> InstantiateSoftwareEncoder(
86 const char *name, const sp<MediaSource> &source,
87 const sp<MetaData> &meta) {
88 struct FactoryInfo {
89 const char *name;
90 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
91 };
92
93 static const FactoryInfo kFactoryInfo[] = {
94 FACTORY_REF(AMRNBEncoder)
95 FACTORY_REF(AMRWBEncoder)
96 FACTORY_REF(AACEncoder)
97 };
98 for (size_t i = 0;
99 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
100 if (!strcmp(name, kFactoryInfo[i].name)) {
101 return (*kFactoryInfo[i].CreateFunc)(source, meta);
102 }
103 }
104
105 return NULL;
106}
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800107
108static sp<MediaSource> InstantiateSoftwareCodec(
109 const char *name, const sp<MediaSource> &source) {
110 struct FactoryInfo {
111 const char *name;
112 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
113 };
114
115 static const FactoryInfo kFactoryInfo[] = {
116 FACTORY_REF(MP3Decoder)
117 FACTORY_REF(AMRNBDecoder)
118 FACTORY_REF(AMRWBDecoder)
119 FACTORY_REF(AACDecoder)
120 FACTORY_REF(AVCDecoder)
James Dong02f5b542009-12-15 16:26:55 -0800121 FACTORY_REF(M4vH263Decoder)
Andreas Huber388379f2010-05-07 10:35:13 -0700122 FACTORY_REF(VorbisDecoder)
Andreas Huber47ba30e2010-05-24 14:38:02 -0700123 FACTORY_REF(VPXDecoder)
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800124 };
125 for (size_t i = 0;
126 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
127 if (!strcmp(name, kFactoryInfo[i].name)) {
128 return (*kFactoryInfo[i].CreateFunc)(source);
129 }
130 }
131
132 return NULL;
133}
134
135#undef FACTORY_REF
136#undef FACTORY_CREATE
137
Andreas Huberbe06d262009-08-14 14:37:10 -0700138static const CodecInfo kDecoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700139 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
James Dong374aee62010-04-26 10:23:30 -0700140// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800141 { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700142// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
Andreas Hubera4357ad2010-04-02 12:49:54 -0700143// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800144 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700145// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700146 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800147 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700148// { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700149 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800150 { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700151// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700152 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700153 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
154 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800155 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700156// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700157 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700158 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800159 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700160// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700161 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700162 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
163 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800164 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
Andreas Huber1a189a82010-03-24 13:49:20 -0700165// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
Andreas Huber388379f2010-05-07 10:35:13 -0700166 { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
Andreas Huber47ba30e2010-05-24 14:38:02 -0700167 { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700168};
169
170static const CodecInfo kEncoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700171 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800172 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700173 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700174 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700175 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700176 { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700177// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
178 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700179 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
180 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700181// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
182 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700183 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
184 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700185// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
186 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
Andreas Huber71c27d92010-03-19 11:43:15 -0700187 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700188 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700189// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700190};
191
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800192#undef OPTIONAL
193
Andreas Hubere0873732009-09-10 09:57:53 -0700194#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700195#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber42c444a2010-02-09 10:20:00 -0800196#define CODEC_LOGE(x, ...) LOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700197
Andreas Huberbe06d262009-08-14 14:37:10 -0700198struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -0700199 OMXCodecObserver() {
200 }
201
202 void setCodec(const sp<OMXCodec> &target) {
203 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -0700204 }
205
206 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -0700207 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700208 sp<OMXCodec> codec = mTarget.promote();
209
210 if (codec.get() != NULL) {
211 codec->on_message(msg);
212 }
213 }
214
215protected:
216 virtual ~OMXCodecObserver() {}
217
218private:
219 wp<OMXCodec> mTarget;
220
221 OMXCodecObserver(const OMXCodecObserver &);
222 OMXCodecObserver &operator=(const OMXCodecObserver &);
223};
224
225static const char *GetCodec(const CodecInfo *info, size_t numInfos,
226 const char *mime, int index) {
227 CHECK(index >= 0);
228 for(size_t i = 0; i < numInfos; ++i) {
229 if (!strcasecmp(mime, info[i].mime)) {
230 if (index == 0) {
231 return info[i].codec;
232 }
233
234 --index;
235 }
236 }
237
238 return NULL;
239}
240
Andreas Huberebf66ea2009-08-19 13:32:58 -0700241enum {
242 kAVCProfileBaseline = 0x42,
243 kAVCProfileMain = 0x4d,
244 kAVCProfileExtended = 0x58,
245 kAVCProfileHigh = 0x64,
246 kAVCProfileHigh10 = 0x6e,
247 kAVCProfileHigh422 = 0x7a,
248 kAVCProfileHigh444 = 0xf4,
249 kAVCProfileCAVLC444Intra = 0x2c
250};
251
252static const char *AVCProfileToString(uint8_t profile) {
253 switch (profile) {
254 case kAVCProfileBaseline:
255 return "Baseline";
256 case kAVCProfileMain:
257 return "Main";
258 case kAVCProfileExtended:
259 return "Extended";
260 case kAVCProfileHigh:
261 return "High";
262 case kAVCProfileHigh10:
263 return "High 10";
264 case kAVCProfileHigh422:
265 return "High 422";
266 case kAVCProfileHigh444:
267 return "High 444";
268 case kAVCProfileCAVLC444Intra:
269 return "CAVLC 444 Intra";
270 default: return "Unknown";
271 }
272}
273
Andreas Huber4c483422009-09-02 16:05:36 -0700274template<class T>
275static void InitOMXParams(T *params) {
276 params->nSize = sizeof(T);
277 params->nVersion.s.nVersionMajor = 1;
278 params->nVersion.s.nVersionMinor = 0;
279 params->nVersion.s.nRevision = 0;
280 params->nVersion.s.nStep = 0;
281}
282
Andreas Hubere13526a2009-10-22 10:43:34 -0700283static bool IsSoftwareCodec(const char *componentName) {
284 if (!strncmp("OMX.PV.", componentName, 7)) {
285 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -0700286 }
287
Andreas Hubere13526a2009-10-22 10:43:34 -0700288 return false;
289}
290
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800291// A sort order in which non-OMX components are first,
292// followed by software codecs, i.e. OMX.PV.*, followed
293// by all the others.
Andreas Hubere13526a2009-10-22 10:43:34 -0700294static int CompareSoftwareCodecsFirst(
295 const String8 *elem1, const String8 *elem2) {
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800296 bool isNotOMX1 = strncmp(elem1->string(), "OMX.", 4);
297 bool isNotOMX2 = strncmp(elem2->string(), "OMX.", 4);
298
299 if (isNotOMX1) {
300 if (isNotOMX2) { return 0; }
301 return -1;
302 }
303 if (isNotOMX2) {
304 return 1;
305 }
306
Andreas Hubere13526a2009-10-22 10:43:34 -0700307 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
308 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
309
310 if (isSoftwareCodec1) {
311 if (isSoftwareCodec2) { return 0; }
312 return -1;
313 }
314
315 if (isSoftwareCodec2) {
316 return 1;
317 }
318
319 return 0;
320}
321
322// static
323uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700324 uint32_t quirks = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700325
Andreas Huberbe06d262009-08-14 14:37:10 -0700326 if (!strcmp(componentName, "OMX.PV.avcdec")) {
Andreas Huber4f5e6022009-08-19 09:29:34 -0700327 quirks |= kWantsNALFragments;
Andreas Huberbe06d262009-08-14 14:37:10 -0700328 }
329 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
330 quirks |= kNeedsFlushBeforeDisable;
Andreas Hubere331c7b2010-02-01 10:51:50 -0800331 quirks |= kDecoderLiesAboutNumberOfChannels;
Andreas Huberbe06d262009-08-14 14:37:10 -0700332 }
333 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
334 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700335 quirks |= kRequiresFlushCompleteEmulation;
Andreas Hubera4357ad2010-04-02 12:49:54 -0700336 quirks |= kSupportsMultipleFramesPerInputBuffer;
Andreas Huberbe06d262009-08-14 14:37:10 -0700337 }
338 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
339 quirks |= kRequiresLoadedToIdleAfterAllocation;
340 quirks |= kRequiresAllocateBufferOnInputPorts;
Andreas Huberb482ce82009-10-29 12:02:48 -0700341 quirks |= kRequiresAllocateBufferOnOutputPorts;
Andreas Huberbe06d262009-08-14 14:37:10 -0700342 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700343 if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
344 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700345 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700346 quirks |= kRequiresAllocateBufferOnOutputPorts;
Andreas Huber52733b82010-01-25 10:41:35 -0800347 quirks |= kDefersOutputBufferAllocation;
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700348 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700349 if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
350 quirks |= kRequiresAllocateBufferOnInputPorts;
351 quirks |= kRequiresAllocateBufferOnOutputPorts;
352 quirks |= kDefersOutputBufferAllocation;
353 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700354
Andreas Huber2dc64d82009-09-11 12:58:53 -0700355 if (!strncmp(componentName, "OMX.TI.", 7)) {
356 // Apparently I must not use OMX_UseBuffer on either input or
357 // output ports on any of the TI components or quote:
358 // "(I) may have unexpected problem (sic) which can be timing related
359 // and hard to reproduce."
360
361 quirks |= kRequiresAllocateBufferOnInputPorts;
362 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dongdca66e12010-06-14 11:14:38 -0700363 if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
James Dong4f501f02010-06-07 14:41:41 -0700364 quirks |= kAvoidMemcopyInputRecordingFrames;
365 }
Andreas Huber2dc64d82009-09-11 12:58:53 -0700366 }
367
Andreas Huberb8de9572010-02-22 14:58:45 -0800368 if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
369 quirks |= kInputBufferSizesAreBogus;
370 }
371
Andreas Hubere13526a2009-10-22 10:43:34 -0700372 return quirks;
373}
374
375// static
376void OMXCodec::findMatchingCodecs(
377 const char *mime,
378 bool createEncoder, const char *matchComponentName,
379 uint32_t flags,
380 Vector<String8> *matchingCodecs) {
381 matchingCodecs->clear();
382
383 for (int index = 0;; ++index) {
384 const char *componentName;
385
386 if (createEncoder) {
387 componentName = GetCodec(
388 kEncoderInfo,
389 sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
390 mime, index);
391 } else {
392 componentName = GetCodec(
393 kDecoderInfo,
394 sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
395 mime, index);
396 }
397
398 if (!componentName) {
399 break;
400 }
401
402 // If a specific codec is requested, skip the non-matching ones.
403 if (matchComponentName && strcmp(componentName, matchComponentName)) {
404 continue;
405 }
406
407 matchingCodecs->push(String8(componentName));
408 }
409
410 if (flags & kPreferSoftwareCodecs) {
411 matchingCodecs->sort(CompareSoftwareCodecsFirst);
412 }
413}
414
415// static
Andreas Huber91eb0352009-12-07 09:43:00 -0800416sp<MediaSource> OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700417 const sp<IOMX> &omx,
418 const sp<MetaData> &meta, bool createEncoder,
419 const sp<MediaSource> &source,
420 const char *matchComponentName,
421 uint32_t flags) {
422 const char *mime;
423 bool success = meta->findCString(kKeyMIMEType, &mime);
424 CHECK(success);
425
426 Vector<String8> matchingCodecs;
427 findMatchingCodecs(
428 mime, createEncoder, matchComponentName, flags, &matchingCodecs);
429
430 if (matchingCodecs.isEmpty()) {
431 return NULL;
432 }
433
434 sp<OMXCodecObserver> observer = new OMXCodecObserver;
435 IOMX::node_id node = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700436
437 const char *componentName;
438 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
439 componentName = matchingCodecs[i].string();
440
James Dong17299ab2010-05-14 15:45:22 -0700441 sp<MediaSource> softwareCodec = createEncoder?
442 InstantiateSoftwareEncoder(componentName, source, meta):
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800443 InstantiateSoftwareCodec(componentName, source);
444
445 if (softwareCodec != NULL) {
446 LOGV("Successfully allocated software codec '%s'", componentName);
447
448 return softwareCodec;
449 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800450
Andreas Hubere13526a2009-10-22 10:43:34 -0700451 LOGV("Attempting to allocate OMX node '%s'", componentName);
452
453 status_t err = omx->allocateNode(componentName, observer, &node);
454 if (err == OK) {
455 LOGV("Successfully allocated OMX node '%s'", componentName);
456
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700457 sp<OMXCodec> codec = new OMXCodec(
458 omx, node, getComponentQuirks(componentName),
459 createEncoder, mime, componentName,
460 source);
461
462 observer->setCodec(codec);
463
464 err = codec->configureCodec(meta);
465
466 if (err == OK) {
467 return codec;
468 }
469
470 LOGV("Failed to configure codec '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700471 }
472 }
473
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700474 return NULL;
475}
Andreas Hubere13526a2009-10-22 10:43:34 -0700476
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700477status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700478 uint32_t type;
479 const void *data;
480 size_t size;
481 if (meta->findData(kKeyESDS, &type, &data, &size)) {
482 ESDS esds((const char *)data, size);
483 CHECK_EQ(esds.InitCheck(), OK);
484
485 const void *codec_specific_data;
486 size_t codec_specific_data_size;
487 esds.getCodecSpecificInfo(
488 &codec_specific_data, &codec_specific_data_size);
489
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700490 addCodecSpecificData(
Andreas Huberbe06d262009-08-14 14:37:10 -0700491 codec_specific_data, codec_specific_data_size);
492 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
Andreas Huberebf66ea2009-08-19 13:32:58 -0700493 // Parse the AVCDecoderConfigurationRecord
494
495 const uint8_t *ptr = (const uint8_t *)data;
496
497 CHECK(size >= 7);
498 CHECK_EQ(ptr[0], 1); // configurationVersion == 1
499 uint8_t profile = ptr[1];
500 uint8_t level = ptr[3];
501
Andreas Huber44e15c42009-11-23 14:39:38 -0800502 // There is decodable content out there that fails the following
503 // assertion, let's be lenient for now...
504 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
Andreas Huberebf66ea2009-08-19 13:32:58 -0700505
506 size_t lengthSize = 1 + (ptr[4] & 3);
507
508 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
509 // violates it...
510 // CHECK((ptr[5] >> 5) == 7); // reserved
511
512 size_t numSeqParameterSets = ptr[5] & 31;
513
514 ptr += 6;
Andreas Huberbe06d262009-08-14 14:37:10 -0700515 size -= 6;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700516
517 for (size_t i = 0; i < numSeqParameterSets; ++i) {
518 CHECK(size >= 2);
519 size_t length = U16_AT(ptr);
Andreas Huberbe06d262009-08-14 14:37:10 -0700520
521 ptr += 2;
522 size -= 2;
523
Andreas Huberbe06d262009-08-14 14:37:10 -0700524 CHECK(size >= length);
525
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700526 addCodecSpecificData(ptr, length);
Andreas Huberbe06d262009-08-14 14:37:10 -0700527
528 ptr += length;
529 size -= length;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700530 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700531
Andreas Huberebf66ea2009-08-19 13:32:58 -0700532 CHECK(size >= 1);
533 size_t numPictureParameterSets = *ptr;
534 ++ptr;
535 --size;
Andreas Huberbe06d262009-08-14 14:37:10 -0700536
Andreas Huberebf66ea2009-08-19 13:32:58 -0700537 for (size_t i = 0; i < numPictureParameterSets; ++i) {
538 CHECK(size >= 2);
539 size_t length = U16_AT(ptr);
540
541 ptr += 2;
542 size -= 2;
543
544 CHECK(size >= length);
545
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700546 addCodecSpecificData(ptr, length);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700547
548 ptr += length;
549 size -= length;
550 }
551
Andreas Hubere2f85072010-06-10 09:51:27 -0700552 CODEC_LOGV(
553 "AVC profile = %d (%s), level = %d",
554 (int)profile, AVCProfileToString(profile), level);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700555
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700556 if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
Andreas Hubere2f85072010-06-10 09:51:27 -0700557 && (profile != kAVCProfileBaseline || level > 30)) {
Andreas Huber784202e2009-10-15 13:46:54 -0700558 // This stream exceeds the decoder's capabilities. The decoder
559 // does not handle this gracefully and would clobber the heap
560 // and wreak havoc instead...
Andreas Huberebf66ea2009-08-19 13:32:58 -0700561
562 LOGE("Profile and/or level exceed the decoder's capabilities.");
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700563 return ERROR_UNSUPPORTED;
Andreas Huberbe06d262009-08-14 14:37:10 -0700564 }
565 }
566
James Dong17299ab2010-05-14 15:45:22 -0700567 int32_t bitRate = 0;
568 if (mIsEncoder) {
569 CHECK(meta->findInt32(kKeyBitRate, &bitRate));
570 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700571 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700572 setAMRFormat(false /* isWAMR */, bitRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700573 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700574 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700575 setAMRFormat(true /* isWAMR */, bitRate);
Andreas Huberee606e62009-09-08 10:19:21 -0700576 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700577 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700578 int32_t numChannels, sampleRate;
579 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
580 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
581
James Dong17299ab2010-05-14 15:45:22 -0700582 setAACFormat(numChannels, sampleRate, bitRate);
Andreas Huberbe06d262009-08-14 14:37:10 -0700583 }
James Dongabed93a2010-04-22 17:27:04 -0700584
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700585 if (!strncasecmp(mMIME, "video/", 6)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700586
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700587 if (mIsEncoder) {
James Dong1244eab2010-06-08 11:58:53 -0700588 setVideoInputFormat(mMIME, meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700589 } else {
James Dong1244eab2010-06-08 11:58:53 -0700590 int32_t width, height;
591 bool success = meta->findInt32(kKeyWidth, &width);
592 success = success && meta->findInt32(kKeyHeight, &height);
593 CHECK(success);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700594 status_t err = setVideoOutputFormat(
595 mMIME, width, height);
596
597 if (err != OK) {
598 return err;
599 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700600 }
601 }
Andreas Hubera4357ad2010-04-02 12:49:54 -0700602
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700603 if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
604 && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700605 OMX_COLOR_FORMATTYPE format =
606 OMX_COLOR_Format32bitARGB8888;
607 // OMX_COLOR_FormatYUV420PackedPlanar;
608 // OMX_COLOR_FormatCbYCrY;
609 // OMX_COLOR_FormatYUV411Planar;
610
611 int32_t width, height;
612 bool success = meta->findInt32(kKeyWidth, &width);
613 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700614
615 int32_t compressedSize;
616 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700617 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700618
619 CHECK(success);
620 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700621
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700622 setImageOutputFormat(format, width, height);
623 setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700624 }
625
Andreas Huberda050cf22009-09-02 14:01:43 -0700626 int32_t maxInputSize;
Andreas Huber1bceff92009-11-23 14:03:32 -0800627 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700628 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
Andreas Huberda050cf22009-09-02 14:01:43 -0700629 }
630
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700631 if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
James Dongabed93a2010-04-22 17:27:04 -0700632 || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
633 || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700634 setMinBufferSize(kPortIndexOutput, 8192); // XXX
Andreas Huberda050cf22009-09-02 14:01:43 -0700635 }
636
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700637 initOutputFormat(meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700638
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700639 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700640}
641
Andreas Huberda050cf22009-09-02 14:01:43 -0700642void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
643 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700644 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700645 def.nPortIndex = portIndex;
646
Andreas Huber784202e2009-10-15 13:46:54 -0700647 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700648 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
649 CHECK_EQ(err, OK);
650
Andreas Huberb8de9572010-02-22 14:58:45 -0800651 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
652 || (def.nBufferSize < size)) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700653 def.nBufferSize = size;
Andreas Huberda050cf22009-09-02 14:01:43 -0700654 }
655
Andreas Huber784202e2009-10-15 13:46:54 -0700656 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700657 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
658 CHECK_EQ(err, OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800659
660 err = mOMX->getParameter(
661 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
662 CHECK_EQ(err, OK);
663
664 // Make sure the setting actually stuck.
Andreas Huberb8de9572010-02-22 14:58:45 -0800665 if (portIndex == kPortIndexInput
666 && (mQuirks & kInputBufferSizesAreBogus)) {
667 CHECK_EQ(def.nBufferSize, size);
668 } else {
669 CHECK(def.nBufferSize >= size);
670 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700671}
672
Andreas Huberbe06d262009-08-14 14:37:10 -0700673status_t OMXCodec::setVideoPortFormatType(
674 OMX_U32 portIndex,
675 OMX_VIDEO_CODINGTYPE compressionFormat,
676 OMX_COLOR_FORMATTYPE colorFormat) {
677 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700678 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700679 format.nPortIndex = portIndex;
680 format.nIndex = 0;
681 bool found = false;
682
683 OMX_U32 index = 0;
684 for (;;) {
685 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700686 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700687 mNode, OMX_IndexParamVideoPortFormat,
688 &format, sizeof(format));
689
690 if (err != OK) {
691 return err;
692 }
693
694 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700695 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700696
697#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700698 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700699 portIndex,
700 index, format.eCompressionFormat, format.eColorFormat);
701#endif
702
703 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
704 if (portIndex == kPortIndexInput
705 && colorFormat == format.eColorFormat) {
706 // eCompressionFormat does not seem right.
707 found = true;
708 break;
709 }
710 if (portIndex == kPortIndexOutput
711 && compressionFormat == format.eCompressionFormat) {
712 // eColorFormat does not seem right.
713 found = true;
714 break;
715 }
716 }
717
718 if (format.eCompressionFormat == compressionFormat
719 && format.eColorFormat == colorFormat) {
720 found = true;
721 break;
722 }
723
724 ++index;
725 }
726
727 if (!found) {
728 return UNKNOWN_ERROR;
729 }
730
Andreas Huber53a76bd2009-10-06 16:20:44 -0700731 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700732 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700733 mNode, OMX_IndexParamVideoPortFormat,
734 &format, sizeof(format));
735
736 return err;
737}
738
Andreas Huberb482ce82009-10-29 12:02:48 -0700739static size_t getFrameSize(
740 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
741 switch (colorFormat) {
742 case OMX_COLOR_FormatYCbYCr:
743 case OMX_COLOR_FormatCbYCrY:
744 return width * height * 2;
745
Andreas Huber71c27d92010-03-19 11:43:15 -0700746 case OMX_COLOR_FormatYUV420Planar:
Andreas Huberb482ce82009-10-29 12:02:48 -0700747 case OMX_COLOR_FormatYUV420SemiPlanar:
748 return (width * height * 3) / 2;
749
750 default:
751 CHECK(!"Should not be here. Unsupported color format.");
752 break;
753 }
754}
755
Andreas Huberbe06d262009-08-14 14:37:10 -0700756void OMXCodec::setVideoInputFormat(
James Dong1244eab2010-06-08 11:58:53 -0700757 const char *mime, const sp<MetaData>& meta) {
758
759 int32_t width, height, frameRate, bitRate, stride, sliceHeight;
760 bool success = meta->findInt32(kKeyWidth, &width);
761 success = success && meta->findInt32(kKeyHeight, &height);
762 success = success && meta->findInt32(kKeySampleRate, &frameRate);
763 success = success && meta->findInt32(kKeyBitRate, &bitRate);
764 success = success && meta->findInt32(kKeyStride, &stride);
765 success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
766 CHECK(success);
767 CHECK(stride != 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700768
769 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700770 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700771 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700772 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700773 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700774 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700775 compressionFormat = OMX_VIDEO_CodingH263;
776 } else {
777 LOGE("Not a supported video mime type: %s", mime);
778 CHECK(!"Should not be here. Not a supported video mime type.");
779 }
780
Andreas Huberea6a38c2009-11-16 15:43:38 -0800781 OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
782 if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
James Dongabed93a2010-04-22 17:27:04 -0700783 colorFormat = OMX_COLOR_FormatYCbYCr;
Andreas Huberbe06d262009-08-14 14:37:10 -0700784 }
785
James Dongb00e2462010-04-26 17:48:26 -0700786 status_t err;
787 OMX_PARAM_PORTDEFINITIONTYPE def;
788 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
789
790 //////////////////////// Input port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700791 CHECK_EQ(setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -0700792 kPortIndexInput, OMX_VIDEO_CodingUnused,
Andreas Huberb482ce82009-10-29 12:02:48 -0700793 colorFormat), OK);
James Dong4f501f02010-06-07 14:41:41 -0700794
James Dongb00e2462010-04-26 17:48:26 -0700795 InitOMXParams(&def);
796 def.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -0700797
James Dongb00e2462010-04-26 17:48:26 -0700798 err = mOMX->getParameter(
799 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
800 CHECK_EQ(err, OK);
801
James Dong1244eab2010-06-08 11:58:53 -0700802 def.nBufferSize = getFrameSize(colorFormat,
803 stride > 0? stride: -stride, sliceHeight);
James Dongb00e2462010-04-26 17:48:26 -0700804
805 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
806
807 video_def->nFrameWidth = width;
808 video_def->nFrameHeight = height;
James Dong1244eab2010-06-08 11:58:53 -0700809 video_def->nStride = stride;
810 video_def->nSliceHeight = sliceHeight;
James Dong4f501f02010-06-07 14:41:41 -0700811 video_def->xFramerate = (frameRate << 16); // Q16 format
James Dongb00e2462010-04-26 17:48:26 -0700812 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
813 video_def->eColorFormat = colorFormat;
814
James Dongb00e2462010-04-26 17:48:26 -0700815 err = mOMX->setParameter(
816 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
817 CHECK_EQ(err, OK);
818
819 //////////////////////// Output port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700820 CHECK_EQ(setVideoPortFormatType(
821 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
822 OK);
Andreas Huber4c483422009-09-02 16:05:36 -0700823 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -0700824 def.nPortIndex = kPortIndexOutput;
825
James Dongb00e2462010-04-26 17:48:26 -0700826 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700827 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
828
829 CHECK_EQ(err, OK);
830 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
831
832 video_def->nFrameWidth = width;
833 video_def->nFrameHeight = height;
James Dong4f501f02010-06-07 14:41:41 -0700834 video_def->xFramerate = (frameRate << 16); // Q16 format
835 video_def->nBitrate = bitRate; // Q16 format
Andreas Huberbe06d262009-08-14 14:37:10 -0700836 video_def->eCompressionFormat = compressionFormat;
837 video_def->eColorFormat = OMX_COLOR_FormatUnused;
838
Andreas Huber784202e2009-10-15 13:46:54 -0700839 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700840 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
841 CHECK_EQ(err, OK);
842
James Dongb00e2462010-04-26 17:48:26 -0700843 /////////////////// Codec-specific ////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700844 switch (compressionFormat) {
845 case OMX_VIDEO_CodingMPEG4:
846 {
James Dong1244eab2010-06-08 11:58:53 -0700847 CHECK_EQ(setupMPEG4EncoderParameters(meta), OK);
Andreas Huberb482ce82009-10-29 12:02:48 -0700848 break;
849 }
850
851 case OMX_VIDEO_CodingH263:
852 break;
853
Andreas Huberea6a38c2009-11-16 15:43:38 -0800854 case OMX_VIDEO_CodingAVC:
855 {
James Dong1244eab2010-06-08 11:58:53 -0700856 CHECK_EQ(setupAVCEncoderParameters(meta), OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -0800857 break;
858 }
859
Andreas Huberb482ce82009-10-29 12:02:48 -0700860 default:
861 CHECK(!"Support for this compressionFormat to be implemented.");
862 break;
863 }
864}
865
James Dong1244eab2010-06-08 11:58:53 -0700866static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
867 if (iFramesInterval < 0) {
868 return 0xFFFFFFFF;
869 } else if (iFramesInterval == 0) {
870 return 0;
871 }
872 OMX_U32 ret = frameRate * iFramesInterval;
873 CHECK(ret > 1);
874 return ret;
875}
876
877status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
878 int32_t iFramesInterval, frameRate, bitRate;
879 bool success = meta->findInt32(kKeyBitRate, &bitRate);
880 success = success && meta->findInt32(kKeySampleRate, &frameRate);
881 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
882 CHECK(success);
Andreas Huberb482ce82009-10-29 12:02:48 -0700883 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
884 InitOMXParams(&mpeg4type);
885 mpeg4type.nPortIndex = kPortIndexOutput;
886
887 status_t err = mOMX->getParameter(
888 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
889 CHECK_EQ(err, OK);
890
891 mpeg4type.nSliceHeaderSpacing = 0;
892 mpeg4type.bSVH = OMX_FALSE;
893 mpeg4type.bGov = OMX_FALSE;
894
895 mpeg4type.nAllowedPictureTypes =
896 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
897
James Dong1244eab2010-06-08 11:58:53 -0700898 mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
899 if (mpeg4type.nPFrames == 0) {
900 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
901 }
Andreas Huberb482ce82009-10-29 12:02:48 -0700902 mpeg4type.nBFrames = 0;
Andreas Huberb482ce82009-10-29 12:02:48 -0700903 mpeg4type.nIDCVLCThreshold = 0;
904 mpeg4type.bACPred = OMX_TRUE;
905 mpeg4type.nMaxPacketSize = 256;
906 mpeg4type.nTimeIncRes = 1000;
907 mpeg4type.nHeaderExtension = 0;
908 mpeg4type.bReversibleVLC = OMX_FALSE;
909
910 mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
911 mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;
912
913 err = mOMX->setParameter(
914 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
915 CHECK_EQ(err, OK);
916
917 // ----------------
918
919 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
920 InitOMXParams(&bitrateType);
921 bitrateType.nPortIndex = kPortIndexOutput;
922
923 err = mOMX->getParameter(
924 mNode, OMX_IndexParamVideoBitrate,
925 &bitrateType, sizeof(bitrateType));
926 CHECK_EQ(err, OK);
927
928 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
James Dong1244eab2010-06-08 11:58:53 -0700929 bitrateType.nTargetBitrate = bitRate;
Andreas Huberb482ce82009-10-29 12:02:48 -0700930
931 err = mOMX->setParameter(
932 mNode, OMX_IndexParamVideoBitrate,
933 &bitrateType, sizeof(bitrateType));
934 CHECK_EQ(err, OK);
935
936 // ----------------
937
938 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
939 InitOMXParams(&errorCorrectionType);
940 errorCorrectionType.nPortIndex = kPortIndexOutput;
941
942 err = mOMX->getParameter(
943 mNode, OMX_IndexParamVideoErrorCorrection,
944 &errorCorrectionType, sizeof(errorCorrectionType));
945 CHECK_EQ(err, OK);
946
947 errorCorrectionType.bEnableHEC = OMX_FALSE;
948 errorCorrectionType.bEnableResync = OMX_TRUE;
949 errorCorrectionType.nResynchMarkerSpacing = 256;
950 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
951 errorCorrectionType.bEnableRVLC = OMX_FALSE;
952
953 err = mOMX->setParameter(
954 mNode, OMX_IndexParamVideoErrorCorrection,
955 &errorCorrectionType, sizeof(errorCorrectionType));
956 CHECK_EQ(err, OK);
957
958 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700959}
960
James Dong1244eab2010-06-08 11:58:53 -0700961status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
962 int32_t iFramesInterval, frameRate, bitRate;
963 bool success = meta->findInt32(kKeyBitRate, &bitRate);
964 success = success && meta->findInt32(kKeySampleRate, &frameRate);
965 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
966 CHECK(success);
967
Andreas Huberea6a38c2009-11-16 15:43:38 -0800968 OMX_VIDEO_PARAM_AVCTYPE h264type;
969 InitOMXParams(&h264type);
970 h264type.nPortIndex = kPortIndexOutput;
971
972 status_t err = mOMX->getParameter(
973 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
974 CHECK_EQ(err, OK);
975
976 h264type.nAllowedPictureTypes =
977 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
978
979 h264type.nSliceHeaderSpacing = 0;
James Dong1244eab2010-06-08 11:58:53 -0700980 h264type.nBFrames = 0; // No B frames support yet
981 h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
982 if (h264type.nPFrames == 0) {
983 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
984 }
Andreas Huberea6a38c2009-11-16 15:43:38 -0800985 h264type.bUseHadamard = OMX_TRUE;
986 h264type.nRefFrames = 1;
987 h264type.nRefIdx10ActiveMinus1 = 0;
988 h264type.nRefIdx11ActiveMinus1 = 0;
989 h264type.bEnableUEP = OMX_FALSE;
990 h264type.bEnableFMO = OMX_FALSE;
991 h264type.bEnableASO = OMX_FALSE;
992 h264type.bEnableRS = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -0800993 h264type.bFrameMBsOnly = OMX_TRUE;
994 h264type.bMBAFF = OMX_FALSE;
995 h264type.bEntropyCodingCABAC = OMX_FALSE;
996 h264type.bWeightedPPrediction = OMX_FALSE;
997 h264type.bconstIpred = OMX_FALSE;
998 h264type.bDirect8x8Inference = OMX_FALSE;
999 h264type.bDirectSpatialTemporal = OMX_FALSE;
1000 h264type.nCabacInitIdc = 0;
1001 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1002
1003 err = mOMX->setParameter(
1004 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1005 CHECK_EQ(err, OK);
1006
1007 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1008 InitOMXParams(&bitrateType);
1009 bitrateType.nPortIndex = kPortIndexOutput;
1010
1011 err = mOMX->getParameter(
1012 mNode, OMX_IndexParamVideoBitrate,
1013 &bitrateType, sizeof(bitrateType));
1014 CHECK_EQ(err, OK);
1015
1016 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
James Dong1244eab2010-06-08 11:58:53 -07001017 bitrateType.nTargetBitrate = bitRate;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001018
1019 err = mOMX->setParameter(
1020 mNode, OMX_IndexParamVideoBitrate,
1021 &bitrateType, sizeof(bitrateType));
1022 CHECK_EQ(err, OK);
1023
1024 return OK;
1025}
1026
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001027status_t OMXCodec::setVideoOutputFormat(
Andreas Huberbe06d262009-08-14 14:37:10 -07001028 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -07001029 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001030
Andreas Huberbe06d262009-08-14 14:37:10 -07001031 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -07001032 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001033 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -07001034 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001035 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -07001036 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001037 compressionFormat = OMX_VIDEO_CodingH263;
1038 } else {
1039 LOGE("Not a supported video mime type: %s", mime);
1040 CHECK(!"Should not be here. Not a supported video mime type.");
1041 }
1042
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001043 status_t err = setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -07001044 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1045
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001046 if (err != OK) {
1047 return err;
1048 }
1049
Andreas Huberbe06d262009-08-14 14:37:10 -07001050#if 1
1051 {
1052 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -07001053 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -07001054 format.nPortIndex = kPortIndexOutput;
1055 format.nIndex = 0;
1056
Andreas Huber784202e2009-10-15 13:46:54 -07001057 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001058 mNode, OMX_IndexParamVideoPortFormat,
1059 &format, sizeof(format));
1060 CHECK_EQ(err, OK);
1061 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
1062
1063 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1064
1065 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1066 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1067 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1068 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1069
Andreas Huber784202e2009-10-15 13:46:54 -07001070 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001071 mNode, OMX_IndexParamVideoPortFormat,
1072 &format, sizeof(format));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001073
1074 if (err != OK) {
1075 return err;
1076 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001077 }
1078#endif
1079
1080 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001081 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001082 def.nPortIndex = kPortIndexInput;
1083
Andreas Huber4c483422009-09-02 16:05:36 -07001084 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1085
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001086 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001087 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1088
1089 CHECK_EQ(err, OK);
1090
1091#if 1
1092 // XXX Need a (much) better heuristic to compute input buffer sizes.
1093 const size_t X = 64 * 1024;
1094 if (def.nBufferSize < X) {
1095 def.nBufferSize = X;
1096 }
1097#endif
1098
1099 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1100
1101 video_def->nFrameWidth = width;
1102 video_def->nFrameHeight = height;
1103
Andreas Huberb482ce82009-10-29 12:02:48 -07001104 video_def->eCompressionFormat = compressionFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -07001105 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1106
Andreas Huber784202e2009-10-15 13:46:54 -07001107 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001108 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001109
1110 if (err != OK) {
1111 return err;
1112 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001113
1114 ////////////////////////////////////////////////////////////////////////////
1115
Andreas Huber4c483422009-09-02 16:05:36 -07001116 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001117 def.nPortIndex = kPortIndexOutput;
1118
Andreas Huber784202e2009-10-15 13:46:54 -07001119 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001120 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1121 CHECK_EQ(err, OK);
1122 CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1123
1124#if 0
1125 def.nBufferSize =
1126 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
1127#endif
1128
1129 video_def->nFrameWidth = width;
1130 video_def->nFrameHeight = height;
1131
Andreas Huber784202e2009-10-15 13:46:54 -07001132 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001133 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001134
1135 return err;
Andreas Huberbe06d262009-08-14 14:37:10 -07001136}
1137
Andreas Huberbe06d262009-08-14 14:37:10 -07001138OMXCodec::OMXCodec(
1139 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
Andreas Huberebf66ea2009-08-19 13:32:58 -07001140 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -07001141 const char *mime,
1142 const char *componentName,
1143 const sp<MediaSource> &source)
1144 : mOMX(omx),
Andreas Huberf1fe0642010-01-15 15:28:19 -08001145 mOMXLivesLocally(omx->livesLocally(getpid())),
Andreas Huberbe06d262009-08-14 14:37:10 -07001146 mNode(node),
1147 mQuirks(quirks),
1148 mIsEncoder(isEncoder),
1149 mMIME(strdup(mime)),
1150 mComponentName(strdup(componentName)),
1151 mSource(source),
1152 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -07001153 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -07001154 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -07001155 mSignalledEOS(false),
1156 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -07001157 mOutputPortSettingsHaveChanged(false),
Andreas Hubera4357ad2010-04-02 12:49:54 -07001158 mSeekTimeUs(-1),
Andreas Huber1f24b302010-06-10 11:12:39 -07001159 mLeftOverBuffer(NULL),
1160 mPaused(false) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001161 mPortStatus[kPortIndexInput] = ENABLED;
1162 mPortStatus[kPortIndexOutput] = ENABLED;
1163
Andreas Huber4c483422009-09-02 16:05:36 -07001164 setComponentRole();
1165}
1166
Andreas Hubere6c40962009-09-10 14:13:30 -07001167// static
1168void OMXCodec::setComponentRole(
1169 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1170 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -07001171 struct MimeToRole {
1172 const char *mime;
1173 const char *decoderRole;
1174 const char *encoderRole;
1175 };
1176
1177 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -07001178 { MEDIA_MIMETYPE_AUDIO_MPEG,
1179 "audio_decoder.mp3", "audio_encoder.mp3" },
1180 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1181 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1182 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1183 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1184 { MEDIA_MIMETYPE_AUDIO_AAC,
1185 "audio_decoder.aac", "audio_encoder.aac" },
1186 { MEDIA_MIMETYPE_VIDEO_AVC,
1187 "video_decoder.avc", "video_encoder.avc" },
1188 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1189 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1190 { MEDIA_MIMETYPE_VIDEO_H263,
1191 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber4c483422009-09-02 16:05:36 -07001192 };
1193
1194 static const size_t kNumMimeToRole =
1195 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1196
1197 size_t i;
1198 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001199 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001200 break;
1201 }
1202 }
1203
1204 if (i == kNumMimeToRole) {
1205 return;
1206 }
1207
1208 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -07001209 isEncoder ? kMimeToRole[i].encoderRole
1210 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -07001211
1212 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -07001213 OMX_PARAM_COMPONENTROLETYPE roleParams;
1214 InitOMXParams(&roleParams);
1215
1216 strncpy((char *)roleParams.cRole,
1217 role, OMX_MAX_STRINGNAME_SIZE - 1);
1218
1219 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1220
Andreas Huber784202e2009-10-15 13:46:54 -07001221 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07001222 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -07001223 &roleParams, sizeof(roleParams));
1224
1225 if (err != OK) {
1226 LOGW("Failed to set standard component role '%s'.", role);
1227 }
1228 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001229}
1230
Andreas Hubere6c40962009-09-10 14:13:30 -07001231void OMXCodec::setComponentRole() {
1232 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1233}
1234
Andreas Huberbe06d262009-08-14 14:37:10 -07001235OMXCodec::~OMXCodec() {
Andreas Huber4f5e6022009-08-19 09:29:34 -07001236 CHECK(mState == LOADED || mState == ERROR);
Andreas Huberbe06d262009-08-14 14:37:10 -07001237
Andreas Huber784202e2009-10-15 13:46:54 -07001238 status_t err = mOMX->freeNode(mNode);
Andreas Huberbe06d262009-08-14 14:37:10 -07001239 CHECK_EQ(err, OK);
1240
1241 mNode = NULL;
1242 setState(DEAD);
1243
1244 clearCodecSpecificData();
1245
1246 free(mComponentName);
1247 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001248
Andreas Huberbe06d262009-08-14 14:37:10 -07001249 free(mMIME);
1250 mMIME = NULL;
1251}
1252
1253status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -07001254 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -07001255
1256 CHECK_EQ(mState, LOADED);
1257
1258 status_t err;
1259 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001260 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -07001261 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001262 setState(LOADED_TO_IDLE);
1263 }
1264
1265 err = allocateBuffers();
1266 CHECK_EQ(err, OK);
1267
1268 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -07001269 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huberbe06d262009-08-14 14:37:10 -07001270 CHECK_EQ(err, OK);
1271
1272 setState(LOADED_TO_IDLE);
1273 }
1274
1275 while (mState != EXECUTING && mState != ERROR) {
1276 mAsyncCompletion.wait(mLock);
1277 }
1278
1279 return mState == ERROR ? UNKNOWN_ERROR : OK;
1280}
1281
1282// static
1283bool OMXCodec::isIntermediateState(State state) {
1284 return state == LOADED_TO_IDLE
1285 || state == IDLE_TO_EXECUTING
1286 || state == EXECUTING_TO_IDLE
1287 || state == IDLE_TO_LOADED
1288 || state == RECONFIGURING;
1289}
1290
1291status_t OMXCodec::allocateBuffers() {
1292 status_t err = allocateBuffersOnPort(kPortIndexInput);
1293
1294 if (err != OK) {
1295 return err;
1296 }
1297
1298 return allocateBuffersOnPort(kPortIndexOutput);
1299}
1300
1301status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
1302 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001303 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001304 def.nPortIndex = portIndex;
1305
Andreas Huber784202e2009-10-15 13:46:54 -07001306 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001307 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1308
1309 if (err != OK) {
1310 return err;
1311 }
1312
Andreas Huber5c0a9132009-08-20 11:16:40 -07001313 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
Mathias Agopian6faf7892010-01-25 19:00:00 -08001314 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
Andreas Huber5c0a9132009-08-20 11:16:40 -07001315
Andreas Huberbe06d262009-08-14 14:37:10 -07001316 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -07001317 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07001318 CHECK(mem.get() != NULL);
1319
Andreas Huberc712b9f2010-01-20 15:05:46 -08001320 BufferInfo info;
1321 info.mData = NULL;
1322 info.mSize = def.nBufferSize;
1323
Andreas Huberbe06d262009-08-14 14:37:10 -07001324 IOMX::buffer_id buffer;
1325 if (portIndex == kPortIndexInput
1326 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001327 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001328 mem.clear();
1329
Andreas Huberf1fe0642010-01-15 15:28:19 -08001330 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001331 mNode, portIndex, def.nBufferSize, &buffer,
1332 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001333 } else {
1334 err = mOMX->allocateBufferWithBackup(
1335 mNode, portIndex, mem, &buffer);
1336 }
Andreas Huber446f44f2009-08-25 17:23:44 -07001337 } else if (portIndex == kPortIndexOutput
1338 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001339 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001340 mem.clear();
1341
Andreas Huberf1fe0642010-01-15 15:28:19 -08001342 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001343 mNode, portIndex, def.nBufferSize, &buffer,
1344 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001345 } else {
1346 err = mOMX->allocateBufferWithBackup(
1347 mNode, portIndex, mem, &buffer);
1348 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001349 } else {
Andreas Huber784202e2009-10-15 13:46:54 -07001350 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001351 }
1352
1353 if (err != OK) {
1354 LOGE("allocate_buffer_with_backup failed");
1355 return err;
1356 }
1357
Andreas Huberc712b9f2010-01-20 15:05:46 -08001358 if (mem != NULL) {
1359 info.mData = mem->pointer();
1360 }
1361
Andreas Huberbe06d262009-08-14 14:37:10 -07001362 info.mBuffer = buffer;
1363 info.mOwnedByComponent = false;
1364 info.mMem = mem;
1365 info.mMediaBuffer = NULL;
1366
1367 if (portIndex == kPortIndexOutput) {
Andreas Huber52733b82010-01-25 10:41:35 -08001368 if (!(mOMXLivesLocally
1369 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1370 && (mQuirks & kDefersOutputBufferAllocation))) {
1371 // If the node does not fill in the buffer ptr at this time,
1372 // we will defer creating the MediaBuffer until receiving
1373 // the first FILL_BUFFER_DONE notification instead.
1374 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1375 info.mMediaBuffer->setObserver(this);
1376 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001377 }
1378
1379 mPortBuffers[portIndex].push(info);
1380
Andreas Huber4c483422009-09-02 16:05:36 -07001381 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -07001382 portIndex == kPortIndexInput ? "input" : "output");
1383 }
1384
Andreas Huber2ea14e22009-12-16 09:30:55 -08001385 // dumpPortStatus(portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001386
1387 return OK;
1388}
1389
1390void OMXCodec::on_message(const omx_message &msg) {
1391 Mutex::Autolock autoLock(mLock);
1392
1393 switch (msg.type) {
1394 case omx_message::EVENT:
1395 {
1396 onEvent(
1397 msg.u.event_data.event, msg.u.event_data.data1,
1398 msg.u.event_data.data2);
1399
1400 break;
1401 }
1402
1403 case omx_message::EMPTY_BUFFER_DONE:
1404 {
1405 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1406
Andreas Huber4c483422009-09-02 16:05:36 -07001407 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001408
1409 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1410 size_t i = 0;
1411 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1412 ++i;
1413 }
1414
1415 CHECK(i < buffers->size());
1416 if (!(*buffers)[i].mOwnedByComponent) {
1417 LOGW("We already own input buffer %p, yet received "
1418 "an EMPTY_BUFFER_DONE.", buffer);
1419 }
1420
1421 buffers->editItemAt(i).mOwnedByComponent = false;
1422
1423 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07001424 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001425
1426 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001427 mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001428 CHECK_EQ(err, OK);
1429
1430 buffers->removeAt(i);
Andreas Huber4a9375e2010-02-09 11:54:33 -08001431 } else if (mState != ERROR
1432 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001433 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
1434 drainInputBuffer(&buffers->editItemAt(i));
1435 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001436 break;
1437 }
1438
1439 case omx_message::FILL_BUFFER_DONE:
1440 {
1441 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1442 OMX_U32 flags = msg.u.extended_buffer_data.flags;
1443
Andreas Huber2ea14e22009-12-16 09:30:55 -08001444 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -07001445 buffer,
1446 msg.u.extended_buffer_data.range_length,
Andreas Huber2ea14e22009-12-16 09:30:55 -08001447 flags,
Andreas Huberbe06d262009-08-14 14:37:10 -07001448 msg.u.extended_buffer_data.timestamp,
1449 msg.u.extended_buffer_data.timestamp / 1E6);
1450
1451 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1452 size_t i = 0;
1453 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1454 ++i;
1455 }
1456
1457 CHECK(i < buffers->size());
1458 BufferInfo *info = &buffers->editItemAt(i);
1459
1460 if (!info->mOwnedByComponent) {
1461 LOGW("We already own output buffer %p, yet received "
1462 "a FILL_BUFFER_DONE.", buffer);
1463 }
1464
1465 info->mOwnedByComponent = false;
1466
1467 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07001468 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001469
1470 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001471 mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001472 CHECK_EQ(err, OK);
1473
1474 buffers->removeAt(i);
Andreas Huber2ea14e22009-12-16 09:30:55 -08001475#if 0
Andreas Huberd7795892009-08-26 10:33:47 -07001476 } else if (mPortStatus[kPortIndexOutput] == ENABLED
1477 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001478 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001479 mNoMoreOutputData = true;
1480 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08001481#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07001482 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
1483 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -07001484
Andreas Huber52733b82010-01-25 10:41:35 -08001485 if (info->mMediaBuffer == NULL) {
1486 CHECK(mOMXLivesLocally);
1487 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
1488 CHECK(mQuirks & kDefersOutputBufferAllocation);
1489
1490 // The qcom video decoders on Nexus don't actually allocate
1491 // output buffer memory on a call to OMX_AllocateBuffer
1492 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
1493 // structure is only filled in later.
1494
1495 info->mMediaBuffer = new MediaBuffer(
1496 msg.u.extended_buffer_data.data_ptr,
1497 info->mSize);
1498 info->mMediaBuffer->setObserver(this);
1499 }
1500
Andreas Huberbe06d262009-08-14 14:37:10 -07001501 MediaBuffer *buffer = info->mMediaBuffer;
1502
1503 buffer->set_range(
1504 msg.u.extended_buffer_data.range_offset,
1505 msg.u.extended_buffer_data.range_length);
1506
1507 buffer->meta_data()->clear();
1508
Andreas Huberfa8de752009-10-08 10:07:49 -07001509 buffer->meta_data()->setInt64(
1510 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -07001511
1512 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
1513 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
1514 }
Andreas Huberea6a38c2009-11-16 15:43:38 -08001515 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
1516 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
1517 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001518
1519 buffer->meta_data()->setPointer(
1520 kKeyPlatformPrivate,
1521 msg.u.extended_buffer_data.platform_private);
1522
1523 buffer->meta_data()->setPointer(
1524 kKeyBufferID,
1525 msg.u.extended_buffer_data.buffer);
1526
1527 mFilledBuffers.push_back(i);
1528 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08001529
1530 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
1531 CODEC_LOGV("No more output data.");
1532 mNoMoreOutputData = true;
1533 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001534 }
1535
1536 break;
1537 }
1538
1539 default:
1540 {
1541 CHECK(!"should not be here.");
1542 break;
1543 }
1544 }
1545}
1546
1547void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1548 switch (event) {
1549 case OMX_EventCmdComplete:
1550 {
1551 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1552 break;
1553 }
1554
1555 case OMX_EventError:
1556 {
Andreas Huber2ea14e22009-12-16 09:30:55 -08001557 LOGE("ERROR(0x%08lx, %ld)", data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001558
1559 setState(ERROR);
1560 break;
1561 }
1562
1563 case OMX_EventPortSettingsChanged:
1564 {
1565 onPortSettingsChanged(data1);
1566 break;
1567 }
1568
Andreas Huber2ea14e22009-12-16 09:30:55 -08001569#if 0
Andreas Huberbe06d262009-08-14 14:37:10 -07001570 case OMX_EventBufferFlag:
1571 {
Andreas Huber4c483422009-09-02 16:05:36 -07001572 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
Andreas Huberbe06d262009-08-14 14:37:10 -07001573
1574 if (data1 == kPortIndexOutput) {
1575 mNoMoreOutputData = true;
1576 }
1577 break;
1578 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08001579#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07001580
1581 default:
1582 {
Andreas Huber4c483422009-09-02 16:05:36 -07001583 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
Andreas Huberbe06d262009-08-14 14:37:10 -07001584 break;
1585 }
1586 }
1587}
1588
Andreas Huberb1678602009-10-19 13:06:40 -07001589// Has the format changed in any way that the client would have to be aware of?
1590static bool formatHasNotablyChanged(
1591 const sp<MetaData> &from, const sp<MetaData> &to) {
1592 if (from.get() == NULL && to.get() == NULL) {
1593 return false;
1594 }
1595
Andreas Huberf68c1682009-10-21 14:01:30 -07001596 if ((from.get() == NULL && to.get() != NULL)
1597 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07001598 return true;
1599 }
1600
1601 const char *mime_from, *mime_to;
1602 CHECK(from->findCString(kKeyMIMEType, &mime_from));
1603 CHECK(to->findCString(kKeyMIMEType, &mime_to));
1604
1605 if (strcasecmp(mime_from, mime_to)) {
1606 return true;
1607 }
1608
1609 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
1610 int32_t colorFormat_from, colorFormat_to;
1611 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
1612 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
1613
1614 if (colorFormat_from != colorFormat_to) {
1615 return true;
1616 }
1617
1618 int32_t width_from, width_to;
1619 CHECK(from->findInt32(kKeyWidth, &width_from));
1620 CHECK(to->findInt32(kKeyWidth, &width_to));
1621
1622 if (width_from != width_to) {
1623 return true;
1624 }
1625
1626 int32_t height_from, height_to;
1627 CHECK(from->findInt32(kKeyHeight, &height_from));
1628 CHECK(to->findInt32(kKeyHeight, &height_to));
1629
1630 if (height_from != height_to) {
1631 return true;
1632 }
1633 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
1634 int32_t numChannels_from, numChannels_to;
1635 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
1636 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
1637
1638 if (numChannels_from != numChannels_to) {
1639 return true;
1640 }
1641
1642 int32_t sampleRate_from, sampleRate_to;
1643 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
1644 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
1645
1646 if (sampleRate_from != sampleRate_to) {
1647 return true;
1648 }
1649 }
1650
1651 return false;
1652}
1653
Andreas Huberbe06d262009-08-14 14:37:10 -07001654void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1655 switch (cmd) {
1656 case OMX_CommandStateSet:
1657 {
1658 onStateChange((OMX_STATETYPE)data);
1659 break;
1660 }
1661
1662 case OMX_CommandPortDisable:
1663 {
1664 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001665 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001666
1667 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1668 CHECK_EQ(mPortStatus[portIndex], DISABLING);
1669 CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1670
1671 mPortStatus[portIndex] = DISABLED;
1672
1673 if (mState == RECONFIGURING) {
1674 CHECK_EQ(portIndex, kPortIndexOutput);
1675
Andreas Huberb1678602009-10-19 13:06:40 -07001676 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07001677 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07001678
1679 // Don't notify clients if the output port settings change
1680 // wasn't of importance to them, i.e. it may be that just the
1681 // number of buffers has changed and nothing else.
1682 mOutputPortSettingsHaveChanged =
1683 formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
Andreas Hubercfd55572009-10-09 14:11:28 -07001684
Andreas Huberbe06d262009-08-14 14:37:10 -07001685 enablePortAsync(portIndex);
1686
1687 status_t err = allocateBuffersOnPort(portIndex);
1688 CHECK_EQ(err, OK);
1689 }
1690 break;
1691 }
1692
1693 case OMX_CommandPortEnable:
1694 {
1695 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07001696 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001697
1698 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1699 CHECK_EQ(mPortStatus[portIndex], ENABLING);
1700
1701 mPortStatus[portIndex] = ENABLED;
1702
1703 if (mState == RECONFIGURING) {
1704 CHECK_EQ(portIndex, kPortIndexOutput);
1705
1706 setState(EXECUTING);
1707
1708 fillOutputBuffers();
1709 }
1710 break;
1711 }
1712
1713 case OMX_CommandFlush:
1714 {
1715 OMX_U32 portIndex = data;
1716
Andreas Huber4c483422009-09-02 16:05:36 -07001717 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001718
1719 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1720 mPortStatus[portIndex] = ENABLED;
1721
1722 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1723 mPortBuffers[portIndex].size());
1724
1725 if (mState == RECONFIGURING) {
1726 CHECK_EQ(portIndex, kPortIndexOutput);
1727
1728 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001729 } else if (mState == EXECUTING_TO_IDLE) {
1730 if (mPortStatus[kPortIndexInput] == ENABLED
1731 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001732 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07001733 "transition from EXECUTING to IDLE.");
1734
1735 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1736 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1737
1738 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001739 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07001740 CHECK_EQ(err, OK);
1741 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001742 } else {
1743 // We're flushing both ports in preparation for seeking.
1744
1745 if (mPortStatus[kPortIndexInput] == ENABLED
1746 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07001747 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07001748 " seek-time.");
1749
Andreas Huber1f24b302010-06-10 11:12:39 -07001750 // We implicitly resume pulling on our upstream source.
1751 mPaused = false;
1752
Andreas Huberbe06d262009-08-14 14:37:10 -07001753 drainInputBuffers();
1754 fillOutputBuffers();
1755 }
1756 }
1757
1758 break;
1759 }
1760
1761 default:
1762 {
Andreas Huber4c483422009-09-02 16:05:36 -07001763 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07001764 break;
1765 }
1766 }
1767}
1768
1769void OMXCodec::onStateChange(OMX_STATETYPE newState) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001770 CODEC_LOGV("onStateChange %d", newState);
1771
Andreas Huberbe06d262009-08-14 14:37:10 -07001772 switch (newState) {
1773 case OMX_StateIdle:
1774 {
Andreas Huber4c483422009-09-02 16:05:36 -07001775 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001776 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07001777 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07001778 mNode, OMX_CommandStateSet, OMX_StateExecuting);
1779
1780 CHECK_EQ(err, OK);
1781
1782 setState(IDLE_TO_EXECUTING);
1783 } else {
1784 CHECK_EQ(mState, EXECUTING_TO_IDLE);
1785
1786 CHECK_EQ(
1787 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1788 mPortBuffers[kPortIndexInput].size());
1789
1790 CHECK_EQ(
1791 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1792 mPortBuffers[kPortIndexOutput].size());
1793
Andreas Huber784202e2009-10-15 13:46:54 -07001794 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07001795 mNode, OMX_CommandStateSet, OMX_StateLoaded);
1796
1797 CHECK_EQ(err, OK);
1798
1799 err = freeBuffersOnPort(kPortIndexInput);
1800 CHECK_EQ(err, OK);
1801
1802 err = freeBuffersOnPort(kPortIndexOutput);
1803 CHECK_EQ(err, OK);
1804
1805 mPortStatus[kPortIndexInput] = ENABLED;
1806 mPortStatus[kPortIndexOutput] = ENABLED;
1807
1808 setState(IDLE_TO_LOADED);
1809 }
1810 break;
1811 }
1812
1813 case OMX_StateExecuting:
1814 {
1815 CHECK_EQ(mState, IDLE_TO_EXECUTING);
1816
Andreas Huber4c483422009-09-02 16:05:36 -07001817 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001818
1819 setState(EXECUTING);
1820
Andreas Huber42978e52009-08-27 10:08:39 -07001821 // Buffers will be submitted to the component in the first
1822 // call to OMXCodec::read as mInitialBufferSubmit is true at
1823 // this point. This ensures that this on_message call returns,
1824 // releases the lock and ::init can notice the state change and
1825 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07001826 break;
1827 }
1828
1829 case OMX_StateLoaded:
1830 {
1831 CHECK_EQ(mState, IDLE_TO_LOADED);
1832
Andreas Huber4c483422009-09-02 16:05:36 -07001833 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07001834
1835 setState(LOADED);
1836 break;
1837 }
1838
Andreas Huberc712b9f2010-01-20 15:05:46 -08001839 case OMX_StateInvalid:
1840 {
1841 setState(ERROR);
1842 break;
1843 }
1844
Andreas Huberbe06d262009-08-14 14:37:10 -07001845 default:
1846 {
1847 CHECK(!"should not be here.");
1848 break;
1849 }
1850 }
1851}
1852
1853// static
1854size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1855 size_t n = 0;
1856 for (size_t i = 0; i < buffers.size(); ++i) {
1857 if (!buffers[i].mOwnedByComponent) {
1858 ++n;
1859 }
1860 }
1861
1862 return n;
1863}
1864
1865status_t OMXCodec::freeBuffersOnPort(
1866 OMX_U32 portIndex, bool onlyThoseWeOwn) {
1867 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1868
1869 status_t stickyErr = OK;
1870
1871 for (size_t i = buffers->size(); i-- > 0;) {
1872 BufferInfo *info = &buffers->editItemAt(i);
1873
1874 if (onlyThoseWeOwn && info->mOwnedByComponent) {
1875 continue;
1876 }
1877
1878 CHECK_EQ(info->mOwnedByComponent, false);
1879
Andreas Huber92022852009-09-14 15:24:14 -07001880 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
1881
Andreas Huberbe06d262009-08-14 14:37:10 -07001882 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001883 mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001884
1885 if (err != OK) {
1886 stickyErr = err;
1887 }
1888
1889 if (info->mMediaBuffer != NULL) {
1890 info->mMediaBuffer->setObserver(NULL);
1891
1892 // Make sure nobody but us owns this buffer at this point.
1893 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1894
1895 info->mMediaBuffer->release();
1896 }
1897
1898 buffers->removeAt(i);
1899 }
1900
1901 CHECK(onlyThoseWeOwn || buffers->isEmpty());
1902
1903 return stickyErr;
1904}
1905
1906void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07001907 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001908
1909 CHECK_EQ(mState, EXECUTING);
1910 CHECK_EQ(portIndex, kPortIndexOutput);
1911 setState(RECONFIGURING);
1912
1913 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07001914 if (!flushPortAsync(portIndex)) {
1915 onCmdComplete(OMX_CommandFlush, portIndex);
1916 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001917 } else {
1918 disablePortAsync(portIndex);
1919 }
1920}
1921
Andreas Huber404cc412009-08-25 14:26:05 -07001922bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07001923 CHECK(mState == EXECUTING || mState == RECONFIGURING
1924 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001925
Andreas Huber4c483422009-09-02 16:05:36 -07001926 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07001927 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1928 mPortBuffers[portIndex].size());
1929
Andreas Huberbe06d262009-08-14 14:37:10 -07001930 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1931 mPortStatus[portIndex] = SHUTTING_DOWN;
1932
Andreas Huber404cc412009-08-25 14:26:05 -07001933 if ((mQuirks & kRequiresFlushCompleteEmulation)
1934 && countBuffersWeOwn(mPortBuffers[portIndex])
1935 == mPortBuffers[portIndex].size()) {
1936 // No flush is necessary and this component fails to send a
1937 // flush-complete event in this case.
1938
1939 return false;
1940 }
1941
Andreas Huberbe06d262009-08-14 14:37:10 -07001942 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001943 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001944 CHECK_EQ(err, OK);
Andreas Huber404cc412009-08-25 14:26:05 -07001945
1946 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07001947}
1948
1949void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1950 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1951
1952 CHECK_EQ(mPortStatus[portIndex], ENABLED);
1953 mPortStatus[portIndex] = DISABLING;
1954
1955 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001956 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001957 CHECK_EQ(err, OK);
1958
1959 freeBuffersOnPort(portIndex, true);
1960}
1961
1962void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1963 CHECK(mState == EXECUTING || mState == RECONFIGURING);
1964
1965 CHECK_EQ(mPortStatus[portIndex], DISABLED);
1966 mPortStatus[portIndex] = ENABLING;
1967
1968 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07001969 mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001970 CHECK_EQ(err, OK);
1971}
1972
1973void OMXCodec::fillOutputBuffers() {
1974 CHECK_EQ(mState, EXECUTING);
1975
Andreas Huberdbcb2c62010-01-14 11:32:13 -08001976 // This is a workaround for some decoders not properly reporting
1977 // end-of-output-stream. If we own all input buffers and also own
1978 // all output buffers and we already signalled end-of-input-stream,
1979 // the end-of-output-stream is implied.
1980 if (mSignalledEOS
1981 && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
1982 == mPortBuffers[kPortIndexInput].size()
1983 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
1984 == mPortBuffers[kPortIndexOutput].size()) {
1985 mNoMoreOutputData = true;
1986 mBufferFilled.signal();
1987
1988 return;
1989 }
1990
Andreas Huberbe06d262009-08-14 14:37:10 -07001991 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1992 for (size_t i = 0; i < buffers->size(); ++i) {
1993 fillOutputBuffer(&buffers->editItemAt(i));
1994 }
1995}
1996
1997void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07001998 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07001999
2000 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2001 for (size_t i = 0; i < buffers->size(); ++i) {
2002 drainInputBuffer(&buffers->editItemAt(i));
2003 }
2004}
2005
2006void OMXCodec::drainInputBuffer(BufferInfo *info) {
2007 CHECK_EQ(info->mOwnedByComponent, false);
2008
2009 if (mSignalledEOS) {
2010 return;
2011 }
2012
2013 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
2014 const CodecSpecificData *specific =
2015 mCodecSpecificData[mCodecSpecificDataIndex];
2016
2017 size_t size = specific->mSize;
2018
Andreas Hubere6c40962009-09-10 14:13:30 -07002019 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07002020 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002021 static const uint8_t kNALStartCode[4] =
2022 { 0x00, 0x00, 0x00, 0x01 };
2023
Andreas Huberc712b9f2010-01-20 15:05:46 -08002024 CHECK(info->mSize >= specific->mSize + 4);
Andreas Huberbe06d262009-08-14 14:37:10 -07002025
2026 size += 4;
2027
Andreas Huberc712b9f2010-01-20 15:05:46 -08002028 memcpy(info->mData, kNALStartCode, 4);
2029 memcpy((uint8_t *)info->mData + 4,
Andreas Huberbe06d262009-08-14 14:37:10 -07002030 specific->mData, specific->mSize);
2031 } else {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002032 CHECK(info->mSize >= specific->mSize);
2033 memcpy(info->mData, specific->mData, specific->mSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07002034 }
2035
Andreas Huber2ea14e22009-12-16 09:30:55 -08002036 mNoMoreOutputData = false;
2037
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002038 CODEC_LOGV("calling emptyBuffer with codec specific data");
2039
Andreas Huber784202e2009-10-15 13:46:54 -07002040 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07002041 mNode, info->mBuffer, 0, size,
2042 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
2043 0);
Andreas Huber3f427072009-10-08 11:02:27 -07002044 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002045
2046 info->mOwnedByComponent = true;
2047
2048 ++mCodecSpecificDataIndex;
2049 return;
2050 }
2051
Andreas Huber1f24b302010-06-10 11:12:39 -07002052 if (mPaused) {
2053 return;
2054 }
2055
Andreas Huberbe06d262009-08-14 14:37:10 -07002056 status_t err;
Andreas Huber2ea14e22009-12-16 09:30:55 -08002057
Andreas Hubera4357ad2010-04-02 12:49:54 -07002058 bool signalEOS = false;
2059 int64_t timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07002060
Andreas Hubera4357ad2010-04-02 12:49:54 -07002061 size_t offset = 0;
2062 int32_t n = 0;
2063 for (;;) {
2064 MediaBuffer *srcBuffer;
2065 if (mSeekTimeUs >= 0) {
2066 if (mLeftOverBuffer) {
2067 mLeftOverBuffer->release();
2068 mLeftOverBuffer = NULL;
2069 }
2070
2071 MediaSource::ReadOptions options;
2072 options.setSeekTo(mSeekTimeUs);
2073
2074 mSeekTimeUs = -1;
2075 mBufferFilled.signal();
2076
2077 err = mSource->read(&srcBuffer, &options);
2078 } else if (mLeftOverBuffer) {
2079 srcBuffer = mLeftOverBuffer;
2080 mLeftOverBuffer = NULL;
2081
2082 err = OK;
2083 } else {
2084 err = mSource->read(&srcBuffer);
2085 }
2086
2087 if (err != OK) {
2088 signalEOS = true;
2089 mFinalStatus = err;
2090 mSignalledEOS = true;
2091 break;
2092 }
2093
2094 size_t remainingBytes = info->mSize - offset;
2095
2096 if (srcBuffer->range_length() > remainingBytes) {
2097 if (offset == 0) {
2098 CODEC_LOGE(
2099 "Codec's input buffers are too small to accomodate "
2100 "buffer read from source (info->mSize = %d, srcLength = %d)",
2101 info->mSize, srcBuffer->range_length());
2102
2103 srcBuffer->release();
2104 srcBuffer = NULL;
2105
2106 setState(ERROR);
2107 return;
2108 }
2109
2110 mLeftOverBuffer = srcBuffer;
2111 break;
2112 }
2113
James Dong4f501f02010-06-07 14:41:41 -07002114 if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2115 CHECK(mOMXLivesLocally && offset == 0);
2116 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
2117 header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
2118 } else {
2119 memcpy((uint8_t *)info->mData + offset,
2120 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
2121 srcBuffer->range_length());
2122 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002123
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002124 int64_t lastBufferTimeUs;
2125 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
2126 CHECK(timestampUs >= 0);
2127
Andreas Hubera4357ad2010-04-02 12:49:54 -07002128 if (offset == 0) {
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002129 timestampUs = lastBufferTimeUs;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002130 }
2131
2132 offset += srcBuffer->range_length();
2133
2134 srcBuffer->release();
2135 srcBuffer = NULL;
2136
2137 ++n;
2138
2139 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
2140 break;
2141 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002142
2143 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
2144
2145 if (coalescedDurationUs > 250000ll) {
2146 // Don't coalesce more than 250ms worth of encoded data at once.
2147 break;
2148 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002149 }
2150
2151 if (n > 1) {
2152 LOGV("coalesced %d frames into one input buffer", n);
Andreas Huberbe06d262009-08-14 14:37:10 -07002153 }
2154
2155 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberbe06d262009-08-14 14:37:10 -07002156
Andreas Hubera4357ad2010-04-02 12:49:54 -07002157 if (signalEOS) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002158 flags |= OMX_BUFFERFLAG_EOS;
Andreas Huberbe06d262009-08-14 14:37:10 -07002159 } else {
Andreas Huber2ea14e22009-12-16 09:30:55 -08002160 mNoMoreOutputData = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002161 }
2162
Andreas Hubera4357ad2010-04-02 12:49:54 -07002163 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
2164 "timestamp %lld us (%.2f secs)",
2165 info->mBuffer, offset,
2166 timestampUs, timestampUs / 1E6);
Andreas Huber3f427072009-10-08 11:02:27 -07002167
Andreas Huber784202e2009-10-15 13:46:54 -07002168 err = mOMX->emptyBuffer(
Andreas Hubera4357ad2010-04-02 12:49:54 -07002169 mNode, info->mBuffer, 0, offset,
Andreas Huberfa8de752009-10-08 10:07:49 -07002170 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07002171
2172 if (err != OK) {
2173 setState(ERROR);
2174 return;
2175 }
2176
2177 info->mOwnedByComponent = true;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002178
2179 // This component does not ever signal the EOS flag on output buffers,
2180 // Thanks for nothing.
2181 if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) {
2182 mNoMoreOutputData = true;
2183 mBufferFilled.signal();
2184 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002185}
2186
2187void OMXCodec::fillOutputBuffer(BufferInfo *info) {
2188 CHECK_EQ(info->mOwnedByComponent, false);
2189
Andreas Huber404cc412009-08-25 14:26:05 -07002190 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07002191 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07002192 "calling fillOutputBuffer");
2193 return;
2194 }
2195
Andreas Huber4c483422009-09-02 16:05:36 -07002196 CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07002197 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber8f14c552010-04-12 10:20:12 -07002198
2199 if (err != OK) {
2200 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
2201
2202 setState(ERROR);
2203 return;
2204 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002205
2206 info->mOwnedByComponent = true;
2207}
2208
2209void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
2210 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2211 for (size_t i = 0; i < buffers->size(); ++i) {
2212 if ((*buffers)[i].mBuffer == buffer) {
2213 drainInputBuffer(&buffers->editItemAt(i));
2214 return;
2215 }
2216 }
2217
2218 CHECK(!"should not be here.");
2219}
2220
2221void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
2222 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2223 for (size_t i = 0; i < buffers->size(); ++i) {
2224 if ((*buffers)[i].mBuffer == buffer) {
2225 fillOutputBuffer(&buffers->editItemAt(i));
2226 return;
2227 }
2228 }
2229
2230 CHECK(!"should not be here.");
2231}
2232
2233void OMXCodec::setState(State newState) {
2234 mState = newState;
2235 mAsyncCompletion.signal();
2236
2237 // This may cause some spurious wakeups but is necessary to
2238 // unblock the reader if we enter ERROR state.
2239 mBufferFilled.signal();
2240}
2241
Andreas Huberda050cf22009-09-02 14:01:43 -07002242void OMXCodec::setRawAudioFormat(
2243 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
James Dongabed93a2010-04-22 17:27:04 -07002244
2245 // port definition
2246 OMX_PARAM_PORTDEFINITIONTYPE def;
2247 InitOMXParams(&def);
2248 def.nPortIndex = portIndex;
2249 status_t err = mOMX->getParameter(
2250 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2251 CHECK_EQ(err, OK);
2252 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2253 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2254 &def, sizeof(def)), OK);
2255
2256 // pcm param
Andreas Huberda050cf22009-09-02 14:01:43 -07002257 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07002258 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07002259 pcmParams.nPortIndex = portIndex;
2260
James Dongabed93a2010-04-22 17:27:04 -07002261 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002262 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2263
2264 CHECK_EQ(err, OK);
2265
2266 pcmParams.nChannels = numChannels;
2267 pcmParams.eNumData = OMX_NumericalDataSigned;
2268 pcmParams.bInterleaved = OMX_TRUE;
2269 pcmParams.nBitPerSample = 16;
2270 pcmParams.nSamplingRate = sampleRate;
2271 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2272
2273 if (numChannels == 1) {
2274 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
2275 } else {
2276 CHECK_EQ(numChannels, 2);
2277
2278 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2279 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2280 }
2281
Andreas Huber784202e2009-10-15 13:46:54 -07002282 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002283 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2284
2285 CHECK_EQ(err, OK);
2286}
2287
James Dong17299ab2010-05-14 15:45:22 -07002288static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
2289 if (isAMRWB) {
2290 if (bps <= 6600) {
2291 return OMX_AUDIO_AMRBandModeWB0;
2292 } else if (bps <= 8850) {
2293 return OMX_AUDIO_AMRBandModeWB1;
2294 } else if (bps <= 12650) {
2295 return OMX_AUDIO_AMRBandModeWB2;
2296 } else if (bps <= 14250) {
2297 return OMX_AUDIO_AMRBandModeWB3;
2298 } else if (bps <= 15850) {
2299 return OMX_AUDIO_AMRBandModeWB4;
2300 } else if (bps <= 18250) {
2301 return OMX_AUDIO_AMRBandModeWB5;
2302 } else if (bps <= 19850) {
2303 return OMX_AUDIO_AMRBandModeWB6;
2304 } else if (bps <= 23050) {
2305 return OMX_AUDIO_AMRBandModeWB7;
2306 }
2307
2308 // 23850 bps
2309 return OMX_AUDIO_AMRBandModeWB8;
2310 } else { // AMRNB
2311 if (bps <= 4750) {
2312 return OMX_AUDIO_AMRBandModeNB0;
2313 } else if (bps <= 5150) {
2314 return OMX_AUDIO_AMRBandModeNB1;
2315 } else if (bps <= 5900) {
2316 return OMX_AUDIO_AMRBandModeNB2;
2317 } else if (bps <= 6700) {
2318 return OMX_AUDIO_AMRBandModeNB3;
2319 } else if (bps <= 7400) {
2320 return OMX_AUDIO_AMRBandModeNB4;
2321 } else if (bps <= 7950) {
2322 return OMX_AUDIO_AMRBandModeNB5;
2323 } else if (bps <= 10200) {
2324 return OMX_AUDIO_AMRBandModeNB6;
2325 }
2326
2327 // 12200 bps
2328 return OMX_AUDIO_AMRBandModeNB7;
2329 }
2330}
2331
2332void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
Andreas Huber8768f2c2009-12-01 15:26:54 -08002333 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002334
Andreas Huber8768f2c2009-12-01 15:26:54 -08002335 OMX_AUDIO_PARAM_AMRTYPE def;
2336 InitOMXParams(&def);
2337 def.nPortIndex = portIndex;
Andreas Huberbe06d262009-08-14 14:37:10 -07002338
Andreas Huber8768f2c2009-12-01 15:26:54 -08002339 status_t err =
2340 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07002341
Andreas Huber8768f2c2009-12-01 15:26:54 -08002342 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002343
Andreas Huber8768f2c2009-12-01 15:26:54 -08002344 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
James Dongabed93a2010-04-22 17:27:04 -07002345
James Dong17299ab2010-05-14 15:45:22 -07002346 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
Andreas Huber8768f2c2009-12-01 15:26:54 -08002347 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2348 CHECK_EQ(err, OK);
Andreas Huberee606e62009-09-08 10:19:21 -07002349
2350 ////////////////////////
2351
2352 if (mIsEncoder) {
2353 sp<MetaData> format = mSource->getFormat();
2354 int32_t sampleRate;
2355 int32_t numChannels;
2356 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
2357 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
2358
2359 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2360 }
2361}
2362
James Dong17299ab2010-05-14 15:45:22 -07002363void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
James Dongabed93a2010-04-22 17:27:04 -07002364 CHECK(numChannels == 1 || numChannels == 2);
Andreas Huberda050cf22009-09-02 14:01:43 -07002365 if (mIsEncoder) {
James Dongabed93a2010-04-22 17:27:04 -07002366 //////////////// input port ////////////////////
Andreas Huberda050cf22009-09-02 14:01:43 -07002367 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
James Dongabed93a2010-04-22 17:27:04 -07002368
2369 //////////////// output port ////////////////////
2370 // format
2371 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2372 format.nPortIndex = kPortIndexOutput;
2373 format.nIndex = 0;
2374 status_t err = OMX_ErrorNone;
2375 while (OMX_ErrorNone == err) {
2376 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
2377 &format, sizeof(format)), OK);
2378 if (format.eEncoding == OMX_AUDIO_CodingAAC) {
2379 break;
2380 }
2381 format.nIndex++;
2382 }
2383 CHECK_EQ(OK, err);
2384 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
2385 &format, sizeof(format)), OK);
2386
2387 // port definition
2388 OMX_PARAM_PORTDEFINITIONTYPE def;
2389 InitOMXParams(&def);
2390 def.nPortIndex = kPortIndexOutput;
2391 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
2392 &def, sizeof(def)), OK);
2393 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2394 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2395 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2396 &def, sizeof(def)), OK);
2397
2398 // profile
2399 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2400 InitOMXParams(&profile);
2401 profile.nPortIndex = kPortIndexOutput;
2402 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
2403 &profile, sizeof(profile)), OK);
2404 profile.nChannels = numChannels;
2405 profile.eChannelMode = (numChannels == 1?
2406 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
2407 profile.nSampleRate = sampleRate;
James Dong17299ab2010-05-14 15:45:22 -07002408 profile.nBitRate = bitRate;
James Dongabed93a2010-04-22 17:27:04 -07002409 profile.nAudioBandWidth = 0;
2410 profile.nFrameLength = 0;
2411 profile.nAACtools = OMX_AUDIO_AACToolAll;
2412 profile.nAACERtools = OMX_AUDIO_AACERNone;
2413 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
2414 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2415 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
2416 &profile, sizeof(profile)), OK);
2417
Andreas Huberda050cf22009-09-02 14:01:43 -07002418 } else {
2419 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07002420 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07002421 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07002422
Andreas Huber784202e2009-10-15 13:46:54 -07002423 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002424 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2425 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002426
Andreas Huberda050cf22009-09-02 14:01:43 -07002427 profile.nChannels = numChannels;
2428 profile.nSampleRate = sampleRate;
2429 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07002430
Andreas Huber784202e2009-10-15 13:46:54 -07002431 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07002432 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2433 CHECK_EQ(err, OK);
2434 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002435}
2436
2437void OMXCodec::setImageOutputFormat(
2438 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07002439 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07002440
2441#if 0
2442 OMX_INDEXTYPE index;
2443 status_t err = mOMX->get_extension_index(
2444 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
2445 CHECK_EQ(err, OK);
2446
2447 err = mOMX->set_config(mNode, index, &format, sizeof(format));
2448 CHECK_EQ(err, OK);
2449#endif
2450
2451 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002452 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002453 def.nPortIndex = kPortIndexOutput;
2454
Andreas Huber784202e2009-10-15 13:46:54 -07002455 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002456 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2457 CHECK_EQ(err, OK);
2458
2459 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2460
2461 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07002462
Andreas Huberbe06d262009-08-14 14:37:10 -07002463 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2464 imageDef->eColorFormat = format;
2465 imageDef->nFrameWidth = width;
2466 imageDef->nFrameHeight = height;
2467
2468 switch (format) {
2469 case OMX_COLOR_FormatYUV420PackedPlanar:
2470 case OMX_COLOR_FormatYUV411Planar:
2471 {
2472 def.nBufferSize = (width * height * 3) / 2;
2473 break;
2474 }
2475
2476 case OMX_COLOR_FormatCbYCrY:
2477 {
2478 def.nBufferSize = width * height * 2;
2479 break;
2480 }
2481
2482 case OMX_COLOR_Format32bitARGB8888:
2483 {
2484 def.nBufferSize = width * height * 4;
2485 break;
2486 }
2487
Andreas Huber201511c2009-09-08 14:01:44 -07002488 case OMX_COLOR_Format16bitARGB4444:
2489 case OMX_COLOR_Format16bitARGB1555:
2490 case OMX_COLOR_Format16bitRGB565:
2491 case OMX_COLOR_Format16bitBGR565:
2492 {
2493 def.nBufferSize = width * height * 2;
2494 break;
2495 }
2496
Andreas Huberbe06d262009-08-14 14:37:10 -07002497 default:
2498 CHECK(!"Should not be here. Unknown color format.");
2499 break;
2500 }
2501
Andreas Huber5c0a9132009-08-20 11:16:40 -07002502 def.nBufferCountActual = def.nBufferCountMin;
2503
Andreas Huber784202e2009-10-15 13:46:54 -07002504 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002505 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2506 CHECK_EQ(err, OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07002507}
Andreas Huberbe06d262009-08-14 14:37:10 -07002508
Andreas Huber5c0a9132009-08-20 11:16:40 -07002509void OMXCodec::setJPEGInputFormat(
2510 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
2511 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002512 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002513 def.nPortIndex = kPortIndexInput;
2514
Andreas Huber784202e2009-10-15 13:46:54 -07002515 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002516 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2517 CHECK_EQ(err, OK);
2518
Andreas Huber5c0a9132009-08-20 11:16:40 -07002519 CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2520 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2521
Andreas Huberbe06d262009-08-14 14:37:10 -07002522 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
2523 imageDef->nFrameWidth = width;
2524 imageDef->nFrameHeight = height;
2525
Andreas Huber5c0a9132009-08-20 11:16:40 -07002526 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07002527 def.nBufferCountActual = def.nBufferCountMin;
2528
Andreas Huber784202e2009-10-15 13:46:54 -07002529 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002530 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2531 CHECK_EQ(err, OK);
2532}
2533
2534void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
2535 CodecSpecificData *specific =
2536 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
2537
2538 specific->mSize = size;
2539 memcpy(specific->mData, data, size);
2540
2541 mCodecSpecificData.push(specific);
2542}
2543
2544void OMXCodec::clearCodecSpecificData() {
2545 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
2546 free(mCodecSpecificData.editItemAt(i));
2547 }
2548 mCodecSpecificData.clear();
2549 mCodecSpecificDataIndex = 0;
2550}
2551
James Dong36e573b2010-06-19 09:04:18 -07002552status_t OMXCodec::start(MetaData *meta) {
Andreas Huber42978e52009-08-27 10:08:39 -07002553 Mutex::Autolock autoLock(mLock);
2554
Andreas Huberbe06d262009-08-14 14:37:10 -07002555 if (mState != LOADED) {
2556 return UNKNOWN_ERROR;
2557 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07002558
Andreas Huberbe06d262009-08-14 14:37:10 -07002559 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07002560 if (mQuirks & kWantsNALFragments) {
2561 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07002562 }
James Dong36e573b2010-06-19 09:04:18 -07002563 if (meta) {
2564 int64_t startTimeUs = 0;
2565 int64_t timeUs;
2566 if (meta->findInt64(kKeyTime, &timeUs)) {
2567 startTimeUs = timeUs;
2568 }
2569 params->setInt64(kKeyTime, startTimeUs);
2570 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002571 status_t err = mSource->start(params.get());
2572
2573 if (err != OK) {
2574 return err;
2575 }
2576
2577 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07002578 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002579 mSignalledEOS = false;
2580 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07002581 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002582 mSeekTimeUs = -1;
2583 mFilledBuffers.clear();
Andreas Huber1f24b302010-06-10 11:12:39 -07002584 mPaused = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002585
2586 return init();
2587}
2588
2589status_t OMXCodec::stop() {
Andreas Huber4a9375e2010-02-09 11:54:33 -08002590 CODEC_LOGV("stop mState=%d", mState);
Andreas Huberbe06d262009-08-14 14:37:10 -07002591
2592 Mutex::Autolock autoLock(mLock);
2593
2594 while (isIntermediateState(mState)) {
2595 mAsyncCompletion.wait(mLock);
2596 }
2597
2598 switch (mState) {
2599 case LOADED:
2600 case ERROR:
2601 break;
2602
2603 case EXECUTING:
2604 {
2605 setState(EXECUTING_TO_IDLE);
2606
Andreas Huber127fcdc2009-08-26 16:27:02 -07002607 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07002608 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07002609 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07002610
Andreas Huber127fcdc2009-08-26 16:27:02 -07002611 bool emulateInputFlushCompletion =
2612 !flushPortAsync(kPortIndexInput);
2613
2614 bool emulateOutputFlushCompletion =
2615 !flushPortAsync(kPortIndexOutput);
2616
2617 if (emulateInputFlushCompletion) {
2618 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2619 }
2620
2621 if (emulateOutputFlushCompletion) {
2622 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2623 }
2624 } else {
2625 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2626 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2627
2628 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002629 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002630 CHECK_EQ(err, OK);
2631 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002632
2633 while (mState != LOADED && mState != ERROR) {
2634 mAsyncCompletion.wait(mLock);
2635 }
2636
2637 break;
2638 }
2639
2640 default:
2641 {
2642 CHECK(!"should not be here.");
2643 break;
2644 }
2645 }
2646
Andreas Hubera4357ad2010-04-02 12:49:54 -07002647 if (mLeftOverBuffer) {
2648 mLeftOverBuffer->release();
2649 mLeftOverBuffer = NULL;
2650 }
2651
Andreas Huberbe06d262009-08-14 14:37:10 -07002652 mSource->stop();
2653
Andreas Huber4a9375e2010-02-09 11:54:33 -08002654 CODEC_LOGV("stopped");
2655
Andreas Huberbe06d262009-08-14 14:37:10 -07002656 return OK;
2657}
2658
2659sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07002660 Mutex::Autolock autoLock(mLock);
2661
Andreas Huberbe06d262009-08-14 14:37:10 -07002662 return mOutputFormat;
2663}
2664
2665status_t OMXCodec::read(
2666 MediaBuffer **buffer, const ReadOptions *options) {
2667 *buffer = NULL;
2668
2669 Mutex::Autolock autoLock(mLock);
2670
Andreas Huberd06e5b82009-08-28 13:18:14 -07002671 if (mState != EXECUTING && mState != RECONFIGURING) {
2672 return UNKNOWN_ERROR;
2673 }
2674
Andreas Hubere981c332009-10-22 13:49:30 -07002675 bool seeking = false;
2676 int64_t seekTimeUs;
2677 if (options && options->getSeekTo(&seekTimeUs)) {
2678 seeking = true;
2679 }
2680
Andreas Huber42978e52009-08-27 10:08:39 -07002681 if (mInitialBufferSubmit) {
2682 mInitialBufferSubmit = false;
2683
Andreas Hubere981c332009-10-22 13:49:30 -07002684 if (seeking) {
2685 CHECK(seekTimeUs >= 0);
2686 mSeekTimeUs = seekTimeUs;
2687
2688 // There's no reason to trigger the code below, there's
2689 // nothing to flush yet.
2690 seeking = false;
Andreas Huber1f24b302010-06-10 11:12:39 -07002691 mPaused = false;
Andreas Hubere981c332009-10-22 13:49:30 -07002692 }
2693
Andreas Huber42978e52009-08-27 10:08:39 -07002694 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07002695
Andreas Huberd06e5b82009-08-28 13:18:14 -07002696 if (mState == EXECUTING) {
2697 // Otherwise mState == RECONFIGURING and this code will trigger
2698 // after the output port is reenabled.
2699 fillOutputBuffers();
2700 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002701 }
2702
Andreas Hubere981c332009-10-22 13:49:30 -07002703 if (seeking) {
Andreas Huber4c483422009-09-02 16:05:36 -07002704 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07002705
2706 mSignalledEOS = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002707
2708 CHECK(seekTimeUs >= 0);
2709 mSeekTimeUs = seekTimeUs;
2710
2711 mFilledBuffers.clear();
2712
2713 CHECK_EQ(mState, EXECUTING);
2714
Andreas Huber404cc412009-08-25 14:26:05 -07002715 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
2716 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
2717
2718 if (emulateInputFlushCompletion) {
2719 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2720 }
2721
2722 if (emulateOutputFlushCompletion) {
2723 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2724 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08002725
2726 while (mSeekTimeUs >= 0) {
2727 mBufferFilled.wait(mLock);
2728 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002729 }
2730
2731 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
2732 mBufferFilled.wait(mLock);
2733 }
2734
2735 if (mState == ERROR) {
2736 return UNKNOWN_ERROR;
2737 }
2738
2739 if (mFilledBuffers.empty()) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08002740 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
Andreas Huberbe06d262009-08-14 14:37:10 -07002741 }
2742
Andreas Hubercfd55572009-10-09 14:11:28 -07002743 if (mOutputPortSettingsHaveChanged) {
2744 mOutputPortSettingsHaveChanged = false;
2745
2746 return INFO_FORMAT_CHANGED;
2747 }
2748
Andreas Huberbe06d262009-08-14 14:37:10 -07002749 size_t index = *mFilledBuffers.begin();
2750 mFilledBuffers.erase(mFilledBuffers.begin());
2751
2752 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2753 info->mMediaBuffer->add_ref();
2754 *buffer = info->mMediaBuffer;
2755
2756 return OK;
2757}
2758
2759void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
2760 Mutex::Autolock autoLock(mLock);
2761
2762 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2763 for (size_t i = 0; i < buffers->size(); ++i) {
2764 BufferInfo *info = &buffers->editItemAt(i);
2765
2766 if (info->mMediaBuffer == buffer) {
2767 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
2768 fillOutputBuffer(info);
2769 return;
2770 }
2771 }
2772
2773 CHECK(!"should not be here.");
2774}
2775
2776static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
2777 static const char *kNames[] = {
2778 "OMX_IMAGE_CodingUnused",
2779 "OMX_IMAGE_CodingAutoDetect",
2780 "OMX_IMAGE_CodingJPEG",
2781 "OMX_IMAGE_CodingJPEG2K",
2782 "OMX_IMAGE_CodingEXIF",
2783 "OMX_IMAGE_CodingTIFF",
2784 "OMX_IMAGE_CodingGIF",
2785 "OMX_IMAGE_CodingPNG",
2786 "OMX_IMAGE_CodingLZW",
2787 "OMX_IMAGE_CodingBMP",
2788 };
2789
2790 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2791
2792 if (type < 0 || (size_t)type >= numNames) {
2793 return "UNKNOWN";
2794 } else {
2795 return kNames[type];
2796 }
2797}
2798
2799static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
2800 static const char *kNames[] = {
2801 "OMX_COLOR_FormatUnused",
2802 "OMX_COLOR_FormatMonochrome",
2803 "OMX_COLOR_Format8bitRGB332",
2804 "OMX_COLOR_Format12bitRGB444",
2805 "OMX_COLOR_Format16bitARGB4444",
2806 "OMX_COLOR_Format16bitARGB1555",
2807 "OMX_COLOR_Format16bitRGB565",
2808 "OMX_COLOR_Format16bitBGR565",
2809 "OMX_COLOR_Format18bitRGB666",
2810 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07002811 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07002812 "OMX_COLOR_Format24bitRGB888",
2813 "OMX_COLOR_Format24bitBGR888",
2814 "OMX_COLOR_Format24bitARGB1887",
2815 "OMX_COLOR_Format25bitARGB1888",
2816 "OMX_COLOR_Format32bitBGRA8888",
2817 "OMX_COLOR_Format32bitARGB8888",
2818 "OMX_COLOR_FormatYUV411Planar",
2819 "OMX_COLOR_FormatYUV411PackedPlanar",
2820 "OMX_COLOR_FormatYUV420Planar",
2821 "OMX_COLOR_FormatYUV420PackedPlanar",
2822 "OMX_COLOR_FormatYUV420SemiPlanar",
2823 "OMX_COLOR_FormatYUV422Planar",
2824 "OMX_COLOR_FormatYUV422PackedPlanar",
2825 "OMX_COLOR_FormatYUV422SemiPlanar",
2826 "OMX_COLOR_FormatYCbYCr",
2827 "OMX_COLOR_FormatYCrYCb",
2828 "OMX_COLOR_FormatCbYCrY",
2829 "OMX_COLOR_FormatCrYCbY",
2830 "OMX_COLOR_FormatYUV444Interleaved",
2831 "OMX_COLOR_FormatRawBayer8bit",
2832 "OMX_COLOR_FormatRawBayer10bit",
2833 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07002834 "OMX_COLOR_FormatL2",
2835 "OMX_COLOR_FormatL4",
2836 "OMX_COLOR_FormatL8",
2837 "OMX_COLOR_FormatL16",
2838 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07002839 "OMX_COLOR_FormatL32",
2840 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
2841 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
2842 "OMX_COLOR_Format18BitBGR666",
2843 "OMX_COLOR_Format24BitARGB6666",
2844 "OMX_COLOR_Format24BitABGR6666",
2845 };
2846
2847 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2848
Andreas Huberbe06d262009-08-14 14:37:10 -07002849 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
2850 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
2851 } else if (type < 0 || (size_t)type >= numNames) {
2852 return "UNKNOWN";
2853 } else {
2854 return kNames[type];
2855 }
2856}
2857
2858static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
2859 static const char *kNames[] = {
2860 "OMX_VIDEO_CodingUnused",
2861 "OMX_VIDEO_CodingAutoDetect",
2862 "OMX_VIDEO_CodingMPEG2",
2863 "OMX_VIDEO_CodingH263",
2864 "OMX_VIDEO_CodingMPEG4",
2865 "OMX_VIDEO_CodingWMV",
2866 "OMX_VIDEO_CodingRV",
2867 "OMX_VIDEO_CodingAVC",
2868 "OMX_VIDEO_CodingMJPEG",
2869 };
2870
2871 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2872
2873 if (type < 0 || (size_t)type >= numNames) {
2874 return "UNKNOWN";
2875 } else {
2876 return kNames[type];
2877 }
2878}
2879
2880static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2881 static const char *kNames[] = {
2882 "OMX_AUDIO_CodingUnused",
2883 "OMX_AUDIO_CodingAutoDetect",
2884 "OMX_AUDIO_CodingPCM",
2885 "OMX_AUDIO_CodingADPCM",
2886 "OMX_AUDIO_CodingAMR",
2887 "OMX_AUDIO_CodingGSMFR",
2888 "OMX_AUDIO_CodingGSMEFR",
2889 "OMX_AUDIO_CodingGSMHR",
2890 "OMX_AUDIO_CodingPDCFR",
2891 "OMX_AUDIO_CodingPDCEFR",
2892 "OMX_AUDIO_CodingPDCHR",
2893 "OMX_AUDIO_CodingTDMAFR",
2894 "OMX_AUDIO_CodingTDMAEFR",
2895 "OMX_AUDIO_CodingQCELP8",
2896 "OMX_AUDIO_CodingQCELP13",
2897 "OMX_AUDIO_CodingEVRC",
2898 "OMX_AUDIO_CodingSMV",
2899 "OMX_AUDIO_CodingG711",
2900 "OMX_AUDIO_CodingG723",
2901 "OMX_AUDIO_CodingG726",
2902 "OMX_AUDIO_CodingG729",
2903 "OMX_AUDIO_CodingAAC",
2904 "OMX_AUDIO_CodingMP3",
2905 "OMX_AUDIO_CodingSBC",
2906 "OMX_AUDIO_CodingVORBIS",
2907 "OMX_AUDIO_CodingWMA",
2908 "OMX_AUDIO_CodingRA",
2909 "OMX_AUDIO_CodingMIDI",
2910 };
2911
2912 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2913
2914 if (type < 0 || (size_t)type >= numNames) {
2915 return "UNKNOWN";
2916 } else {
2917 return kNames[type];
2918 }
2919}
2920
2921static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2922 static const char *kNames[] = {
2923 "OMX_AUDIO_PCMModeLinear",
2924 "OMX_AUDIO_PCMModeALaw",
2925 "OMX_AUDIO_PCMModeMULaw",
2926 };
2927
2928 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2929
2930 if (type < 0 || (size_t)type >= numNames) {
2931 return "UNKNOWN";
2932 } else {
2933 return kNames[type];
2934 }
2935}
2936
Andreas Huber7ae02c82009-09-09 16:29:47 -07002937static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
2938 static const char *kNames[] = {
2939 "OMX_AUDIO_AMRBandModeUnused",
2940 "OMX_AUDIO_AMRBandModeNB0",
2941 "OMX_AUDIO_AMRBandModeNB1",
2942 "OMX_AUDIO_AMRBandModeNB2",
2943 "OMX_AUDIO_AMRBandModeNB3",
2944 "OMX_AUDIO_AMRBandModeNB4",
2945 "OMX_AUDIO_AMRBandModeNB5",
2946 "OMX_AUDIO_AMRBandModeNB6",
2947 "OMX_AUDIO_AMRBandModeNB7",
2948 "OMX_AUDIO_AMRBandModeWB0",
2949 "OMX_AUDIO_AMRBandModeWB1",
2950 "OMX_AUDIO_AMRBandModeWB2",
2951 "OMX_AUDIO_AMRBandModeWB3",
2952 "OMX_AUDIO_AMRBandModeWB4",
2953 "OMX_AUDIO_AMRBandModeWB5",
2954 "OMX_AUDIO_AMRBandModeWB6",
2955 "OMX_AUDIO_AMRBandModeWB7",
2956 "OMX_AUDIO_AMRBandModeWB8",
2957 };
2958
2959 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2960
2961 if (type < 0 || (size_t)type >= numNames) {
2962 return "UNKNOWN";
2963 } else {
2964 return kNames[type];
2965 }
2966}
2967
2968static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
2969 static const char *kNames[] = {
2970 "OMX_AUDIO_AMRFrameFormatConformance",
2971 "OMX_AUDIO_AMRFrameFormatIF1",
2972 "OMX_AUDIO_AMRFrameFormatIF2",
2973 "OMX_AUDIO_AMRFrameFormatFSF",
2974 "OMX_AUDIO_AMRFrameFormatRTPPayload",
2975 "OMX_AUDIO_AMRFrameFormatITU",
2976 };
2977
2978 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2979
2980 if (type < 0 || (size_t)type >= numNames) {
2981 return "UNKNOWN";
2982 } else {
2983 return kNames[type];
2984 }
2985}
Andreas Huberbe06d262009-08-14 14:37:10 -07002986
2987void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2988 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07002989 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07002990 def.nPortIndex = portIndex;
2991
Andreas Huber784202e2009-10-15 13:46:54 -07002992 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07002993 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2994 CHECK_EQ(err, OK);
2995
2996 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2997
2998 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2999 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
3000
3001 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
3002 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
3003 printf(" nBufferSize = %ld\n", def.nBufferSize);
3004
3005 switch (def.eDomain) {
3006 case OMX_PortDomainImage:
3007 {
3008 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3009
3010 printf("\n");
3011 printf(" // Image\n");
3012 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
3013 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
3014 printf(" nStride = %ld\n", imageDef->nStride);
3015
3016 printf(" eCompressionFormat = %s\n",
3017 imageCompressionFormatString(imageDef->eCompressionFormat));
3018
3019 printf(" eColorFormat = %s\n",
3020 colorFormatString(imageDef->eColorFormat));
3021
3022 break;
3023 }
3024
3025 case OMX_PortDomainVideo:
3026 {
3027 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3028
3029 printf("\n");
3030 printf(" // Video\n");
3031 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
3032 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
3033 printf(" nStride = %ld\n", videoDef->nStride);
3034
3035 printf(" eCompressionFormat = %s\n",
3036 videoCompressionFormatString(videoDef->eCompressionFormat));
3037
3038 printf(" eColorFormat = %s\n",
3039 colorFormatString(videoDef->eColorFormat));
3040
3041 break;
3042 }
3043
3044 case OMX_PortDomainAudio:
3045 {
3046 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3047
3048 printf("\n");
3049 printf(" // Audio\n");
3050 printf(" eEncoding = %s\n",
3051 audioCodingTypeString(audioDef->eEncoding));
3052
3053 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
3054 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07003055 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07003056 params.nPortIndex = portIndex;
3057
Andreas Huber784202e2009-10-15 13:46:54 -07003058 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003059 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3060 CHECK_EQ(err, OK);
3061
3062 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
3063 printf(" nChannels = %ld\n", params.nChannels);
3064 printf(" bInterleaved = %d\n", params.bInterleaved);
3065 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
3066
3067 printf(" eNumData = %s\n",
3068 params.eNumData == OMX_NumericalDataSigned
3069 ? "signed" : "unsigned");
3070
3071 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07003072 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
3073 OMX_AUDIO_PARAM_AMRTYPE amr;
3074 InitOMXParams(&amr);
3075 amr.nPortIndex = portIndex;
3076
Andreas Huber784202e2009-10-15 13:46:54 -07003077 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07003078 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
3079 CHECK_EQ(err, OK);
3080
3081 printf(" nChannels = %ld\n", amr.nChannels);
3082 printf(" eAMRBandMode = %s\n",
3083 amrBandModeString(amr.eAMRBandMode));
3084 printf(" eAMRFrameFormat = %s\n",
3085 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07003086 }
3087
3088 break;
3089 }
3090
3091 default:
3092 {
3093 printf(" // Unknown\n");
3094 break;
3095 }
3096 }
3097
3098 printf("}\n");
3099}
3100
3101void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
3102 mOutputFormat = new MetaData;
3103 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
3104
3105 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003106 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003107 def.nPortIndex = kPortIndexOutput;
3108
Andreas Huber784202e2009-10-15 13:46:54 -07003109 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003110 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3111 CHECK_EQ(err, OK);
3112
3113 switch (def.eDomain) {
3114 case OMX_PortDomainImage:
3115 {
3116 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3117 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
3118
Andreas Hubere6c40962009-09-10 14:13:30 -07003119 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07003120 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
3121 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
3122 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
3123 break;
3124 }
3125
3126 case OMX_PortDomainAudio:
3127 {
3128 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
3129
Andreas Huberda050cf22009-09-02 14:01:43 -07003130 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
3131 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07003132 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07003133 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003134
Andreas Huber784202e2009-10-15 13:46:54 -07003135 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003136 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3137 CHECK_EQ(err, OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003138
Andreas Huberda050cf22009-09-02 14:01:43 -07003139 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
3140 CHECK_EQ(params.nBitPerSample, 16);
3141 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07003142
Andreas Huberda050cf22009-09-02 14:01:43 -07003143 int32_t numChannels, sampleRate;
3144 inputFormat->findInt32(kKeyChannelCount, &numChannels);
3145 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07003146
Andreas Huberda050cf22009-09-02 14:01:43 -07003147 if ((OMX_U32)numChannels != params.nChannels) {
3148 LOGW("Codec outputs a different number of channels than "
Andreas Hubere331c7b2010-02-01 10:51:50 -08003149 "the input stream contains (contains %d channels, "
3150 "codec outputs %ld channels).",
3151 numChannels, params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07003152 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003153
Andreas Hubere6c40962009-09-10 14:13:30 -07003154 mOutputFormat->setCString(
3155 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07003156
3157 // Use the codec-advertised number of channels, as some
3158 // codecs appear to output stereo even if the input data is
Andreas Hubere331c7b2010-02-01 10:51:50 -08003159 // mono. If we know the codec lies about this information,
3160 // use the actual number of channels instead.
3161 mOutputFormat->setInt32(
3162 kKeyChannelCount,
3163 (mQuirks & kDecoderLiesAboutNumberOfChannels)
3164 ? numChannels : params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07003165
3166 // The codec-reported sampleRate is not reliable...
3167 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
3168 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07003169 OMX_AUDIO_PARAM_AMRTYPE amr;
3170 InitOMXParams(&amr);
3171 amr.nPortIndex = kPortIndexOutput;
3172
Andreas Huber784202e2009-10-15 13:46:54 -07003173 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07003174 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
3175 CHECK_EQ(err, OK);
3176
3177 CHECK_EQ(amr.nChannels, 1);
3178 mOutputFormat->setInt32(kKeyChannelCount, 1);
3179
3180 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
3181 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003182 mOutputFormat->setCString(
3183 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07003184 mOutputFormat->setInt32(kKeySampleRate, 8000);
3185 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
3186 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003187 mOutputFormat->setCString(
3188 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07003189 mOutputFormat->setInt32(kKeySampleRate, 16000);
3190 } else {
3191 CHECK(!"Unknown AMR band mode.");
3192 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003193 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003194 mOutputFormat->setCString(
3195 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
James Dong17299ab2010-05-14 15:45:22 -07003196 int32_t numChannels, sampleRate, bitRate;
James Dongabed93a2010-04-22 17:27:04 -07003197 inputFormat->findInt32(kKeyChannelCount, &numChannels);
3198 inputFormat->findInt32(kKeySampleRate, &sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07003199 inputFormat->findInt32(kKeyBitRate, &bitRate);
James Dongabed93a2010-04-22 17:27:04 -07003200 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
3201 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07003202 mOutputFormat->setInt32(kKeyBitRate, bitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07003203 } else {
3204 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07003205 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003206 break;
3207 }
3208
3209 case OMX_PortDomainVideo:
3210 {
3211 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3212
3213 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003214 mOutputFormat->setCString(
3215 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07003216 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003217 mOutputFormat->setCString(
3218 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07003219 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003220 mOutputFormat->setCString(
3221 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07003222 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07003223 mOutputFormat->setCString(
3224 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07003225 } else {
3226 CHECK(!"Unknown compression format.");
3227 }
3228
3229 if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
3230 // This component appears to be lying to me.
3231 mOutputFormat->setInt32(
3232 kKeyWidth, (video_def->nFrameWidth + 15) & -16);
3233 mOutputFormat->setInt32(
3234 kKeyHeight, (video_def->nFrameHeight + 15) & -16);
3235 } else {
3236 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
3237 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
3238 }
3239
3240 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
3241 break;
3242 }
3243
3244 default:
3245 {
3246 CHECK(!"should not be here, neither audio nor video.");
3247 break;
3248 }
3249 }
3250}
3251
Andreas Huber1f24b302010-06-10 11:12:39 -07003252status_t OMXCodec::pause() {
3253 Mutex::Autolock autoLock(mLock);
3254
3255 mPaused = true;
3256
3257 return OK;
3258}
3259
Andreas Hubere6c40962009-09-10 14:13:30 -07003260////////////////////////////////////////////////////////////////////////////////
3261
3262status_t QueryCodecs(
3263 const sp<IOMX> &omx,
3264 const char *mime, bool queryDecoders,
3265 Vector<CodecCapabilities> *results) {
3266 results->clear();
3267
3268 for (int index = 0;; ++index) {
3269 const char *componentName;
3270
3271 if (!queryDecoders) {
3272 componentName = GetCodec(
3273 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
3274 mime, index);
3275 } else {
3276 componentName = GetCodec(
3277 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
3278 mime, index);
3279 }
3280
3281 if (!componentName) {
3282 return OK;
3283 }
3284
Andreas Huber1a189a82010-03-24 13:49:20 -07003285 if (strncmp(componentName, "OMX.", 4)) {
3286 // Not an OpenMax component but a software codec.
3287
3288 results->push();
3289 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3290 caps->mComponentName = componentName;
3291
3292 continue;
3293 }
3294
Andreas Huber784202e2009-10-15 13:46:54 -07003295 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07003296 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07003297 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07003298
3299 if (err != OK) {
3300 continue;
3301 }
3302
James Dong722d5912010-04-13 10:56:59 -07003303 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
Andreas Hubere6c40962009-09-10 14:13:30 -07003304
3305 results->push();
3306 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3307 caps->mComponentName = componentName;
3308
3309 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
3310 InitOMXParams(&param);
3311
3312 param.nPortIndex = queryDecoders ? 0 : 1;
3313
3314 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07003315 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07003316 node, OMX_IndexParamVideoProfileLevelQuerySupported,
3317 &param, sizeof(param));
3318
3319 if (err != OK) {
3320 break;
3321 }
3322
3323 CodecProfileLevel profileLevel;
3324 profileLevel.mProfile = param.eProfile;
3325 profileLevel.mLevel = param.eLevel;
3326
3327 caps->mProfileLevels.push(profileLevel);
3328 }
3329
Andreas Huber784202e2009-10-15 13:46:54 -07003330 CHECK_EQ(omx->freeNode(node), OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07003331 }
3332}
3333
Andreas Huberbe06d262009-08-14 14:37:10 -07003334} // namespace android