OMXCodec.cpp revision 7d719af770ddefc3739fd0597634dea553c5569a
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXCodec"
19#include <utils/Log.h>
20
21#include <binder/IServiceManager.h>
22#include <binder/MemoryDealer.h>
23#include <binder/ProcessState.h>
24#include <media/IMediaPlayerService.h>
25#include <media/stagefright/ESDS.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaBufferGroup.h>
28#include <media/stagefright/MediaDebug.h>
29#include <media/stagefright/MediaExtractor.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/MmapSource.h>
32#include <media/stagefright/OMXCodec.h>
33#include <media/stagefright/Utils.h>
34#include <utils/Vector.h>
35
36#include <OMX_Audio.h>
37#include <OMX_Component.h>
38
39namespace android {
40
41struct CodecInfo {
42    const char *mime;
43    const char *codec;
44};
45
46static const CodecInfo kDecoderInfo[] = {
47    { "image/jpeg", "OMX.TI.JPEG.decode" },
48    { "audio/mpeg", "OMX.TI.MP3.decode" },
49    { "audio/mpeg", "OMX.PV.mp3dec" },
50    { "audio/3gpp", "OMX.TI.AMR.decode" },
51    { "audio/3gpp", "OMX.PV.amrdec" },
52    { "audio/mp4a-latm", "OMX.TI.AAC.decode" },
53    { "audio/mp4a-latm", "OMX.PV.aacdec" },
54    { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" },
55    { "video/mp4v-es", "OMX.TI.Video.Decoder" },
56    { "video/mp4v-es", "OMX.PV.mpeg4dec" },
57    { "video/3gpp", "OMX.qcom.video.decoder.h263" },
58    { "video/3gpp", "OMX.TI.Video.Decoder" },
59    { "video/3gpp", "OMX.PV.h263dec" },
60    { "video/avc", "OMX.qcom.video.decoder.avc" },
61    { "video/avc", "OMX.TI.Video.Decoder" },
62    { "video/avc", "OMX.PV.avcdec" },
63};
64
65static const CodecInfo kEncoderInfo[] = {
66    { "audio/3gpp", "OMX.TI.AMR.encode" },
67    { "audio/3gpp", "OMX.PV.amrencnb" },
68    { "audio/mp4a-latm", "OMX.TI.AAC.encode" },
69    { "audio/mp4a-latm", "OMX.PV.aacenc" },
70    { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" },
71    { "video/mp4v-es", "OMX.TI.Video.encoder" },
72    { "video/mp4v-es", "OMX.PV.mpeg4enc" },
73    { "video/3gpp", "OMX.qcom.video.encoder.h263" },
74    { "video/3gpp", "OMX.TI.Video.encoder" },
75    { "video/3gpp", "OMX.PV.h263enc" },
76    { "video/avc", "OMX.TI.Video.encoder" },
77    { "video/avc", "OMX.PV.avcenc" },
78};
79
80struct OMXCodecObserver : public BnOMXObserver {
81    OMXCodecObserver(const wp<OMXCodec> &target)
82        : mTarget(target) {
83    }
84
85    // from IOMXObserver
86    virtual void on_message(const omx_message &msg) {
87        sp<OMXCodec> codec = mTarget.promote();
88
89        if (codec.get() != NULL) {
90            codec->on_message(msg);
91        }
92    }
93
94protected:
95    virtual ~OMXCodecObserver() {}
96
97private:
98    wp<OMXCodec> mTarget;
99
100    OMXCodecObserver(const OMXCodecObserver &);
101    OMXCodecObserver &operator=(const OMXCodecObserver &);
102};
103
104static const char *GetCodec(const CodecInfo *info, size_t numInfos,
105                            const char *mime, int index) {
106    CHECK(index >= 0);
107    for(size_t i = 0; i < numInfos; ++i) {
108        if (!strcasecmp(mime, info[i].mime)) {
109            if (index == 0) {
110                return info[i].codec;
111            }
112
113            --index;
114        }
115    }
116
117    return NULL;
118}
119
120enum {
121    kAVCProfileBaseline      = 0x42,
122    kAVCProfileMain          = 0x4d,
123    kAVCProfileExtended      = 0x58,
124    kAVCProfileHigh          = 0x64,
125    kAVCProfileHigh10        = 0x6e,
126    kAVCProfileHigh422       = 0x7a,
127    kAVCProfileHigh444       = 0xf4,
128    kAVCProfileCAVLC444Intra = 0x2c
129};
130
131static const char *AVCProfileToString(uint8_t profile) {
132    switch (profile) {
133        case kAVCProfileBaseline:
134            return "Baseline";
135        case kAVCProfileMain:
136            return "Main";
137        case kAVCProfileExtended:
138            return "Extended";
139        case kAVCProfileHigh:
140            return "High";
141        case kAVCProfileHigh10:
142            return "High 10";
143        case kAVCProfileHigh422:
144            return "High 422";
145        case kAVCProfileHigh444:
146            return "High 444";
147        case kAVCProfileCAVLC444Intra:
148            return "CAVLC 444 Intra";
149        default:   return "Unknown";
150    }
151}
152
153// static
154sp<OMXCodec> OMXCodec::Create(
155        const sp<IOMX> &omx,
156        const sp<MetaData> &meta, bool createEncoder,
157        const sp<MediaSource> &source) {
158    const char *mime;
159    bool success = meta->findCString(kKeyMIMEType, &mime);
160    CHECK(success);
161
162    const char *componentName = NULL;
163    IOMX::node_id node = 0;
164    for (int index = 0;; ++index) {
165        if (createEncoder) {
166            componentName = GetCodec(
167                    kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
168                    mime, index);
169        } else {
170            componentName = GetCodec(
171                    kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
172                    mime, index);
173        }
174
175        if (!componentName) {
176            return NULL;
177        }
178
179        LOGV("Attempting to allocate OMX node '%s'", componentName);
180
181        status_t err = omx->allocate_node(componentName, &node);
182        if (err == OK) {
183            break;
184        }
185    }
186
187    uint32_t quirks = 0;
188    if (!strcmp(componentName, "OMX.PV.avcdec")) {
189        quirks |= kWantsNALFragments;
190    }
191    if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
192        quirks |= kNeedsFlushBeforeDisable;
193    }
194    if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
195        quirks |= kNeedsFlushBeforeDisable;
196        quirks |= kRequiresFlushCompleteEmulation;
197
198        // The following is currently necessary for proper shutdown
199        // behaviour, but NOT enabled by default in order to make the
200        // bug reproducible...
201        // quirks |= kRequiresFlushBeforeShutdown;
202    }
203    if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
204        quirks |= kRequiresLoadedToIdleAfterAllocation;
205        quirks |= kRequiresAllocateBufferOnInputPorts;
206    }
207
208    sp<OMXCodec> codec = new OMXCodec(
209            omx, node, quirks, createEncoder, mime, componentName,
210            source);
211
212    uint32_t type;
213    const void *data;
214    size_t size;
215    if (meta->findData(kKeyESDS, &type, &data, &size)) {
216        ESDS esds((const char *)data, size);
217        CHECK_EQ(esds.InitCheck(), OK);
218
219        const void *codec_specific_data;
220        size_t codec_specific_data_size;
221        esds.getCodecSpecificInfo(
222                &codec_specific_data, &codec_specific_data_size);
223
224        printf("found codec-specific data of size %d\n",
225               codec_specific_data_size);
226
227        codec->addCodecSpecificData(
228                codec_specific_data, codec_specific_data_size);
229    } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
230        printf("found avcc of size %d\n", size);
231
232        // Parse the AVCDecoderConfigurationRecord
233
234        const uint8_t *ptr = (const uint8_t *)data;
235
236        CHECK(size >= 7);
237        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
238        uint8_t profile = ptr[1];
239        uint8_t level = ptr[3];
240
241        CHECK((ptr[4] >> 2) == 0x3f);  // reserved
242
243        size_t lengthSize = 1 + (ptr[4] & 3);
244
245        // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
246        // violates it...
247        // CHECK((ptr[5] >> 5) == 7);  // reserved
248
249        size_t numSeqParameterSets = ptr[5] & 31;
250
251        ptr += 6;
252        size -= 6;
253
254        for (size_t i = 0; i < numSeqParameterSets; ++i) {
255            CHECK(size >= 2);
256            size_t length = U16_AT(ptr);
257
258            ptr += 2;
259            size -= 2;
260
261            CHECK(size >= length);
262
263            codec->addCodecSpecificData(ptr, length);
264
265            ptr += length;
266            size -= length;
267        }
268
269        CHECK(size >= 1);
270        size_t numPictureParameterSets = *ptr;
271        ++ptr;
272        --size;
273
274        for (size_t i = 0; i < numPictureParameterSets; ++i) {
275            CHECK(size >= 2);
276            size_t length = U16_AT(ptr);
277
278            ptr += 2;
279            size -= 2;
280
281            CHECK(size >= length);
282
283            codec->addCodecSpecificData(ptr, length);
284
285            ptr += length;
286            size -= length;
287        }
288
289        LOGI("AVC profile = %d (%s), level = %d",
290             (int)profile, AVCProfileToString(profile), (int)level / 10);
291
292        if (!strcmp(componentName, "OMX.TI.Video.Decoder")
293            && (profile != kAVCProfileBaseline || level > 39)) {
294            // This stream exceeds the decoder's capabilities.
295
296            LOGE("Profile and/or level exceed the decoder's capabilities.");
297            return NULL;
298        }
299    }
300
301    if (!strcasecmp("audio/3gpp", mime)) {
302        codec->setAMRFormat();
303    }
304    if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
305        codec->setAACFormat();
306    }
307    if (!strncasecmp(mime, "video/", 6)) {
308        int32_t width, height;
309        bool success = meta->findInt32(kKeyWidth, &width);
310        success = success && meta->findInt32(kKeyHeight, &height);
311        CHECK(success);
312
313        if (createEncoder) {
314            codec->setVideoInputFormat(mime, width, height);
315        } else {
316            codec->setVideoOutputFormat(mime, width, height);
317        }
318    }
319    if (!strcasecmp(mime, "image/jpeg")
320        && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
321        OMX_COLOR_FORMATTYPE format =
322            OMX_COLOR_Format32bitARGB8888;
323            // OMX_COLOR_FormatYUV420PackedPlanar;
324            // OMX_COLOR_FormatCbYCrY;
325            // OMX_COLOR_FormatYUV411Planar;
326
327        int32_t width, height;
328        bool success = meta->findInt32(kKeyWidth, &width);
329        success = success && meta->findInt32(kKeyHeight, &height);
330
331        int32_t compressedSize;
332        success = success && meta->findInt32(
333                kKeyCompressedSize, &compressedSize);
334
335        CHECK(success);
336        CHECK(compressedSize > 0);
337
338        codec->setImageOutputFormat(format, width, height);
339        codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
340    }
341
342    codec->initOutputFormat(meta);
343
344    return codec;
345}
346
347status_t OMXCodec::setVideoPortFormatType(
348        OMX_U32 portIndex,
349        OMX_VIDEO_CODINGTYPE compressionFormat,
350        OMX_COLOR_FORMATTYPE colorFormat) {
351    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
352    format.nSize = sizeof(format);
353    format.nVersion.s.nVersionMajor = 1;
354    format.nVersion.s.nVersionMinor = 1;
355    format.nPortIndex = portIndex;
356    format.nIndex = 0;
357    bool found = false;
358
359    OMX_U32 index = 0;
360    for (;;) {
361        format.nIndex = index;
362        status_t err = mOMX->get_parameter(
363                mNode, OMX_IndexParamVideoPortFormat,
364                &format, sizeof(format));
365
366        if (err != OK) {
367            return err;
368        }
369
370        // The following assertion is violated by TI's video decoder.
371        // CHECK_EQ(format.nIndex, index);
372
373#if 1
374        LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
375             portIndex,
376             index, format.eCompressionFormat, format.eColorFormat);
377#endif
378
379        if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
380            if (portIndex == kPortIndexInput
381                    && colorFormat == format.eColorFormat) {
382                // eCompressionFormat does not seem right.
383                found = true;
384                break;
385            }
386            if (portIndex == kPortIndexOutput
387                    && compressionFormat == format.eCompressionFormat) {
388                // eColorFormat does not seem right.
389                found = true;
390                break;
391            }
392        }
393
394        if (format.eCompressionFormat == compressionFormat
395            && format.eColorFormat == colorFormat) {
396            found = true;
397            break;
398        }
399
400        ++index;
401    }
402
403    if (!found) {
404        return UNKNOWN_ERROR;
405    }
406
407    LOGI("found a match.");
408    status_t err = mOMX->set_parameter(
409            mNode, OMX_IndexParamVideoPortFormat,
410            &format, sizeof(format));
411
412    return err;
413}
414
415void OMXCodec::setVideoInputFormat(
416        const char *mime, OMX_U32 width, OMX_U32 height) {
417    LOGI("setVideoInputFormat width=%ld, height=%ld", width, height);
418
419    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
420    if (!strcasecmp("video/avc", mime)) {
421        compressionFormat = OMX_VIDEO_CodingAVC;
422    } else if (!strcasecmp("video/mp4v-es", mime)) {
423        compressionFormat = OMX_VIDEO_CodingMPEG4;
424    } else if (!strcasecmp("video/3gpp", mime)) {
425        compressionFormat = OMX_VIDEO_CodingH263;
426    } else {
427        LOGE("Not a supported video mime type: %s", mime);
428        CHECK(!"Should not be here. Not a supported video mime type.");
429    }
430
431    OMX_COLOR_FORMATTYPE colorFormat =
432        0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
433
434    if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
435        colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
436    }
437
438    setVideoPortFormatType(
439            kPortIndexInput, OMX_VIDEO_CodingUnused,
440            colorFormat);
441
442    setVideoPortFormatType(
443            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
444
445    OMX_PARAM_PORTDEFINITIONTYPE def;
446    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
447
448    def.nSize = sizeof(def);
449    def.nVersion.s.nVersionMajor = 1;
450    def.nVersion.s.nVersionMinor = 1;
451    def.nPortIndex = kPortIndexOutput;
452
453    status_t err = mOMX->get_parameter(
454            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
455
456    CHECK_EQ(err, OK);
457    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
458
459    video_def->nFrameWidth = width;
460    video_def->nFrameHeight = height;
461
462    video_def->eCompressionFormat = compressionFormat;
463    video_def->eColorFormat = OMX_COLOR_FormatUnused;
464
465    err = mOMX->set_parameter(
466            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
467    CHECK_EQ(err, OK);
468
469    ////////////////////////////////////////////////////////////////////////////
470
471    def.nSize = sizeof(def);
472    def.nVersion.s.nVersionMajor = 1;
473    def.nVersion.s.nVersionMinor = 1;
474    def.nPortIndex = kPortIndexInput;
475
476    err = mOMX->get_parameter(
477            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
478    CHECK_EQ(err, OK);
479
480    def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
481    LOGI("setting nBufferSize = %ld", def.nBufferSize);
482
483    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
484
485    video_def->nFrameWidth = width;
486    video_def->nFrameHeight = height;
487    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
488    video_def->eColorFormat = colorFormat;
489
490    err = mOMX->set_parameter(
491            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
492    CHECK_EQ(err, OK);
493}
494
495void OMXCodec::setVideoOutputFormat(
496        const char *mime, OMX_U32 width, OMX_U32 height) {
497    LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
498
499    // Enabling this code appears to be the right thing(tm), but,...
500    // the TI decoder then loses the ability to output YUV420 and only outputs
501    // YCbYCr (16bit)
502
503#if 1
504    if (!strcmp("OMX.TI.Video.Decoder", mComponentName)) {
505        OMX_PARAM_COMPONENTROLETYPE role;
506        role.nSize = sizeof(role);
507        role.nVersion.s.nVersionMajor = 1;
508        role.nVersion.s.nVersionMinor = 1;
509
510        if (!strcasecmp("video/avc", mime)) {
511            strncpy((char *)role.cRole, "video_decoder.avc",
512                    OMX_MAX_STRINGNAME_SIZE - 1);
513        } else if (!strcasecmp("video/mp4v-es", mime)) {
514            strncpy((char *)role.cRole, "video_decoder.mpeg4",
515                    OMX_MAX_STRINGNAME_SIZE - 1);
516        } else if (!strcasecmp("video/3gpp", mime)) {
517            strncpy((char *)role.cRole, "video_decoder.h263",
518                    OMX_MAX_STRINGNAME_SIZE - 1);
519        }
520
521        role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
522
523        status_t err = mOMX->set_parameter(
524                mNode, OMX_IndexParamStandardComponentRole,
525                &role, sizeof(role));
526        CHECK_EQ(err, OK);
527    }
528#endif
529
530    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
531    if (!strcasecmp("video/avc", mime)) {
532        compressionFormat = OMX_VIDEO_CodingAVC;
533    } else if (!strcasecmp("video/mp4v-es", mime)) {
534        compressionFormat = OMX_VIDEO_CodingMPEG4;
535    } else if (!strcasecmp("video/3gpp", mime)) {
536        compressionFormat = OMX_VIDEO_CodingH263;
537    } else {
538        LOGE("Not a supported video mime type: %s", mime);
539        CHECK(!"Should not be here. Not a supported video mime type.");
540    }
541
542    setVideoPortFormatType(
543            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
544
545#if 1
546    {
547        OMX_VIDEO_PARAM_PORTFORMATTYPE format;
548        format.nSize = sizeof(format);
549        format.nVersion.s.nVersionMajor = 1;
550        format.nVersion.s.nVersionMinor = 1;
551        format.nPortIndex = kPortIndexOutput;
552        format.nIndex = 0;
553
554        status_t err = mOMX->get_parameter(
555                mNode, OMX_IndexParamVideoPortFormat,
556                &format, sizeof(format));
557        CHECK_EQ(err, OK);
558        CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
559
560        static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
561
562        CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
563               || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
564               || format.eColorFormat == OMX_COLOR_FormatCbYCrY
565               || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
566
567        err = mOMX->set_parameter(
568                mNode, OMX_IndexParamVideoPortFormat,
569                &format, sizeof(format));
570        CHECK_EQ(err, OK);
571    }
572#endif
573
574    OMX_PARAM_PORTDEFINITIONTYPE def;
575    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
576
577    def.nSize = sizeof(def);
578    def.nVersion.s.nVersionMajor = 1;
579    def.nVersion.s.nVersionMinor = 1;
580    def.nPortIndex = kPortIndexInput;
581
582    status_t err = mOMX->get_parameter(
583            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
584
585    CHECK_EQ(err, OK);
586
587#if 1
588    // XXX Need a (much) better heuristic to compute input buffer sizes.
589    const size_t X = 64 * 1024;
590    if (def.nBufferSize < X) {
591        def.nBufferSize = X;
592    }
593#endif
594
595    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
596
597    video_def->nFrameWidth = width;
598    video_def->nFrameHeight = height;
599
600    video_def->eColorFormat = OMX_COLOR_FormatUnused;
601
602    err = mOMX->set_parameter(
603            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
604    CHECK_EQ(err, OK);
605
606    ////////////////////////////////////////////////////////////////////////////
607
608    def.nSize = sizeof(def);
609    def.nVersion.s.nVersionMajor = 1;
610    def.nVersion.s.nVersionMinor = 1;
611    def.nPortIndex = kPortIndexOutput;
612
613    err = mOMX->get_parameter(
614            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
615    CHECK_EQ(err, OK);
616    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
617
618#if 0
619    def.nBufferSize =
620        (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2;  // YUV420
621#endif
622
623    video_def->nFrameWidth = width;
624    video_def->nFrameHeight = height;
625
626    err = mOMX->set_parameter(
627            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
628    CHECK_EQ(err, OK);
629}
630
631
632OMXCodec::OMXCodec(
633        const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
634        bool isEncoder,
635        const char *mime,
636        const char *componentName,
637        const sp<MediaSource> &source)
638    : mOMX(omx),
639      mNode(node),
640      mQuirks(quirks),
641      mIsEncoder(isEncoder),
642      mMIME(strdup(mime)),
643      mComponentName(strdup(componentName)),
644      mSource(source),
645      mCodecSpecificDataIndex(0),
646      mState(LOADED),
647      mInitialBufferSubmit(true),
648      mSignalledEOS(false),
649      mNoMoreOutputData(false),
650      mSeekTimeUs(-1) {
651    mPortStatus[kPortIndexInput] = ENABLED;
652    mPortStatus[kPortIndexOutput] = ENABLED;
653
654    mObserver = new OMXCodecObserver(this);
655    mOMX->observe_node(mNode, mObserver);
656}
657
658OMXCodec::~OMXCodec() {
659    CHECK(mState == LOADED || mState == ERROR);
660
661    status_t err = mOMX->observe_node(mNode, NULL);
662    CHECK_EQ(err, OK);
663
664    err = mOMX->free_node(mNode);
665    CHECK_EQ(err, OK);
666
667    mNode = NULL;
668    setState(DEAD);
669
670    clearCodecSpecificData();
671
672    free(mComponentName);
673    mComponentName = NULL;
674
675    free(mMIME);
676    mMIME = NULL;
677}
678
679status_t OMXCodec::init() {
680    // mLock is held.
681
682    CHECK_EQ(mState, LOADED);
683
684    status_t err;
685    if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
686        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
687        CHECK_EQ(err, OK);
688
689        setState(LOADED_TO_IDLE);
690    }
691
692    err = allocateBuffers();
693    CHECK_EQ(err, OK);
694
695    if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
696        err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
697        CHECK_EQ(err, OK);
698
699        setState(LOADED_TO_IDLE);
700    }
701
702    while (mState != EXECUTING && mState != ERROR) {
703        mAsyncCompletion.wait(mLock);
704    }
705
706    return mState == ERROR ? UNKNOWN_ERROR : OK;
707}
708
709// static
710bool OMXCodec::isIntermediateState(State state) {
711    return state == LOADED_TO_IDLE
712        || state == IDLE_TO_EXECUTING
713        || state == EXECUTING_TO_IDLE
714        || state == IDLE_TO_LOADED
715        || state == RECONFIGURING;
716}
717
718status_t OMXCodec::allocateBuffers() {
719    status_t err = allocateBuffersOnPort(kPortIndexInput);
720
721    if (err != OK) {
722        return err;
723    }
724
725    return allocateBuffersOnPort(kPortIndexOutput);
726}
727
728status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
729    OMX_PARAM_PORTDEFINITIONTYPE def;
730    def.nSize = sizeof(def);
731    def.nVersion.s.nVersionMajor = 1;
732    def.nVersion.s.nVersionMinor = 1;
733    def.nVersion.s.nRevision = 0;
734    def.nVersion.s.nStep = 0;
735    def.nPortIndex = portIndex;
736
737    status_t err = mOMX->get_parameter(
738            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
739
740    if (err != OK) {
741        return err;
742    }
743
744    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
745    mDealer[portIndex] = new MemoryDealer(totalSize);
746
747    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
748        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
749        CHECK(mem.get() != NULL);
750
751        IOMX::buffer_id buffer;
752        if (portIndex == kPortIndexInput
753                && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
754            err = mOMX->allocate_buffer_with_backup(
755                    mNode, portIndex, mem, &buffer);
756        } else if (portIndex == kPortIndexOutput
757                && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
758            err = mOMX->allocate_buffer(
759                    mNode, portIndex, def.nBufferSize, &buffer);
760        } else {
761            err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
762        }
763
764        if (err != OK) {
765            LOGE("allocate_buffer_with_backup failed");
766            return err;
767        }
768
769        BufferInfo info;
770        info.mBuffer = buffer;
771        info.mOwnedByComponent = false;
772        info.mMem = mem;
773        info.mMediaBuffer = NULL;
774
775        if (portIndex == kPortIndexOutput) {
776            info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
777            info.mMediaBuffer->setObserver(this);
778        }
779
780        mPortBuffers[portIndex].push(info);
781
782        LOGV("allocated buffer %p on %s port", buffer,
783             portIndex == kPortIndexInput ? "input" : "output");
784    }
785
786    dumpPortStatus(portIndex);
787
788    return OK;
789}
790
791void OMXCodec::on_message(const omx_message &msg) {
792    Mutex::Autolock autoLock(mLock);
793
794    switch (msg.type) {
795        case omx_message::EVENT:
796        {
797            onEvent(
798                 msg.u.event_data.event, msg.u.event_data.data1,
799                 msg.u.event_data.data2);
800
801            break;
802        }
803
804        case omx_message::EMPTY_BUFFER_DONE:
805        {
806            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
807
808            LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
809
810            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
811            size_t i = 0;
812            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
813                ++i;
814            }
815
816            CHECK(i < buffers->size());
817            if (!(*buffers)[i].mOwnedByComponent) {
818                LOGW("We already own input buffer %p, yet received "
819                     "an EMPTY_BUFFER_DONE.", buffer);
820            }
821
822            buffers->editItemAt(i).mOwnedByComponent = false;
823
824            if (mPortStatus[kPortIndexInput] == DISABLING) {
825                LOGV("Port is disabled, freeing buffer %p", buffer);
826
827                status_t err =
828                    mOMX->free_buffer(mNode, kPortIndexInput, buffer);
829                CHECK_EQ(err, OK);
830
831                buffers->removeAt(i);
832            } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
833                CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
834                drainInputBuffer(&buffers->editItemAt(i));
835            }
836
837            break;
838        }
839
840        case omx_message::FILL_BUFFER_DONE:
841        {
842            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
843            OMX_U32 flags = msg.u.extended_buffer_data.flags;
844
845            LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
846                 buffer,
847                 msg.u.extended_buffer_data.range_length,
848                 flags);
849
850            LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
851                 msg.u.extended_buffer_data.timestamp,
852                 msg.u.extended_buffer_data.timestamp / 1E6);
853
854            Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
855            size_t i = 0;
856            while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
857                ++i;
858            }
859
860            CHECK(i < buffers->size());
861            BufferInfo *info = &buffers->editItemAt(i);
862
863            if (!info->mOwnedByComponent) {
864                LOGW("We already own output buffer %p, yet received "
865                     "a FILL_BUFFER_DONE.", buffer);
866            }
867
868            info->mOwnedByComponent = false;
869
870            if (mPortStatus[kPortIndexOutput] == DISABLING) {
871                LOGV("Port is disabled, freeing buffer %p", buffer);
872
873                status_t err =
874                    mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
875                CHECK_EQ(err, OK);
876
877                buffers->removeAt(i);
878            } else if (mPortStatus[kPortIndexOutput] == ENABLED
879                       && (flags & OMX_BUFFERFLAG_EOS)) {
880                LOGV("No more output data.");
881                mNoMoreOutputData = true;
882                mBufferFilled.signal();
883            } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
884                CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
885
886                MediaBuffer *buffer = info->mMediaBuffer;
887
888                buffer->set_range(
889                        msg.u.extended_buffer_data.range_offset,
890                        msg.u.extended_buffer_data.range_length);
891
892                buffer->meta_data()->clear();
893
894                buffer->meta_data()->setInt32(
895                        kKeyTimeUnits,
896                        (msg.u.extended_buffer_data.timestamp + 500) / 1000);
897
898                buffer->meta_data()->setInt32(
899                        kKeyTimeScale, 1000);
900
901                if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
902                    buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
903                }
904
905                buffer->meta_data()->setPointer(
906                        kKeyPlatformPrivate,
907                        msg.u.extended_buffer_data.platform_private);
908
909                buffer->meta_data()->setPointer(
910                        kKeyBufferID,
911                        msg.u.extended_buffer_data.buffer);
912
913                mFilledBuffers.push_back(i);
914                mBufferFilled.signal();
915            }
916
917            break;
918        }
919
920        default:
921        {
922            CHECK(!"should not be here.");
923            break;
924        }
925    }
926}
927
928void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
929    switch (event) {
930        case OMX_EventCmdComplete:
931        {
932            onCmdComplete((OMX_COMMANDTYPE)data1, data2);
933            break;
934        }
935
936        case OMX_EventError:
937        {
938            LOGE("ERROR(%ld, %ld)", data1, data2);
939
940            setState(ERROR);
941            break;
942        }
943
944        case OMX_EventPortSettingsChanged:
945        {
946            onPortSettingsChanged(data1);
947            break;
948        }
949
950        case OMX_EventBufferFlag:
951        {
952            LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
953
954            if (data1 == kPortIndexOutput) {
955                mNoMoreOutputData = true;
956            }
957            break;
958        }
959
960        default:
961        {
962            LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
963            break;
964        }
965    }
966}
967
968void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
969    switch (cmd) {
970        case OMX_CommandStateSet:
971        {
972            onStateChange((OMX_STATETYPE)data);
973            break;
974        }
975
976        case OMX_CommandPortDisable:
977        {
978            OMX_U32 portIndex = data;
979            LOGV("PORT_DISABLED(%ld)", portIndex);
980
981            CHECK(mState == EXECUTING || mState == RECONFIGURING);
982            CHECK_EQ(mPortStatus[portIndex], DISABLING);
983            CHECK_EQ(mPortBuffers[portIndex].size(), 0);
984
985            mPortStatus[portIndex] = DISABLED;
986
987            if (mState == RECONFIGURING) {
988                CHECK_EQ(portIndex, kPortIndexOutput);
989
990                enablePortAsync(portIndex);
991
992                status_t err = allocateBuffersOnPort(portIndex);
993                CHECK_EQ(err, OK);
994            }
995            break;
996        }
997
998        case OMX_CommandPortEnable:
999        {
1000            OMX_U32 portIndex = data;
1001            LOGV("PORT_ENABLED(%ld)", portIndex);
1002
1003            CHECK(mState == EXECUTING || mState == RECONFIGURING);
1004            CHECK_EQ(mPortStatus[portIndex], ENABLING);
1005
1006            mPortStatus[portIndex] = ENABLED;
1007
1008            if (mState == RECONFIGURING) {
1009                CHECK_EQ(portIndex, kPortIndexOutput);
1010
1011                setState(EXECUTING);
1012
1013                fillOutputBuffers();
1014            }
1015            break;
1016        }
1017
1018        case OMX_CommandFlush:
1019        {
1020            OMX_U32 portIndex = data;
1021
1022            LOGV("FLUSH_DONE(%ld)", portIndex);
1023
1024            CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
1025            mPortStatus[portIndex] = ENABLED;
1026
1027            CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
1028                     mPortBuffers[portIndex].size());
1029
1030            if (mState == RECONFIGURING) {
1031                CHECK_EQ(portIndex, kPortIndexOutput);
1032
1033                disablePortAsync(portIndex);
1034            } else if (mState == EXECUTING_TO_IDLE) {
1035                if (mPortStatus[kPortIndexInput] == ENABLED
1036                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1037                    LOGV("Finished flushing both ports, now completing "
1038                         "transition from EXECUTING to IDLE.");
1039
1040                    mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1041                    mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1042
1043                    status_t err =
1044                        mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
1045                    CHECK_EQ(err, OK);
1046                }
1047            } else {
1048                // We're flushing both ports in preparation for seeking.
1049
1050                if (mPortStatus[kPortIndexInput] == ENABLED
1051                    && mPortStatus[kPortIndexOutput] == ENABLED) {
1052                    LOGV("Finished flushing both ports, now continuing from"
1053                         " seek-time.");
1054
1055                    drainInputBuffers();
1056                    fillOutputBuffers();
1057                }
1058            }
1059
1060            break;
1061        }
1062
1063        default:
1064        {
1065            LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
1066            break;
1067        }
1068    }
1069}
1070
1071void OMXCodec::onStateChange(OMX_STATETYPE newState) {
1072    switch (newState) {
1073        case OMX_StateIdle:
1074        {
1075            LOGV("Now Idle.");
1076            if (mState == LOADED_TO_IDLE) {
1077                status_t err = mOMX->send_command(
1078                        mNode, OMX_CommandStateSet, OMX_StateExecuting);
1079
1080                CHECK_EQ(err, OK);
1081
1082                setState(IDLE_TO_EXECUTING);
1083            } else {
1084                CHECK_EQ(mState, EXECUTING_TO_IDLE);
1085
1086                CHECK_EQ(
1087                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
1088                    mPortBuffers[kPortIndexInput].size());
1089
1090                CHECK_EQ(
1091                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
1092                    mPortBuffers[kPortIndexOutput].size());
1093
1094                status_t err = mOMX->send_command(
1095                        mNode, OMX_CommandStateSet, OMX_StateLoaded);
1096
1097                CHECK_EQ(err, OK);
1098
1099                err = freeBuffersOnPort(kPortIndexInput);
1100                CHECK_EQ(err, OK);
1101
1102                err = freeBuffersOnPort(kPortIndexOutput);
1103                CHECK_EQ(err, OK);
1104
1105                mPortStatus[kPortIndexInput] = ENABLED;
1106                mPortStatus[kPortIndexOutput] = ENABLED;
1107
1108                setState(IDLE_TO_LOADED);
1109            }
1110            break;
1111        }
1112
1113        case OMX_StateExecuting:
1114        {
1115            CHECK_EQ(mState, IDLE_TO_EXECUTING);
1116
1117            LOGV("Now Executing.");
1118
1119            setState(EXECUTING);
1120
1121            // Buffers will be submitted to the component in the first
1122            // call to OMXCodec::read as mInitialBufferSubmit is true at
1123            // this point. This ensures that this on_message call returns,
1124            // releases the lock and ::init can notice the state change and
1125            // itself return.
1126            break;
1127        }
1128
1129        case OMX_StateLoaded:
1130        {
1131            CHECK_EQ(mState, IDLE_TO_LOADED);
1132
1133            LOGV("Now Loaded.");
1134
1135            setState(LOADED);
1136            break;
1137        }
1138
1139        default:
1140        {
1141            CHECK(!"should not be here.");
1142            break;
1143        }
1144    }
1145}
1146
1147// static
1148size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
1149    size_t n = 0;
1150    for (size_t i = 0; i < buffers.size(); ++i) {
1151        if (!buffers[i].mOwnedByComponent) {
1152            ++n;
1153        }
1154    }
1155
1156    return n;
1157}
1158
1159status_t OMXCodec::freeBuffersOnPort(
1160        OMX_U32 portIndex, bool onlyThoseWeOwn) {
1161    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1162
1163    status_t stickyErr = OK;
1164
1165    for (size_t i = buffers->size(); i-- > 0;) {
1166        BufferInfo *info = &buffers->editItemAt(i);
1167
1168        if (onlyThoseWeOwn && info->mOwnedByComponent) {
1169            continue;
1170        }
1171
1172        CHECK_EQ(info->mOwnedByComponent, false);
1173
1174        status_t err =
1175            mOMX->free_buffer(mNode, portIndex, info->mBuffer);
1176
1177        if (err != OK) {
1178            stickyErr = err;
1179        }
1180
1181        if (info->mMediaBuffer != NULL) {
1182            info->mMediaBuffer->setObserver(NULL);
1183
1184            // Make sure nobody but us owns this buffer at this point.
1185            CHECK_EQ(info->mMediaBuffer->refcount(), 0);
1186
1187            info->mMediaBuffer->release();
1188        }
1189
1190        buffers->removeAt(i);
1191    }
1192
1193    CHECK(onlyThoseWeOwn || buffers->isEmpty());
1194
1195    return stickyErr;
1196}
1197
1198void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
1199    LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
1200
1201    CHECK_EQ(mState, EXECUTING);
1202    CHECK_EQ(portIndex, kPortIndexOutput);
1203    setState(RECONFIGURING);
1204
1205    if (mQuirks & kNeedsFlushBeforeDisable) {
1206        if (!flushPortAsync(portIndex)) {
1207            onCmdComplete(OMX_CommandFlush, portIndex);
1208        }
1209    } else {
1210        disablePortAsync(portIndex);
1211    }
1212}
1213
1214bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
1215    CHECK(mState == EXECUTING || mState == RECONFIGURING
1216            || mState == EXECUTING_TO_IDLE);
1217
1218    LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
1219         portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
1220         mPortBuffers[portIndex].size());
1221
1222    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1223    mPortStatus[portIndex] = SHUTTING_DOWN;
1224
1225    if ((mQuirks & kRequiresFlushCompleteEmulation)
1226        && countBuffersWeOwn(mPortBuffers[portIndex])
1227                == mPortBuffers[portIndex].size()) {
1228        // No flush is necessary and this component fails to send a
1229        // flush-complete event in this case.
1230
1231        return false;
1232    }
1233
1234    status_t err =
1235        mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
1236    CHECK_EQ(err, OK);
1237
1238    return true;
1239}
1240
1241void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
1242    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1243
1244    CHECK_EQ(mPortStatus[portIndex], ENABLED);
1245    mPortStatus[portIndex] = DISABLING;
1246
1247    status_t err =
1248        mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
1249    CHECK_EQ(err, OK);
1250
1251    freeBuffersOnPort(portIndex, true);
1252}
1253
1254void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
1255    CHECK(mState == EXECUTING || mState == RECONFIGURING);
1256
1257    CHECK_EQ(mPortStatus[portIndex], DISABLED);
1258    mPortStatus[portIndex] = ENABLING;
1259
1260    status_t err =
1261        mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
1262    CHECK_EQ(err, OK);
1263}
1264
1265void OMXCodec::fillOutputBuffers() {
1266    CHECK_EQ(mState, EXECUTING);
1267
1268    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1269    for (size_t i = 0; i < buffers->size(); ++i) {
1270        fillOutputBuffer(&buffers->editItemAt(i));
1271    }
1272}
1273
1274void OMXCodec::drainInputBuffers() {
1275    CHECK_EQ(mState, EXECUTING);
1276
1277    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1278    for (size_t i = 0; i < buffers->size(); ++i) {
1279        drainInputBuffer(&buffers->editItemAt(i));
1280    }
1281}
1282
1283void OMXCodec::drainInputBuffer(BufferInfo *info) {
1284    CHECK_EQ(info->mOwnedByComponent, false);
1285
1286    if (mSignalledEOS) {
1287        return;
1288    }
1289
1290    if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
1291        const CodecSpecificData *specific =
1292            mCodecSpecificData[mCodecSpecificDataIndex];
1293
1294        size_t size = specific->mSize;
1295
1296        if (!strcasecmp("video/avc", mMIME)
1297                && !(mQuirks & kWantsNALFragments)) {
1298            static const uint8_t kNALStartCode[4] =
1299                    { 0x00, 0x00, 0x00, 0x01 };
1300
1301            CHECK(info->mMem->size() >= specific->mSize + 4);
1302
1303            size += 4;
1304
1305            memcpy(info->mMem->pointer(), kNALStartCode, 4);
1306            memcpy((uint8_t *)info->mMem->pointer() + 4,
1307                   specific->mData, specific->mSize);
1308        } else {
1309            CHECK(info->mMem->size() >= specific->mSize);
1310            memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
1311        }
1312
1313        mOMX->empty_buffer(
1314                mNode, info->mBuffer, 0, size,
1315                OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
1316                0);
1317
1318        info->mOwnedByComponent = true;
1319
1320        ++mCodecSpecificDataIndex;
1321        return;
1322    }
1323
1324    MediaBuffer *srcBuffer;
1325    status_t err;
1326    if (mSeekTimeUs >= 0) {
1327        MediaSource::ReadOptions options;
1328        options.setSeekTo(mSeekTimeUs);
1329        mSeekTimeUs = -1;
1330
1331        err = mSource->read(&srcBuffer, &options);
1332    } else {
1333        err = mSource->read(&srcBuffer);
1334    }
1335
1336    OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1337    OMX_TICKS timestamp = 0;
1338    size_t srcLength = 0;
1339
1340    if (err != OK) {
1341        LOGV("signalling end of input stream.");
1342        flags |= OMX_BUFFERFLAG_EOS;
1343
1344        mSignalledEOS = true;
1345    } else {
1346        srcLength = srcBuffer->range_length();
1347
1348        if (info->mMem->size() < srcLength) {
1349            LOGE("info->mMem->size() = %d, srcLength = %d",
1350                 info->mMem->size(), srcLength);
1351        }
1352        CHECK(info->mMem->size() >= srcLength);
1353        memcpy(info->mMem->pointer(),
1354               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
1355               srcLength);
1356
1357        int32_t units, scale;
1358        if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units)
1359            && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) {
1360            timestamp = ((OMX_TICKS)units * 1000000) / scale;
1361
1362            LOGV("Calling empty_buffer on buffer %p (length %d)",
1363                 info->mBuffer, srcLength);
1364            LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
1365                 timestamp, timestamp / 1E6);
1366        }
1367    }
1368
1369    mOMX->empty_buffer(
1370            mNode, info->mBuffer, 0, srcLength,
1371            flags, timestamp);
1372
1373    info->mOwnedByComponent = true;
1374
1375    if (srcBuffer != NULL) {
1376        srcBuffer->release();
1377        srcBuffer = NULL;
1378    }
1379}
1380
1381void OMXCodec::fillOutputBuffer(BufferInfo *info) {
1382    CHECK_EQ(info->mOwnedByComponent, false);
1383
1384    if (mNoMoreOutputData) {
1385        LOGV("There is no more output data available, not "
1386             "calling fillOutputBuffer");
1387        return;
1388    }
1389
1390    LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
1391    mOMX->fill_buffer(mNode, info->mBuffer);
1392
1393    info->mOwnedByComponent = true;
1394}
1395
1396void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
1397    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
1398    for (size_t i = 0; i < buffers->size(); ++i) {
1399        if ((*buffers)[i].mBuffer == buffer) {
1400            drainInputBuffer(&buffers->editItemAt(i));
1401            return;
1402        }
1403    }
1404
1405    CHECK(!"should not be here.");
1406}
1407
1408void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
1409    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1410    for (size_t i = 0; i < buffers->size(); ++i) {
1411        if ((*buffers)[i].mBuffer == buffer) {
1412            fillOutputBuffer(&buffers->editItemAt(i));
1413            return;
1414        }
1415    }
1416
1417    CHECK(!"should not be here.");
1418}
1419
1420void OMXCodec::setState(State newState) {
1421    mState = newState;
1422    mAsyncCompletion.signal();
1423
1424    // This may cause some spurious wakeups but is necessary to
1425    // unblock the reader if we enter ERROR state.
1426    mBufferFilled.signal();
1427}
1428
1429void OMXCodec::setAMRFormat() {
1430    if (!mIsEncoder) {
1431        OMX_AUDIO_PARAM_AMRTYPE def;
1432        def.nSize = sizeof(def);
1433        def.nVersion.s.nVersionMajor = 1;
1434        def.nVersion.s.nVersionMinor = 1;
1435        def.nPortIndex = kPortIndexInput;
1436
1437        status_t err =
1438            mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1439
1440        CHECK_EQ(err, OK);
1441
1442        def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1443        def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
1444
1445        err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1446        CHECK_EQ(err, OK);
1447    }
1448
1449    ////////////////////////
1450
1451    if (mIsEncoder) {
1452        sp<MetaData> format = mSource->getFormat();
1453        int32_t sampleRate;
1454        int32_t numChannels;
1455        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
1456        CHECK(format->findInt32(kKeyChannelCount, &numChannels));
1457
1458        OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1459        pcmParams.nSize = sizeof(pcmParams);
1460        pcmParams.nVersion.s.nVersionMajor = 1;
1461        pcmParams.nVersion.s.nVersionMinor = 1;
1462        pcmParams.nPortIndex = kPortIndexInput;
1463
1464        status_t err = mOMX->get_parameter(
1465                mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1466
1467        CHECK_EQ(err, OK);
1468
1469        pcmParams.nChannels = numChannels;
1470        pcmParams.eNumData = OMX_NumericalDataSigned;
1471        pcmParams.bInterleaved = OMX_TRUE;
1472        pcmParams.nBitPerSample = 16;
1473        pcmParams.nSamplingRate = sampleRate;
1474        pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1475
1476        if (numChannels == 1) {
1477            pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1478        } else {
1479            CHECK_EQ(numChannels, 2);
1480
1481            pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1482            pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1483        }
1484
1485        err = mOMX->set_parameter(
1486                mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1487
1488        CHECK_EQ(err, OK);
1489    }
1490}
1491
1492void OMXCodec::setAACFormat() {
1493    OMX_AUDIO_PARAM_AACPROFILETYPE def;
1494    def.nSize = sizeof(def);
1495    def.nVersion.s.nVersionMajor = 1;
1496    def.nVersion.s.nVersionMinor = 1;
1497    def.nPortIndex = kPortIndexInput;
1498
1499    status_t err =
1500        mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
1501    CHECK_EQ(err, OK);
1502
1503    def.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1504
1505    err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
1506    CHECK_EQ(err, OK);
1507}
1508
1509void OMXCodec::setImageOutputFormat(
1510        OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
1511    LOGV("setImageOutputFormat(%ld, %ld)", width, height);
1512
1513#if 0
1514    OMX_INDEXTYPE index;
1515    status_t err = mOMX->get_extension_index(
1516            mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
1517    CHECK_EQ(err, OK);
1518
1519    err = mOMX->set_config(mNode, index, &format, sizeof(format));
1520    CHECK_EQ(err, OK);
1521#endif
1522
1523    OMX_PARAM_PORTDEFINITIONTYPE def;
1524    def.nSize = sizeof(def);
1525    def.nVersion.s.nVersionMajor = 1;
1526    def.nVersion.s.nVersionMinor = 1;
1527    def.nPortIndex = kPortIndexOutput;
1528
1529    status_t err = mOMX->get_parameter(
1530            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1531    CHECK_EQ(err, OK);
1532
1533    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1534
1535    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1536
1537    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
1538    imageDef->eColorFormat = format;
1539    imageDef->nFrameWidth = width;
1540    imageDef->nFrameHeight = height;
1541
1542    switch (format) {
1543        case OMX_COLOR_FormatYUV420PackedPlanar:
1544        case OMX_COLOR_FormatYUV411Planar:
1545        {
1546            def.nBufferSize = (width * height * 3) / 2;
1547            break;
1548        }
1549
1550        case OMX_COLOR_FormatCbYCrY:
1551        {
1552            def.nBufferSize = width * height * 2;
1553            break;
1554        }
1555
1556        case OMX_COLOR_Format32bitARGB8888:
1557        {
1558            def.nBufferSize = width * height * 4;
1559            break;
1560        }
1561
1562        default:
1563            CHECK(!"Should not be here. Unknown color format.");
1564            break;
1565    }
1566
1567    def.nBufferCountActual = def.nBufferCountMin;
1568
1569    err = mOMX->set_parameter(
1570            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1571    CHECK_EQ(err, OK);
1572}
1573
1574void OMXCodec::setJPEGInputFormat(
1575        OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
1576    OMX_PARAM_PORTDEFINITIONTYPE def;
1577    def.nSize = sizeof(def);
1578    def.nVersion.s.nVersionMajor = 1;
1579    def.nVersion.s.nVersionMinor = 1;
1580    def.nPortIndex = kPortIndexInput;
1581
1582    status_t err = mOMX->get_parameter(
1583            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1584    CHECK_EQ(err, OK);
1585
1586    CHECK_EQ(def.eDomain, OMX_PortDomainImage);
1587    OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1588
1589    CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
1590    imageDef->nFrameWidth = width;
1591    imageDef->nFrameHeight = height;
1592
1593    def.nBufferSize = compressedSize;
1594    def.nBufferCountActual = def.nBufferCountMin;
1595
1596    err = mOMX->set_parameter(
1597            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1598    CHECK_EQ(err, OK);
1599}
1600
1601void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
1602    CodecSpecificData *specific =
1603        (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
1604
1605    specific->mSize = size;
1606    memcpy(specific->mData, data, size);
1607
1608    mCodecSpecificData.push(specific);
1609}
1610
1611void OMXCodec::clearCodecSpecificData() {
1612    for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
1613        free(mCodecSpecificData.editItemAt(i));
1614    }
1615    mCodecSpecificData.clear();
1616    mCodecSpecificDataIndex = 0;
1617}
1618
1619status_t OMXCodec::start(MetaData *) {
1620    Mutex::Autolock autoLock(mLock);
1621
1622    if (mState != LOADED) {
1623        return UNKNOWN_ERROR;
1624    }
1625
1626    sp<MetaData> params = new MetaData;
1627    if (mQuirks & kWantsNALFragments) {
1628        params->setInt32(kKeyWantsNALFragments, true);
1629    }
1630    status_t err = mSource->start(params.get());
1631
1632    if (err != OK) {
1633        return err;
1634    }
1635
1636    mCodecSpecificDataIndex = 0;
1637    mInitialBufferSubmit = true;
1638    mSignalledEOS = false;
1639    mNoMoreOutputData = false;
1640    mSeekTimeUs = -1;
1641    mFilledBuffers.clear();
1642
1643    return init();
1644}
1645
1646status_t OMXCodec::stop() {
1647    LOGV("stop");
1648
1649    Mutex::Autolock autoLock(mLock);
1650
1651    while (isIntermediateState(mState)) {
1652        mAsyncCompletion.wait(mLock);
1653    }
1654
1655    switch (mState) {
1656        case LOADED:
1657        case ERROR:
1658            break;
1659
1660        case EXECUTING:
1661        {
1662            setState(EXECUTING_TO_IDLE);
1663
1664            if (mQuirks & kRequiresFlushBeforeShutdown) {
1665                LOGV("This component requires a flush before transitioning "
1666                     "from EXECUTING to IDLE...");
1667
1668                bool emulateInputFlushCompletion =
1669                    !flushPortAsync(kPortIndexInput);
1670
1671                bool emulateOutputFlushCompletion =
1672                    !flushPortAsync(kPortIndexOutput);
1673
1674                if (emulateInputFlushCompletion) {
1675                    onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1676                }
1677
1678                if (emulateOutputFlushCompletion) {
1679                    onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1680                }
1681            } else {
1682                mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
1683                mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
1684
1685                status_t err =
1686                    mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
1687                CHECK_EQ(err, OK);
1688            }
1689
1690            while (mState != LOADED && mState != ERROR) {
1691                mAsyncCompletion.wait(mLock);
1692            }
1693
1694            break;
1695        }
1696
1697        default:
1698        {
1699            CHECK(!"should not be here.");
1700            break;
1701        }
1702    }
1703
1704    mSource->stop();
1705
1706    return OK;
1707}
1708
1709sp<MetaData> OMXCodec::getFormat() {
1710    return mOutputFormat;
1711}
1712
1713status_t OMXCodec::read(
1714        MediaBuffer **buffer, const ReadOptions *options) {
1715    *buffer = NULL;
1716
1717    Mutex::Autolock autoLock(mLock);
1718
1719    if (mInitialBufferSubmit) {
1720        mInitialBufferSubmit = false;
1721
1722        drainInputBuffers();
1723        fillOutputBuffers();
1724    }
1725
1726    if (mState != EXECUTING && mState != RECONFIGURING) {
1727        return UNKNOWN_ERROR;
1728    }
1729
1730    int64_t seekTimeUs;
1731    if (options && options->getSeekTo(&seekTimeUs)) {
1732        LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
1733
1734        mSignalledEOS = false;
1735        mNoMoreOutputData = false;
1736
1737        CHECK(seekTimeUs >= 0);
1738        mSeekTimeUs = seekTimeUs;
1739
1740        mFilledBuffers.clear();
1741
1742        CHECK_EQ(mState, EXECUTING);
1743
1744        bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
1745        bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
1746
1747        if (emulateInputFlushCompletion) {
1748            onCmdComplete(OMX_CommandFlush, kPortIndexInput);
1749        }
1750
1751        if (emulateOutputFlushCompletion) {
1752            onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
1753        }
1754    }
1755
1756    while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
1757        mBufferFilled.wait(mLock);
1758    }
1759
1760    if (mState == ERROR) {
1761        return UNKNOWN_ERROR;
1762    }
1763
1764    if (mFilledBuffers.empty()) {
1765        return ERROR_END_OF_STREAM;
1766    }
1767
1768    size_t index = *mFilledBuffers.begin();
1769    mFilledBuffers.erase(mFilledBuffers.begin());
1770
1771    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1772    info->mMediaBuffer->add_ref();
1773    *buffer = info->mMediaBuffer;
1774
1775    return OK;
1776}
1777
1778void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
1779    Mutex::Autolock autoLock(mLock);
1780
1781    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
1782    for (size_t i = 0; i < buffers->size(); ++i) {
1783        BufferInfo *info = &buffers->editItemAt(i);
1784
1785        if (info->mMediaBuffer == buffer) {
1786            CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
1787            fillOutputBuffer(info);
1788            return;
1789        }
1790    }
1791
1792    CHECK(!"should not be here.");
1793}
1794
1795static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
1796    static const char *kNames[] = {
1797        "OMX_IMAGE_CodingUnused",
1798        "OMX_IMAGE_CodingAutoDetect",
1799        "OMX_IMAGE_CodingJPEG",
1800        "OMX_IMAGE_CodingJPEG2K",
1801        "OMX_IMAGE_CodingEXIF",
1802        "OMX_IMAGE_CodingTIFF",
1803        "OMX_IMAGE_CodingGIF",
1804        "OMX_IMAGE_CodingPNG",
1805        "OMX_IMAGE_CodingLZW",
1806        "OMX_IMAGE_CodingBMP",
1807    };
1808
1809    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1810
1811    if (type < 0 || (size_t)type >= numNames) {
1812        return "UNKNOWN";
1813    } else {
1814        return kNames[type];
1815    }
1816}
1817
1818static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
1819    static const char *kNames[] = {
1820        "OMX_COLOR_FormatUnused",
1821        "OMX_COLOR_FormatMonochrome",
1822        "OMX_COLOR_Format8bitRGB332",
1823        "OMX_COLOR_Format12bitRGB444",
1824        "OMX_COLOR_Format16bitARGB4444",
1825        "OMX_COLOR_Format16bitARGB1555",
1826        "OMX_COLOR_Format16bitRGB565",
1827        "OMX_COLOR_Format16bitBGR565",
1828        "OMX_COLOR_Format18bitRGB666",
1829        "OMX_COLOR_Format18bitARGB1665",
1830        "OMX_COLOR_Format19bitARGB1666",
1831        "OMX_COLOR_Format24bitRGB888",
1832        "OMX_COLOR_Format24bitBGR888",
1833        "OMX_COLOR_Format24bitARGB1887",
1834        "OMX_COLOR_Format25bitARGB1888",
1835        "OMX_COLOR_Format32bitBGRA8888",
1836        "OMX_COLOR_Format32bitARGB8888",
1837        "OMX_COLOR_FormatYUV411Planar",
1838        "OMX_COLOR_FormatYUV411PackedPlanar",
1839        "OMX_COLOR_FormatYUV420Planar",
1840        "OMX_COLOR_FormatYUV420PackedPlanar",
1841        "OMX_COLOR_FormatYUV420SemiPlanar",
1842        "OMX_COLOR_FormatYUV422Planar",
1843        "OMX_COLOR_FormatYUV422PackedPlanar",
1844        "OMX_COLOR_FormatYUV422SemiPlanar",
1845        "OMX_COLOR_FormatYCbYCr",
1846        "OMX_COLOR_FormatYCrYCb",
1847        "OMX_COLOR_FormatCbYCrY",
1848        "OMX_COLOR_FormatCrYCbY",
1849        "OMX_COLOR_FormatYUV444Interleaved",
1850        "OMX_COLOR_FormatRawBayer8bit",
1851        "OMX_COLOR_FormatRawBayer10bit",
1852        "OMX_COLOR_FormatRawBayer8bitcompressed",
1853        "OMX_COLOR_FormatL2",
1854        "OMX_COLOR_FormatL4",
1855        "OMX_COLOR_FormatL8",
1856        "OMX_COLOR_FormatL16",
1857        "OMX_COLOR_FormatL24",
1858        "OMX_COLOR_FormatL32",
1859        "OMX_COLOR_FormatYUV420PackedSemiPlanar",
1860        "OMX_COLOR_FormatYUV422PackedSemiPlanar",
1861        "OMX_COLOR_Format18BitBGR666",
1862        "OMX_COLOR_Format24BitARGB6666",
1863        "OMX_COLOR_Format24BitABGR6666",
1864    };
1865
1866    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1867
1868    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
1869
1870    if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
1871        return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
1872    } else if (type < 0 || (size_t)type >= numNames) {
1873        return "UNKNOWN";
1874    } else {
1875        return kNames[type];
1876    }
1877}
1878
1879static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
1880    static const char *kNames[] = {
1881        "OMX_VIDEO_CodingUnused",
1882        "OMX_VIDEO_CodingAutoDetect",
1883        "OMX_VIDEO_CodingMPEG2",
1884        "OMX_VIDEO_CodingH263",
1885        "OMX_VIDEO_CodingMPEG4",
1886        "OMX_VIDEO_CodingWMV",
1887        "OMX_VIDEO_CodingRV",
1888        "OMX_VIDEO_CodingAVC",
1889        "OMX_VIDEO_CodingMJPEG",
1890    };
1891
1892    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1893
1894    if (type < 0 || (size_t)type >= numNames) {
1895        return "UNKNOWN";
1896    } else {
1897        return kNames[type];
1898    }
1899}
1900
1901static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
1902    static const char *kNames[] = {
1903        "OMX_AUDIO_CodingUnused",
1904        "OMX_AUDIO_CodingAutoDetect",
1905        "OMX_AUDIO_CodingPCM",
1906        "OMX_AUDIO_CodingADPCM",
1907        "OMX_AUDIO_CodingAMR",
1908        "OMX_AUDIO_CodingGSMFR",
1909        "OMX_AUDIO_CodingGSMEFR",
1910        "OMX_AUDIO_CodingGSMHR",
1911        "OMX_AUDIO_CodingPDCFR",
1912        "OMX_AUDIO_CodingPDCEFR",
1913        "OMX_AUDIO_CodingPDCHR",
1914        "OMX_AUDIO_CodingTDMAFR",
1915        "OMX_AUDIO_CodingTDMAEFR",
1916        "OMX_AUDIO_CodingQCELP8",
1917        "OMX_AUDIO_CodingQCELP13",
1918        "OMX_AUDIO_CodingEVRC",
1919        "OMX_AUDIO_CodingSMV",
1920        "OMX_AUDIO_CodingG711",
1921        "OMX_AUDIO_CodingG723",
1922        "OMX_AUDIO_CodingG726",
1923        "OMX_AUDIO_CodingG729",
1924        "OMX_AUDIO_CodingAAC",
1925        "OMX_AUDIO_CodingMP3",
1926        "OMX_AUDIO_CodingSBC",
1927        "OMX_AUDIO_CodingVORBIS",
1928        "OMX_AUDIO_CodingWMA",
1929        "OMX_AUDIO_CodingRA",
1930        "OMX_AUDIO_CodingMIDI",
1931    };
1932
1933    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1934
1935    if (type < 0 || (size_t)type >= numNames) {
1936        return "UNKNOWN";
1937    } else {
1938        return kNames[type];
1939    }
1940}
1941
1942static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
1943    static const char *kNames[] = {
1944        "OMX_AUDIO_PCMModeLinear",
1945        "OMX_AUDIO_PCMModeALaw",
1946        "OMX_AUDIO_PCMModeMULaw",
1947    };
1948
1949    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
1950
1951    if (type < 0 || (size_t)type >= numNames) {
1952        return "UNKNOWN";
1953    } else {
1954        return kNames[type];
1955    }
1956}
1957
1958
1959void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
1960    OMX_PARAM_PORTDEFINITIONTYPE def;
1961    def.nSize = sizeof(def);
1962    def.nVersion.s.nVersionMajor = 1;
1963    def.nVersion.s.nVersionMinor = 1;
1964    def.nPortIndex = portIndex;
1965
1966    status_t err = mOMX->get_parameter(
1967            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1968    CHECK_EQ(err, OK);
1969
1970    printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
1971
1972    CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
1973          || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
1974
1975    printf("  nBufferCountActual = %ld\n", def.nBufferCountActual);
1976    printf("  nBufferCountMin = %ld\n", def.nBufferCountMin);
1977    printf("  nBufferSize = %ld\n", def.nBufferSize);
1978
1979    switch (def.eDomain) {
1980        case OMX_PortDomainImage:
1981        {
1982            const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
1983
1984            printf("\n");
1985            printf("  // Image\n");
1986            printf("  nFrameWidth = %ld\n", imageDef->nFrameWidth);
1987            printf("  nFrameHeight = %ld\n", imageDef->nFrameHeight);
1988            printf("  nStride = %ld\n", imageDef->nStride);
1989
1990            printf("  eCompressionFormat = %s\n",
1991                   imageCompressionFormatString(imageDef->eCompressionFormat));
1992
1993            printf("  eColorFormat = %s\n",
1994                   colorFormatString(imageDef->eColorFormat));
1995
1996            break;
1997        }
1998
1999        case OMX_PortDomainVideo:
2000        {
2001            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2002
2003            printf("\n");
2004            printf("  // Video\n");
2005            printf("  nFrameWidth = %ld\n", videoDef->nFrameWidth);
2006            printf("  nFrameHeight = %ld\n", videoDef->nFrameHeight);
2007            printf("  nStride = %ld\n", videoDef->nStride);
2008
2009            printf("  eCompressionFormat = %s\n",
2010                   videoCompressionFormatString(videoDef->eCompressionFormat));
2011
2012            printf("  eColorFormat = %s\n",
2013                   colorFormatString(videoDef->eColorFormat));
2014
2015            break;
2016        }
2017
2018        case OMX_PortDomainAudio:
2019        {
2020            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2021
2022            printf("\n");
2023            printf("  // Audio\n");
2024            printf("  eEncoding = %s\n",
2025                   audioCodingTypeString(audioDef->eEncoding));
2026
2027            if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
2028                OMX_AUDIO_PARAM_PCMMODETYPE params;
2029                params.nSize = sizeof(params);
2030                params.nVersion.s.nVersionMajor = 1;
2031                params.nVersion.s.nVersionMinor = 1;
2032                params.nPortIndex = portIndex;
2033
2034                err = mOMX->get_parameter(
2035                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2036                CHECK_EQ(err, OK);
2037
2038                printf("  nSamplingRate = %ld\n", params.nSamplingRate);
2039                printf("  nChannels = %ld\n", params.nChannels);
2040                printf("  bInterleaved = %d\n", params.bInterleaved);
2041                printf("  nBitPerSample = %ld\n", params.nBitPerSample);
2042
2043                printf("  eNumData = %s\n",
2044                       params.eNumData == OMX_NumericalDataSigned
2045                        ? "signed" : "unsigned");
2046
2047                printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
2048            }
2049
2050            break;
2051        }
2052
2053        default:
2054        {
2055            printf("  // Unknown\n");
2056            break;
2057        }
2058    }
2059
2060    printf("}\n");
2061}
2062
2063void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
2064    mOutputFormat = new MetaData;
2065    mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
2066
2067    OMX_PARAM_PORTDEFINITIONTYPE def;
2068    def.nSize = sizeof(def);
2069    def.nVersion.s.nVersionMajor = 1;
2070    def.nVersion.s.nVersionMinor = 1;
2071    def.nPortIndex = kPortIndexOutput;
2072
2073    status_t err = mOMX->get_parameter(
2074            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2075    CHECK_EQ(err, OK);
2076
2077    switch (def.eDomain) {
2078        case OMX_PortDomainImage:
2079        {
2080            OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
2081            CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
2082
2083            mOutputFormat->setCString(kKeyMIMEType, "image/raw");
2084            mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
2085            mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
2086            mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
2087            break;
2088        }
2089
2090        case OMX_PortDomainAudio:
2091        {
2092            OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
2093
2094            CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
2095
2096            OMX_AUDIO_PARAM_PCMMODETYPE params;
2097            params.nSize = sizeof(params);
2098            params.nVersion.s.nVersionMajor = 1;
2099            params.nVersion.s.nVersionMinor = 1;
2100            params.nPortIndex = kPortIndexOutput;
2101
2102            err = mOMX->get_parameter(
2103                    mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
2104            CHECK_EQ(err, OK);
2105
2106            CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
2107            CHECK_EQ(params.nBitPerSample, 16);
2108            CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
2109
2110            int32_t numChannels, sampleRate;
2111            inputFormat->findInt32(kKeyChannelCount, &numChannels);
2112            inputFormat->findInt32(kKeySampleRate, &sampleRate);
2113
2114            mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
2115            mOutputFormat->setInt32(kKeyChannelCount, numChannels);
2116            mOutputFormat->setInt32(kKeySampleRate, sampleRate);
2117            break;
2118        }
2119
2120        case OMX_PortDomainVideo:
2121        {
2122            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2123
2124            if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
2125                mOutputFormat->setCString(kKeyMIMEType, "video/raw");
2126            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
2127                mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es");
2128            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
2129                mOutputFormat->setCString(kKeyMIMEType, "video/3gpp");
2130            } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
2131                mOutputFormat->setCString(kKeyMIMEType, "video/avc");
2132            } else {
2133                CHECK(!"Unknown compression format.");
2134            }
2135
2136            if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
2137                // This component appears to be lying to me.
2138                mOutputFormat->setInt32(
2139                        kKeyWidth, (video_def->nFrameWidth + 15) & -16);
2140                mOutputFormat->setInt32(
2141                        kKeyHeight, (video_def->nFrameHeight + 15) & -16);
2142            } else {
2143                mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
2144                mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
2145            }
2146
2147            mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
2148            break;
2149        }
2150
2151        default:
2152        {
2153            CHECK(!"should not be here, neither audio nor video.");
2154            break;
2155        }
2156    }
2157}
2158
2159}  // namespace android
2160