• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
21 #include <binder/IServiceManager.h>
22 #include <binder/MemoryDealer.h>
23 #include <binder/ProcessState.h>
24 #include <media/IMediaPlayerService.h>
25 #include <media/stagefright/ESDS.h>
26 #include <media/stagefright/MediaBuffer.h>
27 #include <media/stagefright/MediaBufferGroup.h>
28 #include <media/stagefright/MediaDebug.h>
29 #include <media/stagefright/MediaDefs.h>
30 #include <media/stagefright/MediaExtractor.h>
31 #include <media/stagefright/MetaData.h>
32 #include <media/stagefright/MmapSource.h>
33 #include <media/stagefright/OMXCodec.h>
34 #include <media/stagefright/Utils.h>
35 #include <utils/Vector.h>
36 
37 #include <OMX_Audio.h>
38 #include <OMX_Component.h>
39 
40 namespace android {
41 
42 struct CodecInfo {
43     const char *mime;
44     const char *codec;
45 };
46 
47 static const CodecInfo kDecoderInfo[] = {
48     { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
49     { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
50     { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
51     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
52     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
53     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
54     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" },
55     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
56     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
57     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
58     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
59     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
60     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
61     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.Decoder" },
62     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
63     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
64     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
65     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
66 };
67 
68 static const CodecInfo kEncoderInfo[] = {
69     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
70     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrencnb" },
71     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
72     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
73     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
74     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
75     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
76     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
77     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
78     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
79     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
80     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
81     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
82 };
83 
84 #define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
85 #define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
86 
87 struct OMXCodecObserver : public BnOMXObserver {
OMXCodecObserverandroid::OMXCodecObserver88     OMXCodecObserver() {
89     }
90 
setCodecandroid::OMXCodecObserver91     void setCodec(const sp<OMXCodec> &target) {
92         mTarget = target;
93     }
94 
95     // from IOMXObserver
onMessageandroid::OMXCodecObserver96     virtual void onMessage(const omx_message &msg) {
97         sp<OMXCodec> codec = mTarget.promote();
98 
99         if (codec.get() != NULL) {
100             codec->on_message(msg);
101         }
102     }
103 
104 protected:
~OMXCodecObserverandroid::OMXCodecObserver105     virtual ~OMXCodecObserver() {}
106 
107 private:
108     wp<OMXCodec> mTarget;
109 
110     OMXCodecObserver(const OMXCodecObserver &);
111     OMXCodecObserver &operator=(const OMXCodecObserver &);
112 };
113 
GetCodec(const CodecInfo * info,size_t numInfos,const char * mime,int index)114 static const char *GetCodec(const CodecInfo *info, size_t numInfos,
115                             const char *mime, int index) {
116     CHECK(index >= 0);
117     for(size_t i = 0; i < numInfos; ++i) {
118         if (!strcasecmp(mime, info[i].mime)) {
119             if (index == 0) {
120                 return info[i].codec;
121             }
122 
123             --index;
124         }
125     }
126 
127     return NULL;
128 }
129 
130 enum {
131     kAVCProfileBaseline      = 0x42,
132     kAVCProfileMain          = 0x4d,
133     kAVCProfileExtended      = 0x58,
134     kAVCProfileHigh          = 0x64,
135     kAVCProfileHigh10        = 0x6e,
136     kAVCProfileHigh422       = 0x7a,
137     kAVCProfileHigh444       = 0xf4,
138     kAVCProfileCAVLC444Intra = 0x2c
139 };
140 
AVCProfileToString(uint8_t profile)141 static const char *AVCProfileToString(uint8_t profile) {
142     switch (profile) {
143         case kAVCProfileBaseline:
144             return "Baseline";
145         case kAVCProfileMain:
146             return "Main";
147         case kAVCProfileExtended:
148             return "Extended";
149         case kAVCProfileHigh:
150             return "High";
151         case kAVCProfileHigh10:
152             return "High 10";
153         case kAVCProfileHigh422:
154             return "High 422";
155         case kAVCProfileHigh444:
156             return "High 444";
157         case kAVCProfileCAVLC444Intra:
158             return "CAVLC 444 Intra";
159         default:   return "Unknown";
160     }
161 }
162 
163 template<class T>
InitOMXParams(T * params)164 static void InitOMXParams(T *params) {
165     params->nSize = sizeof(T);
166     params->nVersion.s.nVersionMajor = 1;
167     params->nVersion.s.nVersionMinor = 0;
168     params->nVersion.s.nRevision = 0;
169     params->nVersion.s.nStep = 0;
170 }
171 
172 // static
Create(const sp<IOMX> & omx,const sp<MetaData> & meta,bool createEncoder,const sp<MediaSource> & source,const char * matchComponentName)173 sp<OMXCodec> OMXCodec::Create(
174         const sp<IOMX> &omx,
175         const sp<MetaData> &meta, bool createEncoder,
176         const sp<MediaSource> &source,
177         const char *matchComponentName) {
178     const char *mime;
179     bool success = meta->findCString(kKeyMIMEType, &mime);
180     CHECK(success);
181 
182     const char *componentName = NULL;
183     sp<OMXCodecObserver> observer = new OMXCodecObserver;
184     IOMX::node_id node = 0;
185     for (int index = 0;; ++index) {
186         if (createEncoder) {
187             componentName = GetCodec(
188                     kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
189                     mime, index);
190         } else {
191             componentName = GetCodec(
192                     kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
193                     mime, index);
194         }
195 
196         if (!componentName) {
197             return NULL;
198         }
199 
200         // If a specific codec is requested, skip the non-matching ones.
201         if (matchComponentName && strcmp(componentName, matchComponentName)) {
202             continue;
203         }
204 
205         LOGV("Attempting to allocate OMX node '%s'", componentName);
206 
207         status_t err = omx->allocateNode(componentName, observer, &node);
208         if (err == OK) {
209             LOGI("Successfully allocated OMX node '%s'", componentName);
210             break;
211         }
212     }
213 
214     uint32_t quirks = 0;
215     if (!strcmp(componentName, "OMX.PV.avcdec")) {
216         quirks |= kWantsNALFragments;
217         quirks |= kOutputDimensionsAre16Aligned;
218     }
219     if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
220         quirks |= kNeedsFlushBeforeDisable;
221     }
222     if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
223         quirks |= kNeedsFlushBeforeDisable;
224         quirks |= kRequiresFlushCompleteEmulation;
225 
226         // The following is currently necessary for proper shutdown
227         // behaviour, but NOT enabled by default in order to make the
228         // bug reproducible...
229         // quirks |= kRequiresFlushBeforeShutdown;
230     }
231     if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
232         quirks |= kRequiresLoadedToIdleAfterAllocation;
233         quirks |= kRequiresAllocateBufferOnInputPorts;
234     }
235     if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
236         // XXX Required on P....on only.
237         quirks |= kRequiresAllocateBufferOnOutputPorts;
238         quirks |= kOutputDimensionsAre16Aligned;
239     }
240 
241     if (!strncmp(componentName, "OMX.TI.", 7)) {
242         // Apparently I must not use OMX_UseBuffer on either input or
243         // output ports on any of the TI components or quote:
244         // "(I) may have unexpected problem (sic) which can be timing related
245         //  and hard to reproduce."
246 
247         quirks |= kRequiresAllocateBufferOnInputPorts;
248         quirks |= kRequiresAllocateBufferOnOutputPorts;
249     }
250 
251     sp<OMXCodec> codec = new OMXCodec(
252             omx, node, quirks, createEncoder, mime, componentName,
253             source);
254 
255     observer->setCodec(codec);
256 
257     uint32_t type;
258     const void *data;
259     size_t size;
260     if (meta->findData(kKeyESDS, &type, &data, &size)) {
261         ESDS esds((const char *)data, size);
262         CHECK_EQ(esds.InitCheck(), OK);
263 
264         const void *codec_specific_data;
265         size_t codec_specific_data_size;
266         esds.getCodecSpecificInfo(
267                 &codec_specific_data, &codec_specific_data_size);
268 
269         printf("found codec-specific data of size %d\n",
270                codec_specific_data_size);
271 
272         codec->addCodecSpecificData(
273                 codec_specific_data, codec_specific_data_size);
274     } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
275         printf("found avcc of size %d\n", size);
276 
277         // Parse the AVCDecoderConfigurationRecord
278 
279         const uint8_t *ptr = (const uint8_t *)data;
280 
281         CHECK(size >= 7);
282         CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
283         uint8_t profile = ptr[1];
284         uint8_t level = ptr[3];
285 
286         CHECK((ptr[4] >> 2) == 0x3f);  // reserved
287 
288         size_t lengthSize = 1 + (ptr[4] & 3);
289 
290         // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
291         // violates it...
292         // CHECK((ptr[5] >> 5) == 7);  // reserved
293 
294         size_t numSeqParameterSets = ptr[5] & 31;
295 
296         ptr += 6;
297         size -= 6;
298 
299         for (size_t i = 0; i < numSeqParameterSets; ++i) {
300             CHECK(size >= 2);
301             size_t length = U16_AT(ptr);
302 
303             ptr += 2;
304             size -= 2;
305 
306             CHECK(size >= length);
307 
308             codec->addCodecSpecificData(ptr, length);
309 
310             ptr += length;
311             size -= length;
312         }
313 
314         CHECK(size >= 1);
315         size_t numPictureParameterSets = *ptr;
316         ++ptr;
317         --size;
318 
319         for (size_t i = 0; i < numPictureParameterSets; ++i) {
320             CHECK(size >= 2);
321             size_t length = U16_AT(ptr);
322 
323             ptr += 2;
324             size -= 2;
325 
326             CHECK(size >= length);
327 
328             codec->addCodecSpecificData(ptr, length);
329 
330             ptr += length;
331             size -= length;
332         }
333 
334         LOGI("AVC profile = %d (%s), level = %d",
335              (int)profile, AVCProfileToString(profile), (int)level / 10);
336 
337         if (!strcmp(componentName, "OMX.TI.Video.Decoder")
338             && (profile != kAVCProfileBaseline || level > 39)) {
339             // This stream exceeds the decoder's capabilities. The decoder
340             // does not handle this gracefully and would clobber the heap
341             // and wreak havoc instead...
342 
343             LOGE("Profile and/or level exceed the decoder's capabilities.");
344             return NULL;
345         }
346     }
347 
348     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
349         codec->setAMRFormat();
350     }
351     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
352         codec->setAMRWBFormat();
353     }
354     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
355         int32_t numChannels, sampleRate;
356         CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
357         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
358 
359         codec->setAACFormat(numChannels, sampleRate);
360     }
361     if (!strncasecmp(mime, "video/", 6)) {
362         int32_t width, height;
363         bool success = meta->findInt32(kKeyWidth, &width);
364         success = success && meta->findInt32(kKeyHeight, &height);
365         CHECK(success);
366 
367         if (createEncoder) {
368             codec->setVideoInputFormat(mime, width, height);
369         } else {
370             codec->setVideoOutputFormat(mime, width, height);
371         }
372     }
373     if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_JPEG)
374         && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
375         OMX_COLOR_FORMATTYPE format =
376             OMX_COLOR_Format32bitARGB8888;
377             // OMX_COLOR_FormatYUV420PackedPlanar;
378             // OMX_COLOR_FormatCbYCrY;
379             // OMX_COLOR_FormatYUV411Planar;
380 
381         int32_t width, height;
382         bool success = meta->findInt32(kKeyWidth, &width);
383         success = success && meta->findInt32(kKeyHeight, &height);
384 
385         int32_t compressedSize;
386         success = success && meta->findInt32(
387                 kKeyMaxInputSize, &compressedSize);
388 
389         CHECK(success);
390         CHECK(compressedSize > 0);
391 
392         codec->setImageOutputFormat(format, width, height);
393         codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
394     }
395 
396     int32_t maxInputSize;
397     if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
398         codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
399     }
400 
401     if (!strcmp(componentName, "OMX.TI.AMR.encode")
402         || !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
403         codec->setMinBufferSize(kPortIndexOutput, 8192);  // XXX
404     }
405 
406     codec->initOutputFormat(meta);
407 
408     return codec;
409 }
410 
setMinBufferSize(OMX_U32 portIndex,OMX_U32 size)411 void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
412     OMX_PARAM_PORTDEFINITIONTYPE def;
413     InitOMXParams(&def);
414     def.nPortIndex = portIndex;
415 
416     status_t err = mOMX->getParameter(
417             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
418     CHECK_EQ(err, OK);
419 
420     if (def.nBufferSize < size) {
421         def.nBufferSize = size;
422 
423     }
424 
425     err = mOMX->setParameter(
426             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
427     CHECK_EQ(err, OK);
428 }
429 
setVideoPortFormatType(OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE compressionFormat,OMX_COLOR_FORMATTYPE colorFormat)430 status_t OMXCodec::setVideoPortFormatType(
431         OMX_U32 portIndex,
432         OMX_VIDEO_CODINGTYPE compressionFormat,
433         OMX_COLOR_FORMATTYPE colorFormat) {
434     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
435     InitOMXParams(&format);
436     format.nPortIndex = portIndex;
437     format.nIndex = 0;
438     bool found = false;
439 
440     OMX_U32 index = 0;
441     for (;;) {
442         format.nIndex = index;
443         status_t err = mOMX->getParameter(
444                 mNode, OMX_IndexParamVideoPortFormat,
445                 &format, sizeof(format));
446 
447         if (err != OK) {
448             return err;
449         }
450 
451         // The following assertion is violated by TI's video decoder.
452         // CHECK_EQ(format.nIndex, index);
453 
454 #if 1
455         CODEC_LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
456              portIndex,
457              index, format.eCompressionFormat, format.eColorFormat);
458 #endif
459 
460         if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
461             if (portIndex == kPortIndexInput
462                     && colorFormat == format.eColorFormat) {
463                 // eCompressionFormat does not seem right.
464                 found = true;
465                 break;
466             }
467             if (portIndex == kPortIndexOutput
468                     && compressionFormat == format.eCompressionFormat) {
469                 // eColorFormat does not seem right.
470                 found = true;
471                 break;
472             }
473         }
474 
475         if (format.eCompressionFormat == compressionFormat
476             && format.eColorFormat == colorFormat) {
477             found = true;
478             break;
479         }
480 
481         ++index;
482     }
483 
484     if (!found) {
485         return UNKNOWN_ERROR;
486     }
487 
488     CODEC_LOGV("found a match.");
489     status_t err = mOMX->setParameter(
490             mNode, OMX_IndexParamVideoPortFormat,
491             &format, sizeof(format));
492 
493     return err;
494 }
495 
setVideoInputFormat(const char * mime,OMX_U32 width,OMX_U32 height)496 void OMXCodec::setVideoInputFormat(
497         const char *mime, OMX_U32 width, OMX_U32 height) {
498     CODEC_LOGI("setVideoInputFormat width=%ld, height=%ld", width, height);
499 
500     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
501     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
502         compressionFormat = OMX_VIDEO_CodingAVC;
503     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
504         compressionFormat = OMX_VIDEO_CodingMPEG4;
505     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
506         compressionFormat = OMX_VIDEO_CodingH263;
507     } else {
508         LOGE("Not a supported video mime type: %s", mime);
509         CHECK(!"Should not be here. Not a supported video mime type.");
510     }
511 
512     OMX_COLOR_FORMATTYPE colorFormat =
513         0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
514 
515     if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
516         colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
517     }
518 
519     setVideoPortFormatType(
520             kPortIndexInput, OMX_VIDEO_CodingUnused,
521             colorFormat);
522 
523     setVideoPortFormatType(
524             kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
525 
526     OMX_PARAM_PORTDEFINITIONTYPE def;
527     InitOMXParams(&def);
528     def.nPortIndex = kPortIndexOutput;
529 
530     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
531 
532     status_t err = mOMX->getParameter(
533             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
534 
535     CHECK_EQ(err, OK);
536     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
537 
538     video_def->nFrameWidth = width;
539     video_def->nFrameHeight = height;
540 
541     video_def->eCompressionFormat = compressionFormat;
542     video_def->eColorFormat = OMX_COLOR_FormatUnused;
543 
544     err = mOMX->setParameter(
545             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
546     CHECK_EQ(err, OK);
547 
548     ////////////////////////////////////////////////////////////////////////////
549 
550     InitOMXParams(&def);
551     def.nPortIndex = kPortIndexInput;
552 
553     err = mOMX->getParameter(
554             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
555     CHECK_EQ(err, OK);
556 
557     def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
558     CODEC_LOGI("Setting nBufferSize = %ld", def.nBufferSize);
559 
560     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
561 
562     video_def->nFrameWidth = width;
563     video_def->nFrameHeight = height;
564     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
565     video_def->eColorFormat = colorFormat;
566 
567     err = mOMX->setParameter(
568             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
569     CHECK_EQ(err, OK);
570 }
571 
setVideoOutputFormat(const char * mime,OMX_U32 width,OMX_U32 height)572 void OMXCodec::setVideoOutputFormat(
573         const char *mime, OMX_U32 width, OMX_U32 height) {
574     CODEC_LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
575 
576     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
577     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
578         compressionFormat = OMX_VIDEO_CodingAVC;
579     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
580         compressionFormat = OMX_VIDEO_CodingMPEG4;
581     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
582         compressionFormat = OMX_VIDEO_CodingH263;
583     } else {
584         LOGE("Not a supported video mime type: %s", mime);
585         CHECK(!"Should not be here. Not a supported video mime type.");
586     }
587 
588     setVideoPortFormatType(
589             kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
590 
591 #if 1
592     {
593         OMX_VIDEO_PARAM_PORTFORMATTYPE format;
594         InitOMXParams(&format);
595         format.nPortIndex = kPortIndexOutput;
596         format.nIndex = 0;
597 
598         status_t err = mOMX->getParameter(
599                 mNode, OMX_IndexParamVideoPortFormat,
600                 &format, sizeof(format));
601         CHECK_EQ(err, OK);
602         CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
603 
604         static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
605 
606         CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
607                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
608                || format.eColorFormat == OMX_COLOR_FormatCbYCrY
609                || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
610 
611         err = mOMX->setParameter(
612                 mNode, OMX_IndexParamVideoPortFormat,
613                 &format, sizeof(format));
614         CHECK_EQ(err, OK);
615     }
616 #endif
617 
618     OMX_PARAM_PORTDEFINITIONTYPE def;
619     InitOMXParams(&def);
620     def.nPortIndex = kPortIndexInput;
621 
622     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
623 
624     status_t err = mOMX->getParameter(
625             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
626 
627     CHECK_EQ(err, OK);
628 
629 #if 1
630     // XXX Need a (much) better heuristic to compute input buffer sizes.
631     const size_t X = 64 * 1024;
632     if (def.nBufferSize < X) {
633         def.nBufferSize = X;
634     }
635 #endif
636 
637     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
638 
639     video_def->nFrameWidth = width;
640     video_def->nFrameHeight = height;
641 
642     video_def->eColorFormat = OMX_COLOR_FormatUnused;
643 
644     err = mOMX->setParameter(
645             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
646     CHECK_EQ(err, OK);
647 
648     ////////////////////////////////////////////////////////////////////////////
649 
650     InitOMXParams(&def);
651     def.nPortIndex = kPortIndexOutput;
652 
653     err = mOMX->getParameter(
654             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
655     CHECK_EQ(err, OK);
656     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
657 
658 #if 0
659     def.nBufferSize =
660         (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2;  // YUV420
661 #endif
662 
663     video_def->nFrameWidth = width;
664     video_def->nFrameHeight = height;
665 
666     err = mOMX->setParameter(
667             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
668     CHECK_EQ(err, OK);
669 }
670 
671 
OMXCodec(const sp<IOMX> & omx,IOMX::node_id node,uint32_t quirks,bool isEncoder,const char * mime,const char * componentName,const sp<MediaSource> & source)672 OMXCodec::OMXCodec(
673         const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
674         bool isEncoder,
675         const char *mime,
676         const char *componentName,
677         const sp<MediaSource> &source)
678     : mOMX(omx),
679       mNode(node),
680       mQuirks(quirks),
681       mIsEncoder(isEncoder),
682       mMIME(strdup(mime)),
683       mComponentName(strdup(componentName)),
684       mSource(source),
685       mCodecSpecificDataIndex(0),
686       mState(LOADED),
687       mInitialBufferSubmit(true),
688       mSignalledEOS(false),
689       mNoMoreOutputData(false),
690       mSeekTimeUs(-1) {
691     mPortStatus[kPortIndexInput] = ENABLED;
692     mPortStatus[kPortIndexOutput] = ENABLED;
693 
694     setComponentRole();
695 }
696 
697 // static
setComponentRole(const sp<IOMX> & omx,IOMX::node_id node,bool isEncoder,const char * mime)698 void OMXCodec::setComponentRole(
699         const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
700         const char *mime) {
701     struct MimeToRole {
702         const char *mime;
703         const char *decoderRole;
704         const char *encoderRole;
705     };
706 
707     static const MimeToRole kMimeToRole[] = {
708         { MEDIA_MIMETYPE_AUDIO_MPEG,
709             "audio_decoder.mp3", "audio_encoder.mp3" },
710         { MEDIA_MIMETYPE_AUDIO_AMR_NB,
711             "audio_decoder.amrnb", "audio_encoder.amrnb" },
712         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
713             "audio_decoder.amrwb", "audio_encoder.amrwb" },
714         { MEDIA_MIMETYPE_AUDIO_AAC,
715             "audio_decoder.aac", "audio_encoder.aac" },
716         { MEDIA_MIMETYPE_VIDEO_AVC,
717             "video_decoder.avc", "video_encoder.avc" },
718         { MEDIA_MIMETYPE_VIDEO_MPEG4,
719             "video_decoder.mpeg4", "video_encoder.mpeg4" },
720         { MEDIA_MIMETYPE_VIDEO_H263,
721             "video_decoder.h263", "video_encoder.h263" },
722     };
723 
724     static const size_t kNumMimeToRole =
725         sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
726 
727     size_t i;
728     for (i = 0; i < kNumMimeToRole; ++i) {
729         if (!strcasecmp(mime, kMimeToRole[i].mime)) {
730             break;
731         }
732     }
733 
734     if (i == kNumMimeToRole) {
735         return;
736     }
737 
738     const char *role =
739         isEncoder ? kMimeToRole[i].encoderRole
740                   : kMimeToRole[i].decoderRole;
741 
742     if (role != NULL) {
743         OMX_PARAM_COMPONENTROLETYPE roleParams;
744         InitOMXParams(&roleParams);
745 
746         strncpy((char *)roleParams.cRole,
747                 role, OMX_MAX_STRINGNAME_SIZE - 1);
748 
749         roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
750 
751         status_t err = omx->setParameter(
752                 node, OMX_IndexParamStandardComponentRole,
753                 &roleParams, sizeof(roleParams));
754 
755         if (err != OK) {
756             LOGW("Failed to set standard component role '%s'.", role);
757         }
758     }
759 }
760 
setComponentRole()761 void OMXCodec::setComponentRole() {
762     setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
763 }
764 
~OMXCodec()765 OMXCodec::~OMXCodec() {
766     CHECK(mState == LOADED || mState == ERROR);
767 
768     status_t err = mOMX->freeNode(mNode);
769     CHECK_EQ(err, OK);
770 
771     mNode = NULL;
772     setState(DEAD);
773 
774     clearCodecSpecificData();
775 
776     free(mComponentName);
777     mComponentName = NULL;
778 
779     free(mMIME);
780     mMIME = NULL;
781 }
782 
init()783 status_t OMXCodec::init() {
784     // mLock is held.
785 
786     CHECK_EQ(mState, LOADED);
787 
788     status_t err;
789     if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
790         err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
791         CHECK_EQ(err, OK);
792         setState(LOADED_TO_IDLE);
793     }
794 
795     err = allocateBuffers();
796     CHECK_EQ(err, OK);
797 
798     if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
799         err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
800         CHECK_EQ(err, OK);
801 
802         setState(LOADED_TO_IDLE);
803     }
804 
805     while (mState != EXECUTING && mState != ERROR) {
806         mAsyncCompletion.wait(mLock);
807     }
808 
809     return mState == ERROR ? UNKNOWN_ERROR : OK;
810 }
811 
812 // static
isIntermediateState(State state)813 bool OMXCodec::isIntermediateState(State state) {
814     return state == LOADED_TO_IDLE
815         || state == IDLE_TO_EXECUTING
816         || state == EXECUTING_TO_IDLE
817         || state == IDLE_TO_LOADED
818         || state == RECONFIGURING;
819 }
820 
allocateBuffers()821 status_t OMXCodec::allocateBuffers() {
822     status_t err = allocateBuffersOnPort(kPortIndexInput);
823 
824     if (err != OK) {
825         return err;
826     }
827 
828     return allocateBuffersOnPort(kPortIndexOutput);
829 }
830 
allocateBuffersOnPort(OMX_U32 portIndex)831 status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
832     OMX_PARAM_PORTDEFINITIONTYPE def;
833     InitOMXParams(&def);
834     def.nPortIndex = portIndex;
835 
836     status_t err = mOMX->getParameter(
837             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
838 
839     if (err != OK) {
840         return err;
841     }
842 
843     size_t totalSize = def.nBufferCountActual * def.nBufferSize;
844     mDealer[portIndex] = new MemoryDealer(totalSize);
845 
846     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
847         sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
848         CHECK(mem.get() != NULL);
849 
850         IOMX::buffer_id buffer;
851         if (portIndex == kPortIndexInput
852                 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
853             err = mOMX->allocateBufferWithBackup(
854                     mNode, portIndex, mem, &buffer);
855         } else if (portIndex == kPortIndexOutput
856                 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
857             err = mOMX->allocateBufferWithBackup(
858                     mNode, portIndex, mem, &buffer);
859         } else {
860             err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
861         }
862 
863         if (err != OK) {
864             LOGE("allocate_buffer_with_backup failed");
865             return err;
866         }
867 
868         BufferInfo info;
869         info.mBuffer = buffer;
870         info.mOwnedByComponent = false;
871         info.mMem = mem;
872         info.mMediaBuffer = NULL;
873 
874         if (portIndex == kPortIndexOutput) {
875             info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
876             info.mMediaBuffer->setObserver(this);
877         }
878 
879         mPortBuffers[portIndex].push(info);
880 
881         CODEC_LOGV("allocated buffer %p on %s port", buffer,
882              portIndex == kPortIndexInput ? "input" : "output");
883     }
884 
885     dumpPortStatus(portIndex);
886 
887     return OK;
888 }
889 
on_message(const omx_message & msg)890 void OMXCodec::on_message(const omx_message &msg) {
891     Mutex::Autolock autoLock(mLock);
892 
893     switch (msg.type) {
894         case omx_message::EVENT:
895         {
896             onEvent(
897                  msg.u.event_data.event, msg.u.event_data.data1,
898                  msg.u.event_data.data2);
899 
900             break;
901         }
902 
903         case omx_message::EMPTY_BUFFER_DONE:
904         {
905             IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
906 
907             CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
908 
909             Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
910             size_t i = 0;
911             while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
912                 ++i;
913             }
914 
915             CHECK(i < buffers->size());
916             if (!(*buffers)[i].mOwnedByComponent) {
917                 LOGW("We already own input buffer %p, yet received "
918                      "an EMPTY_BUFFER_DONE.", buffer);
919             }
920 
921             buffers->editItemAt(i).mOwnedByComponent = false;
922 
923             if (mPortStatus[kPortIndexInput] == DISABLING) {
924                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
925 
926                 status_t err =
927                     mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
928                 CHECK_EQ(err, OK);
929 
930                 buffers->removeAt(i);
931             } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
932                 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
933                 drainInputBuffer(&buffers->editItemAt(i));
934             }
935 
936             break;
937         }
938 
939         case omx_message::FILL_BUFFER_DONE:
940         {
941             IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
942             OMX_U32 flags = msg.u.extended_buffer_data.flags;
943 
944             CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
945                  buffer,
946                  msg.u.extended_buffer_data.range_length,
947                  flags);
948 
949             CODEC_LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
950                  msg.u.extended_buffer_data.timestamp,
951                  msg.u.extended_buffer_data.timestamp / 1E6);
952 
953             Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
954             size_t i = 0;
955             while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
956                 ++i;
957             }
958 
959             CHECK(i < buffers->size());
960             BufferInfo *info = &buffers->editItemAt(i);
961 
962             if (!info->mOwnedByComponent) {
963                 LOGW("We already own output buffer %p, yet received "
964                      "a FILL_BUFFER_DONE.", buffer);
965             }
966 
967             info->mOwnedByComponent = false;
968 
969             if (mPortStatus[kPortIndexOutput] == DISABLING) {
970                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
971 
972                 status_t err =
973                     mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
974                 CHECK_EQ(err, OK);
975 
976                 buffers->removeAt(i);
977             } else if (mPortStatus[kPortIndexOutput] == ENABLED
978                        && (flags & OMX_BUFFERFLAG_EOS)) {
979                 CODEC_LOGV("No more output data.");
980                 mNoMoreOutputData = true;
981                 mBufferFilled.signal();
982             } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
983                 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
984 
985                 MediaBuffer *buffer = info->mMediaBuffer;
986 
987                 buffer->set_range(
988                         msg.u.extended_buffer_data.range_offset,
989                         msg.u.extended_buffer_data.range_length);
990 
991                 buffer->meta_data()->clear();
992 
993                 buffer->meta_data()->setInt32(
994                         kKeyTimeUnits,
995                         (msg.u.extended_buffer_data.timestamp + 500) / 1000);
996 
997                 buffer->meta_data()->setInt32(
998                         kKeyTimeScale, 1000);
999 
1000                 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
1001                     buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
1002                 }
1003 
1004                 buffer->meta_data()->setPointer(
1005                         kKeyPlatformPrivate,
1006                         msg.u.extended_buffer_data.platform_private);
1007 
1008                 buffer->meta_data()->setPointer(
1009                         kKeyBufferID,
1010                         msg.u.extended_buffer_data.buffer);
1011 
1012                 mFilledBuffers.push_back(i);
1013                 mBufferFilled.signal();
1014             }
1015 
1016             break;
1017         }
1018 
1019         default:
1020         {
1021             CHECK(!"should not be here.");
1022             break;
1023         }
1024     }
1025 }
1026 
onEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)1027 void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1028     switch (event) {
1029         case OMX_EventCmdComplete:
1030         {
1031             onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1032             break;
1033         }
1034 
1035         case OMX_EventError:
1036         {
1037             LOGE("ERROR(%ld, %ld)", data1, data2);
1038 
1039             setState(ERROR);
1040             break;
1041         }
1042 
1043         case OMX_EventPortSettingsChanged:
1044         {
1045             onPortSettingsChanged(data1);
1046             break;
1047         }
1048 
1049         case OMX_EventBufferFlag:
1050         {
1051             CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
1052 
1053             if (data1 == kPortIndexOutput) {
1054                 mNoMoreOutputData = true;
1055             }
1056             break;
1057         }
1058 
1059         default:
1060         {
1061             CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
1062             break;
1063         }
1064     }
1065 }
1066 
onCmdComplete(OMX_COMMANDTYPE cmd,OMX_U32 data)1067 void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1068     switch (cmd) {
1069         case OMX_CommandStateSet:
1070         {
1071             onStateChange((OMX_STATETYPE)data);
1072             break;
1073         }
1074 
1075         case OMX_CommandPortDisable:
1076         {
1077             OMX_U32 portIndex = data;
1078             CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
1079 
1080             CHECK(mState == EXECUTING || mState == RECONFIGURING);
1081             CHECK_EQ(mPortStatus[portIndex], DISABLING);
1082             CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1083 
1084             mPortStatus[portIndex] = DISABLED;
1085 
1086             if (mState == RECONFIGURING) {
1087                 CHECK_EQ(portIndex, kPortIndexOutput);
1088 
1089                 enablePortAsync(portIndex);
1090 
1091                 status_t err = allocateBuffersOnPort(portIndex);
1092                 CHECK_EQ(err, OK);
1093             }
1094             break;
1095         }
1096 
1097         case OMX_CommandPortEnable:
1098         {
1099             OMX_U32 portIndex = data;
1100             CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
1101 
1102             CHECK(mState == EXECUTING || mState == RECONFIGURING);
1103             CHECK_EQ(mPortStatus[portIndex], ENABLING);
1104 
1105             mPortStatus[portIndex] = ENABLED;
1106 
1107             if (mState == RECONFIGURING) {
1108                 CHECK_EQ(portIndex, kPortIndexOutput);
1109 
1110                 setState(EXECUTING);
1111 
1112                 fillOutputBuffers();
1113             }
1114             break;
1115         }
1116 
1117         case OMX_CommandFlush:
1118         {
1119             OMX_U32 portIndex = data;
1120 
1121             CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
1122 
1123             CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1124             mPortStatus[portIndex] = ENABLED;
1125 
1126             CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1127                      mPortBuffers[portIndex].size());
1128 
1129             if (mState == RECONFIGURING) {
1130                 CHECK_EQ(portIndex, kPortIndexOutput);
1131 
1132                 disablePortAsync(portIndex);
1133             } else if (mState == EXECUTING_TO_IDLE) {
1134                 if (mPortStatus[kPortIndexInput] == ENABLED
1135                     && mPortStatus[kPortIndexOutput] == ENABLED) {
1136                     CODEC_LOGV("Finished flushing both ports, now completing "
1137                          "transition from EXECUTING to IDLE.");
1138 
1139                     mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1140                     mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1141 
1142                     status_t err =
1143                         mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1144                     CHECK_EQ(err, OK);
1145                 }
1146             } else {
1147                 // We're flushing both ports in preparation for seeking.
1148 
1149                 if (mPortStatus[kPortIndexInput] == ENABLED
1150                     && mPortStatus[kPortIndexOutput] == ENABLED) {
1151                     CODEC_LOGV("Finished flushing both ports, now continuing from"
1152                          " seek-time.");
1153 
1154                     // Clear this flag in case the decoder sent us either
1155                     // the EVENT_BUFFER_FLAG(1) or an output buffer with
1156                     // the EOS flag set _while_ flushing. Since we're going
1157                     // to submit "fresh" input data now, this flag no longer
1158                     // applies to our future.
1159                     mNoMoreOutputData = false;
1160 
1161                     drainInputBuffers();
1162                     fillOutputBuffers();
1163                 }
1164             }
1165 
1166             break;
1167         }
1168 
1169         default:
1170         {
1171             CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
1172             break;
1173         }
1174     }
1175 }
1176 
onStateChange(OMX_STATETYPE newState)1177 void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1178     switch (newState) {
1179         case OMX_StateIdle:
1180         {
1181             CODEC_LOGV("Now Idle.");
1182             if (mState == LOADED_TO_IDLE) {
1183                 status_t err = mOMX->sendCommand(
1184                         mNode, OMX_CommandStateSet, OMX_StateExecuting);
1185 
1186                 CHECK_EQ(err, OK);
1187 
1188                 setState(IDLE_TO_EXECUTING);
1189             } else {
1190                 CHECK_EQ(mState, EXECUTING_TO_IDLE);
1191 
1192                 CHECK_EQ(
1193                     countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1194                     mPortBuffers[kPortIndexInput].size());
1195 
1196                 CHECK_EQ(
1197                     countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1198                     mPortBuffers[kPortIndexOutput].size());
1199 
1200                 status_t err = mOMX->sendCommand(
1201                         mNode, OMX_CommandStateSet, OMX_StateLoaded);
1202 
1203                 CHECK_EQ(err, OK);
1204 
1205                 err = freeBuffersOnPort(kPortIndexInput);
1206                 CHECK_EQ(err, OK);
1207 
1208                 err = freeBuffersOnPort(kPortIndexOutput);
1209                 CHECK_EQ(err, OK);
1210 
1211                 mPortStatus[kPortIndexInput] = ENABLED;
1212                 mPortStatus[kPortIndexOutput] = ENABLED;
1213 
1214                 setState(IDLE_TO_LOADED);
1215             }
1216             break;
1217         }
1218 
1219         case OMX_StateExecuting:
1220         {
1221             CHECK_EQ(mState, IDLE_TO_EXECUTING);
1222 
1223             CODEC_LOGV("Now Executing.");
1224 
1225             setState(EXECUTING);
1226 
1227             // Buffers will be submitted to the component in the first
1228             // call to OMXCodec::read as mInitialBufferSubmit is true at
1229             // this point. This ensures that this on_message call returns,
1230             // releases the lock and ::init can notice the state change and
1231             // itself return.
1232             break;
1233         }
1234 
1235         case OMX_StateLoaded:
1236         {
1237             CHECK_EQ(mState, IDLE_TO_LOADED);
1238 
1239             CODEC_LOGV("Now Loaded.");
1240 
1241             setState(LOADED);
1242             break;
1243         }
1244 
1245         default:
1246         {
1247             CHECK(!"should not be here.");
1248             break;
1249         }
1250     }
1251 }
1252 
1253 // static
countBuffersWeOwn(const Vector<BufferInfo> & buffers)1254 size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1255     size_t n = 0;
1256     for (size_t i = 0; i < buffers.size(); ++i) {
1257         if (!buffers[i].mOwnedByComponent) {
1258             ++n;
1259         }
1260     }
1261 
1262     return n;
1263 }
1264 
freeBuffersOnPort(OMX_U32 portIndex,bool onlyThoseWeOwn)1265 status_t OMXCodec::freeBuffersOnPort(
1266         OMX_U32 portIndex, bool onlyThoseWeOwn) {
1267     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1268 
1269     status_t stickyErr = OK;
1270 
1271     for (size_t i = buffers->size(); i-- > 0;) {
1272         BufferInfo *info = &buffers->editItemAt(i);
1273 
1274         if (onlyThoseWeOwn && info->mOwnedByComponent) {
1275             continue;
1276         }
1277 
1278         CHECK_EQ(info->mOwnedByComponent, false);
1279 
1280         CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
1281 
1282         status_t err =
1283             mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
1284 
1285         if (err != OK) {
1286             stickyErr = err;
1287         }
1288 
1289         if (info->mMediaBuffer != NULL) {
1290             info->mMediaBuffer->setObserver(NULL);
1291 
1292             // Make sure nobody but us owns this buffer at this point.
1293             CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1294 
1295             info->mMediaBuffer->release();
1296         }
1297 
1298         buffers->removeAt(i);
1299     }
1300 
1301     CHECK(onlyThoseWeOwn || buffers->isEmpty());
1302 
1303     return stickyErr;
1304 }
1305 
onPortSettingsChanged(OMX_U32 portIndex)1306 void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
1307     CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
1308 
1309     CHECK_EQ(mState, EXECUTING);
1310     CHECK_EQ(portIndex, kPortIndexOutput);
1311     setState(RECONFIGURING);
1312 
1313     if (mQuirks & kNeedsFlushBeforeDisable) {
1314         if (!flushPortAsync(portIndex)) {
1315             onCmdComplete(OMX_CommandFlush, portIndex);
1316         }
1317     } else {
1318         disablePortAsync(portIndex);
1319     }
1320 }
1321 
flushPortAsync(OMX_U32 portIndex)1322 bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
1323     CHECK(mState == EXECUTING || mState == RECONFIGURING
1324             || mState == EXECUTING_TO_IDLE);
1325 
1326     CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
1327          portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1328          mPortBuffers[portIndex].size());
1329 
1330     CHECK_EQ(mPortStatus[portIndex], ENABLED);
1331     mPortStatus[portIndex] = SHUTTING_DOWN;
1332 
1333     if ((mQuirks & kRequiresFlushCompleteEmulation)
1334         && countBuffersWeOwn(mPortBuffers[portIndex])
1335                 == mPortBuffers[portIndex].size()) {
1336         // No flush is necessary and this component fails to send a
1337         // flush-complete event in this case.
1338 
1339         return false;
1340     }
1341 
1342     status_t err =
1343         mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
1344     CHECK_EQ(err, OK);
1345 
1346     return true;
1347 }
1348 
disablePortAsync(OMX_U32 portIndex)1349 void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1350     CHECK(mState == EXECUTING || mState == RECONFIGURING);
1351 
1352     CHECK_EQ(mPortStatus[portIndex], ENABLED);
1353     mPortStatus[portIndex] = DISABLING;
1354 
1355     status_t err =
1356         mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
1357     CHECK_EQ(err, OK);
1358 
1359     freeBuffersOnPort(portIndex, true);
1360 }
1361 
enablePortAsync(OMX_U32 portIndex)1362 void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1363     CHECK(mState == EXECUTING || mState == RECONFIGURING);
1364 
1365     CHECK_EQ(mPortStatus[portIndex], DISABLED);
1366     mPortStatus[portIndex] = ENABLING;
1367 
1368     status_t err =
1369         mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
1370     CHECK_EQ(err, OK);
1371 }
1372 
fillOutputBuffers()1373 void OMXCodec::fillOutputBuffers() {
1374     CHECK_EQ(mState, EXECUTING);
1375 
1376     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1377     for (size_t i = 0; i < buffers->size(); ++i) {
1378         fillOutputBuffer(&buffers->editItemAt(i));
1379     }
1380 }
1381 
drainInputBuffers()1382 void OMXCodec::drainInputBuffers() {
1383     CHECK(mState == EXECUTING || mState == RECONFIGURING);
1384 
1385     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1386     for (size_t i = 0; i < buffers->size(); ++i) {
1387         drainInputBuffer(&buffers->editItemAt(i));
1388     }
1389 }
1390 
drainInputBuffer(BufferInfo * info)1391 void OMXCodec::drainInputBuffer(BufferInfo *info) {
1392     CHECK_EQ(info->mOwnedByComponent, false);
1393 
1394     if (mSignalledEOS) {
1395         return;
1396     }
1397 
1398     if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1399         const CodecSpecificData *specific =
1400             mCodecSpecificData[mCodecSpecificDataIndex];
1401 
1402         size_t size = specific->mSize;
1403 
1404         if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
1405                 && !(mQuirks & kWantsNALFragments)) {
1406             static const uint8_t kNALStartCode[4] =
1407                     { 0x00, 0x00, 0x00, 0x01 };
1408 
1409             CHECK(info->mMem->size() >= specific->mSize + 4);
1410 
1411             size += 4;
1412 
1413             memcpy(info->mMem->pointer(), kNALStartCode, 4);
1414             memcpy((uint8_t *)info->mMem->pointer() + 4,
1415                    specific->mData, specific->mSize);
1416         } else {
1417             CHECK(info->mMem->size() >= specific->mSize);
1418             memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1419         }
1420 
1421         status_t err = mOMX->emptyBuffer(
1422                 mNode, info->mBuffer, 0, size,
1423                 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1424                 0);
1425         CHECK_EQ(err, OK);
1426 
1427         info->mOwnedByComponent = true;
1428 
1429         ++mCodecSpecificDataIndex;
1430         return;
1431     }
1432 
1433     MediaBuffer *srcBuffer;
1434     status_t err;
1435     if (mSeekTimeUs >= 0) {
1436         MediaSource::ReadOptions options;
1437         options.setSeekTo(mSeekTimeUs);
1438         mSeekTimeUs = -1;
1439 
1440         err = mSource->read(&srcBuffer, &options);
1441     } else {
1442         err = mSource->read(&srcBuffer);
1443     }
1444 
1445     OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1446     OMX_TICKS timestamp = 0;
1447     size_t srcLength = 0;
1448 
1449     if (err != OK) {
1450         CODEC_LOGV("signalling end of input stream.");
1451         flags |= OMX_BUFFERFLAG_EOS;
1452 
1453         mSignalledEOS = true;
1454     } else {
1455         srcLength = srcBuffer->range_length();
1456 
1457         if (info->mMem->size() < srcLength) {
1458             LOGE("info->mMem->size() = %d, srcLength = %d",
1459                  info->mMem->size(), srcLength);
1460         }
1461         CHECK(info->mMem->size() >= srcLength);
1462         memcpy(info->mMem->pointer(),
1463                (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1464                srcLength);
1465 
1466         int32_t units, scale;
1467         if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units)
1468             && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) {
1469             timestamp = ((OMX_TICKS)units * 1000000) / scale;
1470 
1471             CODEC_LOGV("Calling empty_buffer on buffer %p (length %d)",
1472                  info->mBuffer, srcLength);
1473             CODEC_LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
1474                  timestamp, timestamp / 1E6);
1475         }
1476     }
1477 
1478     if (srcBuffer != NULL) {
1479         srcBuffer->release();
1480         srcBuffer = NULL;
1481     }
1482 
1483     err = mOMX->emptyBuffer(
1484             mNode, info->mBuffer, 0, srcLength,
1485             flags, timestamp);
1486 
1487     if (err != OK) {
1488         setState(ERROR);
1489         return;
1490     }
1491 
1492     info->mOwnedByComponent = true;
1493 }
1494 
fillOutputBuffer(BufferInfo * info)1495 void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1496     CHECK_EQ(info->mOwnedByComponent, false);
1497 
1498     if (mNoMoreOutputData) {
1499         CODEC_LOGV("There is no more output data available, not "
1500              "calling fillOutputBuffer");
1501         return;
1502     }
1503 
1504     CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
1505     status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
1506     CHECK_EQ(err, OK);
1507 
1508     info->mOwnedByComponent = true;
1509 }
1510 
drainInputBuffer(IOMX::buffer_id buffer)1511 void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1512     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1513     for (size_t i = 0; i < buffers->size(); ++i) {
1514         if ((*buffers)[i].mBuffer == buffer) {
1515             drainInputBuffer(&buffers->editItemAt(i));
1516             return;
1517         }
1518     }
1519 
1520     CHECK(!"should not be here.");
1521 }
1522 
fillOutputBuffer(IOMX::buffer_id buffer)1523 void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1524     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1525     for (size_t i = 0; i < buffers->size(); ++i) {
1526         if ((*buffers)[i].mBuffer == buffer) {
1527             fillOutputBuffer(&buffers->editItemAt(i));
1528             return;
1529         }
1530     }
1531 
1532     CHECK(!"should not be here.");
1533 }
1534 
setState(State newState)1535 void OMXCodec::setState(State newState) {
1536     mState = newState;
1537     mAsyncCompletion.signal();
1538 
1539     // This may cause some spurious wakeups but is necessary to
1540     // unblock the reader if we enter ERROR state.
1541     mBufferFilled.signal();
1542 }
1543 
setRawAudioFormat(OMX_U32 portIndex,int32_t sampleRate,int32_t numChannels)1544 void OMXCodec::setRawAudioFormat(
1545         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1546     OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1547     InitOMXParams(&pcmParams);
1548     pcmParams.nPortIndex = portIndex;
1549 
1550     status_t err = mOMX->getParameter(
1551             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1552 
1553     CHECK_EQ(err, OK);
1554 
1555     pcmParams.nChannels = numChannels;
1556     pcmParams.eNumData = OMX_NumericalDataSigned;
1557     pcmParams.bInterleaved = OMX_TRUE;
1558     pcmParams.nBitPerSample = 16;
1559     pcmParams.nSamplingRate = sampleRate;
1560     pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1561 
1562     if (numChannels == 1) {
1563         pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1564     } else {
1565         CHECK_EQ(numChannels, 2);
1566 
1567         pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1568         pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1569     }
1570 
1571     err = mOMX->setParameter(
1572             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1573 
1574     CHECK_EQ(err, OK);
1575 }
1576 
setAMRFormat()1577 void OMXCodec::setAMRFormat() {
1578     if (!mIsEncoder) {
1579         OMX_AUDIO_PARAM_AMRTYPE def;
1580         InitOMXParams(&def);
1581         def.nPortIndex = kPortIndexInput;
1582 
1583         status_t err =
1584             mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1585 
1586         CHECK_EQ(err, OK);
1587 
1588         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1589         def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1590 
1591         err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1592         CHECK_EQ(err, OK);
1593     }
1594 
1595     ////////////////////////
1596 
1597     if (mIsEncoder) {
1598         sp<MetaData> format = mSource->getFormat();
1599         int32_t sampleRate;
1600         int32_t numChannels;
1601         CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1602         CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1603 
1604         setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1605     }
1606 }
1607 
setAMRWBFormat()1608 void OMXCodec::setAMRWBFormat() {
1609     if (!mIsEncoder) {
1610         OMX_AUDIO_PARAM_AMRTYPE def;
1611         InitOMXParams(&def);
1612         def.nPortIndex = kPortIndexInput;
1613 
1614         status_t err =
1615             mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1616 
1617         CHECK_EQ(err, OK);
1618 
1619         def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1620         def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
1621 
1622         err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1623         CHECK_EQ(err, OK);
1624     }
1625 
1626     ////////////////////////
1627 
1628     if (mIsEncoder) {
1629         sp<MetaData> format = mSource->getFormat();
1630         int32_t sampleRate;
1631         int32_t numChannels;
1632         CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1633         CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1634 
1635         setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1636     }
1637 }
1638 
setAACFormat(int32_t numChannels,int32_t sampleRate)1639 void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
1640     if (mIsEncoder) {
1641         setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1642     } else {
1643         OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1644         InitOMXParams(&profile);
1645         profile.nPortIndex = kPortIndexInput;
1646 
1647         status_t err = mOMX->getParameter(
1648                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1649         CHECK_EQ(err, OK);
1650 
1651         profile.nChannels = numChannels;
1652         profile.nSampleRate = sampleRate;
1653         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1654 
1655         err = mOMX->setParameter(
1656                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1657         CHECK_EQ(err, OK);
1658     }
1659 }
1660 
setImageOutputFormat(OMX_COLOR_FORMATTYPE format,OMX_U32 width,OMX_U32 height)1661 void OMXCodec::setImageOutputFormat(
1662         OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
1663     CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
1664 
1665 #if 0
1666     OMX_INDEXTYPE index;
1667     status_t err = mOMX->get_extension_index(
1668             mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1669     CHECK_EQ(err, OK);
1670 
1671     err = mOMX->set_config(mNode, index, &format, sizeof(format));
1672     CHECK_EQ(err, OK);
1673 #endif
1674 
1675     OMX_PARAM_PORTDEFINITIONTYPE def;
1676     InitOMXParams(&def);
1677     def.nPortIndex = kPortIndexOutput;
1678 
1679     status_t err = mOMX->getParameter(
1680             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1681     CHECK_EQ(err, OK);
1682 
1683     CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1684 
1685     OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1686 
1687     CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1688     imageDef->eColorFormat = format;
1689     imageDef->nFrameWidth = width;
1690     imageDef->nFrameHeight = height;
1691 
1692     switch (format) {
1693         case OMX_COLOR_FormatYUV420PackedPlanar:
1694         case OMX_COLOR_FormatYUV411Planar:
1695         {
1696             def.nBufferSize = (width * height * 3) / 2;
1697             break;
1698         }
1699 
1700         case OMX_COLOR_FormatCbYCrY:
1701         {
1702             def.nBufferSize = width * height * 2;
1703             break;
1704         }
1705 
1706         case OMX_COLOR_Format32bitARGB8888:
1707         {
1708             def.nBufferSize = width * height * 4;
1709             break;
1710         }
1711 
1712         case OMX_COLOR_Format16bitARGB4444:
1713         case OMX_COLOR_Format16bitARGB1555:
1714         case OMX_COLOR_Format16bitRGB565:
1715         case OMX_COLOR_Format16bitBGR565:
1716         {
1717             def.nBufferSize = width * height * 2;
1718             break;
1719         }
1720 
1721         default:
1722             CHECK(!"Should not be here. Unknown color format.");
1723             break;
1724     }
1725 
1726     def.nBufferCountActual = def.nBufferCountMin;
1727 
1728     err = mOMX->setParameter(
1729             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1730     CHECK_EQ(err, OK);
1731 }
1732 
setJPEGInputFormat(OMX_U32 width,OMX_U32 height,OMX_U32 compressedSize)1733 void OMXCodec::setJPEGInputFormat(
1734         OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
1735     OMX_PARAM_PORTDEFINITIONTYPE def;
1736     InitOMXParams(&def);
1737     def.nPortIndex = kPortIndexInput;
1738 
1739     status_t err = mOMX->getParameter(
1740             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1741     CHECK_EQ(err, OK);
1742 
1743     CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1744     OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1745 
1746     CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1747     imageDef->nFrameWidth = width;
1748     imageDef->nFrameHeight = height;
1749 
1750     def.nBufferSize = compressedSize;
1751     def.nBufferCountActual = def.nBufferCountMin;
1752 
1753     err = mOMX->setParameter(
1754             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1755     CHECK_EQ(err, OK);
1756 }
1757 
addCodecSpecificData(const void * data,size_t size)1758 void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
1759     CodecSpecificData *specific =
1760         (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
1761 
1762     specific->mSize = size;
1763     memcpy(specific->mData, data, size);
1764 
1765     mCodecSpecificData.push(specific);
1766 }
1767 
clearCodecSpecificData()1768 void OMXCodec::clearCodecSpecificData() {
1769     for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
1770         free(mCodecSpecificData.editItemAt(i));
1771     }
1772     mCodecSpecificData.clear();
1773     mCodecSpecificDataIndex = 0;
1774 }
1775 
start(MetaData *)1776 status_t OMXCodec::start(MetaData *) {
1777     Mutex::Autolock autoLock(mLock);
1778 
1779     if (mState != LOADED) {
1780         return UNKNOWN_ERROR;
1781     }
1782 
1783     sp<MetaData> params = new MetaData;
1784     if (mQuirks & kWantsNALFragments) {
1785         params->setInt32(kKeyWantsNALFragments, true);
1786     }
1787     status_t err = mSource->start(params.get());
1788 
1789     if (err != OK) {
1790         return err;
1791     }
1792 
1793     mCodecSpecificDataIndex = 0;
1794     mInitialBufferSubmit = true;
1795     mSignalledEOS = false;
1796     mNoMoreOutputData = false;
1797     mSeekTimeUs = -1;
1798     mFilledBuffers.clear();
1799 
1800     return init();
1801 }
1802 
stop()1803 status_t OMXCodec::stop() {
1804     CODEC_LOGV("stop");
1805 
1806     Mutex::Autolock autoLock(mLock);
1807 
1808     while (isIntermediateState(mState)) {
1809         mAsyncCompletion.wait(mLock);
1810     }
1811 
1812     switch (mState) {
1813         case LOADED:
1814         case ERROR:
1815             break;
1816 
1817         case EXECUTING:
1818         {
1819             setState(EXECUTING_TO_IDLE);
1820 
1821             if (mQuirks & kRequiresFlushBeforeShutdown) {
1822                 CODEC_LOGV("This component requires a flush before transitioning "
1823                      "from EXECUTING to IDLE...");
1824 
1825                 bool emulateInputFlushCompletion =
1826                     !flushPortAsync(kPortIndexInput);
1827 
1828                 bool emulateOutputFlushCompletion =
1829                     !flushPortAsync(kPortIndexOutput);
1830 
1831                 if (emulateInputFlushCompletion) {
1832                     onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1833                 }
1834 
1835                 if (emulateOutputFlushCompletion) {
1836                     onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1837                 }
1838             } else {
1839                 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1840                 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1841 
1842                 status_t err =
1843                     mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1844                 CHECK_EQ(err, OK);
1845             }
1846 
1847             while (mState != LOADED && mState != ERROR) {
1848                 mAsyncCompletion.wait(mLock);
1849             }
1850 
1851             break;
1852         }
1853 
1854         default:
1855         {
1856             CHECK(!"should not be here.");
1857             break;
1858         }
1859     }
1860 
1861     mSource->stop();
1862 
1863     return OK;
1864 }
1865 
getFormat()1866 sp<MetaData> OMXCodec::getFormat() {
1867     return mOutputFormat;
1868 }
1869 
read(MediaBuffer ** buffer,const ReadOptions * options)1870 status_t OMXCodec::read(
1871         MediaBuffer **buffer, const ReadOptions *options) {
1872     *buffer = NULL;
1873 
1874     Mutex::Autolock autoLock(mLock);
1875 
1876     if (mState != EXECUTING && mState != RECONFIGURING) {
1877         return UNKNOWN_ERROR;
1878     }
1879 
1880     bool seeking = false;
1881     int64_t seekTimeUs;
1882     if (options && options->getSeekTo(&seekTimeUs)) {
1883         seeking = true;
1884     }
1885 
1886     if (mInitialBufferSubmit) {
1887         mInitialBufferSubmit = false;
1888 
1889         if (seeking) {
1890             CHECK(seekTimeUs >= 0);
1891             mSeekTimeUs = seekTimeUs;
1892 
1893             // There's no reason to trigger the code below, there's
1894             // nothing to flush yet.
1895             seeking = false;
1896         }
1897 
1898         drainInputBuffers();
1899 
1900         if (mState == EXECUTING) {
1901             // Otherwise mState == RECONFIGURING and this code will trigger
1902             // after the output port is reenabled.
1903             fillOutputBuffers();
1904         }
1905     }
1906 
1907     if (seeking) {
1908         CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
1909 
1910         mSignalledEOS = false;
1911         mNoMoreOutputData = false;
1912 
1913         CHECK(seekTimeUs >= 0);
1914         mSeekTimeUs = seekTimeUs;
1915 
1916         mFilledBuffers.clear();
1917 
1918         CHECK_EQ(mState, EXECUTING);
1919 
1920         bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
1921         bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
1922 
1923         if (emulateInputFlushCompletion) {
1924             onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1925         }
1926 
1927         if (emulateOutputFlushCompletion) {
1928             onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1929         }
1930     }
1931 
1932     while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
1933         mBufferFilled.wait(mLock);
1934     }
1935 
1936     if (mState == ERROR) {
1937         return UNKNOWN_ERROR;
1938     }
1939 
1940     if (mFilledBuffers.empty()) {
1941         return ERROR_END_OF_STREAM;
1942     }
1943 
1944     size_t index = *mFilledBuffers.begin();
1945     mFilledBuffers.erase(mFilledBuffers.begin());
1946 
1947     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1948     info->mMediaBuffer->add_ref();
1949     *buffer = info->mMediaBuffer;
1950 
1951     return OK;
1952 }
1953 
signalBufferReturned(MediaBuffer * buffer)1954 void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
1955     Mutex::Autolock autoLock(mLock);
1956 
1957     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1958     for (size_t i = 0; i < buffers->size(); ++i) {
1959         BufferInfo *info = &buffers->editItemAt(i);
1960 
1961         if (info->mMediaBuffer == buffer) {
1962             CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1963             fillOutputBuffer(info);
1964             return;
1965         }
1966     }
1967 
1968     CHECK(!"should not be here.");
1969 }
1970 
imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type)1971 static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
1972     static const char *kNames[] = {
1973         "OMX_IMAGE_CodingUnused",
1974         "OMX_IMAGE_CodingAutoDetect",
1975         "OMX_IMAGE_CodingJPEG",
1976         "OMX_IMAGE_CodingJPEG2K",
1977         "OMX_IMAGE_CodingEXIF",
1978         "OMX_IMAGE_CodingTIFF",
1979         "OMX_IMAGE_CodingGIF",
1980         "OMX_IMAGE_CodingPNG",
1981         "OMX_IMAGE_CodingLZW",
1982         "OMX_IMAGE_CodingBMP",
1983     };
1984 
1985     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1986 
1987     if (type < 0 || (size_t)type >= numNames) {
1988         return "UNKNOWN";
1989     } else {
1990         return kNames[type];
1991     }
1992 }
1993 
colorFormatString(OMX_COLOR_FORMATTYPE type)1994 static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
1995     static const char *kNames[] = {
1996         "OMX_COLOR_FormatUnused",
1997         "OMX_COLOR_FormatMonochrome",
1998         "OMX_COLOR_Format8bitRGB332",
1999         "OMX_COLOR_Format12bitRGB444",
2000         "OMX_COLOR_Format16bitARGB4444",
2001         "OMX_COLOR_Format16bitARGB1555",
2002         "OMX_COLOR_Format16bitRGB565",
2003         "OMX_COLOR_Format16bitBGR565",
2004         "OMX_COLOR_Format18bitRGB666",
2005         "OMX_COLOR_Format18bitARGB1665",
2006         "OMX_COLOR_Format19bitARGB1666",
2007         "OMX_COLOR_Format24bitRGB888",
2008         "OMX_COLOR_Format24bitBGR888",
2009         "OMX_COLOR_Format24bitARGB1887",
2010         "OMX_COLOR_Format25bitARGB1888",
2011         "OMX_COLOR_Format32bitBGRA8888",
2012         "OMX_COLOR_Format32bitARGB8888",
2013         "OMX_COLOR_FormatYUV411Planar",
2014         "OMX_COLOR_FormatYUV411PackedPlanar",
2015         "OMX_COLOR_FormatYUV420Planar",
2016         "OMX_COLOR_FormatYUV420PackedPlanar",
2017         "OMX_COLOR_FormatYUV420SemiPlanar",
2018         "OMX_COLOR_FormatYUV422Planar",
2019         "OMX_COLOR_FormatYUV422PackedPlanar",
2020         "OMX_COLOR_FormatYUV422SemiPlanar",
2021         "OMX_COLOR_FormatYCbYCr",
2022         "OMX_COLOR_FormatYCrYCb",
2023         "OMX_COLOR_FormatCbYCrY",
2024         "OMX_COLOR_FormatCrYCbY",
2025         "OMX_COLOR_FormatYUV444Interleaved",
2026         "OMX_COLOR_FormatRawBayer8bit",
2027         "OMX_COLOR_FormatRawBayer10bit",
2028         "OMX_COLOR_FormatRawBayer8bitcompressed",
2029         "OMX_COLOR_FormatL2",
2030         "OMX_COLOR_FormatL4",
2031         "OMX_COLOR_FormatL8",
2032         "OMX_COLOR_FormatL16",
2033         "OMX_COLOR_FormatL24",
2034         "OMX_COLOR_FormatL32",
2035         "OMX_COLOR_FormatYUV420PackedSemiPlanar",
2036         "OMX_COLOR_FormatYUV422PackedSemiPlanar",
2037         "OMX_COLOR_Format18BitBGR666",
2038         "OMX_COLOR_Format24BitARGB6666",
2039         "OMX_COLOR_Format24BitABGR6666",
2040     };
2041 
2042     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2043 
2044     static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
2045 
2046     if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
2047         return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
2048     } else if (type < 0 || (size_t)type >= numNames) {
2049         return "UNKNOWN";
2050     } else {
2051         return kNames[type];
2052     }
2053 }
2054 
videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type)2055 static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
2056     static const char *kNames[] = {
2057         "OMX_VIDEO_CodingUnused",
2058         "OMX_VIDEO_CodingAutoDetect",
2059         "OMX_VIDEO_CodingMPEG2",
2060         "OMX_VIDEO_CodingH263",
2061         "OMX_VIDEO_CodingMPEG4",
2062         "OMX_VIDEO_CodingWMV",
2063         "OMX_VIDEO_CodingRV",
2064         "OMX_VIDEO_CodingAVC",
2065         "OMX_VIDEO_CodingMJPEG",
2066     };
2067 
2068     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2069 
2070     if (type < 0 || (size_t)type >= numNames) {
2071         return "UNKNOWN";
2072     } else {
2073         return kNames[type];
2074     }
2075 }
2076 
audioCodingTypeString(OMX_AUDIO_CODINGTYPE type)2077 static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2078     static const char *kNames[] = {
2079         "OMX_AUDIO_CodingUnused",
2080         "OMX_AUDIO_CodingAutoDetect",
2081         "OMX_AUDIO_CodingPCM",
2082         "OMX_AUDIO_CodingADPCM",
2083         "OMX_AUDIO_CodingAMR",
2084         "OMX_AUDIO_CodingGSMFR",
2085         "OMX_AUDIO_CodingGSMEFR",
2086         "OMX_AUDIO_CodingGSMHR",
2087         "OMX_AUDIO_CodingPDCFR",
2088         "OMX_AUDIO_CodingPDCEFR",
2089         "OMX_AUDIO_CodingPDCHR",
2090         "OMX_AUDIO_CodingTDMAFR",
2091         "OMX_AUDIO_CodingTDMAEFR",
2092         "OMX_AUDIO_CodingQCELP8",
2093         "OMX_AUDIO_CodingQCELP13",
2094         "OMX_AUDIO_CodingEVRC",
2095         "OMX_AUDIO_CodingSMV",
2096         "OMX_AUDIO_CodingG711",
2097         "OMX_AUDIO_CodingG723",
2098         "OMX_AUDIO_CodingG726",
2099         "OMX_AUDIO_CodingG729",
2100         "OMX_AUDIO_CodingAAC",
2101         "OMX_AUDIO_CodingMP3",
2102         "OMX_AUDIO_CodingSBC",
2103         "OMX_AUDIO_CodingVORBIS",
2104         "OMX_AUDIO_CodingWMA",
2105         "OMX_AUDIO_CodingRA",
2106         "OMX_AUDIO_CodingMIDI",
2107     };
2108 
2109     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2110 
2111     if (type < 0 || (size_t)type >= numNames) {
2112         return "UNKNOWN";
2113     } else {
2114         return kNames[type];
2115     }
2116 }
2117 
audioPCMModeString(OMX_AUDIO_PCMMODETYPE type)2118 static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2119     static const char *kNames[] = {
2120         "OMX_AUDIO_PCMModeLinear",
2121         "OMX_AUDIO_PCMModeALaw",
2122         "OMX_AUDIO_PCMModeMULaw",
2123     };
2124 
2125     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2126 
2127     if (type < 0 || (size_t)type >= numNames) {
2128         return "UNKNOWN";
2129     } else {
2130         return kNames[type];
2131     }
2132 }
2133 
amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type)2134 static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
2135     static const char *kNames[] = {
2136         "OMX_AUDIO_AMRBandModeUnused",
2137         "OMX_AUDIO_AMRBandModeNB0",
2138         "OMX_AUDIO_AMRBandModeNB1",
2139         "OMX_AUDIO_AMRBandModeNB2",
2140         "OMX_AUDIO_AMRBandModeNB3",
2141         "OMX_AUDIO_AMRBandModeNB4",
2142         "OMX_AUDIO_AMRBandModeNB5",
2143         "OMX_AUDIO_AMRBandModeNB6",
2144         "OMX_AUDIO_AMRBandModeNB7",
2145         "OMX_AUDIO_AMRBandModeWB0",
2146         "OMX_AUDIO_AMRBandModeWB1",
2147         "OMX_AUDIO_AMRBandModeWB2",
2148         "OMX_AUDIO_AMRBandModeWB3",
2149         "OMX_AUDIO_AMRBandModeWB4",
2150         "OMX_AUDIO_AMRBandModeWB5",
2151         "OMX_AUDIO_AMRBandModeWB6",
2152         "OMX_AUDIO_AMRBandModeWB7",
2153         "OMX_AUDIO_AMRBandModeWB8",
2154     };
2155 
2156     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2157 
2158     if (type < 0 || (size_t)type >= numNames) {
2159         return "UNKNOWN";
2160     } else {
2161         return kNames[type];
2162     }
2163 }
2164 
amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type)2165 static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
2166     static const char *kNames[] = {
2167         "OMX_AUDIO_AMRFrameFormatConformance",
2168         "OMX_AUDIO_AMRFrameFormatIF1",
2169         "OMX_AUDIO_AMRFrameFormatIF2",
2170         "OMX_AUDIO_AMRFrameFormatFSF",
2171         "OMX_AUDIO_AMRFrameFormatRTPPayload",
2172         "OMX_AUDIO_AMRFrameFormatITU",
2173     };
2174 
2175     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2176 
2177     if (type < 0 || (size_t)type >= numNames) {
2178         return "UNKNOWN";
2179     } else {
2180         return kNames[type];
2181     }
2182 }
2183 
dumpPortStatus(OMX_U32 portIndex)2184 void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2185     OMX_PARAM_PORTDEFINITIONTYPE def;
2186     InitOMXParams(&def);
2187     def.nPortIndex = portIndex;
2188 
2189     status_t err = mOMX->getParameter(
2190             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2191     CHECK_EQ(err, OK);
2192 
2193     printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2194 
2195     CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2196           || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
2197 
2198     printf("  nBufferCountActual = %ld\n", def.nBufferCountActual);
2199     printf("  nBufferCountMin = %ld\n", def.nBufferCountMin);
2200     printf("  nBufferSize = %ld\n", def.nBufferSize);
2201 
2202     switch (def.eDomain) {
2203         case OMX_PortDomainImage:
2204         {
2205             const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2206 
2207             printf("\n");
2208             printf("  // Image\n");
2209             printf("  nFrameWidth = %ld\n", imageDef->nFrameWidth);
2210             printf("  nFrameHeight = %ld\n", imageDef->nFrameHeight);
2211             printf("  nStride = %ld\n", imageDef->nStride);
2212 
2213             printf("  eCompressionFormat = %s\n",
2214                    imageCompressionFormatString(imageDef->eCompressionFormat));
2215 
2216             printf("  eColorFormat = %s\n",
2217                    colorFormatString(imageDef->eColorFormat));
2218 
2219             break;
2220         }
2221 
2222         case OMX_PortDomainVideo:
2223         {
2224             OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2225 
2226             printf("\n");
2227             printf("  // Video\n");
2228             printf("  nFrameWidth = %ld\n", videoDef->nFrameWidth);
2229             printf("  nFrameHeight = %ld\n", videoDef->nFrameHeight);
2230             printf("  nStride = %ld\n", videoDef->nStride);
2231 
2232             printf("  eCompressionFormat = %s\n",
2233                    videoCompressionFormatString(videoDef->eCompressionFormat));
2234 
2235             printf("  eColorFormat = %s\n",
2236                    colorFormatString(videoDef->eColorFormat));
2237 
2238             break;
2239         }
2240 
2241         case OMX_PortDomainAudio:
2242         {
2243             OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2244 
2245             printf("\n");
2246             printf("  // Audio\n");
2247             printf("  eEncoding = %s\n",
2248                    audioCodingTypeString(audioDef->eEncoding));
2249 
2250             if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2251                 OMX_AUDIO_PARAM_PCMMODETYPE params;
2252                 InitOMXParams(&params);
2253                 params.nPortIndex = portIndex;
2254 
2255                 err = mOMX->getParameter(
2256                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2257                 CHECK_EQ(err, OK);
2258 
2259                 printf("  nSamplingRate = %ld\n", params.nSamplingRate);
2260                 printf("  nChannels = %ld\n", params.nChannels);
2261                 printf("  bInterleaved = %d\n", params.bInterleaved);
2262                 printf("  nBitPerSample = %ld\n", params.nBitPerSample);
2263 
2264                 printf("  eNumData = %s\n",
2265                        params.eNumData == OMX_NumericalDataSigned
2266                         ? "signed" : "unsigned");
2267 
2268                 printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
2269             } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
2270                 OMX_AUDIO_PARAM_AMRTYPE amr;
2271                 InitOMXParams(&amr);
2272                 amr.nPortIndex = portIndex;
2273 
2274                 err = mOMX->getParameter(
2275                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2276                 CHECK_EQ(err, OK);
2277 
2278                 printf("  nChannels = %ld\n", amr.nChannels);
2279                 printf("  eAMRBandMode = %s\n",
2280                         amrBandModeString(amr.eAMRBandMode));
2281                 printf("  eAMRFrameFormat = %s\n",
2282                         amrFrameFormatString(amr.eAMRFrameFormat));
2283             }
2284 
2285             break;
2286         }
2287 
2288         default:
2289         {
2290             printf("  // Unknown\n");
2291             break;
2292         }
2293     }
2294 
2295     printf("}\n");
2296 }
2297 
initOutputFormat(const sp<MetaData> & inputFormat)2298 void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
2299     mOutputFormat = new MetaData;
2300     mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
2301 
2302     OMX_PARAM_PORTDEFINITIONTYPE def;
2303     InitOMXParams(&def);
2304     def.nPortIndex = kPortIndexOutput;
2305 
2306     status_t err = mOMX->getParameter(
2307             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2308     CHECK_EQ(err, OK);
2309 
2310     switch (def.eDomain) {
2311         case OMX_PortDomainImage:
2312         {
2313             OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2314             CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2315 
2316             mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
2317             mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
2318             mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
2319             mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
2320             break;
2321         }
2322 
2323         case OMX_PortDomainAudio:
2324         {
2325             OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
2326 
2327             if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
2328                 OMX_AUDIO_PARAM_PCMMODETYPE params;
2329                 InitOMXParams(&params);
2330                 params.nPortIndex = kPortIndexOutput;
2331 
2332                 err = mOMX->getParameter(
2333                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2334                 CHECK_EQ(err, OK);
2335 
2336                 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
2337                 CHECK_EQ(params.nBitPerSample, 16);
2338                 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
2339 
2340                 int32_t numChannels, sampleRate;
2341                 inputFormat->findInt32(kKeyChannelCount, &numChannels);
2342                 inputFormat->findInt32(kKeySampleRate, &sampleRate);
2343 
2344                 if ((OMX_U32)numChannels != params.nChannels) {
2345                     LOGW("Codec outputs a different number of channels than "
2346                          "the input stream contains.");
2347                 }
2348 
2349                 mOutputFormat->setCString(
2350                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
2351 
2352                 // Use the codec-advertised number of channels, as some
2353                 // codecs appear to output stereo even if the input data is
2354                 // mono.
2355                 mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
2356 
2357                 // The codec-reported sampleRate is not reliable...
2358                 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
2359             } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
2360                 OMX_AUDIO_PARAM_AMRTYPE amr;
2361                 InitOMXParams(&amr);
2362                 amr.nPortIndex = kPortIndexOutput;
2363 
2364                 err = mOMX->getParameter(
2365                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2366                 CHECK_EQ(err, OK);
2367 
2368                 CHECK_EQ(amr.nChannels, 1);
2369                 mOutputFormat->setInt32(kKeyChannelCount, 1);
2370 
2371                 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
2372                     && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
2373                     mOutputFormat->setCString(
2374                             kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
2375                     mOutputFormat->setInt32(kKeySampleRate, 8000);
2376                 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
2377                             && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
2378                     mOutputFormat->setCString(
2379                             kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
2380                     mOutputFormat->setInt32(kKeySampleRate, 16000);
2381                 } else {
2382                     CHECK(!"Unknown AMR band mode.");
2383                 }
2384             } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
2385                 mOutputFormat->setCString(
2386                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
2387             } else {
2388                 CHECK(!"Should not be here. Unknown audio encoding.");
2389             }
2390             break;
2391         }
2392 
2393         case OMX_PortDomainVideo:
2394         {
2395             OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2396 
2397             if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
2398                 mOutputFormat->setCString(
2399                         kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
2400             } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
2401                 mOutputFormat->setCString(
2402                         kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
2403             } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
2404                 mOutputFormat->setCString(
2405                         kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
2406             } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
2407                 mOutputFormat->setCString(
2408                         kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
2409             } else {
2410                 CHECK(!"Unknown compression format.");
2411             }
2412 
2413             if (mQuirks & kOutputDimensionsAre16Aligned) {
2414                 // This component appears to be lying to me.
2415                 mOutputFormat->setInt32(
2416                         kKeyWidth, (video_def->nFrameWidth + 15) & -16);
2417                 mOutputFormat->setInt32(
2418                         kKeyHeight, (video_def->nFrameHeight + 15) & -16);
2419             } else {
2420                 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
2421                 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
2422             }
2423 
2424             mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
2425             break;
2426         }
2427 
2428         default:
2429         {
2430             CHECK(!"should not be here, neither audio nor video.");
2431             break;
2432         }
2433     }
2434 }
2435 
2436 ////////////////////////////////////////////////////////////////////////////////
2437 
QueryCodecs(const sp<IOMX> & omx,const char * mime,bool queryDecoders,Vector<CodecCapabilities> * results)2438 status_t QueryCodecs(
2439         const sp<IOMX> &omx,
2440         const char *mime, bool queryDecoders,
2441         Vector<CodecCapabilities> *results) {
2442     results->clear();
2443 
2444     for (int index = 0;; ++index) {
2445         const char *componentName;
2446 
2447         if (!queryDecoders) {
2448             componentName = GetCodec(
2449                     kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
2450                     mime, index);
2451         } else {
2452             componentName = GetCodec(
2453                     kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
2454                     mime, index);
2455         }
2456 
2457         if (!componentName) {
2458             return OK;
2459         }
2460 
2461         sp<OMXCodecObserver> observer = new OMXCodecObserver;
2462         IOMX::node_id node;
2463         status_t err = omx->allocateNode(componentName, observer, &node);
2464 
2465         if (err != OK) {
2466             continue;
2467         }
2468 
2469         OMXCodec::setComponentRole(omx, node, queryDecoders, mime);
2470 
2471         results->push();
2472         CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
2473         caps->mComponentName = componentName;
2474 
2475         OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
2476         InitOMXParams(&param);
2477 
2478         param.nPortIndex = queryDecoders ? 0 : 1;
2479 
2480         for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
2481             err = omx->getParameter(
2482                     node, OMX_IndexParamVideoProfileLevelQuerySupported,
2483                     &param, sizeof(param));
2484 
2485             if (err != OK) {
2486                 break;
2487             }
2488 
2489             CodecProfileLevel profileLevel;
2490             profileLevel.mProfile = param.eProfile;
2491             profileLevel.mLevel = param.eLevel;
2492 
2493             caps->mProfileLevels.push(profileLevel);
2494         }
2495 
2496         CHECK_EQ(omx->freeNode(node), OK);
2497     }
2498 }
2499 
2500 }  // namespace android
2501