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