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