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