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