blob: cd5bdfb7091668a65c26187e6c4b9643be86e308 [file] [log] [blame]
Andreas Huberbe06d262009-08-14 14:37:10 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXCodec"
19#include <utils/Log.h>
20
Andreas Huberdacaa732009-12-07 09:56:32 -080021#include "include/AACDecoder.h"
James Dong17299ab2010-05-14 15:45:22 -070022#include "include/AACEncoder.h"
Andreas Hubera30d4002009-12-08 15:40:06 -080023#include "include/AMRNBDecoder.h"
Andreas Huberd49b526dd2009-12-11 15:07:25 -080024#include "include/AMRNBEncoder.h"
Andreas Hubera30d4002009-12-08 15:40:06 -080025#include "include/AMRWBDecoder.h"
James Dong17299ab2010-05-14 15:45:22 -070026#include "include/AMRWBEncoder.h"
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080027#include "include/AVCDecoder.h"
James Dong1cc31e62010-07-02 17:44:44 -070028#include "include/AVCEncoder.h"
Andreas Huber520b2a72010-08-09 09:54:59 -070029#include "include/G711Decoder.h"
James Dong02f5b542009-12-15 16:26:55 -080030#include "include/M4vH263Decoder.h"
James Dong42ef0c72010-07-12 21:46:25 -070031#include "include/M4vH263Encoder.h"
Andreas Huber250f2432009-12-07 14:22:35 -080032#include "include/MP3Decoder.h"
Andreas Huber388379f2010-05-07 10:35:13 -070033#include "include/VorbisDecoder.h"
Andreas Huber47ba30e2010-05-24 14:38:02 -070034#include "include/VPXDecoder.h"
Andreas Huber8c7ab032009-12-07 11:23:44 -080035
Andreas Huberbd7b43b2009-10-13 10:22:55 -070036#include "include/ESDS.h"
37
Andreas Huberbe06d262009-08-14 14:37:10 -070038#include <binder/IServiceManager.h>
39#include <binder/MemoryDealer.h>
40#include <binder/ProcessState.h>
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080041#include <media/stagefright/foundation/ADebug.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070042#include <media/IMediaPlayerService.h>
Jamie Gennis58a36ad2010-10-07 14:08:38 -070043#include <media/stagefright/HardwareAPI.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070044#include <media/stagefright/MediaBuffer.h>
45#include <media/stagefright/MediaBufferGroup.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070046#include <media/stagefright/MediaDefs.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070047#include <media/stagefright/MediaExtractor.h>
48#include <media/stagefright/MetaData.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070049#include <media/stagefright/OMXCodec.h>
Andreas Huberebf66ea2009-08-19 13:32:58 -070050#include <media/stagefright/Utils.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070051#include <utils/Vector.h>
52
53#include <OMX_Audio.h>
54#include <OMX_Component.h>
55
Andreas Huber4b3913a2011-05-11 14:13:42 -070056#if HAVE_SOFTWARE_DECODERS
Andreas Huber8946ab22010-09-15 16:20:42 -070057#include "include/ThreadedSource.h"
Andreas Huber4b3913a2011-05-11 14:13:42 -070058#endif
59
Andreas Huberf7e2e312010-11-15 09:01:13 -080060#include "include/avc_utils.h"
Andreas Huber8946ab22010-09-15 16:20:42 -070061
Andreas Huberbe06d262009-08-14 14:37:10 -070062namespace android {
63
Andreas Huber8b432b12009-10-07 13:36:52 -070064static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
65
Andreas Huberbe06d262009-08-14 14:37:10 -070066struct CodecInfo {
67 const char *mime;
68 const char *codec;
69};
70
James Dong17299ab2010-05-14 15:45:22 -070071#define FACTORY_CREATE_ENCODER(name) \
72static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
73 return new name(source, meta); \
74}
75
Andreas Huberfb1c2f82009-12-15 13:25:11 -080076#define FACTORY_REF(name) { #name, Make##name },
77
James Dong17299ab2010-05-14 15:45:22 -070078FACTORY_CREATE_ENCODER(AMRNBEncoder)
79FACTORY_CREATE_ENCODER(AMRWBEncoder)
80FACTORY_CREATE_ENCODER(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -070081FACTORY_CREATE_ENCODER(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -070082FACTORY_CREATE_ENCODER(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -070083
Andreas Huber4b3913a2011-05-11 14:13:42 -070084#if HAVE_SOFTWARE_DECODERS
85
86#define FACTORY_CREATE(name) \
87static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
88 return new name(source); \
89}
90
91FACTORY_CREATE(AMRNBDecoder)
92FACTORY_CREATE(AMRWBDecoder)
93FACTORY_CREATE(AACDecoder)
94FACTORY_CREATE(AVCDecoder)
95FACTORY_CREATE(G711Decoder)
96FACTORY_CREATE(MP3Decoder)
97FACTORY_CREATE(M4vH263Decoder)
98FACTORY_CREATE(VorbisDecoder)
99FACTORY_CREATE(VPXDecoder)
100#endif
101
James Dong17299ab2010-05-14 15:45:22 -0700102static sp<MediaSource> InstantiateSoftwareEncoder(
103 const char *name, const sp<MediaSource> &source,
104 const sp<MetaData> &meta) {
105 struct FactoryInfo {
106 const char *name;
107 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
108 };
109
110 static const FactoryInfo kFactoryInfo[] = {
111 FACTORY_REF(AMRNBEncoder)
112 FACTORY_REF(AMRWBEncoder)
113 FACTORY_REF(AACEncoder)
James Dong1cc31e62010-07-02 17:44:44 -0700114 FACTORY_REF(AVCEncoder)
James Dong42ef0c72010-07-12 21:46:25 -0700115 FACTORY_REF(M4vH263Encoder)
James Dong17299ab2010-05-14 15:45:22 -0700116 };
117 for (size_t i = 0;
118 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
119 if (!strcmp(name, kFactoryInfo[i].name)) {
120 return (*kFactoryInfo[i].CreateFunc)(source, meta);
121 }
122 }
123
124 return NULL;
125}
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800126
127static sp<MediaSource> InstantiateSoftwareCodec(
128 const char *name, const sp<MediaSource> &source) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700129#if HAVE_SOFTWARE_DECODERS
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800130 struct FactoryInfo {
131 const char *name;
132 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
133 };
134
135 static const FactoryInfo kFactoryInfo[] = {
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800136 FACTORY_REF(AMRNBDecoder)
137 FACTORY_REF(AMRWBDecoder)
138 FACTORY_REF(AACDecoder)
139 FACTORY_REF(AVCDecoder)
Andreas Huber520b2a72010-08-09 09:54:59 -0700140 FACTORY_REF(G711Decoder)
Andreas Huber4b3913a2011-05-11 14:13:42 -0700141 FACTORY_REF(MP3Decoder)
James Dong02f5b542009-12-15 16:26:55 -0800142 FACTORY_REF(M4vH263Decoder)
Andreas Huber388379f2010-05-07 10:35:13 -0700143 FACTORY_REF(VorbisDecoder)
Andreas Huber47ba30e2010-05-24 14:38:02 -0700144 FACTORY_REF(VPXDecoder)
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800145 };
146 for (size_t i = 0;
147 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
148 if (!strcmp(name, kFactoryInfo[i].name)) {
Andreas Huber8946ab22010-09-15 16:20:42 -0700149 if (!strcmp(name, "VPXDecoder")) {
150 return new ThreadedSource(
151 (*kFactoryInfo[i].CreateFunc)(source));
152 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800153 return (*kFactoryInfo[i].CreateFunc)(source);
154 }
155 }
Andreas Huber4b3913a2011-05-11 14:13:42 -0700156#endif
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800157
158 return NULL;
159}
160
161#undef FACTORY_REF
162#undef FACTORY_CREATE
163
Andreas Huberbe06d262009-08-14 14:37:10 -0700164static const CodecInfo kDecoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700165 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
Andreas Huberd222c842010-08-26 14:29:34 -0700166// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.Nvidia.mp3.decoder" },
James Dong374aee62010-04-26 10:23:30 -0700167// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700168 { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800169 { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
Andreas Hubera4357ad2010-04-02 12:49:54 -0700170// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
Andreas Huberd222c842010-08-26 14:29:34 -0700171// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700172 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800173 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
Andreas Huberd222c842010-08-26 14:29:34 -0700174// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700175 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700176 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800177 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
Andreas Huberd222c842010-08-26 14:29:34 -0700178// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700179 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700180 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800181 { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700182 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
Andreas Huber520b2a72010-08-09 09:54:59 -0700183 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700184 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
Andreas Huber520b2a72010-08-09 09:54:59 -0700185 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
Andreas Huber9f9ae602010-10-27 14:53:55 -0700186 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700187 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700188 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
189 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700190 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700191 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800192 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
Andreas Huber9f9ae602010-10-27 14:53:55 -0700193 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700194 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700195 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700196 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700197 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800198 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
pgudadhe6ad2c352010-07-26 15:04:33 -0700199 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700200 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700201 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
202 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700203 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700204 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800205 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700206 { MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
Andreas Huber388379f2010-05-07 10:35:13 -0700207 { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
Andreas Huber4b3913a2011-05-11 14:13:42 -0700208 { MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
Andreas Huber47ba30e2010-05-24 14:38:02 -0700209 { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700210};
211
212static const CodecInfo kEncoderInfo[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -0700213 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
Andreas Huberacfbc802010-02-04 10:48:37 -0800214 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700215 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700216 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700217 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
James Dong17299ab2010-05-14 15:45:22 -0700218 { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700219 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700220 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
221 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
James Dong2e87f7b2010-09-23 17:46:34 -0700222 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700223 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700224 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700225 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700226 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
227 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
James Dong2e87f7b2010-09-23 17:46:34 -0700228 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700229 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
James Dong42ef0c72010-07-12 21:46:25 -0700230 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
Andreas Huber8ef64c92010-06-29 09:14:00 -0700231 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
Andreas Huber71c27d92010-03-19 11:43:15 -0700232 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
Andreas Hubere6c40962009-09-10 14:13:30 -0700233 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
pgudadhe9c305322010-07-26 13:59:29 -0700234 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.encoder" },
Andreas Huber524e6f62010-09-16 11:23:09 -0700235 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Encoder" },
James Dong1cc31e62010-07-02 17:44:44 -0700236 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
Andreas Huberbe06d262009-08-14 14:37:10 -0700237};
238
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800239#undef OPTIONAL
240
Andreas Hubere0873732009-09-10 09:57:53 -0700241#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700242#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber42c444a2010-02-09 10:20:00 -0800243#define CODEC_LOGE(x, ...) LOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
Andreas Huber4c483422009-09-02 16:05:36 -0700244
Andreas Huberbe06d262009-08-14 14:37:10 -0700245struct OMXCodecObserver : public BnOMXObserver {
Andreas Huber784202e2009-10-15 13:46:54 -0700246 OMXCodecObserver() {
247 }
248
249 void setCodec(const sp<OMXCodec> &target) {
250 mTarget = target;
Andreas Huberbe06d262009-08-14 14:37:10 -0700251 }
252
253 // from IOMXObserver
Andreas Huber784202e2009-10-15 13:46:54 -0700254 virtual void onMessage(const omx_message &msg) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700255 sp<OMXCodec> codec = mTarget.promote();
256
257 if (codec.get() != NULL) {
James Dong681e89c2011-01-10 08:55:02 -0800258 Mutex::Autolock autoLock(codec->mLock);
Andreas Huberbe06d262009-08-14 14:37:10 -0700259 codec->on_message(msg);
James Dong681e89c2011-01-10 08:55:02 -0800260 codec.clear();
Andreas Huberbe06d262009-08-14 14:37:10 -0700261 }
262 }
263
264protected:
265 virtual ~OMXCodecObserver() {}
266
267private:
268 wp<OMXCodec> mTarget;
269
270 OMXCodecObserver(const OMXCodecObserver &);
271 OMXCodecObserver &operator=(const OMXCodecObserver &);
272};
273
274static const char *GetCodec(const CodecInfo *info, size_t numInfos,
275 const char *mime, int index) {
276 CHECK(index >= 0);
277 for(size_t i = 0; i < numInfos; ++i) {
278 if (!strcasecmp(mime, info[i].mime)) {
279 if (index == 0) {
280 return info[i].codec;
281 }
282
283 --index;
284 }
285 }
286
287 return NULL;
288}
289
Andreas Huber4c483422009-09-02 16:05:36 -0700290template<class T>
291static void InitOMXParams(T *params) {
292 params->nSize = sizeof(T);
293 params->nVersion.s.nVersionMajor = 1;
294 params->nVersion.s.nVersionMinor = 0;
295 params->nVersion.s.nRevision = 0;
296 params->nVersion.s.nStep = 0;
297}
298
Andreas Hubere13526a2009-10-22 10:43:34 -0700299static bool IsSoftwareCodec(const char *componentName) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700300 if (!strncmp("OMX.google.", componentName, 11)) {
301 return true;
302 }
303
James Dong5592bcc2010-10-22 17:10:43 -0700304 if (!strncmp("OMX.", componentName, 4)) {
305 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -0700306 }
307
James Dong5592bcc2010-10-22 17:10:43 -0700308 return true;
Andreas Hubere13526a2009-10-22 10:43:34 -0700309}
310
Andreas Huber4b3913a2011-05-11 14:13:42 -0700311// A sort order in which OMX software codecs are first, followed
312// by other (non-OMX) software codecs, followed by everything else.
Andreas Hubere13526a2009-10-22 10:43:34 -0700313static int CompareSoftwareCodecsFirst(
314 const String8 *elem1, const String8 *elem2) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700315 bool isOMX1 = !strncmp(elem1->string(), "OMX.", 4);
316 bool isOMX2 = !strncmp(elem2->string(), "OMX.", 4);
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800317
Andreas Hubere13526a2009-10-22 10:43:34 -0700318 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
319 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
320
321 if (isSoftwareCodec1) {
Andreas Huber4b3913a2011-05-11 14:13:42 -0700322 if (!isSoftwareCodec2) { return -1; }
323
324 if (isOMX1) {
325 if (isOMX2) { return 0; }
326
327 return -1;
328 } else {
329 if (isOMX2) { return 0; }
330
331 return 1;
332 }
333
Andreas Hubere13526a2009-10-22 10:43:34 -0700334 return -1;
335 }
336
337 if (isSoftwareCodec2) {
338 return 1;
339 }
340
341 return 0;
342}
343
344// static
Andreas Huber1e194162010-10-06 16:43:57 -0700345uint32_t OMXCodec::getComponentQuirks(
346 const char *componentName, bool isEncoder) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700347 uint32_t quirks = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700348
Dima Zavin30ba6cb2010-08-23 11:10:03 -0700349 if (!strcmp(componentName, "OMX.Nvidia.amr.decoder") ||
350 !strcmp(componentName, "OMX.Nvidia.amrwb.decoder") ||
351 !strcmp(componentName, "OMX.Nvidia.aac.decoder") ||
352 !strcmp(componentName, "OMX.Nvidia.mp3.decoder")) {
353 quirks |= kDecoderLiesAboutNumberOfChannels;
354 }
355
Andreas Huberbe06d262009-08-14 14:37:10 -0700356 if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
357 quirks |= kNeedsFlushBeforeDisable;
Andreas Hubere331c7b2010-02-01 10:51:50 -0800358 quirks |= kDecoderLiesAboutNumberOfChannels;
Andreas Huberbe06d262009-08-14 14:37:10 -0700359 }
360 if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
361 quirks |= kNeedsFlushBeforeDisable;
Andreas Huber404cc412009-08-25 14:26:05 -0700362 quirks |= kRequiresFlushCompleteEmulation;
Andreas Hubera4357ad2010-04-02 12:49:54 -0700363 quirks |= kSupportsMultipleFramesPerInputBuffer;
Andreas Huberbe06d262009-08-14 14:37:10 -0700364 }
365 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
366 quirks |= kRequiresLoadedToIdleAfterAllocation;
367 quirks |= kRequiresAllocateBufferOnInputPorts;
Andreas Huberb482ce82009-10-29 12:02:48 -0700368 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dong90862e22010-08-26 19:12:59 -0700369 if (!strncmp(componentName, "OMX.qcom.video.encoder.avc", 26)) {
370
371 // The AVC encoder advertises the size of output buffers
372 // based on the input video resolution and assumes
373 // the worst/least compression ratio is 0.5. It is found that
374 // sometimes, the output buffer size is larger than
375 // size advertised by the encoder.
376 quirks |= kRequiresLargerEncoderOutputBuffer;
377 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700378 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700379 if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
380 }
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700381 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700382 quirks |= kRequiresAllocateBufferOnOutputPorts;
Andreas Huber52733b82010-01-25 10:41:35 -0800383 quirks |= kDefersOutputBufferAllocation;
Andreas Hubera7d0cf42009-09-04 07:48:51 -0700384 }
Andreas Huber8ef64c92010-06-29 09:14:00 -0700385 if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
386 quirks |= kRequiresAllocateBufferOnInputPorts;
387 quirks |= kRequiresAllocateBufferOnOutputPorts;
388 quirks |= kDefersOutputBufferAllocation;
389 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700390
Andreas Huber2dc64d82009-09-11 12:58:53 -0700391 if (!strncmp(componentName, "OMX.TI.", 7)) {
392 // Apparently I must not use OMX_UseBuffer on either input or
393 // output ports on any of the TI components or quote:
394 // "(I) may have unexpected problem (sic) which can be timing related
395 // and hard to reproduce."
396
397 quirks |= kRequiresAllocateBufferOnInputPorts;
398 quirks |= kRequiresAllocateBufferOnOutputPorts;
James Dongdca66e12010-06-14 11:14:38 -0700399 if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
James Dong4f501f02010-06-07 14:41:41 -0700400 quirks |= kAvoidMemcopyInputRecordingFrames;
401 }
Andreas Huber2dc64d82009-09-11 12:58:53 -0700402 }
403
Andreas Huberb8de9572010-02-22 14:58:45 -0800404 if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
405 quirks |= kInputBufferSizesAreBogus;
406 }
407
Andreas Huber1e194162010-10-06 16:43:57 -0700408 if (!strncmp(componentName, "OMX.SEC.", 8) && !isEncoder) {
409 // These output buffers contain no video data, just some
410 // opaque information that allows the overlay to display their
411 // contents.
412 quirks |= kOutputBuffersAreUnreadable;
413 }
414
Andreas Hubere13526a2009-10-22 10:43:34 -0700415 return quirks;
416}
417
418// static
419void OMXCodec::findMatchingCodecs(
420 const char *mime,
421 bool createEncoder, const char *matchComponentName,
422 uint32_t flags,
423 Vector<String8> *matchingCodecs) {
424 matchingCodecs->clear();
425
426 for (int index = 0;; ++index) {
427 const char *componentName;
428
429 if (createEncoder) {
430 componentName = GetCodec(
431 kEncoderInfo,
432 sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
433 mime, index);
434 } else {
435 componentName = GetCodec(
436 kDecoderInfo,
437 sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
438 mime, index);
439 }
440
441 if (!componentName) {
442 break;
443 }
444
445 // If a specific codec is requested, skip the non-matching ones.
446 if (matchComponentName && strcmp(componentName, matchComponentName)) {
447 continue;
448 }
449
James Dong170a9292010-10-22 17:28:15 -0700450 // When requesting software-only codecs, only push software codecs
451 // When requesting hardware-only codecs, only push hardware codecs
452 // When there is request neither for software-only nor for
453 // hardware-only codecs, push all codecs
454 if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
455 ((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
456 (!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
457
458 matchingCodecs->push(String8(componentName));
459 }
Andreas Hubere13526a2009-10-22 10:43:34 -0700460 }
461
462 if (flags & kPreferSoftwareCodecs) {
463 matchingCodecs->sort(CompareSoftwareCodecsFirst);
464 }
465}
466
467// static
Andreas Huber91eb0352009-12-07 09:43:00 -0800468sp<MediaSource> OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700469 const sp<IOMX> &omx,
470 const sp<MetaData> &meta, bool createEncoder,
471 const sp<MediaSource> &source,
472 const char *matchComponentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700473 uint32_t flags,
474 const sp<ANativeWindow> &nativeWindow) {
Andreas Hubere13526a2009-10-22 10:43:34 -0700475 const char *mime;
476 bool success = meta->findCString(kKeyMIMEType, &mime);
477 CHECK(success);
478
479 Vector<String8> matchingCodecs;
480 findMatchingCodecs(
481 mime, createEncoder, matchComponentName, flags, &matchingCodecs);
482
483 if (matchingCodecs.isEmpty()) {
484 return NULL;
485 }
486
487 sp<OMXCodecObserver> observer = new OMXCodecObserver;
488 IOMX::node_id node = 0;
Andreas Hubere13526a2009-10-22 10:43:34 -0700489
490 const char *componentName;
491 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
492 componentName = matchingCodecs[i].string();
493
James Dong17299ab2010-05-14 15:45:22 -0700494 sp<MediaSource> softwareCodec = createEncoder?
495 InstantiateSoftwareEncoder(componentName, source, meta):
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800496 InstantiateSoftwareCodec(componentName, source);
497
498 if (softwareCodec != NULL) {
499 LOGV("Successfully allocated software codec '%s'", componentName);
500
501 return softwareCodec;
502 }
Andreas Huberfb1c2f82009-12-15 13:25:11 -0800503
Andreas Hubere13526a2009-10-22 10:43:34 -0700504 LOGV("Attempting to allocate OMX node '%s'", componentName);
505
Andreas Huber5a40e392010-10-18 09:57:42 -0700506 uint32_t quirks = getComponentQuirks(componentName, createEncoder);
507
508 if (!createEncoder
509 && (quirks & kOutputBuffersAreUnreadable)
510 && (flags & kClientNeedsFramebuffer)) {
511 if (strncmp(componentName, "OMX.SEC.", 8)) {
512 // For OMX.SEC.* decoders we can enable a special mode that
513 // gives the client access to the framebuffer contents.
514
515 LOGW("Component '%s' does not give the client access to "
516 "the framebuffer contents. Skipping.",
517 componentName);
518
519 continue;
520 }
521 }
522
Andreas Hubere13526a2009-10-22 10:43:34 -0700523 status_t err = omx->allocateNode(componentName, observer, &node);
524 if (err == OK) {
525 LOGV("Successfully allocated OMX node '%s'", componentName);
526
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700527 sp<OMXCodec> codec = new OMXCodec(
Andreas Huber5a40e392010-10-18 09:57:42 -0700528 omx, node, quirks,
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700529 createEncoder, mime, componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700530 source, nativeWindow);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700531
532 observer->setCodec(codec);
533
Andreas Huber4c19bf92010-09-08 14:32:20 -0700534 err = codec->configureCodec(meta, flags);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700535
536 if (err == OK) {
537 return codec;
538 }
539
540 LOGV("Failed to configure codec '%s'", componentName);
Andreas Hubere13526a2009-10-22 10:43:34 -0700541 }
542 }
543
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700544 return NULL;
545}
Andreas Hubere13526a2009-10-22 10:43:34 -0700546
Andreas Huber4c19bf92010-09-08 14:32:20 -0700547status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) {
James Dong05c2fd52010-11-02 13:20:11 -0700548 mIsMetaDataStoredInVideoBuffers = false;
549 if (flags & kStoreMetaDataInVideoBuffers) {
550 mIsMetaDataStoredInVideoBuffers = true;
551 }
James Dong5f3ab062011-01-25 16:31:28 -0800552
553 mOnlySubmitOneBufferAtOneTime = false;
554 if (flags & kOnlySubmitOneInputBufferAtOneTime) {
555 mOnlySubmitOneBufferAtOneTime = true;
556 }
557
Glenn Kastenb8763f62011-01-28 12:37:51 -0800558 mEnableGrallocUsageProtected = false;
559 if (flags & kEnableGrallocUsageProtected) {
560 mEnableGrallocUsageProtected = true;
561 }
562 LOGV("configureCodec protected=%d", mEnableGrallocUsageProtected);
563
Andreas Huber4c19bf92010-09-08 14:32:20 -0700564 if (!(flags & kIgnoreCodecSpecificData)) {
565 uint32_t type;
566 const void *data;
567 size_t size;
568 if (meta->findData(kKeyESDS, &type, &data, &size)) {
569 ESDS esds((const char *)data, size);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800570 CHECK_EQ(esds.InitCheck(), (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -0700571
Andreas Huber4c19bf92010-09-08 14:32:20 -0700572 const void *codec_specific_data;
573 size_t codec_specific_data_size;
574 esds.getCodecSpecificInfo(
575 &codec_specific_data, &codec_specific_data_size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700576
Andreas Huber4c19bf92010-09-08 14:32:20 -0700577 addCodecSpecificData(
578 codec_specific_data, codec_specific_data_size);
579 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
580 // Parse the AVCDecoderConfigurationRecord
Andreas Huberebf66ea2009-08-19 13:32:58 -0700581
Andreas Huber4c19bf92010-09-08 14:32:20 -0700582 const uint8_t *ptr = (const uint8_t *)data;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700583
Andreas Huber4c19bf92010-09-08 14:32:20 -0700584 CHECK(size >= 7);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800585 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
Andreas Huber4c19bf92010-09-08 14:32:20 -0700586 uint8_t profile = ptr[1];
587 uint8_t level = ptr[3];
Andreas Huberebf66ea2009-08-19 13:32:58 -0700588
Andreas Huber4c19bf92010-09-08 14:32:20 -0700589 // There is decodable content out there that fails the following
590 // assertion, let's be lenient for now...
591 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
Andreas Huberebf66ea2009-08-19 13:32:58 -0700592
Andreas Huber4c19bf92010-09-08 14:32:20 -0700593 size_t lengthSize = 1 + (ptr[4] & 3);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700594
Andreas Huber4c19bf92010-09-08 14:32:20 -0700595 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
596 // violates it...
597 // CHECK((ptr[5] >> 5) == 7); // reserved
Andreas Huberebf66ea2009-08-19 13:32:58 -0700598
Andreas Huber4c19bf92010-09-08 14:32:20 -0700599 size_t numSeqParameterSets = ptr[5] & 31;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700600
Andreas Huber4c19bf92010-09-08 14:32:20 -0700601 ptr += 6;
602 size -= 6;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700603
Andreas Huber4c19bf92010-09-08 14:32:20 -0700604 for (size_t i = 0; i < numSeqParameterSets; ++i) {
605 CHECK(size >= 2);
606 size_t length = U16_AT(ptr);
Andreas Huberbe06d262009-08-14 14:37:10 -0700607
Andreas Huber4c19bf92010-09-08 14:32:20 -0700608 ptr += 2;
609 size -= 2;
Andreas Huberbe06d262009-08-14 14:37:10 -0700610
Andreas Huber4c19bf92010-09-08 14:32:20 -0700611 CHECK(size >= length);
Andreas Huberbe06d262009-08-14 14:37:10 -0700612
Andreas Huber4c19bf92010-09-08 14:32:20 -0700613 addCodecSpecificData(ptr, length);
Andreas Huberbe06d262009-08-14 14:37:10 -0700614
Andreas Huber4c19bf92010-09-08 14:32:20 -0700615 ptr += length;
616 size -= length;
617 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700618
Andreas Huber4c19bf92010-09-08 14:32:20 -0700619 CHECK(size >= 1);
620 size_t numPictureParameterSets = *ptr;
621 ++ptr;
622 --size;
Andreas Huberbe06d262009-08-14 14:37:10 -0700623
Andreas Huber4c19bf92010-09-08 14:32:20 -0700624 for (size_t i = 0; i < numPictureParameterSets; ++i) {
625 CHECK(size >= 2);
626 size_t length = U16_AT(ptr);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700627
Andreas Huber4c19bf92010-09-08 14:32:20 -0700628 ptr += 2;
629 size -= 2;
Andreas Huberebf66ea2009-08-19 13:32:58 -0700630
Andreas Huber4c19bf92010-09-08 14:32:20 -0700631 CHECK(size >= length);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700632
Andreas Huber4c19bf92010-09-08 14:32:20 -0700633 addCodecSpecificData(ptr, length);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700634
Andreas Huber4c19bf92010-09-08 14:32:20 -0700635 ptr += length;
636 size -= length;
637 }
Andreas Huberebf66ea2009-08-19 13:32:58 -0700638
Andreas Huber6ac2cb22010-11-18 14:06:07 -0800639 CODEC_LOGI(
Andreas Huber4c19bf92010-09-08 14:32:20 -0700640 "AVC profile = %d (%s), level = %d",
641 (int)profile, AVCProfileToString(profile), level);
Andreas Huberebf66ea2009-08-19 13:32:58 -0700642
Andreas Huber4c19bf92010-09-08 14:32:20 -0700643 if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
644 && (profile != kAVCProfileBaseline || level > 30)) {
645 // This stream exceeds the decoder's capabilities. The decoder
646 // does not handle this gracefully and would clobber the heap
647 // and wreak havoc instead...
Andreas Huberebf66ea2009-08-19 13:32:58 -0700648
Andreas Huber4c19bf92010-09-08 14:32:20 -0700649 LOGE("Profile and/or level exceed the decoder's capabilities.");
650 return ERROR_UNSUPPORTED;
651 }
Andreas Huber4b3913a2011-05-11 14:13:42 -0700652 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
653 addCodecSpecificData(data, size);
654
655 CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
656 addCodecSpecificData(data, size);
Andreas Huberbe06d262009-08-14 14:37:10 -0700657 }
658 }
659
James Dong17299ab2010-05-14 15:45:22 -0700660 int32_t bitRate = 0;
661 if (mIsEncoder) {
662 CHECK(meta->findInt32(kKeyBitRate, &bitRate));
663 }
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700664 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700665 setAMRFormat(false /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700666 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
James Dong17299ab2010-05-14 15:45:22 -0700667 setAMRFormat(true /* isWAMR */, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700668 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
Andreas Huber43ad6eaf2009-09-01 16:02:43 -0700669 int32_t numChannels, sampleRate;
670 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
671 CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
672
James Dong17299ab2010-05-14 15:45:22 -0700673 setAACFormat(numChannels, sampleRate, bitRate);
Andreas Huber4b3913a2011-05-11 14:13:42 -0700674 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
675 || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
676 // These are PCM-like formats with a fixed sample rate but
677 // a variable number of channels.
678
679 int32_t numChannels;
680 CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
681
682 setG711Format(numChannels);
Andreas Huberbe06d262009-08-14 14:37:10 -0700683 }
James Dongabed93a2010-04-22 17:27:04 -0700684
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700685 if (!strncasecmp(mMIME, "video/", 6)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700686
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700687 if (mIsEncoder) {
James Dong1244eab2010-06-08 11:58:53 -0700688 setVideoInputFormat(mMIME, meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700689 } else {
James Dong1244eab2010-06-08 11:58:53 -0700690 int32_t width, height;
691 bool success = meta->findInt32(kKeyWidth, &width);
692 success = success && meta->findInt32(kKeyHeight, &height);
693 CHECK(success);
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700694 status_t err = setVideoOutputFormat(
695 mMIME, width, height);
696
697 if (err != OK) {
698 return err;
699 }
Andreas Huberbe06d262009-08-14 14:37:10 -0700700 }
701 }
Andreas Hubera4357ad2010-04-02 12:49:54 -0700702
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700703 if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
704 && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700705 OMX_COLOR_FORMATTYPE format =
706 OMX_COLOR_Format32bitARGB8888;
707 // OMX_COLOR_FormatYUV420PackedPlanar;
708 // OMX_COLOR_FormatCbYCrY;
709 // OMX_COLOR_FormatYUV411Planar;
710
711 int32_t width, height;
712 bool success = meta->findInt32(kKeyWidth, &width);
713 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700714
715 int32_t compressedSize;
716 success = success && meta->findInt32(
Andreas Huberda050cf22009-09-02 14:01:43 -0700717 kKeyMaxInputSize, &compressedSize);
Andreas Huber5c0a9132009-08-20 11:16:40 -0700718
719 CHECK(success);
720 CHECK(compressedSize > 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700721
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700722 setImageOutputFormat(format, width, height);
723 setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
Andreas Huberbe06d262009-08-14 14:37:10 -0700724 }
725
Andreas Huberda050cf22009-09-02 14:01:43 -0700726 int32_t maxInputSize;
Andreas Huber1bceff92009-11-23 14:03:32 -0800727 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700728 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
Andreas Huberda050cf22009-09-02 14:01:43 -0700729 }
730
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700731 if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
James Dongabed93a2010-04-22 17:27:04 -0700732 || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
733 || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700734 setMinBufferSize(kPortIndexOutput, 8192); // XXX
Andreas Huberda050cf22009-09-02 14:01:43 -0700735 }
736
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700737 initOutputFormat(meta);
Andreas Huberbe06d262009-08-14 14:37:10 -0700738
Andreas Huber5a40e392010-10-18 09:57:42 -0700739 if ((flags & kClientNeedsFramebuffer)
740 && !strncmp(mComponentName, "OMX.SEC.", 8)) {
741 OMX_INDEXTYPE index;
742
743 status_t err =
744 mOMX->getExtensionIndex(
745 mNode,
746 "OMX.SEC.index.ThumbnailMode",
747 &index);
748
749 if (err != OK) {
750 return err;
751 }
752
753 OMX_BOOL enable = OMX_TRUE;
754 err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
755
756 if (err != OK) {
757 CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
758 "returned error 0x%08x", err);
759
760 return err;
761 }
762
763 mQuirks &= ~kOutputBuffersAreUnreadable;
764 }
765
Jamie Gennisdbfb32e2010-10-20 15:53:59 -0700766 if (mNativeWindow != NULL
767 && !mIsEncoder
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700768 && !strncasecmp(mMIME, "video/", 6)
769 && !strncmp(mComponentName, "OMX.", 4)) {
770 status_t err = initNativeWindow();
771 if (err != OK) {
772 return err;
773 }
774 }
775
Andreas Huber2a09c7e2010-03-16 11:44:07 -0700776 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -0700777}
778
Andreas Huberda050cf22009-09-02 14:01:43 -0700779void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
780 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -0700781 InitOMXParams(&def);
Andreas Huberda050cf22009-09-02 14:01:43 -0700782 def.nPortIndex = portIndex;
783
Andreas Huber784202e2009-10-15 13:46:54 -0700784 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700785 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800786 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -0700787
Andreas Huberb8de9572010-02-22 14:58:45 -0800788 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
789 || (def.nBufferSize < size)) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700790 def.nBufferSize = size;
Andreas Huberda050cf22009-09-02 14:01:43 -0700791 }
792
Andreas Huber784202e2009-10-15 13:46:54 -0700793 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -0700794 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800795 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800796
797 err = mOMX->getParameter(
798 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800799 CHECK_EQ(err, (status_t)OK);
Andreas Huber1bceff92009-11-23 14:03:32 -0800800
801 // Make sure the setting actually stuck.
Andreas Huberb8de9572010-02-22 14:58:45 -0800802 if (portIndex == kPortIndexInput
803 && (mQuirks & kInputBufferSizesAreBogus)) {
804 CHECK_EQ(def.nBufferSize, size);
805 } else {
806 CHECK(def.nBufferSize >= size);
807 }
Andreas Huberda050cf22009-09-02 14:01:43 -0700808}
809
Andreas Huberbe06d262009-08-14 14:37:10 -0700810status_t OMXCodec::setVideoPortFormatType(
811 OMX_U32 portIndex,
812 OMX_VIDEO_CODINGTYPE compressionFormat,
813 OMX_COLOR_FORMATTYPE colorFormat) {
814 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -0700815 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -0700816 format.nPortIndex = portIndex;
817 format.nIndex = 0;
818 bool found = false;
819
820 OMX_U32 index = 0;
821 for (;;) {
822 format.nIndex = index;
Andreas Huber784202e2009-10-15 13:46:54 -0700823 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700824 mNode, OMX_IndexParamVideoPortFormat,
825 &format, sizeof(format));
826
827 if (err != OK) {
828 return err;
829 }
830
831 // The following assertion is violated by TI's video decoder.
Andreas Huber5c0a9132009-08-20 11:16:40 -0700832 // CHECK_EQ(format.nIndex, index);
Andreas Huberbe06d262009-08-14 14:37:10 -0700833
834#if 1
Andreas Huber53a76bd2009-10-06 16:20:44 -0700835 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
Andreas Huberbe06d262009-08-14 14:37:10 -0700836 portIndex,
837 index, format.eCompressionFormat, format.eColorFormat);
838#endif
839
840 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
841 if (portIndex == kPortIndexInput
842 && colorFormat == format.eColorFormat) {
843 // eCompressionFormat does not seem right.
844 found = true;
845 break;
846 }
847 if (portIndex == kPortIndexOutput
848 && compressionFormat == format.eCompressionFormat) {
849 // eColorFormat does not seem right.
850 found = true;
851 break;
852 }
853 }
854
855 if (format.eCompressionFormat == compressionFormat
856 && format.eColorFormat == colorFormat) {
857 found = true;
858 break;
859 }
860
861 ++index;
862 }
863
864 if (!found) {
865 return UNKNOWN_ERROR;
866 }
867
Andreas Huber53a76bd2009-10-06 16:20:44 -0700868 CODEC_LOGV("found a match.");
Andreas Huber784202e2009-10-15 13:46:54 -0700869 status_t err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -0700870 mNode, OMX_IndexParamVideoPortFormat,
871 &format, sizeof(format));
872
873 return err;
874}
875
Andreas Huberb482ce82009-10-29 12:02:48 -0700876static size_t getFrameSize(
877 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
878 switch (colorFormat) {
879 case OMX_COLOR_FormatYCbYCr:
880 case OMX_COLOR_FormatCbYCrY:
881 return width * height * 2;
882
Andreas Huber71c27d92010-03-19 11:43:15 -0700883 case OMX_COLOR_FormatYUV420Planar:
Andreas Huberb482ce82009-10-29 12:02:48 -0700884 case OMX_COLOR_FormatYUV420SemiPlanar:
885 return (width * height * 3) / 2;
886
887 default:
888 CHECK(!"Should not be here. Unsupported color format.");
889 break;
890 }
891}
892
James Dongafd97e82010-08-03 17:19:23 -0700893status_t OMXCodec::findTargetColorFormat(
894 const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat) {
895 LOGV("findTargetColorFormat");
896 CHECK(mIsEncoder);
897
898 *colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
899 int32_t targetColorFormat;
900 if (meta->findInt32(kKeyColorFormat, &targetColorFormat)) {
901 *colorFormat = (OMX_COLOR_FORMATTYPE) targetColorFormat;
902 } else {
903 if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
904 *colorFormat = OMX_COLOR_FormatYCbYCr;
905 }
906 }
907
908 // Check whether the target color format is supported.
909 return isColorFormatSupported(*colorFormat, kPortIndexInput);
910}
911
912status_t OMXCodec::isColorFormatSupported(
913 OMX_COLOR_FORMATTYPE colorFormat, int portIndex) {
914 LOGV("isColorFormatSupported: %d", static_cast<int>(colorFormat));
915
916 // Enumerate all the color formats supported by
917 // the omx component to see whether the given
918 // color format is supported.
919 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
920 InitOMXParams(&portFormat);
921 portFormat.nPortIndex = portIndex;
922 OMX_U32 index = 0;
923 portFormat.nIndex = index;
924 while (true) {
925 if (OMX_ErrorNone != mOMX->getParameter(
926 mNode, OMX_IndexParamVideoPortFormat,
927 &portFormat, sizeof(portFormat))) {
James Dongb5024da2010-09-13 16:30:51 -0700928 break;
James Dongafd97e82010-08-03 17:19:23 -0700929 }
930 // Make sure that omx component does not overwrite
931 // the incremented index (bug 2897413).
932 CHECK_EQ(index, portFormat.nIndex);
933 if ((portFormat.eColorFormat == colorFormat)) {
934 LOGV("Found supported color format: %d", portFormat.eColorFormat);
935 return OK; // colorFormat is supported!
936 }
937 ++index;
938 portFormat.nIndex = index;
939
940 // OMX Spec defines less than 50 color formats
941 // 1000 is more than enough for us to tell whether the omx
942 // component in question is buggy or not.
943 if (index >= 1000) {
944 LOGE("More than %ld color formats are supported???", index);
945 break;
946 }
947 }
James Dongb5024da2010-09-13 16:30:51 -0700948
949 LOGE("color format %d is not supported", colorFormat);
James Dongafd97e82010-08-03 17:19:23 -0700950 return UNKNOWN_ERROR;
951}
952
Andreas Huberbe06d262009-08-14 14:37:10 -0700953void OMXCodec::setVideoInputFormat(
James Dong1244eab2010-06-08 11:58:53 -0700954 const char *mime, const sp<MetaData>& meta) {
955
956 int32_t width, height, frameRate, bitRate, stride, sliceHeight;
957 bool success = meta->findInt32(kKeyWidth, &width);
958 success = success && meta->findInt32(kKeyHeight, &height);
James Dongaac193c2010-11-10 20:43:53 -0800959 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -0700960 success = success && meta->findInt32(kKeyBitRate, &bitRate);
961 success = success && meta->findInt32(kKeyStride, &stride);
962 success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
963 CHECK(success);
964 CHECK(stride != 0);
Andreas Huberbe06d262009-08-14 14:37:10 -0700965
966 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -0700967 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700968 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -0700969 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700970 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -0700971 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -0700972 compressionFormat = OMX_VIDEO_CodingH263;
973 } else {
974 LOGE("Not a supported video mime type: %s", mime);
975 CHECK(!"Should not be here. Not a supported video mime type.");
976 }
977
James Dongafd97e82010-08-03 17:19:23 -0700978 OMX_COLOR_FORMATTYPE colorFormat;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800979 CHECK_EQ((status_t)OK, findTargetColorFormat(meta, &colorFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -0700980
James Dongb00e2462010-04-26 17:48:26 -0700981 status_t err;
982 OMX_PARAM_PORTDEFINITIONTYPE def;
983 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
984
985 //////////////////////// Input port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -0700986 CHECK_EQ(setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -0700987 kPortIndexInput, OMX_VIDEO_CodingUnused,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800988 colorFormat), (status_t)OK);
James Dong4f501f02010-06-07 14:41:41 -0700989
James Dongb00e2462010-04-26 17:48:26 -0700990 InitOMXParams(&def);
991 def.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -0700992
James Dongb00e2462010-04-26 17:48:26 -0700993 err = mOMX->getParameter(
994 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800995 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -0700996
James Dong1244eab2010-06-08 11:58:53 -0700997 def.nBufferSize = getFrameSize(colorFormat,
998 stride > 0? stride: -stride, sliceHeight);
James Dongb00e2462010-04-26 17:48:26 -0700999
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001000 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
James Dongb00e2462010-04-26 17:48:26 -07001001
1002 video_def->nFrameWidth = width;
1003 video_def->nFrameHeight = height;
James Dong1244eab2010-06-08 11:58:53 -07001004 video_def->nStride = stride;
1005 video_def->nSliceHeight = sliceHeight;
James Dong4f501f02010-06-07 14:41:41 -07001006 video_def->xFramerate = (frameRate << 16); // Q16 format
James Dongb00e2462010-04-26 17:48:26 -07001007 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1008 video_def->eColorFormat = colorFormat;
1009
James Dongb00e2462010-04-26 17:48:26 -07001010 err = mOMX->setParameter(
1011 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001012 CHECK_EQ(err, (status_t)OK);
James Dongb00e2462010-04-26 17:48:26 -07001013
1014 //////////////////////// Output port /////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -07001015 CHECK_EQ(setVideoPortFormatType(
1016 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001017 (status_t)OK);
Andreas Huber4c483422009-09-02 16:05:36 -07001018 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001019 def.nPortIndex = kPortIndexOutput;
1020
James Dongb00e2462010-04-26 17:48:26 -07001021 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001022 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1023
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001024 CHECK_EQ(err, (status_t)OK);
1025 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001026
1027 video_def->nFrameWidth = width;
1028 video_def->nFrameHeight = height;
James Dong81c929a2010-07-01 15:02:14 -07001029 video_def->xFramerate = 0; // No need for output port
James Dong4f501f02010-06-07 14:41:41 -07001030 video_def->nBitrate = bitRate; // Q16 format
Andreas Huberbe06d262009-08-14 14:37:10 -07001031 video_def->eCompressionFormat = compressionFormat;
1032 video_def->eColorFormat = OMX_COLOR_FormatUnused;
James Dong90862e22010-08-26 19:12:59 -07001033 if (mQuirks & kRequiresLargerEncoderOutputBuffer) {
1034 // Increases the output buffer size
1035 def.nBufferSize = ((def.nBufferSize * 3) >> 1);
1036 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001037
Andreas Huber784202e2009-10-15 13:46:54 -07001038 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001039 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001040 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001041
James Dongb00e2462010-04-26 17:48:26 -07001042 /////////////////// Codec-specific ////////////////////////
Andreas Huberb482ce82009-10-29 12:02:48 -07001043 switch (compressionFormat) {
1044 case OMX_VIDEO_CodingMPEG4:
1045 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001046 CHECK_EQ(setupMPEG4EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001047 break;
1048 }
1049
1050 case OMX_VIDEO_CodingH263:
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001051 CHECK_EQ(setupH263EncoderParameters(meta), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001052 break;
1053
Andreas Huberea6a38c2009-11-16 15:43:38 -08001054 case OMX_VIDEO_CodingAVC:
1055 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001056 CHECK_EQ(setupAVCEncoderParameters(meta), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001057 break;
1058 }
1059
Andreas Huberb482ce82009-10-29 12:02:48 -07001060 default:
1061 CHECK(!"Support for this compressionFormat to be implemented.");
1062 break;
1063 }
1064}
1065
James Dong1244eab2010-06-08 11:58:53 -07001066static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1067 if (iFramesInterval < 0) {
1068 return 0xFFFFFFFF;
1069 } else if (iFramesInterval == 0) {
1070 return 0;
1071 }
1072 OMX_U32 ret = frameRate * iFramesInterval;
1073 CHECK(ret > 1);
1074 return ret;
1075}
1076
James Dongc0ab2a62010-06-29 16:29:19 -07001077status_t OMXCodec::setupErrorCorrectionParameters() {
1078 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1079 InitOMXParams(&errorCorrectionType);
1080 errorCorrectionType.nPortIndex = kPortIndexOutput;
1081
1082 status_t err = mOMX->getParameter(
1083 mNode, OMX_IndexParamVideoErrorCorrection,
1084 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -07001085 if (err != OK) {
1086 LOGW("Error correction param query is not supported");
1087 return OK; // Optional feature. Ignore this failure
1088 }
James Dongc0ab2a62010-06-29 16:29:19 -07001089
1090 errorCorrectionType.bEnableHEC = OMX_FALSE;
1091 errorCorrectionType.bEnableResync = OMX_TRUE;
1092 errorCorrectionType.nResynchMarkerSpacing = 256;
1093 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1094 errorCorrectionType.bEnableRVLC = OMX_FALSE;
1095
1096 err = mOMX->setParameter(
1097 mNode, OMX_IndexParamVideoErrorCorrection,
1098 &errorCorrectionType, sizeof(errorCorrectionType));
James Dong903fc222010-09-22 17:37:42 -07001099 if (err != OK) {
1100 LOGW("Error correction param configuration is not supported");
1101 }
1102
1103 // Optional feature. Ignore the failure.
James Dongc0ab2a62010-06-29 16:29:19 -07001104 return OK;
1105}
1106
1107status_t OMXCodec::setupBitRate(int32_t bitRate) {
1108 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1109 InitOMXParams(&bitrateType);
1110 bitrateType.nPortIndex = kPortIndexOutput;
1111
1112 status_t err = mOMX->getParameter(
1113 mNode, OMX_IndexParamVideoBitrate,
1114 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001115 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001116
1117 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1118 bitrateType.nTargetBitrate = bitRate;
1119
1120 err = mOMX->setParameter(
1121 mNode, OMX_IndexParamVideoBitrate,
1122 &bitrateType, sizeof(bitrateType));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001123 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001124 return OK;
1125}
1126
James Dong81c929a2010-07-01 15:02:14 -07001127status_t OMXCodec::getVideoProfileLevel(
1128 const sp<MetaData>& meta,
1129 const CodecProfileLevel& defaultProfileLevel,
1130 CodecProfileLevel &profileLevel) {
1131 CODEC_LOGV("Default profile: %ld, level %ld",
1132 defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
1133
1134 // Are the default profile and level overwriten?
1135 int32_t profile, level;
1136 if (!meta->findInt32(kKeyVideoProfile, &profile)) {
1137 profile = defaultProfileLevel.mProfile;
1138 }
1139 if (!meta->findInt32(kKeyVideoLevel, &level)) {
1140 level = defaultProfileLevel.mLevel;
1141 }
1142 CODEC_LOGV("Target profile: %d, level: %d", profile, level);
1143
1144 // Are the target profile and level supported by the encoder?
1145 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
1146 InitOMXParams(&param);
1147 param.nPortIndex = kPortIndexOutput;
1148 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
1149 status_t err = mOMX->getParameter(
1150 mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
1151 &param, sizeof(param));
1152
James Dongdfb89912010-09-15 21:07:52 -07001153 if (err != OK) break;
James Dong81c929a2010-07-01 15:02:14 -07001154
1155 int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
1156 int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
James Dong929642e2010-07-08 11:16:11 -07001157 CODEC_LOGV("Supported profile: %d, level %d",
James Dong81c929a2010-07-01 15:02:14 -07001158 supportedProfile, supportedLevel);
1159
1160 if (profile == supportedProfile &&
James Dongdfb89912010-09-15 21:07:52 -07001161 level <= supportedLevel) {
1162 // We can further check whether the level is a valid
1163 // value; but we will leave that to the omx encoder component
1164 // via OMX_SetParameter call.
James Dong81c929a2010-07-01 15:02:14 -07001165 profileLevel.mProfile = profile;
1166 profileLevel.mLevel = level;
1167 return OK;
1168 }
1169 }
1170
1171 CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
1172 profile, level);
1173 return BAD_VALUE;
1174}
1175
James Dongc0ab2a62010-06-29 16:29:19 -07001176status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
1177 int32_t iFramesInterval, frameRate, bitRate;
1178 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001179 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dongc0ab2a62010-06-29 16:29:19 -07001180 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1181 CHECK(success);
1182 OMX_VIDEO_PARAM_H263TYPE h263type;
1183 InitOMXParams(&h263type);
1184 h263type.nPortIndex = kPortIndexOutput;
1185
1186 status_t err = mOMX->getParameter(
1187 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001188 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001189
1190 h263type.nAllowedPictureTypes =
1191 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1192
1193 h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1194 if (h263type.nPFrames == 0) {
1195 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1196 }
1197 h263type.nBFrames = 0;
1198
James Dong81c929a2010-07-01 15:02:14 -07001199 // Check profile and level parameters
1200 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001201 defaultProfileLevel.mProfile = h263type.eProfile;
1202 defaultProfileLevel.mLevel = h263type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001203 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1204 if (err != OK) return err;
1205 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
1206 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
James Dongc0ab2a62010-06-29 16:29:19 -07001207
1208 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1209 h263type.bForceRoundingTypeToZero = OMX_FALSE;
1210 h263type.nPictureHeaderRepetition = 0;
1211 h263type.nGOBHeaderInterval = 0;
1212
1213 err = mOMX->setParameter(
1214 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001215 CHECK_EQ(err, (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001216
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001217 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1218 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
James Dongc0ab2a62010-06-29 16:29:19 -07001219
1220 return OK;
1221}
1222
James Dong1244eab2010-06-08 11:58:53 -07001223status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
1224 int32_t iFramesInterval, frameRate, bitRate;
1225 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001226 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001227 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1228 CHECK(success);
Andreas Huberb482ce82009-10-29 12:02:48 -07001229 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1230 InitOMXParams(&mpeg4type);
1231 mpeg4type.nPortIndex = kPortIndexOutput;
1232
1233 status_t err = mOMX->getParameter(
1234 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001235 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001236
1237 mpeg4type.nSliceHeaderSpacing = 0;
1238 mpeg4type.bSVH = OMX_FALSE;
1239 mpeg4type.bGov = OMX_FALSE;
1240
1241 mpeg4type.nAllowedPictureTypes =
1242 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1243
James Dong1244eab2010-06-08 11:58:53 -07001244 mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1245 if (mpeg4type.nPFrames == 0) {
1246 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1247 }
Andreas Huberb482ce82009-10-29 12:02:48 -07001248 mpeg4type.nBFrames = 0;
Andreas Huberb482ce82009-10-29 12:02:48 -07001249 mpeg4type.nIDCVLCThreshold = 0;
1250 mpeg4type.bACPred = OMX_TRUE;
1251 mpeg4type.nMaxPacketSize = 256;
1252 mpeg4type.nTimeIncRes = 1000;
1253 mpeg4type.nHeaderExtension = 0;
1254 mpeg4type.bReversibleVLC = OMX_FALSE;
1255
James Dong81c929a2010-07-01 15:02:14 -07001256 // Check profile and level parameters
1257 CodecProfileLevel defaultProfileLevel, profileLevel;
James Dong1e0e1662010-09-22 17:42:09 -07001258 defaultProfileLevel.mProfile = mpeg4type.eProfile;
1259 defaultProfileLevel.mLevel = mpeg4type.eLevel;
James Dong81c929a2010-07-01 15:02:14 -07001260 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1261 if (err != OK) return err;
1262 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
1263 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
Andreas Huberb482ce82009-10-29 12:02:48 -07001264
1265 err = mOMX->setParameter(
1266 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001267 CHECK_EQ(err, (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001268
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001269 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
1270 CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
Andreas Huberb482ce82009-10-29 12:02:48 -07001271
1272 return OK;
Andreas Huberbe06d262009-08-14 14:37:10 -07001273}
1274
James Dong1244eab2010-06-08 11:58:53 -07001275status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
1276 int32_t iFramesInterval, frameRate, bitRate;
1277 bool success = meta->findInt32(kKeyBitRate, &bitRate);
James Dongaac193c2010-11-10 20:43:53 -08001278 success = success && meta->findInt32(kKeyFrameRate, &frameRate);
James Dong1244eab2010-06-08 11:58:53 -07001279 success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
1280 CHECK(success);
1281
Andreas Huberea6a38c2009-11-16 15:43:38 -08001282 OMX_VIDEO_PARAM_AVCTYPE h264type;
1283 InitOMXParams(&h264type);
1284 h264type.nPortIndex = kPortIndexOutput;
1285
1286 status_t err = mOMX->getParameter(
1287 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001288 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001289
1290 h264type.nAllowedPictureTypes =
1291 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1292
1293 h264type.nSliceHeaderSpacing = 0;
James Dong1244eab2010-06-08 11:58:53 -07001294 h264type.nBFrames = 0; // No B frames support yet
1295 h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
1296 if (h264type.nPFrames == 0) {
1297 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1298 }
James Dong81c929a2010-07-01 15:02:14 -07001299
1300 // Check profile and level parameters
1301 CodecProfileLevel defaultProfileLevel, profileLevel;
1302 defaultProfileLevel.mProfile = h264type.eProfile;
1303 defaultProfileLevel.mLevel = h264type.eLevel;
1304 err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
1305 if (err != OK) return err;
1306 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
1307 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
1308
1309 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1310 h264type.bUseHadamard = OMX_TRUE;
1311 h264type.nRefFrames = 1;
1312 h264type.nRefIdx10ActiveMinus1 = 0;
1313 h264type.nRefIdx11ActiveMinus1 = 0;
1314 h264type.bEntropyCodingCABAC = OMX_FALSE;
1315 h264type.bWeightedPPrediction = OMX_FALSE;
1316 h264type.bconstIpred = OMX_FALSE;
1317 h264type.bDirect8x8Inference = OMX_FALSE;
1318 h264type.bDirectSpatialTemporal = OMX_FALSE;
1319 h264type.nCabacInitIdc = 0;
1320 }
1321
1322 if (h264type.nBFrames != 0) {
1323 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1324 }
1325
Andreas Huberea6a38c2009-11-16 15:43:38 -08001326 h264type.bEnableUEP = OMX_FALSE;
1327 h264type.bEnableFMO = OMX_FALSE;
1328 h264type.bEnableASO = OMX_FALSE;
1329 h264type.bEnableRS = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001330 h264type.bFrameMBsOnly = OMX_TRUE;
1331 h264type.bMBAFF = OMX_FALSE;
Andreas Huberea6a38c2009-11-16 15:43:38 -08001332 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1333
pgudadhe9c305322010-07-26 13:59:29 -07001334 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
1335 h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1336 }
1337
Andreas Huberea6a38c2009-11-16 15:43:38 -08001338 err = mOMX->setParameter(
1339 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001340 CHECK_EQ(err, (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001341
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001342 CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
Andreas Huberea6a38c2009-11-16 15:43:38 -08001343
1344 return OK;
1345}
1346
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001347status_t OMXCodec::setVideoOutputFormat(
Andreas Huberbe06d262009-08-14 14:37:10 -07001348 const char *mime, OMX_U32 width, OMX_U32 height) {
Andreas Huber53a76bd2009-10-06 16:20:44 -07001349 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07001350
Andreas Huberbe06d262009-08-14 14:37:10 -07001351 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
Andreas Hubere6c40962009-09-10 14:13:30 -07001352 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001353 compressionFormat = OMX_VIDEO_CodingAVC;
Andreas Hubere6c40962009-09-10 14:13:30 -07001354 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001355 compressionFormat = OMX_VIDEO_CodingMPEG4;
Andreas Hubere6c40962009-09-10 14:13:30 -07001356 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001357 compressionFormat = OMX_VIDEO_CodingH263;
Andreas Huber4b3913a2011-05-11 14:13:42 -07001358 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1359 compressionFormat = OMX_VIDEO_CodingVPX;
Andreas Huberbe06d262009-08-14 14:37:10 -07001360 } else {
1361 LOGE("Not a supported video mime type: %s", mime);
1362 CHECK(!"Should not be here. Not a supported video mime type.");
1363 }
1364
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001365 status_t err = setVideoPortFormatType(
Andreas Huberbe06d262009-08-14 14:37:10 -07001366 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1367
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001368 if (err != OK) {
1369 return err;
1370 }
1371
Andreas Huberbe06d262009-08-14 14:37:10 -07001372#if 1
1373 {
1374 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
Andreas Huber4c483422009-09-02 16:05:36 -07001375 InitOMXParams(&format);
Andreas Huberbe06d262009-08-14 14:37:10 -07001376 format.nPortIndex = kPortIndexOutput;
1377 format.nIndex = 0;
1378
Andreas Huber784202e2009-10-15 13:46:54 -07001379 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001380 mNode, OMX_IndexParamVideoPortFormat,
1381 &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001382 CHECK_EQ(err, (status_t)OK);
1383 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07001384
1385 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1386
1387 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1388 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1389 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1390 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1391
Andreas Huber784202e2009-10-15 13:46:54 -07001392 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001393 mNode, OMX_IndexParamVideoPortFormat,
1394 &format, sizeof(format));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001395
1396 if (err != OK) {
1397 return err;
1398 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001399 }
1400#endif
1401
1402 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001403 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001404 def.nPortIndex = kPortIndexInput;
1405
Andreas Huber4c483422009-09-02 16:05:36 -07001406 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1407
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001408 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001409 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1410
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001411 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001412
1413#if 1
1414 // XXX Need a (much) better heuristic to compute input buffer sizes.
1415 const size_t X = 64 * 1024;
1416 if (def.nBufferSize < X) {
1417 def.nBufferSize = X;
1418 }
1419#endif
1420
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001421 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001422
1423 video_def->nFrameWidth = width;
1424 video_def->nFrameHeight = height;
1425
Andreas Huberb482ce82009-10-29 12:02:48 -07001426 video_def->eCompressionFormat = compressionFormat;
Andreas Huberbe06d262009-08-14 14:37:10 -07001427 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1428
Andreas Huber784202e2009-10-15 13:46:54 -07001429 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001430 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001431
1432 if (err != OK) {
1433 return err;
1434 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001435
1436 ////////////////////////////////////////////////////////////////////////////
1437
Andreas Huber4c483422009-09-02 16:05:36 -07001438 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001439 def.nPortIndex = kPortIndexOutput;
1440
Andreas Huber784202e2009-10-15 13:46:54 -07001441 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001442 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001443 CHECK_EQ(err, (status_t)OK);
1444 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
Andreas Huberbe06d262009-08-14 14:37:10 -07001445
1446#if 0
1447 def.nBufferSize =
1448 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
1449#endif
1450
1451 video_def->nFrameWidth = width;
1452 video_def->nFrameHeight = height;
1453
Andreas Huber784202e2009-10-15 13:46:54 -07001454 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001455 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber2a09c7e2010-03-16 11:44:07 -07001456
1457 return err;
Andreas Huberbe06d262009-08-14 14:37:10 -07001458}
1459
Andreas Huberbe06d262009-08-14 14:37:10 -07001460OMXCodec::OMXCodec(
1461 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
Andreas Huberebf66ea2009-08-19 13:32:58 -07001462 bool isEncoder,
Andreas Huberbe06d262009-08-14 14:37:10 -07001463 const char *mime,
1464 const char *componentName,
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001465 const sp<MediaSource> &source,
1466 const sp<ANativeWindow> &nativeWindow)
Andreas Huberbe06d262009-08-14 14:37:10 -07001467 : mOMX(omx),
Andreas Huberf1fe0642010-01-15 15:28:19 -08001468 mOMXLivesLocally(omx->livesLocally(getpid())),
Andreas Huberbe06d262009-08-14 14:37:10 -07001469 mNode(node),
1470 mQuirks(quirks),
1471 mIsEncoder(isEncoder),
1472 mMIME(strdup(mime)),
1473 mComponentName(strdup(componentName)),
1474 mSource(source),
1475 mCodecSpecificDataIndex(0),
Andreas Huberbe06d262009-08-14 14:37:10 -07001476 mState(LOADED),
Andreas Huber42978e52009-08-27 10:08:39 -07001477 mInitialBufferSubmit(true),
Andreas Huberbe06d262009-08-14 14:37:10 -07001478 mSignalledEOS(false),
1479 mNoMoreOutputData(false),
Andreas Hubercfd55572009-10-09 14:11:28 -07001480 mOutputPortSettingsHaveChanged(false),
Andreas Hubera4357ad2010-04-02 12:49:54 -07001481 mSeekTimeUs(-1),
Andreas Huber6624c9f2010-07-20 15:04:28 -07001482 mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
1483 mTargetTimeUs(-1),
Andreas Huberb9289832011-02-08 13:10:25 -08001484 mOutputPortSettingsChangedPending(false),
Andreas Huber1f24b302010-06-10 11:12:39 -07001485 mLeftOverBuffer(NULL),
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001486 mPaused(false),
Andreas Huber4b3913a2011-05-11 14:13:42 -07001487 mNativeWindow(!strncmp(componentName, "OMX.google.", 11)
1488 ? NULL : nativeWindow) {
Andreas Huberbe06d262009-08-14 14:37:10 -07001489 mPortStatus[kPortIndexInput] = ENABLED;
1490 mPortStatus[kPortIndexOutput] = ENABLED;
1491
Andreas Huber4c483422009-09-02 16:05:36 -07001492 setComponentRole();
1493}
1494
Andreas Hubere6c40962009-09-10 14:13:30 -07001495// static
1496void OMXCodec::setComponentRole(
1497 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1498 const char *mime) {
Andreas Huber4c483422009-09-02 16:05:36 -07001499 struct MimeToRole {
1500 const char *mime;
1501 const char *decoderRole;
1502 const char *encoderRole;
1503 };
1504
1505 static const MimeToRole kMimeToRole[] = {
Andreas Hubere6c40962009-09-10 14:13:30 -07001506 { MEDIA_MIMETYPE_AUDIO_MPEG,
1507 "audio_decoder.mp3", "audio_encoder.mp3" },
1508 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1509 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1510 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1511 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1512 { MEDIA_MIMETYPE_AUDIO_AAC,
1513 "audio_decoder.aac", "audio_encoder.aac" },
1514 { MEDIA_MIMETYPE_VIDEO_AVC,
1515 "video_decoder.avc", "video_encoder.avc" },
1516 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1517 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1518 { MEDIA_MIMETYPE_VIDEO_H263,
1519 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber4c483422009-09-02 16:05:36 -07001520 };
1521
1522 static const size_t kNumMimeToRole =
1523 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1524
1525 size_t i;
1526 for (i = 0; i < kNumMimeToRole; ++i) {
Andreas Hubere6c40962009-09-10 14:13:30 -07001527 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
Andreas Huber4c483422009-09-02 16:05:36 -07001528 break;
1529 }
1530 }
1531
1532 if (i == kNumMimeToRole) {
1533 return;
1534 }
1535
1536 const char *role =
Andreas Hubere6c40962009-09-10 14:13:30 -07001537 isEncoder ? kMimeToRole[i].encoderRole
1538 : kMimeToRole[i].decoderRole;
Andreas Huber4c483422009-09-02 16:05:36 -07001539
1540 if (role != NULL) {
Andreas Huber4c483422009-09-02 16:05:36 -07001541 OMX_PARAM_COMPONENTROLETYPE roleParams;
1542 InitOMXParams(&roleParams);
1543
1544 strncpy((char *)roleParams.cRole,
1545 role, OMX_MAX_STRINGNAME_SIZE - 1);
1546
1547 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1548
Andreas Huber784202e2009-10-15 13:46:54 -07001549 status_t err = omx->setParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07001550 node, OMX_IndexParamStandardComponentRole,
Andreas Huber4c483422009-09-02 16:05:36 -07001551 &roleParams, sizeof(roleParams));
1552
1553 if (err != OK) {
1554 LOGW("Failed to set standard component role '%s'.", role);
1555 }
1556 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001557}
1558
Andreas Hubere6c40962009-09-10 14:13:30 -07001559void OMXCodec::setComponentRole() {
1560 setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1561}
1562
Andreas Huberbe06d262009-08-14 14:37:10 -07001563OMXCodec::~OMXCodec() {
Andreas Huberf98197a2010-09-17 11:49:39 -07001564 mSource.clear();
1565
Andreas Hubereec06d32011-01-06 10:26:36 -08001566 CHECK(mState == LOADED || mState == ERROR || mState == LOADED_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07001567
Andreas Huber784202e2009-10-15 13:46:54 -07001568 status_t err = mOMX->freeNode(mNode);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001569 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001570
1571 mNode = NULL;
1572 setState(DEAD);
1573
1574 clearCodecSpecificData();
1575
1576 free(mComponentName);
1577 mComponentName = NULL;
Andreas Huberebf66ea2009-08-19 13:32:58 -07001578
Andreas Huberbe06d262009-08-14 14:37:10 -07001579 free(mMIME);
1580 mMIME = NULL;
1581}
1582
1583status_t OMXCodec::init() {
Andreas Huber42978e52009-08-27 10:08:39 -07001584 // mLock is held.
Andreas Huberbe06d262009-08-14 14:37:10 -07001585
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001586 CHECK_EQ((int)mState, (int)LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07001587
1588 status_t err;
1589 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
Andreas Huber784202e2009-10-15 13:46:54 -07001590 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001591 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001592 setState(LOADED_TO_IDLE);
1593 }
1594
1595 err = allocateBuffers();
Jamie Gennisfd8b75a2010-12-17 15:07:02 -08001596 if (err != (status_t)OK) {
1597 return err;
1598 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001599
1600 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
Andreas Huber784202e2009-10-15 13:46:54 -07001601 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001602 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07001603
1604 setState(LOADED_TO_IDLE);
1605 }
1606
1607 while (mState != EXECUTING && mState != ERROR) {
1608 mAsyncCompletion.wait(mLock);
1609 }
1610
1611 return mState == ERROR ? UNKNOWN_ERROR : OK;
1612}
1613
1614// static
1615bool OMXCodec::isIntermediateState(State state) {
1616 return state == LOADED_TO_IDLE
1617 || state == IDLE_TO_EXECUTING
1618 || state == EXECUTING_TO_IDLE
1619 || state == IDLE_TO_LOADED
1620 || state == RECONFIGURING;
1621}
1622
1623status_t OMXCodec::allocateBuffers() {
1624 status_t err = allocateBuffersOnPort(kPortIndexInput);
1625
1626 if (err != OK) {
1627 return err;
1628 }
1629
1630 return allocateBuffersOnPort(kPortIndexOutput);
1631}
1632
1633status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
Jamie Gennisdbfb32e2010-10-20 15:53:59 -07001634 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001635 return allocateOutputBuffersFromNativeWindow();
1636 }
1637
Jamie Gennis66380f72011-04-07 19:03:56 -07001638 if (mEnableGrallocUsageProtected && portIndex == kPortIndexOutput) {
1639 LOGE("protected output buffers must be stent to an ANativeWindow");
1640 return PERMISSION_DENIED;
1641 }
1642
Andreas Huberbe06d262009-08-14 14:37:10 -07001643 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07001644 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07001645 def.nPortIndex = portIndex;
1646
Andreas Huber784202e2009-10-15 13:46:54 -07001647 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07001648 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1649
1650 if (err != OK) {
1651 return err;
1652 }
1653
James Dong05c2fd52010-11-02 13:20:11 -07001654 if (mIsMetaDataStoredInVideoBuffers && portIndex == kPortIndexInput) {
1655 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1656 if (err != OK) {
1657 LOGE("Storing meta data in video buffers is not supported");
1658 return err;
1659 }
1660 }
1661
Andreas Huber57648e42010-08-04 10:14:30 -07001662 CODEC_LOGI("allocating %lu buffers of size %lu on %s port",
1663 def.nBufferCountActual, def.nBufferSize,
1664 portIndex == kPortIndexInput ? "input" : "output");
1665
Andreas Huber5c0a9132009-08-20 11:16:40 -07001666 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
Mathias Agopian6faf7892010-01-25 19:00:00 -08001667 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
Andreas Huber5c0a9132009-08-20 11:16:40 -07001668
Andreas Huberbe06d262009-08-14 14:37:10 -07001669 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Andreas Huber5c0a9132009-08-20 11:16:40 -07001670 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07001671 CHECK(mem.get() != NULL);
1672
Andreas Huberc712b9f2010-01-20 15:05:46 -08001673 BufferInfo info;
1674 info.mData = NULL;
1675 info.mSize = def.nBufferSize;
1676
Andreas Huberbe06d262009-08-14 14:37:10 -07001677 IOMX::buffer_id buffer;
1678 if (portIndex == kPortIndexInput
1679 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001680 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001681 mem.clear();
1682
Andreas Huberf1fe0642010-01-15 15:28:19 -08001683 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001684 mNode, portIndex, def.nBufferSize, &buffer,
1685 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001686 } else {
1687 err = mOMX->allocateBufferWithBackup(
1688 mNode, portIndex, mem, &buffer);
1689 }
Andreas Huber446f44f2009-08-25 17:23:44 -07001690 } else if (portIndex == kPortIndexOutput
1691 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
Andreas Huberf1fe0642010-01-15 15:28:19 -08001692 if (mOMXLivesLocally) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08001693 mem.clear();
1694
Andreas Huberf1fe0642010-01-15 15:28:19 -08001695 err = mOMX->allocateBuffer(
Andreas Huberc712b9f2010-01-20 15:05:46 -08001696 mNode, portIndex, def.nBufferSize, &buffer,
1697 &info.mData);
Andreas Huberf1fe0642010-01-15 15:28:19 -08001698 } else {
1699 err = mOMX->allocateBufferWithBackup(
1700 mNode, portIndex, mem, &buffer);
1701 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001702 } else {
Andreas Huber784202e2009-10-15 13:46:54 -07001703 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07001704 }
1705
1706 if (err != OK) {
1707 LOGE("allocate_buffer_with_backup failed");
1708 return err;
1709 }
1710
Andreas Huberc712b9f2010-01-20 15:05:46 -08001711 if (mem != NULL) {
1712 info.mData = mem->pointer();
1713 }
1714
Andreas Huberbe06d262009-08-14 14:37:10 -07001715 info.mBuffer = buffer;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001716 info.mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07001717 info.mMem = mem;
1718 info.mMediaBuffer = NULL;
1719
1720 if (portIndex == kPortIndexOutput) {
Andreas Huber52733b82010-01-25 10:41:35 -08001721 if (!(mOMXLivesLocally
1722 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1723 && (mQuirks & kDefersOutputBufferAllocation))) {
1724 // If the node does not fill in the buffer ptr at this time,
1725 // we will defer creating the MediaBuffer until receiving
1726 // the first FILL_BUFFER_DONE notification instead.
1727 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1728 info.mMediaBuffer->setObserver(this);
1729 }
Andreas Huberbe06d262009-08-14 14:37:10 -07001730 }
1731
1732 mPortBuffers[portIndex].push(info);
1733
Andreas Huber4c483422009-09-02 16:05:36 -07001734 CODEC_LOGV("allocated buffer %p on %s port", buffer,
Andreas Huberbe06d262009-08-14 14:37:10 -07001735 portIndex == kPortIndexInput ? "input" : "output");
1736 }
1737
Andreas Huber2ea14e22009-12-16 09:30:55 -08001738 // dumpPortStatus(portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07001739
1740 return OK;
1741}
1742
Andreas Huber5e9dc942011-01-21 14:32:31 -08001743status_t OMXCodec::applyRotation() {
1744 sp<MetaData> meta = mSource->getFormat();
1745
1746 int32_t rotationDegrees;
1747 if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
1748 rotationDegrees = 0;
1749 }
1750
1751 uint32_t transform;
1752 switch (rotationDegrees) {
1753 case 0: transform = 0; break;
1754 case 90: transform = HAL_TRANSFORM_ROT_90; break;
1755 case 180: transform = HAL_TRANSFORM_ROT_180; break;
1756 case 270: transform = HAL_TRANSFORM_ROT_270; break;
1757 default: transform = 0; break;
1758 }
1759
1760 status_t err = OK;
1761
1762 if (transform) {
1763 err = native_window_set_buffers_transform(
1764 mNativeWindow.get(), transform);
1765 }
1766
1767 return err;
1768}
1769
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001770status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
1771 // Get the number of buffers needed.
1772 OMX_PARAM_PORTDEFINITIONTYPE def;
1773 InitOMXParams(&def);
1774 def.nPortIndex = kPortIndexOutput;
1775
1776 status_t err = mOMX->getParameter(
1777 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1778 if (err != OK) {
1779 return err;
1780 }
1781
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001782 err = native_window_set_buffers_geometry(
1783 mNativeWindow.get(),
1784 def.format.video.nFrameWidth,
1785 def.format.video.nFrameHeight,
Jamie Gennis044ace62010-10-29 15:19:29 -07001786 def.format.video.eColorFormat);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001787
1788 if (err != 0) {
1789 LOGE("native_window_set_buffers_geometry failed: %s (%d)",
1790 strerror(-err), -err);
1791 return err;
1792 }
1793
Andreas Huber5e9dc942011-01-21 14:32:31 -08001794 err = applyRotation();
1795 if (err != OK) {
1796 return err;
1797 }
1798
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001799 // Set up the native window.
Jamie Gennis94c59802011-02-24 12:48:17 -08001800 OMX_U32 usage = 0;
1801 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
1802 if (err != 0) {
1803 LOGW("querying usage flags from OMX IL component failed: %d", err);
1804 // XXX: Currently this error is logged, but not fatal.
1805 usage = 0;
1806 }
Glenn Kastenb8763f62011-01-28 12:37:51 -08001807 if (mEnableGrallocUsageProtected) {
1808 usage |= GRALLOC_USAGE_PROTECTED;
1809 }
Jamie Gennis94c59802011-02-24 12:48:17 -08001810
Jamie Gennis66380f72011-04-07 19:03:56 -07001811 // Make sure to check whether either Stagefright or the video decoder
1812 // requested protected buffers.
1813 if (usage & GRALLOC_USAGE_PROTECTED) {
1814 // Verify that the ANativeWindow sends images directly to
1815 // SurfaceFlinger.
1816 int queuesToNativeWindow = 0;
1817 err = mNativeWindow->query(
1818 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
1819 &queuesToNativeWindow);
1820 if (err != 0) {
1821 LOGE("error authenticating native window: %d", err);
1822 return err;
1823 }
1824 if (queuesToNativeWindow != 1) {
1825 LOGE("native window could not be authenticated");
1826 return PERMISSION_DENIED;
1827 }
1828 }
1829
Glenn Kastenb8763f62011-01-28 12:37:51 -08001830 LOGV("native_window_set_usage usage=0x%x", usage);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001831 err = native_window_set_usage(
Jamie Gennis94c59802011-02-24 12:48:17 -08001832 mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001833 if (err != 0) {
1834 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
1835 return err;
1836 }
1837
Jamie Gennis01951fd2011-02-27 15:10:34 -08001838 int minUndequeuedBufs = 0;
1839 err = mNativeWindow->query(mNativeWindow.get(),
1840 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
1841 if (err != 0) {
1842 LOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
1843 strerror(-err), -err);
1844 return err;
1845 }
1846
1847 // XXX: Is this the right logic to use? It's not clear to me what the OMX
1848 // buffer counts refer to - how do they account for the renderer holding on
1849 // to buffers?
1850 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
1851 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
1852 def.nBufferCountActual = newBufferCount;
1853 err = mOMX->setParameter(
1854 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1855 if (err != OK) {
1856 CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
1857 newBufferCount, err);
1858 return err;
1859 }
1860 }
1861
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001862 err = native_window_set_buffer_count(
1863 mNativeWindow.get(), def.nBufferCountActual);
1864 if (err != 0) {
1865 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1866 -err);
1867 return err;
1868 }
1869
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001870 CODEC_LOGI("allocating %lu buffers from a native window of size %lu on "
1871 "output port", def.nBufferCountActual, def.nBufferSize);
1872
1873 // Dequeue buffers and send them to OMX
Jamie Gennis42024642011-02-22 18:33:06 -08001874 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07001875 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001876 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
1877 if (err != 0) {
1878 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1879 break;
1880 }
1881
1882 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001883 BufferInfo info;
1884 info.mData = NULL;
1885 info.mSize = def.nBufferSize;
Andreas Huberbbbcf652010-12-07 14:25:54 -08001886 info.mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001887 info.mMem = NULL;
1888 info.mMediaBuffer = new MediaBuffer(graphicBuffer);
1889 info.mMediaBuffer->setObserver(this);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001890 mPortBuffers[kPortIndexOutput].push(info);
Jamie Gennis42024642011-02-22 18:33:06 -08001891
1892 IOMX::buffer_id bufferId;
1893 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1894 &bufferId);
1895 if (err != 0) {
1896 CODEC_LOGE("registering GraphicBuffer with OMX IL component "
1897 "failed: %d", err);
1898 break;
1899 }
1900
1901 mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId;
1902
1903 CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
1904 bufferId, graphicBuffer.get());
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001905 }
1906
1907 OMX_U32 cancelStart;
1908 OMX_U32 cancelEnd;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001909 if (err != 0) {
1910 // If an error occurred while dequeuing we need to cancel any buffers
1911 // that were dequeued.
1912 cancelStart = 0;
Jamie Gennis42024642011-02-22 18:33:06 -08001913 cancelEnd = mPortBuffers[kPortIndexOutput].size();
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001914 } else {
1915 // Return the last two buffers to the native window.
Jamie Gennis01951fd2011-02-27 15:10:34 -08001916 cancelStart = def.nBufferCountActual - minUndequeuedBufs;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001917 cancelEnd = def.nBufferCountActual;
1918 }
1919
1920 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1921 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
1922 cancelBufferToNativeWindow(info);
1923 }
1924
1925 return err;
1926}
1927
1928status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08001929 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001930 CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
1931 int err = mNativeWindow->cancelBuffer(
1932 mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
1933 if (err != 0) {
1934 CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
1935
1936 setState(ERROR);
1937 return err;
1938 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08001939 info->mStatus = OWNED_BY_NATIVE_WINDOW;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001940 return OK;
1941}
1942
1943OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
1944 // Dequeue the next buffer from the native window.
Iliyan Malchevb2a153a2011-05-01 11:33:26 -07001945 ANativeWindowBuffer* buf;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001946 int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
1947 if (err != 0) {
1948 CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
1949
1950 setState(ERROR);
1951 return 0;
1952 }
1953
1954 // Determine which buffer we just dequeued.
1955 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1956 BufferInfo *bufInfo = 0;
1957 for (size_t i = 0; i < buffers->size(); i++) {
1958 sp<GraphicBuffer> graphicBuffer = buffers->itemAt(i).
1959 mMediaBuffer->graphicBuffer();
1960 if (graphicBuffer->handle == buf->handle) {
1961 bufInfo = &buffers->editItemAt(i);
1962 break;
1963 }
1964 }
1965
1966 if (bufInfo == 0) {
1967 CODEC_LOGE("dequeued unrecognized buffer: %p", buf);
1968
1969 setState(ERROR);
1970 return 0;
1971 }
1972
1973 // The native window no longer owns the buffer.
Andreas Huberbbbcf652010-12-07 14:25:54 -08001974 CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
1975 bufInfo->mStatus = OWNED_BY_US;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07001976
1977 return bufInfo;
1978}
1979
Andreas Huberbe06d262009-08-14 14:37:10 -07001980void OMXCodec::on_message(const omx_message &msg) {
Andreas Huber3a28b022011-03-28 14:48:28 -07001981 if (mState == ERROR) {
1982 LOGW("Dropping OMX message - we're in ERROR state.");
1983 return;
1984 }
1985
Andreas Huberbe06d262009-08-14 14:37:10 -07001986 switch (msg.type) {
1987 case omx_message::EVENT:
1988 {
1989 onEvent(
1990 msg.u.event_data.event, msg.u.event_data.data1,
1991 msg.u.event_data.data2);
1992
1993 break;
1994 }
1995
1996 case omx_message::EMPTY_BUFFER_DONE:
1997 {
1998 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1999
Andreas Huber4c483422009-09-02 16:05:36 -07002000 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002001
2002 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2003 size_t i = 0;
2004 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2005 ++i;
2006 }
2007
2008 CHECK(i < buffers->size());
Andreas Huberbbbcf652010-12-07 14:25:54 -08002009 if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002010 LOGW("We already own input buffer %p, yet received "
2011 "an EMPTY_BUFFER_DONE.", buffer);
2012 }
2013
James Dong05c2fd52010-11-02 13:20:11 -07002014 BufferInfo* info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002015 info->mStatus = OWNED_BY_US;
James Dong05c2fd52010-11-02 13:20:11 -07002016
2017 // Buffer could not be released until empty buffer done is called.
2018 if (info->mMediaBuffer != NULL) {
James Dong31b9375f2010-11-10 21:11:41 -08002019 if (mIsEncoder &&
2020 (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2021 // If zero-copy mode is enabled this will send the
2022 // input buffer back to the upstream source.
2023 restorePatchedDataPointer(info);
2024 }
2025
James Dong05c2fd52010-11-02 13:20:11 -07002026 info->mMediaBuffer->release();
2027 info->mMediaBuffer = NULL;
2028 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002029
2030 if (mPortStatus[kPortIndexInput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002031 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002032
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002033 status_t err = freeBuffer(kPortIndexInput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002034 CHECK_EQ(err, (status_t)OK);
Andreas Huber4a9375e2010-02-09 11:54:33 -08002035 } else if (mState != ERROR
2036 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002037 CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002038 drainInputBuffer(&buffers->editItemAt(i));
2039 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002040 break;
2041 }
2042
2043 case omx_message::FILL_BUFFER_DONE:
2044 {
2045 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
2046 OMX_U32 flags = msg.u.extended_buffer_data.flags;
2047
Andreas Huber2ea14e22009-12-16 09:30:55 -08002048 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
Andreas Huberbe06d262009-08-14 14:37:10 -07002049 buffer,
2050 msg.u.extended_buffer_data.range_length,
Andreas Huber2ea14e22009-12-16 09:30:55 -08002051 flags,
Andreas Huberbe06d262009-08-14 14:37:10 -07002052 msg.u.extended_buffer_data.timestamp,
2053 msg.u.extended_buffer_data.timestamp / 1E6);
2054
2055 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2056 size_t i = 0;
2057 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
2058 ++i;
2059 }
2060
2061 CHECK(i < buffers->size());
2062 BufferInfo *info = &buffers->editItemAt(i);
2063
Andreas Huberbbbcf652010-12-07 14:25:54 -08002064 if (info->mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002065 LOGW("We already own output buffer %p, yet received "
2066 "a FILL_BUFFER_DONE.", buffer);
2067 }
2068
Andreas Huberbbbcf652010-12-07 14:25:54 -08002069 info->mStatus = OWNED_BY_US;
Andreas Huberbe06d262009-08-14 14:37:10 -07002070
2071 if (mPortStatus[kPortIndexOutput] == DISABLING) {
Andreas Huber4c483422009-09-02 16:05:36 -07002072 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
Andreas Huberbe06d262009-08-14 14:37:10 -07002073
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002074 status_t err = freeBuffer(kPortIndexOutput, i);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002075 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002076
Andreas Huber2ea14e22009-12-16 09:30:55 -08002077#if 0
Andreas Huberd7795892009-08-26 10:33:47 -07002078 } else if (mPortStatus[kPortIndexOutput] == ENABLED
2079 && (flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber4c483422009-09-02 16:05:36 -07002080 CODEC_LOGV("No more output data.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002081 mNoMoreOutputData = true;
2082 mBufferFilled.signal();
Andreas Huber2ea14e22009-12-16 09:30:55 -08002083#endif
Andreas Huberbe06d262009-08-14 14:37:10 -07002084 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002085 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberebf66ea2009-08-19 13:32:58 -07002086
Andreas Huber52733b82010-01-25 10:41:35 -08002087 if (info->mMediaBuffer == NULL) {
2088 CHECK(mOMXLivesLocally);
2089 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
2090 CHECK(mQuirks & kDefersOutputBufferAllocation);
2091
2092 // The qcom video decoders on Nexus don't actually allocate
2093 // output buffer memory on a call to OMX_AllocateBuffer
2094 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
2095 // structure is only filled in later.
2096
2097 info->mMediaBuffer = new MediaBuffer(
2098 msg.u.extended_buffer_data.data_ptr,
2099 info->mSize);
2100 info->mMediaBuffer->setObserver(this);
2101 }
2102
Andreas Huberbe06d262009-08-14 14:37:10 -07002103 MediaBuffer *buffer = info->mMediaBuffer;
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002104 bool isGraphicBuffer = buffer->graphicBuffer() != NULL;
Andreas Huberbe06d262009-08-14 14:37:10 -07002105
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002106 if (!isGraphicBuffer
2107 && msg.u.extended_buffer_data.range_offset
Andreas Huberf88f8442010-08-10 11:18:36 -07002108 + msg.u.extended_buffer_data.range_length
2109 > buffer->size()) {
2110 CODEC_LOGE(
2111 "Codec lied about its buffer size requirements, "
2112 "sending a buffer larger than the originally "
2113 "advertised size in FILL_BUFFER_DONE!");
2114 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002115 buffer->set_range(
2116 msg.u.extended_buffer_data.range_offset,
2117 msg.u.extended_buffer_data.range_length);
2118
2119 buffer->meta_data()->clear();
2120
Andreas Huberfa8de752009-10-08 10:07:49 -07002121 buffer->meta_data()->setInt64(
2122 kKeyTime, msg.u.extended_buffer_data.timestamp);
Andreas Huberbe06d262009-08-14 14:37:10 -07002123
2124 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
2125 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
2126 }
Andreas Huberea6a38c2009-11-16 15:43:38 -08002127 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
2128 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
2129 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002130
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002131 if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
Andreas Huber1e194162010-10-06 16:43:57 -07002132 buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
2133 }
2134
Andreas Huberbe06d262009-08-14 14:37:10 -07002135 buffer->meta_data()->setPointer(
2136 kKeyPlatformPrivate,
2137 msg.u.extended_buffer_data.platform_private);
2138
2139 buffer->meta_data()->setPointer(
2140 kKeyBufferID,
2141 msg.u.extended_buffer_data.buffer);
2142
Andreas Huber2ea14e22009-12-16 09:30:55 -08002143 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
2144 CODEC_LOGV("No more output data.");
2145 mNoMoreOutputData = true;
2146 }
Andreas Huber6624c9f2010-07-20 15:04:28 -07002147
2148 if (mTargetTimeUs >= 0) {
2149 CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
2150
2151 if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
2152 CODEC_LOGV(
2153 "skipping output buffer at timestamp %lld us",
2154 msg.u.extended_buffer_data.timestamp);
2155
2156 fillOutputBuffer(info);
2157 break;
2158 }
2159
2160 CODEC_LOGV(
2161 "returning output buffer at target timestamp "
2162 "%lld us",
2163 msg.u.extended_buffer_data.timestamp);
2164
2165 mTargetTimeUs = -1;
2166 }
2167
2168 mFilledBuffers.push_back(i);
2169 mBufferFilled.signal();
James Dongfc8b7c92010-12-07 14:37:27 -08002170 if (mIsEncoder) {
2171 sched_yield();
2172 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002173 }
2174
2175 break;
2176 }
2177
2178 default:
2179 {
2180 CHECK(!"should not be here.");
2181 break;
2182 }
2183 }
2184}
2185
Andreas Huberb1678602009-10-19 13:06:40 -07002186// Has the format changed in any way that the client would have to be aware of?
2187static bool formatHasNotablyChanged(
2188 const sp<MetaData> &from, const sp<MetaData> &to) {
2189 if (from.get() == NULL && to.get() == NULL) {
2190 return false;
2191 }
2192
Andreas Huberf68c1682009-10-21 14:01:30 -07002193 if ((from.get() == NULL && to.get() != NULL)
2194 || (from.get() != NULL && to.get() == NULL)) {
Andreas Huberb1678602009-10-19 13:06:40 -07002195 return true;
2196 }
2197
2198 const char *mime_from, *mime_to;
2199 CHECK(from->findCString(kKeyMIMEType, &mime_from));
2200 CHECK(to->findCString(kKeyMIMEType, &mime_to));
2201
2202 if (strcasecmp(mime_from, mime_to)) {
2203 return true;
2204 }
2205
2206 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
2207 int32_t colorFormat_from, colorFormat_to;
2208 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
2209 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
2210
2211 if (colorFormat_from != colorFormat_to) {
2212 return true;
2213 }
2214
2215 int32_t width_from, width_to;
2216 CHECK(from->findInt32(kKeyWidth, &width_from));
2217 CHECK(to->findInt32(kKeyWidth, &width_to));
2218
2219 if (width_from != width_to) {
2220 return true;
2221 }
2222
2223 int32_t height_from, height_to;
2224 CHECK(from->findInt32(kKeyHeight, &height_from));
2225 CHECK(to->findInt32(kKeyHeight, &height_to));
2226
2227 if (height_from != height_to) {
2228 return true;
2229 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002230
2231 int32_t left_from, top_from, right_from, bottom_from;
2232 CHECK(from->findRect(
2233 kKeyCropRect,
2234 &left_from, &top_from, &right_from, &bottom_from));
2235
2236 int32_t left_to, top_to, right_to, bottom_to;
2237 CHECK(to->findRect(
2238 kKeyCropRect,
2239 &left_to, &top_to, &right_to, &bottom_to));
2240
2241 if (left_to != left_from || top_to != top_from
2242 || right_to != right_from || bottom_to != bottom_from) {
2243 return true;
2244 }
Andreas Huberb1678602009-10-19 13:06:40 -07002245 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
2246 int32_t numChannels_from, numChannels_to;
2247 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
2248 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
2249
2250 if (numChannels_from != numChannels_to) {
2251 return true;
2252 }
2253
2254 int32_t sampleRate_from, sampleRate_to;
2255 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
2256 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
2257
2258 if (sampleRate_from != sampleRate_to) {
2259 return true;
2260 }
2261 }
2262
2263 return false;
2264}
2265
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002266void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2267 switch (event) {
2268 case OMX_EventCmdComplete:
2269 {
2270 onCmdComplete((OMX_COMMANDTYPE)data1, data2);
2271 break;
2272 }
2273
2274 case OMX_EventError:
2275 {
2276 CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
2277
2278 setState(ERROR);
2279 break;
2280 }
2281
2282 case OMX_EventPortSettingsChanged:
2283 {
2284 CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
2285 data1, data2);
2286
2287 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
2288 onPortSettingsChanged(data1);
James Dong7e91d912011-03-18 12:19:43 -07002289 } else if (data1 == kPortIndexOutput &&
2290 (data2 == OMX_IndexConfigCommonOutputCrop ||
2291 data2 == OMX_IndexConfigCommonScale)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002292
2293 sp<MetaData> oldOutputFormat = mOutputFormat;
2294 initOutputFormat(mSource->getFormat());
2295
James Dong7e91d912011-03-18 12:19:43 -07002296 if (data2 == OMX_IndexConfigCommonOutputCrop &&
2297 formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002298 mOutputPortSettingsHaveChanged = true;
2299
2300 if (mNativeWindow != NULL) {
2301 int32_t left, top, right, bottom;
2302 CHECK(mOutputFormat->findRect(
2303 kKeyCropRect,
2304 &left, &top, &right, &bottom));
2305
2306 android_native_rect_t crop;
2307 crop.left = left;
2308 crop.top = top;
Andreas Huberb13c4a92011-03-29 10:00:20 -07002309 crop.right = right + 1;
2310 crop.bottom = bottom + 1;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002311
Andreas Huber00d6c722011-01-26 12:02:35 -08002312 // We'll ignore any errors here, if the surface is
2313 // already invalid, we'll know soon enough.
2314 native_window_set_crop(mNativeWindow.get(), &crop);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002315 }
James Dong7e91d912011-03-18 12:19:43 -07002316 } else if (data2 == OMX_IndexConfigCommonScale) {
2317 OMX_CONFIG_SCALEFACTORTYPE scale;
2318 InitOMXParams(&scale);
2319 scale.nPortIndex = kPortIndexOutput;
2320
2321 // Change display dimension only when necessary.
2322 if (OK == mOMX->getConfig(
2323 mNode,
2324 OMX_IndexConfigCommonScale,
2325 &scale, sizeof(scale))) {
2326 int32_t left, top, right, bottom;
2327 CHECK(mOutputFormat->findRect(kKeyCropRect,
2328 &left, &top,
2329 &right, &bottom));
2330
2331 // The scale is in 16.16 format.
2332 // scale 1.0 = 0x010000. When there is no
2333 // need to change the display, skip it.
2334 LOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
2335 scale.xWidth, scale.xHeight);
2336
2337 if (scale.xWidth != 0x010000) {
2338 mOutputFormat->setInt32(kKeyDisplayWidth,
2339 ((right - left + 1) * scale.xWidth) >> 16);
2340 mOutputPortSettingsHaveChanged = true;
2341 }
2342
2343 if (scale.xHeight != 0x010000) {
2344 mOutputFormat->setInt32(kKeyDisplayHeight,
2345 ((bottom - top + 1) * scale.xHeight) >> 16);
2346 mOutputPortSettingsHaveChanged = true;
2347 }
2348 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002349 }
2350 }
2351 break;
2352 }
2353
2354#if 0
2355 case OMX_EventBufferFlag:
2356 {
2357 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
2358
2359 if (data1 == kPortIndexOutput) {
2360 mNoMoreOutputData = true;
2361 }
2362 break;
2363 }
2364#endif
2365
2366 default:
2367 {
2368 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
2369 break;
2370 }
2371 }
2372}
2373
Andreas Huberbe06d262009-08-14 14:37:10 -07002374void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
2375 switch (cmd) {
2376 case OMX_CommandStateSet:
2377 {
2378 onStateChange((OMX_STATETYPE)data);
2379 break;
2380 }
2381
2382 case OMX_CommandPortDisable:
2383 {
2384 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002385 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002386
2387 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002388 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING);
2389 CHECK_EQ(mPortBuffers[portIndex].size(), 0u);
Andreas Huberbe06d262009-08-14 14:37:10 -07002390
2391 mPortStatus[portIndex] = DISABLED;
2392
2393 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002394 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002395
Andreas Huberb1678602009-10-19 13:06:40 -07002396 sp<MetaData> oldOutputFormat = mOutputFormat;
Andreas Hubercfd55572009-10-09 14:11:28 -07002397 initOutputFormat(mSource->getFormat());
Andreas Huberb1678602009-10-19 13:06:40 -07002398
2399 // Don't notify clients if the output port settings change
2400 // wasn't of importance to them, i.e. it may be that just the
2401 // number of buffers has changed and nothing else.
2402 mOutputPortSettingsHaveChanged =
2403 formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
Andreas Hubercfd55572009-10-09 14:11:28 -07002404
Andreas Huberbe06d262009-08-14 14:37:10 -07002405 enablePortAsync(portIndex);
2406
2407 status_t err = allocateBuffersOnPort(portIndex);
Andreas Huberba1b16792011-01-19 09:20:58 -08002408
2409 if (err != OK) {
2410 CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
2411 setState(ERROR);
2412 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002413 }
2414 break;
2415 }
2416
2417 case OMX_CommandPortEnable:
2418 {
2419 OMX_U32 portIndex = data;
Andreas Huber4c483422009-09-02 16:05:36 -07002420 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002421
2422 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002423 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002424
2425 mPortStatus[portIndex] = ENABLED;
2426
2427 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002428 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002429
2430 setState(EXECUTING);
2431
2432 fillOutputBuffers();
2433 }
2434 break;
2435 }
2436
2437 case OMX_CommandFlush:
2438 {
2439 OMX_U32 portIndex = data;
2440
Andreas Huber4c483422009-09-02 16:05:36 -07002441 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002442
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002443 CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN);
Andreas Huberbe06d262009-08-14 14:37:10 -07002444 mPortStatus[portIndex] = ENABLED;
2445
2446 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
2447 mPortBuffers[portIndex].size());
2448
2449 if (mState == RECONFIGURING) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002450 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberbe06d262009-08-14 14:37:10 -07002451
2452 disablePortAsync(portIndex);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002453 } else if (mState == EXECUTING_TO_IDLE) {
2454 if (mPortStatus[kPortIndexInput] == ENABLED
2455 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002456 CODEC_LOGV("Finished flushing both ports, now completing "
Andreas Huber127fcdc2009-08-26 16:27:02 -07002457 "transition from EXECUTING to IDLE.");
2458
2459 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2460 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2461
2462 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002463 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002464 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07002465 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002466 } else {
2467 // We're flushing both ports in preparation for seeking.
2468
2469 if (mPortStatus[kPortIndexInput] == ENABLED
2470 && mPortStatus[kPortIndexOutput] == ENABLED) {
Andreas Huber4c483422009-09-02 16:05:36 -07002471 CODEC_LOGV("Finished flushing both ports, now continuing from"
Andreas Huberbe06d262009-08-14 14:37:10 -07002472 " seek-time.");
2473
Andreas Huber1f24b302010-06-10 11:12:39 -07002474 // We implicitly resume pulling on our upstream source.
2475 mPaused = false;
2476
Andreas Huberbe06d262009-08-14 14:37:10 -07002477 drainInputBuffers();
2478 fillOutputBuffers();
2479 }
Andreas Huberb9289832011-02-08 13:10:25 -08002480
2481 if (mOutputPortSettingsChangedPending) {
2482 CODEC_LOGV(
2483 "Honoring deferred output port settings change.");
2484
2485 mOutputPortSettingsChangedPending = false;
2486 onPortSettingsChanged(kPortIndexOutput);
2487 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002488 }
2489
2490 break;
2491 }
2492
2493 default:
2494 {
Andreas Huber4c483422009-09-02 16:05:36 -07002495 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
Andreas Huberbe06d262009-08-14 14:37:10 -07002496 break;
2497 }
2498 }
2499}
2500
2501void OMXCodec::onStateChange(OMX_STATETYPE newState) {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002502 CODEC_LOGV("onStateChange %d", newState);
2503
Andreas Huberbe06d262009-08-14 14:37:10 -07002504 switch (newState) {
2505 case OMX_StateIdle:
2506 {
Andreas Huber4c483422009-09-02 16:05:36 -07002507 CODEC_LOGV("Now Idle.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002508 if (mState == LOADED_TO_IDLE) {
Andreas Huber784202e2009-10-15 13:46:54 -07002509 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002510 mNode, OMX_CommandStateSet, OMX_StateExecuting);
2511
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002512 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002513
2514 setState(IDLE_TO_EXECUTING);
2515 } else {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002516 CHECK_EQ((int)mState, (int)EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002517
2518 CHECK_EQ(
2519 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
2520 mPortBuffers[kPortIndexInput].size());
2521
2522 CHECK_EQ(
2523 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
2524 mPortBuffers[kPortIndexOutput].size());
2525
Andreas Huber784202e2009-10-15 13:46:54 -07002526 status_t err = mOMX->sendCommand(
Andreas Huberbe06d262009-08-14 14:37:10 -07002527 mNode, OMX_CommandStateSet, OMX_StateLoaded);
2528
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002529 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002530
2531 err = freeBuffersOnPort(kPortIndexInput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002532 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002533
2534 err = freeBuffersOnPort(kPortIndexOutput);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002535 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002536
2537 mPortStatus[kPortIndexInput] = ENABLED;
2538 mPortStatus[kPortIndexOutput] = ENABLED;
2539
2540 setState(IDLE_TO_LOADED);
2541 }
2542 break;
2543 }
2544
2545 case OMX_StateExecuting:
2546 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002547 CHECK_EQ((int)mState, (int)IDLE_TO_EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002548
Andreas Huber4c483422009-09-02 16:05:36 -07002549 CODEC_LOGV("Now Executing.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002550
Andreas Huberb9289832011-02-08 13:10:25 -08002551 mOutputPortSettingsChangedPending = false;
2552
Andreas Huberbe06d262009-08-14 14:37:10 -07002553 setState(EXECUTING);
2554
Andreas Huber42978e52009-08-27 10:08:39 -07002555 // Buffers will be submitted to the component in the first
2556 // call to OMXCodec::read as mInitialBufferSubmit is true at
2557 // this point. This ensures that this on_message call returns,
2558 // releases the lock and ::init can notice the state change and
2559 // itself return.
Andreas Huberbe06d262009-08-14 14:37:10 -07002560 break;
2561 }
2562
2563 case OMX_StateLoaded:
2564 {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002565 CHECK_EQ((int)mState, (int)IDLE_TO_LOADED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002566
Andreas Huber4c483422009-09-02 16:05:36 -07002567 CODEC_LOGV("Now Loaded.");
Andreas Huberbe06d262009-08-14 14:37:10 -07002568
2569 setState(LOADED);
2570 break;
2571 }
2572
Andreas Huberc712b9f2010-01-20 15:05:46 -08002573 case OMX_StateInvalid:
2574 {
2575 setState(ERROR);
2576 break;
2577 }
2578
Andreas Huberbe06d262009-08-14 14:37:10 -07002579 default:
2580 {
2581 CHECK(!"should not be here.");
2582 break;
2583 }
2584 }
2585}
2586
2587// static
2588size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
2589 size_t n = 0;
2590 for (size_t i = 0; i < buffers.size(); ++i) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002591 if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002592 ++n;
2593 }
2594 }
2595
2596 return n;
2597}
2598
2599status_t OMXCodec::freeBuffersOnPort(
2600 OMX_U32 portIndex, bool onlyThoseWeOwn) {
2601 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2602
2603 status_t stickyErr = OK;
2604
2605 for (size_t i = buffers->size(); i-- > 0;) {
2606 BufferInfo *info = &buffers->editItemAt(i);
2607
Andreas Huberbbbcf652010-12-07 14:25:54 -08002608 if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002609 continue;
2610 }
2611
Andreas Huberbbbcf652010-12-07 14:25:54 -08002612 CHECK(info->mStatus == OWNED_BY_US
2613 || info->mStatus == OWNED_BY_NATIVE_WINDOW);
Andreas Huberbe06d262009-08-14 14:37:10 -07002614
Andreas Huber92022852009-09-14 15:24:14 -07002615 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
2616
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002617 status_t err = freeBuffer(portIndex, i);
Andreas Huberbe06d262009-08-14 14:37:10 -07002618
2619 if (err != OK) {
2620 stickyErr = err;
2621 }
2622
Andreas Huberbe06d262009-08-14 14:37:10 -07002623 }
2624
2625 CHECK(onlyThoseWeOwn || buffers->isEmpty());
2626
2627 return stickyErr;
2628}
2629
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002630status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) {
2631 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2632
2633 BufferInfo *info = &buffers->editItemAt(bufIndex);
2634
2635 status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
2636
2637 if (err == OK && info->mMediaBuffer != NULL) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002638 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002639 info->mMediaBuffer->setObserver(NULL);
2640
2641 // Make sure nobody but us owns this buffer at this point.
2642 CHECK_EQ(info->mMediaBuffer->refcount(), 0);
2643
2644 // Cancel the buffer if it belongs to an ANativeWindow.
2645 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
Andreas Huberbbbcf652010-12-07 14:25:54 -08002646 if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002647 err = cancelBufferToNativeWindow(info);
2648 }
2649
2650 info->mMediaBuffer->release();
James Dong31b9375f2010-11-10 21:11:41 -08002651 info->mMediaBuffer = NULL;
Jamie Gennisf0c5c1e2010-11-01 16:04:31 -07002652 }
2653
2654 if (err == OK) {
2655 buffers->removeAt(bufIndex);
2656 }
2657
2658 return err;
2659}
2660
Andreas Huberbe06d262009-08-14 14:37:10 -07002661void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
Andreas Huber4c483422009-09-02 16:05:36 -07002662 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002663
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002664 CHECK_EQ((int)mState, (int)EXECUTING);
2665 CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
Andreas Huberb9289832011-02-08 13:10:25 -08002666 CHECK(!mOutputPortSettingsChangedPending);
2667
2668 if (mPortStatus[kPortIndexOutput] != ENABLED) {
2669 CODEC_LOGV("Deferring output port settings change.");
2670 mOutputPortSettingsChangedPending = true;
2671 return;
2672 }
2673
Andreas Huberbe06d262009-08-14 14:37:10 -07002674 setState(RECONFIGURING);
2675
2676 if (mQuirks & kNeedsFlushBeforeDisable) {
Andreas Huber404cc412009-08-25 14:26:05 -07002677 if (!flushPortAsync(portIndex)) {
2678 onCmdComplete(OMX_CommandFlush, portIndex);
2679 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002680 } else {
2681 disablePortAsync(portIndex);
2682 }
2683}
2684
Andreas Huber404cc412009-08-25 14:26:05 -07002685bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
Andreas Huber127fcdc2009-08-26 16:27:02 -07002686 CHECK(mState == EXECUTING || mState == RECONFIGURING
2687 || mState == EXECUTING_TO_IDLE);
Andreas Huberbe06d262009-08-14 14:37:10 -07002688
Andreas Huber4c483422009-09-02 16:05:36 -07002689 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
Andreas Huber404cc412009-08-25 14:26:05 -07002690 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
2691 mPortBuffers[portIndex].size());
2692
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002693 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002694 mPortStatus[portIndex] = SHUTTING_DOWN;
2695
Andreas Huber404cc412009-08-25 14:26:05 -07002696 if ((mQuirks & kRequiresFlushCompleteEmulation)
2697 && countBuffersWeOwn(mPortBuffers[portIndex])
2698 == mPortBuffers[portIndex].size()) {
2699 // No flush is necessary and this component fails to send a
2700 // flush-complete event in this case.
2701
2702 return false;
2703 }
2704
Andreas Huberbe06d262009-08-14 14:37:10 -07002705 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002706 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002707 CHECK_EQ(err, (status_t)OK);
Andreas Huber404cc412009-08-25 14:26:05 -07002708
2709 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002710}
2711
2712void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
2713 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2714
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002715 CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002716 mPortStatus[portIndex] = DISABLING;
2717
Andreas Huberd222c842010-08-26 14:29:34 -07002718 CODEC_LOGV("sending OMX_CommandPortDisable(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002719 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002720 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002721 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002722
2723 freeBuffersOnPort(portIndex, true);
2724}
2725
2726void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
2727 CHECK(mState == EXECUTING || mState == RECONFIGURING);
2728
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002729 CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED);
Andreas Huberbe06d262009-08-14 14:37:10 -07002730 mPortStatus[portIndex] = ENABLING;
2731
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002732 CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
Andreas Huberbe06d262009-08-14 14:37:10 -07002733 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07002734 mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002735 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002736}
2737
2738void OMXCodec::fillOutputBuffers() {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002739 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002740
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002741 // This is a workaround for some decoders not properly reporting
2742 // end-of-output-stream. If we own all input buffers and also own
2743 // all output buffers and we already signalled end-of-input-stream,
2744 // the end-of-output-stream is implied.
2745 if (mSignalledEOS
2746 && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
2747 == mPortBuffers[kPortIndexInput].size()
2748 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
2749 == mPortBuffers[kPortIndexOutput].size()) {
2750 mNoMoreOutputData = true;
2751 mBufferFilled.signal();
2752
2753 return;
2754 }
2755
Andreas Huberbe06d262009-08-14 14:37:10 -07002756 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2757 for (size_t i = 0; i < buffers->size(); ++i) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002758 BufferInfo *info = &buffers->editItemAt(i);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002759 if (info->mStatus == OWNED_BY_US) {
Jamie Gennis58a36ad2010-10-07 14:08:38 -07002760 fillOutputBuffer(&buffers->editItemAt(i));
2761 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002762 }
2763}
2764
2765void OMXCodec::drainInputBuffers() {
Andreas Huberd06e5b82009-08-28 13:18:14 -07002766 CHECK(mState == EXECUTING || mState == RECONFIGURING);
Andreas Huberbe06d262009-08-14 14:37:10 -07002767
2768 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2769 for (size_t i = 0; i < buffers->size(); ++i) {
James Dong5f3ab062011-01-25 16:31:28 -08002770 BufferInfo *info = &buffers->editItemAt(i);
2771
2772 if (info->mStatus != OWNED_BY_US) {
2773 continue;
2774 }
2775
2776 if (!drainInputBuffer(info)) {
2777 break;
2778 }
2779
2780 if (mOnlySubmitOneBufferAtOneTime) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002781 break;
2782 }
Andreas Huberbe06d262009-08-14 14:37:10 -07002783 }
2784}
2785
Andreas Huberbbbcf652010-12-07 14:25:54 -08002786bool OMXCodec::drainInputBuffer(BufferInfo *info) {
2787 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Andreas Huberbe06d262009-08-14 14:37:10 -07002788
2789 if (mSignalledEOS) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002790 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002791 }
2792
2793 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
2794 const CodecSpecificData *specific =
2795 mCodecSpecificData[mCodecSpecificDataIndex];
2796
2797 size_t size = specific->mSize;
2798
Andreas Hubere6c40962009-09-10 14:13:30 -07002799 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
Andreas Huber4f5e6022009-08-19 09:29:34 -07002800 && !(mQuirks & kWantsNALFragments)) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002801 static const uint8_t kNALStartCode[4] =
2802 { 0x00, 0x00, 0x00, 0x01 };
2803
Andreas Huberc712b9f2010-01-20 15:05:46 -08002804 CHECK(info->mSize >= specific->mSize + 4);
Andreas Huberbe06d262009-08-14 14:37:10 -07002805
2806 size += 4;
2807
Andreas Huberc712b9f2010-01-20 15:05:46 -08002808 memcpy(info->mData, kNALStartCode, 4);
2809 memcpy((uint8_t *)info->mData + 4,
Andreas Huberbe06d262009-08-14 14:37:10 -07002810 specific->mData, specific->mSize);
2811 } else {
Andreas Huberc712b9f2010-01-20 15:05:46 -08002812 CHECK(info->mSize >= specific->mSize);
2813 memcpy(info->mData, specific->mData, specific->mSize);
Andreas Huberbe06d262009-08-14 14:37:10 -07002814 }
2815
Andreas Huber2ea14e22009-12-16 09:30:55 -08002816 mNoMoreOutputData = false;
2817
Andreas Huberdbcb2c62010-01-14 11:32:13 -08002818 CODEC_LOGV("calling emptyBuffer with codec specific data");
2819
Andreas Huber784202e2009-10-15 13:46:54 -07002820 status_t err = mOMX->emptyBuffer(
Andreas Huberbe06d262009-08-14 14:37:10 -07002821 mNode, info->mBuffer, 0, size,
2822 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
2823 0);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08002824 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07002825
Andreas Huberbbbcf652010-12-07 14:25:54 -08002826 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07002827
2828 ++mCodecSpecificDataIndex;
Andreas Huberbbbcf652010-12-07 14:25:54 -08002829 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07002830 }
2831
Andreas Huber1f24b302010-06-10 11:12:39 -07002832 if (mPaused) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08002833 return false;
Andreas Huber1f24b302010-06-10 11:12:39 -07002834 }
2835
Andreas Huberbe06d262009-08-14 14:37:10 -07002836 status_t err;
Andreas Huber2ea14e22009-12-16 09:30:55 -08002837
Andreas Hubera4357ad2010-04-02 12:49:54 -07002838 bool signalEOS = false;
2839 int64_t timestampUs = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -07002840
Andreas Hubera4357ad2010-04-02 12:49:54 -07002841 size_t offset = 0;
2842 int32_t n = 0;
Andreas Huberbbbcf652010-12-07 14:25:54 -08002843
Andreas Hubera4357ad2010-04-02 12:49:54 -07002844 for (;;) {
2845 MediaBuffer *srcBuffer;
2846 if (mSeekTimeUs >= 0) {
2847 if (mLeftOverBuffer) {
2848 mLeftOverBuffer->release();
2849 mLeftOverBuffer = NULL;
2850 }
James Dong2144f632010-12-11 10:43:41 -08002851
2852 MediaSource::ReadOptions options;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002853 options.setSeekTo(mSeekTimeUs, mSeekMode);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002854
2855 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07002856 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002857 mBufferFilled.signal();
2858
2859 err = mSource->read(&srcBuffer, &options);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002860
2861 if (err == OK) {
2862 int64_t targetTimeUs;
2863 if (srcBuffer->meta_data()->findInt64(
2864 kKeyTargetTime, &targetTimeUs)
2865 && targetTimeUs >= 0) {
Andreas Huberb9289832011-02-08 13:10:25 -08002866 CODEC_LOGV("targetTimeUs = %lld us", targetTimeUs);
Andreas Huber6624c9f2010-07-20 15:04:28 -07002867 mTargetTimeUs = targetTimeUs;
2868 } else {
2869 mTargetTimeUs = -1;
2870 }
2871 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002872 } else if (mLeftOverBuffer) {
2873 srcBuffer = mLeftOverBuffer;
2874 mLeftOverBuffer = NULL;
2875
2876 err = OK;
2877 } else {
James Dong2144f632010-12-11 10:43:41 -08002878 err = mSource->read(&srcBuffer);
Andreas Hubera4357ad2010-04-02 12:49:54 -07002879 }
2880
2881 if (err != OK) {
2882 signalEOS = true;
2883 mFinalStatus = err;
2884 mSignalledEOS = true;
Andreas Huber94bced12010-12-14 09:50:46 -08002885 mBufferFilled.signal();
Andreas Hubera4357ad2010-04-02 12:49:54 -07002886 break;
2887 }
2888
2889 size_t remainingBytes = info->mSize - offset;
2890
2891 if (srcBuffer->range_length() > remainingBytes) {
2892 if (offset == 0) {
2893 CODEC_LOGE(
2894 "Codec's input buffers are too small to accomodate "
2895 "buffer read from source (info->mSize = %d, srcLength = %d)",
2896 info->mSize, srcBuffer->range_length());
2897
2898 srcBuffer->release();
2899 srcBuffer = NULL;
2900
2901 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002902 return false;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002903 }
2904
2905 mLeftOverBuffer = srcBuffer;
2906 break;
2907 }
2908
James Dong05c2fd52010-11-02 13:20:11 -07002909 bool releaseBuffer = true;
James Dong4f501f02010-06-07 14:41:41 -07002910 if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
2911 CHECK(mOMXLivesLocally && offset == 0);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002912
2913 OMX_BUFFERHEADERTYPE *header =
2914 (OMX_BUFFERHEADERTYPE *)info->mBuffer;
2915
James Dong31b9375f2010-11-10 21:11:41 -08002916 CHECK(header->pBuffer == info->mData);
Andreas Huberbbbcf652010-12-07 14:25:54 -08002917
2918 header->pBuffer =
2919 (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
2920
James Dong05c2fd52010-11-02 13:20:11 -07002921 releaseBuffer = false;
2922 info->mMediaBuffer = srcBuffer;
James Dong4f501f02010-06-07 14:41:41 -07002923 } else {
James Dong05c2fd52010-11-02 13:20:11 -07002924 if (mIsMetaDataStoredInVideoBuffers) {
2925 releaseBuffer = false;
2926 info->mMediaBuffer = srcBuffer;
2927 }
James Dong4f501f02010-06-07 14:41:41 -07002928 memcpy((uint8_t *)info->mData + offset,
Andreas Huberbbbcf652010-12-07 14:25:54 -08002929 (const uint8_t *)srcBuffer->data()
2930 + srcBuffer->range_offset(),
James Dong4f501f02010-06-07 14:41:41 -07002931 srcBuffer->range_length());
2932 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002933
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002934 int64_t lastBufferTimeUs;
2935 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
Andreas Huber6624c9f2010-07-20 15:04:28 -07002936 CHECK(lastBufferTimeUs >= 0);
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002937
Andreas Hubera4357ad2010-04-02 12:49:54 -07002938 if (offset == 0) {
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002939 timestampUs = lastBufferTimeUs;
Andreas Hubera4357ad2010-04-02 12:49:54 -07002940 }
2941
2942 offset += srcBuffer->range_length();
2943
Andreas Huber4b3913a2011-05-11 14:13:42 -07002944 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mMIME)) {
2945 CHECK(!(mQuirks & kSupportsMultipleFramesPerInputBuffer));
2946 CHECK_GE(info->mSize, offset + sizeof(int32_t));
2947
2948 int32_t numPageSamples;
2949 if (!srcBuffer->meta_data()->findInt32(
2950 kKeyValidSamples, &numPageSamples)) {
2951 numPageSamples = -1;
2952 }
2953
2954 memcpy((uint8_t *)info->mData + offset,
2955 &numPageSamples,
2956 sizeof(numPageSamples));
2957
2958 offset += sizeof(numPageSamples);
2959 }
2960
James Dong05c2fd52010-11-02 13:20:11 -07002961 if (releaseBuffer) {
2962 srcBuffer->release();
2963 srcBuffer = NULL;
2964 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002965
2966 ++n;
2967
2968 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
2969 break;
2970 }
Andreas Huber2dd8ff82010-04-20 14:26:00 -07002971
2972 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
2973
2974 if (coalescedDurationUs > 250000ll) {
2975 // Don't coalesce more than 250ms worth of encoded data at once.
2976 break;
2977 }
Andreas Hubera4357ad2010-04-02 12:49:54 -07002978 }
2979
2980 if (n > 1) {
2981 LOGV("coalesced %d frames into one input buffer", n);
Andreas Huberbe06d262009-08-14 14:37:10 -07002982 }
2983
2984 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
Andreas Huberbe06d262009-08-14 14:37:10 -07002985
Andreas Hubera4357ad2010-04-02 12:49:54 -07002986 if (signalEOS) {
Andreas Huberbe06d262009-08-14 14:37:10 -07002987 flags |= OMX_BUFFERFLAG_EOS;
Andreas Huberbe06d262009-08-14 14:37:10 -07002988 } else {
Andreas Huber2ea14e22009-12-16 09:30:55 -08002989 mNoMoreOutputData = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07002990 }
2991
Andreas Hubera4357ad2010-04-02 12:49:54 -07002992 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
2993 "timestamp %lld us (%.2f secs)",
2994 info->mBuffer, offset,
2995 timestampUs, timestampUs / 1E6);
Andreas Huber3f427072009-10-08 11:02:27 -07002996
Andreas Huber784202e2009-10-15 13:46:54 -07002997 err = mOMX->emptyBuffer(
Andreas Hubera4357ad2010-04-02 12:49:54 -07002998 mNode, info->mBuffer, 0, offset,
Andreas Huberfa8de752009-10-08 10:07:49 -07002999 flags, timestampUs);
Andreas Huber3f427072009-10-08 11:02:27 -07003000
3001 if (err != OK) {
3002 setState(ERROR);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003003 return false;
Andreas Huber3f427072009-10-08 11:02:27 -07003004 }
3005
Andreas Huberbbbcf652010-12-07 14:25:54 -08003006 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberea6a38c2009-11-16 15:43:38 -08003007
3008 // This component does not ever signal the EOS flag on output buffers,
3009 // Thanks for nothing.
3010 if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) {
3011 mNoMoreOutputData = true;
3012 mBufferFilled.signal();
3013 }
Andreas Huberbbbcf652010-12-07 14:25:54 -08003014
3015 return true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003016}
3017
3018void OMXCodec::fillOutputBuffer(BufferInfo *info) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003019 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
Andreas Huberbe06d262009-08-14 14:37:10 -07003020
Andreas Huber404cc412009-08-25 14:26:05 -07003021 if (mNoMoreOutputData) {
Andreas Huber4c483422009-09-02 16:05:36 -07003022 CODEC_LOGV("There is no more output data available, not "
Andreas Huber404cc412009-08-25 14:26:05 -07003023 "calling fillOutputBuffer");
3024 return;
3025 }
3026
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003027 if (info->mMediaBuffer != NULL) {
3028 sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
3029 if (graphicBuffer != 0) {
3030 // When using a native buffer we need to lock the buffer before
3031 // giving it to OMX.
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003032 CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
3033 int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
3034 graphicBuffer.get());
3035 if (err != 0) {
3036 CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003037
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003038 setState(ERROR);
3039 return;
3040 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003041 }
3042 }
3043
3044 CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
Andreas Huber784202e2009-10-15 13:46:54 -07003045 status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
Andreas Huber8f14c552010-04-12 10:20:12 -07003046
3047 if (err != OK) {
3048 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
3049
3050 setState(ERROR);
3051 return;
3052 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003053
Andreas Huberbbbcf652010-12-07 14:25:54 -08003054 info->mStatus = OWNED_BY_COMPONENT;
Andreas Huberbe06d262009-08-14 14:37:10 -07003055}
3056
Andreas Huberbbbcf652010-12-07 14:25:54 -08003057bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
Andreas Huberbe06d262009-08-14 14:37:10 -07003058 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
3059 for (size_t i = 0; i < buffers->size(); ++i) {
3060 if ((*buffers)[i].mBuffer == buffer) {
Andreas Huberbbbcf652010-12-07 14:25:54 -08003061 return drainInputBuffer(&buffers->editItemAt(i));
Andreas Huberbe06d262009-08-14 14:37:10 -07003062 }
3063 }
3064
3065 CHECK(!"should not be here.");
Andreas Huberbbbcf652010-12-07 14:25:54 -08003066
3067 return false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003068}
3069
3070void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
3071 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3072 for (size_t i = 0; i < buffers->size(); ++i) {
3073 if ((*buffers)[i].mBuffer == buffer) {
3074 fillOutputBuffer(&buffers->editItemAt(i));
3075 return;
3076 }
3077 }
3078
3079 CHECK(!"should not be here.");
3080}
3081
3082void OMXCodec::setState(State newState) {
3083 mState = newState;
3084 mAsyncCompletion.signal();
3085
3086 // This may cause some spurious wakeups but is necessary to
3087 // unblock the reader if we enter ERROR state.
3088 mBufferFilled.signal();
3089}
3090
Andreas Huberda050cf22009-09-02 14:01:43 -07003091void OMXCodec::setRawAudioFormat(
3092 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
James Dongabed93a2010-04-22 17:27:04 -07003093
3094 // port definition
3095 OMX_PARAM_PORTDEFINITIONTYPE def;
3096 InitOMXParams(&def);
3097 def.nPortIndex = portIndex;
3098 status_t err = mOMX->getParameter(
3099 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003100 CHECK_EQ(err, (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003101 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
3102 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003103 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003104
3105 // pcm param
Andreas Huberda050cf22009-09-02 14:01:43 -07003106 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
Andreas Huber4c483422009-09-02 16:05:36 -07003107 InitOMXParams(&pcmParams);
Andreas Huberda050cf22009-09-02 14:01:43 -07003108 pcmParams.nPortIndex = portIndex;
3109
James Dongabed93a2010-04-22 17:27:04 -07003110 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003111 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3112
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003113 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003114
3115 pcmParams.nChannels = numChannels;
3116 pcmParams.eNumData = OMX_NumericalDataSigned;
3117 pcmParams.bInterleaved = OMX_TRUE;
3118 pcmParams.nBitPerSample = 16;
3119 pcmParams.nSamplingRate = sampleRate;
3120 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3121
3122 if (numChannels == 1) {
3123 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
3124 } else {
3125 CHECK_EQ(numChannels, 2);
3126
3127 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
3128 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
3129 }
3130
Andreas Huber784202e2009-10-15 13:46:54 -07003131 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003132 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3133
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003134 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003135}
3136
James Dong17299ab2010-05-14 15:45:22 -07003137static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
3138 if (isAMRWB) {
3139 if (bps <= 6600) {
3140 return OMX_AUDIO_AMRBandModeWB0;
3141 } else if (bps <= 8850) {
3142 return OMX_AUDIO_AMRBandModeWB1;
3143 } else if (bps <= 12650) {
3144 return OMX_AUDIO_AMRBandModeWB2;
3145 } else if (bps <= 14250) {
3146 return OMX_AUDIO_AMRBandModeWB3;
3147 } else if (bps <= 15850) {
3148 return OMX_AUDIO_AMRBandModeWB4;
3149 } else if (bps <= 18250) {
3150 return OMX_AUDIO_AMRBandModeWB5;
3151 } else if (bps <= 19850) {
3152 return OMX_AUDIO_AMRBandModeWB6;
3153 } else if (bps <= 23050) {
3154 return OMX_AUDIO_AMRBandModeWB7;
3155 }
3156
3157 // 23850 bps
3158 return OMX_AUDIO_AMRBandModeWB8;
3159 } else { // AMRNB
3160 if (bps <= 4750) {
3161 return OMX_AUDIO_AMRBandModeNB0;
3162 } else if (bps <= 5150) {
3163 return OMX_AUDIO_AMRBandModeNB1;
3164 } else if (bps <= 5900) {
3165 return OMX_AUDIO_AMRBandModeNB2;
3166 } else if (bps <= 6700) {
3167 return OMX_AUDIO_AMRBandModeNB3;
3168 } else if (bps <= 7400) {
3169 return OMX_AUDIO_AMRBandModeNB4;
3170 } else if (bps <= 7950) {
3171 return OMX_AUDIO_AMRBandModeNB5;
3172 } else if (bps <= 10200) {
3173 return OMX_AUDIO_AMRBandModeNB6;
3174 }
3175
3176 // 12200 bps
3177 return OMX_AUDIO_AMRBandModeNB7;
3178 }
3179}
3180
3181void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
Andreas Huber8768f2c2009-12-01 15:26:54 -08003182 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003183
Andreas Huber8768f2c2009-12-01 15:26:54 -08003184 OMX_AUDIO_PARAM_AMRTYPE def;
3185 InitOMXParams(&def);
3186 def.nPortIndex = portIndex;
Andreas Huberbe06d262009-08-14 14:37:10 -07003187
Andreas Huber8768f2c2009-12-01 15:26:54 -08003188 status_t err =
3189 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huberbe06d262009-08-14 14:37:10 -07003190
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003191 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003192
Andreas Huber8768f2c2009-12-01 15:26:54 -08003193 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
James Dongabed93a2010-04-22 17:27:04 -07003194
James Dong17299ab2010-05-14 15:45:22 -07003195 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
Andreas Huber8768f2c2009-12-01 15:26:54 -08003196 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003197 CHECK_EQ(err, (status_t)OK);
Andreas Huberee606e62009-09-08 10:19:21 -07003198
3199 ////////////////////////
3200
3201 if (mIsEncoder) {
3202 sp<MetaData> format = mSource->getFormat();
3203 int32_t sampleRate;
3204 int32_t numChannels;
3205 CHECK(format->findInt32(kKeySampleRate, &sampleRate));
3206 CHECK(format->findInt32(kKeyChannelCount, &numChannels));
3207
3208 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
3209 }
3210}
3211
James Dong17299ab2010-05-14 15:45:22 -07003212void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
James Dongabed93a2010-04-22 17:27:04 -07003213 CHECK(numChannels == 1 || numChannels == 2);
Andreas Huberda050cf22009-09-02 14:01:43 -07003214 if (mIsEncoder) {
James Dongabed93a2010-04-22 17:27:04 -07003215 //////////////// input port ////////////////////
Andreas Huberda050cf22009-09-02 14:01:43 -07003216 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
James Dongabed93a2010-04-22 17:27:04 -07003217
3218 //////////////// output port ////////////////////
3219 // format
3220 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
3221 format.nPortIndex = kPortIndexOutput;
3222 format.nIndex = 0;
3223 status_t err = OMX_ErrorNone;
3224 while (OMX_ErrorNone == err) {
3225 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003226 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003227 if (format.eEncoding == OMX_AUDIO_CodingAAC) {
3228 break;
3229 }
3230 format.nIndex++;
3231 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003232 CHECK_EQ((status_t)OK, err);
James Dongabed93a2010-04-22 17:27:04 -07003233 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003234 &format, sizeof(format)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003235
3236 // port definition
3237 OMX_PARAM_PORTDEFINITIONTYPE def;
3238 InitOMXParams(&def);
3239 def.nPortIndex = kPortIndexOutput;
3240 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003241 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003242 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
3243 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
3244 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003245 &def, sizeof(def)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003246
3247 // profile
3248 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
3249 InitOMXParams(&profile);
3250 profile.nPortIndex = kPortIndexOutput;
3251 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003252 &profile, sizeof(profile)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003253 profile.nChannels = numChannels;
3254 profile.eChannelMode = (numChannels == 1?
3255 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
3256 profile.nSampleRate = sampleRate;
James Dong17299ab2010-05-14 15:45:22 -07003257 profile.nBitRate = bitRate;
James Dongabed93a2010-04-22 17:27:04 -07003258 profile.nAudioBandWidth = 0;
3259 profile.nFrameLength = 0;
3260 profile.nAACtools = OMX_AUDIO_AACToolAll;
3261 profile.nAACERtools = OMX_AUDIO_AACERNone;
3262 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
3263 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
3264 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003265 &profile, sizeof(profile)), (status_t)OK);
James Dongabed93a2010-04-22 17:27:04 -07003266
Andreas Huberda050cf22009-09-02 14:01:43 -07003267 } else {
3268 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
Andreas Huber4c483422009-09-02 16:05:36 -07003269 InitOMXParams(&profile);
Andreas Huberda050cf22009-09-02 14:01:43 -07003270 profile.nPortIndex = kPortIndexInput;
Andreas Huberbe06d262009-08-14 14:37:10 -07003271
Andreas Huber784202e2009-10-15 13:46:54 -07003272 status_t err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003273 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003274 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003275
Andreas Huberda050cf22009-09-02 14:01:43 -07003276 profile.nChannels = numChannels;
3277 profile.nSampleRate = sampleRate;
3278 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
Andreas Huberbe06d262009-08-14 14:37:10 -07003279
Andreas Huber784202e2009-10-15 13:46:54 -07003280 err = mOMX->setParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07003281 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003282 CHECK_EQ(err, (status_t)OK);
Andreas Huberda050cf22009-09-02 14:01:43 -07003283 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003284}
3285
Andreas Huber4b3913a2011-05-11 14:13:42 -07003286void OMXCodec::setG711Format(int32_t numChannels) {
3287 CHECK(!mIsEncoder);
3288 setRawAudioFormat(kPortIndexInput, 8000, numChannels);
3289}
3290
Andreas Huberbe06d262009-08-14 14:37:10 -07003291void OMXCodec::setImageOutputFormat(
3292 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
Andreas Huber4c483422009-09-02 16:05:36 -07003293 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
Andreas Huberbe06d262009-08-14 14:37:10 -07003294
3295#if 0
3296 OMX_INDEXTYPE index;
3297 status_t err = mOMX->get_extension_index(
3298 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003299 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003300
3301 err = mOMX->set_config(mNode, index, &format, sizeof(format));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003302 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003303#endif
3304
3305 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003306 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003307 def.nPortIndex = kPortIndexOutput;
3308
Andreas Huber784202e2009-10-15 13:46:54 -07003309 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003310 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003311 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003312
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003313 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huberbe06d262009-08-14 14:37:10 -07003314
3315 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huberebf66ea2009-08-19 13:32:58 -07003316
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003317 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07003318 imageDef->eColorFormat = format;
3319 imageDef->nFrameWidth = width;
3320 imageDef->nFrameHeight = height;
3321
3322 switch (format) {
3323 case OMX_COLOR_FormatYUV420PackedPlanar:
3324 case OMX_COLOR_FormatYUV411Planar:
3325 {
3326 def.nBufferSize = (width * height * 3) / 2;
3327 break;
3328 }
3329
3330 case OMX_COLOR_FormatCbYCrY:
3331 {
3332 def.nBufferSize = width * height * 2;
3333 break;
3334 }
3335
3336 case OMX_COLOR_Format32bitARGB8888:
3337 {
3338 def.nBufferSize = width * height * 4;
3339 break;
3340 }
3341
Andreas Huber201511c2009-09-08 14:01:44 -07003342 case OMX_COLOR_Format16bitARGB4444:
3343 case OMX_COLOR_Format16bitARGB1555:
3344 case OMX_COLOR_Format16bitRGB565:
3345 case OMX_COLOR_Format16bitBGR565:
3346 {
3347 def.nBufferSize = width * height * 2;
3348 break;
3349 }
3350
Andreas Huberbe06d262009-08-14 14:37:10 -07003351 default:
3352 CHECK(!"Should not be here. Unknown color format.");
3353 break;
3354 }
3355
Andreas Huber5c0a9132009-08-20 11:16:40 -07003356 def.nBufferCountActual = def.nBufferCountMin;
3357
Andreas Huber784202e2009-10-15 13:46:54 -07003358 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003359 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003360 CHECK_EQ(err, (status_t)OK);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003361}
Andreas Huberbe06d262009-08-14 14:37:10 -07003362
Andreas Huber5c0a9132009-08-20 11:16:40 -07003363void OMXCodec::setJPEGInputFormat(
3364 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
3365 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003366 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003367 def.nPortIndex = kPortIndexInput;
3368
Andreas Huber784202e2009-10-15 13:46:54 -07003369 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003370 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003371 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003372
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003373 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
Andreas Huber5c0a9132009-08-20 11:16:40 -07003374 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3375
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003376 CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingJPEG);
Andreas Huberbe06d262009-08-14 14:37:10 -07003377 imageDef->nFrameWidth = width;
3378 imageDef->nFrameHeight = height;
3379
Andreas Huber5c0a9132009-08-20 11:16:40 -07003380 def.nBufferSize = compressedSize;
Andreas Huberbe06d262009-08-14 14:37:10 -07003381 def.nBufferCountActual = def.nBufferCountMin;
3382
Andreas Huber784202e2009-10-15 13:46:54 -07003383 err = mOMX->setParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003384 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003385 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003386}
3387
3388void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
3389 CodecSpecificData *specific =
3390 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
3391
3392 specific->mSize = size;
3393 memcpy(specific->mData, data, size);
3394
3395 mCodecSpecificData.push(specific);
3396}
3397
3398void OMXCodec::clearCodecSpecificData() {
3399 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
3400 free(mCodecSpecificData.editItemAt(i));
3401 }
3402 mCodecSpecificData.clear();
3403 mCodecSpecificDataIndex = 0;
3404}
3405
James Dong36e573b2010-06-19 09:04:18 -07003406status_t OMXCodec::start(MetaData *meta) {
Andreas Huber42978e52009-08-27 10:08:39 -07003407 Mutex::Autolock autoLock(mLock);
3408
Andreas Huberbe06d262009-08-14 14:37:10 -07003409 if (mState != LOADED) {
3410 return UNKNOWN_ERROR;
3411 }
Andreas Huberebf66ea2009-08-19 13:32:58 -07003412
Andreas Huberbe06d262009-08-14 14:37:10 -07003413 sp<MetaData> params = new MetaData;
Andreas Huber4f5e6022009-08-19 09:29:34 -07003414 if (mQuirks & kWantsNALFragments) {
3415 params->setInt32(kKeyWantsNALFragments, true);
Andreas Huberbe06d262009-08-14 14:37:10 -07003416 }
James Dong36e573b2010-06-19 09:04:18 -07003417 if (meta) {
3418 int64_t startTimeUs = 0;
3419 int64_t timeUs;
3420 if (meta->findInt64(kKeyTime, &timeUs)) {
3421 startTimeUs = timeUs;
3422 }
3423 params->setInt64(kKeyTime, startTimeUs);
3424 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003425 status_t err = mSource->start(params.get());
3426
3427 if (err != OK) {
3428 return err;
3429 }
3430
3431 mCodecSpecificDataIndex = 0;
Andreas Huber42978e52009-08-27 10:08:39 -07003432 mInitialBufferSubmit = true;
Andreas Huberbe06d262009-08-14 14:37:10 -07003433 mSignalledEOS = false;
3434 mNoMoreOutputData = false;
Andreas Hubercfd55572009-10-09 14:11:28 -07003435 mOutputPortSettingsHaveChanged = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003436 mSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003437 mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
3438 mTargetTimeUs = -1;
Andreas Huberbe06d262009-08-14 14:37:10 -07003439 mFilledBuffers.clear();
Andreas Huber1f24b302010-06-10 11:12:39 -07003440 mPaused = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003441
3442 return init();
3443}
3444
3445status_t OMXCodec::stop() {
Andreas Huber7ff89392011-02-15 15:34:11 -08003446 CODEC_LOGV("stop mState=%d", mState);
Andreas Huberbe06d262009-08-14 14:37:10 -07003447
3448 Mutex::Autolock autoLock(mLock);
3449
3450 while (isIntermediateState(mState)) {
3451 mAsyncCompletion.wait(mLock);
3452 }
3453
3454 switch (mState) {
3455 case LOADED:
3456 case ERROR:
3457 break;
3458
3459 case EXECUTING:
3460 {
3461 setState(EXECUTING_TO_IDLE);
3462
Andreas Huber127fcdc2009-08-26 16:27:02 -07003463 if (mQuirks & kRequiresFlushBeforeShutdown) {
Andreas Huber4c483422009-09-02 16:05:36 -07003464 CODEC_LOGV("This component requires a flush before transitioning "
Andreas Huber127fcdc2009-08-26 16:27:02 -07003465 "from EXECUTING to IDLE...");
Andreas Huberbe06d262009-08-14 14:37:10 -07003466
Andreas Huber127fcdc2009-08-26 16:27:02 -07003467 bool emulateInputFlushCompletion =
3468 !flushPortAsync(kPortIndexInput);
3469
3470 bool emulateOutputFlushCompletion =
3471 !flushPortAsync(kPortIndexOutput);
3472
3473 if (emulateInputFlushCompletion) {
3474 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3475 }
3476
3477 if (emulateOutputFlushCompletion) {
3478 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3479 }
3480 } else {
3481 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
3482 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
3483
3484 status_t err =
Andreas Huber784202e2009-10-15 13:46:54 -07003485 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003486 CHECK_EQ(err, (status_t)OK);
Andreas Huber127fcdc2009-08-26 16:27:02 -07003487 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003488
3489 while (mState != LOADED && mState != ERROR) {
3490 mAsyncCompletion.wait(mLock);
3491 }
3492
3493 break;
3494 }
3495
3496 default:
3497 {
3498 CHECK(!"should not be here.");
3499 break;
3500 }
3501 }
3502
Andreas Hubera4357ad2010-04-02 12:49:54 -07003503 if (mLeftOverBuffer) {
3504 mLeftOverBuffer->release();
3505 mLeftOverBuffer = NULL;
3506 }
3507
Andreas Huberbe06d262009-08-14 14:37:10 -07003508 mSource->stop();
3509
Andreas Huber06be3b12011-01-25 14:55:00 -08003510 CODEC_LOGI("stopped in state %d", mState);
Andreas Huber4a9375e2010-02-09 11:54:33 -08003511
Andreas Huberbe06d262009-08-14 14:37:10 -07003512 return OK;
3513}
3514
3515sp<MetaData> OMXCodec::getFormat() {
Andreas Hubercfd55572009-10-09 14:11:28 -07003516 Mutex::Autolock autoLock(mLock);
3517
Andreas Huberbe06d262009-08-14 14:37:10 -07003518 return mOutputFormat;
3519}
3520
3521status_t OMXCodec::read(
3522 MediaBuffer **buffer, const ReadOptions *options) {
3523 *buffer = NULL;
3524
3525 Mutex::Autolock autoLock(mLock);
3526
Andreas Huberd06e5b82009-08-28 13:18:14 -07003527 if (mState != EXECUTING && mState != RECONFIGURING) {
3528 return UNKNOWN_ERROR;
3529 }
3530
Andreas Hubere981c332009-10-22 13:49:30 -07003531 bool seeking = false;
3532 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003533 ReadOptions::SeekMode seekMode;
3534 if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
Andreas Hubere981c332009-10-22 13:49:30 -07003535 seeking = true;
3536 }
3537
Andreas Huber42978e52009-08-27 10:08:39 -07003538 if (mInitialBufferSubmit) {
3539 mInitialBufferSubmit = false;
3540
Andreas Hubere981c332009-10-22 13:49:30 -07003541 if (seeking) {
3542 CHECK(seekTimeUs >= 0);
3543 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003544 mSeekMode = seekMode;
Andreas Hubere981c332009-10-22 13:49:30 -07003545
3546 // There's no reason to trigger the code below, there's
3547 // nothing to flush yet.
3548 seeking = false;
Andreas Huber1f24b302010-06-10 11:12:39 -07003549 mPaused = false;
Andreas Hubere981c332009-10-22 13:49:30 -07003550 }
3551
Andreas Huber42978e52009-08-27 10:08:39 -07003552 drainInputBuffers();
Andreas Huber42978e52009-08-27 10:08:39 -07003553
Andreas Huberd06e5b82009-08-28 13:18:14 -07003554 if (mState == EXECUTING) {
3555 // Otherwise mState == RECONFIGURING and this code will trigger
3556 // after the output port is reenabled.
3557 fillOutputBuffers();
3558 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003559 }
3560
Andreas Hubere981c332009-10-22 13:49:30 -07003561 if (seeking) {
Andreas Huberb9289832011-02-08 13:10:25 -08003562 while (mState == RECONFIGURING) {
3563 mBufferFilled.wait(mLock);
3564 }
3565
3566 if (mState != EXECUTING) {
3567 return UNKNOWN_ERROR;
3568 }
3569
Andreas Huber4c483422009-09-02 16:05:36 -07003570 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
Andreas Huberbe06d262009-08-14 14:37:10 -07003571
3572 mSignalledEOS = false;
Andreas Huberbe06d262009-08-14 14:37:10 -07003573
3574 CHECK(seekTimeUs >= 0);
3575 mSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -07003576 mSeekMode = seekMode;
Andreas Huberbe06d262009-08-14 14:37:10 -07003577
3578 mFilledBuffers.clear();
3579
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003580 CHECK_EQ((int)mState, (int)EXECUTING);
Andreas Huberbe06d262009-08-14 14:37:10 -07003581
Andreas Huber404cc412009-08-25 14:26:05 -07003582 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
3583 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
3584
3585 if (emulateInputFlushCompletion) {
3586 onCmdComplete(OMX_CommandFlush, kPortIndexInput);
3587 }
3588
3589 if (emulateOutputFlushCompletion) {
3590 onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
3591 }
Andreas Huber2ea14e22009-12-16 09:30:55 -08003592
3593 while (mSeekTimeUs >= 0) {
3594 mBufferFilled.wait(mLock);
3595 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003596 }
3597
3598 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
James Dong74556302010-12-20 21:29:12 -08003599 if (mIsEncoder) {
3600 if (NO_ERROR != mBufferFilled.waitRelative(mLock, 3000000000LL)) {
3601 LOGW("Timed out waiting for buffers from video encoder: %d/%d",
3602 countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
3603 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
3604 }
3605 } else {
3606 mBufferFilled.wait(mLock);
3607 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003608 }
3609
3610 if (mState == ERROR) {
3611 return UNKNOWN_ERROR;
3612 }
3613
3614 if (mFilledBuffers.empty()) {
Andreas Huberd7d22eb2010-02-23 13:45:33 -08003615 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
Andreas Huberbe06d262009-08-14 14:37:10 -07003616 }
3617
Andreas Hubercfd55572009-10-09 14:11:28 -07003618 if (mOutputPortSettingsHaveChanged) {
3619 mOutputPortSettingsHaveChanged = false;
3620
3621 return INFO_FORMAT_CHANGED;
3622 }
3623
Andreas Huberbe06d262009-08-14 14:37:10 -07003624 size_t index = *mFilledBuffers.begin();
3625 mFilledBuffers.erase(mFilledBuffers.begin());
3626
3627 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003628 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
3629 info->mStatus = OWNED_BY_CLIENT;
3630
Andreas Huberbe06d262009-08-14 14:37:10 -07003631 info->mMediaBuffer->add_ref();
3632 *buffer = info->mMediaBuffer;
3633
3634 return OK;
3635}
3636
3637void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
3638 Mutex::Autolock autoLock(mLock);
3639
3640 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
3641 for (size_t i = 0; i < buffers->size(); ++i) {
3642 BufferInfo *info = &buffers->editItemAt(i);
3643
3644 if (info->mMediaBuffer == buffer) {
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003645 CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
Andreas Huberbbbcf652010-12-07 14:25:54 -08003646 CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
3647
3648 info->mStatus = OWNED_BY_US;
3649
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003650 if (buffer->graphicBuffer() == 0) {
3651 fillOutputBuffer(info);
3652 } else {
3653 sp<MetaData> metaData = info->mMediaBuffer->meta_data();
3654 int32_t rendered = 0;
3655 if (!metaData->findInt32(kKeyRendered, &rendered)) {
3656 rendered = 0;
3657 }
3658 if (!rendered) {
3659 status_t err = cancelBufferToNativeWindow(info);
3660 if (err < 0) {
3661 return;
3662 }
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003663 }
3664
Andreas Huberbbbcf652010-12-07 14:25:54 -08003665 info->mStatus = OWNED_BY_NATIVE_WINDOW;
3666
Jamie Gennis58a36ad2010-10-07 14:08:38 -07003667 // Dequeue the next buffer from the native window.
3668 BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
3669 if (nextBufInfo == 0) {
3670 return;
3671 }
3672
3673 // Give the buffer to the OMX node to fill.
3674 fillOutputBuffer(nextBufInfo);
3675 }
Andreas Huberbe06d262009-08-14 14:37:10 -07003676 return;
3677 }
3678 }
3679
3680 CHECK(!"should not be here.");
3681}
3682
3683static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
3684 static const char *kNames[] = {
3685 "OMX_IMAGE_CodingUnused",
3686 "OMX_IMAGE_CodingAutoDetect",
3687 "OMX_IMAGE_CodingJPEG",
3688 "OMX_IMAGE_CodingJPEG2K",
3689 "OMX_IMAGE_CodingEXIF",
3690 "OMX_IMAGE_CodingTIFF",
3691 "OMX_IMAGE_CodingGIF",
3692 "OMX_IMAGE_CodingPNG",
3693 "OMX_IMAGE_CodingLZW",
3694 "OMX_IMAGE_CodingBMP",
3695 };
3696
3697 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3698
3699 if (type < 0 || (size_t)type >= numNames) {
3700 return "UNKNOWN";
3701 } else {
3702 return kNames[type];
3703 }
3704}
3705
3706static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
3707 static const char *kNames[] = {
3708 "OMX_COLOR_FormatUnused",
3709 "OMX_COLOR_FormatMonochrome",
3710 "OMX_COLOR_Format8bitRGB332",
3711 "OMX_COLOR_Format12bitRGB444",
3712 "OMX_COLOR_Format16bitARGB4444",
3713 "OMX_COLOR_Format16bitARGB1555",
3714 "OMX_COLOR_Format16bitRGB565",
3715 "OMX_COLOR_Format16bitBGR565",
3716 "OMX_COLOR_Format18bitRGB666",
3717 "OMX_COLOR_Format18bitARGB1665",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003718 "OMX_COLOR_Format19bitARGB1666",
Andreas Huberbe06d262009-08-14 14:37:10 -07003719 "OMX_COLOR_Format24bitRGB888",
3720 "OMX_COLOR_Format24bitBGR888",
3721 "OMX_COLOR_Format24bitARGB1887",
3722 "OMX_COLOR_Format25bitARGB1888",
3723 "OMX_COLOR_Format32bitBGRA8888",
3724 "OMX_COLOR_Format32bitARGB8888",
3725 "OMX_COLOR_FormatYUV411Planar",
3726 "OMX_COLOR_FormatYUV411PackedPlanar",
3727 "OMX_COLOR_FormatYUV420Planar",
3728 "OMX_COLOR_FormatYUV420PackedPlanar",
3729 "OMX_COLOR_FormatYUV420SemiPlanar",
3730 "OMX_COLOR_FormatYUV422Planar",
3731 "OMX_COLOR_FormatYUV422PackedPlanar",
3732 "OMX_COLOR_FormatYUV422SemiPlanar",
3733 "OMX_COLOR_FormatYCbYCr",
3734 "OMX_COLOR_FormatYCrYCb",
3735 "OMX_COLOR_FormatCbYCrY",
3736 "OMX_COLOR_FormatCrYCbY",
3737 "OMX_COLOR_FormatYUV444Interleaved",
3738 "OMX_COLOR_FormatRawBayer8bit",
3739 "OMX_COLOR_FormatRawBayer10bit",
3740 "OMX_COLOR_FormatRawBayer8bitcompressed",
Andreas Huberebf66ea2009-08-19 13:32:58 -07003741 "OMX_COLOR_FormatL2",
3742 "OMX_COLOR_FormatL4",
3743 "OMX_COLOR_FormatL8",
3744 "OMX_COLOR_FormatL16",
3745 "OMX_COLOR_FormatL24",
Andreas Huberbe06d262009-08-14 14:37:10 -07003746 "OMX_COLOR_FormatL32",
3747 "OMX_COLOR_FormatYUV420PackedSemiPlanar",
3748 "OMX_COLOR_FormatYUV422PackedSemiPlanar",
3749 "OMX_COLOR_Format18BitBGR666",
3750 "OMX_COLOR_Format24BitARGB6666",
3751 "OMX_COLOR_Format24BitABGR6666",
3752 };
3753
3754 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3755
Andreas Huberbe06d262009-08-14 14:37:10 -07003756 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
3757 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
3758 } else if (type < 0 || (size_t)type >= numNames) {
3759 return "UNKNOWN";
3760 } else {
3761 return kNames[type];
3762 }
3763}
3764
3765static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
3766 static const char *kNames[] = {
3767 "OMX_VIDEO_CodingUnused",
3768 "OMX_VIDEO_CodingAutoDetect",
3769 "OMX_VIDEO_CodingMPEG2",
3770 "OMX_VIDEO_CodingH263",
3771 "OMX_VIDEO_CodingMPEG4",
3772 "OMX_VIDEO_CodingWMV",
3773 "OMX_VIDEO_CodingRV",
3774 "OMX_VIDEO_CodingAVC",
3775 "OMX_VIDEO_CodingMJPEG",
3776 };
3777
3778 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3779
3780 if (type < 0 || (size_t)type >= numNames) {
3781 return "UNKNOWN";
3782 } else {
3783 return kNames[type];
3784 }
3785}
3786
3787static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
3788 static const char *kNames[] = {
3789 "OMX_AUDIO_CodingUnused",
3790 "OMX_AUDIO_CodingAutoDetect",
3791 "OMX_AUDIO_CodingPCM",
3792 "OMX_AUDIO_CodingADPCM",
3793 "OMX_AUDIO_CodingAMR",
3794 "OMX_AUDIO_CodingGSMFR",
3795 "OMX_AUDIO_CodingGSMEFR",
3796 "OMX_AUDIO_CodingGSMHR",
3797 "OMX_AUDIO_CodingPDCFR",
3798 "OMX_AUDIO_CodingPDCEFR",
3799 "OMX_AUDIO_CodingPDCHR",
3800 "OMX_AUDIO_CodingTDMAFR",
3801 "OMX_AUDIO_CodingTDMAEFR",
3802 "OMX_AUDIO_CodingQCELP8",
3803 "OMX_AUDIO_CodingQCELP13",
3804 "OMX_AUDIO_CodingEVRC",
3805 "OMX_AUDIO_CodingSMV",
3806 "OMX_AUDIO_CodingG711",
3807 "OMX_AUDIO_CodingG723",
3808 "OMX_AUDIO_CodingG726",
3809 "OMX_AUDIO_CodingG729",
3810 "OMX_AUDIO_CodingAAC",
3811 "OMX_AUDIO_CodingMP3",
3812 "OMX_AUDIO_CodingSBC",
3813 "OMX_AUDIO_CodingVORBIS",
3814 "OMX_AUDIO_CodingWMA",
3815 "OMX_AUDIO_CodingRA",
3816 "OMX_AUDIO_CodingMIDI",
3817 };
3818
3819 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3820
3821 if (type < 0 || (size_t)type >= numNames) {
3822 return "UNKNOWN";
3823 } else {
3824 return kNames[type];
3825 }
3826}
3827
3828static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
3829 static const char *kNames[] = {
3830 "OMX_AUDIO_PCMModeLinear",
3831 "OMX_AUDIO_PCMModeALaw",
3832 "OMX_AUDIO_PCMModeMULaw",
3833 };
3834
3835 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3836
3837 if (type < 0 || (size_t)type >= numNames) {
3838 return "UNKNOWN";
3839 } else {
3840 return kNames[type];
3841 }
3842}
3843
Andreas Huber7ae02c82009-09-09 16:29:47 -07003844static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
3845 static const char *kNames[] = {
3846 "OMX_AUDIO_AMRBandModeUnused",
3847 "OMX_AUDIO_AMRBandModeNB0",
3848 "OMX_AUDIO_AMRBandModeNB1",
3849 "OMX_AUDIO_AMRBandModeNB2",
3850 "OMX_AUDIO_AMRBandModeNB3",
3851 "OMX_AUDIO_AMRBandModeNB4",
3852 "OMX_AUDIO_AMRBandModeNB5",
3853 "OMX_AUDIO_AMRBandModeNB6",
3854 "OMX_AUDIO_AMRBandModeNB7",
3855 "OMX_AUDIO_AMRBandModeWB0",
3856 "OMX_AUDIO_AMRBandModeWB1",
3857 "OMX_AUDIO_AMRBandModeWB2",
3858 "OMX_AUDIO_AMRBandModeWB3",
3859 "OMX_AUDIO_AMRBandModeWB4",
3860 "OMX_AUDIO_AMRBandModeWB5",
3861 "OMX_AUDIO_AMRBandModeWB6",
3862 "OMX_AUDIO_AMRBandModeWB7",
3863 "OMX_AUDIO_AMRBandModeWB8",
3864 };
3865
3866 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3867
3868 if (type < 0 || (size_t)type >= numNames) {
3869 return "UNKNOWN";
3870 } else {
3871 return kNames[type];
3872 }
3873}
3874
3875static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
3876 static const char *kNames[] = {
3877 "OMX_AUDIO_AMRFrameFormatConformance",
3878 "OMX_AUDIO_AMRFrameFormatIF1",
3879 "OMX_AUDIO_AMRFrameFormatIF2",
3880 "OMX_AUDIO_AMRFrameFormatFSF",
3881 "OMX_AUDIO_AMRFrameFormatRTPPayload",
3882 "OMX_AUDIO_AMRFrameFormatITU",
3883 };
3884
3885 size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
3886
3887 if (type < 0 || (size_t)type >= numNames) {
3888 return "UNKNOWN";
3889 } else {
3890 return kNames[type];
3891 }
3892}
Andreas Huberbe06d262009-08-14 14:37:10 -07003893
3894void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
3895 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07003896 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07003897 def.nPortIndex = portIndex;
3898
Andreas Huber784202e2009-10-15 13:46:54 -07003899 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003900 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003901 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003902
3903 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
3904
3905 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
3906 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
3907
3908 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
3909 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
3910 printf(" nBufferSize = %ld\n", def.nBufferSize);
3911
3912 switch (def.eDomain) {
3913 case OMX_PortDomainImage:
3914 {
3915 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3916
3917 printf("\n");
3918 printf(" // Image\n");
3919 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
3920 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
3921 printf(" nStride = %ld\n", imageDef->nStride);
3922
3923 printf(" eCompressionFormat = %s\n",
3924 imageCompressionFormatString(imageDef->eCompressionFormat));
3925
3926 printf(" eColorFormat = %s\n",
3927 colorFormatString(imageDef->eColorFormat));
3928
3929 break;
3930 }
3931
3932 case OMX_PortDomainVideo:
3933 {
3934 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3935
3936 printf("\n");
3937 printf(" // Video\n");
3938 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
3939 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
3940 printf(" nStride = %ld\n", videoDef->nStride);
3941
3942 printf(" eCompressionFormat = %s\n",
3943 videoCompressionFormatString(videoDef->eCompressionFormat));
3944
3945 printf(" eColorFormat = %s\n",
3946 colorFormatString(videoDef->eColorFormat));
3947
3948 break;
3949 }
3950
3951 case OMX_PortDomainAudio:
3952 {
3953 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3954
3955 printf("\n");
3956 printf(" // Audio\n");
3957 printf(" eEncoding = %s\n",
3958 audioCodingTypeString(audioDef->eEncoding));
3959
3960 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
3961 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07003962 InitOMXParams(&params);
Andreas Huberbe06d262009-08-14 14:37:10 -07003963 params.nPortIndex = portIndex;
3964
Andreas Huber784202e2009-10-15 13:46:54 -07003965 err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07003966 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003967 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07003968
3969 printf(" nSamplingRate = %ld\n", params.nSamplingRate);
3970 printf(" nChannels = %ld\n", params.nChannels);
3971 printf(" bInterleaved = %d\n", params.bInterleaved);
3972 printf(" nBitPerSample = %ld\n", params.nBitPerSample);
3973
3974 printf(" eNumData = %s\n",
3975 params.eNumData == OMX_NumericalDataSigned
3976 ? "signed" : "unsigned");
3977
3978 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
Andreas Huber7ae02c82009-09-09 16:29:47 -07003979 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
3980 OMX_AUDIO_PARAM_AMRTYPE amr;
3981 InitOMXParams(&amr);
3982 amr.nPortIndex = portIndex;
3983
Andreas Huber784202e2009-10-15 13:46:54 -07003984 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07003985 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08003986 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07003987
3988 printf(" nChannels = %ld\n", amr.nChannels);
3989 printf(" eAMRBandMode = %s\n",
3990 amrBandModeString(amr.eAMRBandMode));
3991 printf(" eAMRFrameFormat = %s\n",
3992 amrFrameFormatString(amr.eAMRFrameFormat));
Andreas Huberbe06d262009-08-14 14:37:10 -07003993 }
3994
3995 break;
3996 }
3997
3998 default:
3999 {
4000 printf(" // Unknown\n");
4001 break;
4002 }
4003 }
4004
4005 printf("}\n");
4006}
4007
Jamie Gennis58a36ad2010-10-07 14:08:38 -07004008status_t OMXCodec::initNativeWindow() {
4009 // Enable use of a GraphicBuffer as the output for this node. This must
4010 // happen before getting the IndexParamPortDefinition parameter because it
4011 // will affect the pixel format that the node reports.
4012 status_t err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
4013 if (err != 0) {
4014 return err;
4015 }
4016
4017 return OK;
4018}
4019
Andreas Huberbe06d262009-08-14 14:37:10 -07004020void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
4021 mOutputFormat = new MetaData;
4022 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
James Dong52d13f02010-07-02 11:39:06 -07004023 if (mIsEncoder) {
4024 int32_t timeScale;
4025 if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
4026 mOutputFormat->setInt32(kKeyTimeScale, timeScale);
4027 }
4028 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004029
4030 OMX_PARAM_PORTDEFINITIONTYPE def;
Andreas Huber4c483422009-09-02 16:05:36 -07004031 InitOMXParams(&def);
Andreas Huberbe06d262009-08-14 14:37:10 -07004032 def.nPortIndex = kPortIndexOutput;
4033
Andreas Huber784202e2009-10-15 13:46:54 -07004034 status_t err = mOMX->getParameter(
Andreas Huberbe06d262009-08-14 14:37:10 -07004035 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004036 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004037
4038 switch (def.eDomain) {
4039 case OMX_PortDomainImage:
4040 {
4041 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004042 CHECK_EQ((int)imageDef->eCompressionFormat,
4043 (int)OMX_IMAGE_CodingUnused);
Andreas Huberbe06d262009-08-14 14:37:10 -07004044
Andreas Hubere6c40962009-09-10 14:13:30 -07004045 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004046 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
4047 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
4048 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
4049 break;
4050 }
4051
4052 case OMX_PortDomainAudio:
4053 {
4054 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
4055
Andreas Huberda050cf22009-09-02 14:01:43 -07004056 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
4057 OMX_AUDIO_PARAM_PCMMODETYPE params;
Andreas Huber4c483422009-09-02 16:05:36 -07004058 InitOMXParams(&params);
Andreas Huberda050cf22009-09-02 14:01:43 -07004059 params.nPortIndex = kPortIndexOutput;
Andreas Huberbe06d262009-08-14 14:37:10 -07004060
Andreas Huber784202e2009-10-15 13:46:54 -07004061 err = mOMX->getParameter(
Andreas Huberda050cf22009-09-02 14:01:43 -07004062 mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004063 CHECK_EQ(err, (status_t)OK);
Andreas Huberbe06d262009-08-14 14:37:10 -07004064
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004065 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
4066 CHECK_EQ(params.nBitPerSample, 16u);
4067 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
Andreas Huberbe06d262009-08-14 14:37:10 -07004068
Andreas Huberda050cf22009-09-02 14:01:43 -07004069 int32_t numChannels, sampleRate;
4070 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4071 inputFormat->findInt32(kKeySampleRate, &sampleRate);
Andreas Huberbe06d262009-08-14 14:37:10 -07004072
Andreas Huberda050cf22009-09-02 14:01:43 -07004073 if ((OMX_U32)numChannels != params.nChannels) {
4074 LOGW("Codec outputs a different number of channels than "
Andreas Hubere331c7b2010-02-01 10:51:50 -08004075 "the input stream contains (contains %d channels, "
4076 "codec outputs %ld channels).",
4077 numChannels, params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004078 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004079
Andreas Huber4b3913a2011-05-11 14:13:42 -07004080 if (sampleRate != params.nSamplingRate) {
4081 LOGW("Codec outputs at different sampling rate than "
4082 "what the input stream contains (contains data at "
4083 "%d Hz, codec outputs %d Hz)",
4084 sampleRate, params.nSamplingRate);
4085 }
4086
Andreas Hubere6c40962009-09-10 14:13:30 -07004087 mOutputFormat->setCString(
4088 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
Andreas Huberda050cf22009-09-02 14:01:43 -07004089
4090 // Use the codec-advertised number of channels, as some
4091 // codecs appear to output stereo even if the input data is
Andreas Hubere331c7b2010-02-01 10:51:50 -08004092 // mono. If we know the codec lies about this information,
4093 // use the actual number of channels instead.
4094 mOutputFormat->setInt32(
4095 kKeyChannelCount,
4096 (mQuirks & kDecoderLiesAboutNumberOfChannels)
4097 ? numChannels : params.nChannels);
Andreas Huberda050cf22009-09-02 14:01:43 -07004098
Andreas Huber4b3913a2011-05-11 14:13:42 -07004099 mOutputFormat->setInt32(kKeySampleRate, params.nSamplingRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004100 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
Andreas Huber7ae02c82009-09-09 16:29:47 -07004101 OMX_AUDIO_PARAM_AMRTYPE amr;
4102 InitOMXParams(&amr);
4103 amr.nPortIndex = kPortIndexOutput;
4104
Andreas Huber784202e2009-10-15 13:46:54 -07004105 err = mOMX->getParameter(
Andreas Huber7ae02c82009-09-09 16:29:47 -07004106 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004107 CHECK_EQ(err, (status_t)OK);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004108
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004109 CHECK_EQ(amr.nChannels, 1u);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004110 mOutputFormat->setInt32(kKeyChannelCount, 1);
4111
4112 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
4113 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004114 mOutputFormat->setCString(
4115 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004116 mOutputFormat->setInt32(kKeySampleRate, 8000);
4117 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
4118 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004119 mOutputFormat->setCString(
4120 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
Andreas Huber7ae02c82009-09-09 16:29:47 -07004121 mOutputFormat->setInt32(kKeySampleRate, 16000);
4122 } else {
4123 CHECK(!"Unknown AMR band mode.");
4124 }
Andreas Huberda050cf22009-09-02 14:01:43 -07004125 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004126 mOutputFormat->setCString(
4127 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
James Dong17299ab2010-05-14 15:45:22 -07004128 int32_t numChannels, sampleRate, bitRate;
James Dongabed93a2010-04-22 17:27:04 -07004129 inputFormat->findInt32(kKeyChannelCount, &numChannels);
4130 inputFormat->findInt32(kKeySampleRate, &sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004131 inputFormat->findInt32(kKeyBitRate, &bitRate);
James Dongabed93a2010-04-22 17:27:04 -07004132 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
4133 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
James Dong17299ab2010-05-14 15:45:22 -07004134 mOutputFormat->setInt32(kKeyBitRate, bitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -07004135 } else {
4136 CHECK(!"Should not be here. Unknown audio encoding.");
Andreas Huber43ad6eaf2009-09-01 16:02:43 -07004137 }
Andreas Huberbe06d262009-08-14 14:37:10 -07004138 break;
4139 }
4140
4141 case OMX_PortDomainVideo:
4142 {
4143 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4144
4145 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004146 mOutputFormat->setCString(
4147 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -07004148 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004149 mOutputFormat->setCString(
4150 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
Andreas Huberbe06d262009-08-14 14:37:10 -07004151 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004152 mOutputFormat->setCString(
4153 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huberbe06d262009-08-14 14:37:10 -07004154 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
Andreas Hubere6c40962009-09-10 14:13:30 -07004155 mOutputFormat->setCString(
4156 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Huberbe06d262009-08-14 14:37:10 -07004157 } else {
4158 CHECK(!"Unknown compression format.");
4159 }
4160
James Dong5592bcc2010-10-22 17:10:43 -07004161 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
4162 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
Andreas Huberbe06d262009-08-14 14:37:10 -07004163 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004164
James Dong0c9153d2010-11-23 11:30:21 -08004165 if (!mIsEncoder) {
4166 OMX_CONFIG_RECTTYPE rect;
James Donga1735412011-01-07 14:56:34 -08004167 InitOMXParams(&rect);
4168 rect.nPortIndex = kPortIndexOutput;
James Dong0c9153d2010-11-23 11:30:21 -08004169 status_t err =
4170 mOMX->getConfig(
4171 mNode, OMX_IndexConfigCommonOutputCrop,
4172 &rect, sizeof(rect));
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004173
James Dong0c9153d2010-11-23 11:30:21 -08004174 if (err == OK) {
4175 CHECK_GE(rect.nLeft, 0);
4176 CHECK_GE(rect.nTop, 0);
4177 CHECK_GE(rect.nWidth, 0u);
4178 CHECK_GE(rect.nHeight, 0u);
4179 CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
4180 CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004181
James Dong0c9153d2010-11-23 11:30:21 -08004182 mOutputFormat->setRect(
4183 kKeyCropRect,
4184 rect.nLeft,
4185 rect.nTop,
4186 rect.nLeft + rect.nWidth - 1,
4187 rect.nTop + rect.nHeight - 1);
4188 } else {
4189 mOutputFormat->setRect(
4190 kKeyCropRect,
4191 0, 0,
4192 video_def->nFrameWidth - 1,
4193 video_def->nFrameHeight - 1);
4194 }
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004195 }
4196
Andreas Huberbe06d262009-08-14 14:37:10 -07004197 break;
4198 }
4199
4200 default:
4201 {
4202 CHECK(!"should not be here, neither audio nor video.");
4203 break;
4204 }
4205 }
4206}
4207
Andreas Huber1f24b302010-06-10 11:12:39 -07004208status_t OMXCodec::pause() {
4209 Mutex::Autolock autoLock(mLock);
4210
4211 mPaused = true;
4212
4213 return OK;
4214}
4215
Andreas Hubere6c40962009-09-10 14:13:30 -07004216////////////////////////////////////////////////////////////////////////////////
4217
4218status_t QueryCodecs(
4219 const sp<IOMX> &omx,
4220 const char *mime, bool queryDecoders,
4221 Vector<CodecCapabilities> *results) {
4222 results->clear();
4223
4224 for (int index = 0;; ++index) {
4225 const char *componentName;
4226
4227 if (!queryDecoders) {
4228 componentName = GetCodec(
4229 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
4230 mime, index);
4231 } else {
4232 componentName = GetCodec(
4233 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
4234 mime, index);
4235 }
4236
4237 if (!componentName) {
4238 return OK;
4239 }
4240
Andreas Huber1a189a82010-03-24 13:49:20 -07004241 if (strncmp(componentName, "OMX.", 4)) {
4242 // Not an OpenMax component but a software codec.
4243
4244 results->push();
4245 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4246 caps->mComponentName = componentName;
4247
4248 continue;
4249 }
4250
Andreas Huber784202e2009-10-15 13:46:54 -07004251 sp<OMXCodecObserver> observer = new OMXCodecObserver;
Andreas Hubere6c40962009-09-10 14:13:30 -07004252 IOMX::node_id node;
Andreas Huber784202e2009-10-15 13:46:54 -07004253 status_t err = omx->allocateNode(componentName, observer, &node);
Andreas Hubere6c40962009-09-10 14:13:30 -07004254
4255 if (err != OK) {
4256 continue;
4257 }
4258
James Dong722d5912010-04-13 10:56:59 -07004259 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
Andreas Hubere6c40962009-09-10 14:13:30 -07004260
4261 results->push();
4262 CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
4263 caps->mComponentName = componentName;
4264
4265 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
4266 InitOMXParams(&param);
4267
4268 param.nPortIndex = queryDecoders ? 0 : 1;
4269
4270 for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
Andreas Huber784202e2009-10-15 13:46:54 -07004271 err = omx->getParameter(
Andreas Hubere6c40962009-09-10 14:13:30 -07004272 node, OMX_IndexParamVideoProfileLevelQuerySupported,
4273 &param, sizeof(param));
4274
4275 if (err != OK) {
4276 break;
4277 }
4278
4279 CodecProfileLevel profileLevel;
4280 profileLevel.mProfile = param.eProfile;
4281 profileLevel.mLevel = param.eLevel;
4282
4283 caps->mProfileLevels.push(profileLevel);
4284 }
4285
James Dongd7810892010-11-11 00:33:05 -08004286 // Color format query
4287 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
4288 InitOMXParams(&portFormat);
4289 portFormat.nPortIndex = queryDecoders ? 1 : 0;
4290 for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
4291 err = omx->getParameter(
4292 node, OMX_IndexParamVideoPortFormat,
4293 &portFormat, sizeof(portFormat));
4294 if (err != OK) {
4295 break;
4296 }
4297 caps->mColorFormats.push(portFormat.eColorFormat);
4298 }
4299
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08004300 CHECK_EQ(omx->freeNode(node), (status_t)OK);
Andreas Hubere6c40962009-09-10 14:13:30 -07004301 }
4302}
4303
James Dong31b9375f2010-11-10 21:11:41 -08004304void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
4305 CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
4306 CHECK(mOMXLivesLocally);
4307
4308 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
4309 header->pBuffer = (OMX_U8 *)info->mData;
4310}
4311
Andreas Huberbe06d262009-08-14 14:37:10 -07004312} // namespace android