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