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