blob: f9f92d2624925e45462d07f80d29f303de4c5136 [file] [log] [blame]
Andreas Huberbe06d262009-08-14 14:37:10 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXCodec"
19#include <utils/Log.h>
20
James Dong17299ab2010-05-14 15:45:22 -070021#include "include/AACEncoder.h"
Andreas Huberd49b526dd2009-12-11 15:07:25 -080022#include "include/AMRNBEncoder.h"
James Dong17299ab2010-05-14 15:45:22 -070023#include "include/AMRWBEncoder.h"
James Dong1cc31e62010-07-02 17:44:44 -070024#include "include/AVCEncoder.h"
James Dong42ef0c72010-07-12 21:46:25 -070025#include "include/M4vH263Encoder.h"
Andreas Huber8c7ab032009-12-07 11:23:44 -080026
Andreas Huberbd7b43b2009-10-13 10:22:55 -070027#include "include/ESDS.h"
28
Andreas Huberbe06d262009-08-14 14:37:10 -070029#include <binder/IServiceManager.h>
30#include <binder/MemoryDealer.h>
31#include <binder/ProcessState.h>
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080032#include <media/stagefright/foundation/ADebug.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070033#include <media/IMediaPlayerService.h>
Jamie Gennis58a36ad2010-10-07 14:08:38 -070034#include <media/stagefright/HardwareAPI.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070035#include <media/stagefright/MediaBuffer.h>
36#include <media/stagefright/MediaBufferGroup.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070037#include <media/stagefright/MediaDefs.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070038#include <media/stagefright/MediaExtractor.h>
39#include <media/stagefright/MetaData.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070040#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070041#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070042#include <utils/Vector.h>
43
44#include <OMX_Audio.h>
45#include <OMX_Component.h>
46
Andreas Huberf7e2e312010-11-15 09:01:13 -080047#include "include/avc_utils.h"
Andreas Huber8946ab22010-09-15 16:20:42 -070048
Andreas Huberbe06d262009-08-14 14:37:10 -070049namespace android {
50
James Dongd9ac6212011-07-15 15:25:36 -070051// Treat time out as an error if we have not received any output
52// buffers after 3 seconds.
James Dong4a0c91f2011-09-09 13:19:59 -070053const static int64_t kBufferFilledEventTimeOutNs = 3000000000LL;
James Dongd9ac6212011-07-15 15:25:36 -070054
James Dong5a37afa2011-10-18 16:21:52 -070055// OMX Spec defines less than 50 color formats. If the query for
56// color format is executed for more than kMaxColorFormatSupported,
57// the query will fail to avoid looping forever.
58// 1000 is more than enough for us to tell whether the omx
59// component in question is buggy or not.
60const static uint32_t kMaxColorFormatSupported = 1000;
61
Andreas Huberbe06d262009-08-14 14:37:10 -070062struct CodecInfo {
63 const char *mime;
64 const char *codec;
65};
66
James Dong17299ab2010-05-14 15:45:22 -070067#define FACTORY_CREATE_ENCODER(name) \
68static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
69 return new name(source, meta); \
70}
71
Andreas Huberfb1c2f82009-12-15 13:25:11 -080072#define FACTORY_REF(name) { #name, Make##name },
73
James Dong17299ab2010-05-14 15:45:22 -070074FACTORY_CREATE_ENCODER(AMRNBEncoder)
75FACTORY_CREATE_ENCODER(AMRWBEncoder)
76FACTORY_CREATE_ENCODER(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070077FACTORY_CREATE_ENCODER(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070078FACTORY_CREATE_ENCODER(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070079
80static sp<MediaSource> InstantiateSoftwareEncoder(
81 const char *name, const sp<MediaSource> &source,
82 const sp<MetaData> &meta) {
83 struct FactoryInfo {
84 const char *name;
85 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
86 };
87
88 static const FactoryInfo kFactoryInfo[] = {
89 FACTORY_REF(AMRNBEncoder)
90 FACTORY_REF(AMRWBEncoder)
91 FACTORY_REF(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070092 FACTORY_REF(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070093 FACTORY_REF(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070094 };
95 for (size_t i = 0;
96 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
97 if (!strcmp(name, kFactoryInfo[i].name)) {
98 return (*kFactoryInfo[i].CreateFunc)(source, meta);
99 }
100 }
101
102 return NULL;
103}
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800104
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800105#undef FACTORY_REF
106#undef FACTORY_CREATE
107
Andreas Huberbe06d262009-08-14 14:37:10 -0700108static const CodecInfo kDecoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700109 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
James Dong374aee62010-04-26 10:23:30 -0700110// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700111 { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
Andreas Huberbc554952011-09-08 14:12:44 -0700112 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, "OMX.Nvidia.mp2.decoder" },
Andreas Hubera4357ad2010-04-02 12:49:54 -0700113// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
Andreas Huberd222c842010-08-26 14:29:34 -0700114// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700115 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" },
Andreas Huberd222c842010-08-26 14:29:34 -0700116// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700117 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700118 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
Andreas Huberd222c842010-08-26 14:29:34 -0700119// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700120 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700121 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700122 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700123 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
Anu Sundararajand35df442011-06-22 12:24:46 -0500124 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
Andreas Huber9f9ae602010-10-27 14:53:55 -0700125 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700126 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700127 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
128 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700129 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700130 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
Anu Sundararajand35df442011-06-22 12:24:46 -0500131 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
Andreas Huber9f9ae602010-10-27 14:53:55 -0700132 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700133 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700134 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700135 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700136 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
Anu Sundararajand35df442011-06-22 12:24:46 -0500137 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
pgudadhe6ad2c352010-07-26 15:04:33 -0700138 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700139 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700140 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
141 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700142 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
James Dongbebc99d2011-05-31 18:53:46 -0700143 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.h264.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700144 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700145 { MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700146 { MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
Andreas Hubereb2f9c12011-05-19 08:37:39 -0700147 { MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700148};
149
150static const CodecInfo kEncoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700151 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800152 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700153 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700154 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700155 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700156 { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
Dandawate Sakete641dc52011-07-11 19:12:57 -0700157 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700158 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700159 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
160 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
James Dong2e87f7b2010-09-23 17:46:34 -0700161 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700162 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700163 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
Dandawate Sakete641dc52011-07-11 19:12:57 -0700164 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700165 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700166 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
167 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
James Dong2e87f7b2010-09-23 17:46:34 -0700168 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700169 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700170 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
Dandawate Sakete641dc52011-07-11 19:12:57 -0700171 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.H264E" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700172 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
Andreas Huber71c27d92010-03-19 11:43:15 -0700173 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700174 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
pgudadhe9c305322010-07-26 13:59:29 -0700175 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700176 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Encoder" },
James Dong1cc31e62010-07-02 17:44:44 -0700177 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700178};
179
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800180#undef OPTIONAL
181
Andreas Hubere0873732009-09-10 09:57:53 -0700182#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Steve Block71f2cf12011-10-20 11:56:00 +0100183#define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber42c444a2010-02-09 10:20:00 -0800184#define CODEC_LOGE(x, ...) LOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700185
Andreas Huberbe06d262009-08-14 14:37:10 -0700186struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -0700187 OMXCodecObserver() {
188 }
189
190 void setCodec(const sp<OMXCodec> &target) {
191 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -0700192 }
193
194 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -0700195 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700196 sp<OMXCodec> codec = mTarget.promote();
197
198 if (codec.get() != NULL) {
James Dong681e89c2011-01-10 08:55:02 -0800199 Mutex::Autolock autoLock(codec->mLock);
Andreas Huberbe06d262009-08-14 14:37:10 -0700200 codec->on_message(msg);
James Dong681e89c2011-01-10 08:55:02 -0800201 codec.clear();
Andreas Huberbe06d262009-08-14 14:37:10 -0700202 }
203 }
204
205protected:
206 virtual ~OMXCodecObserver() {}
207
208private:
209 wp<OMXCodec> mTarget;
210
211 OMXCodecObserver(const OMXCodecObserver &);
212 OMXCodecObserver &operator=(const OMXCodecObserver &);
213};
214
215static const char *GetCodec(const CodecInfo *info, size_t numInfos,
216 const char *mime, int index) {
217 CHECK(index >= 0);
218 for(size_t i = 0; i < numInfos; ++i) {
219 if (!strcasecmp(mime, info[i].mime)) {
220 if (index == 0) {
221 return info[i].codec;
222 }
223
224 --index;
225 }
226 }
227
228 return NULL;
229}
230
Andreas Huber4c483422009-09-02 16:05:36 -0700231template<class T>
232static void InitOMXParams(T *params) {
233 params->nSize = sizeof(T);
234 params->nVersion.s.nVersionMajor = 1;
235 params->nVersion.s.nVersionMinor = 0;
236 params->nVersion.s.nRevision = 0;
237 params->nVersion.s.nStep = 0;
238}
239
Andreas Hubere13526a2009-10-22 10:43:34 -0700240static bool IsSoftwareCodec(const char *componentName) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700241 if (!strncmp("OMX.google.", componentName, 11)) {
242 return true;
243 }
244
James Dong5592bcc2010-10-22 17:10:43 -0700245 if (!strncmp("OMX.", componentName, 4)) {
246 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -0700247 }
248
James Dong5592bcc2010-10-22 17:10:43 -0700249 return true;
Andreas Hubere13526a2009-10-22 10:43:34 -0700250}
251
Andreas Huber4b3913a2011-05-11 14:13:42 -0700252// A sort order in which OMX software codecs are first, followed
253// by other (non-OMX) software codecs, followed by everything else.
Andreas Hubere13526a2009-10-22 10:43:34 -0700254static int CompareSoftwareCodecsFirst(
255 const String8 *elem1, const String8 *elem2) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700256 bool isOMX1 = !strncmp(elem1->string(), "OMX.", 4);
257 bool isOMX2 = !strncmp(elem2->string(), "OMX.", 4);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800258
Andreas Hubere13526a2009-10-22 10:43:34 -0700259 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
260 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
261
262 if (isSoftwareCodec1) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700263 if (!isSoftwareCodec2) { return -1; }
264
265 if (isOMX1) {
266 if (isOMX2) { return 0; }
267
268 return -1;
269 } else {
270 if (isOMX2) { return 0; }
271
272 return 1;
273 }
274
Andreas Hubere13526a2009-10-22 10:43:34 -0700275 return -1;
276 }
277
278 if (isSoftwareCodec2) {
279 return 1;
280 }
281
282 return 0;
283}
284
285// static
Andreas Huber1e194162010-10-06 16:43:57 -0700286uint32_t OMXCodec::getComponentQuirks(
287 const char *componentName, bool isEncoder) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700288 uint32_t quirks = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700289
Dima Zavin30ba6cb2010-08-23 11:10:03 -0700290 if (!strcmp(componentName, "OMX.Nvidia.amr.decoder") ||
291 !strcmp(componentName, "OMX.Nvidia.amrwb.decoder") ||
292 !strcmp(componentName, "OMX.Nvidia.aac.decoder") ||
293 !strcmp(componentName, "OMX.Nvidia.mp3.decoder")) {
294 quirks |= kDecoderLiesAboutNumberOfChannels;
295 }
296
Andreas Huberbe06d262009-08-14 14:37:10 -0700297 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
298 quirks |= kNeedsFlushBeforeDisable;
Andreas Hubere331c7b2010-02-01 10:51:50 -0800299 quirks |= kDecoderLiesAboutNumberOfChannels;
Andreas Huberbe06d262009-08-14 14:37:10 -0700300 }
301 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
302 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700303 quirks |= kRequiresFlushCompleteEmulation;
Andreas Hubera4357ad2010-04-02 12:49:54 -0700304 quirks |= kSupportsMultipleFramesPerInputBuffer;
Andreas Huberbe06d262009-08-14 14:37:10 -0700305 }
306 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
307 quirks |= kRequiresLoadedToIdleAfterAllocation;
308 quirks |= kRequiresAllocateBufferOnInputPorts;
Andreas Huberb482ce82009-10-29 12:02:48 -0700309 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dong90862e22010-08-26 19:12:59 -0700310 if (!strncmp(componentName, "OMX.qcom.video.encoder.avc", 26)) {
311
312 // The AVC encoder advertises the size of output buffers
313 // based on the input video resolution and assumes
314 // the worst/least compression ratio is 0.5. It is found that
315 // sometimes, the output buffer size is larger than
316 // size advertised by the encoder.
317 quirks |= kRequiresLargerEncoderOutputBuffer;
318 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700319 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700320 if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
321 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700322 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700323 quirks |= kRequiresAllocateBufferOnOutputPorts;
Andreas Huber52733b82010-01-25 10:41:35 -0800324 quirks |= kDefersOutputBufferAllocation;
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700325 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700326 if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
327 quirks |= kRequiresAllocateBufferOnInputPorts;
328 quirks |= kRequiresAllocateBufferOnOutputPorts;
329 quirks |= kDefersOutputBufferAllocation;
330 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700331
Anu Sundararajand35df442011-06-22 12:24:46 -0500332 if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) {
333 quirks |= kRequiresAllocateBufferOnInputPorts;
334 quirks |= kRequiresAllocateBufferOnOutputPorts;
Dandawate Sakete641dc52011-07-11 19:12:57 -0700335 }
336
337 // FIXME:
338 // Remove the quirks after the work is done.
339 else if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.MPEG4E") ||
340 !strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.H264E")) {
341
342 quirks |= kRequiresAllocateBufferOnInputPorts;
343 quirks |= kRequiresAllocateBufferOnOutputPorts;
344 }
345 else if (!strncmp(componentName, "OMX.TI.", 7)) {
Andreas Huber2dc64d82009-09-11 12:58:53 -0700346 // Apparently I must not use OMX_UseBuffer on either input or
347 // output ports on any of the TI components or quote:
348 // "(I) may have unexpected problem (sic) which can be timing related
349 // and hard to reproduce."
350
351 quirks |= kRequiresAllocateBufferOnInputPorts;
352 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dongdca66e12010-06-14 11:14:38 -0700353 if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
James Dong4f501f02010-06-07 14:41:41 -0700354 quirks |= kAvoidMemcopyInputRecordingFrames;
355 }
Andreas Huber2dc64d82009-09-11 12:58:53 -0700356 }
357
Andreas Huberb8de9572010-02-22 14:58:45 -0800358 if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
359 quirks |= kInputBufferSizesAreBogus;
360 }
361
Andreas Huber1e194162010-10-06 16:43:57 -0700362 if (!strncmp(componentName, "OMX.SEC.", 8) && !isEncoder) {
363 // These output buffers contain no video data, just some
364 // opaque information that allows the overlay to display their
365 // contents.
366 quirks |= kOutputBuffersAreUnreadable;
367 }
368
Andreas Hubere13526a2009-10-22 10:43:34 -0700369 return quirks;
370}
371
372// static
373void OMXCodec::findMatchingCodecs(
374 const char *mime,
375 bool createEncoder, const char *matchComponentName,
376 uint32_t flags,
377 Vector<String8> *matchingCodecs) {
378 matchingCodecs->clear();
379
380 for (int index = 0;; ++index) {
381 const char *componentName;
382
383 if (createEncoder) {
384 componentName = GetCodec(
385 kEncoderInfo,
386 sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
387 mime, index);
388 } else {
389 componentName = GetCodec(
390 kDecoderInfo,
391 sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
392 mime, index);
393 }
394
395 if (!componentName) {
396 break;
397 }
398
399 // If a specific codec is requested, skip the non-matching ones.
400 if (matchComponentName && strcmp(componentName, matchComponentName)) {
401 continue;
402 }
403
James Dong170a9292010-10-22 17:28:15 -0700404 // When requesting software-only codecs, only push software codecs
405 // When requesting hardware-only codecs, only push hardware codecs
406 // When there is request neither for software-only nor for
407 // hardware-only codecs, push all codecs
408 if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
409 ((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
410 (!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
411
412 matchingCodecs->push(String8(componentName));
413 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700414 }
415
416 if (flags & kPreferSoftwareCodecs) {
417 matchingCodecs->sort(CompareSoftwareCodecsFirst);
418 }
419}
420
421// static
Andreas Huber91eb0352009-12-07 09:43:00 -0800422sp<MediaSource> OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700423 const sp<IOMX> &omx,
424 const sp<MetaData> &meta, bool createEncoder,
425 const sp<MediaSource> &source,
426 const char *matchComponentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700427 uint32_t flags,
428 const sp<ANativeWindow> &nativeWindow) {
Andreas Huber42fb5d62011-06-29 15:53:28 -0700429 int32_t requiresSecureBuffers;
430 if (source->getFormat()->findInt32(
431 kKeyRequiresSecureBuffers,
432 &requiresSecureBuffers)
433 && requiresSecureBuffers) {
434 flags |= kIgnoreCodecSpecificData;
435 flags |= kUseSecureInputBuffers;
436 }
437
Andreas Hubere13526a2009-10-22 10:43:34 -0700438 const char *mime;
439 bool success = meta->findCString(kKeyMIMEType, &mime);
440 CHECK(success);
441
442 Vector<String8> matchingCodecs;
443 findMatchingCodecs(
444 mime, createEncoder, matchComponentName, flags, &matchingCodecs);
445
446 if (matchingCodecs.isEmpty()) {
447 return NULL;
448 }
449
450 sp<OMXCodecObserver> observer = new OMXCodecObserver;
451 IOMX::node_id node = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700452
Andreas Hubere13526a2009-10-22 10:43:34 -0700453 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
Andreas Huber753fd9a2011-08-10 12:53:59 -0700454 const char *componentNameBase = matchingCodecs[i].string();
455 const char *componentName = componentNameBase;
456
457 AString tmp;
458 if (flags & kUseSecureInputBuffers) {
459 tmp = componentNameBase;
460 tmp.append(".secure");
461
462 componentName = tmp.c_str();
463 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700464
Andreas Hubera8ccc502011-07-13 12:38:46 -0700465 if (createEncoder) {
466 sp<MediaSource> softwareCodec =
467 InstantiateSoftwareEncoder(componentName, source, meta);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800468
Andreas Hubera8ccc502011-07-13 12:38:46 -0700469 if (softwareCodec != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100470 ALOGV("Successfully allocated software codec '%s'", componentName);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800471
Andreas Hubera8ccc502011-07-13 12:38:46 -0700472 return softwareCodec;
473 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800474 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800475
Steve Block71f2cf12011-10-20 11:56:00 +0100476 ALOGV("Attempting to allocate OMX node '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700477
Andreas Huber753fd9a2011-08-10 12:53:59 -0700478 uint32_t quirks = getComponentQuirks(componentNameBase, createEncoder);
Andreas Huber5a40e392010-10-18 09:57:42 -0700479
480 if (!createEncoder
481 && (quirks & kOutputBuffersAreUnreadable)
482 && (flags & kClientNeedsFramebuffer)) {
483 if (strncmp(componentName, "OMX.SEC.", 8)) {
484 // For OMX.SEC.* decoders we can enable a special mode that
485 // gives the client access to the framebuffer contents.
486
487 LOGW("Component '%s' does not give the client access to "
488 "the framebuffer contents. Skipping.",
489 componentName);
490
491 continue;
492 }
493 }
494
Andreas Hubere13526a2009-10-22 10:43:34 -0700495 status_t err = omx->allocateNode(componentName, observer, &node);
496 if (err == OK) {
Steve Block71f2cf12011-10-20 11:56:00 +0100497 ALOGV("Successfully allocated OMX node '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700498
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700499 sp<OMXCodec> codec = new OMXCodec(
Andreas Huber42fb5d62011-06-29 15:53:28 -0700500 omx, node, quirks, flags,
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700501 createEncoder, mime, componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700502 source, nativeWindow);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700503
504 observer->setCodec(codec);
505
Andreas Huber42fb5d62011-06-29 15:53:28 -0700506 err = codec->configureCodec(meta);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700507
508 if (err == OK) {
Andreas Hubereb2f9c12011-05-19 08:37:39 -0700509 if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) {
Andreas Huber42fb5d62011-06-29 15:53:28 -0700510 codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime;
Andreas Hubereb2f9c12011-05-19 08:37:39 -0700511 }
512
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700513 return codec;
514 }
515
Steve Block71f2cf12011-10-20 11:56:00 +0100516 ALOGV("Failed to configure codec '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700517 }
518 }
519
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700520 return NULL;
521}
Andreas Hubere13526a2009-10-22 10:43:34 -0700522
Andreas Huber0ba86602011-11-18 12:22:59 -0800523status_t OMXCodec::parseAVCCodecSpecificData(
524 const void *data, size_t size,
525 unsigned *profile, unsigned *level) {
526 const uint8_t *ptr = (const uint8_t *)data;
527
528 // verify minimum size and configurationVersion == 1.
529 if (size < 7 || ptr[0] != 1) {
530 return ERROR_MALFORMED;
531 }
532
533 *profile = ptr[1];
534 *level = ptr[3];
535
536 // There is decodable content out there that fails the following
537 // assertion, let's be lenient for now...
538 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
539
540 size_t lengthSize = 1 + (ptr[4] & 3);
541
542 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
543 // violates it...
544 // CHECK((ptr[5] >> 5) == 7); // reserved
545
546 size_t numSeqParameterSets = ptr[5] & 31;
547
548 ptr += 6;
549 size -= 6;
550
551 for (size_t i = 0; i < numSeqParameterSets; ++i) {
552 if (size < 2) {
553 return ERROR_MALFORMED;
554 }
555
556 size_t length = U16_AT(ptr);
557
558 ptr += 2;
559 size -= 2;
560
561 if (size < length) {
562 return ERROR_MALFORMED;
563 }
564
565 addCodecSpecificData(ptr, length);
566
567 ptr += length;
568 size -= length;
569 }
570
571 if (size < 1) {
572 return ERROR_MALFORMED;
573 }
574
575 size_t numPictureParameterSets = *ptr;
576 ++ptr;
577 --size;
578
579 for (size_t i = 0; i < numPictureParameterSets; ++i) {
580 if (size < 2) {
581 return ERROR_MALFORMED;
582 }
583
584 size_t length = U16_AT(ptr);
585
586 ptr += 2;
587 size -= 2;
588
589 if (size < length) {
590 return ERROR_MALFORMED;
591 }
592
593 addCodecSpecificData(ptr, length);
594
595 ptr += length;
596 size -= length;
597 }
598
599 return OK;
600}
601
Andreas Huber42fb5d62011-06-29 15:53:28 -0700602status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
Steve Block71f2cf12011-10-20 11:56:00 +0100603 ALOGV("configureCodec protected=%d",
Andreas Huber42fb5d62011-06-29 15:53:28 -0700604 (mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
James Dong5f3ab062011-01-25 16:31:28 -0800605
Andreas Huber42fb5d62011-06-29 15:53:28 -0700606 if (!(mFlags & kIgnoreCodecSpecificData)) {
Andreas Huber4c19bf92010-09-08 14:32:20 -0700607 uint32_t type;
608 const void *data;
609 size_t size;
610 if (meta->findData(kKeyESDS, &type, &data, &size)) {
611 ESDS esds((const char *)data, size);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800612 CHECK_EQ(esds.InitCheck(), (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700613
Andreas Huber4c19bf92010-09-08 14:32:20 -0700614 const void *codec_specific_data;
615 size_t codec_specific_data_size;
616 esds.getCodecSpecificInfo(
617 &codec_specific_data, &codec_specific_data_size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700618
Andreas Huber4c19bf92010-09-08 14:32:20 -0700619 addCodecSpecificData(
620 codec_specific_data, codec_specific_data_size);
621 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
622 // Parse the AVCDecoderConfigurationRecord
Andreas Huberebf66ea2009-08-19 13:32:58 -0700623
Andreas Huber0ba86602011-11-18 12:22:59 -0800624 unsigned profile, level;
625 status_t err;
626 if ((err = parseAVCCodecSpecificData(
627 data, size, &profile, &level)) != OK) {
628 LOGE("Malformed AVC codec specific data.");
629 return err;
Andreas Huber4c19bf92010-09-08 14:32:20 -0700630 }
Andreas Huberebf66ea2009-08-19 13:32:58 -0700631
Andreas Huber6ac2cb22010-11-18 14:06:07 -0800632 CODEC_LOGI(
Andreas Huber0ba86602011-11-18 12:22:59 -0800633 "AVC profile = %u (%s), level = %u",
634 profile, AVCProfileToString(profile), level);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700635
Andreas Huber4c19bf92010-09-08 14:32:20 -0700636 if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
637 && (profile != kAVCProfileBaseline || level > 30)) {
638 // This stream exceeds the decoder's capabilities. The decoder
639 // does not handle this gracefully and would clobber the heap
640 // and wreak havoc instead...
Andreas Huberebf66ea2009-08-19 13:32:58 -0700641
Andreas Huber4c19bf92010-09-08 14:32:20 -0700642 LOGE("Profile and/or level exceed the decoder's capabilities.");
643 return ERROR_UNSUPPORTED;
644 }
Andreas Huber4b3913a2011-05-11 14:13:42 -0700645 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
646 addCodecSpecificData(data, size);
647
648 CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
649 addCodecSpecificData(data, size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700650 }
651 }
652
James Dong17299ab2010-05-14 15:45:22 -0700653 int32_t bitRate = 0;
654 if (mIsEncoder) {
655 CHECK(meta->findInt32(kKeyBitRate, &bitRate));
656 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700657 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700658 setAMRFormat(false /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700659 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700660 setAMRFormat(true /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700661 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700662 int32_t numChannels, sampleRate;
663 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
664 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
665
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -0500666 status_t err = setAACFormat(numChannels, sampleRate, bitRate);
667 if (err != OK) {
668 CODEC_LOGE("setAACFormat() failed (err = %d)", err);
669 return err;
670 }
Andreas Huber4b3913a2011-05-11 14:13:42 -0700671 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
672 || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
673 // These are PCM-like formats with a fixed sample rate but
674 // a variable number of channels.
675
676 int32_t numChannels;
677 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
678
679 setG711Format(numChannels);
Andreas Huberbe06d262009-08-14 14:37:10 -0700680 }
James Dongabed93a2010-04-22 17:27:04 -0700681
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700682 if (!strncasecmp(mMIME, "video/", 6)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700683
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700684 if (mIsEncoder) {
James Dong1244eab2010-06-08 11:58:53 -0700685 setVideoInputFormat(mMIME, meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700686 } else {
James Dong1244eab2010-06-08 11:58:53 -0700687 int32_t width, height;
688 bool success = meta->findInt32(kKeyWidth, &width);
689 success = success && meta->findInt32(kKeyHeight, &height);
690 CHECK(success);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700691 status_t err = setVideoOutputFormat(
692 mMIME, width, height);
693
694 if (err != OK) {
695 return err;
696 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700697 }
698 }
Andreas Hubera4357ad2010-04-02 12:49:54 -0700699
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700700 if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
701 && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700702 OMX_COLOR_FORMATTYPE format =
703 OMX_COLOR_Format32bitARGB8888;
704 // OMX_COLOR_FormatYUV420PackedPlanar;
705 // OMX_COLOR_FormatCbYCrY;
706 // OMX_COLOR_FormatYUV411Planar;
707
708 int32_t width, height;
709 bool success = meta->findInt32(kKeyWidth, &width);
710 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700711
712 int32_t compressedSize;
713 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700714 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700715
716 CHECK(success);
717 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700718
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700719 setImageOutputFormat(format, width, height);
720 setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700721 }
722
Andreas Huberda050cf22009-09-02 14:01:43 -0700723 int32_t maxInputSize;
Andreas Huber1bceff92009-11-23 14:03:32 -0800724 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700725 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
Andreas Huberda050cf22009-09-02 14:01:43 -0700726 }
727
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700728 if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
James Dongabed93a2010-04-22 17:27:04 -0700729 || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
730 || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700731 setMinBufferSize(kPortIndexOutput, 8192); // XXX
Andreas Huberda050cf22009-09-02 14:01:43 -0700732 }
733
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700734 initOutputFormat(meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700735
Andreas Huber42fb5d62011-06-29 15:53:28 -0700736 if ((mFlags & kClientNeedsFramebuffer)
Andreas Huber5a40e392010-10-18 09:57:42 -0700737 && !strncmp(mComponentName, "OMX.SEC.", 8)) {
738 OMX_INDEXTYPE index;
739
740 status_t err =
741 mOMX->getExtensionIndex(
742 mNode,
743 "OMX.SEC.index.ThumbnailMode",
744 &index);
745
746 if (err != OK) {
747 return err;
748 }
749
750 OMX_BOOL enable = OMX_TRUE;
751 err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
752
753 if (err != OK) {
754 CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
755 "returned error 0x%08x", err);
756
757 return err;
758 }
759
760 mQuirks &= ~kOutputBuffersAreUnreadable;
761 }
762
Jamie Gennisdbfb32e2010-10-20 15:53:59 -0700763 if (mNativeWindow != NULL
764 && !mIsEncoder
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700765 && !strncasecmp(mMIME, "video/", 6)
766 && !strncmp(mComponentName, "OMX.", 4)) {
767 status_t err = initNativeWindow();
768 if (err != OK) {
769 return err;
770 }
771 }
772
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700773 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700774}
775
Andreas Huberda050cf22009-09-02 14:01:43 -0700776void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
777 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700778 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700779 def.nPortIndex = portIndex;
780
Andreas Huber784202e2009-10-15 13:46:54 -0700781 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700782 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800783 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -0700784
Andreas Huberb8de9572010-02-22 14:58:45 -0800785 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
786 || (def.nBufferSize < size)) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700787 def.nBufferSize = size;
Andreas Huberda050cf22009-09-02 14:01:43 -0700788 }
789
Andreas Huber784202e2009-10-15 13:46:54 -0700790 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700791 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800792 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800793
794 err = mOMX->getParameter(
795 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800796 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800797
798 // Make sure the setting actually stuck.
Andreas Huberb8de9572010-02-22 14:58:45 -0800799 if (portIndex == kPortIndexInput
800 && (mQuirks & kInputBufferSizesAreBogus)) {
801 CHECK_EQ(def.nBufferSize, size);
802 } else {
803 CHECK(def.nBufferSize >= size);
804 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700805}
806
Andreas Huberbe06d262009-08-14 14:37:10 -0700807status_t OMXCodec::setVideoPortFormatType(
808 OMX_U32 portIndex,
809 OMX_VIDEO_CODINGTYPE compressionFormat,
810 OMX_COLOR_FORMATTYPE colorFormat) {
811 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700812 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700813 format.nPortIndex = portIndex;
814 format.nIndex = 0;
815 bool found = false;
816
817 OMX_U32 index = 0;
818 for (;;) {
819 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700820 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700821 mNode, OMX_IndexParamVideoPortFormat,
822 &format, sizeof(format));
823
824 if (err != OK) {
825 return err;
826 }
827
828 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700829 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700830
831#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700832 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700833 portIndex,
834 index, format.eCompressionFormat, format.eColorFormat);
835#endif
836
837 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
838 if (portIndex == kPortIndexInput
839 && colorFormat == format.eColorFormat) {
840 // eCompressionFormat does not seem right.
841 found = true;
842 break;
843 }
844 if (portIndex == kPortIndexOutput
845 && compressionFormat == format.eCompressionFormat) {
846 // eColorFormat does not seem right.
847 found = true;
848 break;
849 }
850 }
851
852 if (format.eCompressionFormat == compressionFormat
Pannag Sanketi557b7092011-08-18 21:53:02 -0700853 && format.eColorFormat == colorFormat) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700854 found = true;
855 break;
856 }
857
858 ++index;
James Dong5a37afa2011-10-18 16:21:52 -0700859 if (index >= kMaxColorFormatSupported) {
860 CODEC_LOGE("color format %d or compression format %d is not supported",
861 colorFormat, compressionFormat);
862 return UNKNOWN_ERROR;
863 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700864 }
865
866 if (!found) {
867 return UNKNOWN_ERROR;
868 }
869
Andreas Huber53a76bd2009-10-06 16:20:44 -0700870 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700871 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700872 mNode, OMX_IndexParamVideoPortFormat,
873 &format, sizeof(format));
874
875 return err;
876}
877
Andreas Huberb482ce82009-10-29 12:02:48 -0700878static size_t getFrameSize(
879 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
880 switch (colorFormat) {
881 case OMX_COLOR_FormatYCbYCr:
882 case OMX_COLOR_FormatCbYCrY:
883 return width * height * 2;
884
Andreas Huber71c27d92010-03-19 11:43:15 -0700885 case OMX_COLOR_FormatYUV420Planar:
Andreas Huberb482ce82009-10-29 12:02:48 -0700886 case OMX_COLOR_FormatYUV420SemiPlanar:
Dandawate Sakete641dc52011-07-11 19:12:57 -0700887 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
Pannag Sanketi557b7092011-08-18 21:53:02 -0700888 /*
889 * FIXME: For the Opaque color format, the frame size does not
890 * need to be (w*h*3)/2. It just needs to
891 * be larger than certain minimum buffer size. However,
892 * currently, this opaque foramt has been tested only on
893 * YUV420 formats. If that is changed, then we need to revisit
894 * this part in the future
895 */
896 case OMX_COLOR_FormatAndroidOpaque:
Andreas Huberb482ce82009-10-29 12:02:48 -0700897 return (width * height * 3) / 2;
898
899 default:
900 CHECK(!"Should not be here. Unsupported color format.");
901 break;
902 }
903}
904
James Dongafd97e82010-08-03 17:19:23 -0700905status_t OMXCodec::findTargetColorFormat(
906 const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat) {
Steve Block71f2cf12011-10-20 11:56:00 +0100907 ALOGV("findTargetColorFormat");
James Dongafd97e82010-08-03 17:19:23 -0700908 CHECK(mIsEncoder);
909
910 *colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
911 int32_t targetColorFormat;
912 if (meta->findInt32(kKeyColorFormat, &targetColorFormat)) {
913 *colorFormat = (OMX_COLOR_FORMATTYPE) targetColorFormat;
914 } else {
915 if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
916 *colorFormat = OMX_COLOR_FormatYCbYCr;
917 }
918 }
919
Dandawate Sakete641dc52011-07-11 19:12:57 -0700920
James Dongafd97e82010-08-03 17:19:23 -0700921 // Check whether the target color format is supported.
922 return isColorFormatSupported(*colorFormat, kPortIndexInput);
923}
924
925status_t OMXCodec::isColorFormatSupported(
926 OMX_COLOR_FORMATTYPE colorFormat, int portIndex) {
Steve Block71f2cf12011-10-20 11:56:00 +0100927 ALOGV("isColorFormatSupported: %d", static_cast<int>(colorFormat));
James Dongafd97e82010-08-03 17:19:23 -0700928
929 // Enumerate all the color formats supported by
930 // the omx component to see whether the given
931 // color format is supported.
932 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
933 InitOMXParams(&portFormat);
934 portFormat.nPortIndex = portIndex;
935 OMX_U32 index = 0;
936 portFormat.nIndex = index;
937 while (true) {
938 if (OMX_ErrorNone != mOMX->getParameter(
939 mNode, OMX_IndexParamVideoPortFormat,
940 &portFormat, sizeof(portFormat))) {
James Dongb5024da2010-09-13 16:30:51 -0700941 break;
James Dongafd97e82010-08-03 17:19:23 -0700942 }
943 // Make sure that omx component does not overwrite
944 // the incremented index (bug 2897413).
945 CHECK_EQ(index, portFormat.nIndex);
Pannag Sanketi557b7092011-08-18 21:53:02 -0700946 if (portFormat.eColorFormat == colorFormat) {
James Dong5a37afa2011-10-18 16:21:52 -0700947 CODEC_LOGV("Found supported color format: %d", portFormat.eColorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700948 return OK; // colorFormat is supported!
949 }
950 ++index;
951 portFormat.nIndex = index;
952
James Dong5a37afa2011-10-18 16:21:52 -0700953 if (index >= kMaxColorFormatSupported) {
954 CODEC_LOGE("More than %ld color formats are supported???", index);
James Dongafd97e82010-08-03 17:19:23 -0700955 break;
956 }
957 }
James Dongb5024da2010-09-13 16:30:51 -0700958
James Dong5a37afa2011-10-18 16:21:52 -0700959 CODEC_LOGE("color format %d is not supported", colorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700960 return UNKNOWN_ERROR;
961}
962
Andreas Huberbe06d262009-08-14 14:37:10 -0700963void OMXCodec::setVideoInputFormat(
James Dong1244eab2010-06-08 11:58:53 -0700964 const char *mime, const sp<MetaData>& meta) {
965
966 int32_t width, height, frameRate, bitRate, stride, sliceHeight;
967 bool success = meta->findInt32(kKeyWidth, &width);
968 success = success && meta->findInt32(kKeyHeight, &height);
James Dongaac193c2010-11-10 20:43:53 -0800969 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -0700970 success = success && meta->findInt32(kKeyBitRate, &bitRate);
971 success = success && meta->findInt32(kKeyStride, &stride);
972 success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
973 CHECK(success);
974 CHECK(stride != 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700975
976 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700977 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700978 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700979 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700980 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700981 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700982 compressionFormat = OMX_VIDEO_CodingH263;
983 } else {
984 LOGE("Not a supported video mime type: %s", mime);
985 CHECK(!"Should not be here. Not a supported video mime type.");
986 }
987
James Dongafd97e82010-08-03 17:19:23 -0700988 OMX_COLOR_FORMATTYPE colorFormat;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800989 CHECK_EQ((status_t)OK, findTargetColorFormat(meta, &colorFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -0700990
James Dongb00e2462010-04-26 17:48:26 -0700991 status_t err;
992 OMX_PARAM_PORTDEFINITIONTYPE def;
993 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
994
995 //////////////////////// Input port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700996 CHECK_EQ(setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -0700997 kPortIndexInput, OMX_VIDEO_CodingUnused,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800998 colorFormat), (status_t)OK);
James Dong4f501f02010-06-07 14:41:41 -0700999
James Dongb00e2462010-04-26 17:48:26 -07001000 InitOMXParams(&def);
1001 def.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07001002
James Dongb00e2462010-04-26 17:48:26 -07001003 err = mOMX->getParameter(
1004 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001005 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -07001006
James Dong1244eab2010-06-08 11:58:53 -07001007 def.nBufferSize = getFrameSize(colorFormat,
1008 stride > 0? stride: -stride, sliceHeight);
James Dongb00e2462010-04-26 17:48:26 -07001009
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001010 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
James Dongb00e2462010-04-26 17:48:26 -07001011
1012 video_def->nFrameWidth = width;
1013 video_def->nFrameHeight = height;
James Dong1244eab2010-06-08 11:58:53 -07001014 video_def->nStride = stride;
1015 video_def->nSliceHeight = sliceHeight;
James Dong4f501f02010-06-07 14:41:41 -07001016 video_def->xFramerate = (frameRate << 16); // Q16 format
James Dongb00e2462010-04-26 17:48:26 -07001017 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1018 video_def->eColorFormat = colorFormat;
1019
James Dongb00e2462010-04-26 17:48:26 -07001020 err = mOMX->setParameter(
1021 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001022 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -07001023
1024 //////////////////////// Output port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -07001025 CHECK_EQ(setVideoPortFormatType(
1026 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001027 (status_t)OK);
Andreas Huber4c483422009-09-02 16:05:36 -07001028 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001029 def.nPortIndex = kPortIndexOutput;
1030
James Dongb00e2462010-04-26 17:48:26 -07001031 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001032 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1033
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001034 CHECK_EQ(err, (status_t)OK);
1035 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001036
1037 video_def->nFrameWidth = width;
1038 video_def->nFrameHeight = height;
James Dong81c929a2010-07-01 15:02:14 -07001039 video_def->xFramerate = 0; // No need for output port
James Dong4f501f02010-06-07 14:41:41 -07001040 video_def->nBitrate = bitRate; // Q16 format
Andreas Huberbe06d262009-08-14 14:37:10 -07001041 video_def->eCompressionFormat = compressionFormat;
1042 video_def->eColorFormat = OMX_COLOR_FormatUnused;
James Dong90862e22010-08-26 19:12:59 -07001043 if (mQuirks & kRequiresLargerEncoderOutputBuffer) {
1044 // Increases the output buffer size
1045 def.nBufferSize = ((def.nBufferSize * 3) >> 1);
1046 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001047
Andreas Huber784202e2009-10-15 13:46:54 -07001048 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001049 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001050 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001051
James Dongb00e2462010-04-26 17:48:26 -07001052 /////////////////// Codec-specific ////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -07001053 switch (compressionFormat) {
1054 case OMX_VIDEO_CodingMPEG4:
1055 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001056 CHECK_EQ(setupMPEG4EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001057 break;
1058 }
1059
1060 case OMX_VIDEO_CodingH263:
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001061 CHECK_EQ(setupH263EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001062 break;
1063
Andreas Huberea6a38c2009-11-16 15:43:38 -08001064 case OMX_VIDEO_CodingAVC:
1065 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001066 CHECK_EQ(setupAVCEncoderParameters(meta), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001067 break;
1068 }
1069
Andreas Huberb482ce82009-10-29 12:02:48 -07001070 default:
1071 CHECK(!"Support for this compressionFormat to be implemented.");
1072 break;
1073 }
1074}
1075
James Dong1244eab2010-06-08 11:58:53 -07001076static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1077 if (iFramesInterval < 0) {
1078 return 0xFFFFFFFF;
1079 } else if (iFramesInterval == 0) {
1080 return 0;
1081 }
1082 OMX_U32 ret = frameRate * iFramesInterval;
1083 CHECK(ret > 1);
1084 return ret;
1085}
1086
James Dongc0ab2a62010-06-29 16:29:19 -07001087status_t OMXCodec::setupErrorCorrectionParameters() {
1088 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1089 InitOMXParams(&errorCorrectionType);
1090 errorCorrectionType.nPortIndex = kPortIndexOutput;
1091
1092 status_t err = mOMX->getParameter(
1093 mNode, OMX_IndexParamVideoErrorCorrection,
1094 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -07001095 if (err != OK) {
1096 LOGW("Error correction param query is not supported");
1097 return OK; // Optional feature. Ignore this failure
1098 }
James Dongc0ab2a62010-06-29 16:29:19 -07001099
1100 errorCorrectionType.bEnableHEC = OMX_FALSE;
1101 errorCorrectionType.bEnableResync = OMX_TRUE;
1102 errorCorrectionType.nResynchMarkerSpacing = 256;
1103 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1104 errorCorrectionType.bEnableRVLC = OMX_FALSE;
1105
1106 err = mOMX->setParameter(
1107 mNode, OMX_IndexParamVideoErrorCorrection,
1108 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -07001109 if (err != OK) {
1110 LOGW("Error correction param configuration is not supported");
1111 }
1112
1113 // Optional feature. Ignore the failure.
James Dongc0ab2a62010-06-29 16:29:19 -07001114 return OK;
1115}
1116
1117status_t OMXCodec::setupBitRate(int32_t bitRate) {
1118 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1119 InitOMXParams(&bitrateType);
1120 bitrateType.nPortIndex = kPortIndexOutput;
1121
1122 status_t err = mOMX->getParameter(
1123 mNode, OMX_IndexParamVideoBitrate,
1124 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001125 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001126
1127 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1128 bitrateType.nTargetBitrate = bitRate;
1129
1130 err = mOMX->setParameter(
1131 mNode, OMX_IndexParamVideoBitrate,
1132 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001133 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001134 return OK;
1135}
1136
James Dong81c929a2010-07-01 15:02:14 -07001137status_t OMXCodec::getVideoProfileLevel(
1138 const sp<MetaData>& meta,
1139 const CodecProfileLevel& defaultProfileLevel,
1140 CodecProfileLevel &profileLevel) {
1141 CODEC_LOGV("Default profile: %ld, level %ld",
1142 defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
1143
1144 // Are the default profile and level overwriten?
1145 int32_t profile, level;
1146 if (!meta->findInt32(kKeyVideoProfile, &profile)) {
1147 profile = defaultProfileLevel.mProfile;
1148 }
1149 if (!meta->findInt32(kKeyVideoLevel, &level)) {
1150 level = defaultProfileLevel.mLevel;
1151 }
1152 CODEC_LOGV("Target profile: %d, level: %d", profile, level);
1153
1154 // Are the target profile and level supported by the encoder?
1155 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
1156 InitOMXParams(&param);
1157 param.nPortIndex = kPortIndexOutput;
1158 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
1159 status_t err = mOMX->getParameter(
1160 mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
1161 &param, sizeof(param));
1162
James Dongdfb89912010-09-15 21:07:52 -07001163 if (err != OK) break;
James Dong81c929a2010-07-01 15:02:14 -07001164
1165 int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
1166 int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
James Dong929642e2010-07-08 11:16:11 -07001167 CODEC_LOGV("Supported profile: %d, level %d",
James Dong81c929a2010-07-01 15:02:14 -07001168 supportedProfile, supportedLevel);
1169
1170 if (profile == supportedProfile &&
James Dongdfb89912010-09-15 21:07:52 -07001171 level <= supportedLevel) {
1172 // We can further check whether the level is a valid
1173 // value; but we will leave that to the omx encoder component
1174 // via OMX_SetParameter call.
James Dong81c929a2010-07-01 15:02:14 -07001175 profileLevel.mProfile = profile;
1176 profileLevel.mLevel = level;
1177 return OK;
1178 }
1179 }
1180
1181 CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
1182 profile, level);
1183 return BAD_VALUE;
1184}
1185
James Dongc0ab2a62010-06-29 16:29:19 -07001186status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
1187 int32_t iFramesInterval, frameRate, bitRate;
1188 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001189 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dongc0ab2a62010-06-29 16:29:19 -07001190 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1191 CHECK(success);
1192 OMX_VIDEO_PARAM_H263TYPE h263type;
1193 InitOMXParams(&h263type);
1194 h263type.nPortIndex = kPortIndexOutput;
1195
1196 status_t err = mOMX->getParameter(
1197 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001198 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001199
1200 h263type.nAllowedPictureTypes =
1201 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1202
1203 h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1204 if (h263type.nPFrames == 0) {
1205 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1206 }
1207 h263type.nBFrames = 0;
1208
James Dong81c929a2010-07-01 15:02:14 -07001209 // Check profile and level parameters
1210 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001211 defaultProfileLevel.mProfile = h263type.eProfile;
1212 defaultProfileLevel.mLevel = h263type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001213 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1214 if (err != OK) return err;
1215 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
1216 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
James Dongc0ab2a62010-06-29 16:29:19 -07001217
1218 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1219 h263type.bForceRoundingTypeToZero = OMX_FALSE;
1220 h263type.nPictureHeaderRepetition = 0;
1221 h263type.nGOBHeaderInterval = 0;
1222
1223 err = mOMX->setParameter(
1224 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001225 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001226
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001227 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1228 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001229
1230 return OK;
1231}
1232
James Dong1244eab2010-06-08 11:58:53 -07001233status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
1234 int32_t iFramesInterval, frameRate, bitRate;
1235 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001236 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001237 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1238 CHECK(success);
Andreas Huberb482ce82009-10-29 12:02:48 -07001239 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1240 InitOMXParams(&mpeg4type);
1241 mpeg4type.nPortIndex = kPortIndexOutput;
1242
1243 status_t err = mOMX->getParameter(
1244 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001245 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001246
1247 mpeg4type.nSliceHeaderSpacing = 0;
1248 mpeg4type.bSVH = OMX_FALSE;
1249 mpeg4type.bGov = OMX_FALSE;
1250
1251 mpeg4type.nAllowedPictureTypes =
1252 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1253
James Dong1244eab2010-06-08 11:58:53 -07001254 mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1255 if (mpeg4type.nPFrames == 0) {
1256 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1257 }
Andreas Huberb482ce82009-10-29 12:02:48 -07001258 mpeg4type.nBFrames = 0;
Andreas Huberb482ce82009-10-29 12:02:48 -07001259 mpeg4type.nIDCVLCThreshold = 0;
1260 mpeg4type.bACPred = OMX_TRUE;
1261 mpeg4type.nMaxPacketSize = 256;
1262 mpeg4type.nTimeIncRes = 1000;
1263 mpeg4type.nHeaderExtension = 0;
1264 mpeg4type.bReversibleVLC = OMX_FALSE;
1265
James Dong81c929a2010-07-01 15:02:14 -07001266 // Check profile and level parameters
1267 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001268 defaultProfileLevel.mProfile = mpeg4type.eProfile;
1269 defaultProfileLevel.mLevel = mpeg4type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001270 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1271 if (err != OK) return err;
1272 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
1273 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
Andreas Huberb482ce82009-10-29 12:02:48 -07001274
1275 err = mOMX->setParameter(
1276 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001277 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001278
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001279 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1280 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001281
1282 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07001283}
1284
James Dong1244eab2010-06-08 11:58:53 -07001285status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
1286 int32_t iFramesInterval, frameRate, bitRate;
1287 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001288 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001289 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1290 CHECK(success);
1291
Andreas Huberea6a38c2009-11-16 15:43:38 -08001292 OMX_VIDEO_PARAM_AVCTYPE h264type;
1293 InitOMXParams(&h264type);
1294 h264type.nPortIndex = kPortIndexOutput;
1295
1296 status_t err = mOMX->getParameter(
1297 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001298 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001299
1300 h264type.nAllowedPictureTypes =
1301 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1302
James Dong81c929a2010-07-01 15:02:14 -07001303 // Check profile and level parameters
1304 CodecProfileLevel defaultProfileLevel, profileLevel;
1305 defaultProfileLevel.mProfile = h264type.eProfile;
1306 defaultProfileLevel.mLevel = h264type.eLevel;
1307 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1308 if (err != OK) return err;
1309 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
1310 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
1311
Dandawate Sakete641dc52011-07-11 19:12:57 -07001312 // FIXME:
1313 // Remove the workaround after the work in done.
1314 if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
1315 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1316 }
1317
James Dong81c929a2010-07-01 15:02:14 -07001318 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
James Dongbe650872011-07-07 16:41:25 -07001319 h264type.nSliceHeaderSpacing = 0;
James Dong81c929a2010-07-01 15:02:14 -07001320 h264type.bUseHadamard = OMX_TRUE;
1321 h264type.nRefFrames = 1;
James Dongbe650872011-07-07 16:41:25 -07001322 h264type.nBFrames = 0;
1323 h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1324 if (h264type.nPFrames == 0) {
1325 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1326 }
James Dong81c929a2010-07-01 15:02:14 -07001327 h264type.nRefIdx10ActiveMinus1 = 0;
1328 h264type.nRefIdx11ActiveMinus1 = 0;
1329 h264type.bEntropyCodingCABAC = OMX_FALSE;
1330 h264type.bWeightedPPrediction = OMX_FALSE;
1331 h264type.bconstIpred = OMX_FALSE;
1332 h264type.bDirect8x8Inference = OMX_FALSE;
1333 h264type.bDirectSpatialTemporal = OMX_FALSE;
1334 h264type.nCabacInitIdc = 0;
1335 }
1336
1337 if (h264type.nBFrames != 0) {
1338 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1339 }
1340
Andreas Huberea6a38c2009-11-16 15:43:38 -08001341 h264type.bEnableUEP = OMX_FALSE;
1342 h264type.bEnableFMO = OMX_FALSE;
1343 h264type.bEnableASO = OMX_FALSE;
1344 h264type.bEnableRS = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001345 h264type.bFrameMBsOnly = OMX_TRUE;
1346 h264type.bMBAFF = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001347 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1348
pgudadhe9c305322010-07-26 13:59:29 -07001349 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
1350 h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1351 }
1352
Andreas Huberea6a38c2009-11-16 15:43:38 -08001353 err = mOMX->setParameter(
1354 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001355 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001356
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001357 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001358
1359 return OK;
1360}
1361
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001362status_t OMXCodec::setVideoOutputFormat(
Andreas Huberbe06d262009-08-14 14:37:10 -07001363 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -07001364 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001365
Andreas Huberbe06d262009-08-14 14:37:10 -07001366 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -07001367 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001368 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -07001369 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001370 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -07001371 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001372 compressionFormat = OMX_VIDEO_CodingH263;
Andreas Huber4b3913a2011-05-11 14:13:42 -07001373 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1374 compressionFormat = OMX_VIDEO_CodingVPX;
Andreas Hubereb2f9c12011-05-19 08:37:39 -07001375 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1376 compressionFormat = OMX_VIDEO_CodingMPEG2;
Andreas Huberbe06d262009-08-14 14:37:10 -07001377 } else {
1378 LOGE("Not a supported video mime type: %s", mime);
1379 CHECK(!"Should not be here. Not a supported video mime type.");
1380 }
1381
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001382 status_t err = setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -07001383 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1384
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001385 if (err != OK) {
1386 return err;
1387 }
1388
Andreas Huberbe06d262009-08-14 14:37:10 -07001389#if 1
1390 {
1391 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -07001392 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -07001393 format.nPortIndex = kPortIndexOutput;
1394 format.nIndex = 0;
1395
Andreas Huber784202e2009-10-15 13:46:54 -07001396 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001397 mNode, OMX_IndexParamVideoPortFormat,
1398 &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001399 CHECK_EQ(err, (status_t)OK);
1400 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07001401
Andreas Huberbe06d262009-08-14 14:37:10 -07001402 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1403 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1404 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
Anu Sundararajand35df442011-06-22 12:24:46 -05001405 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
Andreas Huberbe06d262009-08-14 14:37:10 -07001406 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1407
Andreas Huber784202e2009-10-15 13:46:54 -07001408 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001409 mNode, OMX_IndexParamVideoPortFormat,
1410 &format, sizeof(format));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001411
1412 if (err != OK) {
1413 return err;
1414 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001415 }
1416#endif
1417
1418 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001419 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001420 def.nPortIndex = kPortIndexInput;
1421
Andreas Huber4c483422009-09-02 16:05:36 -07001422 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1423
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001424 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001425 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1426
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001427 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001428
1429#if 1
1430 // XXX Need a (much) better heuristic to compute input buffer sizes.
1431 const size_t X = 64 * 1024;
1432 if (def.nBufferSize < X) {
1433 def.nBufferSize = X;
1434 }
1435#endif
1436
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001437 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001438
1439 video_def->nFrameWidth = width;
1440 video_def->nFrameHeight = height;
1441
Andreas Huberb482ce82009-10-29 12:02:48 -07001442 video_def->eCompressionFormat = compressionFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -07001443 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1444
Andreas Huber784202e2009-10-15 13:46:54 -07001445 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001446 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001447
1448 if (err != OK) {
1449 return err;
1450 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001451
1452 ////////////////////////////////////////////////////////////////////////////
1453
Andreas Huber4c483422009-09-02 16:05:36 -07001454 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001455 def.nPortIndex = kPortIndexOutput;
1456
Andreas Huber784202e2009-10-15 13:46:54 -07001457 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001458 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001459 CHECK_EQ(err, (status_t)OK);
1460 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001461
1462#if 0
1463 def.nBufferSize =
1464 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
1465#endif
1466
1467 video_def->nFrameWidth = width;
1468 video_def->nFrameHeight = height;
1469
Andreas Huber784202e2009-10-15 13:46:54 -07001470 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001471 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001472
1473 return err;
Andreas Huberbe06d262009-08-14 14:37:10 -07001474}
1475
Andreas Huberbe06d262009-08-14 14:37:10 -07001476OMXCodec::OMXCodec(
Andreas Huber42fb5d62011-06-29 15:53:28 -07001477 const sp<IOMX> &omx, IOMX::node_id node,
1478 uint32_t quirks, uint32_t flags,
Andreas Huberebf66ea2009-08-19 13:32:58 -07001479 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -07001480 const char *mime,
1481 const char *componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001482 const sp<MediaSource> &source,
1483 const sp<ANativeWindow> &nativeWindow)
Andreas Huberbe06d262009-08-14 14:37:10 -07001484 : mOMX(omx),
Andreas Huberf1fe0642010-01-15 15:28:19 -08001485 mOMXLivesLocally(omx->livesLocally(getpid())),
Andreas Huberbe06d262009-08-14 14:37:10 -07001486 mNode(node),
1487 mQuirks(quirks),
Andreas Huber42fb5d62011-06-29 15:53:28 -07001488 mFlags(flags),
Andreas Huberbe06d262009-08-14 14:37:10 -07001489 mIsEncoder(isEncoder),
1490 mMIME(strdup(mime)),
1491 mComponentName(strdup(componentName)),
1492 mSource(source),
1493 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -07001494 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -07001495 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -07001496 mSignalledEOS(false),
1497 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -07001498 mOutputPortSettingsHaveChanged(false),
Andreas Hubera4357ad2010-04-02 12:49:54 -07001499 mSeekTimeUs(-1),
Andreas Huber6624c9f2010-07-20 15:04:28 -07001500 mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
1501 mTargetTimeUs(-1),
Andreas Huberb9289832011-02-08 13:10:25 -08001502 mOutputPortSettingsChangedPending(false),
Andreas Huber1f24b302010-06-10 11:12:39 -07001503 mLeftOverBuffer(NULL),
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001504 mPaused(false),
Andreas Huberbc554952011-09-08 14:12:44 -07001505 mNativeWindow(
1506 (!strncmp(componentName, "OMX.google.", 11)
1507 || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode"))
Andreas Huber4b3913a2011-05-11 14:13:42 -07001508 ? NULL : nativeWindow) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001509 mPortStatus[kPortIndexInput] = ENABLED;
1510 mPortStatus[kPortIndexOutput] = ENABLED;
1511
Andreas Huber4c483422009-09-02 16:05:36 -07001512 setComponentRole();
1513}
1514
Andreas Hubere6c40962009-09-10 14:13:30 -07001515// static
1516void OMXCodec::setComponentRole(
1517 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1518 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -07001519 struct MimeToRole {
1520 const char *mime;
1521 const char *decoderRole;
1522 const char *encoderRole;
1523 };
1524
1525 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -07001526 { MEDIA_MIMETYPE_AUDIO_MPEG,
1527 "audio_decoder.mp3", "audio_encoder.mp3" },
Andreas Huberbc554952011-09-08 14:12:44 -07001528 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1529 "audio_decoder.mp1", "audio_encoder.mp1" },
1530 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1531 "audio_decoder.mp2", "audio_encoder.mp2" },
1532 { MEDIA_MIMETYPE_AUDIO_MPEG,
1533 "audio_decoder.mp3", "audio_encoder.mp3" },
Andreas Hubere6c40962009-09-10 14:13:30 -07001534 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1535 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1536 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1537 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1538 { MEDIA_MIMETYPE_AUDIO_AAC,
1539 "audio_decoder.aac", "audio_encoder.aac" },
Andreas Huber3e408f32011-09-28 12:37:36 -07001540 { MEDIA_MIMETYPE_AUDIO_VORBIS,
1541 "audio_decoder.vorbis", "audio_encoder.vorbis" },
Andreas Hubere6c40962009-09-10 14:13:30 -07001542 { MEDIA_MIMETYPE_VIDEO_AVC,
1543 "video_decoder.avc", "video_encoder.avc" },
1544 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1545 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1546 { MEDIA_MIMETYPE_VIDEO_H263,
1547 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber4c483422009-09-02 16:05:36 -07001548 };
1549
1550 static const size_t kNumMimeToRole =
1551 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1552
1553 size_t i;
1554 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001555 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001556 break;
1557 }
1558 }
1559
1560 if (i == kNumMimeToRole) {
1561 return;
1562 }
1563
1564 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -07001565 isEncoder ? kMimeToRole[i].encoderRole
1566 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -07001567
1568 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -07001569 OMX_PARAM_COMPONENTROLETYPE roleParams;
1570 InitOMXParams(&roleParams);
1571
1572 strncpy((char *)roleParams.cRole,
1573 role, OMX_MAX_STRINGNAME_SIZE - 1);
1574
1575 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1576
Andreas Huber784202e2009-10-15 13:46:54 -07001577 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07001578 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -07001579 &roleParams, sizeof(roleParams));
1580
1581 if (err != OK) {
1582 LOGW("Failed to set standard component role '%s'.", role);
1583 }
1584 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001585}
1586
Andreas Hubere6c40962009-09-10 14:13:30 -07001587void OMXCodec::setComponentRole() {
1588 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1589}
1590
Andreas Huberbe06d262009-08-14 14:37:10 -07001591OMXCodec::~OMXCodec() {
Andreas Huberf98197a2010-09-17 11:49:39 -07001592 mSource.clear();
1593
Andreas Hubereec06d32011-01-06 10:26:36 -08001594 CHECK(mState == LOADED || mState == ERROR || mState == LOADED_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001595
Andreas Huber784202e2009-10-15 13:46:54 -07001596 status_t err = mOMX->freeNode(mNode);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001597 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001598
1599 mNode = NULL;
1600 setState(DEAD);
1601
1602 clearCodecSpecificData();
1603
1604 free(mComponentName);
1605 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001606
Andreas Huberbe06d262009-08-14 14:37:10 -07001607 free(mMIME);
1608 mMIME = NULL;
1609}
1610
1611status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -07001612 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -07001613
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001614 CHECK_EQ((int)mState, (int)LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07001615
1616 status_t err;
1617 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001618 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001619 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001620 setState(LOADED_TO_IDLE);
1621 }
1622
1623 err = allocateBuffers();
Jamie Gennisfd8b75a2010-12-17 15:07:02 -08001624 if (err != (status_t)OK) {
1625 return err;
1626 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001627
1628 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -07001629 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001630 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001631
1632 setState(LOADED_TO_IDLE);
1633 }
1634
1635 while (mState != EXECUTING && mState != ERROR) {
1636 mAsyncCompletion.wait(mLock);
1637 }
1638
1639 return mState == ERROR ? UNKNOWN_ERROR : OK;
1640}
1641
1642// static
1643bool OMXCodec::isIntermediateState(State state) {
1644 return state == LOADED_TO_IDLE
1645 || state == IDLE_TO_EXECUTING
1646 || state == EXECUTING_TO_IDLE
1647 || state == IDLE_TO_LOADED
1648 || state == RECONFIGURING;
1649}
1650
1651status_t OMXCodec::allocateBuffers() {
1652 status_t err = allocateBuffersOnPort(kPortIndexInput);
1653
1654 if (err != OK) {
1655 return err;
1656 }
1657
1658 return allocateBuffersOnPort(kPortIndexOutput);
1659}
1660
1661status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
Jamie Gennisdbfb32e2010-10-20 15:53:59 -07001662 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001663 return allocateOutputBuffersFromNativeWindow();
1664 }
1665
Andreas Huber42fb5d62011-06-29 15:53:28 -07001666 if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
Jamie Gennis66380f72011-04-07 19:03:56 -07001667 LOGE("protected output buffers must be stent to an ANativeWindow");
1668 return PERMISSION_DENIED;
1669 }
1670
James Dong7d6143a2011-06-08 10:35:19 -07001671 status_t err = OK;
Andreas Huber42fb5d62011-06-29 15:53:28 -07001672 if ((mFlags & kStoreMetaDataInVideoBuffers)
1673 && portIndex == kPortIndexInput) {
James Dong05c2fd52010-11-02 13:20:11 -07001674 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1675 if (err != OK) {
1676 LOGE("Storing meta data in video buffers is not supported");
1677 return err;
1678 }
1679 }
1680
James Dong7d6143a2011-06-08 10:35:19 -07001681 OMX_PARAM_PORTDEFINITIONTYPE def;
1682 InitOMXParams(&def);
1683 def.nPortIndex = portIndex;
1684
1685 err = mOMX->getParameter(
1686 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1687
1688 if (err != OK) {
1689 return err;
1690 }
1691
Andreas Huber262d7e82011-09-27 15:05:40 -07001692 CODEC_LOGV("allocating %lu buffers of size %lu on %s port",
Andreas Huber57648e42010-08-04 10:14:30 -07001693 def.nBufferCountActual, def.nBufferSize,
1694 portIndex == kPortIndexInput ? "input" : "output");
1695
Andreas Huber5c0a9132009-08-20 11:16:40 -07001696 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
Mathias Agopian6faf7892010-01-25 19:00:00 -08001697 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
Andreas Huber5c0a9132009-08-20 11:16:40 -07001698
Andreas Huberbe06d262009-08-14 14:37:10 -07001699 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -07001700 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07001701 CHECK(mem.get() != NULL);
1702
Andreas Huberc712b9f2010-01-20 15:05:46 -08001703 BufferInfo info;
1704 info.mData = NULL;
1705 info.mSize = def.nBufferSize;
1706
Andreas Huberbe06d262009-08-14 14:37:10 -07001707 IOMX::buffer_id buffer;
1708 if (portIndex == kPortIndexInput
Andreas Huber42fb5d62011-06-29 15:53:28 -07001709 && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
1710 || (mFlags & kUseSecureInputBuffers))) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001711 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001712 mem.clear();
1713
Andreas Huberf1fe0642010-01-15 15:28:19 -08001714 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001715 mNode, portIndex, def.nBufferSize, &buffer,
1716 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001717 } else {
1718 err = mOMX->allocateBufferWithBackup(
1719 mNode, portIndex, mem, &buffer);
1720 }
Andreas Huber446f44f2009-08-25 17:23:44 -07001721 } else if (portIndex == kPortIndexOutput
1722 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001723 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001724 mem.clear();
1725
Andreas Huberf1fe0642010-01-15 15:28:19 -08001726 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001727 mNode, portIndex, def.nBufferSize, &buffer,
1728 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001729 } else {
1730 err = mOMX->allocateBufferWithBackup(
1731 mNode, portIndex, mem, &buffer);
1732 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001733 } else {
Andreas Huber784202e2009-10-15 13:46:54 -07001734 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001735 }
1736
1737 if (err != OK) {
1738 LOGE("allocate_buffer_with_backup failed");
1739 return err;
1740 }
1741
Andreas Huberc712b9f2010-01-20 15:05:46 -08001742 if (mem != NULL) {
1743 info.mData = mem->pointer();
1744 }
1745
Andreas Huberbe06d262009-08-14 14:37:10 -07001746 info.mBuffer = buffer;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001747 info.mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07001748 info.mMem = mem;
1749 info.mMediaBuffer = NULL;
1750
1751 if (portIndex == kPortIndexOutput) {
Andreas Huber52733b82010-01-25 10:41:35 -08001752 if (!(mOMXLivesLocally
1753 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1754 && (mQuirks & kDefersOutputBufferAllocation))) {
1755 // If the node does not fill in the buffer ptr at this time,
1756 // we will defer creating the MediaBuffer until receiving
1757 // the first FILL_BUFFER_DONE notification instead.
1758 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1759 info.mMediaBuffer->setObserver(this);
1760 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001761 }
1762
1763 mPortBuffers[portIndex].push(info);
1764
Andreas Huber4c483422009-09-02 16:05:36 -07001765 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -07001766 portIndex == kPortIndexInput ? "input" : "output");
1767 }
1768
Andreas Huber2ea14e22009-12-16 09:30:55 -08001769 // dumpPortStatus(portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001770
Andreas Huber42fb5d62011-06-29 15:53:28 -07001771 if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
1772 Vector<MediaBuffer *> buffers;
1773 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
1774 const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);
1775
1776 MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
1777 buffers.push(mbuf);
1778 }
1779
1780 status_t err = mSource->setBuffers(buffers);
1781
1782 if (err != OK) {
1783 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
1784 buffers.editItemAt(i)->release();
1785 }
1786 buffers.clear();
1787
1788 CODEC_LOGE(
1789 "Codec requested to use secure input buffers but "
1790 "upstream source didn't support that.");
1791
1792 return err;
1793 }
1794 }
1795
Andreas Huberbe06d262009-08-14 14:37:10 -07001796 return OK;
1797}
1798
Andreas Huber5e9dc942011-01-21 14:32:31 -08001799status_t OMXCodec::applyRotation() {
1800 sp<MetaData> meta = mSource->getFormat();
1801
1802 int32_t rotationDegrees;
1803 if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
1804 rotationDegrees = 0;
1805 }
1806
1807 uint32_t transform;
1808 switch (rotationDegrees) {
1809 case 0: transform = 0; break;
1810 case 90: transform = HAL_TRANSFORM_ROT_90; break;
1811 case 180: transform = HAL_TRANSFORM_ROT_180; break;
1812 case 270: transform = HAL_TRANSFORM_ROT_270; break;
1813 default: transform = 0; break;
1814 }
1815
1816 status_t err = OK;
1817
1818 if (transform) {
1819 err = native_window_set_buffers_transform(
1820 mNativeWindow.get(), transform);
1821 }
1822
1823 return err;
1824}
1825
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001826status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
1827 // Get the number of buffers needed.
1828 OMX_PARAM_PORTDEFINITIONTYPE def;
1829 InitOMXParams(&def);
1830 def.nPortIndex = kPortIndexOutput;
1831
1832 status_t err = mOMX->getParameter(
1833 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1834 if (err != OK) {
1835 return err;
1836 }
1837
Mathias Agopianff86f372011-07-18 16:15:08 -07001838 err = native_window_set_scaling_mode(mNativeWindow.get(),
1839 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1840
1841 if (err != OK) {
1842 return err;
1843 }
1844
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001845 err = native_window_set_buffers_geometry(
1846 mNativeWindow.get(),
1847 def.format.video.nFrameWidth,
1848 def.format.video.nFrameHeight,
Jamie Gennis044ace62010-10-29 15:19:29 -07001849 def.format.video.eColorFormat);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001850
1851 if (err != 0) {
1852 LOGE("native_window_set_buffers_geometry failed: %s (%d)",
1853 strerror(-err), -err);
1854 return err;
1855 }
1856
Andreas Huber5e9dc942011-01-21 14:32:31 -08001857 err = applyRotation();
1858 if (err != OK) {
1859 return err;
1860 }
1861
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001862 // Set up the native window.
Jamie Gennis94c59802011-02-24 12:48:17 -08001863 OMX_U32 usage = 0;
1864 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
1865 if (err != 0) {
1866 LOGW("querying usage flags from OMX IL component failed: %d", err);
1867 // XXX: Currently this error is logged, but not fatal.
1868 usage = 0;
1869 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07001870 if (mFlags & kEnableGrallocUsageProtected) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001871 usage |= GRALLOC_USAGE_PROTECTED;
1872 }
Jamie Gennis94c59802011-02-24 12:48:17 -08001873
Jamie Gennis66380f72011-04-07 19:03:56 -07001874 // Make sure to check whether either Stagefright or the video decoder
1875 // requested protected buffers.
1876 if (usage & GRALLOC_USAGE_PROTECTED) {
1877 // Verify that the ANativeWindow sends images directly to
1878 // SurfaceFlinger.
1879 int queuesToNativeWindow = 0;
1880 err = mNativeWindow->query(
1881 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
1882 &queuesToNativeWindow);
1883 if (err != 0) {
1884 LOGE("error authenticating native window: %d", err);
1885 return err;
1886 }
1887 if (queuesToNativeWindow != 1) {
1888 LOGE("native window could not be authenticated");
1889 return PERMISSION_DENIED;
1890 }
1891 }
1892
Steve Block71f2cf12011-10-20 11:56:00 +01001893 ALOGV("native_window_set_usage usage=0x%lx", usage);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001894 err = native_window_set_usage(
Jamie Gennis94c59802011-02-24 12:48:17 -08001895 mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001896 if (err != 0) {
1897 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
1898 return err;
1899 }
1900
Jamie Gennis01951fd2011-02-27 15:10:34 -08001901 int minUndequeuedBufs = 0;
1902 err = mNativeWindow->query(mNativeWindow.get(),
1903 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
1904 if (err != 0) {
1905 LOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
1906 strerror(-err), -err);
1907 return err;
1908 }
1909
1910 // XXX: Is this the right logic to use? It's not clear to me what the OMX
1911 // buffer counts refer to - how do they account for the renderer holding on
1912 // to buffers?
1913 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
1914 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
1915 def.nBufferCountActual = newBufferCount;
1916 err = mOMX->setParameter(
1917 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1918 if (err != OK) {
1919 CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
1920 newBufferCount, err);
1921 return err;
1922 }
1923 }
1924
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001925 err = native_window_set_buffer_count(
1926 mNativeWindow.get(), def.nBufferCountActual);
1927 if (err != 0) {
1928 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1929 -err);
1930 return err;
1931 }
1932
Andreas Huber262d7e82011-09-27 15:05:40 -07001933 CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001934 "output port", def.nBufferCountActual, def.nBufferSize);
1935
1936 // Dequeue buffers and send them to OMX
Jamie Gennis42024642011-02-22 18:33:06 -08001937 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07001938 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001939 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
1940 if (err != 0) {
1941 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1942 break;
1943 }
1944
1945 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001946 BufferInfo info;
1947 info.mData = NULL;
1948 info.mSize = def.nBufferSize;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001949 info.mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001950 info.mMem = NULL;
1951 info.mMediaBuffer = new MediaBuffer(graphicBuffer);
1952 info.mMediaBuffer->setObserver(this);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001953 mPortBuffers[kPortIndexOutput].push(info);
Jamie Gennis42024642011-02-22 18:33:06 -08001954
1955 IOMX::buffer_id bufferId;
1956 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1957 &bufferId);
1958 if (err != 0) {
1959 CODEC_LOGE("registering GraphicBuffer with OMX IL component "
1960 "failed: %d", err);
1961 break;
1962 }
1963
1964 mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId;
1965
1966 CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
1967 bufferId, graphicBuffer.get());
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001968 }
1969
1970 OMX_U32 cancelStart;
1971 OMX_U32 cancelEnd;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001972 if (err != 0) {
1973 // If an error occurred while dequeuing we need to cancel any buffers
1974 // that were dequeued.
1975 cancelStart = 0;
Jamie Gennis42024642011-02-22 18:33:06 -08001976 cancelEnd = mPortBuffers[kPortIndexOutput].size();
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001977 } else {
1978 // Return the last two buffers to the native window.
Jamie Gennis01951fd2011-02-27 15:10:34 -08001979 cancelStart = def.nBufferCountActual - minUndequeuedBufs;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001980 cancelEnd = def.nBufferCountActual;
1981 }
1982
1983 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1984 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
1985 cancelBufferToNativeWindow(info);
1986 }
1987
1988 return err;
1989}
1990
1991status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08001992 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001993 CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
1994 int err = mNativeWindow->cancelBuffer(
1995 mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
1996 if (err != 0) {
1997 CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
1998
1999 setState(ERROR);
2000 return err;
2001 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08002002 info->mStatus = OWNED_BY_NATIVE_WINDOW;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002003 return OK;
2004}
2005
2006OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
2007 // Dequeue the next buffer from the native window.
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07002008 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002009 int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
2010 if (err != 0) {
2011 CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
2012
2013 setState(ERROR);
2014 return 0;
2015 }
2016
2017 // Determine which buffer we just dequeued.
2018 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2019 BufferInfo *bufInfo = 0;
2020 for (size_t i = 0; i < buffers->size(); i++) {
2021 sp<GraphicBuffer> graphicBuffer = buffers->itemAt(i).
2022 mMediaBuffer->graphicBuffer();
2023 if (graphicBuffer->handle == buf->handle) {
2024 bufInfo = &buffers->editItemAt(i);
2025 break;
2026 }
2027 }
2028
2029 if (bufInfo == 0) {
2030 CODEC_LOGE("dequeued unrecognized buffer: %p", buf);
2031
2032 setState(ERROR);
2033 return 0;
2034 }
2035
2036 // The native window no longer owns the buffer.
Andreas Huberbbbcf652010-12-07 14:25:54 -08002037 CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
2038 bufInfo->mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002039
2040 return bufInfo;
2041}
2042
Jamie Gennisc0e42932011-10-25 14:50:16 -07002043status_t OMXCodec::pushBlankBuffersToNativeWindow() {
2044 status_t err = NO_ERROR;
2045 ANativeWindowBuffer* anb = NULL;
2046 int numBufs = 0;
2047 int minUndequeuedBufs = 0;
2048
2049 // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2050 // no frames get dropped by SurfaceFlinger assuming that these are video
2051 // frames.
2052 err = native_window_api_disconnect(mNativeWindow.get(),
2053 NATIVE_WINDOW_API_MEDIA);
2054 if (err != NO_ERROR) {
2055 LOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2056 strerror(-err), -err);
2057 return err;
2058 }
2059
2060 err = native_window_api_connect(mNativeWindow.get(),
2061 NATIVE_WINDOW_API_CPU);
2062 if (err != NO_ERROR) {
2063 LOGE("error pushing blank frames: api_connect failed: %s (%d)",
2064 strerror(-err), -err);
2065 return err;
2066 }
2067
2068 err = native_window_set_scaling_mode(mNativeWindow.get(),
2069 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
2070 if (err != NO_ERROR) {
2071 LOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2072 strerror(-err), -err);
2073 goto error;
2074 }
2075
2076 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2077 HAL_PIXEL_FORMAT_RGBX_8888);
2078 if (err != NO_ERROR) {
2079 LOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2080 strerror(-err), -err);
2081 goto error;
2082 }
2083
2084 err = native_window_set_usage(mNativeWindow.get(),
2085 GRALLOC_USAGE_SW_WRITE_OFTEN);
2086 if (err != NO_ERROR) {
2087 LOGE("error pushing blank frames: set_usage failed: %s (%d)",
2088 strerror(-err), -err);
2089 goto error;
2090 }
2091
2092 err = mNativeWindow->query(mNativeWindow.get(),
2093 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2094 if (err != NO_ERROR) {
2095 LOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2096 "failed: %s (%d)", strerror(-err), -err);
2097 goto error;
2098 }
2099
2100 numBufs = minUndequeuedBufs + 1;
2101 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2102 if (err != NO_ERROR) {
2103 LOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2104 strerror(-err), -err);
2105 goto error;
2106 }
2107
2108 // We push numBufs + 1 buffers to ensure that we've drawn into the same
2109 // buffer twice. This should guarantee that the buffer has been displayed
2110 // on the screen and then been replaced, so an previous video frames are
2111 // guaranteed NOT to be currently displayed.
2112 for (int i = 0; i < numBufs + 1; i++) {
2113 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
2114 if (err != NO_ERROR) {
2115 LOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2116 strerror(-err), -err);
2117 goto error;
2118 }
2119
2120 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2121 err = mNativeWindow->lockBuffer(mNativeWindow.get(),
2122 buf->getNativeBuffer());
2123 if (err != NO_ERROR) {
2124 LOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
2125 strerror(-err), -err);
2126 goto error;
2127 }
2128
2129 // Fill the buffer with the a 1x1 checkerboard pattern ;)
2130 uint32_t* img = NULL;
2131 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2132 if (err != NO_ERROR) {
2133 LOGE("error pushing blank frames: lock failed: %s (%d)",
2134 strerror(-err), -err);
2135 goto error;
2136 }
2137
2138 *img = 0;
2139
2140 err = buf->unlock();
2141 if (err != NO_ERROR) {
2142 LOGE("error pushing blank frames: unlock failed: %s (%d)",
2143 strerror(-err), -err);
2144 goto error;
2145 }
2146
2147 err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2148 buf->getNativeBuffer());
2149 if (err != NO_ERROR) {
2150 LOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2151 strerror(-err), -err);
2152 goto error;
2153 }
2154
2155 anb = NULL;
2156 }
2157
2158error:
2159
2160 if (err != NO_ERROR) {
2161 // Clean up after an error.
2162 if (anb != NULL) {
2163 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
2164 }
2165
2166 native_window_api_disconnect(mNativeWindow.get(),
2167 NATIVE_WINDOW_API_CPU);
2168 native_window_api_connect(mNativeWindow.get(),
2169 NATIVE_WINDOW_API_MEDIA);
2170
2171 return err;
2172 } else {
2173 // Clean up after success.
2174 err = native_window_api_disconnect(mNativeWindow.get(),
2175 NATIVE_WINDOW_API_CPU);
2176 if (err != NO_ERROR) {
2177 LOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2178 strerror(-err), -err);
2179 return err;
2180 }
2181
2182 err = native_window_api_connect(mNativeWindow.get(),
2183 NATIVE_WINDOW_API_MEDIA);
2184 if (err != NO_ERROR) {
2185 LOGE("error pushing blank frames: api_connect failed: %s (%d)",
2186 strerror(-err), -err);
2187 return err;
2188 }
2189
2190 return NO_ERROR;
2191 }
2192}
2193
James Dong4108b1ed2011-06-07 19:45:54 -07002194int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
2195 CHECK(mIsEncoder);
James Dong32bb368a52011-06-20 11:40:52 -07002196
2197 if (mDecodingTimeList.empty()) {
James Dong58c524e2011-08-30 17:06:10 -07002198 CHECK(mSignalledEOS || mNoMoreOutputData);
James Dong32bb368a52011-06-20 11:40:52 -07002199 // No corresponding input frame available.
2200 // This could happen when EOS is reached.
2201 return 0;
2202 }
2203
James Dong4108b1ed2011-06-07 19:45:54 -07002204 List<int64_t>::iterator it = mDecodingTimeList.begin();
2205 int64_t timeUs = *it;
2206
2207 // If the output buffer is codec specific configuration,
2208 // do not remove the decoding time from the list.
2209 if (!isCodecSpecific) {
2210 mDecodingTimeList.erase(it);
2211 }
2212 return timeUs;
2213}
2214
Andreas Huberbe06d262009-08-14 14:37:10 -07002215void OMXCodec::on_message(const omx_message &msg) {
Andreas Huber3a28b022011-03-28 14:48:28 -07002216 if (mState == ERROR) {
2217 LOGW("Dropping OMX message - we're in ERROR state.");
2218 return;
2219 }
2220
Andreas Huberbe06d262009-08-14 14:37:10 -07002221 switch (msg.type) {
2222 case omx_message::EVENT:
2223 {
2224 onEvent(
2225 msg.u.event_data.event, msg.u.event_data.data1,
2226 msg.u.event_data.data2);
2227
2228 break;
2229 }
2230
2231 case omx_message::EMPTY_BUFFER_DONE:
2232 {
2233 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
2234
Andreas Huber4c483422009-09-02 16:05:36 -07002235 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002236
2237 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2238 size_t i = 0;
2239 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2240 ++i;
2241 }
2242
2243 CHECK(i < buffers->size());
Andreas Huberbbbcf652010-12-07 14:25:54 -08002244 if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002245 LOGW("We already own input buffer %p, yet received "
2246 "an EMPTY_BUFFER_DONE.", buffer);
2247 }
2248
James Dong05c2fd52010-11-02 13:20:11 -07002249 BufferInfo* info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002250 info->mStatus = OWNED_BY_US;
James Dong05c2fd52010-11-02 13:20:11 -07002251
2252 // Buffer could not be released until empty buffer done is called.
2253 if (info->mMediaBuffer != NULL) {
James Dong31b9375f2010-11-10 21:11:41 -08002254 if (mIsEncoder &&
2255 (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2256 // If zero-copy mode is enabled this will send the
2257 // input buffer back to the upstream source.
2258 restorePatchedDataPointer(info);
2259 }
2260
James Dong05c2fd52010-11-02 13:20:11 -07002261 info->mMediaBuffer->release();
2262 info->mMediaBuffer = NULL;
2263 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002264
2265 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002266 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002267
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002268 status_t err = freeBuffer(kPortIndexInput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002269 CHECK_EQ(err, (status_t)OK);
Andreas Huber4a9375e2010-02-09 11:54:33 -08002270 } else if (mState != ERROR
2271 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002272 CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
Andreas Huber42fb5d62011-06-29 15:53:28 -07002273
2274 if (mFlags & kUseSecureInputBuffers) {
2275 drainAnyInputBuffer();
2276 } else {
2277 drainInputBuffer(&buffers->editItemAt(i));
2278 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002279 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002280 break;
2281 }
2282
2283 case omx_message::FILL_BUFFER_DONE:
2284 {
2285 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
2286 OMX_U32 flags = msg.u.extended_buffer_data.flags;
2287
Andreas Huber2ea14e22009-12-16 09:30:55 -08002288 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -07002289 buffer,
2290 msg.u.extended_buffer_data.range_length,
Andreas Huber2ea14e22009-12-16 09:30:55 -08002291 flags,
Andreas Huberbe06d262009-08-14 14:37:10 -07002292 msg.u.extended_buffer_data.timestamp,
2293 msg.u.extended_buffer_data.timestamp / 1E6);
2294
2295 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2296 size_t i = 0;
2297 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2298 ++i;
2299 }
2300
2301 CHECK(i < buffers->size());
2302 BufferInfo *info = &buffers->editItemAt(i);
2303
Andreas Huberbbbcf652010-12-07 14:25:54 -08002304 if (info->mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002305 LOGW("We already own output buffer %p, yet received "
2306 "a FILL_BUFFER_DONE.", buffer);
2307 }
2308
Andreas Huberbbbcf652010-12-07 14:25:54 -08002309 info->mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07002310
2311 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002312 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002313
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002314 status_t err = freeBuffer(kPortIndexOutput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002315 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002316
Andreas Huber2ea14e22009-12-16 09:30:55 -08002317#if 0
Andreas Huberd7795892009-08-26 10:33:47 -07002318 } else if (mPortStatus[kPortIndexOutput] == ENABLED
2319 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -07002320 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002321 mNoMoreOutputData = true;
2322 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08002323#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07002324 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002325 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -07002326
Andreas Huber52733b82010-01-25 10:41:35 -08002327 if (info->mMediaBuffer == NULL) {
2328 CHECK(mOMXLivesLocally);
2329 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
2330 CHECK(mQuirks & kDefersOutputBufferAllocation);
2331
2332 // The qcom video decoders on Nexus don't actually allocate
2333 // output buffer memory on a call to OMX_AllocateBuffer
2334 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
2335 // structure is only filled in later.
2336
2337 info->mMediaBuffer = new MediaBuffer(
2338 msg.u.extended_buffer_data.data_ptr,
2339 info->mSize);
2340 info->mMediaBuffer->setObserver(this);
2341 }
2342
Andreas Huberbe06d262009-08-14 14:37:10 -07002343 MediaBuffer *buffer = info->mMediaBuffer;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002344 bool isGraphicBuffer = buffer->graphicBuffer() != NULL;
Andreas Huberbe06d262009-08-14 14:37:10 -07002345
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002346 if (!isGraphicBuffer
2347 && msg.u.extended_buffer_data.range_offset
Andreas Huberf88f8442010-08-10 11:18:36 -07002348 + msg.u.extended_buffer_data.range_length
2349 > buffer->size()) {
2350 CODEC_LOGE(
2351 "Codec lied about its buffer size requirements, "
2352 "sending a buffer larger than the originally "
2353 "advertised size in FILL_BUFFER_DONE!");
2354 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002355 buffer->set_range(
2356 msg.u.extended_buffer_data.range_offset,
2357 msg.u.extended_buffer_data.range_length);
2358
2359 buffer->meta_data()->clear();
2360
Andreas Huberfa8de752009-10-08 10:07:49 -07002361 buffer->meta_data()->setInt64(
2362 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -07002363
2364 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
2365 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
2366 }
James Dong4108b1ed2011-06-07 19:45:54 -07002367 bool isCodecSpecific = false;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002368 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
2369 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
James Dong4108b1ed2011-06-07 19:45:54 -07002370 isCodecSpecific = true;
Andreas Huberea6a38c2009-11-16 15:43:38 -08002371 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002372
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002373 if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
Andreas Huber1e194162010-10-06 16:43:57 -07002374 buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
2375 }
2376
Andreas Huberbe06d262009-08-14 14:37:10 -07002377 buffer->meta_data()->setPointer(
2378 kKeyPlatformPrivate,
2379 msg.u.extended_buffer_data.platform_private);
2380
2381 buffer->meta_data()->setPointer(
2382 kKeyBufferID,
2383 msg.u.extended_buffer_data.buffer);
2384
Andreas Huber2ea14e22009-12-16 09:30:55 -08002385 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
2386 CODEC_LOGV("No more output data.");
2387 mNoMoreOutputData = true;
2388 }
Andreas Huber6624c9f2010-07-20 15:04:28 -07002389
James Dong32bb368a52011-06-20 11:40:52 -07002390 if (mIsEncoder) {
2391 int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
2392 buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
2393 }
2394
Andreas Huber6624c9f2010-07-20 15:04:28 -07002395 if (mTargetTimeUs >= 0) {
2396 CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
2397
2398 if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
2399 CODEC_LOGV(
2400 "skipping output buffer at timestamp %lld us",
2401 msg.u.extended_buffer_data.timestamp);
2402
2403 fillOutputBuffer(info);
2404 break;
2405 }
2406
2407 CODEC_LOGV(
2408 "returning output buffer at target timestamp "
2409 "%lld us",
2410 msg.u.extended_buffer_data.timestamp);
2411
2412 mTargetTimeUs = -1;
2413 }
2414
2415 mFilledBuffers.push_back(i);
2416 mBufferFilled.signal();
James Dongfc8b7c92010-12-07 14:37:27 -08002417 if (mIsEncoder) {
2418 sched_yield();
2419 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002420 }
2421
2422 break;
2423 }
2424
2425 default:
2426 {
2427 CHECK(!"should not be here.");
2428 break;
2429 }
2430 }
2431}
2432
Andreas Huberb1678602009-10-19 13:06:40 -07002433// Has the format changed in any way that the client would have to be aware of?
2434static bool formatHasNotablyChanged(
2435 const sp<MetaData> &from, const sp<MetaData> &to) {
2436 if (from.get() == NULL && to.get() == NULL) {
2437 return false;
2438 }
2439
Andreas Huberf68c1682009-10-21 14:01:30 -07002440 if ((from.get() == NULL && to.get() != NULL)
2441 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07002442 return true;
2443 }
2444
2445 const char *mime_from, *mime_to;
2446 CHECK(from->findCString(kKeyMIMEType, &mime_from));
2447 CHECK(to->findCString(kKeyMIMEType, &mime_to));
2448
2449 if (strcasecmp(mime_from, mime_to)) {
2450 return true;
2451 }
2452
2453 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
2454 int32_t colorFormat_from, colorFormat_to;
2455 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
2456 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
2457
2458 if (colorFormat_from != colorFormat_to) {
2459 return true;
2460 }
2461
2462 int32_t width_from, width_to;
2463 CHECK(from->findInt32(kKeyWidth, &width_from));
2464 CHECK(to->findInt32(kKeyWidth, &width_to));
2465
2466 if (width_from != width_to) {
2467 return true;
2468 }
2469
2470 int32_t height_from, height_to;
2471 CHECK(from->findInt32(kKeyHeight, &height_from));
2472 CHECK(to->findInt32(kKeyHeight, &height_to));
2473
2474 if (height_from != height_to) {
2475 return true;
2476 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002477
2478 int32_t left_from, top_from, right_from, bottom_from;
2479 CHECK(from->findRect(
2480 kKeyCropRect,
2481 &left_from, &top_from, &right_from, &bottom_from));
2482
2483 int32_t left_to, top_to, right_to, bottom_to;
2484 CHECK(to->findRect(
2485 kKeyCropRect,
2486 &left_to, &top_to, &right_to, &bottom_to));
2487
2488 if (left_to != left_from || top_to != top_from
2489 || right_to != right_from || bottom_to != bottom_from) {
2490 return true;
2491 }
Andreas Huberb1678602009-10-19 13:06:40 -07002492 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
2493 int32_t numChannels_from, numChannels_to;
2494 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
2495 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
2496
2497 if (numChannels_from != numChannels_to) {
2498 return true;
2499 }
2500
2501 int32_t sampleRate_from, sampleRate_to;
2502 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
2503 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
2504
2505 if (sampleRate_from != sampleRate_to) {
2506 return true;
2507 }
2508 }
2509
2510 return false;
2511}
2512
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002513void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2514 switch (event) {
2515 case OMX_EventCmdComplete:
2516 {
2517 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
2518 break;
2519 }
2520
2521 case OMX_EventError:
2522 {
2523 CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
2524
2525 setState(ERROR);
2526 break;
2527 }
2528
2529 case OMX_EventPortSettingsChanged:
2530 {
2531 CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
2532 data1, data2);
2533
2534 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
James Dong4a0c91f2011-09-09 13:19:59 -07002535 // There is no need to check whether mFilledBuffers is empty or not
2536 // when the OMX_EventPortSettingsChanged is not meant for reallocating
2537 // the output buffers.
2538 if (data1 == kPortIndexOutput) {
2539 CHECK(mFilledBuffers.empty());
2540 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002541 onPortSettingsChanged(data1);
James Dong7e91d912011-03-18 12:19:43 -07002542 } else if (data1 == kPortIndexOutput &&
2543 (data2 == OMX_IndexConfigCommonOutputCrop ||
2544 data2 == OMX_IndexConfigCommonScale)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002545
2546 sp<MetaData> oldOutputFormat = mOutputFormat;
2547 initOutputFormat(mSource->getFormat());
2548
James Dong7e91d912011-03-18 12:19:43 -07002549 if (data2 == OMX_IndexConfigCommonOutputCrop &&
2550 formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002551 mOutputPortSettingsHaveChanged = true;
2552
James Dong7e91d912011-03-18 12:19:43 -07002553 } else if (data2 == OMX_IndexConfigCommonScale) {
2554 OMX_CONFIG_SCALEFACTORTYPE scale;
2555 InitOMXParams(&scale);
2556 scale.nPortIndex = kPortIndexOutput;
2557
2558 // Change display dimension only when necessary.
2559 if (OK == mOMX->getConfig(
2560 mNode,
2561 OMX_IndexConfigCommonScale,
2562 &scale, sizeof(scale))) {
2563 int32_t left, top, right, bottom;
2564 CHECK(mOutputFormat->findRect(kKeyCropRect,
2565 &left, &top,
2566 &right, &bottom));
2567
2568 // The scale is in 16.16 format.
2569 // scale 1.0 = 0x010000. When there is no
2570 // need to change the display, skip it.
Steve Block71f2cf12011-10-20 11:56:00 +01002571 ALOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
James Dong7e91d912011-03-18 12:19:43 -07002572 scale.xWidth, scale.xHeight);
2573
2574 if (scale.xWidth != 0x010000) {
2575 mOutputFormat->setInt32(kKeyDisplayWidth,
2576 ((right - left + 1) * scale.xWidth) >> 16);
2577 mOutputPortSettingsHaveChanged = true;
2578 }
2579
2580 if (scale.xHeight != 0x010000) {
2581 mOutputFormat->setInt32(kKeyDisplayHeight,
2582 ((bottom - top + 1) * scale.xHeight) >> 16);
2583 mOutputPortSettingsHaveChanged = true;
2584 }
2585 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002586 }
2587 }
2588 break;
2589 }
2590
2591#if 0
2592 case OMX_EventBufferFlag:
2593 {
2594 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
2595
2596 if (data1 == kPortIndexOutput) {
2597 mNoMoreOutputData = true;
2598 }
2599 break;
2600 }
2601#endif
2602
2603 default:
2604 {
2605 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
2606 break;
2607 }
2608 }
2609}
2610
Andreas Huberbe06d262009-08-14 14:37:10 -07002611void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
2612 switch (cmd) {
2613 case OMX_CommandStateSet:
2614 {
2615 onStateChange((OMX_STATETYPE)data);
2616 break;
2617 }
2618
2619 case OMX_CommandPortDisable:
2620 {
2621 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002622 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002623
2624 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002625 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING);
2626 CHECK_EQ(mPortBuffers[portIndex].size(), 0u);
Andreas Huberbe06d262009-08-14 14:37:10 -07002627
2628 mPortStatus[portIndex] = DISABLED;
2629
2630 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002631 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002632
Andreas Huberb1678602009-10-19 13:06:40 -07002633 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07002634 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07002635
2636 // Don't notify clients if the output port settings change
2637 // wasn't of importance to them, i.e. it may be that just the
2638 // number of buffers has changed and nothing else.
James Dongbd9d0302011-09-01 19:31:01 -07002639 bool formatChanged = formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
2640 if (!mOutputPortSettingsHaveChanged) {
2641 mOutputPortSettingsHaveChanged = formatChanged;
2642 }
Andreas Hubercfd55572009-10-09 14:11:28 -07002643
James Dong0209da12011-09-12 19:56:23 -07002644 status_t err = enablePortAsync(portIndex);
Andreas Huberba1b16792011-01-19 09:20:58 -08002645 if (err != OK) {
James Dong0209da12011-09-12 19:56:23 -07002646 CODEC_LOGE("enablePortAsync(%ld) failed (err = %d)", portIndex, err);
Andreas Huberba1b16792011-01-19 09:20:58 -08002647 setState(ERROR);
James Dong0209da12011-09-12 19:56:23 -07002648 } else {
2649 err = allocateBuffersOnPort(portIndex);
2650 if (err != OK) {
2651 CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
2652 setState(ERROR);
2653 }
Andreas Huberba1b16792011-01-19 09:20:58 -08002654 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002655 }
2656 break;
2657 }
2658
2659 case OMX_CommandPortEnable:
2660 {
2661 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002662 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002663
2664 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002665 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002666
2667 mPortStatus[portIndex] = ENABLED;
2668
2669 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002670 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002671
2672 setState(EXECUTING);
2673
2674 fillOutputBuffers();
2675 }
2676 break;
2677 }
2678
2679 case OMX_CommandFlush:
2680 {
2681 OMX_U32 portIndex = data;
2682
Andreas Huber4c483422009-09-02 16:05:36 -07002683 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002684
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002685 CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN);
Andreas Huberbe06d262009-08-14 14:37:10 -07002686 mPortStatus[portIndex] = ENABLED;
2687
2688 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
2689 mPortBuffers[portIndex].size());
2690
2691 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002692 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002693
2694 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002695 } else if (mState == EXECUTING_TO_IDLE) {
2696 if (mPortStatus[kPortIndexInput] == ENABLED
2697 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002698 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07002699 "transition from EXECUTING to IDLE.");
2700
2701 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2702 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2703
2704 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002705 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002706 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002707 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002708 } else {
2709 // We're flushing both ports in preparation for seeking.
2710
2711 if (mPortStatus[kPortIndexInput] == ENABLED
2712 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002713 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07002714 " seek-time.");
2715
Andreas Huber1f24b302010-06-10 11:12:39 -07002716 // We implicitly resume pulling on our upstream source.
2717 mPaused = false;
2718
Andreas Huberbe06d262009-08-14 14:37:10 -07002719 drainInputBuffers();
2720 fillOutputBuffers();
2721 }
Andreas Huberb9289832011-02-08 13:10:25 -08002722
2723 if (mOutputPortSettingsChangedPending) {
2724 CODEC_LOGV(
2725 "Honoring deferred output port settings change.");
2726
2727 mOutputPortSettingsChangedPending = false;
2728 onPortSettingsChanged(kPortIndexOutput);
2729 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002730 }
2731
2732 break;
2733 }
2734
2735 default:
2736 {
Andreas Huber4c483422009-09-02 16:05:36 -07002737 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07002738 break;
2739 }
2740 }
2741}
2742
2743void OMXCodec::onStateChange(OMX_STATETYPE newState) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002744 CODEC_LOGV("onStateChange %d", newState);
2745
Andreas Huberbe06d262009-08-14 14:37:10 -07002746 switch (newState) {
2747 case OMX_StateIdle:
2748 {
Andreas Huber4c483422009-09-02 16:05:36 -07002749 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002750 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07002751 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002752 mNode, OMX_CommandStateSet, OMX_StateExecuting);
2753
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002754 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002755
2756 setState(IDLE_TO_EXECUTING);
2757 } else {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002758 CHECK_EQ((int)mState, (int)EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002759
2760 CHECK_EQ(
2761 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
2762 mPortBuffers[kPortIndexInput].size());
2763
2764 CHECK_EQ(
2765 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
2766 mPortBuffers[kPortIndexOutput].size());
2767
Andreas Huber784202e2009-10-15 13:46:54 -07002768 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002769 mNode, OMX_CommandStateSet, OMX_StateLoaded);
2770
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002771 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002772
2773 err = freeBuffersOnPort(kPortIndexInput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002774 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002775
2776 err = freeBuffersOnPort(kPortIndexOutput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002777 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002778
2779 mPortStatus[kPortIndexInput] = ENABLED;
2780 mPortStatus[kPortIndexOutput] = ENABLED;
2781
Jamie Gennisc0e42932011-10-25 14:50:16 -07002782 if ((mFlags & kEnableGrallocUsageProtected) &&
2783 mNativeWindow != NULL) {
2784 // We push enough 1x1 blank buffers to ensure that one of
2785 // them has made it to the display. This allows the OMX
2786 // component teardown to zero out any protected buffers
2787 // without the risk of scanning out one of those buffers.
2788 pushBlankBuffersToNativeWindow();
2789 }
2790
Andreas Huberbe06d262009-08-14 14:37:10 -07002791 setState(IDLE_TO_LOADED);
2792 }
2793 break;
2794 }
2795
2796 case OMX_StateExecuting:
2797 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002798 CHECK_EQ((int)mState, (int)IDLE_TO_EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002799
Andreas Huber4c483422009-09-02 16:05:36 -07002800 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002801
Andreas Huberb9289832011-02-08 13:10:25 -08002802 mOutputPortSettingsChangedPending = false;
2803
Andreas Huberbe06d262009-08-14 14:37:10 -07002804 setState(EXECUTING);
2805
Andreas Huber42978e52009-08-27 10:08:39 -07002806 // Buffers will be submitted to the component in the first
2807 // call to OMXCodec::read as mInitialBufferSubmit is true at
2808 // this point. This ensures that this on_message call returns,
2809 // releases the lock and ::init can notice the state change and
2810 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07002811 break;
2812 }
2813
2814 case OMX_StateLoaded:
2815 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002816 CHECK_EQ((int)mState, (int)IDLE_TO_LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002817
Andreas Huber4c483422009-09-02 16:05:36 -07002818 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002819
2820 setState(LOADED);
2821 break;
2822 }
2823
Andreas Huberc712b9f2010-01-20 15:05:46 -08002824 case OMX_StateInvalid:
2825 {
2826 setState(ERROR);
2827 break;
2828 }
2829
Andreas Huberbe06d262009-08-14 14:37:10 -07002830 default:
2831 {
2832 CHECK(!"should not be here.");
2833 break;
2834 }
2835 }
2836}
2837
2838// static
2839size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
2840 size_t n = 0;
2841 for (size_t i = 0; i < buffers.size(); ++i) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002842 if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002843 ++n;
2844 }
2845 }
2846
2847 return n;
2848}
2849
2850status_t OMXCodec::freeBuffersOnPort(
2851 OMX_U32 portIndex, bool onlyThoseWeOwn) {
2852 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2853
2854 status_t stickyErr = OK;
2855
2856 for (size_t i = buffers->size(); i-- > 0;) {
2857 BufferInfo *info = &buffers->editItemAt(i);
2858
Andreas Huberbbbcf652010-12-07 14:25:54 -08002859 if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002860 continue;
2861 }
2862
Andreas Huberbbbcf652010-12-07 14:25:54 -08002863 CHECK(info->mStatus == OWNED_BY_US
2864 || info->mStatus == OWNED_BY_NATIVE_WINDOW);
Andreas Huberbe06d262009-08-14 14:37:10 -07002865
Andreas Huber92022852009-09-14 15:24:14 -07002866 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
2867
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002868 status_t err = freeBuffer(portIndex, i);
Andreas Huberbe06d262009-08-14 14:37:10 -07002869
2870 if (err != OK) {
2871 stickyErr = err;
2872 }
2873
Andreas Huberbe06d262009-08-14 14:37:10 -07002874 }
2875
2876 CHECK(onlyThoseWeOwn || buffers->isEmpty());
2877
2878 return stickyErr;
2879}
2880
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002881status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) {
2882 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2883
2884 BufferInfo *info = &buffers->editItemAt(bufIndex);
2885
2886 status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
2887
2888 if (err == OK && info->mMediaBuffer != NULL) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002889 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002890 info->mMediaBuffer->setObserver(NULL);
2891
2892 // Make sure nobody but us owns this buffer at this point.
2893 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
2894
2895 // Cancel the buffer if it belongs to an ANativeWindow.
2896 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
Andreas Huberbbbcf652010-12-07 14:25:54 -08002897 if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002898 err = cancelBufferToNativeWindow(info);
2899 }
2900
2901 info->mMediaBuffer->release();
James Dong31b9375f2010-11-10 21:11:41 -08002902 info->mMediaBuffer = NULL;
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002903 }
2904
2905 if (err == OK) {
2906 buffers->removeAt(bufIndex);
2907 }
2908
2909 return err;
2910}
2911
Andreas Huberbe06d262009-08-14 14:37:10 -07002912void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07002913 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002914
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002915 CHECK_EQ((int)mState, (int)EXECUTING);
2916 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberb9289832011-02-08 13:10:25 -08002917 CHECK(!mOutputPortSettingsChangedPending);
2918
2919 if (mPortStatus[kPortIndexOutput] != ENABLED) {
2920 CODEC_LOGV("Deferring output port settings change.");
2921 mOutputPortSettingsChangedPending = true;
2922 return;
2923 }
2924
Andreas Huberbe06d262009-08-14 14:37:10 -07002925 setState(RECONFIGURING);
2926
2927 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07002928 if (!flushPortAsync(portIndex)) {
2929 onCmdComplete(OMX_CommandFlush, portIndex);
2930 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002931 } else {
2932 disablePortAsync(portIndex);
2933 }
2934}
2935
Andreas Huber404cc412009-08-25 14:26:05 -07002936bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07002937 CHECK(mState == EXECUTING || mState == RECONFIGURING
2938 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002939
Andreas Huber4c483422009-09-02 16:05:36 -07002940 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07002941 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
2942 mPortBuffers[portIndex].size());
2943
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002944 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002945 mPortStatus[portIndex] = SHUTTING_DOWN;
2946
Andreas Huber404cc412009-08-25 14:26:05 -07002947 if ((mQuirks & kRequiresFlushCompleteEmulation)
2948 && countBuffersWeOwn(mPortBuffers[portIndex])
2949 == mPortBuffers[portIndex].size()) {
2950 // No flush is necessary and this component fails to send a
2951 // flush-complete event in this case.
2952
2953 return false;
2954 }
2955
Andreas Huberbe06d262009-08-14 14:37:10 -07002956 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002957 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002958 CHECK_EQ(err, (status_t)OK);
Andreas Huber404cc412009-08-25 14:26:05 -07002959
2960 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002961}
2962
2963void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
2964 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2965
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002966 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002967 mPortStatus[portIndex] = DISABLING;
2968
Andreas Huberd222c842010-08-26 14:29:34 -07002969 CODEC_LOGV("sending OMX_CommandPortDisable(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002970 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002971 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002972 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002973
2974 freeBuffersOnPort(portIndex, true);
2975}
2976
James Dong0209da12011-09-12 19:56:23 -07002977status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002978 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2979
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002980 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002981 mPortStatus[portIndex] = ENABLING;
2982
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002983 CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
James Dong0209da12011-09-12 19:56:23 -07002984 return mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002985}
2986
2987void OMXCodec::fillOutputBuffers() {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002988 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002989
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002990 // This is a workaround for some decoders not properly reporting
2991 // end-of-output-stream. If we own all input buffers and also own
2992 // all output buffers and we already signalled end-of-input-stream,
2993 // the end-of-output-stream is implied.
2994 if (mSignalledEOS
2995 && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
2996 == mPortBuffers[kPortIndexInput].size()
2997 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
2998 == mPortBuffers[kPortIndexOutput].size()) {
2999 mNoMoreOutputData = true;
3000 mBufferFilled.signal();
3001
3002 return;
3003 }
3004
Andreas Huberbe06d262009-08-14 14:37:10 -07003005 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3006 for (size_t i = 0; i < buffers->size(); ++i) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003007 BufferInfo *info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003008 if (info->mStatus == OWNED_BY_US) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003009 fillOutputBuffer(&buffers->editItemAt(i));
3010 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003011 }
3012}
3013
3014void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07003015 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07003016
Andreas Huber42fb5d62011-06-29 15:53:28 -07003017 if (mFlags & kUseSecureInputBuffers) {
3018 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
3019 for (size_t i = 0; i < buffers->size(); ++i) {
3020 if (!drainAnyInputBuffer()
3021 || (mFlags & kOnlySubmitOneInputBufferAtOneTime)) {
3022 break;
3023 }
James Dong5f3ab062011-01-25 16:31:28 -08003024 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07003025 } else {
3026 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
3027 for (size_t i = 0; i < buffers->size(); ++i) {
3028 BufferInfo *info = &buffers->editItemAt(i);
James Dong5f3ab062011-01-25 16:31:28 -08003029
Andreas Huber42fb5d62011-06-29 15:53:28 -07003030 if (info->mStatus != OWNED_BY_US) {
3031 continue;
3032 }
James Dong5f3ab062011-01-25 16:31:28 -08003033
Andreas Huber42fb5d62011-06-29 15:53:28 -07003034 if (!drainInputBuffer(info)) {
3035 break;
3036 }
3037
3038 if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
3039 break;
3040 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08003041 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003042 }
3043}
3044
Andreas Huber42fb5d62011-06-29 15:53:28 -07003045bool OMXCodec::drainAnyInputBuffer() {
3046 return drainInputBuffer((BufferInfo *)NULL);
3047}
3048
3049OMXCodec::BufferInfo *OMXCodec::findInputBufferByDataPointer(void *ptr) {
3050 Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
3051 for (size_t i = 0; i < infos->size(); ++i) {
3052 BufferInfo *info = &infos->editItemAt(i);
3053
3054 if (info->mData == ptr) {
3055 CODEC_LOGV(
3056 "input buffer data ptr = %p, buffer_id = %p",
3057 ptr,
3058 info->mBuffer);
3059
3060 return info;
3061 }
3062 }
3063
3064 TRESPASS();
3065}
3066
3067OMXCodec::BufferInfo *OMXCodec::findEmptyInputBuffer() {
3068 Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
3069 for (size_t i = 0; i < infos->size(); ++i) {
3070 BufferInfo *info = &infos->editItemAt(i);
3071
3072 if (info->mStatus == OWNED_BY_US) {
3073 return info;
3074 }
3075 }
3076
3077 TRESPASS();
3078}
3079
Andreas Huberbbbcf652010-12-07 14:25:54 -08003080bool OMXCodec::drainInputBuffer(BufferInfo *info) {
Andreas Huber42fb5d62011-06-29 15:53:28 -07003081 if (info != NULL) {
3082 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
3083 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003084
3085 if (mSignalledEOS) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003086 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003087 }
3088
3089 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
Andreas Huber42fb5d62011-06-29 15:53:28 -07003090 CHECK(!(mFlags & kUseSecureInputBuffers));
3091
Andreas Huberbe06d262009-08-14 14:37:10 -07003092 const CodecSpecificData *specific =
3093 mCodecSpecificData[mCodecSpecificDataIndex];
3094
3095 size_t size = specific->mSize;
3096
Andreas Hubere6c40962009-09-10 14:13:30 -07003097 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07003098 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003099 static const uint8_t kNALStartCode[4] =
3100 { 0x00, 0x00, 0x00, 0x01 };
3101
Andreas Huberc712b9f2010-01-20 15:05:46 -08003102 CHECK(info->mSize >= specific->mSize + 4);
Andreas Huberbe06d262009-08-14 14:37:10 -07003103
3104 size += 4;
3105
Andreas Huberc712b9f2010-01-20 15:05:46 -08003106 memcpy(info->mData, kNALStartCode, 4);
3107 memcpy((uint8_t *)info->mData + 4,
Andreas Huberbe06d262009-08-14 14:37:10 -07003108 specific->mData, specific->mSize);
3109 } else {
Andreas Huberc712b9f2010-01-20 15:05:46 -08003110 CHECK(info->mSize >= specific->mSize);
3111 memcpy(info->mData, specific->mData, specific->mSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07003112 }
3113
Andreas Huber2ea14e22009-12-16 09:30:55 -08003114 mNoMoreOutputData = false;
3115
Andreas Huberdbcb2c62010-01-14 11:32:13 -08003116 CODEC_LOGV("calling emptyBuffer with codec specific data");
3117
Andreas Huber784202e2009-10-15 13:46:54 -07003118 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07003119 mNode, info->mBuffer, 0, size,
3120 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
3121 0);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003122 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003123
Andreas Huberbbbcf652010-12-07 14:25:54 -08003124 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07003125
3126 ++mCodecSpecificDataIndex;
Andreas Huberbbbcf652010-12-07 14:25:54 -08003127 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003128 }
3129
Andreas Huber1f24b302010-06-10 11:12:39 -07003130 if (mPaused) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003131 return false;
Andreas Huber1f24b302010-06-10 11:12:39 -07003132 }
3133
Andreas Huberbe06d262009-08-14 14:37:10 -07003134 status_t err;
Andreas Huber2ea14e22009-12-16 09:30:55 -08003135
Andreas Hubera4357ad2010-04-02 12:49:54 -07003136 bool signalEOS = false;
3137 int64_t timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07003138
Andreas Hubera4357ad2010-04-02 12:49:54 -07003139 size_t offset = 0;
3140 int32_t n = 0;
Andreas Huberbbbcf652010-12-07 14:25:54 -08003141
Pannag Sanketi557b7092011-08-18 21:53:02 -07003142
Andreas Hubera4357ad2010-04-02 12:49:54 -07003143 for (;;) {
3144 MediaBuffer *srcBuffer;
3145 if (mSeekTimeUs >= 0) {
3146 if (mLeftOverBuffer) {
3147 mLeftOverBuffer->release();
3148 mLeftOverBuffer = NULL;
3149 }
James Dong2144f632010-12-11 10:43:41 -08003150
3151 MediaSource::ReadOptions options;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003152 options.setSeekTo(mSeekTimeUs, mSeekMode);
Andreas Hubera4357ad2010-04-02 12:49:54 -07003153
3154 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003155 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
Andreas Hubera4357ad2010-04-02 12:49:54 -07003156 mBufferFilled.signal();
3157
3158 err = mSource->read(&srcBuffer, &options);
Andreas Huber6624c9f2010-07-20 15:04:28 -07003159
3160 if (err == OK) {
3161 int64_t targetTimeUs;
3162 if (srcBuffer->meta_data()->findInt64(
3163 kKeyTargetTime, &targetTimeUs)
3164 && targetTimeUs >= 0) {
Andreas Huberb9289832011-02-08 13:10:25 -08003165 CODEC_LOGV("targetTimeUs = %lld us", targetTimeUs);
Andreas Huber6624c9f2010-07-20 15:04:28 -07003166 mTargetTimeUs = targetTimeUs;
3167 } else {
3168 mTargetTimeUs = -1;
3169 }
3170 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003171 } else if (mLeftOverBuffer) {
3172 srcBuffer = mLeftOverBuffer;
3173 mLeftOverBuffer = NULL;
3174
3175 err = OK;
3176 } else {
James Dong2144f632010-12-11 10:43:41 -08003177 err = mSource->read(&srcBuffer);
Andreas Hubera4357ad2010-04-02 12:49:54 -07003178 }
3179
3180 if (err != OK) {
3181 signalEOS = true;
3182 mFinalStatus = err;
3183 mSignalledEOS = true;
Andreas Huber94bced12010-12-14 09:50:46 -08003184 mBufferFilled.signal();
Andreas Hubera4357ad2010-04-02 12:49:54 -07003185 break;
3186 }
3187
Andreas Huber42fb5d62011-06-29 15:53:28 -07003188 if (mFlags & kUseSecureInputBuffers) {
3189 info = findInputBufferByDataPointer(srcBuffer->data());
3190 CHECK(info != NULL);
3191 }
3192
Andreas Hubera4357ad2010-04-02 12:49:54 -07003193 size_t remainingBytes = info->mSize - offset;
3194
3195 if (srcBuffer->range_length() > remainingBytes) {
3196 if (offset == 0) {
3197 CODEC_LOGE(
3198 "Codec's input buffers are too small to accomodate "
3199 "buffer read from source (info->mSize = %d, srcLength = %d)",
3200 info->mSize, srcBuffer->range_length());
3201
3202 srcBuffer->release();
3203 srcBuffer = NULL;
3204
3205 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003206 return false;
Andreas Hubera4357ad2010-04-02 12:49:54 -07003207 }
3208
3209 mLeftOverBuffer = srcBuffer;
3210 break;
3211 }
3212
James Dong05c2fd52010-11-02 13:20:11 -07003213 bool releaseBuffer = true;
James Dong4f501f02010-06-07 14:41:41 -07003214 if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
3215 CHECK(mOMXLivesLocally && offset == 0);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003216
3217 OMX_BUFFERHEADERTYPE *header =
3218 (OMX_BUFFERHEADERTYPE *)info->mBuffer;
3219
James Dong31b9375f2010-11-10 21:11:41 -08003220 CHECK(header->pBuffer == info->mData);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003221
3222 header->pBuffer =
3223 (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
3224
James Dong05c2fd52010-11-02 13:20:11 -07003225 releaseBuffer = false;
3226 info->mMediaBuffer = srcBuffer;
James Dong4f501f02010-06-07 14:41:41 -07003227 } else {
Andreas Huber42fb5d62011-06-29 15:53:28 -07003228 if (mFlags & kStoreMetaDataInVideoBuffers) {
James Dong05c2fd52010-11-02 13:20:11 -07003229 releaseBuffer = false;
3230 info->mMediaBuffer = srcBuffer;
3231 }
Andreas Huber42fb5d62011-06-29 15:53:28 -07003232
3233 if (mFlags & kUseSecureInputBuffers) {
3234 // Data in "info" is already provided at this time.
3235
3236 releaseBuffer = false;
3237
3238 CHECK(info->mMediaBuffer == NULL);
3239 info->mMediaBuffer = srcBuffer;
3240 } else {
Pannag Sanketi557b7092011-08-18 21:53:02 -07003241 CHECK(srcBuffer->data() != NULL) ;
Andreas Huber42fb5d62011-06-29 15:53:28 -07003242 memcpy((uint8_t *)info->mData + offset,
3243 (const uint8_t *)srcBuffer->data()
3244 + srcBuffer->range_offset(),
3245 srcBuffer->range_length());
3246 }
James Dong4f501f02010-06-07 14:41:41 -07003247 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003248
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003249 int64_t lastBufferTimeUs;
3250 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
Andreas Huber6624c9f2010-07-20 15:04:28 -07003251 CHECK(lastBufferTimeUs >= 0);
James Dong4108b1ed2011-06-07 19:45:54 -07003252 if (mIsEncoder) {
3253 mDecodingTimeList.push_back(lastBufferTimeUs);
3254 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003255
Andreas Hubera4357ad2010-04-02 12:49:54 -07003256 if (offset == 0) {
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003257 timestampUs = lastBufferTimeUs;
Andreas Hubera4357ad2010-04-02 12:49:54 -07003258 }
3259
3260 offset += srcBuffer->range_length();
3261
Andreas Huber4b3913a2011-05-11 14:13:42 -07003262 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mMIME)) {
3263 CHECK(!(mQuirks & kSupportsMultipleFramesPerInputBuffer));
3264 CHECK_GE(info->mSize, offset + sizeof(int32_t));
3265
3266 int32_t numPageSamples;
3267 if (!srcBuffer->meta_data()->findInt32(
3268 kKeyValidSamples, &numPageSamples)) {
3269 numPageSamples = -1;
3270 }
3271
3272 memcpy((uint8_t *)info->mData + offset,
3273 &numPageSamples,
3274 sizeof(numPageSamples));
3275
3276 offset += sizeof(numPageSamples);
3277 }
3278
James Dong05c2fd52010-11-02 13:20:11 -07003279 if (releaseBuffer) {
3280 srcBuffer->release();
3281 srcBuffer = NULL;
3282 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003283
3284 ++n;
3285
3286 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
3287 break;
3288 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07003289
3290 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
3291
3292 if (coalescedDurationUs > 250000ll) {
3293 // Don't coalesce more than 250ms worth of encoded data at once.
3294 break;
3295 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07003296 }
3297
3298 if (n > 1) {
Steve Block71f2cf12011-10-20 11:56:00 +01003299 ALOGV("coalesced %d frames into one input buffer", n);
Andreas Huberbe06d262009-08-14 14:37:10 -07003300 }
3301
3302 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberbe06d262009-08-14 14:37:10 -07003303
Andreas Hubera4357ad2010-04-02 12:49:54 -07003304 if (signalEOS) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003305 flags |= OMX_BUFFERFLAG_EOS;
Andreas Huberbe06d262009-08-14 14:37:10 -07003306 } else {
Andreas Huber2ea14e22009-12-16 09:30:55 -08003307 mNoMoreOutputData = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003308 }
3309
Andreas Hubera4357ad2010-04-02 12:49:54 -07003310 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
3311 "timestamp %lld us (%.2f secs)",
3312 info->mBuffer, offset,
3313 timestampUs, timestampUs / 1E6);
Andreas Huber3f427072009-10-08 11:02:27 -07003314
Andreas Huber42fb5d62011-06-29 15:53:28 -07003315 if (info == NULL) {
3316 CHECK(mFlags & kUseSecureInputBuffers);
3317 CHECK(signalEOS);
3318
3319 // This is fishy, there's still a MediaBuffer corresponding to this
3320 // info available to the source at this point even though we're going
3321 // to use it to signal EOS to the codec.
3322 info = findEmptyInputBuffer();
3323 }
3324
Andreas Huber784202e2009-10-15 13:46:54 -07003325 err = mOMX->emptyBuffer(
Andreas Hubera4357ad2010-04-02 12:49:54 -07003326 mNode, info->mBuffer, 0, offset,
Andreas Huberfa8de752009-10-08 10:07:49 -07003327 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07003328
3329 if (err != OK) {
3330 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003331 return false;
Andreas Huber3f427072009-10-08 11:02:27 -07003332 }
3333
Andreas Huberbbbcf652010-12-07 14:25:54 -08003334 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberea6a38c2009-11-16 15:43:38 -08003335
3336 // This component does not ever signal the EOS flag on output buffers,
3337 // Thanks for nothing.
3338 if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) {
3339 mNoMoreOutputData = true;
3340 mBufferFilled.signal();
3341 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08003342
3343 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003344}
3345
3346void OMXCodec::fillOutputBuffer(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003347 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Andreas Huberbe06d262009-08-14 14:37:10 -07003348
Andreas Huber404cc412009-08-25 14:26:05 -07003349 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07003350 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07003351 "calling fillOutputBuffer");
3352 return;
3353 }
3354
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003355 if (info->mMediaBuffer != NULL) {
3356 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
3357 if (graphicBuffer != 0) {
3358 // When using a native buffer we need to lock the buffer before
3359 // giving it to OMX.
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003360 CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
3361 int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
3362 graphicBuffer.get());
3363 if (err != 0) {
3364 CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003365
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003366 setState(ERROR);
3367 return;
3368 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003369 }
3370 }
3371
3372 CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07003373 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber8f14c552010-04-12 10:20:12 -07003374
3375 if (err != OK) {
3376 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
3377
3378 setState(ERROR);
3379 return;
3380 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003381
Andreas Huberbbbcf652010-12-07 14:25:54 -08003382 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07003383}
3384
Andreas Huberbbbcf652010-12-07 14:25:54 -08003385bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003386 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
3387 for (size_t i = 0; i < buffers->size(); ++i) {
3388 if ((*buffers)[i].mBuffer == buffer) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003389 return drainInputBuffer(&buffers->editItemAt(i));
Andreas Huberbe06d262009-08-14 14:37:10 -07003390 }
3391 }
3392
3393 CHECK(!"should not be here.");
Andreas Huberbbbcf652010-12-07 14:25:54 -08003394
3395 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003396}
3397
3398void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
3399 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3400 for (size_t i = 0; i < buffers->size(); ++i) {
3401 if ((*buffers)[i].mBuffer == buffer) {
3402 fillOutputBuffer(&buffers->editItemAt(i));
3403 return;
3404 }
3405 }
3406
3407 CHECK(!"should not be here.");
3408}
3409
3410void OMXCodec::setState(State newState) {
3411 mState = newState;
3412 mAsyncCompletion.signal();
3413
3414 // This may cause some spurious wakeups but is necessary to
3415 // unblock the reader if we enter ERROR state.
3416 mBufferFilled.signal();
3417}
3418
James Dongd9ac6212011-07-15 15:25:36 -07003419status_t OMXCodec::waitForBufferFilled_l() {
James Dong92d6ea32011-08-14 16:14:12 -07003420
3421 if (mIsEncoder) {
3422 // For timelapse video recording, the timelapse video recording may
3423 // not send an input frame for a _long_ time. Do not use timeout
3424 // for video encoding.
3425 return mBufferFilled.wait(mLock);
3426 }
James Dong4a0c91f2011-09-09 13:19:59 -07003427 status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutNs);
James Dongd9ac6212011-07-15 15:25:36 -07003428 if (err != OK) {
James Dong92d6ea32011-08-14 16:14:12 -07003429 CODEC_LOGE("Timed out waiting for output buffers: %d/%d",
James Dongd9ac6212011-07-15 15:25:36 -07003430 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
3431 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
3432 }
3433 return err;
3434}
3435
Andreas Huberda050cf22009-09-02 14:01:43 -07003436void OMXCodec::setRawAudioFormat(
3437 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
James Dongabed93a2010-04-22 17:27:04 -07003438
3439 // port definition
3440 OMX_PARAM_PORTDEFINITIONTYPE def;
3441 InitOMXParams(&def);
3442 def.nPortIndex = portIndex;
3443 status_t err = mOMX->getParameter(
3444 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003445 CHECK_EQ(err, (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003446 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
3447 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003448 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003449
3450 // pcm param
Andreas Huberda050cf22009-09-02 14:01:43 -07003451 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07003452 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07003453 pcmParams.nPortIndex = portIndex;
3454
James Dongabed93a2010-04-22 17:27:04 -07003455 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003456 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3457
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003458 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003459
3460 pcmParams.nChannels = numChannels;
3461 pcmParams.eNumData = OMX_NumericalDataSigned;
3462 pcmParams.bInterleaved = OMX_TRUE;
3463 pcmParams.nBitPerSample = 16;
3464 pcmParams.nSamplingRate = sampleRate;
3465 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3466
3467 if (numChannels == 1) {
3468 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
3469 } else {
3470 CHECK_EQ(numChannels, 2);
3471
3472 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
3473 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
3474 }
3475
Andreas Huber784202e2009-10-15 13:46:54 -07003476 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003477 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3478
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003479 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003480}
3481
James Dong17299ab2010-05-14 15:45:22 -07003482static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
3483 if (isAMRWB) {
3484 if (bps <= 6600) {
3485 return OMX_AUDIO_AMRBandModeWB0;
3486 } else if (bps <= 8850) {
3487 return OMX_AUDIO_AMRBandModeWB1;
3488 } else if (bps <= 12650) {
3489 return OMX_AUDIO_AMRBandModeWB2;
3490 } else if (bps <= 14250) {
3491 return OMX_AUDIO_AMRBandModeWB3;
3492 } else if (bps <= 15850) {
3493 return OMX_AUDIO_AMRBandModeWB4;
3494 } else if (bps <= 18250) {
3495 return OMX_AUDIO_AMRBandModeWB5;
3496 } else if (bps <= 19850) {
3497 return OMX_AUDIO_AMRBandModeWB6;
3498 } else if (bps <= 23050) {
3499 return OMX_AUDIO_AMRBandModeWB7;
3500 }
3501
3502 // 23850 bps
3503 return OMX_AUDIO_AMRBandModeWB8;
3504 } else { // AMRNB
3505 if (bps <= 4750) {
3506 return OMX_AUDIO_AMRBandModeNB0;
3507 } else if (bps <= 5150) {
3508 return OMX_AUDIO_AMRBandModeNB1;
3509 } else if (bps <= 5900) {
3510 return OMX_AUDIO_AMRBandModeNB2;
3511 } else if (bps <= 6700) {
3512 return OMX_AUDIO_AMRBandModeNB3;
3513 } else if (bps <= 7400) {
3514 return OMX_AUDIO_AMRBandModeNB4;
3515 } else if (bps <= 7950) {
3516 return OMX_AUDIO_AMRBandModeNB5;
3517 } else if (bps <= 10200) {
3518 return OMX_AUDIO_AMRBandModeNB6;
3519 }
3520
3521 // 12200 bps
3522 return OMX_AUDIO_AMRBandModeNB7;
3523 }
3524}
3525
3526void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
Andreas Huber8768f2c2009-12-01 15:26:54 -08003527 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003528
Andreas Huber8768f2c2009-12-01 15:26:54 -08003529 OMX_AUDIO_PARAM_AMRTYPE def;
3530 InitOMXParams(&def);
3531 def.nPortIndex = portIndex;
Andreas Huberbe06d262009-08-14 14:37:10 -07003532
Andreas Huber8768f2c2009-12-01 15:26:54 -08003533 status_t err =
3534 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07003535
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003536 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003537
Andreas Huber8768f2c2009-12-01 15:26:54 -08003538 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
James Dongabed93a2010-04-22 17:27:04 -07003539
James Dong17299ab2010-05-14 15:45:22 -07003540 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
Andreas Huber8768f2c2009-12-01 15:26:54 -08003541 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003542 CHECK_EQ(err, (status_t)OK);
Andreas Huberee606e62009-09-08 10:19:21 -07003543
3544 ////////////////////////
3545
3546 if (mIsEncoder) {
3547 sp<MetaData> format = mSource->getFormat();
3548 int32_t sampleRate;
3549 int32_t numChannels;
3550 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
3551 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
3552
3553 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
3554 }
3555}
3556
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003557status_t OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
3558 if (numChannels > 2)
3559 LOGW("Number of channels: (%d) \n", numChannels);
3560
Andreas Huberda050cf22009-09-02 14:01:43 -07003561 if (mIsEncoder) {
James Dongabed93a2010-04-22 17:27:04 -07003562 //////////////// input port ////////////////////
Andreas Huberda050cf22009-09-02 14:01:43 -07003563 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
James Dongabed93a2010-04-22 17:27:04 -07003564
3565 //////////////// output port ////////////////////
3566 // format
3567 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
3568 format.nPortIndex = kPortIndexOutput;
3569 format.nIndex = 0;
3570 status_t err = OMX_ErrorNone;
3571 while (OMX_ErrorNone == err) {
3572 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003573 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003574 if (format.eEncoding == OMX_AUDIO_CodingAAC) {
3575 break;
3576 }
3577 format.nIndex++;
3578 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003579 CHECK_EQ((status_t)OK, err);
James Dongabed93a2010-04-22 17:27:04 -07003580 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003581 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003582
3583 // port definition
3584 OMX_PARAM_PORTDEFINITIONTYPE def;
3585 InitOMXParams(&def);
3586 def.nPortIndex = kPortIndexOutput;
3587 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003588 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003589 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
3590 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
3591 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003592 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003593
3594 // profile
3595 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
3596 InitOMXParams(&profile);
3597 profile.nPortIndex = kPortIndexOutput;
3598 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003599 &profile, sizeof(profile)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003600 profile.nChannels = numChannels;
3601 profile.eChannelMode = (numChannels == 1?
3602 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
3603 profile.nSampleRate = sampleRate;
James Dong17299ab2010-05-14 15:45:22 -07003604 profile.nBitRate = bitRate;
James Dongabed93a2010-04-22 17:27:04 -07003605 profile.nAudioBandWidth = 0;
3606 profile.nFrameLength = 0;
3607 profile.nAACtools = OMX_AUDIO_AACToolAll;
3608 profile.nAACERtools = OMX_AUDIO_AACERNone;
3609 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
3610 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003611 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
3612 &profile, sizeof(profile));
James Dongabed93a2010-04-22 17:27:04 -07003613
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003614 if (err != OK) {
3615 CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err);
3616 return err;
3617 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003618 } else {
3619 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07003620 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07003621 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003622
Andreas Huber784202e2009-10-15 13:46:54 -07003623 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003624 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003625 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003626
Andreas Huberda050cf22009-09-02 14:01:43 -07003627 profile.nChannels = numChannels;
3628 profile.nSampleRate = sampleRate;
3629 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07003630
Andreas Huber784202e2009-10-15 13:46:54 -07003631 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003632 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003633
3634 if (err != OK) {
3635 CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed (err = %d)", err);
3636 return err;
3637 }
Andreas Huberda050cf22009-09-02 14:01:43 -07003638 }
Gilles-Arnaud Bleu-Laine9a6ed362011-09-15 21:30:13 -05003639
3640 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07003641}
3642
Andreas Huber4b3913a2011-05-11 14:13:42 -07003643void OMXCodec::setG711Format(int32_t numChannels) {
3644 CHECK(!mIsEncoder);
3645 setRawAudioFormat(kPortIndexInput, 8000, numChannels);
3646}
3647
Andreas Huberbe06d262009-08-14 14:37:10 -07003648void OMXCodec::setImageOutputFormat(
3649 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07003650 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07003651
3652#if 0
3653 OMX_INDEXTYPE index;
3654 status_t err = mOMX->get_extension_index(
3655 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003656 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003657
3658 err = mOMX->set_config(mNode, index, &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003659 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003660#endif
3661
3662 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003663 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003664 def.nPortIndex = kPortIndexOutput;
3665
Andreas Huber784202e2009-10-15 13:46:54 -07003666 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003667 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003668 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003669
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003670 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huberbe06d262009-08-14 14:37:10 -07003671
3672 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07003673
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003674 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07003675 imageDef->eColorFormat = format;
3676 imageDef->nFrameWidth = width;
3677 imageDef->nFrameHeight = height;
3678
3679 switch (format) {
3680 case OMX_COLOR_FormatYUV420PackedPlanar:
3681 case OMX_COLOR_FormatYUV411Planar:
3682 {
3683 def.nBufferSize = (width * height * 3) / 2;
3684 break;
3685 }
3686
3687 case OMX_COLOR_FormatCbYCrY:
3688 {
3689 def.nBufferSize = width * height * 2;
3690 break;
3691 }
3692
3693 case OMX_COLOR_Format32bitARGB8888:
3694 {
3695 def.nBufferSize = width * height * 4;
3696 break;
3697 }
3698
Andreas Huber201511c2009-09-08 14:01:44 -07003699 case OMX_COLOR_Format16bitARGB4444:
3700 case OMX_COLOR_Format16bitARGB1555:
3701 case OMX_COLOR_Format16bitRGB565:
3702 case OMX_COLOR_Format16bitBGR565:
3703 {
3704 def.nBufferSize = width * height * 2;
3705 break;
3706 }
3707
Andreas Huberbe06d262009-08-14 14:37:10 -07003708 default:
3709 CHECK(!"Should not be here. Unknown color format.");
3710 break;
3711 }
3712
Andreas Huber5c0a9132009-08-20 11:16:40 -07003713 def.nBufferCountActual = def.nBufferCountMin;
3714
Andreas Huber784202e2009-10-15 13:46:54 -07003715 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003716 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003717 CHECK_EQ(err, (status_t)OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003718}
Andreas Huberbe06d262009-08-14 14:37:10 -07003719
Andreas Huber5c0a9132009-08-20 11:16:40 -07003720void OMXCodec::setJPEGInputFormat(
3721 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
3722 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003723 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003724 def.nPortIndex = kPortIndexInput;
3725
Andreas Huber784202e2009-10-15 13:46:54 -07003726 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003727 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003728 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003729
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003730 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003731 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3732
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003733 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingJPEG);
Andreas Huberbe06d262009-08-14 14:37:10 -07003734 imageDef->nFrameWidth = width;
3735 imageDef->nFrameHeight = height;
3736
Andreas Huber5c0a9132009-08-20 11:16:40 -07003737 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07003738 def.nBufferCountActual = def.nBufferCountMin;
3739
Andreas Huber784202e2009-10-15 13:46:54 -07003740 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003741 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003742 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003743}
3744
3745void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
3746 CodecSpecificData *specific =
3747 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
3748
3749 specific->mSize = size;
3750 memcpy(specific->mData, data, size);
3751
3752 mCodecSpecificData.push(specific);
3753}
3754
3755void OMXCodec::clearCodecSpecificData() {
3756 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
3757 free(mCodecSpecificData.editItemAt(i));
3758 }
3759 mCodecSpecificData.clear();
3760 mCodecSpecificDataIndex = 0;
3761}
3762
James Dong36e573b2010-06-19 09:04:18 -07003763status_t OMXCodec::start(MetaData *meta) {
Andreas Huber42978e52009-08-27 10:08:39 -07003764 Mutex::Autolock autoLock(mLock);
3765
Andreas Huberbe06d262009-08-14 14:37:10 -07003766 if (mState != LOADED) {
3767 return UNKNOWN_ERROR;
3768 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07003769
Andreas Huberbe06d262009-08-14 14:37:10 -07003770 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07003771 if (mQuirks & kWantsNALFragments) {
3772 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07003773 }
James Dong36e573b2010-06-19 09:04:18 -07003774 if (meta) {
3775 int64_t startTimeUs = 0;
3776 int64_t timeUs;
3777 if (meta->findInt64(kKeyTime, &timeUs)) {
3778 startTimeUs = timeUs;
3779 }
3780 params->setInt64(kKeyTime, startTimeUs);
3781 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003782 status_t err = mSource->start(params.get());
3783
3784 if (err != OK) {
3785 return err;
3786 }
3787
3788 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07003789 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003790 mSignalledEOS = false;
3791 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07003792 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003793 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003794 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
3795 mTargetTimeUs = -1;
Andreas Huberbe06d262009-08-14 14:37:10 -07003796 mFilledBuffers.clear();
Andreas Huber1f24b302010-06-10 11:12:39 -07003797 mPaused = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003798
3799 return init();
3800}
3801
3802status_t OMXCodec::stop() {
James Dong2c17f052011-07-14 16:22:47 -07003803 CODEC_LOGV("stop mState=%d", mState);
Andreas Huberbe06d262009-08-14 14:37:10 -07003804
3805 Mutex::Autolock autoLock(mLock);
3806
3807 while (isIntermediateState(mState)) {
3808 mAsyncCompletion.wait(mLock);
3809 }
3810
Jamie Gennis6607b392011-10-19 21:14:13 -07003811 bool isError = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003812 switch (mState) {
3813 case LOADED:
Andreas Huberbe06d262009-08-14 14:37:10 -07003814 break;
3815
Jamie Gennis6607b392011-10-19 21:14:13 -07003816 case ERROR:
3817 {
3818 OMX_STATETYPE state = OMX_StateInvalid;
3819 status_t err = mOMX->getState(mNode, &state);
3820 CHECK_EQ(err, (status_t)OK);
3821
3822 if (state != OMX_StateExecuting) {
3823 break;
3824 }
3825 // else fall through to the idling code
3826 isError = true;
3827 }
3828
Andreas Huberbe06d262009-08-14 14:37:10 -07003829 case EXECUTING:
3830 {
3831 setState(EXECUTING_TO_IDLE);
3832
Andreas Huber127fcdc2009-08-26 16:27:02 -07003833 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07003834 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07003835 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07003836
Andreas Huber127fcdc2009-08-26 16:27:02 -07003837 bool emulateInputFlushCompletion =
3838 !flushPortAsync(kPortIndexInput);
3839
3840 bool emulateOutputFlushCompletion =
3841 !flushPortAsync(kPortIndexOutput);
3842
3843 if (emulateInputFlushCompletion) {
3844 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3845 }
3846
3847 if (emulateOutputFlushCompletion) {
3848 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3849 }
3850 } else {
3851 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
3852 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
3853
3854 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07003855 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003856 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07003857 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003858
3859 while (mState != LOADED && mState != ERROR) {
3860 mAsyncCompletion.wait(mLock);
3861 }
3862
Jamie Gennis6607b392011-10-19 21:14:13 -07003863 if (isError) {
3864 // We were in the ERROR state coming in, so restore that now
3865 // that we've idled the OMX component.
3866 setState(ERROR);
3867 }
3868
Andreas Huberbe06d262009-08-14 14:37:10 -07003869 break;
3870 }
3871
3872 default:
3873 {
3874 CHECK(!"should not be here.");
3875 break;
3876 }
3877 }
3878
Andreas Hubera4357ad2010-04-02 12:49:54 -07003879 if (mLeftOverBuffer) {
3880 mLeftOverBuffer->release();
3881 mLeftOverBuffer = NULL;
3882 }
3883
Andreas Huberbe06d262009-08-14 14:37:10 -07003884 mSource->stop();
3885
Andreas Huber262d7e82011-09-27 15:05:40 -07003886 CODEC_LOGV("stopped in state %d", mState);
Andreas Huber4a9375e2010-02-09 11:54:33 -08003887
Andreas Huberbe06d262009-08-14 14:37:10 -07003888 return OK;
3889}
3890
3891sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07003892 Mutex::Autolock autoLock(mLock);
3893
Andreas Huberbe06d262009-08-14 14:37:10 -07003894 return mOutputFormat;
3895}
3896
3897status_t OMXCodec::read(
3898 MediaBuffer **buffer, const ReadOptions *options) {
James Dongd9ac6212011-07-15 15:25:36 -07003899 status_t err = OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07003900 *buffer = NULL;
3901
3902 Mutex::Autolock autoLock(mLock);
3903
Andreas Huberd06e5b82009-08-28 13:18:14 -07003904 if (mState != EXECUTING && mState != RECONFIGURING) {
3905 return UNKNOWN_ERROR;
3906 }
3907
Andreas Hubere981c332009-10-22 13:49:30 -07003908 bool seeking = false;
3909 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003910 ReadOptions::SeekMode seekMode;
3911 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
Andreas Hubere981c332009-10-22 13:49:30 -07003912 seeking = true;
3913 }
3914
Andreas Huber42978e52009-08-27 10:08:39 -07003915 if (mInitialBufferSubmit) {
3916 mInitialBufferSubmit = false;
3917
Andreas Hubere981c332009-10-22 13:49:30 -07003918 if (seeking) {
3919 CHECK(seekTimeUs >= 0);
3920 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003921 mSeekMode = seekMode;
Andreas Hubere981c332009-10-22 13:49:30 -07003922
3923 // There's no reason to trigger the code below, there's
3924 // nothing to flush yet.
3925 seeking = false;
Andreas Huber1f24b302010-06-10 11:12:39 -07003926 mPaused = false;
Andreas Hubere981c332009-10-22 13:49:30 -07003927 }
3928
Andreas Huber42978e52009-08-27 10:08:39 -07003929 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07003930
Andreas Huberd06e5b82009-08-28 13:18:14 -07003931 if (mState == EXECUTING) {
3932 // Otherwise mState == RECONFIGURING and this code will trigger
3933 // after the output port is reenabled.
3934 fillOutputBuffers();
3935 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003936 }
3937
Andreas Hubere981c332009-10-22 13:49:30 -07003938 if (seeking) {
Andreas Huberb9289832011-02-08 13:10:25 -08003939 while (mState == RECONFIGURING) {
James Dongd9ac6212011-07-15 15:25:36 -07003940 if ((err = waitForBufferFilled_l()) != OK) {
3941 return err;
3942 }
Andreas Huberb9289832011-02-08 13:10:25 -08003943 }
3944
3945 if (mState != EXECUTING) {
3946 return UNKNOWN_ERROR;
3947 }
3948
Andreas Huber4c483422009-09-02 16:05:36 -07003949 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07003950
3951 mSignalledEOS = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003952
3953 CHECK(seekTimeUs >= 0);
3954 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003955 mSeekMode = seekMode;
Andreas Huberbe06d262009-08-14 14:37:10 -07003956
3957 mFilledBuffers.clear();
3958
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003959 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07003960
Andreas Huber404cc412009-08-25 14:26:05 -07003961 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
3962 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
3963
3964 if (emulateInputFlushCompletion) {
3965 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3966 }
3967
3968 if (emulateOutputFlushCompletion) {
3969 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3970 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003971
3972 while (mSeekTimeUs >= 0) {
James Dongd9ac6212011-07-15 15:25:36 -07003973 if ((err = waitForBufferFilled_l()) != OK) {
3974 return err;
3975 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003976 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003977 }
3978
3979 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
James Dongd9ac6212011-07-15 15:25:36 -07003980 if ((err = waitForBufferFilled_l()) != OK) {
3981 return err;
James Dong74556302010-12-20 21:29:12 -08003982 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003983 }
3984
3985 if (mState == ERROR) {
3986 return UNKNOWN_ERROR;
3987 }
3988
3989 if (mFilledBuffers.empty()) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08003990 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
Andreas Huberbe06d262009-08-14 14:37:10 -07003991 }
3992
Andreas Hubercfd55572009-10-09 14:11:28 -07003993 if (mOutputPortSettingsHaveChanged) {
3994 mOutputPortSettingsHaveChanged = false;
3995
3996 return INFO_FORMAT_CHANGED;
3997 }
3998
Andreas Huberbe06d262009-08-14 14:37:10 -07003999 size_t index = *mFilledBuffers.begin();
4000 mFilledBuffers.erase(mFilledBuffers.begin());
4001
4002 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
Andreas Huberbbbcf652010-12-07 14:25:54 -08004003 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
4004 info->mStatus = OWNED_BY_CLIENT;
4005
Andreas Huberbe06d262009-08-14 14:37:10 -07004006 info->mMediaBuffer->add_ref();
4007 *buffer = info->mMediaBuffer;
4008
4009 return OK;
4010}
4011
4012void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
4013 Mutex::Autolock autoLock(mLock);
4014
4015 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
4016 for (size_t i = 0; i < buffers->size(); ++i) {
4017 BufferInfo *info = &buffers->editItemAt(i);
4018
4019 if (info->mMediaBuffer == buffer) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004020 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberbbbcf652010-12-07 14:25:54 -08004021 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
4022
4023 info->mStatus = OWNED_BY_US;
4024
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004025 if (buffer->graphicBuffer() == 0) {
4026 fillOutputBuffer(info);
4027 } else {
4028 sp<MetaData> metaData = info->mMediaBuffer->meta_data();
4029 int32_t rendered = 0;
4030 if (!metaData->findInt32(kKeyRendered, &rendered)) {
4031 rendered = 0;
4032 }
4033 if (!rendered) {
4034 status_t err = cancelBufferToNativeWindow(info);
4035 if (err < 0) {
4036 return;
4037 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004038 }
4039
Andreas Huberbbbcf652010-12-07 14:25:54 -08004040 info->mStatus = OWNED_BY_NATIVE_WINDOW;
4041
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004042 // Dequeue the next buffer from the native window.
4043 BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
4044 if (nextBufInfo == 0) {
4045 return;
4046 }
4047
4048 // Give the buffer to the OMX node to fill.
4049 fillOutputBuffer(nextBufInfo);
4050 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004051 return;
4052 }
4053 }
4054
4055 CHECK(!"should not be here.");
4056}
4057
4058static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
4059 static const char *kNames[] = {
4060 "OMX_IMAGE_CodingUnused",
4061 "OMX_IMAGE_CodingAutoDetect",
4062 "OMX_IMAGE_CodingJPEG",
4063 "OMX_IMAGE_CodingJPEG2K",
4064 "OMX_IMAGE_CodingEXIF",
4065 "OMX_IMAGE_CodingTIFF",
4066 "OMX_IMAGE_CodingGIF",
4067 "OMX_IMAGE_CodingPNG",
4068 "OMX_IMAGE_CodingLZW",
4069 "OMX_IMAGE_CodingBMP",
4070 };
4071
4072 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4073
4074 if (type < 0 || (size_t)type >= numNames) {
4075 return "UNKNOWN";
4076 } else {
4077 return kNames[type];
4078 }
4079}
4080
4081static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
4082 static const char *kNames[] = {
4083 "OMX_COLOR_FormatUnused",
4084 "OMX_COLOR_FormatMonochrome",
4085 "OMX_COLOR_Format8bitRGB332",
4086 "OMX_COLOR_Format12bitRGB444",
4087 "OMX_COLOR_Format16bitARGB4444",
4088 "OMX_COLOR_Format16bitARGB1555",
4089 "OMX_COLOR_Format16bitRGB565",
4090 "OMX_COLOR_Format16bitBGR565",
4091 "OMX_COLOR_Format18bitRGB666",
4092 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07004093 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07004094 "OMX_COLOR_Format24bitRGB888",
4095 "OMX_COLOR_Format24bitBGR888",
4096 "OMX_COLOR_Format24bitARGB1887",
4097 "OMX_COLOR_Format25bitARGB1888",
4098 "OMX_COLOR_Format32bitBGRA8888",
4099 "OMX_COLOR_Format32bitARGB8888",
4100 "OMX_COLOR_FormatYUV411Planar",
4101 "OMX_COLOR_FormatYUV411PackedPlanar",
4102 "OMX_COLOR_FormatYUV420Planar",
4103 "OMX_COLOR_FormatYUV420PackedPlanar",
4104 "OMX_COLOR_FormatYUV420SemiPlanar",
4105 "OMX_COLOR_FormatYUV422Planar",
4106 "OMX_COLOR_FormatYUV422PackedPlanar",
4107 "OMX_COLOR_FormatYUV422SemiPlanar",
4108 "OMX_COLOR_FormatYCbYCr",
4109 "OMX_COLOR_FormatYCrYCb",
4110 "OMX_COLOR_FormatCbYCrY",
4111 "OMX_COLOR_FormatCrYCbY",
4112 "OMX_COLOR_FormatYUV444Interleaved",
4113 "OMX_COLOR_FormatRawBayer8bit",
4114 "OMX_COLOR_FormatRawBayer10bit",
4115 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07004116 "OMX_COLOR_FormatL2",
4117 "OMX_COLOR_FormatL4",
4118 "OMX_COLOR_FormatL8",
4119 "OMX_COLOR_FormatL16",
4120 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07004121 "OMX_COLOR_FormatL32",
4122 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
4123 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
4124 "OMX_COLOR_Format18BitBGR666",
4125 "OMX_COLOR_Format24BitARGB6666",
4126 "OMX_COLOR_Format24BitABGR6666",
4127 };
4128
4129 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4130
Anu Sundararajand35df442011-06-22 12:24:46 -05004131 if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
4132 return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
4133 } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
Andreas Huberbe06d262009-08-14 14:37:10 -07004134 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
4135 } else if (type < 0 || (size_t)type >= numNames) {
4136 return "UNKNOWN";
4137 } else {
4138 return kNames[type];
4139 }
4140}
4141
4142static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
4143 static const char *kNames[] = {
4144 "OMX_VIDEO_CodingUnused",
4145 "OMX_VIDEO_CodingAutoDetect",
4146 "OMX_VIDEO_CodingMPEG2",
4147 "OMX_VIDEO_CodingH263",
4148 "OMX_VIDEO_CodingMPEG4",
4149 "OMX_VIDEO_CodingWMV",
4150 "OMX_VIDEO_CodingRV",
4151 "OMX_VIDEO_CodingAVC",
4152 "OMX_VIDEO_CodingMJPEG",
4153 };
4154
4155 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4156
4157 if (type < 0 || (size_t)type >= numNames) {
4158 return "UNKNOWN";
4159 } else {
4160 return kNames[type];
4161 }
4162}
4163
4164static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
4165 static const char *kNames[] = {
4166 "OMX_AUDIO_CodingUnused",
4167 "OMX_AUDIO_CodingAutoDetect",
4168 "OMX_AUDIO_CodingPCM",
4169 "OMX_AUDIO_CodingADPCM",
4170 "OMX_AUDIO_CodingAMR",
4171 "OMX_AUDIO_CodingGSMFR",
4172 "OMX_AUDIO_CodingGSMEFR",
4173 "OMX_AUDIO_CodingGSMHR",
4174 "OMX_AUDIO_CodingPDCFR",
4175 "OMX_AUDIO_CodingPDCEFR",
4176 "OMX_AUDIO_CodingPDCHR",
4177 "OMX_AUDIO_CodingTDMAFR",
4178 "OMX_AUDIO_CodingTDMAEFR",
4179 "OMX_AUDIO_CodingQCELP8",
4180 "OMX_AUDIO_CodingQCELP13",
4181 "OMX_AUDIO_CodingEVRC",
4182 "OMX_AUDIO_CodingSMV",
4183 "OMX_AUDIO_CodingG711",
4184 "OMX_AUDIO_CodingG723",
4185 "OMX_AUDIO_CodingG726",
4186 "OMX_AUDIO_CodingG729",
4187 "OMX_AUDIO_CodingAAC",
4188 "OMX_AUDIO_CodingMP3",
4189 "OMX_AUDIO_CodingSBC",
4190 "OMX_AUDIO_CodingVORBIS",
4191 "OMX_AUDIO_CodingWMA",
4192 "OMX_AUDIO_CodingRA",
4193 "OMX_AUDIO_CodingMIDI",
4194 };
4195
4196 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4197
4198 if (type < 0 || (size_t)type >= numNames) {
4199 return "UNKNOWN";
4200 } else {
4201 return kNames[type];
4202 }
4203}
4204
4205static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
4206 static const char *kNames[] = {
4207 "OMX_AUDIO_PCMModeLinear",
4208 "OMX_AUDIO_PCMModeALaw",
4209 "OMX_AUDIO_PCMModeMULaw",
4210 };
4211
4212 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4213
4214 if (type < 0 || (size_t)type >= numNames) {
4215 return "UNKNOWN";
4216 } else {
4217 return kNames[type];
4218 }
4219}
4220
Andreas Huber7ae02c82009-09-09 16:29:47 -07004221static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
4222 static const char *kNames[] = {
4223 "OMX_AUDIO_AMRBandModeUnused",
4224 "OMX_AUDIO_AMRBandModeNB0",
4225 "OMX_AUDIO_AMRBandModeNB1",
4226 "OMX_AUDIO_AMRBandModeNB2",
4227 "OMX_AUDIO_AMRBandModeNB3",
4228 "OMX_AUDIO_AMRBandModeNB4",
4229 "OMX_AUDIO_AMRBandModeNB5",
4230 "OMX_AUDIO_AMRBandModeNB6",
4231 "OMX_AUDIO_AMRBandModeNB7",
4232 "OMX_AUDIO_AMRBandModeWB0",
4233 "OMX_AUDIO_AMRBandModeWB1",
4234 "OMX_AUDIO_AMRBandModeWB2",
4235 "OMX_AUDIO_AMRBandModeWB3",
4236 "OMX_AUDIO_AMRBandModeWB4",
4237 "OMX_AUDIO_AMRBandModeWB5",
4238 "OMX_AUDIO_AMRBandModeWB6",
4239 "OMX_AUDIO_AMRBandModeWB7",
4240 "OMX_AUDIO_AMRBandModeWB8",
4241 };
4242
4243 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4244
4245 if (type < 0 || (size_t)type >= numNames) {
4246 return "UNKNOWN";
4247 } else {
4248 return kNames[type];
4249 }
4250}
4251
4252static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
4253 static const char *kNames[] = {
4254 "OMX_AUDIO_AMRFrameFormatConformance",
4255 "OMX_AUDIO_AMRFrameFormatIF1",
4256 "OMX_AUDIO_AMRFrameFormatIF2",
4257 "OMX_AUDIO_AMRFrameFormatFSF",
4258 "OMX_AUDIO_AMRFrameFormatRTPPayload",
4259 "OMX_AUDIO_AMRFrameFormatITU",
4260 };
4261
4262 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
4263
4264 if (type < 0 || (size_t)type >= numNames) {
4265 return "UNKNOWN";
4266 } else {
4267 return kNames[type];
4268 }
4269}
Andreas Huberbe06d262009-08-14 14:37:10 -07004270
4271void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
4272 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07004273 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07004274 def.nPortIndex = portIndex;
4275
Andreas Huber784202e2009-10-15 13:46:54 -07004276 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004277 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004278 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004279
4280 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
4281
4282 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
4283 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
4284
4285 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
4286 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
4287 printf(" nBufferSize = %ld\n", def.nBufferSize);
4288
4289 switch (def.eDomain) {
4290 case OMX_PortDomainImage:
4291 {
4292 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
4293
4294 printf("\n");
4295 printf(" // Image\n");
4296 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
4297 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
4298 printf(" nStride = %ld\n", imageDef->nStride);
4299
4300 printf(" eCompressionFormat = %s\n",
4301 imageCompressionFormatString(imageDef->eCompressionFormat));
4302
4303 printf(" eColorFormat = %s\n",
4304 colorFormatString(imageDef->eColorFormat));
4305
4306 break;
4307 }
4308
4309 case OMX_PortDomainVideo:
4310 {
4311 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4312
4313 printf("\n");
4314 printf(" // Video\n");
4315 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
4316 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
4317 printf(" nStride = %ld\n", videoDef->nStride);
4318
4319 printf(" eCompressionFormat = %s\n",
4320 videoCompressionFormatString(videoDef->eCompressionFormat));
4321
4322 printf(" eColorFormat = %s\n",
4323 colorFormatString(videoDef->eColorFormat));
4324
4325 break;
4326 }
4327
4328 case OMX_PortDomainAudio:
4329 {
4330 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4331
4332 printf("\n");
4333 printf(" // Audio\n");
4334 printf(" eEncoding = %s\n",
4335 audioCodingTypeString(audioDef->eEncoding));
4336
4337 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
4338 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07004339 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07004340 params.nPortIndex = portIndex;
4341
Andreas Huber784202e2009-10-15 13:46:54 -07004342 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004343 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004344 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004345
4346 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
4347 printf(" nChannels = %ld\n", params.nChannels);
4348 printf(" bInterleaved = %d\n", params.bInterleaved);
4349 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
4350
4351 printf(" eNumData = %s\n",
4352 params.eNumData == OMX_NumericalDataSigned
4353 ? "signed" : "unsigned");
4354
4355 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07004356 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
4357 OMX_AUDIO_PARAM_AMRTYPE amr;
4358 InitOMXParams(&amr);
4359 amr.nPortIndex = portIndex;
4360
Andreas Huber784202e2009-10-15 13:46:54 -07004361 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07004362 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004363 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004364
4365 printf(" nChannels = %ld\n", amr.nChannels);
4366 printf(" eAMRBandMode = %s\n",
4367 amrBandModeString(amr.eAMRBandMode));
4368 printf(" eAMRFrameFormat = %s\n",
4369 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07004370 }
4371
4372 break;
4373 }
4374
4375 default:
4376 {
4377 printf(" // Unknown\n");
4378 break;
4379 }
4380 }
4381
4382 printf("}\n");
4383}
4384
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004385status_t OMXCodec::initNativeWindow() {
4386 // Enable use of a GraphicBuffer as the output for this node. This must
4387 // happen before getting the IndexParamPortDefinition parameter because it
4388 // will affect the pixel format that the node reports.
4389 status_t err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
4390 if (err != 0) {
4391 return err;
4392 }
4393
4394 return OK;
4395}
4396
Lakshman Gowdadb62a242011-09-29 17:47:35 -07004397void OMXCodec::initNativeWindowCrop() {
4398 int32_t left, top, right, bottom;
4399
4400 CHECK(mOutputFormat->findRect(
4401 kKeyCropRect,
4402 &left, &top, &right, &bottom));
4403
4404 android_native_rect_t crop;
4405 crop.left = left;
4406 crop.top = top;
4407 crop.right = right + 1;
4408 crop.bottom = bottom + 1;
4409
4410 // We'll ignore any errors here, if the surface is
4411 // already invalid, we'll know soon enough.
4412 native_window_set_crop(mNativeWindow.get(), &crop);
4413}
4414
Andreas Huberbe06d262009-08-14 14:37:10 -07004415void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
4416 mOutputFormat = new MetaData;
4417 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
James Dong52d13f02010-07-02 11:39:06 -07004418 if (mIsEncoder) {
4419 int32_t timeScale;
4420 if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
4421 mOutputFormat->setInt32(kKeyTimeScale, timeScale);
4422 }
4423 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004424
4425 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07004426 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07004427 def.nPortIndex = kPortIndexOutput;
4428
Andreas Huber784202e2009-10-15 13:46:54 -07004429 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004430 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004431 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004432
4433 switch (def.eDomain) {
4434 case OMX_PortDomainImage:
4435 {
4436 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004437 CHECK_EQ((int)imageDef->eCompressionFormat,
4438 (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07004439
Andreas Hubere6c40962009-09-10 14:13:30 -07004440 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004441 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
4442 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
4443 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
4444 break;
4445 }
4446
4447 case OMX_PortDomainAudio:
4448 {
4449 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
4450
Andreas Huberda050cf22009-09-02 14:01:43 -07004451 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
4452 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07004453 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07004454 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07004455
Andreas Huber784202e2009-10-15 13:46:54 -07004456 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07004457 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004458 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004459
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004460 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
4461 CHECK_EQ(params.nBitPerSample, 16u);
4462 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07004463
Andreas Huberda050cf22009-09-02 14:01:43 -07004464 int32_t numChannels, sampleRate;
4465 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4466 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07004467
Andreas Huberda050cf22009-09-02 14:01:43 -07004468 if ((OMX_U32)numChannels != params.nChannels) {
Steve Block71f2cf12011-10-20 11:56:00 +01004469 ALOGV("Codec outputs a different number of channels than "
Andreas Hubere331c7b2010-02-01 10:51:50 -08004470 "the input stream contains (contains %d channels, "
4471 "codec outputs %ld channels).",
4472 numChannels, params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004473 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004474
Andreas Huber0920bca2011-05-18 09:31:22 -07004475 if (sampleRate != (int32_t)params.nSamplingRate) {
Steve Block71f2cf12011-10-20 11:56:00 +01004476 ALOGV("Codec outputs at different sampling rate than "
Andreas Huber4b3913a2011-05-11 14:13:42 -07004477 "what the input stream contains (contains data at "
Andreas Huber0920bca2011-05-18 09:31:22 -07004478 "%d Hz, codec outputs %lu Hz)",
Andreas Huber4b3913a2011-05-11 14:13:42 -07004479 sampleRate, params.nSamplingRate);
4480 }
4481
Andreas Hubere6c40962009-09-10 14:13:30 -07004482 mOutputFormat->setCString(
4483 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07004484
4485 // Use the codec-advertised number of channels, as some
4486 // codecs appear to output stereo even if the input data is
Andreas Hubere331c7b2010-02-01 10:51:50 -08004487 // mono. If we know the codec lies about this information,
4488 // use the actual number of channels instead.
4489 mOutputFormat->setInt32(
4490 kKeyChannelCount,
4491 (mQuirks & kDecoderLiesAboutNumberOfChannels)
4492 ? numChannels : params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004493
Andreas Huber4b3913a2011-05-11 14:13:42 -07004494 mOutputFormat->setInt32(kKeySampleRate, params.nSamplingRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004495 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07004496 OMX_AUDIO_PARAM_AMRTYPE amr;
4497 InitOMXParams(&amr);
4498 amr.nPortIndex = kPortIndexOutput;
4499
Andreas Huber784202e2009-10-15 13:46:54 -07004500 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07004501 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004502 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004503
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004504 CHECK_EQ(amr.nChannels, 1u);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004505 mOutputFormat->setInt32(kKeyChannelCount, 1);
4506
4507 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
4508 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004509 mOutputFormat->setCString(
4510 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004511 mOutputFormat->setInt32(kKeySampleRate, 8000);
4512 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
4513 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004514 mOutputFormat->setCString(
4515 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004516 mOutputFormat->setInt32(kKeySampleRate, 16000);
4517 } else {
4518 CHECK(!"Unknown AMR band mode.");
4519 }
Andreas Huberda050cf22009-09-02 14:01:43 -07004520 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004521 mOutputFormat->setCString(
4522 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
James Dong17299ab2010-05-14 15:45:22 -07004523 int32_t numChannels, sampleRate, bitRate;
James Dongabed93a2010-04-22 17:27:04 -07004524 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4525 inputFormat->findInt32(kKeySampleRate, &sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004526 inputFormat->findInt32(kKeyBitRate, &bitRate);
James Dongabed93a2010-04-22 17:27:04 -07004527 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
4528 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004529 mOutputFormat->setInt32(kKeyBitRate, bitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004530 } else {
4531 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07004532 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004533 break;
4534 }
4535
4536 case OMX_PortDomainVideo:
4537 {
4538 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4539
4540 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004541 mOutputFormat->setCString(
4542 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004543 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004544 mOutputFormat->setCString(
4545 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07004546 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004547 mOutputFormat->setCString(
4548 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07004549 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004550 mOutputFormat->setCString(
4551 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07004552 } else {
4553 CHECK(!"Unknown compression format.");
4554 }
4555
James Dong5592bcc2010-10-22 17:10:43 -07004556 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
4557 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
Andreas Huberbe06d262009-08-14 14:37:10 -07004558 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004559
James Dong0c9153d2010-11-23 11:30:21 -08004560 if (!mIsEncoder) {
4561 OMX_CONFIG_RECTTYPE rect;
James Donga1735412011-01-07 14:56:34 -08004562 InitOMXParams(&rect);
4563 rect.nPortIndex = kPortIndexOutput;
James Dong0c9153d2010-11-23 11:30:21 -08004564 status_t err =
4565 mOMX->getConfig(
4566 mNode, OMX_IndexConfigCommonOutputCrop,
4567 &rect, sizeof(rect));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004568
Andreas Huberf167f502011-06-24 13:15:30 -07004569 CODEC_LOGI(
4570 "video dimensions are %ld x %ld",
4571 video_def->nFrameWidth, video_def->nFrameHeight);
4572
James Dong0c9153d2010-11-23 11:30:21 -08004573 if (err == OK) {
4574 CHECK_GE(rect.nLeft, 0);
4575 CHECK_GE(rect.nTop, 0);
4576 CHECK_GE(rect.nWidth, 0u);
4577 CHECK_GE(rect.nHeight, 0u);
4578 CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
4579 CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004580
James Dong0c9153d2010-11-23 11:30:21 -08004581 mOutputFormat->setRect(
4582 kKeyCropRect,
4583 rect.nLeft,
4584 rect.nTop,
4585 rect.nLeft + rect.nWidth - 1,
4586 rect.nTop + rect.nHeight - 1);
Andreas Huberf167f502011-06-24 13:15:30 -07004587
4588 CODEC_LOGI(
4589 "Crop rect is %ld x %ld @ (%ld, %ld)",
4590 rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
James Dong0c9153d2010-11-23 11:30:21 -08004591 } else {
4592 mOutputFormat->setRect(
4593 kKeyCropRect,
4594 0, 0,
4595 video_def->nFrameWidth - 1,
4596 video_def->nFrameHeight - 1);
4597 }
Lakshman Gowdadb62a242011-09-29 17:47:35 -07004598
4599 if (mNativeWindow != NULL) {
4600 initNativeWindowCrop();
4601 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004602 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004603 break;
4604 }
4605
4606 default:
4607 {
4608 CHECK(!"should not be here, neither audio nor video.");
4609 break;
4610 }
4611 }
Andreas Huber0920bca2011-05-18 09:31:22 -07004612
4613 // If the input format contains rotation information, flag the output
4614 // format accordingly.
4615
4616 int32_t rotationDegrees;
4617 if (mSource->getFormat()->findInt32(kKeyRotation, &rotationDegrees)) {
4618 mOutputFormat->setInt32(kKeyRotation, rotationDegrees);
4619 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004620}
4621
Andreas Huber1f24b302010-06-10 11:12:39 -07004622status_t OMXCodec::pause() {
4623 Mutex::Autolock autoLock(mLock);
4624
4625 mPaused = true;
4626
4627 return OK;
4628}
4629
Andreas Hubere6c40962009-09-10 14:13:30 -07004630////////////////////////////////////////////////////////////////////////////////
4631
4632status_t QueryCodecs(
4633 const sp<IOMX> &omx,
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004634 const char *mime, bool queryDecoders, bool hwCodecOnly,
Andreas Hubere6c40962009-09-10 14:13:30 -07004635 Vector<CodecCapabilities> *results) {
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004636 Vector<String8> matchingCodecs;
Andreas Hubere6c40962009-09-10 14:13:30 -07004637 results->clear();
4638
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004639 OMXCodec::findMatchingCodecs(mime,
4640 !queryDecoders /*createEncoder*/,
4641 NULL /*matchComponentName*/,
4642 hwCodecOnly ? OMXCodec::kHardwareCodecsOnly : 0 /*flags*/,
4643 &matchingCodecs);
Andreas Hubere6c40962009-09-10 14:13:30 -07004644
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004645 for (size_t c = 0; c < matchingCodecs.size(); c++) {
4646 const char *componentName = matchingCodecs.itemAt(c).string();
Andreas Hubere6c40962009-09-10 14:13:30 -07004647
Andreas Huber1a189a82010-03-24 13:49:20 -07004648 if (strncmp(componentName, "OMX.", 4)) {
4649 // Not an OpenMax component but a software codec.
4650
4651 results->push();
4652 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4653 caps->mComponentName = componentName;
Andreas Huber1a189a82010-03-24 13:49:20 -07004654 continue;
4655 }
4656
Andreas Huber784202e2009-10-15 13:46:54 -07004657 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07004658 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07004659 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07004660
4661 if (err != OK) {
4662 continue;
4663 }
4664
James Dong722d5912010-04-13 10:56:59 -07004665 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
Andreas Hubere6c40962009-09-10 14:13:30 -07004666
4667 results->push();
4668 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4669 caps->mComponentName = componentName;
4670
4671 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
4672 InitOMXParams(&param);
4673
4674 param.nPortIndex = queryDecoders ? 0 : 1;
4675
4676 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07004677 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07004678 node, OMX_IndexParamVideoProfileLevelQuerySupported,
4679 &param, sizeof(param));
4680
4681 if (err != OK) {
4682 break;
4683 }
4684
4685 CodecProfileLevel profileLevel;
4686 profileLevel.mProfile = param.eProfile;
4687 profileLevel.mLevel = param.eLevel;
4688
4689 caps->mProfileLevels.push(profileLevel);
4690 }
4691
James Dongd7810892010-11-11 00:33:05 -08004692 // Color format query
4693 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
4694 InitOMXParams(&portFormat);
4695 portFormat.nPortIndex = queryDecoders ? 1 : 0;
4696 for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
4697 err = omx->getParameter(
4698 node, OMX_IndexParamVideoPortFormat,
4699 &portFormat, sizeof(portFormat));
4700 if (err != OK) {
4701 break;
4702 }
4703 caps->mColorFormats.push(portFormat.eColorFormat);
4704 }
4705
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004706 CHECK_EQ(omx->freeNode(node), (status_t)OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07004707 }
Jean-Michel Trivi56a37b02011-07-17 16:35:11 -07004708
4709 return OK;
Andreas Hubere6c40962009-09-10 14:13:30 -07004710}
4711
Jean-Michel Trivia05f0992011-07-22 09:52:39 -07004712status_t QueryCodecs(
4713 const sp<IOMX> &omx,
4714 const char *mimeType, bool queryDecoders,
4715 Vector<CodecCapabilities> *results) {
4716 return QueryCodecs(omx, mimeType, queryDecoders, false /*hwCodecOnly*/, results);
4717}
4718
James Dong31b9375f2010-11-10 21:11:41 -08004719void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
4720 CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
4721 CHECK(mOMXLivesLocally);
4722
4723 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
4724 header->pBuffer = (OMX_U8 *)info->mData;
4725}
4726
Andreas Huberbe06d262009-08-14 14:37:10 -07004727} // namespace android