OMXCodec.cpp revision 956c553ab0ce72f8074ad0fda2ffd66a0305700c
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.eProfile = OMX_VIDEO_AVCProfileBaseline;
936    h264type.eLevel = OMX_VIDEO_AVCLevel1b;
937    h264type.bFrameMBsOnly = OMX_TRUE;
938    h264type.bMBAFF = OMX_FALSE;
939    h264type.bEntropyCodingCABAC = OMX_FALSE;
940    h264type.bWeightedPPrediction = OMX_FALSE;
941    h264type.bconstIpred = OMX_FALSE;
942    h264type.bDirect8x8Inference = OMX_FALSE;
943    h264type.bDirectSpatialTemporal = OMX_FALSE;
944    h264type.nCabacInitIdc = 0;
945    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
946
947    err = mOMX->setParameter(
948            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
949    CHECK_EQ(err, OK);
950
951    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
952    InitOMXParams(&bitrateType);
953    bitrateType.nPortIndex = kPortIndexOutput;
954
955    err = mOMX->getParameter(
956            mNode, OMX_IndexParamVideoBitrate,
957            &bitrateType, sizeof(bitrateType));
958    CHECK_EQ(err, OK);
959
960    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
961    bitrateType.nTargetBitrate = 3000000;
962
963    err = mOMX->setParameter(
964            mNode, OMX_IndexParamVideoBitrate,
965            &bitrateType, sizeof(bitrateType));
966    CHECK_EQ(err, OK);
967
968    return OK;
969}
970
971status_t OMXCodec::setVideoOutputFormat(
972        const char *mime, OMX_U32 width, OMX_U32 height) {
973    CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
974
975    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
976    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
977        compressionFormat = OMX_VIDEO_CodingAVC;
978    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
979        compressionFormat = OMX_VIDEO_CodingMPEG4;
980    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
981        compressionFormat = OMX_VIDEO_CodingH263;
982    } else {
983        LOGE("Not a supported video mime type: %s", mime);
984        CHECK(!"Should not be here. Not a supported video mime type.");
985    }
986
987    status_t err = setVideoPortFormatType(
988            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
989
990    if (err != OK) {
991        return err;
992    }
993
994#if 1
995    {
996        OMX_VIDEO_PARAM_PORTFORMATTYPE format;
997        InitOMXParams(&format);
998        format.nPortIndex = kPortIndexOutput;
999        format.nIndex = 0;
1000
1001        status_t err = mOMX->getParameter(
1002                mNode, OMX_IndexParamVideoPortFormat,
1003                &format, sizeof(format));
1004        CHECK_EQ(err, OK);
1005        CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
1006
1007        static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1008
1009        CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1010               || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1011               || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1012               || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1013
1014        err = mOMX->setParameter(
1015                mNode, OMX_IndexParamVideoPortFormat,
1016                &format, sizeof(format));
1017
1018        if (err != OK) {
1019            return err;
1020        }
1021    }
1022#endif
1023
1024    OMX_PARAM_PORTDEFINITIONTYPE def;
1025    InitOMXParams(&def);
1026    def.nPortIndex = kPortIndexInput;
1027
1028    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1029
1030    err = mOMX->getParameter(
1031            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1032
1033    CHECK_EQ(err, OK);
1034
1035#if 1
1036    // XXX Need a (much) better heuristic to compute input buffer sizes.
1037    const size_t X = 64 * 1024;
1038    if (def.nBufferSize < X) {
1039        def.nBufferSize = X;
1040    }
1041#endif
1042
1043    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1044
1045    video_def->nFrameWidth = width;
1046    video_def->nFrameHeight = height;
1047
1048    video_def->eCompressionFormat = compressionFormat;
1049    video_def->eColorFormat = OMX_COLOR_FormatUnused;
1050
1051    err = mOMX->setParameter(
1052            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1053
1054    if (err != OK) {
1055        return err;
1056    }
1057
1058    ////////////////////////////////////////////////////////////////////////////
1059
1060    InitOMXParams(&def);
1061    def.nPortIndex = kPortIndexOutput;
1062
1063    err = mOMX->getParameter(
1064            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1065    CHECK_EQ(err, OK);
1066    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
1067
1068#if 0
1069    def.nBufferSize =
1070        (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2;  // YUV420
1071#endif
1072
1073    video_def->nFrameWidth = width;
1074    video_def->nFrameHeight = height;
1075
1076    err = mOMX->setParameter(
1077            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1078
1079    return err;
1080}
1081
1082OMXCodec::OMXCodec(
1083        const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
1084        bool isEncoder,
1085        const char *mime,
1086        const char *componentName,
1087        const sp<MediaSource> &source)
1088    : mOMX(omx),
1089      mOMXLivesLocally(omx->livesLocally(getpid())),
1090      mNode(node),
1091      mQuirks(quirks),
1092      mIsEncoder(isEncoder),
1093      mMIME(strdup(mime)),
1094      mComponentName(strdup(componentName)),
1095      mSource(source),
1096      mCodecSpecificDataIndex(0),
1097      mState(LOADED),
1098      mInitialBufferSubmit(true),
1099      mSignalledEOS(false),
1100      mNoMoreOutputData(false),
1101      mOutputPortSettingsHaveChanged(false),
1102      mSeekTimeUs(-1),
1103      mLeftOverBuffer(NULL) {
1104    mPortStatus[kPortIndexInput] = ENABLED;
1105    mPortStatus[kPortIndexOutput] = ENABLED;
1106
1107    setComponentRole();
1108}
1109
1110// static
1111void OMXCodec::setComponentRole(
1112        const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
1113        const char *mime) {
1114    struct MimeToRole {
1115        const char *mime;
1116        const char *decoderRole;
1117        const char *encoderRole;
1118    };
1119
1120    static const MimeToRole kMimeToRole[] = {
1121        { MEDIA_MIMETYPE_AUDIO_MPEG,
1122            "audio_decoder.mp3", "audio_encoder.mp3" },
1123        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1124            "audio_decoder.amrnb", "audio_encoder.amrnb" },
1125        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1126            "audio_decoder.amrwb", "audio_encoder.amrwb" },
1127        { MEDIA_MIMETYPE_AUDIO_AAC,
1128            "audio_decoder.aac", "audio_encoder.aac" },
1129        { MEDIA_MIMETYPE_VIDEO_AVC,
1130            "video_decoder.avc", "video_encoder.avc" },
1131        { MEDIA_MIMETYPE_VIDEO_MPEG4,
1132            "video_decoder.mpeg4", "video_encoder.mpeg4" },
1133        { MEDIA_MIMETYPE_VIDEO_H263,
1134            "video_decoder.h263", "video_encoder.h263" },
1135    };
1136
1137    static const size_t kNumMimeToRole =
1138        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1139
1140    size_t i;
1141    for (i = 0; i < kNumMimeToRole; ++i) {
1142        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1143            break;
1144        }
1145    }
1146
1147    if (i == kNumMimeToRole) {
1148        return;
1149    }
1150
1151    const char *role =
1152        isEncoder ? kMimeToRole[i].encoderRole
1153                  : kMimeToRole[i].decoderRole;
1154
1155    if (role != NULL) {
1156        OMX_PARAM_COMPONENTROLETYPE roleParams;
1157        InitOMXParams(&roleParams);
1158
1159        strncpy((char *)roleParams.cRole,
1160                role, OMX_MAX_STRINGNAME_SIZE - 1);
1161
1162        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1163
1164        status_t err = omx->setParameter(
1165                node, OMX_IndexParamStandardComponentRole,
1166                &roleParams, sizeof(roleParams));
1167
1168        if (err != OK) {
1169            LOGW("Failed to set standard component role '%s'.", role);
1170        }
1171    }
1172}
1173
1174void OMXCodec::setComponentRole() {
1175    setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
1176}
1177
1178OMXCodec::~OMXCodec() {
1179    CHECK(mState == LOADED || mState == ERROR);
1180
1181    status_t err = mOMX->freeNode(mNode);
1182    CHECK_EQ(err, OK);
1183
1184    mNode = NULL;
1185    setState(DEAD);
1186
1187    clearCodecSpecificData();
1188
1189    free(mComponentName);
1190    mComponentName = NULL;
1191
1192    free(mMIME);
1193    mMIME = NULL;
1194}
1195
1196status_t OMXCodec::init() {
1197    // mLock is held.
1198
1199    CHECK_EQ(mState, LOADED);
1200
1201    status_t err;
1202    if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
1203        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1204        CHECK_EQ(err, OK);
1205        setState(LOADED_TO_IDLE);
1206    }
1207
1208    err = allocateBuffers();
1209    CHECK_EQ(err, OK);
1210
1211    if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
1212        err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1213        CHECK_EQ(err, OK);
1214
1215        setState(LOADED_TO_IDLE);
1216    }
1217
1218    while (mState != EXECUTING && mState != ERROR) {
1219        mAsyncCompletion.wait(mLock);
1220    }
1221
1222    return mState == ERROR ? UNKNOWN_ERROR : OK;
1223}
1224
1225// static
1226bool OMXCodec::isIntermediateState(State state) {
1227    return state == LOADED_TO_IDLE
1228        || state == IDLE_TO_EXECUTING
1229        || state == EXECUTING_TO_IDLE
1230        || state == IDLE_TO_LOADED
1231        || state == RECONFIGURING;
1232}
1233
1234status_t OMXCodec::allocateBuffers() {
1235    status_t err = allocateBuffersOnPort(kPortIndexInput);
1236
1237    if (err != OK) {
1238        return err;
1239    }
1240
1241    return allocateBuffersOnPort(kPortIndexOutput);
1242}
1243
1244status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
1245    OMX_PARAM_PORTDEFINITIONTYPE def;
1246    InitOMXParams(&def);
1247    def.nPortIndex = portIndex;
1248
1249    status_t err = mOMX->getParameter(
1250            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1251
1252    if (err != OK) {
1253        return err;
1254    }
1255
1256    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
1257    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
1258
1259    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
1260        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
1261        CHECK(mem.get() != NULL);
1262
1263        BufferInfo info;
1264        info.mData = NULL;
1265        info.mSize = def.nBufferSize;
1266
1267        IOMX::buffer_id buffer;
1268        if (portIndex == kPortIndexInput
1269                && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
1270            if (mOMXLivesLocally) {
1271                mem.clear();
1272
1273                err = mOMX->allocateBuffer(
1274                        mNode, portIndex, def.nBufferSize, &buffer,
1275                        &info.mData);
1276            } else {
1277                err = mOMX->allocateBufferWithBackup(
1278                        mNode, portIndex, mem, &buffer);
1279            }
1280        } else if (portIndex == kPortIndexOutput
1281                && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
1282            if (mOMXLivesLocally) {
1283                mem.clear();
1284
1285                err = mOMX->allocateBuffer(
1286                        mNode, portIndex, def.nBufferSize, &buffer,
1287                        &info.mData);
1288            } else {
1289                err = mOMX->allocateBufferWithBackup(
1290                        mNode, portIndex, mem, &buffer);
1291            }
1292        } else {
1293            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
1294        }
1295
1296        if (err != OK) {
1297            LOGE("allocate_buffer_with_backup failed");
1298            return err;
1299        }
1300
1301        if (mem != NULL) {
1302            info.mData = mem->pointer();
1303        }
1304
1305        info.mBuffer = buffer;
1306        info.mOwnedByComponent = false;
1307        info.mMem = mem;
1308        info.mMediaBuffer = NULL;
1309
1310        if (portIndex == kPortIndexOutput) {
1311            if (!(mOMXLivesLocally
1312                        && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
1313                        && (mQuirks & kDefersOutputBufferAllocation))) {
1314                // If the node does not fill in the buffer ptr at this time,
1315                // we will defer creating the MediaBuffer until receiving
1316                // the first FILL_BUFFER_DONE notification instead.
1317                info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
1318                info.mMediaBuffer->setObserver(this);
1319            }
1320        }
1321
1322        mPortBuffers[portIndex].push(info);
1323
1324        CODEC_LOGV("allocated buffer %p on %s port", buffer,
1325             portIndex == kPortIndexInput ? "input" : "output");
1326    }
1327
1328    // dumpPortStatus(portIndex);
1329
1330    return OK;
1331}
1332
1333void OMXCodec::on_message(const omx_message &msg) {
1334    Mutex::Autolock autoLock(mLock);
1335
1336    switch (msg.type) {
1337        case omx_message::EVENT:
1338        {
1339            onEvent(
1340                 msg.u.event_data.event, msg.u.event_data.data1,
1341                 msg.u.event_data.data2);
1342
1343            break;
1344        }
1345
1346        case omx_message::EMPTY_BUFFER_DONE:
1347        {
1348            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1349
1350            CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
1351
1352            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1353            size_t i = 0;
1354            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1355                ++i;
1356            }
1357
1358            CHECK(i < buffers->size());
1359            if (!(*buffers)[i].mOwnedByComponent) {
1360                LOGW("We already own input buffer %p, yet received "
1361                     "an EMPTY_BUFFER_DONE.", buffer);
1362            }
1363
1364            buffers->editItemAt(i).mOwnedByComponent = false;
1365
1366            if (mPortStatus[kPortIndexInput] == DISABLING) {
1367                CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
1368
1369                status_t err =
1370                    mOMX->freeBuffer(mNode, kPortIndexInput, buffer);
1371                CHECK_EQ(err, OK);
1372
1373                buffers->removeAt(i);
1374            } else if (mState != ERROR
1375                    && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
1376                CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
1377                drainInputBuffer(&buffers->editItemAt(i));
1378            }
1379            break;
1380        }
1381
1382        case omx_message::FILL_BUFFER_DONE:
1383        {
1384            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
1385            OMX_U32 flags = msg.u.extended_buffer_data.flags;
1386
1387            CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
1388                 buffer,
1389                 msg.u.extended_buffer_data.range_length,
1390                 flags,
1391                 msg.u.extended_buffer_data.timestamp,
1392                 msg.u.extended_buffer_data.timestamp / 1E6);
1393
1394            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1395            size_t i = 0;
1396            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
1397                ++i;
1398            }
1399
1400            CHECK(i < buffers->size());
1401            BufferInfo *info = &buffers->editItemAt(i);
1402
1403            if (!info->mOwnedByComponent) {
1404                LOGW("We already own output buffer %p, yet received "
1405                     "a FILL_BUFFER_DONE.", buffer);
1406            }
1407
1408            info->mOwnedByComponent = false;
1409
1410            if (mPortStatus[kPortIndexOutput] == DISABLING) {
1411                CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
1412
1413                status_t err =
1414                    mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
1415                CHECK_EQ(err, OK);
1416
1417                buffers->removeAt(i);
1418#if 0
1419            } else if (mPortStatus[kPortIndexOutput] == ENABLED
1420                       && (flags & OMX_BUFFERFLAG_EOS)) {
1421                CODEC_LOGV("No more output data.");
1422                mNoMoreOutputData = true;
1423                mBufferFilled.signal();
1424#endif
1425            } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
1426                CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1427
1428                if (info->mMediaBuffer == NULL) {
1429                    CHECK(mOMXLivesLocally);
1430                    CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
1431                    CHECK(mQuirks & kDefersOutputBufferAllocation);
1432
1433                    // The qcom video decoders on Nexus don't actually allocate
1434                    // output buffer memory on a call to OMX_AllocateBuffer
1435                    // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
1436                    // structure is only filled in later.
1437
1438                    info->mMediaBuffer = new MediaBuffer(
1439                            msg.u.extended_buffer_data.data_ptr,
1440                            info->mSize);
1441                    info->mMediaBuffer->setObserver(this);
1442                }
1443
1444                MediaBuffer *buffer = info->mMediaBuffer;
1445
1446                buffer->set_range(
1447                        msg.u.extended_buffer_data.range_offset,
1448                        msg.u.extended_buffer_data.range_length);
1449
1450                buffer->meta_data()->clear();
1451
1452                buffer->meta_data()->setInt64(
1453                        kKeyTime, msg.u.extended_buffer_data.timestamp);
1454
1455                if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
1456                    buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
1457                }
1458                if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
1459                    buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
1460                }
1461
1462                buffer->meta_data()->setPointer(
1463                        kKeyPlatformPrivate,
1464                        msg.u.extended_buffer_data.platform_private);
1465
1466                buffer->meta_data()->setPointer(
1467                        kKeyBufferID,
1468                        msg.u.extended_buffer_data.buffer);
1469
1470                mFilledBuffers.push_back(i);
1471                mBufferFilled.signal();
1472
1473                if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
1474                    CODEC_LOGV("No more output data.");
1475                    mNoMoreOutputData = true;
1476                }
1477            }
1478
1479            break;
1480        }
1481
1482        default:
1483        {
1484            CHECK(!"should not be here.");
1485            break;
1486        }
1487    }
1488}
1489
1490void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1491    switch (event) {
1492        case OMX_EventCmdComplete:
1493        {
1494            onCmdComplete((OMX_COMMANDTYPE)data1, data2);
1495            break;
1496        }
1497
1498        case OMX_EventError:
1499        {
1500            LOGE("ERROR(0x%08lx, %ld)", data1, data2);
1501
1502            setState(ERROR);
1503            break;
1504        }
1505
1506        case OMX_EventPortSettingsChanged:
1507        {
1508            onPortSettingsChanged(data1);
1509            break;
1510        }
1511
1512#if 0
1513        case OMX_EventBufferFlag:
1514        {
1515            CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
1516
1517            if (data1 == kPortIndexOutput) {
1518                mNoMoreOutputData = true;
1519            }
1520            break;
1521        }
1522#endif
1523
1524        default:
1525        {
1526            CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
1527            break;
1528        }
1529    }
1530}
1531
1532// Has the format changed in any way that the client would have to be aware of?
1533static bool formatHasNotablyChanged(
1534        const sp<MetaData> &from, const sp<MetaData> &to) {
1535    if (from.get() == NULL && to.get() == NULL) {
1536        return false;
1537    }
1538
1539    if ((from.get() == NULL && to.get() != NULL)
1540        || (from.get() != NULL && to.get() == NULL)) {
1541        return true;
1542    }
1543
1544    const char *mime_from, *mime_to;
1545    CHECK(from->findCString(kKeyMIMEType, &mime_from));
1546    CHECK(to->findCString(kKeyMIMEType, &mime_to));
1547
1548    if (strcasecmp(mime_from, mime_to)) {
1549        return true;
1550    }
1551
1552    if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
1553        int32_t colorFormat_from, colorFormat_to;
1554        CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
1555        CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
1556
1557        if (colorFormat_from != colorFormat_to) {
1558            return true;
1559        }
1560
1561        int32_t width_from, width_to;
1562        CHECK(from->findInt32(kKeyWidth, &width_from));
1563        CHECK(to->findInt32(kKeyWidth, &width_to));
1564
1565        if (width_from != width_to) {
1566            return true;
1567        }
1568
1569        int32_t height_from, height_to;
1570        CHECK(from->findInt32(kKeyHeight, &height_from));
1571        CHECK(to->findInt32(kKeyHeight, &height_to));
1572
1573        if (height_from != height_to) {
1574            return true;
1575        }
1576    } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
1577        int32_t numChannels_from, numChannels_to;
1578        CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
1579        CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
1580
1581        if (numChannels_from != numChannels_to) {
1582            return true;
1583        }
1584
1585        int32_t sampleRate_from, sampleRate_to;
1586        CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
1587        CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
1588
1589        if (sampleRate_from != sampleRate_to) {
1590            return true;
1591        }
1592    }
1593
1594    return false;
1595}
1596
1597void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
1598    switch (cmd) {
1599        case OMX_CommandStateSet:
1600        {
1601            onStateChange((OMX_STATETYPE)data);
1602            break;
1603        }
1604
1605        case OMX_CommandPortDisable:
1606        {
1607            OMX_U32 portIndex = data;
1608            CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
1609
1610            CHECK(mState == EXECUTING || mState == RECONFIGURING);
1611            CHECK_EQ(mPortStatus[portIndex], DISABLING);
1612            CHECK_EQ(mPortBuffers[portIndex].size(), 0);
1613
1614            mPortStatus[portIndex] = DISABLED;
1615
1616            if (mState == RECONFIGURING) {
1617                CHECK_EQ(portIndex, kPortIndexOutput);
1618
1619                sp<MetaData> oldOutputFormat = mOutputFormat;
1620                initOutputFormat(mSource->getFormat());
1621
1622                // Don't notify clients if the output port settings change
1623                // wasn't of importance to them, i.e. it may be that just the
1624                // number of buffers has changed and nothing else.
1625                mOutputPortSettingsHaveChanged =
1626                    formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
1627
1628                enablePortAsync(portIndex);
1629
1630                status_t err = allocateBuffersOnPort(portIndex);
1631                CHECK_EQ(err, OK);
1632            }
1633            break;
1634        }
1635
1636        case OMX_CommandPortEnable:
1637        {
1638            OMX_U32 portIndex = data;
1639            CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
1640
1641            CHECK(mState == EXECUTING || mState == RECONFIGURING);
1642            CHECK_EQ(mPortStatus[portIndex], ENABLING);
1643
1644            mPortStatus[portIndex] = ENABLED;
1645
1646            if (mState == RECONFIGURING) {
1647                CHECK_EQ(portIndex, kPortIndexOutput);
1648
1649                setState(EXECUTING);
1650
1651                fillOutputBuffers();
1652            }
1653            break;
1654        }
1655
1656        case OMX_CommandFlush:
1657        {
1658            OMX_U32 portIndex = data;
1659
1660            CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
1661
1662            CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1663            mPortStatus[portIndex] = ENABLED;
1664
1665            CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1666                     mPortBuffers[portIndex].size());
1667
1668            if (mState == RECONFIGURING) {
1669                CHECK_EQ(portIndex, kPortIndexOutput);
1670
1671                disablePortAsync(portIndex);
1672            } else if (mState == EXECUTING_TO_IDLE) {
1673                if (mPortStatus[kPortIndexInput] == ENABLED
1674                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1675                    CODEC_LOGV("Finished flushing both ports, now completing "
1676                         "transition from EXECUTING to IDLE.");
1677
1678                    mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1679                    mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1680
1681                    status_t err =
1682                        mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
1683                    CHECK_EQ(err, OK);
1684                }
1685            } else {
1686                // We're flushing both ports in preparation for seeking.
1687
1688                if (mPortStatus[kPortIndexInput] == ENABLED
1689                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1690                    CODEC_LOGV("Finished flushing both ports, now continuing from"
1691                         " seek-time.");
1692
1693                    drainInputBuffers();
1694                    fillOutputBuffers();
1695                }
1696            }
1697
1698            break;
1699        }
1700
1701        default:
1702        {
1703            CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
1704            break;
1705        }
1706    }
1707}
1708
1709void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1710    CODEC_LOGV("onStateChange %d", newState);
1711
1712    switch (newState) {
1713        case OMX_StateIdle:
1714        {
1715            CODEC_LOGV("Now Idle.");
1716            if (mState == LOADED_TO_IDLE) {
1717                status_t err = mOMX->sendCommand(
1718                        mNode, OMX_CommandStateSet, OMX_StateExecuting);
1719
1720                CHECK_EQ(err, OK);
1721
1722                setState(IDLE_TO_EXECUTING);
1723            } else {
1724                CHECK_EQ(mState, EXECUTING_TO_IDLE);
1725
1726                CHECK_EQ(
1727                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1728                    mPortBuffers[kPortIndexInput].size());
1729
1730                CHECK_EQ(
1731                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1732                    mPortBuffers[kPortIndexOutput].size());
1733
1734                status_t err = mOMX->sendCommand(
1735                        mNode, OMX_CommandStateSet, OMX_StateLoaded);
1736
1737                CHECK_EQ(err, OK);
1738
1739                err = freeBuffersOnPort(kPortIndexInput);
1740                CHECK_EQ(err, OK);
1741
1742                err = freeBuffersOnPort(kPortIndexOutput);
1743                CHECK_EQ(err, OK);
1744
1745                mPortStatus[kPortIndexInput] = ENABLED;
1746                mPortStatus[kPortIndexOutput] = ENABLED;
1747
1748                setState(IDLE_TO_LOADED);
1749            }
1750            break;
1751        }
1752
1753        case OMX_StateExecuting:
1754        {
1755            CHECK_EQ(mState, IDLE_TO_EXECUTING);
1756
1757            CODEC_LOGV("Now Executing.");
1758
1759            setState(EXECUTING);
1760
1761            // Buffers will be submitted to the component in the first
1762            // call to OMXCodec::read as mInitialBufferSubmit is true at
1763            // this point. This ensures that this on_message call returns,
1764            // releases the lock and ::init can notice the state change and
1765            // itself return.
1766            break;
1767        }
1768
1769        case OMX_StateLoaded:
1770        {
1771            CHECK_EQ(mState, IDLE_TO_LOADED);
1772
1773            CODEC_LOGV("Now Loaded.");
1774
1775            setState(LOADED);
1776            break;
1777        }
1778
1779        case OMX_StateInvalid:
1780        {
1781            setState(ERROR);
1782            break;
1783        }
1784
1785        default:
1786        {
1787            CHECK(!"should not be here.");
1788            break;
1789        }
1790    }
1791}
1792
1793// static
1794size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1795    size_t n = 0;
1796    for (size_t i = 0; i < buffers.size(); ++i) {
1797        if (!buffers[i].mOwnedByComponent) {
1798            ++n;
1799        }
1800    }
1801
1802    return n;
1803}
1804
1805status_t OMXCodec::freeBuffersOnPort(
1806        OMX_U32 portIndex, bool onlyThoseWeOwn) {
1807    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1808
1809    status_t stickyErr = OK;
1810
1811    for (size_t i = buffers->size(); i-- > 0;) {
1812        BufferInfo *info = &buffers->editItemAt(i);
1813
1814        if (onlyThoseWeOwn && info->mOwnedByComponent) {
1815            continue;
1816        }
1817
1818        CHECK_EQ(info->mOwnedByComponent, false);
1819
1820        CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
1821
1822        status_t err =
1823            mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
1824
1825        if (err != OK) {
1826            stickyErr = err;
1827        }
1828
1829        if (info->mMediaBuffer != NULL) {
1830            info->mMediaBuffer->setObserver(NULL);
1831
1832            // Make sure nobody but us owns this buffer at this point.
1833            CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1834
1835            info->mMediaBuffer->release();
1836        }
1837
1838        buffers->removeAt(i);
1839    }
1840
1841    CHECK(onlyThoseWeOwn || buffers->isEmpty());
1842
1843    return stickyErr;
1844}
1845
1846void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
1847    CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
1848
1849    CHECK_EQ(mState, EXECUTING);
1850    CHECK_EQ(portIndex, kPortIndexOutput);
1851    setState(RECONFIGURING);
1852
1853    if (mQuirks & kNeedsFlushBeforeDisable) {
1854        if (!flushPortAsync(portIndex)) {
1855            onCmdComplete(OMX_CommandFlush, portIndex);
1856        }
1857    } else {
1858        disablePortAsync(portIndex);
1859    }
1860}
1861
1862bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
1863    CHECK(mState == EXECUTING || mState == RECONFIGURING
1864            || mState == EXECUTING_TO_IDLE);
1865
1866    CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
1867         portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1868         mPortBuffers[portIndex].size());
1869
1870    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1871    mPortStatus[portIndex] = SHUTTING_DOWN;
1872
1873    if ((mQuirks & kRequiresFlushCompleteEmulation)
1874        && countBuffersWeOwn(mPortBuffers[portIndex])
1875                == mPortBuffers[portIndex].size()) {
1876        // No flush is necessary and this component fails to send a
1877        // flush-complete event in this case.
1878
1879        return false;
1880    }
1881
1882    status_t err =
1883        mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
1884    CHECK_EQ(err, OK);
1885
1886    return true;
1887}
1888
1889void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1890    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1891
1892    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1893    mPortStatus[portIndex] = DISABLING;
1894
1895    status_t err =
1896        mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
1897    CHECK_EQ(err, OK);
1898
1899    freeBuffersOnPort(portIndex, true);
1900}
1901
1902void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1903    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1904
1905    CHECK_EQ(mPortStatus[portIndex], DISABLED);
1906    mPortStatus[portIndex] = ENABLING;
1907
1908    status_t err =
1909        mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
1910    CHECK_EQ(err, OK);
1911}
1912
1913void OMXCodec::fillOutputBuffers() {
1914    CHECK_EQ(mState, EXECUTING);
1915
1916    // This is a workaround for some decoders not properly reporting
1917    // end-of-output-stream. If we own all input buffers and also own
1918    // all output buffers and we already signalled end-of-input-stream,
1919    // the end-of-output-stream is implied.
1920    if (mSignalledEOS
1921            && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
1922                == mPortBuffers[kPortIndexInput].size()
1923            && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
1924                == mPortBuffers[kPortIndexOutput].size()) {
1925        mNoMoreOutputData = true;
1926        mBufferFilled.signal();
1927
1928        return;
1929    }
1930
1931    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1932    for (size_t i = 0; i < buffers->size(); ++i) {
1933        fillOutputBuffer(&buffers->editItemAt(i));
1934    }
1935}
1936
1937void OMXCodec::drainInputBuffers() {
1938    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1939
1940    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1941    for (size_t i = 0; i < buffers->size(); ++i) {
1942        drainInputBuffer(&buffers->editItemAt(i));
1943    }
1944}
1945
1946void OMXCodec::drainInputBuffer(BufferInfo *info) {
1947    CHECK_EQ(info->mOwnedByComponent, false);
1948
1949    if (mSignalledEOS) {
1950        return;
1951    }
1952
1953    if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1954        const CodecSpecificData *specific =
1955            mCodecSpecificData[mCodecSpecificDataIndex];
1956
1957        size_t size = specific->mSize;
1958
1959        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
1960                && !(mQuirks & kWantsNALFragments)) {
1961            static const uint8_t kNALStartCode[4] =
1962                    { 0x00, 0x00, 0x00, 0x01 };
1963
1964            CHECK(info->mSize >= specific->mSize + 4);
1965
1966            size += 4;
1967
1968            memcpy(info->mData, kNALStartCode, 4);
1969            memcpy((uint8_t *)info->mData + 4,
1970                   specific->mData, specific->mSize);
1971        } else {
1972            CHECK(info->mSize >= specific->mSize);
1973            memcpy(info->mData, specific->mData, specific->mSize);
1974        }
1975
1976        mNoMoreOutputData = false;
1977
1978        CODEC_LOGV("calling emptyBuffer with codec specific data");
1979
1980        status_t err = mOMX->emptyBuffer(
1981                mNode, info->mBuffer, 0, size,
1982                OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1983                0);
1984        CHECK_EQ(err, OK);
1985
1986        info->mOwnedByComponent = true;
1987
1988        ++mCodecSpecificDataIndex;
1989        return;
1990    }
1991
1992    status_t err;
1993
1994    bool signalEOS = false;
1995    int64_t timestampUs = 0;
1996
1997    size_t offset = 0;
1998    int32_t n = 0;
1999    for (;;) {
2000        MediaBuffer *srcBuffer;
2001        if (mSeekTimeUs >= 0) {
2002            if (mLeftOverBuffer) {
2003                mLeftOverBuffer->release();
2004                mLeftOverBuffer = NULL;
2005            }
2006
2007            MediaSource::ReadOptions options;
2008            options.setSeekTo(mSeekTimeUs);
2009
2010            mSeekTimeUs = -1;
2011            mBufferFilled.signal();
2012
2013            err = mSource->read(&srcBuffer, &options);
2014        } else if (mLeftOverBuffer) {
2015            srcBuffer = mLeftOverBuffer;
2016            mLeftOverBuffer = NULL;
2017
2018            err = OK;
2019        } else {
2020            err = mSource->read(&srcBuffer);
2021        }
2022
2023        if (err != OK) {
2024            signalEOS = true;
2025            mFinalStatus = err;
2026            mSignalledEOS = true;
2027            break;
2028        }
2029
2030        size_t remainingBytes = info->mSize - offset;
2031
2032        if (srcBuffer->range_length() > remainingBytes) {
2033            if (offset == 0) {
2034                CODEC_LOGE(
2035                     "Codec's input buffers are too small to accomodate "
2036                     "buffer read from source (info->mSize = %d, srcLength = %d)",
2037                     info->mSize, srcBuffer->range_length());
2038
2039                srcBuffer->release();
2040                srcBuffer = NULL;
2041
2042                setState(ERROR);
2043                return;
2044            }
2045
2046            mLeftOverBuffer = srcBuffer;
2047            break;
2048        }
2049
2050        memcpy((uint8_t *)info->mData + offset,
2051               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
2052               srcBuffer->range_length());
2053
2054        int64_t lastBufferTimeUs;
2055        CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
2056        CHECK(timestampUs >= 0);
2057
2058        if (offset == 0) {
2059            timestampUs = lastBufferTimeUs;
2060        }
2061
2062        offset += srcBuffer->range_length();
2063
2064        srcBuffer->release();
2065        srcBuffer = NULL;
2066
2067        ++n;
2068
2069        if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
2070            break;
2071        }
2072
2073        int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
2074
2075        if (coalescedDurationUs > 250000ll) {
2076            // Don't coalesce more than 250ms worth of encoded data at once.
2077            break;
2078        }
2079    }
2080
2081    if (n > 1) {
2082        LOGV("coalesced %d frames into one input buffer", n);
2083    }
2084
2085    OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2086
2087    if (signalEOS) {
2088        flags |= OMX_BUFFERFLAG_EOS;
2089    } else {
2090        mNoMoreOutputData = false;
2091    }
2092
2093    CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
2094               "timestamp %lld us (%.2f secs)",
2095               info->mBuffer, offset,
2096               timestampUs, timestampUs / 1E6);
2097
2098    err = mOMX->emptyBuffer(
2099            mNode, info->mBuffer, 0, offset,
2100            flags, timestampUs);
2101
2102    if (err != OK) {
2103        setState(ERROR);
2104        return;
2105    }
2106
2107    info->mOwnedByComponent = true;
2108
2109    // This component does not ever signal the EOS flag on output buffers,
2110    // Thanks for nothing.
2111    if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) {
2112        mNoMoreOutputData = true;
2113        mBufferFilled.signal();
2114    }
2115}
2116
2117void OMXCodec::fillOutputBuffer(BufferInfo *info) {
2118    CHECK_EQ(info->mOwnedByComponent, false);
2119
2120    if (mNoMoreOutputData) {
2121        CODEC_LOGV("There is no more output data available, not "
2122             "calling fillOutputBuffer");
2123        return;
2124    }
2125
2126    CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
2127    status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
2128
2129    if (err != OK) {
2130        CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
2131
2132        setState(ERROR);
2133        return;
2134    }
2135
2136    info->mOwnedByComponent = true;
2137}
2138
2139void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
2140    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
2141    for (size_t i = 0; i < buffers->size(); ++i) {
2142        if ((*buffers)[i].mBuffer == buffer) {
2143            drainInputBuffer(&buffers->editItemAt(i));
2144            return;
2145        }
2146    }
2147
2148    CHECK(!"should not be here.");
2149}
2150
2151void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
2152    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2153    for (size_t i = 0; i < buffers->size(); ++i) {
2154        if ((*buffers)[i].mBuffer == buffer) {
2155            fillOutputBuffer(&buffers->editItemAt(i));
2156            return;
2157        }
2158    }
2159
2160    CHECK(!"should not be here.");
2161}
2162
2163void OMXCodec::setState(State newState) {
2164    mState = newState;
2165    mAsyncCompletion.signal();
2166
2167    // This may cause some spurious wakeups but is necessary to
2168    // unblock the reader if we enter ERROR state.
2169    mBufferFilled.signal();
2170}
2171
2172void OMXCodec::setRawAudioFormat(
2173        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2174
2175    // port definition
2176    OMX_PARAM_PORTDEFINITIONTYPE def;
2177    InitOMXParams(&def);
2178    def.nPortIndex = portIndex;
2179    status_t err = mOMX->getParameter(
2180            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2181    CHECK_EQ(err, OK);
2182    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2183    CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2184            &def, sizeof(def)), OK);
2185
2186    // pcm param
2187    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2188    InitOMXParams(&pcmParams);
2189    pcmParams.nPortIndex = portIndex;
2190
2191    err = mOMX->getParameter(
2192            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2193
2194    CHECK_EQ(err, OK);
2195
2196    pcmParams.nChannels = numChannels;
2197    pcmParams.eNumData = OMX_NumericalDataSigned;
2198    pcmParams.bInterleaved = OMX_TRUE;
2199    pcmParams.nBitPerSample = 16;
2200    pcmParams.nSamplingRate = sampleRate;
2201    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2202
2203    if (numChannels == 1) {
2204        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
2205    } else {
2206        CHECK_EQ(numChannels, 2);
2207
2208        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
2209        pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
2210    }
2211
2212    err = mOMX->setParameter(
2213            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2214
2215    CHECK_EQ(err, OK);
2216}
2217
2218static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
2219    if (isAMRWB) {
2220        if (bps <= 6600) {
2221            return OMX_AUDIO_AMRBandModeWB0;
2222        } else if (bps <= 8850) {
2223            return OMX_AUDIO_AMRBandModeWB1;
2224        } else if (bps <= 12650) {
2225            return OMX_AUDIO_AMRBandModeWB2;
2226        } else if (bps <= 14250) {
2227            return OMX_AUDIO_AMRBandModeWB3;
2228        } else if (bps <= 15850) {
2229            return OMX_AUDIO_AMRBandModeWB4;
2230        } else if (bps <= 18250) {
2231            return OMX_AUDIO_AMRBandModeWB5;
2232        } else if (bps <= 19850) {
2233            return OMX_AUDIO_AMRBandModeWB6;
2234        } else if (bps <= 23050) {
2235            return OMX_AUDIO_AMRBandModeWB7;
2236        }
2237
2238        // 23850 bps
2239        return OMX_AUDIO_AMRBandModeWB8;
2240    } else {  // AMRNB
2241        if (bps <= 4750) {
2242            return OMX_AUDIO_AMRBandModeNB0;
2243        } else if (bps <= 5150) {
2244            return OMX_AUDIO_AMRBandModeNB1;
2245        } else if (bps <= 5900) {
2246            return OMX_AUDIO_AMRBandModeNB2;
2247        } else if (bps <= 6700) {
2248            return OMX_AUDIO_AMRBandModeNB3;
2249        } else if (bps <= 7400) {
2250            return OMX_AUDIO_AMRBandModeNB4;
2251        } else if (bps <= 7950) {
2252            return OMX_AUDIO_AMRBandModeNB5;
2253        } else if (bps <= 10200) {
2254            return OMX_AUDIO_AMRBandModeNB6;
2255        }
2256
2257        // 12200 bps
2258        return OMX_AUDIO_AMRBandModeNB7;
2259    }
2260}
2261
2262void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
2263    OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
2264
2265    OMX_AUDIO_PARAM_AMRTYPE def;
2266    InitOMXParams(&def);
2267    def.nPortIndex = portIndex;
2268
2269    status_t err =
2270        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2271
2272    CHECK_EQ(err, OK);
2273
2274    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2275
2276    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
2277    err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2278    CHECK_EQ(err, OK);
2279
2280    ////////////////////////
2281
2282    if (mIsEncoder) {
2283        sp<MetaData> format = mSource->getFormat();
2284        int32_t sampleRate;
2285        int32_t numChannels;
2286        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
2287        CHECK(format->findInt32(kKeyChannelCount, &numChannels));
2288
2289        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2290    }
2291}
2292
2293void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
2294    CHECK(numChannels == 1 || numChannels == 2);
2295    if (mIsEncoder) {
2296        //////////////// input port ////////////////////
2297        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2298
2299        //////////////// output port ////////////////////
2300        // format
2301        OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2302        format.nPortIndex = kPortIndexOutput;
2303        format.nIndex = 0;
2304        status_t err = OMX_ErrorNone;
2305        while (OMX_ErrorNone == err) {
2306            CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
2307                    &format, sizeof(format)), OK);
2308            if (format.eEncoding == OMX_AUDIO_CodingAAC) {
2309                break;
2310            }
2311            format.nIndex++;
2312        }
2313        CHECK_EQ(OK, err);
2314        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
2315                &format, sizeof(format)), OK);
2316
2317        // port definition
2318        OMX_PARAM_PORTDEFINITIONTYPE def;
2319        InitOMXParams(&def);
2320        def.nPortIndex = kPortIndexOutput;
2321        CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
2322                &def, sizeof(def)), OK);
2323        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2324        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2325        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
2326                &def, sizeof(def)), OK);
2327
2328        // profile
2329        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2330        InitOMXParams(&profile);
2331        profile.nPortIndex = kPortIndexOutput;
2332        CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
2333                &profile, sizeof(profile)), OK);
2334        profile.nChannels = numChannels;
2335        profile.eChannelMode = (numChannels == 1?
2336                OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
2337        profile.nSampleRate = sampleRate;
2338        profile.nBitRate = bitRate;
2339        profile.nAudioBandWidth = 0;
2340        profile.nFrameLength = 0;
2341        profile.nAACtools = OMX_AUDIO_AACToolAll;
2342        profile.nAACERtools = OMX_AUDIO_AACERNone;
2343        profile.eAACProfile = OMX_AUDIO_AACObjectLC;
2344        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2345        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
2346                &profile, sizeof(profile)), OK);
2347
2348    } else {
2349        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2350        InitOMXParams(&profile);
2351        profile.nPortIndex = kPortIndexInput;
2352
2353        status_t err = mOMX->getParameter(
2354                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2355        CHECK_EQ(err, OK);
2356
2357        profile.nChannels = numChannels;
2358        profile.nSampleRate = sampleRate;
2359        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
2360
2361        err = mOMX->setParameter(
2362                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2363        CHECK_EQ(err, OK);
2364    }
2365}
2366
2367void OMXCodec::setImageOutputFormat(
2368        OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
2369    CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
2370
2371#if 0
2372    OMX_INDEXTYPE index;
2373    status_t err = mOMX->get_extension_index(
2374            mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
2375    CHECK_EQ(err, OK);
2376
2377    err = mOMX->set_config(mNode, index, &format, sizeof(format));
2378    CHECK_EQ(err, OK);
2379#endif
2380
2381    OMX_PARAM_PORTDEFINITIONTYPE def;
2382    InitOMXParams(&def);
2383    def.nPortIndex = kPortIndexOutput;
2384
2385    status_t err = mOMX->getParameter(
2386            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2387    CHECK_EQ(err, OK);
2388
2389    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2390
2391    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2392
2393    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2394    imageDef->eColorFormat = format;
2395    imageDef->nFrameWidth = width;
2396    imageDef->nFrameHeight = height;
2397
2398    switch (format) {
2399        case OMX_COLOR_FormatYUV420PackedPlanar:
2400        case OMX_COLOR_FormatYUV411Planar:
2401        {
2402            def.nBufferSize = (width * height * 3) / 2;
2403            break;
2404        }
2405
2406        case OMX_COLOR_FormatCbYCrY:
2407        {
2408            def.nBufferSize = width * height * 2;
2409            break;
2410        }
2411
2412        case OMX_COLOR_Format32bitARGB8888:
2413        {
2414            def.nBufferSize = width * height * 4;
2415            break;
2416        }
2417
2418        case OMX_COLOR_Format16bitARGB4444:
2419        case OMX_COLOR_Format16bitARGB1555:
2420        case OMX_COLOR_Format16bitRGB565:
2421        case OMX_COLOR_Format16bitBGR565:
2422        {
2423            def.nBufferSize = width * height * 2;
2424            break;
2425        }
2426
2427        default:
2428            CHECK(!"Should not be here. Unknown color format.");
2429            break;
2430    }
2431
2432    def.nBufferCountActual = def.nBufferCountMin;
2433
2434    err = mOMX->setParameter(
2435            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2436    CHECK_EQ(err, OK);
2437}
2438
2439void OMXCodec::setJPEGInputFormat(
2440        OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
2441    OMX_PARAM_PORTDEFINITIONTYPE def;
2442    InitOMXParams(&def);
2443    def.nPortIndex = kPortIndexInput;
2444
2445    status_t err = mOMX->getParameter(
2446            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2447    CHECK_EQ(err, OK);
2448
2449    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
2450    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2451
2452    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
2453    imageDef->nFrameWidth = width;
2454    imageDef->nFrameHeight = height;
2455
2456    def.nBufferSize = compressedSize;
2457    def.nBufferCountActual = def.nBufferCountMin;
2458
2459    err = mOMX->setParameter(
2460            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2461    CHECK_EQ(err, OK);
2462}
2463
2464void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
2465    CodecSpecificData *specific =
2466        (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
2467
2468    specific->mSize = size;
2469    memcpy(specific->mData, data, size);
2470
2471    mCodecSpecificData.push(specific);
2472}
2473
2474void OMXCodec::clearCodecSpecificData() {
2475    for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
2476        free(mCodecSpecificData.editItemAt(i));
2477    }
2478    mCodecSpecificData.clear();
2479    mCodecSpecificDataIndex = 0;
2480}
2481
2482status_t OMXCodec::start(MetaData *) {
2483    Mutex::Autolock autoLock(mLock);
2484
2485    if (mState != LOADED) {
2486        return UNKNOWN_ERROR;
2487    }
2488
2489    sp<MetaData> params = new MetaData;
2490    if (mQuirks & kWantsNALFragments) {
2491        params->setInt32(kKeyWantsNALFragments, true);
2492    }
2493    status_t err = mSource->start(params.get());
2494
2495    if (err != OK) {
2496        return err;
2497    }
2498
2499    mCodecSpecificDataIndex = 0;
2500    mInitialBufferSubmit = true;
2501    mSignalledEOS = false;
2502    mNoMoreOutputData = false;
2503    mOutputPortSettingsHaveChanged = false;
2504    mSeekTimeUs = -1;
2505    mFilledBuffers.clear();
2506
2507    return init();
2508}
2509
2510status_t OMXCodec::stop() {
2511    CODEC_LOGV("stop mState=%d", mState);
2512
2513    Mutex::Autolock autoLock(mLock);
2514
2515    while (isIntermediateState(mState)) {
2516        mAsyncCompletion.wait(mLock);
2517    }
2518
2519    switch (mState) {
2520        case LOADED:
2521        case ERROR:
2522            break;
2523
2524        case EXECUTING:
2525        {
2526            setState(EXECUTING_TO_IDLE);
2527
2528            if (mQuirks & kRequiresFlushBeforeShutdown) {
2529                CODEC_LOGV("This component requires a flush before transitioning "
2530                     "from EXECUTING to IDLE...");
2531
2532                bool emulateInputFlushCompletion =
2533                    !flushPortAsync(kPortIndexInput);
2534
2535                bool emulateOutputFlushCompletion =
2536                    !flushPortAsync(kPortIndexOutput);
2537
2538                if (emulateInputFlushCompletion) {
2539                    onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2540                }
2541
2542                if (emulateOutputFlushCompletion) {
2543                    onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2544                }
2545            } else {
2546                mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
2547                mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
2548
2549                status_t err =
2550                    mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
2551                CHECK_EQ(err, OK);
2552            }
2553
2554            while (mState != LOADED && mState != ERROR) {
2555                mAsyncCompletion.wait(mLock);
2556            }
2557
2558            break;
2559        }
2560
2561        default:
2562        {
2563            CHECK(!"should not be here.");
2564            break;
2565        }
2566    }
2567
2568    if (mLeftOverBuffer) {
2569        mLeftOverBuffer->release();
2570        mLeftOverBuffer = NULL;
2571    }
2572
2573    mSource->stop();
2574
2575    CODEC_LOGV("stopped");
2576
2577    return OK;
2578}
2579
2580sp<MetaData> OMXCodec::getFormat() {
2581    Mutex::Autolock autoLock(mLock);
2582
2583    return mOutputFormat;
2584}
2585
2586status_t OMXCodec::read(
2587        MediaBuffer **buffer, const ReadOptions *options) {
2588    *buffer = NULL;
2589
2590    Mutex::Autolock autoLock(mLock);
2591
2592    if (mState != EXECUTING && mState != RECONFIGURING) {
2593        return UNKNOWN_ERROR;
2594    }
2595
2596    bool seeking = false;
2597    int64_t seekTimeUs;
2598    if (options && options->getSeekTo(&seekTimeUs)) {
2599        seeking = true;
2600    }
2601
2602    if (mInitialBufferSubmit) {
2603        mInitialBufferSubmit = false;
2604
2605        if (seeking) {
2606            CHECK(seekTimeUs >= 0);
2607            mSeekTimeUs = seekTimeUs;
2608
2609            // There's no reason to trigger the code below, there's
2610            // nothing to flush yet.
2611            seeking = false;
2612        }
2613
2614        drainInputBuffers();
2615
2616        if (mState == EXECUTING) {
2617            // Otherwise mState == RECONFIGURING and this code will trigger
2618            // after the output port is reenabled.
2619            fillOutputBuffers();
2620        }
2621    }
2622
2623    if (seeking) {
2624        CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
2625
2626        mSignalledEOS = false;
2627
2628        CHECK(seekTimeUs >= 0);
2629        mSeekTimeUs = seekTimeUs;
2630
2631        mFilledBuffers.clear();
2632
2633        CHECK_EQ(mState, EXECUTING);
2634
2635        bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
2636        bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
2637
2638        if (emulateInputFlushCompletion) {
2639            onCmdComplete(OMX_CommandFlush, kPortIndexInput);
2640        }
2641
2642        if (emulateOutputFlushCompletion) {
2643            onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
2644        }
2645
2646        while (mSeekTimeUs >= 0) {
2647            mBufferFilled.wait(mLock);
2648        }
2649    }
2650
2651    while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
2652        mBufferFilled.wait(mLock);
2653    }
2654
2655    if (mState == ERROR) {
2656        return UNKNOWN_ERROR;
2657    }
2658
2659    if (mFilledBuffers.empty()) {
2660        return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
2661    }
2662
2663    if (mOutputPortSettingsHaveChanged) {
2664        mOutputPortSettingsHaveChanged = false;
2665
2666        return INFO_FORMAT_CHANGED;
2667    }
2668
2669    size_t index = *mFilledBuffers.begin();
2670    mFilledBuffers.erase(mFilledBuffers.begin());
2671
2672    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2673    info->mMediaBuffer->add_ref();
2674    *buffer = info->mMediaBuffer;
2675
2676    return OK;
2677}
2678
2679void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
2680    Mutex::Autolock autoLock(mLock);
2681
2682    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
2683    for (size_t i = 0; i < buffers->size(); ++i) {
2684        BufferInfo *info = &buffers->editItemAt(i);
2685
2686        if (info->mMediaBuffer == buffer) {
2687            CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
2688            fillOutputBuffer(info);
2689            return;
2690        }
2691    }
2692
2693    CHECK(!"should not be here.");
2694}
2695
2696static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
2697    static const char *kNames[] = {
2698        "OMX_IMAGE_CodingUnused",
2699        "OMX_IMAGE_CodingAutoDetect",
2700        "OMX_IMAGE_CodingJPEG",
2701        "OMX_IMAGE_CodingJPEG2K",
2702        "OMX_IMAGE_CodingEXIF",
2703        "OMX_IMAGE_CodingTIFF",
2704        "OMX_IMAGE_CodingGIF",
2705        "OMX_IMAGE_CodingPNG",
2706        "OMX_IMAGE_CodingLZW",
2707        "OMX_IMAGE_CodingBMP",
2708    };
2709
2710    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2711
2712    if (type < 0 || (size_t)type >= numNames) {
2713        return "UNKNOWN";
2714    } else {
2715        return kNames[type];
2716    }
2717}
2718
2719static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
2720    static const char *kNames[] = {
2721        "OMX_COLOR_FormatUnused",
2722        "OMX_COLOR_FormatMonochrome",
2723        "OMX_COLOR_Format8bitRGB332",
2724        "OMX_COLOR_Format12bitRGB444",
2725        "OMX_COLOR_Format16bitARGB4444",
2726        "OMX_COLOR_Format16bitARGB1555",
2727        "OMX_COLOR_Format16bitRGB565",
2728        "OMX_COLOR_Format16bitBGR565",
2729        "OMX_COLOR_Format18bitRGB666",
2730        "OMX_COLOR_Format18bitARGB1665",
2731        "OMX_COLOR_Format19bitARGB1666",
2732        "OMX_COLOR_Format24bitRGB888",
2733        "OMX_COLOR_Format24bitBGR888",
2734        "OMX_COLOR_Format24bitARGB1887",
2735        "OMX_COLOR_Format25bitARGB1888",
2736        "OMX_COLOR_Format32bitBGRA8888",
2737        "OMX_COLOR_Format32bitARGB8888",
2738        "OMX_COLOR_FormatYUV411Planar",
2739        "OMX_COLOR_FormatYUV411PackedPlanar",
2740        "OMX_COLOR_FormatYUV420Planar",
2741        "OMX_COLOR_FormatYUV420PackedPlanar",
2742        "OMX_COLOR_FormatYUV420SemiPlanar",
2743        "OMX_COLOR_FormatYUV422Planar",
2744        "OMX_COLOR_FormatYUV422PackedPlanar",
2745        "OMX_COLOR_FormatYUV422SemiPlanar",
2746        "OMX_COLOR_FormatYCbYCr",
2747        "OMX_COLOR_FormatYCrYCb",
2748        "OMX_COLOR_FormatCbYCrY",
2749        "OMX_COLOR_FormatCrYCbY",
2750        "OMX_COLOR_FormatYUV444Interleaved",
2751        "OMX_COLOR_FormatRawBayer8bit",
2752        "OMX_COLOR_FormatRawBayer10bit",
2753        "OMX_COLOR_FormatRawBayer8bitcompressed",
2754        "OMX_COLOR_FormatL2",
2755        "OMX_COLOR_FormatL4",
2756        "OMX_COLOR_FormatL8",
2757        "OMX_COLOR_FormatL16",
2758        "OMX_COLOR_FormatL24",
2759        "OMX_COLOR_FormatL32",
2760        "OMX_COLOR_FormatYUV420PackedSemiPlanar",
2761        "OMX_COLOR_FormatYUV422PackedSemiPlanar",
2762        "OMX_COLOR_Format18BitBGR666",
2763        "OMX_COLOR_Format24BitARGB6666",
2764        "OMX_COLOR_Format24BitABGR6666",
2765    };
2766
2767    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2768
2769    if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
2770        return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
2771    } else if (type < 0 || (size_t)type >= numNames) {
2772        return "UNKNOWN";
2773    } else {
2774        return kNames[type];
2775    }
2776}
2777
2778static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
2779    static const char *kNames[] = {
2780        "OMX_VIDEO_CodingUnused",
2781        "OMX_VIDEO_CodingAutoDetect",
2782        "OMX_VIDEO_CodingMPEG2",
2783        "OMX_VIDEO_CodingH263",
2784        "OMX_VIDEO_CodingMPEG4",
2785        "OMX_VIDEO_CodingWMV",
2786        "OMX_VIDEO_CodingRV",
2787        "OMX_VIDEO_CodingAVC",
2788        "OMX_VIDEO_CodingMJPEG",
2789    };
2790
2791    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2792
2793    if (type < 0 || (size_t)type >= numNames) {
2794        return "UNKNOWN";
2795    } else {
2796        return kNames[type];
2797    }
2798}
2799
2800static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
2801    static const char *kNames[] = {
2802        "OMX_AUDIO_CodingUnused",
2803        "OMX_AUDIO_CodingAutoDetect",
2804        "OMX_AUDIO_CodingPCM",
2805        "OMX_AUDIO_CodingADPCM",
2806        "OMX_AUDIO_CodingAMR",
2807        "OMX_AUDIO_CodingGSMFR",
2808        "OMX_AUDIO_CodingGSMEFR",
2809        "OMX_AUDIO_CodingGSMHR",
2810        "OMX_AUDIO_CodingPDCFR",
2811        "OMX_AUDIO_CodingPDCEFR",
2812        "OMX_AUDIO_CodingPDCHR",
2813        "OMX_AUDIO_CodingTDMAFR",
2814        "OMX_AUDIO_CodingTDMAEFR",
2815        "OMX_AUDIO_CodingQCELP8",
2816        "OMX_AUDIO_CodingQCELP13",
2817        "OMX_AUDIO_CodingEVRC",
2818        "OMX_AUDIO_CodingSMV",
2819        "OMX_AUDIO_CodingG711",
2820        "OMX_AUDIO_CodingG723",
2821        "OMX_AUDIO_CodingG726",
2822        "OMX_AUDIO_CodingG729",
2823        "OMX_AUDIO_CodingAAC",
2824        "OMX_AUDIO_CodingMP3",
2825        "OMX_AUDIO_CodingSBC",
2826        "OMX_AUDIO_CodingVORBIS",
2827        "OMX_AUDIO_CodingWMA",
2828        "OMX_AUDIO_CodingRA",
2829        "OMX_AUDIO_CodingMIDI",
2830    };
2831
2832    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2833
2834    if (type < 0 || (size_t)type >= numNames) {
2835        return "UNKNOWN";
2836    } else {
2837        return kNames[type];
2838    }
2839}
2840
2841static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
2842    static const char *kNames[] = {
2843        "OMX_AUDIO_PCMModeLinear",
2844        "OMX_AUDIO_PCMModeALaw",
2845        "OMX_AUDIO_PCMModeMULaw",
2846    };
2847
2848    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2849
2850    if (type < 0 || (size_t)type >= numNames) {
2851        return "UNKNOWN";
2852    } else {
2853        return kNames[type];
2854    }
2855}
2856
2857static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
2858    static const char *kNames[] = {
2859        "OMX_AUDIO_AMRBandModeUnused",
2860        "OMX_AUDIO_AMRBandModeNB0",
2861        "OMX_AUDIO_AMRBandModeNB1",
2862        "OMX_AUDIO_AMRBandModeNB2",
2863        "OMX_AUDIO_AMRBandModeNB3",
2864        "OMX_AUDIO_AMRBandModeNB4",
2865        "OMX_AUDIO_AMRBandModeNB5",
2866        "OMX_AUDIO_AMRBandModeNB6",
2867        "OMX_AUDIO_AMRBandModeNB7",
2868        "OMX_AUDIO_AMRBandModeWB0",
2869        "OMX_AUDIO_AMRBandModeWB1",
2870        "OMX_AUDIO_AMRBandModeWB2",
2871        "OMX_AUDIO_AMRBandModeWB3",
2872        "OMX_AUDIO_AMRBandModeWB4",
2873        "OMX_AUDIO_AMRBandModeWB5",
2874        "OMX_AUDIO_AMRBandModeWB6",
2875        "OMX_AUDIO_AMRBandModeWB7",
2876        "OMX_AUDIO_AMRBandModeWB8",
2877    };
2878
2879    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2880
2881    if (type < 0 || (size_t)type >= numNames) {
2882        return "UNKNOWN";
2883    } else {
2884        return kNames[type];
2885    }
2886}
2887
2888static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
2889    static const char *kNames[] = {
2890        "OMX_AUDIO_AMRFrameFormatConformance",
2891        "OMX_AUDIO_AMRFrameFormatIF1",
2892        "OMX_AUDIO_AMRFrameFormatIF2",
2893        "OMX_AUDIO_AMRFrameFormatFSF",
2894        "OMX_AUDIO_AMRFrameFormatRTPPayload",
2895        "OMX_AUDIO_AMRFrameFormatITU",
2896    };
2897
2898    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
2899
2900    if (type < 0 || (size_t)type >= numNames) {
2901        return "UNKNOWN";
2902    } else {
2903        return kNames[type];
2904    }
2905}
2906
2907void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
2908    OMX_PARAM_PORTDEFINITIONTYPE def;
2909    InitOMXParams(&def);
2910    def.nPortIndex = portIndex;
2911
2912    status_t err = mOMX->getParameter(
2913            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2914    CHECK_EQ(err, OK);
2915
2916    printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
2917
2918    CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
2919          || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
2920
2921    printf("  nBufferCountActual = %ld\n", def.nBufferCountActual);
2922    printf("  nBufferCountMin = %ld\n", def.nBufferCountMin);
2923    printf("  nBufferSize = %ld\n", def.nBufferSize);
2924
2925    switch (def.eDomain) {
2926        case OMX_PortDomainImage:
2927        {
2928            const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2929
2930            printf("\n");
2931            printf("  // Image\n");
2932            printf("  nFrameWidth = %ld\n", imageDef->nFrameWidth);
2933            printf("  nFrameHeight = %ld\n", imageDef->nFrameHeight);
2934            printf("  nStride = %ld\n", imageDef->nStride);
2935
2936            printf("  eCompressionFormat = %s\n",
2937                   imageCompressionFormatString(imageDef->eCompressionFormat));
2938
2939            printf("  eColorFormat = %s\n",
2940                   colorFormatString(imageDef->eColorFormat));
2941
2942            break;
2943        }
2944
2945        case OMX_PortDomainVideo:
2946        {
2947            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2948
2949            printf("\n");
2950            printf("  // Video\n");
2951            printf("  nFrameWidth = %ld\n", videoDef->nFrameWidth);
2952            printf("  nFrameHeight = %ld\n", videoDef->nFrameHeight);
2953            printf("  nStride = %ld\n", videoDef->nStride);
2954
2955            printf("  eCompressionFormat = %s\n",
2956                   videoCompressionFormatString(videoDef->eCompressionFormat));
2957
2958            printf("  eColorFormat = %s\n",
2959                   colorFormatString(videoDef->eColorFormat));
2960
2961            break;
2962        }
2963
2964        case OMX_PortDomainAudio:
2965        {
2966            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2967
2968            printf("\n");
2969            printf("  // Audio\n");
2970            printf("  eEncoding = %s\n",
2971                   audioCodingTypeString(audioDef->eEncoding));
2972
2973            if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2974                OMX_AUDIO_PARAM_PCMMODETYPE params;
2975                InitOMXParams(&params);
2976                params.nPortIndex = portIndex;
2977
2978                err = mOMX->getParameter(
2979                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2980                CHECK_EQ(err, OK);
2981
2982                printf("  nSamplingRate = %ld\n", params.nSamplingRate);
2983                printf("  nChannels = %ld\n", params.nChannels);
2984                printf("  bInterleaved = %d\n", params.bInterleaved);
2985                printf("  nBitPerSample = %ld\n", params.nBitPerSample);
2986
2987                printf("  eNumData = %s\n",
2988                       params.eNumData == OMX_NumericalDataSigned
2989                        ? "signed" : "unsigned");
2990
2991                printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
2992            } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
2993                OMX_AUDIO_PARAM_AMRTYPE amr;
2994                InitOMXParams(&amr);
2995                amr.nPortIndex = portIndex;
2996
2997                err = mOMX->getParameter(
2998                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
2999                CHECK_EQ(err, OK);
3000
3001                printf("  nChannels = %ld\n", amr.nChannels);
3002                printf("  eAMRBandMode = %s\n",
3003                        amrBandModeString(amr.eAMRBandMode));
3004                printf("  eAMRFrameFormat = %s\n",
3005                        amrFrameFormatString(amr.eAMRFrameFormat));
3006            }
3007
3008            break;
3009        }
3010
3011        default:
3012        {
3013            printf("  // Unknown\n");
3014            break;
3015        }
3016    }
3017
3018    printf("}\n");
3019}
3020
3021void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
3022    mOutputFormat = new MetaData;
3023    mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
3024
3025    OMX_PARAM_PORTDEFINITIONTYPE def;
3026    InitOMXParams(&def);
3027    def.nPortIndex = kPortIndexOutput;
3028
3029    status_t err = mOMX->getParameter(
3030            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3031    CHECK_EQ(err, OK);
3032
3033    switch (def.eDomain) {
3034        case OMX_PortDomainImage:
3035        {
3036            OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
3037            CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
3038
3039            mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
3040            mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
3041            mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
3042            mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
3043            break;
3044        }
3045
3046        case OMX_PortDomainAudio:
3047        {
3048            OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
3049
3050            if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
3051                OMX_AUDIO_PARAM_PCMMODETYPE params;
3052                InitOMXParams(&params);
3053                params.nPortIndex = kPortIndexOutput;
3054
3055                err = mOMX->getParameter(
3056                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
3057                CHECK_EQ(err, OK);
3058
3059                CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
3060                CHECK_EQ(params.nBitPerSample, 16);
3061                CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
3062
3063                int32_t numChannels, sampleRate;
3064                inputFormat->findInt32(kKeyChannelCount, &numChannels);
3065                inputFormat->findInt32(kKeySampleRate, &sampleRate);
3066
3067                if ((OMX_U32)numChannels != params.nChannels) {
3068                    LOGW("Codec outputs a different number of channels than "
3069                         "the input stream contains (contains %d channels, "
3070                         "codec outputs %ld channels).",
3071                         numChannels, params.nChannels);
3072                }
3073
3074                mOutputFormat->setCString(
3075                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
3076
3077                // Use the codec-advertised number of channels, as some
3078                // codecs appear to output stereo even if the input data is
3079                // mono. If we know the codec lies about this information,
3080                // use the actual number of channels instead.
3081                mOutputFormat->setInt32(
3082                        kKeyChannelCount,
3083                        (mQuirks & kDecoderLiesAboutNumberOfChannels)
3084                            ? numChannels : params.nChannels);
3085
3086                // The codec-reported sampleRate is not reliable...
3087                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
3088            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
3089                OMX_AUDIO_PARAM_AMRTYPE amr;
3090                InitOMXParams(&amr);
3091                amr.nPortIndex = kPortIndexOutput;
3092
3093                err = mOMX->getParameter(
3094                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
3095                CHECK_EQ(err, OK);
3096
3097                CHECK_EQ(amr.nChannels, 1);
3098                mOutputFormat->setInt32(kKeyChannelCount, 1);
3099
3100                if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
3101                    && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
3102                    mOutputFormat->setCString(
3103                            kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
3104                    mOutputFormat->setInt32(kKeySampleRate, 8000);
3105                } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
3106                            && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
3107                    mOutputFormat->setCString(
3108                            kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
3109                    mOutputFormat->setInt32(kKeySampleRate, 16000);
3110                } else {
3111                    CHECK(!"Unknown AMR band mode.");
3112                }
3113            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
3114                mOutputFormat->setCString(
3115                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
3116                int32_t numChannels, sampleRate, bitRate;
3117                inputFormat->findInt32(kKeyChannelCount, &numChannels);
3118                inputFormat->findInt32(kKeySampleRate, &sampleRate);
3119                inputFormat->findInt32(kKeyBitRate, &bitRate);
3120                mOutputFormat->setInt32(kKeyChannelCount, numChannels);
3121                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
3122                mOutputFormat->setInt32(kKeyBitRate, bitRate);
3123            } else {
3124                CHECK(!"Should not be here. Unknown audio encoding.");
3125            }
3126            break;
3127        }
3128
3129        case OMX_PortDomainVideo:
3130        {
3131            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3132
3133            if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
3134                mOutputFormat->setCString(
3135                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
3136            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
3137                mOutputFormat->setCString(
3138                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
3139            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
3140                mOutputFormat->setCString(
3141                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
3142            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
3143                mOutputFormat->setCString(
3144                        kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
3145            } else {
3146                CHECK(!"Unknown compression format.");
3147            }
3148
3149            if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
3150                // This component appears to be lying to me.
3151                mOutputFormat->setInt32(
3152                        kKeyWidth, (video_def->nFrameWidth + 15) & -16);
3153                mOutputFormat->setInt32(
3154                        kKeyHeight, (video_def->nFrameHeight + 15) & -16);
3155            } else {
3156                mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
3157                mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
3158            }
3159
3160            mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
3161            break;
3162        }
3163
3164        default:
3165        {
3166            CHECK(!"should not be here, neither audio nor video.");
3167            break;
3168        }
3169    }
3170}
3171
3172////////////////////////////////////////////////////////////////////////////////
3173
3174status_t QueryCodecs(
3175        const sp<IOMX> &omx,
3176        const char *mime, bool queryDecoders,
3177        Vector<CodecCapabilities> *results) {
3178    results->clear();
3179
3180    for (int index = 0;; ++index) {
3181        const char *componentName;
3182
3183        if (!queryDecoders) {
3184            componentName = GetCodec(
3185                    kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
3186                    mime, index);
3187        } else {
3188            componentName = GetCodec(
3189                    kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
3190                    mime, index);
3191        }
3192
3193        if (!componentName) {
3194            return OK;
3195        }
3196
3197        if (strncmp(componentName, "OMX.", 4)) {
3198            // Not an OpenMax component but a software codec.
3199
3200            results->push();
3201            CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3202            caps->mComponentName = componentName;
3203
3204            continue;
3205        }
3206
3207        sp<OMXCodecObserver> observer = new OMXCodecObserver;
3208        IOMX::node_id node;
3209        status_t err = omx->allocateNode(componentName, observer, &node);
3210
3211        if (err != OK) {
3212            continue;
3213        }
3214
3215        OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
3216
3217        results->push();
3218        CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
3219        caps->mComponentName = componentName;
3220
3221        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
3222        InitOMXParams(&param);
3223
3224        param.nPortIndex = queryDecoders ? 0 : 1;
3225
3226        for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
3227            err = omx->getParameter(
3228                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
3229                    &param, sizeof(param));
3230
3231            if (err != OK) {
3232                break;
3233            }
3234
3235            CodecProfileLevel profileLevel;
3236            profileLevel.mProfile = param.eProfile;
3237            profileLevel.mLevel = param.eLevel;
3238
3239            caps->mProfileLevels.push(profileLevel);
3240        }
3241
3242        CHECK_EQ(omx->freeNode(node), OK);
3243    }
3244}
3245
3246}  // namespace android
3247