142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong/*
242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * Copyright (C) 2010 The Android Open Source Project
342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong *
442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * Licensed under the Apache License, Version 2.0 (the "License");
542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * you may not use this file except in compliance with the License.
642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * You may obtain a copy of the License at
742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong *
842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong *      http://www.apache.org/licenses/LICENSE-2.0
942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong *
1042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * Unless required by applicable law or agreed to in writing, software
1142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * distributed under the License is distributed on an "AS IS" BASIS,
1242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * See the License for the specific language governing permissions and
1442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong * limitations under the License.
1542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong */
1642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
1742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong//#define LOG_NDEBUG 0
1842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#define LOG_TAG "M4vH263Encoder"
1942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <utils/Log.h>
2042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
2142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include "M4vH263Encoder.h"
2242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
2342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include "mp4enc_api.h"
2442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include "OMX_Video.h"
2542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
2642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/MediaBufferGroup.h>
2742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/MediaDebug.h>
2842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/MediaDefs.h>
2942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/MediaErrors.h>
3042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/MetaData.h>
3142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong#include <media/stagefright/Utils.h>
3242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
3342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongnamespace android {
3442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
35af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dongstatic status_t ConvertOmxProfileLevel(
36af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        MP4EncodingMode mode,
37af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        int32_t omxProfile,
38af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        int32_t omxLevel,
39af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        ProfileLevelType* pvProfileLevel) {
40af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    LOGV("ConvertOmxProfileLevel: %d/%d/%d", mode, omxProfile, omxLevel);
41af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    ProfileLevelType profileLevel;
42af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    if (mode == H263_MODE) {
43af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        switch (omxProfile) {
44af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            case OMX_VIDEO_H263ProfileBaseline:
45af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                if (omxLevel > OMX_VIDEO_H263Level45) {
46af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    LOGE("Unsupported level (%d) for H263", omxLevel);
47af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    return BAD_VALUE;
48af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                } else {
49af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    LOGW("PV does not support level configuration for H263");
50af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    profileLevel = CORE_PROFILE_LEVEL2;
51af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    break;
52af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                }
530244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                break;
54af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            default:
55af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                LOGE("Unsupported profile (%d) for H263", omxProfile);
56af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                return BAD_VALUE;
57af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        }
58af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    } else {  // MPEG4
59af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        switch (omxProfile) {
60af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            case OMX_VIDEO_MPEG4ProfileSimple:
61af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                switch (omxLevel) {
62af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level0b:
63af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_PROFILE_LEVEL0;
64af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
65af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level1:
66af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_PROFILE_LEVEL1;
67af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
68af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level2:
69af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_PROFILE_LEVEL2;
70af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
71af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level3:
72af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_PROFILE_LEVEL3;
73af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
74af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    default:
75af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        LOGE("Unsupported level (%d) for MPEG4 simple profile",
76af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                            omxLevel);
77af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        return BAD_VALUE;
780244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                }
790244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                break;
80af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            case OMX_VIDEO_MPEG4ProfileSimpleScalable:
81af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                switch (omxLevel) {
82af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level0b:
83af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL0;
84af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
85af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level1:
86af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL1;
87af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
88af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level2:
89af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL2;
90af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
91af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    default:
92af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        LOGE("Unsupported level (%d) for MPEG4 simple "
93af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                             "scalable profile", omxLevel);
94af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        return BAD_VALUE;
95af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                }
960244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                break;
97af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            case OMX_VIDEO_MPEG4ProfileCore:
98af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                switch (omxLevel) {
99af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level1:
100af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = CORE_PROFILE_LEVEL1;
101af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
102af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level2:
103af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = CORE_PROFILE_LEVEL2;
104af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
105af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    default:
106af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        LOGE("Unsupported level (%d) for MPEG4 core "
107af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                             "profile", omxLevel);
108af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        return BAD_VALUE;
109af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                }
1100244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                break;
111af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            case OMX_VIDEO_MPEG4ProfileCoreScalable:
112af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                switch (omxLevel) {
113af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level1:
114af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL1;
115af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
116af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level2:
117af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL2;
118af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
119af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    case OMX_VIDEO_MPEG4Level3:
120af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        profileLevel = CORE_SCALABLE_PROFILE_LEVEL3;
121af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        break;
122af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                    default:
123af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        LOGE("Unsupported level (%d) for MPEG4 core "
124af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                             "scalable profile", omxLevel);
125af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        return BAD_VALUE;
126af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                }
1270244d94455236abd1c07e62f0e6cbbff37bf2c8cJames Dong                break;
128af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            default:
129af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                LOGE("Unsupported MPEG4 profile (%d)", omxProfile);
130af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                return BAD_VALUE;
131af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        }
132af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    }
133af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong
134af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    *pvProfileLevel = profileLevel;
135af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    return OK;
136af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong}
137af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong
13842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Donginline static void ConvertYUV420SemiPlanarToYUV420Planar(
13942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        uint8_t *inyuv, uint8_t* outyuv,
14042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        int32_t width, int32_t height) {
14142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
14242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int32_t outYsize = width * height;
14342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint32_t *outy = (uint32_t *)  outyuv;
14442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
14542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
14642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
14742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    /* Y copying */
14842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    memcpy(outy, inyuv, outYsize);
14942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
15042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    /* U & V copying */
15142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
15242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    for (int32_t i = height >> 1; i > 0; --i) {
15342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        for (int32_t j = width >> 2; j > 0; --j) {
15442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            uint32_t temp = *inyuv_4++;
15542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            uint32_t tempU = temp & 0xFF;
15642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            tempU = tempU | ((temp >> 8) & 0xFF00);
15742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
15842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            uint32_t tempV = (temp >> 8) & 0xFF;
15942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            tempV = tempV | ((temp >> 16) & 0xFF00);
16042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
16142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            // Flip U and V
16242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            *outcb++ = tempV;
16342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            *outcr++ = tempU;
16442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        }
16542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
16642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
16742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
16842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames DongM4vH263Encoder::M4vH263Encoder(
16942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        const sp<MediaSource>& source,
17042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        const sp<MetaData>& meta)
17142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    : mSource(source),
17242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mMeta(meta),
17342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mNumInputFrames(-1),
17442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mNextModTimeUs(0),
175e95d192fae5a80ed821c53bfea214a85ea395e90James Dong      mPrevTimestampUs(-1),
17642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mStarted(false),
17742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mInputBuffer(NULL),
17842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mInputFrameData(NULL),
17942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong      mGroup(NULL) {
18042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
1816312dd6d2b19d158773d14ed8cefa3f20272d488James Dong    LOGI("Construct software M4vH263Encoder");
18242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
18342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mHandle = new tagvideoEncControls;
18442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    memset(mHandle, 0, sizeof(tagvideoEncControls));
18542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
18642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mInitCheck = initCheck(meta);
18742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
18842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
18942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames DongM4vH263Encoder::~M4vH263Encoder() {
19042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("Destruct software M4vH263Encoder");
19142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mStarted) {
19242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        stop();
19342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
19442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
19542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    delete mEncParams;
19642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    delete mHandle;
19742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
19842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
19942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongstatus_t M4vH263Encoder::initCheck(const sp<MetaData>& meta) {
20042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("initCheck");
20142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
20242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
203aac193cf38ac084eea0f6367b98f6304d1ec38f2James Dong    CHECK(meta->findInt32(kKeyFrameRate, &mVideoFrameRate));
20442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
20542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
20642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // XXX: Add more color format support
20742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
20842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
20942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
21042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            LOGE("Color format %d is not supported", mVideoColorFormat);
21142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            return BAD_VALUE;
21242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        }
21342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        // Allocate spare buffer only when color conversion is needed.
21442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
21542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputFrameData =
21642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
21742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        CHECK(mInputFrameData);
21842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
21942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
22042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // XXX: Remove this restriction
22142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
22242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGE("Video frame size %dx%d must be a multiple of 16",
22342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            mVideoWidth, mVideoHeight);
22442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return BAD_VALUE;
22542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
22642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
22742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams = new tagvideoEncOptions;
22842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    memset(mEncParams, 0, sizeof(tagvideoEncOptions));
22942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!PVGetDefaultEncOption(mEncParams, 0)) {
23042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGE("Failed to get default encoding parameters");
23142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return BAD_VALUE;
23242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
23342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
23442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Need to know which role the encoder is in.
23542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // XXX: Set the mode proper for other types of applications
23642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    //      like streaming or video conference
23742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    const char *mime;
23842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findCString(kKeyMIMEType, &mime));
23942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
24042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong          !strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263));
24142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
24242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mEncParams->encMode = COMBINE_MODE_WITH_ERR_RES;
24342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    } else {
24442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mEncParams->encMode = H263_MODE;
24542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
24642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->encWidth[0] = mVideoWidth;
24742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->encHeight[0] = mVideoHeight;
24842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->encFrameRate[0] = mVideoFrameRate;
24942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->rcType = VBR_1;
25042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->vbvDelay = (float)5.0;
25142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
25242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Set profile and level
25342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // If profile and level setting is not correct, failure
25442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // is reported when the encoder is initialized.
25542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->profile_level = CORE_PROFILE_LEVEL2;
256af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    int32_t profile, level;
257af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong    if (meta->findInt32(kKeyVideoProfile, &profile) &&
258af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        meta->findInt32(kKeyVideoLevel, &level)) {
259af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        if (OK != ConvertOmxProfileLevel(
260af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        mEncParams->encMode, profile, level,
261af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong                        &mEncParams->profile_level)) {
262af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong            return BAD_VALUE;
263af50969f079901e18f9ba3a68a3d3e54e5f26a08James Dong        }
26442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
26542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
26642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->packetSize = 32;
26742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->rvlcEnable = PV_OFF;
26842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->numLayers = 1;
26942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->timeIncRes = 1000;
27042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
27142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
27242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->bitRate[0] = mVideoBitRate;
27342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->iQuant[0] = 15;
27442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->pQuant[0] = 12;
27542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->quantType[0] = 0;
27642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->noFrameSkipped = PV_OFF;
27742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
27842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Set IDR frame refresh interval
27942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int32_t iFramesIntervalSec;
28042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
28142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (iFramesIntervalSec < 0) {
28242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mEncParams->intraPeriod = -1;
28342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    } else if (iFramesIntervalSec == 0) {
28442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mEncParams->intraPeriod = 1;  // All I frames
28542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    } else {
28642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mEncParams->intraPeriod =
28742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            (iFramesIntervalSec * mVideoFrameRate);
28842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
28942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
29042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->numIntraMB = 0;
29142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->sceneDetect = PV_ON;
29242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->searchRange = 16;
29342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->mv8x8Enable = PV_OFF;
29442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->gobHeaderInterval = 0;
29542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->useACPred = PV_ON;
29642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mEncParams->intraDCVlcTh = 0;
29742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
29842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat = new MetaData;
29942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setInt32(kKeyWidth, mVideoWidth);
30042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setInt32(kKeyHeight, mVideoHeight);
30142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setInt32(kKeyBitRate, mVideoBitRate);
302aac193cf38ac084eea0f6367b98f6304d1ec38f2James Dong    mFormat->setInt32(kKeyFrameRate, mVideoFrameRate);
30342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
30442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
30542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setCString(kKeyMIMEType, mime);
30642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mFormat->setCString(kKeyDecoderComponent, "M4vH263Encoder");
30742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    return OK;
30842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
30942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
31042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongstatus_t M4vH263Encoder::start(MetaData *params) {
31142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("start");
31242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mInitCheck != OK) {
31342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return mInitCheck;
31442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
31542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
31642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mStarted) {
31742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGW("Call start() when encoder already started");
31842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return OK;
31942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
32042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
32142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!PVInitVideoEncoder(mHandle, mEncParams)) {
32242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGE("Failed to initialize the encoder");
32342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return UNKNOWN_ERROR;
32442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
32542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
32642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mGroup = new MediaBufferGroup();
32742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int32_t maxSize;
32842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!PVGetMaxVideoFrameSize(mHandle, &maxSize)) {
32942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        maxSize = 256 * 1024;  // Magic #
33042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
33142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("Max output buffer size: %d", maxSize);
33242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mGroup->add_buffer(new MediaBuffer(maxSize));
33342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
33442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mSource->start(params);
33542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mNumInputFrames = -1;  // 1st frame contains codec specific data
33642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mStarted = true;
33742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
33842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    return OK;
33942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
34042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
34142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongstatus_t M4vH263Encoder::stop() {
34242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("stop");
34342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!mStarted) {
34442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGW("Call stop() when encoder has not started");
34542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return OK;
34642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
34742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
34842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mInputBuffer) {
34942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer->release();
35042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer = NULL;
35142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
35242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
35342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mGroup) {
35442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        delete mGroup;
35542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mGroup = NULL;
35642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
35742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
35842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mInputFrameData) {
35942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        delete mInputFrameData;
36042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputFrameData = NULL;
36142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
36242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
36342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(PVCleanUpVideoEncoder(mHandle));
36442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
36542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mSource->stop();
36642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mStarted = false;
36742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
36842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    return OK;
36942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
37042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
37142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongsp<MetaData> M4vH263Encoder::getFormat() {
37242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    LOGV("getFormat");
37342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    return mFormat;
37442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
37542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
37642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongstatus_t M4vH263Encoder::read(
37742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        MediaBuffer **out, const ReadOptions *options) {
37842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
37942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    *out = NULL;
38042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
38142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    MediaBuffer *outputBuffer;
38242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
38342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint8_t *outPtr = (uint8_t *) outputBuffer->data();
38442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int32_t dataLength = outputBuffer->size();
38542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
38642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Output codec specific data
38742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mNumInputFrames < 0) {
38842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        if (!PVGetVolHeader(mHandle, outPtr, &dataLength, 0)) {
38942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            LOGE("Failed to get VOL header");
39042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            return UNKNOWN_ERROR;
39142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        }
39242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGV("Output VOL header: %d bytes", dataLength);
39342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
39442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->set_range(0, dataLength);
39542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        *out = outputBuffer;
39642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        ++mNumInputFrames;
39742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return OK;
39842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
39942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
40042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Ready for accepting an input video frame
401d39e8f4c2319087c439b456d3793109330f1c8b0James Dong    status_t err = mSource->read(&mInputBuffer, options);
402d39e8f4c2319087c439b456d3793109330f1c8b0James Dong    if (OK != err) {
403d39e8f4c2319087c439b456d3793109330f1c8b0James Dong        if (err != ERROR_END_OF_STREAM) {
404d39e8f4c2319087c439b456d3793109330f1c8b0James Dong            LOGE("Failed to read from data source");
405d39e8f4c2319087c439b456d3793109330f1c8b0James Dong        }
40642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->release();
407d39e8f4c2319087c439b456d3793109330f1c8b0James Dong        return err;
40842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
409e6daea5940c38267d24a39fc32bffa119132e852James Dong
410e6daea5940c38267d24a39fc32bffa119132e852James Dong    if (mInputBuffer->size() - ((mVideoWidth * mVideoHeight * 3) >> 1) != 0) {
411e6daea5940c38267d24a39fc32bffa119132e852James Dong        outputBuffer->release();
412e6daea5940c38267d24a39fc32bffa119132e852James Dong        mInputBuffer->release();
413e6daea5940c38267d24a39fc32bffa119132e852James Dong        mInputBuffer = NULL;
414e6daea5940c38267d24a39fc32bffa119132e852James Dong        return UNKNOWN_ERROR;
415e6daea5940c38267d24a39fc32bffa119132e852James Dong    }
416e6daea5940c38267d24a39fc32bffa119132e852James Dong
41742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int64_t timeUs;
41842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
419708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong
420708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    // When the timestamp of the current sample is the same as that
421708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    // of the previous sample, encoding of the current sample is
422708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    // bypassed, and the output length of the sample is set to 0
423708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    if (mNumInputFrames >= 1 &&
424708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong        (mNextModTimeUs > timeUs || mPrevTimestampUs == timeUs)) {
425708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong        // Frame arrives too late
42642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->set_range(0, 0);
42742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        *out = outputBuffer;
42842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer->release();
42942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer = NULL;
43042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return OK;
43142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
43242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
433708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    // Don't accept out-of-order samples
434708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    CHECK(mPrevTimestampUs < timeUs);
435708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong    mPrevTimestampUs = timeUs;
436708ec39c21568e0c2aa3d20c681f0e14ee6134adJames Dong
43742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Color convert to OMX_COLOR_FormatYUV420Planar if necessary
43842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
43942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    uint8_t *inPtr = (uint8_t *) mInputBuffer->data();
44042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
44142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        CHECK(mInputFrameData);
44242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
44342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        ConvertYUV420SemiPlanarToYUV420Planar(
44442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            inPtr, mInputFrameData, mVideoWidth, mVideoHeight);
44542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        inPtr = mInputFrameData;
44642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
44742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK(inPtr != NULL);
44842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
44942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    // Ready for encoding a video frame
45042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    VideoEncFrameIO vin, vout;
45142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.height = ((mVideoHeight + 15) >> 4) << 4;
45242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.pitch  = ((mVideoWidth  + 15) >> 4) << 4;
45342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.timestamp = (timeUs + 500) / 1000; // in ms
45442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.yChan = inPtr;
45542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.uChan = vin.yChan + vin.height * vin.pitch;
45642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
45742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    unsigned long modTimeMs = 0;
45842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    int32_t nLayer = 0;
45942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    MP4HintTrack hintTrack;
46042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (!PVEncodeVideoFrame(mHandle, &vin, &vout,
46142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            &modTimeMs, outPtr, &dataLength, &nLayer) ||
46242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        !PVGetHintTrack(mHandle, &hintTrack)) {
46342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        LOGE("Failed to encode frame or get hink track at frame %lld",
46442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong            mNumInputFrames);
46542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->release();
46642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer->release();
46742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        mInputBuffer = NULL;
46842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        return UNKNOWN_ERROR;
46942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
47042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    CHECK_EQ(NULL, PVGetOverrunBuffer(mHandle));
47142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    if (hintTrack.CodeType == 0) {  // I-frame serves as sync frame
47242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong        outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
47342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    }
47442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
47542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    ++mNumInputFrames;
47642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mNextModTimeUs = modTimeMs * 1000LL;
47742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    outputBuffer->set_range(0, dataLength);
47842ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    *out = outputBuffer;
47942ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mInputBuffer->release();
48042ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    mInputBuffer = NULL;
48142ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong    return OK;
48242ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
48342ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
48442ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dongvoid M4vH263Encoder::signalBufferReturned(MediaBuffer *buffer) {
48542ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}
48642ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong
48742ef0c715da879a9878b7bf4eb9c90b21e4ab8aeJames Dong}  // namespace android
488