OMXCodec.cpp revision 022ad466c95001eaf043b1f0aff89cde92e3387f
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 =
598        0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
599
600    if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
601        colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
602    }
603
604    CHECK_EQ(setVideoPortFormatType(
605            kPortIndexInput, OMX_VIDEO_CodingUnused,
606            colorFormat), OK);
607
608    CHECK_EQ(setVideoPortFormatType(
609            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
610            OK);
611
612    OMX_PARAM_PORTDEFINITIONTYPE def;
613    InitOMXParams(&def);
614    def.nPortIndex = kPortIndexOutput;
615
616    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
617
618    status_t err = mOMX->getParameter(
619            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
620
621    CHECK_EQ(err, OK);
622    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
623
624    video_def->nFrameWidth = width;
625    video_def->nFrameHeight = height;
626
627    video_def->eCompressionFormat = compressionFormat;
628    video_def->eColorFormat = OMX_COLOR_FormatUnused;
629
630    err = mOMX->setParameter(
631            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
632    CHECK_EQ(err, OK);
633
634    ////////////////////////////////////////////////////////////////////////////
635
636    InitOMXParams(&def);
637    def.nPortIndex = kPortIndexInput;
638
639    err = mOMX->getParameter(
640            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
641    CHECK_EQ(err, OK);
642
643    def.nBufferSize = getFrameSize(colorFormat, width, height);
644    CODEC_LOGV("Setting nBufferSize = %ld", def.nBufferSize);
645
646    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
647
648    video_def->nFrameWidth = width;
649    video_def->nFrameHeight = height;
650    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
651    video_def->eColorFormat = colorFormat;
652
653    video_def->xFramerate = 24 << 16;  // XXX crucial!
654
655    err = mOMX->setParameter(
656            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
657    CHECK_EQ(err, OK);
658
659    switch (compressionFormat) {
660        case OMX_VIDEO_CodingMPEG4:
661        {
662            CHECK_EQ(setupMPEG4EncoderParameters(), OK);
663            break;
664        }
665
666        case OMX_VIDEO_CodingH263:
667            break;
668
669        default:
670            CHECK(!"Support for this compressionFormat to be implemented.");
671            break;
672    }
673}
674
675status_t OMXCodec::setupMPEG4EncoderParameters() {
676    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
677    InitOMXParams(&mpeg4type);
678    mpeg4type.nPortIndex = kPortIndexOutput;
679
680    status_t err = mOMX->getParameter(
681            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
682    CHECK_EQ(err, OK);
683
684    mpeg4type.nSliceHeaderSpacing = 0;
685    mpeg4type.bSVH = OMX_FALSE;
686    mpeg4type.bGov = OMX_FALSE;
687
688    mpeg4type.nAllowedPictureTypes =
689        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
690
691    mpeg4type.nPFrames = 23;
692    mpeg4type.nBFrames = 0;
693
694    mpeg4type.nIDCVLCThreshold = 0;
695    mpeg4type.bACPred = OMX_TRUE;
696    mpeg4type.nMaxPacketSize = 256;
697    mpeg4type.nTimeIncRes = 1000;
698    mpeg4type.nHeaderExtension = 0;
699    mpeg4type.bReversibleVLC = OMX_FALSE;
700
701    mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
702    mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;
703
704    err = mOMX->setParameter(
705            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
706    CHECK_EQ(err, OK);
707
708    // ----------------
709
710    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
711    InitOMXParams(&bitrateType);
712    bitrateType.nPortIndex = kPortIndexOutput;
713
714    err = mOMX->getParameter(
715            mNode, OMX_IndexParamVideoBitrate,
716            &bitrateType, sizeof(bitrateType));
717    CHECK_EQ(err, OK);
718
719    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
720    bitrateType.nTargetBitrate = 1000000;
721
722    err = mOMX->setParameter(
723            mNode, OMX_IndexParamVideoBitrate,
724            &bitrateType, sizeof(bitrateType));
725    CHECK_EQ(err, OK);
726
727    // ----------------
728
729    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
730    InitOMXParams(&errorCorrectionType);
731    errorCorrectionType.nPortIndex = kPortIndexOutput;
732
733    err = mOMX->getParameter(
734            mNode, OMX_IndexParamVideoErrorCorrection,
735            &errorCorrectionType, sizeof(errorCorrectionType));
736    CHECK_EQ(err, OK);
737
738    errorCorrectionType.bEnableHEC = OMX_FALSE;
739    errorCorrectionType.bEnableResync = OMX_TRUE;
740    errorCorrectionType.nResynchMarkerSpacing = 256;
741    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
742    errorCorrectionType.bEnableRVLC = OMX_FALSE;
743
744    err = mOMX->setParameter(
745            mNode, OMX_IndexParamVideoErrorCorrection,
746            &errorCorrectionType, sizeof(errorCorrectionType));
747    CHECK_EQ(err, OK);
748
749    return OK;
750}
751
752void OMXCodec::setVideoOutputFormat(
753        const char *mime, OMX_U32 width, OMX_U32 height) {
754    CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
755
756    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
757    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
758        compressionFormat = OMX_VIDEO_CodingAVC;
759    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
760        compressionFormat = OMX_VIDEO_CodingMPEG4;
761    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
762        compressionFormat = OMX_VIDEO_CodingH263;
763    } else {
764        LOGE("Not a supported video mime type: %s", mime);
765        CHECK(!"Should not be here. Not a supported video mime type.");
766    }
767
768    setVideoPortFormatType(
769            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
770
771#if 1
772    {
773        OMX_VIDEO_PARAM_PORTFORMATTYPE format;
774        InitOMXParams(&format);
775        format.nPortIndex = kPortIndexOutput;
776        format.nIndex = 0;
777
778        status_t err = mOMX->getParameter(
779                mNode, OMX_IndexParamVideoPortFormat,
780                &format, sizeof(format));
781        CHECK_EQ(err, OK);
782        CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
783
784        static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
785
786        CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
787               || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
788               || format.eColorFormat == OMX_COLOR_FormatCbYCrY
789               || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
790
791        err = mOMX->setParameter(
792                mNode, OMX_IndexParamVideoPortFormat,
793                &format, sizeof(format));
794        CHECK_EQ(err, OK);
795    }
796#endif
797
798    OMX_PARAM_PORTDEFINITIONTYPE def;
799    InitOMXParams(&def);
800    def.nPortIndex = kPortIndexInput;
801
802    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
803
804    status_t err = mOMX->getParameter(
805            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
806
807    CHECK_EQ(err, OK);
808
809#if 1
810    // XXX Need a (much) better heuristic to compute input buffer sizes.
811    const size_t X = 64 * 1024;
812    if (def.nBufferSize < X) {
813        def.nBufferSize = X;
814    }
815#endif
816
817    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
818
819    video_def->nFrameWidth = width;
820    video_def->nFrameHeight = height;
821
822    video_def->eCompressionFormat = compressionFormat;
823    video_def->eColorFormat = OMX_COLOR_FormatUnused;
824
825    err = mOMX->setParameter(
826            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
827    CHECK_EQ(err, OK);
828
829    ////////////////////////////////////////////////////////////////////////////
830
831    InitOMXParams(&def);
832    def.nPortIndex = kPortIndexOutput;
833
834    err = mOMX->getParameter(
835            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
836    CHECK_EQ(err, OK);
837    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
838
839#if 0
840    def.nBufferSize =
841        (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2;  // YUV420
842#endif
843
844    video_def->nFrameWidth = width;
845    video_def->nFrameHeight = height;
846
847    err = mOMX->setParameter(
848            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
849    CHECK_EQ(err, OK);
850}
851
852
853OMXCodec::OMXCodec(
854        const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
855        bool isEncoder,
856        const char *mime,
857        const char *componentName,
858        const sp<MediaSource> &source)
859    : mOMX(omx),
860      mNode(node),
861      mQuirks(quirks),
862      mIsEncoder(isEncoder),
863      mMIME(strdup(mime)),
864      mComponentName(strdup(componentName)),
865      mSource(source),
866      mCodecSpecificDataIndex(0),
867      mState(LOADED),
868      mInitialBufferSubmit(true),
869      mSignalledEOS(false),
870      mNoMoreOutputData(false),
871      mOutputPortSettingsHaveChanged(false),
872      mSeekTimeUs(-1) {
873    mPortStatus[kPortIndexInput] = ENABLED;
874    mPortStatus[kPortIndexOutput] = ENABLED;
875
876    setComponentRole();
877}
878
879// static
880void OMXCodec::setComponentRole(
881        const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
882        const char *mime) {
883    struct MimeToRole {
884        const char *mime;
885        const char *decoderRole;
886        const char *encoderRole;
887    };
888
889    static const MimeToRole kMimeToRole[] = {
890        { MEDIA_MIMETYPE_AUDIO_MPEG,
891            "audio_decoder.mp3", "audio_encoder.mp3" },
892        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
893            "audio_decoder.amrnb", "audio_encoder.amrnb" },
894        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
895            "audio_decoder.amrwb", "audio_encoder.amrwb" },
896        { MEDIA_MIMETYPE_AUDIO_AAC,
897            "audio_decoder.aac", "audio_encoder.aac" },
898        { MEDIA_MIMETYPE_VIDEO_AVC,
899            "video_decoder.avc", "video_encoder.avc" },
900        { MEDIA_MIMETYPE_VIDEO_MPEG4,
901            "video_decoder.mpeg4", "video_encoder.mpeg4" },
902        { MEDIA_MIMETYPE_VIDEO_H263,
903            "video_decoder.h263", "video_encoder.h263" },
904    };
905
906    static const size_t kNumMimeToRole =
907        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
908
909    size_t i;
910    for (i = 0; i < kNumMimeToRole; ++i) {
911        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
912            break;
913        }
914    }
915
916    if (i == kNumMimeToRole) {
917        return;
918    }
919
920    const char *role =
921        isEncoder ? kMimeToRole[i].encoderRole
922                  : kMimeToRole[i].decoderRole;
923
924    if (role != NULL) {
925        OMX_PARAM_COMPONENTROLETYPE roleParams;
926        InitOMXParams(&roleParams);
927
928        strncpy((char *)roleParams.cRole,
929                role, OMX_MAX_STRINGNAME_SIZE - 1);
930
931        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
932
933        status_t err = omx->setParameter(
934                node, OMX_IndexParamStandardComponentRole,
935                &roleParams, sizeof(roleParams));
936
937        if (err != OK) {
938            LOGW("Failed to set standard component role '%s'.", role);
939        }
940    }
941}
942
943void OMXCodec::setComponentRole() {
944    setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
945}
946
947OMXCodec::~OMXCodec() {
948    CHECK(mState == LOADED || mState == ERROR);
949
950    status_t err = mOMX->freeNode(mNode);
951    CHECK_EQ(err, OK);
952
953    mNode = NULL;
954    setState(DEAD);
955
956    clearCodecSpecificData();
957
958    free(mComponentName);
959    mComponentName = NULL;
960
961    free(mMIME);
962    mMIME = NULL;
963}
964
965status_t OMXCodec::init() {
966    // mLock is held.
967
968    CHECK_EQ(mState, LOADED);
969
970    status_t err;
971    if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
972        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
973        CHECK_EQ(err, OK);
974        setState(LOADED_TO_IDLE);
975    }
976
977    err = allocateBuffers();
978    CHECK_EQ(err, OK);
979
980    if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
981        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
982        CHECK_EQ(err, OK);
983
984        setState(LOADED_TO_IDLE);
985    }
986
987    while (mState != EXECUTING && mState != ERROR) {
988        mAsyncCompletion.wait(mLock);
989    }
990
991    return mState == ERROR ? UNKNOWN_ERROR : OK;
992}
993
994// static
995bool OMXCodec::isIntermediateState(State state) {
996    return state == LOADED_TO_IDLE
997        || state == IDLE_TO_EXECUTING
998        || state == EXECUTING_TO_IDLE
999        || state == IDLE_TO_LOADED
1000        || state == RECONFIGURING;
1001}
1002
1003status_t OMXCodec::allocateBuffers() {
1004    status_t err = allocateBuffersOnPort(kPortIndexInput);
1005
1006    if (err != OK) {
1007        return err;
1008    }
1009
1010    return allocateBuffersOnPort(kPortIndexOutput);
1011}
1012
1013status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
1014    OMX_PARAM_PORTDEFINITIONTYPE def;
1015    InitOMXParams(&def);
1016    def.nPortIndex = portIndex;
1017
1018    status_t err = mOMX->getParameter(
1019            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1020
1021    if (err != OK) {
1022        return err;
1023    }
1024
1025    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
1026    mDealer[portIndex] = new MemoryDealer(totalSize);
1027
1028    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
1029        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
1030        CHECK(mem.get() != NULL);
1031
1032        IOMX::buffer_id buffer;
1033        if (portIndex == kPortIndexInput
1034                && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
1035            err = mOMX->allocateBufferWithBackup(
1036                    mNode, portIndex, mem, &buffer);
1037        } else if (portIndex == kPortIndexOutput
1038                && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
1039            err = mOMX->allocateBufferWithBackup(
1040                    mNode, portIndex, mem, &buffer);
1041        } else {
1042            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
1043        }
1044
1045        if (err != OK) {
1046            LOGE("allocate_buffer_with_backup failed");
1047            return err;
1048        }
1049
1050        BufferInfo info;
1051        info.mBuffer = buffer;
1052        info.mOwnedByComponent = false;
1053        info.mMem = mem;
1054        info.mMediaBuffer = NULL;
1055
1056        if (portIndex == kPortIndexOutput) {
1057            info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
1058            info.mMediaBuffer->setObserver(this);
1059        }
1060
1061        mPortBuffers[portIndex].push(info);
1062
1063        CODEC_LOGV("allocated buffer %p on %s port", buffer,
1064             portIndex == kPortIndexInput ? "input" : "output");
1065    }
1066
1067    dumpPortStatus(portIndex);
1068
1069    return OK;
1070}
1071
1072void OMXCodec::on_message(const omx_message &msg) {
1073    Mutex::Autolock autoLock(mLock);
1074
1075    switch (msg.type) {
1076        case omx_message::EVENT:
1077        {
1078            onEvent(
1079                 msg.u.event_data.event, msg.u.event_data.data1,
1080                 msg.u.event_data.data2);
1081
1082            break;
1083        }
1084
1085        case omx_message::EMPTY_BUFFER_DONE:
1086        {
1087            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1088
1089            CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
1090
1091            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1092            size_t i = 0;
1093            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1094                ++i;
1095            }
1096
1097            CHECK(i < buffers->size());
1098            if (!(*buffers)[i].mOwnedByComponent) {
1099                LOGW("We already own input buffer %p, yet received "
1100                     "an EMPTY_BUFFER_DONE.", buffer);
1101            }
1102
1103            buffers->editItemAt(i).mOwnedByComponent = false;
1104
1105            if (mPortStatus[kPortIndexInput] == DISABLING) {
1106                CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
1107
1108                status_t err =
1109                    mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
1110                CHECK_EQ(err, OK);
1111
1112                buffers->removeAt(i);
1113            } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
1114                CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
1115                drainInputBuffer(&buffers->editItemAt(i));
1116            }
1117
1118            break;
1119        }
1120
1121        case omx_message::FILL_BUFFER_DONE:
1122        {
1123            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1124            OMX_U32 flags = msg.u.extended_buffer_data.flags;
1125
1126            CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
1127                 buffer,
1128                 msg.u.extended_buffer_data.range_length,
1129                 flags);
1130
1131            CODEC_LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
1132                 msg.u.extended_buffer_data.timestamp,
1133                 msg.u.extended_buffer_data.timestamp / 1E6);
1134
1135            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1136            size_t i = 0;
1137            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1138                ++i;
1139            }
1140
1141            CHECK(i < buffers->size());
1142            BufferInfo *info = &buffers->editItemAt(i);
1143
1144            if (!info->mOwnedByComponent) {
1145                LOGW("We already own output buffer %p, yet received "
1146                     "a FILL_BUFFER_DONE.", buffer);
1147            }
1148
1149            info->mOwnedByComponent = false;
1150
1151            if (mPortStatus[kPortIndexOutput] == DISABLING) {
1152                CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
1153
1154                status_t err =
1155                    mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
1156                CHECK_EQ(err, OK);
1157
1158                buffers->removeAt(i);
1159            } else if (mPortStatus[kPortIndexOutput] == ENABLED
1160                       && (flags & OMX_BUFFERFLAG_EOS)) {
1161                CODEC_LOGV("No more output data.");
1162                mNoMoreOutputData = true;
1163                mBufferFilled.signal();
1164            } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
1165                CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1166
1167                MediaBuffer *buffer = info->mMediaBuffer;
1168
1169                buffer->set_range(
1170                        msg.u.extended_buffer_data.range_offset,
1171                        msg.u.extended_buffer_data.range_length);
1172
1173                buffer->meta_data()->clear();
1174
1175                buffer->meta_data()->setInt64(
1176                        kKeyTime, msg.u.extended_buffer_data.timestamp);
1177
1178                if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
1179                    buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
1180                }
1181
1182                buffer->meta_data()->setPointer(
1183                        kKeyPlatformPrivate,
1184                        msg.u.extended_buffer_data.platform_private);
1185
1186                buffer->meta_data()->setPointer(
1187                        kKeyBufferID,
1188                        msg.u.extended_buffer_data.buffer);
1189
1190                mFilledBuffers.push_back(i);
1191                mBufferFilled.signal();
1192            }
1193
1194            break;
1195        }
1196
1197        default:
1198        {
1199            CHECK(!"should not be here.");
1200            break;
1201        }
1202    }
1203}
1204
1205void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1206    switch (event) {
1207        case OMX_EventCmdComplete:
1208        {
1209            onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1210            break;
1211        }
1212
1213        case OMX_EventError:
1214        {
1215            LOGE("ERROR(%ld, %ld)", data1, data2);
1216
1217            setState(ERROR);
1218            break;
1219        }
1220
1221        case OMX_EventPortSettingsChanged:
1222        {
1223            onPortSettingsChanged(data1);
1224            break;
1225        }
1226
1227        case OMX_EventBufferFlag:
1228        {
1229            CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
1230
1231            if (data1 == kPortIndexOutput) {
1232                mNoMoreOutputData = true;
1233            }
1234            break;
1235        }
1236
1237        default:
1238        {
1239            CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
1240            break;
1241        }
1242    }
1243}
1244
1245// Has the format changed in any way that the client would have to be aware of?
1246static bool formatHasNotablyChanged(
1247        const sp<MetaData> &from, const sp<MetaData> &to) {
1248    if (from.get() == NULL && to.get() == NULL) {
1249        return false;
1250    }
1251
1252    if ((from.get() == NULL && to.get() != NULL)
1253        || (from.get() != NULL && to.get() == NULL)) {
1254        return true;
1255    }
1256
1257    const char *mime_from, *mime_to;
1258    CHECK(from->findCString(kKeyMIMEType, &mime_from));
1259    CHECK(to->findCString(kKeyMIMEType, &mime_to));
1260
1261    if (strcasecmp(mime_from, mime_to)) {
1262        return true;
1263    }
1264
1265    if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
1266        int32_t colorFormat_from, colorFormat_to;
1267        CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
1268        CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
1269
1270        if (colorFormat_from != colorFormat_to) {
1271            return true;
1272        }
1273
1274        int32_t width_from, width_to;
1275        CHECK(from->findInt32(kKeyWidth, &width_from));
1276        CHECK(to->findInt32(kKeyWidth, &width_to));
1277
1278        if (width_from != width_to) {
1279            return true;
1280        }
1281
1282        int32_t height_from, height_to;
1283        CHECK(from->findInt32(kKeyHeight, &height_from));
1284        CHECK(to->findInt32(kKeyHeight, &height_to));
1285
1286        if (height_from != height_to) {
1287            return true;
1288        }
1289    } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
1290        int32_t numChannels_from, numChannels_to;
1291        CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
1292        CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
1293
1294        if (numChannels_from != numChannels_to) {
1295            return true;
1296        }
1297
1298        int32_t sampleRate_from, sampleRate_to;
1299        CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
1300        CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
1301
1302        if (sampleRate_from != sampleRate_to) {
1303            return true;
1304        }
1305    }
1306
1307    return false;
1308}
1309
1310void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1311    switch (cmd) {
1312        case OMX_CommandStateSet:
1313        {
1314            onStateChange((OMX_STATETYPE)data);
1315            break;
1316        }
1317
1318        case OMX_CommandPortDisable:
1319        {
1320            OMX_U32 portIndex = data;
1321            CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
1322
1323            CHECK(mState == EXECUTING || mState == RECONFIGURING);
1324            CHECK_EQ(mPortStatus[portIndex], DISABLING);
1325            CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1326
1327            mPortStatus[portIndex] = DISABLED;
1328
1329            if (mState == RECONFIGURING) {
1330                CHECK_EQ(portIndex, kPortIndexOutput);
1331
1332                sp<MetaData> oldOutputFormat = mOutputFormat;
1333                initOutputFormat(mSource->getFormat());
1334
1335                // Don't notify clients if the output port settings change
1336                // wasn't of importance to them, i.e. it may be that just the
1337                // number of buffers has changed and nothing else.
1338                mOutputPortSettingsHaveChanged =
1339                    formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
1340
1341                enablePortAsync(portIndex);
1342
1343                status_t err = allocateBuffersOnPort(portIndex);
1344                CHECK_EQ(err, OK);
1345            }
1346            break;
1347        }
1348
1349        case OMX_CommandPortEnable:
1350        {
1351            OMX_U32 portIndex = data;
1352            CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
1353
1354            CHECK(mState == EXECUTING || mState == RECONFIGURING);
1355            CHECK_EQ(mPortStatus[portIndex], ENABLING);
1356
1357            mPortStatus[portIndex] = ENABLED;
1358
1359            if (mState == RECONFIGURING) {
1360                CHECK_EQ(portIndex, kPortIndexOutput);
1361
1362                setState(EXECUTING);
1363
1364                fillOutputBuffers();
1365            }
1366            break;
1367        }
1368
1369        case OMX_CommandFlush:
1370        {
1371            OMX_U32 portIndex = data;
1372
1373            CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
1374
1375            CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1376            mPortStatus[portIndex] = ENABLED;
1377
1378            CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1379                     mPortBuffers[portIndex].size());
1380
1381            if (mState == RECONFIGURING) {
1382                CHECK_EQ(portIndex, kPortIndexOutput);
1383
1384                disablePortAsync(portIndex);
1385            } else if (mState == EXECUTING_TO_IDLE) {
1386                if (mPortStatus[kPortIndexInput] == ENABLED
1387                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1388                    CODEC_LOGV("Finished flushing both ports, now completing "
1389                         "transition from EXECUTING to IDLE.");
1390
1391                    mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1392                    mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1393
1394                    status_t err =
1395                        mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1396                    CHECK_EQ(err, OK);
1397                }
1398            } else {
1399                // We're flushing both ports in preparation for seeking.
1400
1401                if (mPortStatus[kPortIndexInput] == ENABLED
1402                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1403                    CODEC_LOGV("Finished flushing both ports, now continuing from"
1404                         " seek-time.");
1405
1406                    // Clear this flag in case the decoder sent us either
1407                    // the EVENT_BUFFER_FLAG(1) or an output buffer with
1408                    // the EOS flag set _while_ flushing. Since we're going
1409                    // to submit "fresh" input data now, this flag no longer
1410                    // applies to our future.
1411                    mNoMoreOutputData = false;
1412
1413                    drainInputBuffers();
1414                    fillOutputBuffers();
1415                }
1416            }
1417
1418            break;
1419        }
1420
1421        default:
1422        {
1423            CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
1424            break;
1425        }
1426    }
1427}
1428
1429void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1430    switch (newState) {
1431        case OMX_StateIdle:
1432        {
1433            CODEC_LOGV("Now Idle.");
1434            if (mState == LOADED_TO_IDLE) {
1435                status_t err = mOMX->sendCommand(
1436                        mNode, OMX_CommandStateSet, OMX_StateExecuting);
1437
1438                CHECK_EQ(err, OK);
1439
1440                setState(IDLE_TO_EXECUTING);
1441            } else {
1442                CHECK_EQ(mState, EXECUTING_TO_IDLE);
1443
1444                CHECK_EQ(
1445                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1446                    mPortBuffers[kPortIndexInput].size());
1447
1448                CHECK_EQ(
1449                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1450                    mPortBuffers[kPortIndexOutput].size());
1451
1452                status_t err = mOMX->sendCommand(
1453                        mNode, OMX_CommandStateSet, OMX_StateLoaded);
1454
1455                CHECK_EQ(err, OK);
1456
1457                err = freeBuffersOnPort(kPortIndexInput);
1458                CHECK_EQ(err, OK);
1459
1460                err = freeBuffersOnPort(kPortIndexOutput);
1461                CHECK_EQ(err, OK);
1462
1463                mPortStatus[kPortIndexInput] = ENABLED;
1464                mPortStatus[kPortIndexOutput] = ENABLED;
1465
1466                setState(IDLE_TO_LOADED);
1467            }
1468            break;
1469        }
1470
1471        case OMX_StateExecuting:
1472        {
1473            CHECK_EQ(mState, IDLE_TO_EXECUTING);
1474
1475            CODEC_LOGV("Now Executing.");
1476
1477            setState(EXECUTING);
1478
1479            // Buffers will be submitted to the component in the first
1480            // call to OMXCodec::read as mInitialBufferSubmit is true at
1481            // this point. This ensures that this on_message call returns,
1482            // releases the lock and ::init can notice the state change and
1483            // itself return.
1484            break;
1485        }
1486
1487        case OMX_StateLoaded:
1488        {
1489            CHECK_EQ(mState, IDLE_TO_LOADED);
1490
1491            CODEC_LOGV("Now Loaded.");
1492
1493            setState(LOADED);
1494            break;
1495        }
1496
1497        default:
1498        {
1499            CHECK(!"should not be here.");
1500            break;
1501        }
1502    }
1503}
1504
1505// static
1506size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1507    size_t n = 0;
1508    for (size_t i = 0; i < buffers.size(); ++i) {
1509        if (!buffers[i].mOwnedByComponent) {
1510            ++n;
1511        }
1512    }
1513
1514    return n;
1515}
1516
1517status_t OMXCodec::freeBuffersOnPort(
1518        OMX_U32 portIndex, bool onlyThoseWeOwn) {
1519    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1520
1521    status_t stickyErr = OK;
1522
1523    for (size_t i = buffers->size(); i-- > 0;) {
1524        BufferInfo *info = &buffers->editItemAt(i);
1525
1526        if (onlyThoseWeOwn && info->mOwnedByComponent) {
1527            continue;
1528        }
1529
1530        CHECK_EQ(info->mOwnedByComponent, false);
1531
1532        CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
1533
1534        status_t err =
1535            mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
1536
1537        if (err != OK) {
1538            stickyErr = err;
1539        }
1540
1541        if (info->mMediaBuffer != NULL) {
1542            info->mMediaBuffer->setObserver(NULL);
1543
1544            // Make sure nobody but us owns this buffer at this point.
1545            CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1546
1547            info->mMediaBuffer->release();
1548        }
1549
1550        buffers->removeAt(i);
1551    }
1552
1553    CHECK(onlyThoseWeOwn || buffers->isEmpty());
1554
1555    return stickyErr;
1556}
1557
1558void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
1559    CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
1560
1561    CHECK_EQ(mState, EXECUTING);
1562    CHECK_EQ(portIndex, kPortIndexOutput);
1563    setState(RECONFIGURING);
1564
1565    if (mQuirks & kNeedsFlushBeforeDisable) {
1566        if (!flushPortAsync(portIndex)) {
1567            onCmdComplete(OMX_CommandFlush, portIndex);
1568        }
1569    } else {
1570        disablePortAsync(portIndex);
1571    }
1572}
1573
1574bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
1575    CHECK(mState == EXECUTING || mState == RECONFIGURING
1576            || mState == EXECUTING_TO_IDLE);
1577
1578    CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
1579         portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1580         mPortBuffers[portIndex].size());
1581
1582    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1583    mPortStatus[portIndex] = SHUTTING_DOWN;
1584
1585    if ((mQuirks & kRequiresFlushCompleteEmulation)
1586        && countBuffersWeOwn(mPortBuffers[portIndex])
1587                == mPortBuffers[portIndex].size()) {
1588        // No flush is necessary and this component fails to send a
1589        // flush-complete event in this case.
1590
1591        return false;
1592    }
1593
1594    status_t err =
1595        mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
1596    CHECK_EQ(err, OK);
1597
1598    return true;
1599}
1600
1601void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1602    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1603
1604    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1605    mPortStatus[portIndex] = DISABLING;
1606
1607    status_t err =
1608        mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
1609    CHECK_EQ(err, OK);
1610
1611    freeBuffersOnPort(portIndex, true);
1612}
1613
1614void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1615    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1616
1617    CHECK_EQ(mPortStatus[portIndex], DISABLED);
1618    mPortStatus[portIndex] = ENABLING;
1619
1620    status_t err =
1621        mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
1622    CHECK_EQ(err, OK);
1623}
1624
1625void OMXCodec::fillOutputBuffers() {
1626    CHECK_EQ(mState, EXECUTING);
1627
1628    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1629    for (size_t i = 0; i < buffers->size(); ++i) {
1630        fillOutputBuffer(&buffers->editItemAt(i));
1631    }
1632}
1633
1634void OMXCodec::drainInputBuffers() {
1635    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1636
1637    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1638    for (size_t i = 0; i < buffers->size(); ++i) {
1639        drainInputBuffer(&buffers->editItemAt(i));
1640    }
1641}
1642
1643void OMXCodec::drainInputBuffer(BufferInfo *info) {
1644    CHECK_EQ(info->mOwnedByComponent, false);
1645
1646    if (mSignalledEOS) {
1647        return;
1648    }
1649
1650    if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1651        const CodecSpecificData *specific =
1652            mCodecSpecificData[mCodecSpecificDataIndex];
1653
1654        size_t size = specific->mSize;
1655
1656        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
1657                && !(mQuirks & kWantsNALFragments)) {
1658            static const uint8_t kNALStartCode[4] =
1659                    { 0x00, 0x00, 0x00, 0x01 };
1660
1661            CHECK(info->mMem->size() >= specific->mSize + 4);
1662
1663            size += 4;
1664
1665            memcpy(info->mMem->pointer(), kNALStartCode, 4);
1666            memcpy((uint8_t *)info->mMem->pointer() + 4,
1667                   specific->mData, specific->mSize);
1668        } else {
1669            CHECK(info->mMem->size() >= specific->mSize);
1670            memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1671        }
1672
1673        status_t err = mOMX->emptyBuffer(
1674                mNode, info->mBuffer, 0, size,
1675                OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1676                0);
1677        CHECK_EQ(err, OK);
1678
1679        info->mOwnedByComponent = true;
1680
1681        ++mCodecSpecificDataIndex;
1682        return;
1683    }
1684
1685    MediaBuffer *srcBuffer;
1686    status_t err;
1687    if (mSeekTimeUs >= 0) {
1688        MediaSource::ReadOptions options;
1689        options.setSeekTo(mSeekTimeUs);
1690        mSeekTimeUs = -1;
1691
1692        err = mSource->read(&srcBuffer, &options);
1693    } else {
1694        err = mSource->read(&srcBuffer);
1695    }
1696
1697    OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1698    OMX_TICKS timestampUs = 0;
1699    size_t srcLength = 0;
1700
1701    if (err != OK) {
1702        CODEC_LOGV("signalling end of input stream.");
1703        flags |= OMX_BUFFERFLAG_EOS;
1704
1705        mSignalledEOS = true;
1706    } else {
1707        srcLength = srcBuffer->range_length();
1708
1709        if (info->mMem->size() < srcLength) {
1710            LOGE("info->mMem->size() = %d, srcLength = %d",
1711                 info->mMem->size(), srcLength);
1712        }
1713        CHECK(info->mMem->size() >= srcLength);
1714        memcpy(info->mMem->pointer(),
1715               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1716               srcLength);
1717
1718        if (srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs)) {
1719            CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d)",
1720                 info->mBuffer, srcLength);
1721            CODEC_LOGV("Calling emptyBuffer with timestamp %lld us (%.2f secs)",
1722                 timestampUs, timestampUs / 1E6);
1723        }
1724    }
1725
1726    if (srcBuffer != NULL) {
1727        srcBuffer->release();
1728        srcBuffer = NULL;
1729    }
1730
1731    err = mOMX->emptyBuffer(
1732            mNode, info->mBuffer, 0, srcLength,
1733            flags, timestampUs);
1734
1735    if (err != OK) {
1736        setState(ERROR);
1737        return;
1738    }
1739
1740    info->mOwnedByComponent = true;
1741}
1742
1743void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1744    CHECK_EQ(info->mOwnedByComponent, false);
1745
1746    if (mNoMoreOutputData) {
1747        CODEC_LOGV("There is no more output data available, not "
1748             "calling fillOutputBuffer");
1749        return;
1750    }
1751
1752    CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
1753    status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
1754    CHECK_EQ(err, OK);
1755
1756    info->mOwnedByComponent = true;
1757}
1758
1759void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1760    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1761    for (size_t i = 0; i < buffers->size(); ++i) {
1762        if ((*buffers)[i].mBuffer == buffer) {
1763            drainInputBuffer(&buffers->editItemAt(i));
1764            return;
1765        }
1766    }
1767
1768    CHECK(!"should not be here.");
1769}
1770
1771void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1772    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1773    for (size_t i = 0; i < buffers->size(); ++i) {
1774        if ((*buffers)[i].mBuffer == buffer) {
1775            fillOutputBuffer(&buffers->editItemAt(i));
1776            return;
1777        }
1778    }
1779
1780    CHECK(!"should not be here.");
1781}
1782
1783void OMXCodec::setState(State newState) {
1784    mState = newState;
1785    mAsyncCompletion.signal();
1786
1787    // This may cause some spurious wakeups but is necessary to
1788    // unblock the reader if we enter ERROR state.
1789    mBufferFilled.signal();
1790}
1791
1792void OMXCodec::setRawAudioFormat(
1793        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1794    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1795    InitOMXParams(&pcmParams);
1796    pcmParams.nPortIndex = portIndex;
1797
1798    status_t err = mOMX->getParameter(
1799            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1800
1801    CHECK_EQ(err, OK);
1802
1803    pcmParams.nChannels = numChannels;
1804    pcmParams.eNumData = OMX_NumericalDataSigned;
1805    pcmParams.bInterleaved = OMX_TRUE;
1806    pcmParams.nBitPerSample = 16;
1807    pcmParams.nSamplingRate = sampleRate;
1808    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1809
1810    if (numChannels == 1) {
1811        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1812    } else {
1813        CHECK_EQ(numChannels, 2);
1814
1815        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1816        pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1817    }
1818
1819    err = mOMX->setParameter(
1820            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1821
1822    CHECK_EQ(err, OK);
1823}
1824
1825void OMXCodec::setAMRFormat() {
1826    if (!mIsEncoder) {
1827        OMX_AUDIO_PARAM_AMRTYPE def;
1828        InitOMXParams(&def);
1829        def.nPortIndex = kPortIndexInput;
1830
1831        status_t err =
1832            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1833
1834        CHECK_EQ(err, OK);
1835
1836        def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1837        def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1838
1839        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1840        CHECK_EQ(err, OK);
1841    }
1842
1843    ////////////////////////
1844
1845    if (mIsEncoder) {
1846        sp<MetaData> format = mSource->getFormat();
1847        int32_t sampleRate;
1848        int32_t numChannels;
1849        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1850        CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1851
1852        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1853    }
1854}
1855
1856void OMXCodec::setAMRWBFormat() {
1857    if (!mIsEncoder) {
1858        OMX_AUDIO_PARAM_AMRTYPE def;
1859        InitOMXParams(&def);
1860        def.nPortIndex = kPortIndexInput;
1861
1862        status_t err =
1863            mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1864
1865        CHECK_EQ(err, OK);
1866
1867        def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1868        def.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
1869
1870        err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1871        CHECK_EQ(err, OK);
1872    }
1873
1874    ////////////////////////
1875
1876    if (mIsEncoder) {
1877        sp<MetaData> format = mSource->getFormat();
1878        int32_t sampleRate;
1879        int32_t numChannels;
1880        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1881        CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1882
1883        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1884    }
1885}
1886
1887void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
1888    if (mIsEncoder) {
1889        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1890    } else {
1891        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1892        InitOMXParams(&profile);
1893        profile.nPortIndex = kPortIndexInput;
1894
1895        status_t err = mOMX->getParameter(
1896                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1897        CHECK_EQ(err, OK);
1898
1899        profile.nChannels = numChannels;
1900        profile.nSampleRate = sampleRate;
1901        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1902
1903        err = mOMX->setParameter(
1904                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1905        CHECK_EQ(err, OK);
1906    }
1907}
1908
1909void OMXCodec::setImageOutputFormat(
1910        OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
1911    CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
1912
1913#if 0
1914    OMX_INDEXTYPE index;
1915    status_t err = mOMX->get_extension_index(
1916            mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1917    CHECK_EQ(err, OK);
1918
1919    err = mOMX->set_config(mNode, index, &format, sizeof(format));
1920    CHECK_EQ(err, OK);
1921#endif
1922
1923    OMX_PARAM_PORTDEFINITIONTYPE def;
1924    InitOMXParams(&def);
1925    def.nPortIndex = kPortIndexOutput;
1926
1927    status_t err = mOMX->getParameter(
1928            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1929    CHECK_EQ(err, OK);
1930
1931    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1932
1933    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1934
1935    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1936    imageDef->eColorFormat = format;
1937    imageDef->nFrameWidth = width;
1938    imageDef->nFrameHeight = height;
1939
1940    switch (format) {
1941        case OMX_COLOR_FormatYUV420PackedPlanar:
1942        case OMX_COLOR_FormatYUV411Planar:
1943        {
1944            def.nBufferSize = (width * height * 3) / 2;
1945            break;
1946        }
1947
1948        case OMX_COLOR_FormatCbYCrY:
1949        {
1950            def.nBufferSize = width * height * 2;
1951            break;
1952        }
1953
1954        case OMX_COLOR_Format32bitARGB8888:
1955        {
1956            def.nBufferSize = width * height * 4;
1957            break;
1958        }
1959
1960        case OMX_COLOR_Format16bitARGB4444:
1961        case OMX_COLOR_Format16bitARGB1555:
1962        case OMX_COLOR_Format16bitRGB565:
1963        case OMX_COLOR_Format16bitBGR565:
1964        {
1965            def.nBufferSize = width * height * 2;
1966            break;
1967        }
1968
1969        default:
1970            CHECK(!"Should not be here. Unknown color format.");
1971            break;
1972    }
1973
1974    def.nBufferCountActual = def.nBufferCountMin;
1975
1976    err = mOMX->setParameter(
1977            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1978    CHECK_EQ(err, OK);
1979}
1980
1981void OMXCodec::setJPEGInputFormat(
1982        OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
1983    OMX_PARAM_PORTDEFINITIONTYPE def;
1984    InitOMXParams(&def);
1985    def.nPortIndex = kPortIndexInput;
1986
1987    status_t err = mOMX->getParameter(
1988            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1989    CHECK_EQ(err, OK);
1990
1991    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1992    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1993
1994    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1995    imageDef->nFrameWidth = width;
1996    imageDef->nFrameHeight = height;
1997
1998    def.nBufferSize = compressedSize;
1999    def.nBufferCountActual = def.nBufferCountMin;
2000
2001    err = mOMX->setParameter(
2002            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2003    CHECK_EQ(err, OK);
2004}
2005
2006void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
2007    CodecSpecificData *specific =
2008        (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
2009
2010    specific->mSize = size;
2011    memcpy(specific->mData, data, size);
2012
2013    mCodecSpecificData.push(specific);
2014}
2015
2016void OMXCodec::clearCodecSpecificData() {
2017    for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
2018        free(mCodecSpecificData.editItemAt(i));
2019    }
2020    mCodecSpecificData.clear();
2021    mCodecSpecificDataIndex = 0;
2022}
2023
2024status_t OMXCodec::start(MetaData *) {
2025    Mutex::Autolock autoLock(mLock);
2026
2027    if (mState != LOADED) {
2028        return UNKNOWN_ERROR;
2029    }
2030
2031    sp<MetaData> params = new MetaData;
2032    if (mQuirks & kWantsNALFragments) {
2033        params->setInt32(kKeyWantsNALFragments, true);
2034    }
2035    status_t err = mSource->start(params.get());
2036
2037    if (err != OK) {
2038        return err;
2039    }
2040
2041    mCodecSpecificDataIndex = 0;
2042    mInitialBufferSubmit = true;
2043    mSignalledEOS = false;
2044    mNoMoreOutputData = false;
2045    mOutputPortSettingsHaveChanged = false;
2046    mSeekTimeUs = -1;
2047    mFilledBuffers.clear();
2048
2049    return init();
2050}
2051
2052status_t OMXCodec::stop() {
2053    CODEC_LOGV("stop");
2054
2055    Mutex::Autolock autoLock(mLock);
2056
2057    while (isIntermediateState(mState)) {
2058        mAsyncCompletion.wait(mLock);
2059    }
2060
2061    switch (mState) {
2062        case LOADED:
2063        case ERROR:
2064            break;
2065
2066        case EXECUTING:
2067        {
2068            setState(EXECUTING_TO_IDLE);
2069
2070            if (mQuirks & kRequiresFlushBeforeShutdown) {
2071                CODEC_LOGV("This component requires a flush before transitioning "
2072                     "from EXECUTING to IDLE...");
2073
2074                bool emulateInputFlushCompletion =
2075                    !flushPortAsync(kPortIndexInput);
2076
2077                bool emulateOutputFlushCompletion =
2078                    !flushPortAsync(kPortIndexOutput);
2079
2080                if (emulateInputFlushCompletion) {
2081                    onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2082                }
2083
2084                if (emulateOutputFlushCompletion) {
2085                    onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2086                }
2087            } else {
2088                mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2089                mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2090
2091                status_t err =
2092                    mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
2093                CHECK_EQ(err, OK);
2094            }
2095
2096            while (mState != LOADED && mState != ERROR) {
2097                mAsyncCompletion.wait(mLock);
2098            }
2099
2100            break;
2101        }
2102
2103        default:
2104        {
2105            CHECK(!"should not be here.");
2106            break;
2107        }
2108    }
2109
2110    mSource->stop();
2111
2112    return OK;
2113}
2114
2115sp<MetaData> OMXCodec::getFormat() {
2116    Mutex::Autolock autoLock(mLock);
2117
2118    return mOutputFormat;
2119}
2120
2121status_t OMXCodec::read(
2122        MediaBuffer **buffer, const ReadOptions *options) {
2123    *buffer = NULL;
2124
2125    Mutex::Autolock autoLock(mLock);
2126
2127    if (mState != EXECUTING && mState != RECONFIGURING) {
2128        return UNKNOWN_ERROR;
2129    }
2130
2131    bool seeking = false;
2132    int64_t seekTimeUs;
2133    if (options && options->getSeekTo(&seekTimeUs)) {
2134        seeking = true;
2135    }
2136
2137    if (mInitialBufferSubmit) {
2138        mInitialBufferSubmit = false;
2139
2140        if (seeking) {
2141            CHECK(seekTimeUs >= 0);
2142            mSeekTimeUs = seekTimeUs;
2143
2144            // There's no reason to trigger the code below, there's
2145            // nothing to flush yet.
2146            seeking = false;
2147        }
2148
2149        drainInputBuffers();
2150
2151        if (mState == EXECUTING) {
2152            // Otherwise mState == RECONFIGURING and this code will trigger
2153            // after the output port is reenabled.
2154            fillOutputBuffers();
2155        }
2156    }
2157
2158    if (seeking) {
2159        CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
2160
2161        mSignalledEOS = false;
2162        mNoMoreOutputData = false;
2163
2164        CHECK(seekTimeUs >= 0);
2165        mSeekTimeUs = seekTimeUs;
2166
2167        mFilledBuffers.clear();
2168
2169        CHECK_EQ(mState, EXECUTING);
2170
2171        bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
2172        bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
2173
2174        if (emulateInputFlushCompletion) {
2175            onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2176        }
2177
2178        if (emulateOutputFlushCompletion) {
2179            onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2180        }
2181    }
2182
2183    while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
2184        mBufferFilled.wait(mLock);
2185    }
2186
2187    if (mState == ERROR) {
2188        return UNKNOWN_ERROR;
2189    }
2190
2191    if (mFilledBuffers.empty()) {
2192        return ERROR_END_OF_STREAM;
2193    }
2194
2195    if (mOutputPortSettingsHaveChanged) {
2196        mOutputPortSettingsHaveChanged = false;
2197
2198        return INFO_FORMAT_CHANGED;
2199    }
2200
2201    size_t index = *mFilledBuffers.begin();
2202    mFilledBuffers.erase(mFilledBuffers.begin());
2203
2204    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2205    info->mMediaBuffer->add_ref();
2206    *buffer = info->mMediaBuffer;
2207
2208    return OK;
2209}
2210
2211void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
2212    Mutex::Autolock autoLock(mLock);
2213
2214    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2215    for (size_t i = 0; i < buffers->size(); ++i) {
2216        BufferInfo *info = &buffers->editItemAt(i);
2217
2218        if (info->mMediaBuffer == buffer) {
2219            CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
2220            fillOutputBuffer(info);
2221            return;
2222        }
2223    }
2224
2225    CHECK(!"should not be here.");
2226}
2227
2228static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
2229    static const char *kNames[] = {
2230        "OMX_IMAGE_CodingUnused",
2231        "OMX_IMAGE_CodingAutoDetect",
2232        "OMX_IMAGE_CodingJPEG",
2233        "OMX_IMAGE_CodingJPEG2K",
2234        "OMX_IMAGE_CodingEXIF",
2235        "OMX_IMAGE_CodingTIFF",
2236        "OMX_IMAGE_CodingGIF",
2237        "OMX_IMAGE_CodingPNG",
2238        "OMX_IMAGE_CodingLZW",
2239        "OMX_IMAGE_CodingBMP",
2240    };
2241
2242    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2243
2244    if (type < 0 || (size_t)type >= numNames) {
2245        return "UNKNOWN";
2246    } else {
2247        return kNames[type];
2248    }
2249}
2250
2251static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
2252    static const char *kNames[] = {
2253        "OMX_COLOR_FormatUnused",
2254        "OMX_COLOR_FormatMonochrome",
2255        "OMX_COLOR_Format8bitRGB332",
2256        "OMX_COLOR_Format12bitRGB444",
2257        "OMX_COLOR_Format16bitARGB4444",
2258        "OMX_COLOR_Format16bitARGB1555",
2259        "OMX_COLOR_Format16bitRGB565",
2260        "OMX_COLOR_Format16bitBGR565",
2261        "OMX_COLOR_Format18bitRGB666",
2262        "OMX_COLOR_Format18bitARGB1665",
2263        "OMX_COLOR_Format19bitARGB1666",
2264        "OMX_COLOR_Format24bitRGB888",
2265        "OMX_COLOR_Format24bitBGR888",
2266        "OMX_COLOR_Format24bitARGB1887",
2267        "OMX_COLOR_Format25bitARGB1888",
2268        "OMX_COLOR_Format32bitBGRA8888",
2269        "OMX_COLOR_Format32bitARGB8888",
2270        "OMX_COLOR_FormatYUV411Planar",
2271        "OMX_COLOR_FormatYUV411PackedPlanar",
2272        "OMX_COLOR_FormatYUV420Planar",
2273        "OMX_COLOR_FormatYUV420PackedPlanar",
2274        "OMX_COLOR_FormatYUV420SemiPlanar",
2275        "OMX_COLOR_FormatYUV422Planar",
2276        "OMX_COLOR_FormatYUV422PackedPlanar",
2277        "OMX_COLOR_FormatYUV422SemiPlanar",
2278        "OMX_COLOR_FormatYCbYCr",
2279        "OMX_COLOR_FormatYCrYCb",
2280        "OMX_COLOR_FormatCbYCrY",
2281        "OMX_COLOR_FormatCrYCbY",
2282        "OMX_COLOR_FormatYUV444Interleaved",
2283        "OMX_COLOR_FormatRawBayer8bit",
2284        "OMX_COLOR_FormatRawBayer10bit",
2285        "OMX_COLOR_FormatRawBayer8bitcompressed",
2286        "OMX_COLOR_FormatL2",
2287        "OMX_COLOR_FormatL4",
2288        "OMX_COLOR_FormatL8",
2289        "OMX_COLOR_FormatL16",
2290        "OMX_COLOR_FormatL24",
2291        "OMX_COLOR_FormatL32",
2292        "OMX_COLOR_FormatYUV420PackedSemiPlanar",
2293        "OMX_COLOR_FormatYUV422PackedSemiPlanar",
2294        "OMX_COLOR_Format18BitBGR666",
2295        "OMX_COLOR_Format24BitARGB6666",
2296        "OMX_COLOR_Format24BitABGR6666",
2297    };
2298
2299    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2300
2301    if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
2302        return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
2303    } else if (type < 0 || (size_t)type >= numNames) {
2304        return "UNKNOWN";
2305    } else {
2306        return kNames[type];
2307    }
2308}
2309
2310static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
2311    static const char *kNames[] = {
2312        "OMX_VIDEO_CodingUnused",
2313        "OMX_VIDEO_CodingAutoDetect",
2314        "OMX_VIDEO_CodingMPEG2",
2315        "OMX_VIDEO_CodingH263",
2316        "OMX_VIDEO_CodingMPEG4",
2317        "OMX_VIDEO_CodingWMV",
2318        "OMX_VIDEO_CodingRV",
2319        "OMX_VIDEO_CodingAVC",
2320        "OMX_VIDEO_CodingMJPEG",
2321    };
2322
2323    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2324
2325    if (type < 0 || (size_t)type >= numNames) {
2326        return "UNKNOWN";
2327    } else {
2328        return kNames[type];
2329    }
2330}
2331
2332static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2333    static const char *kNames[] = {
2334        "OMX_AUDIO_CodingUnused",
2335        "OMX_AUDIO_CodingAutoDetect",
2336        "OMX_AUDIO_CodingPCM",
2337        "OMX_AUDIO_CodingADPCM",
2338        "OMX_AUDIO_CodingAMR",
2339        "OMX_AUDIO_CodingGSMFR",
2340        "OMX_AUDIO_CodingGSMEFR",
2341        "OMX_AUDIO_CodingGSMHR",
2342        "OMX_AUDIO_CodingPDCFR",
2343        "OMX_AUDIO_CodingPDCEFR",
2344        "OMX_AUDIO_CodingPDCHR",
2345        "OMX_AUDIO_CodingTDMAFR",
2346        "OMX_AUDIO_CodingTDMAEFR",
2347        "OMX_AUDIO_CodingQCELP8",
2348        "OMX_AUDIO_CodingQCELP13",
2349        "OMX_AUDIO_CodingEVRC",
2350        "OMX_AUDIO_CodingSMV",
2351        "OMX_AUDIO_CodingG711",
2352        "OMX_AUDIO_CodingG723",
2353        "OMX_AUDIO_CodingG726",
2354        "OMX_AUDIO_CodingG729",
2355        "OMX_AUDIO_CodingAAC",
2356        "OMX_AUDIO_CodingMP3",
2357        "OMX_AUDIO_CodingSBC",
2358        "OMX_AUDIO_CodingVORBIS",
2359        "OMX_AUDIO_CodingWMA",
2360        "OMX_AUDIO_CodingRA",
2361        "OMX_AUDIO_CodingMIDI",
2362    };
2363
2364    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2365
2366    if (type < 0 || (size_t)type >= numNames) {
2367        return "UNKNOWN";
2368    } else {
2369        return kNames[type];
2370    }
2371}
2372
2373static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2374    static const char *kNames[] = {
2375        "OMX_AUDIO_PCMModeLinear",
2376        "OMX_AUDIO_PCMModeALaw",
2377        "OMX_AUDIO_PCMModeMULaw",
2378    };
2379
2380    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2381
2382    if (type < 0 || (size_t)type >= numNames) {
2383        return "UNKNOWN";
2384    } else {
2385        return kNames[type];
2386    }
2387}
2388
2389static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
2390    static const char *kNames[] = {
2391        "OMX_AUDIO_AMRBandModeUnused",
2392        "OMX_AUDIO_AMRBandModeNB0",
2393        "OMX_AUDIO_AMRBandModeNB1",
2394        "OMX_AUDIO_AMRBandModeNB2",
2395        "OMX_AUDIO_AMRBandModeNB3",
2396        "OMX_AUDIO_AMRBandModeNB4",
2397        "OMX_AUDIO_AMRBandModeNB5",
2398        "OMX_AUDIO_AMRBandModeNB6",
2399        "OMX_AUDIO_AMRBandModeNB7",
2400        "OMX_AUDIO_AMRBandModeWB0",
2401        "OMX_AUDIO_AMRBandModeWB1",
2402        "OMX_AUDIO_AMRBandModeWB2",
2403        "OMX_AUDIO_AMRBandModeWB3",
2404        "OMX_AUDIO_AMRBandModeWB4",
2405        "OMX_AUDIO_AMRBandModeWB5",
2406        "OMX_AUDIO_AMRBandModeWB6",
2407        "OMX_AUDIO_AMRBandModeWB7",
2408        "OMX_AUDIO_AMRBandModeWB8",
2409    };
2410
2411    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2412
2413    if (type < 0 || (size_t)type >= numNames) {
2414        return "UNKNOWN";
2415    } else {
2416        return kNames[type];
2417    }
2418}
2419
2420static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
2421    static const char *kNames[] = {
2422        "OMX_AUDIO_AMRFrameFormatConformance",
2423        "OMX_AUDIO_AMRFrameFormatIF1",
2424        "OMX_AUDIO_AMRFrameFormatIF2",
2425        "OMX_AUDIO_AMRFrameFormatFSF",
2426        "OMX_AUDIO_AMRFrameFormatRTPPayload",
2427        "OMX_AUDIO_AMRFrameFormatITU",
2428    };
2429
2430    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2431
2432    if (type < 0 || (size_t)type >= numNames) {
2433        return "UNKNOWN";
2434    } else {
2435        return kNames[type];
2436    }
2437}
2438
2439void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2440    OMX_PARAM_PORTDEFINITIONTYPE def;
2441    InitOMXParams(&def);
2442    def.nPortIndex = portIndex;
2443
2444    status_t err = mOMX->getParameter(
2445            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2446    CHECK_EQ(err, OK);
2447
2448    printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2449
2450    CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2451          || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
2452
2453    printf("  nBufferCountActual = %ld\n", def.nBufferCountActual);
2454    printf("  nBufferCountMin = %ld\n", def.nBufferCountMin);
2455    printf("  nBufferSize = %ld\n", def.nBufferSize);
2456
2457    switch (def.eDomain) {
2458        case OMX_PortDomainImage:
2459        {
2460            const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2461
2462            printf("\n");
2463            printf("  // Image\n");
2464            printf("  nFrameWidth = %ld\n", imageDef->nFrameWidth);
2465            printf("  nFrameHeight = %ld\n", imageDef->nFrameHeight);
2466            printf("  nStride = %ld\n", imageDef->nStride);
2467
2468            printf("  eCompressionFormat = %s\n",
2469                   imageCompressionFormatString(imageDef->eCompressionFormat));
2470
2471            printf("  eColorFormat = %s\n",
2472                   colorFormatString(imageDef->eColorFormat));
2473
2474            break;
2475        }
2476
2477        case OMX_PortDomainVideo:
2478        {
2479            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2480
2481            printf("\n");
2482            printf("  // Video\n");
2483            printf("  nFrameWidth = %ld\n", videoDef->nFrameWidth);
2484            printf("  nFrameHeight = %ld\n", videoDef->nFrameHeight);
2485            printf("  nStride = %ld\n", videoDef->nStride);
2486
2487            printf("  eCompressionFormat = %s\n",
2488                   videoCompressionFormatString(videoDef->eCompressionFormat));
2489
2490            printf("  eColorFormat = %s\n",
2491                   colorFormatString(videoDef->eColorFormat));
2492
2493            break;
2494        }
2495
2496        case OMX_PortDomainAudio:
2497        {
2498            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2499
2500            printf("\n");
2501            printf("  // Audio\n");
2502            printf("  eEncoding = %s\n",
2503                   audioCodingTypeString(audioDef->eEncoding));
2504
2505            if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2506                OMX_AUDIO_PARAM_PCMMODETYPE params;
2507                InitOMXParams(&params);
2508                params.nPortIndex = portIndex;
2509
2510                err = mOMX->getParameter(
2511                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2512                CHECK_EQ(err, OK);
2513
2514                printf("  nSamplingRate = %ld\n", params.nSamplingRate);
2515                printf("  nChannels = %ld\n", params.nChannels);
2516                printf("  bInterleaved = %d\n", params.bInterleaved);
2517                printf("  nBitPerSample = %ld\n", params.nBitPerSample);
2518
2519                printf("  eNumData = %s\n",
2520                       params.eNumData == OMX_NumericalDataSigned
2521                        ? "signed" : "unsigned");
2522
2523                printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
2524            } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
2525                OMX_AUDIO_PARAM_AMRTYPE amr;
2526                InitOMXParams(&amr);
2527                amr.nPortIndex = portIndex;
2528
2529                err = mOMX->getParameter(
2530                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2531                CHECK_EQ(err, OK);
2532
2533                printf("  nChannels = %ld\n", amr.nChannels);
2534                printf("  eAMRBandMode = %s\n",
2535                        amrBandModeString(amr.eAMRBandMode));
2536                printf("  eAMRFrameFormat = %s\n",
2537                        amrFrameFormatString(amr.eAMRFrameFormat));
2538            }
2539
2540            break;
2541        }
2542
2543        default:
2544        {
2545            printf("  // Unknown\n");
2546            break;
2547        }
2548    }
2549
2550    printf("}\n");
2551}
2552
2553void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
2554    mOutputFormat = new MetaData;
2555    mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
2556
2557    OMX_PARAM_PORTDEFINITIONTYPE def;
2558    InitOMXParams(&def);
2559    def.nPortIndex = kPortIndexOutput;
2560
2561    status_t err = mOMX->getParameter(
2562            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2563    CHECK_EQ(err, OK);
2564
2565    switch (def.eDomain) {
2566        case OMX_PortDomainImage:
2567        {
2568            OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2569            CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2570
2571            mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
2572            mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
2573            mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
2574            mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
2575            break;
2576        }
2577
2578        case OMX_PortDomainAudio:
2579        {
2580            OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
2581
2582            if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
2583                OMX_AUDIO_PARAM_PCMMODETYPE params;
2584                InitOMXParams(&params);
2585                params.nPortIndex = kPortIndexOutput;
2586
2587                err = mOMX->getParameter(
2588                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2589                CHECK_EQ(err, OK);
2590
2591                CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
2592                CHECK_EQ(params.nBitPerSample, 16);
2593                CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
2594
2595                int32_t numChannels, sampleRate;
2596                inputFormat->findInt32(kKeyChannelCount, &numChannels);
2597                inputFormat->findInt32(kKeySampleRate, &sampleRate);
2598
2599                if ((OMX_U32)numChannels != params.nChannels) {
2600                    LOGW("Codec outputs a different number of channels than "
2601                         "the input stream contains.");
2602                }
2603
2604                mOutputFormat->setCString(
2605                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
2606
2607                // Use the codec-advertised number of channels, as some
2608                // codecs appear to output stereo even if the input data is
2609                // mono.
2610                mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
2611
2612                // The codec-reported sampleRate is not reliable...
2613                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
2614            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
2615                OMX_AUDIO_PARAM_AMRTYPE amr;
2616                InitOMXParams(&amr);
2617                amr.nPortIndex = kPortIndexOutput;
2618
2619                err = mOMX->getParameter(
2620                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2621                CHECK_EQ(err, OK);
2622
2623                CHECK_EQ(amr.nChannels, 1);
2624                mOutputFormat->setInt32(kKeyChannelCount, 1);
2625
2626                if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
2627                    && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
2628                    mOutputFormat->setCString(
2629                            kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
2630                    mOutputFormat->setInt32(kKeySampleRate, 8000);
2631                } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
2632                            && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
2633                    mOutputFormat->setCString(
2634                            kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
2635                    mOutputFormat->setInt32(kKeySampleRate, 16000);
2636                } else {
2637                    CHECK(!"Unknown AMR band mode.");
2638                }
2639            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
2640                mOutputFormat->setCString(
2641                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
2642            } else {
2643                CHECK(!"Should not be here. Unknown audio encoding.");
2644            }
2645            break;
2646        }
2647
2648        case OMX_PortDomainVideo:
2649        {
2650            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2651
2652            if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
2653                mOutputFormat->setCString(
2654                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
2655            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
2656                mOutputFormat->setCString(
2657                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
2658            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
2659                mOutputFormat->setCString(
2660                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
2661            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
2662                mOutputFormat->setCString(
2663                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
2664            } else {
2665                CHECK(!"Unknown compression format.");
2666            }
2667
2668            if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
2669                // This component appears to be lying to me.
2670                mOutputFormat->setInt32(
2671                        kKeyWidth, (video_def->nFrameWidth + 15) & -16);
2672                mOutputFormat->setInt32(
2673                        kKeyHeight, (video_def->nFrameHeight + 15) & -16);
2674            } else {
2675                mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
2676                mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
2677            }
2678
2679            mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
2680            break;
2681        }
2682
2683        default:
2684        {
2685            CHECK(!"should not be here, neither audio nor video.");
2686            break;
2687        }
2688    }
2689}
2690
2691////////////////////////////////////////////////////////////////////////////////
2692
2693status_t QueryCodecs(
2694        const sp<IOMX> &omx,
2695        const char *mime, bool queryDecoders,
2696        Vector<CodecCapabilities> *results) {
2697    results->clear();
2698
2699    for (int index = 0;; ++index) {
2700        const char *componentName;
2701
2702        if (!queryDecoders) {
2703            componentName = GetCodec(
2704                    kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
2705                    mime, index);
2706        } else {
2707            componentName = GetCodec(
2708                    kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
2709                    mime, index);
2710        }
2711
2712        if (!componentName) {
2713            return OK;
2714        }
2715
2716        sp<OMXCodecObserver> observer = new OMXCodecObserver;
2717        IOMX::node_id node;
2718        status_t err = omx->allocateNode(componentName, observer, &node);
2719
2720        if (err != OK) {
2721            continue;
2722        }
2723
2724        OMXCodec::setComponentRole(omx, node, queryDecoders, mime);
2725
2726        results->push();
2727        CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
2728        caps->mComponentName = componentName;
2729
2730        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
2731        InitOMXParams(&param);
2732
2733        param.nPortIndex = queryDecoders ? 0 : 1;
2734
2735        for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
2736            err = omx->getParameter(
2737                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
2738                    &param, sizeof(param));
2739
2740            if (err != OK) {
2741                break;
2742            }
2743
2744            CodecProfileLevel profileLevel;
2745            profileLevel.mProfile = param.eProfile;
2746            profileLevel.mLevel = param.eLevel;
2747
2748            caps->mProfileLevels.push(profileLevel);
2749        }
2750
2751        CHECK_EQ(omx->freeNode(node), OK);
2752    }
2753}
2754
2755}  // namespace android
2756