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