1/*
2 * Copyright (C) 2013 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 "SoftVPXEncoder"
19#include "SoftVPXEncoder.h"
20
21#include "SoftVP8Encoder.h"
22#include "SoftVP9Encoder.h"
23
24#include <utils/Log.h>
25#include <utils/misc.h>
26
27#include <media/hardware/HardwareAPI.h>
28#include <media/hardware/MetadataBufferType.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/MediaDefs.h>
31
32#ifndef INT32_MAX
33#define INT32_MAX   2147483647
34#endif
35
36namespace android {
37
38template<class T>
39static void InitOMXParams(T *params) {
40    params->nSize = sizeof(T);
41    // OMX IL 1.1.2
42    params->nVersion.s.nVersionMajor = 1;
43    params->nVersion.s.nVersionMinor = 1;
44    params->nVersion.s.nRevision = 2;
45    params->nVersion.s.nStep = 0;
46}
47
48static int GetCPUCoreCount() {
49    int cpuCoreCount = 1;
50#if defined(_SC_NPROCESSORS_ONLN)
51    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
52#else
53    // _SC_NPROC_ONLN must be defined...
54    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
55#endif
56    CHECK_GE(cpuCoreCount, 1);
57    return cpuCoreCount;
58}
59
60SoftVPXEncoder::SoftVPXEncoder(const char *name,
61                               const OMX_CALLBACKTYPE *callbacks,
62                               OMX_PTR appData,
63                               OMX_COMPONENTTYPE **component,
64                               const char* role,
65                               OMX_VIDEO_CODINGTYPE codingType,
66                               const char* mimeType,
67                               int32_t minCompressionRatio,
68                               const CodecProfileLevel *profileLevels,
69                               size_t numProfileLevels)
70    : SoftVideoEncoderOMXComponent(
71            name, role, codingType, profileLevels, numProfileLevels,
72            176 /* width */, 144 /* height */,
73            callbacks, appData, component),
74      mCodecContext(NULL),
75      mCodecConfiguration(NULL),
76      mCodecInterface(NULL),
77      mBitrateUpdated(false),
78      mBitrateControlMode(VPX_VBR),
79      mErrorResilience(OMX_FALSE),
80      mKeyFrameInterval(0),
81      mMinQuantizer(0),
82      mMaxQuantizer(0),
83      mTemporalLayers(0),
84      mTemporalPatternType(OMX_VIDEO_VPXTemporalLayerPatternNone),
85      mTemporalPatternLength(0),
86      mTemporalPatternIdx(0),
87      mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
88      mConversionBuffer(NULL),
89      mKeyFrameRequested(false) {
90    memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
91    mTemporalLayerBitrateRatio[0] = 100;
92
93    const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary
94
95    initPorts(
96            kNumBuffers, kNumBuffers, kMinOutputBufferSize,
97            mimeType, minCompressionRatio);
98}
99
100SoftVPXEncoder::~SoftVPXEncoder() {
101    releaseEncoder();
102}
103
104status_t SoftVPXEncoder::initEncoder() {
105    vpx_codec_err_t codec_return;
106    status_t result = UNKNOWN_ERROR;
107
108    setCodecSpecificInterface();
109    if (mCodecInterface == NULL) {
110        goto CLEAN_UP;
111    }
112    ALOGD("VPx: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u",
113          (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
114          mMinQuantizer, mMaxQuantizer);
115
116    mCodecConfiguration = new vpx_codec_enc_cfg_t;
117    codec_return = vpx_codec_enc_config_default(mCodecInterface,
118                                                mCodecConfiguration,
119                                                0);
120
121    if (codec_return != VPX_CODEC_OK) {
122        ALOGE("Error populating default configuration for vpx encoder.");
123        goto CLEAN_UP;
124    }
125
126    mCodecConfiguration->g_w = mWidth;
127    mCodecConfiguration->g_h = mHeight;
128    mCodecConfiguration->g_threads = GetCPUCoreCount();
129    mCodecConfiguration->g_error_resilient = mErrorResilience;
130
131    // OMX timebase unit is microsecond
132    // g_timebase is in seconds (i.e. 1/1000000 seconds)
133    mCodecConfiguration->g_timebase.num = 1;
134    mCodecConfiguration->g_timebase.den = 1000000;
135    // rc_target_bitrate is in kbps, mBitrate in bps
136    mCodecConfiguration->rc_target_bitrate = (mBitrate + 500) / 1000;
137    mCodecConfiguration->rc_end_usage = mBitrateControlMode;
138    // Disable frame drop - not allowed in MediaCodec now.
139    mCodecConfiguration->rc_dropframe_thresh = 0;
140    // Disable lagged encoding.
141    mCodecConfiguration->g_lag_in_frames = 0;
142    if (mBitrateControlMode == VPX_CBR) {
143        // Disable spatial resizing.
144        mCodecConfiguration->rc_resize_allowed = 0;
145        // Single-pass mode.
146        mCodecConfiguration->g_pass = VPX_RC_ONE_PASS;
147        // Maximum amount of bits that can be subtracted from the target
148        // bitrate - expressed as percentage of the target bitrate.
149        mCodecConfiguration->rc_undershoot_pct = 100;
150        // Maximum amount of bits that can be added to the target
151        // bitrate - expressed as percentage of the target bitrate.
152        mCodecConfiguration->rc_overshoot_pct = 15;
153        // Initial value of the buffer level in ms.
154        mCodecConfiguration->rc_buf_initial_sz = 500;
155        // Amount of data that the encoder should try to maintain in ms.
156        mCodecConfiguration->rc_buf_optimal_sz = 600;
157        // The amount of data that may be buffered by the decoding
158        // application in ms.
159        mCodecConfiguration->rc_buf_sz = 1000;
160        // Enable error resilience - needed for packet loss.
161        mCodecConfiguration->g_error_resilient = 1;
162        // Maximum key frame interval - for CBR boost to 3000
163        mCodecConfiguration->kf_max_dist = 3000;
164        // Encoder determines optimal key frame placement automatically.
165        mCodecConfiguration->kf_mode = VPX_KF_AUTO;
166    }
167
168    // Frames temporal pattern - for now WebRTC like pattern is only supported.
169    switch (mTemporalLayers) {
170        case 0:
171        {
172            mTemporalPatternLength = 0;
173            break;
174        }
175        case 1:
176        {
177            mCodecConfiguration->ts_number_layers = 1;
178            mCodecConfiguration->ts_rate_decimator[0] = 1;
179            mCodecConfiguration->ts_periodicity = 1;
180            mCodecConfiguration->ts_layer_id[0] = 0;
181            mTemporalPattern[0] = kTemporalUpdateLastRefAll;
182            mTemporalPatternLength = 1;
183            break;
184        }
185        case 2:
186        {
187            mCodecConfiguration->ts_number_layers = 2;
188            mCodecConfiguration->ts_rate_decimator[0] = 2;
189            mCodecConfiguration->ts_rate_decimator[1] = 1;
190            mCodecConfiguration->ts_periodicity = 2;
191            mCodecConfiguration->ts_layer_id[0] = 0;
192            mCodecConfiguration->ts_layer_id[1] = 1;
193            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
194            mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
195            mTemporalPattern[2] = kTemporalUpdateLastRefAltRef;
196            mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef;
197            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
198            mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef;
199            mTemporalPattern[6] = kTemporalUpdateLastRefAltRef;
200            mTemporalPattern[7] = kTemporalUpdateNone;
201            mTemporalPatternLength = 8;
202            break;
203        }
204        case 3:
205        {
206            mCodecConfiguration->ts_number_layers = 3;
207            mCodecConfiguration->ts_rate_decimator[0] = 4;
208            mCodecConfiguration->ts_rate_decimator[1] = 2;
209            mCodecConfiguration->ts_rate_decimator[2] = 1;
210            mCodecConfiguration->ts_periodicity = 4;
211            mCodecConfiguration->ts_layer_id[0] = 0;
212            mCodecConfiguration->ts_layer_id[1] = 2;
213            mCodecConfiguration->ts_layer_id[2] = 1;
214            mCodecConfiguration->ts_layer_id[3] = 2;
215            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
216            mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
217            mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
218            mTemporalPattern[3] = kTemporalUpdateNone;
219            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
220            mTemporalPattern[5] = kTemporalUpdateNone;
221            mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef;
222            mTemporalPattern[7] = kTemporalUpdateNone;
223            mTemporalPatternLength = 8;
224            break;
225        }
226        default:
227        {
228            ALOGE("Wrong number of temporal layers %zu", mTemporalLayers);
229            goto CLEAN_UP;
230        }
231    }
232    // Set bitrate values for each layer
233    for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) {
234        mCodecConfiguration->ts_target_bitrate[i] =
235            mCodecConfiguration->rc_target_bitrate *
236            mTemporalLayerBitrateRatio[i] / 100;
237    }
238    if (mKeyFrameInterval > 0) {
239        mCodecConfiguration->kf_max_dist = mKeyFrameInterval;
240        mCodecConfiguration->kf_min_dist = mKeyFrameInterval;
241        mCodecConfiguration->kf_mode = VPX_KF_AUTO;
242    }
243    if (mMinQuantizer > 0) {
244        mCodecConfiguration->rc_min_quantizer = mMinQuantizer;
245    }
246    if (mMaxQuantizer > 0) {
247        mCodecConfiguration->rc_max_quantizer = mMaxQuantizer;
248    }
249    setCodecSpecificConfiguration();
250    mCodecContext = new vpx_codec_ctx_t;
251    codec_return = vpx_codec_enc_init(mCodecContext,
252                                      mCodecInterface,
253                                      mCodecConfiguration,
254                                      0);  // flags
255
256    if (codec_return != VPX_CODEC_OK) {
257        ALOGE("Error initializing vpx encoder");
258        goto CLEAN_UP;
259    }
260
261    // Extra CBR settings
262    if (mBitrateControlMode == VPX_CBR) {
263        codec_return = vpx_codec_control(mCodecContext,
264                                         VP8E_SET_STATIC_THRESHOLD,
265                                         1);
266        if (codec_return == VPX_CODEC_OK) {
267            uint32_t rc_max_intra_target =
268                mCodecConfiguration->rc_buf_optimal_sz * (mFramerate >> 17) / 10;
269            // Don't go below 3 times per frame bandwidth.
270            if (rc_max_intra_target < 300) {
271                rc_max_intra_target = 300;
272            }
273            codec_return = vpx_codec_control(mCodecContext,
274                                             VP8E_SET_MAX_INTRA_BITRATE_PCT,
275                                             rc_max_intra_target);
276        }
277        if (codec_return == VPX_CODEC_OK) {
278            codec_return = vpx_codec_control(mCodecContext,
279                                             VP8E_SET_CPUUSED,
280                                             -8);
281        }
282        if (codec_return != VPX_CODEC_OK) {
283            ALOGE("Error setting cbr parameters for vpx encoder.");
284            goto CLEAN_UP;
285        }
286    }
287
288    codec_return = setCodecSpecificControls();
289
290    if (codec_return != VPX_CODEC_OK) {
291        // The codec specific method would have logged the error.
292        goto CLEAN_UP;
293    }
294
295    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
296        free(mConversionBuffer);
297        mConversionBuffer = NULL;
298        if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
299            ALOGE("b/25812794, Buffer size is too big, width=%d, height=%d.", mWidth, mHeight);
300            goto CLEAN_UP;
301        }
302        mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2);
303        if (mConversionBuffer == NULL) {
304            ALOGE("Allocating conversion buffer failed.");
305            goto CLEAN_UP;
306        }
307    }
308    return OK;
309
310CLEAN_UP:
311    releaseEncoder();
312    return result;
313}
314
315status_t SoftVPXEncoder::releaseEncoder() {
316    if (mCodecContext != NULL) {
317        vpx_codec_destroy(mCodecContext);
318        delete mCodecContext;
319        mCodecContext = NULL;
320    }
321
322    if (mCodecConfiguration != NULL) {
323        delete mCodecConfiguration;
324        mCodecConfiguration = NULL;
325    }
326
327    if (mConversionBuffer != NULL) {
328        free(mConversionBuffer);
329        mConversionBuffer = NULL;
330    }
331
332    // this one is not allocated by us
333    mCodecInterface = NULL;
334
335    return OK;
336}
337
338OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
339                                                   OMX_PTR param) {
340    // can include extension index OMX_INDEXEXTTYPE
341    const int32_t indexFull = index;
342
343    switch (indexFull) {
344        case OMX_IndexParamVideoBitrate: {
345            OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
346                (OMX_VIDEO_PARAM_BITRATETYPE *)param;
347
348            if (!isValidOMXParam(bitrate)) {
349                return OMX_ErrorBadParameter;
350            }
351
352            if (bitrate->nPortIndex != kOutputPortIndex) {
353                return OMX_ErrorUnsupportedIndex;
354            }
355
356            bitrate->nTargetBitrate = mBitrate;
357
358            if (mBitrateControlMode == VPX_VBR) {
359                bitrate->eControlRate = OMX_Video_ControlRateVariable;
360            } else if (mBitrateControlMode == VPX_CBR) {
361                bitrate->eControlRate = OMX_Video_ControlRateConstant;
362            } else {
363                return OMX_ErrorUnsupportedSetting;
364            }
365            return OMX_ErrorNone;
366        }
367
368        case OMX_IndexParamVideoAndroidVp8Encoder:
369            return internalGetAndroidVpxParams(
370                (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
371
372        default:
373            return SoftVideoEncoderOMXComponent::internalGetParameter(index, param);
374    }
375}
376
377OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
378                                                   const OMX_PTR param) {
379    // can include extension index OMX_INDEXEXTTYPE
380    const int32_t indexFull = index;
381
382    switch (indexFull) {
383        case OMX_IndexParamVideoBitrate: {
384            const OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
385                (const OMX_VIDEO_PARAM_BITRATETYPE*) param;
386
387            if (!isValidOMXParam(bitRate)) {
388                return OMX_ErrorBadParameter;
389            }
390
391            return internalSetBitrateParams(bitRate);
392        }
393
394        case OMX_IndexParamVideoAndroidVp8Encoder:
395            return internalSetAndroidVpxParams(
396                (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
397
398        default:
399            return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
400    }
401}
402
403OMX_ERRORTYPE SoftVPXEncoder::setConfig(
404        OMX_INDEXTYPE index, const OMX_PTR _params) {
405    switch (index) {
406        case OMX_IndexConfigVideoIntraVOPRefresh:
407        {
408            OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
409                (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
410
411            if (!isValidOMXParam(params)) {
412                return OMX_ErrorBadParameter;
413            }
414
415            if (params->nPortIndex != kOutputPortIndex) {
416                return OMX_ErrorBadPortIndex;
417            }
418
419            mKeyFrameRequested = params->IntraRefreshVOP;
420            return OMX_ErrorNone;
421        }
422
423        case OMX_IndexConfigVideoBitrate:
424        {
425            OMX_VIDEO_CONFIG_BITRATETYPE *params =
426                (OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
427
428            if (!isValidOMXParam(params)) {
429                return OMX_ErrorBadParameter;
430            }
431
432            if (params->nPortIndex != kOutputPortIndex) {
433                return OMX_ErrorBadPortIndex;
434            }
435
436            if (mBitrate != params->nEncodeBitrate) {
437                mBitrate = params->nEncodeBitrate;
438                mBitrateUpdated = true;
439            }
440            return OMX_ErrorNone;
441        }
442
443        default:
444            return SimpleSoftOMXComponent::setConfig(index, _params);
445    }
446}
447
448OMX_ERRORTYPE SoftVPXEncoder::internalGetBitrateParams(
449        OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
450    if (bitrate->nPortIndex != kOutputPortIndex) {
451        return OMX_ErrorUnsupportedIndex;
452    }
453
454    bitrate->nTargetBitrate = mBitrate;
455
456    if (mBitrateControlMode == VPX_VBR) {
457        bitrate->eControlRate = OMX_Video_ControlRateVariable;
458    } else if (mBitrateControlMode == VPX_CBR) {
459        bitrate->eControlRate = OMX_Video_ControlRateConstant;
460    } else {
461        return OMX_ErrorUnsupportedSetting;
462    }
463    return OMX_ErrorNone;
464}
465
466OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
467        const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
468    if (bitrate->nPortIndex != kOutputPortIndex) {
469        return OMX_ErrorUnsupportedIndex;
470    }
471
472    mBitrate = bitrate->nTargetBitrate;
473
474    if (bitrate->eControlRate == OMX_Video_ControlRateVariable) {
475        mBitrateControlMode = VPX_VBR;
476    } else if (bitrate->eControlRate == OMX_Video_ControlRateConstant) {
477        mBitrateControlMode = VPX_CBR;
478    } else {
479        return OMX_ErrorUnsupportedSetting;
480    }
481
482    return OMX_ErrorNone;
483}
484
485OMX_ERRORTYPE SoftVPXEncoder::internalGetAndroidVpxParams(
486        OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
487    if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
488        return OMX_ErrorUnsupportedIndex;
489    }
490
491    vpxAndroidParams->nKeyFrameInterval = mKeyFrameInterval;
492    vpxAndroidParams->eTemporalPattern = mTemporalPatternType;
493    vpxAndroidParams->nTemporalLayerCount = mTemporalLayers;
494    vpxAndroidParams->nMinQuantizer = mMinQuantizer;
495    vpxAndroidParams->nMaxQuantizer = mMaxQuantizer;
496    memcpy(vpxAndroidParams->nTemporalLayerBitrateRatio,
497           mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
498    return OMX_ErrorNone;
499}
500
501OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVpxParams(
502        const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
503    if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
504        return OMX_ErrorUnsupportedIndex;
505    }
506    if (vpxAndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone &&
507            vpxAndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
508        return OMX_ErrorBadParameter;
509    }
510    if (vpxAndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
511        return OMX_ErrorBadParameter;
512    }
513    if (vpxAndroidParams->nMinQuantizer > vpxAndroidParams->nMaxQuantizer) {
514        return OMX_ErrorBadParameter;
515    }
516
517    mTemporalPatternType = vpxAndroidParams->eTemporalPattern;
518    if (vpxAndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
519        mTemporalLayers = vpxAndroidParams->nTemporalLayerCount;
520    } else if (vpxAndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) {
521        mTemporalLayers = 0;
522    }
523    // Check the bitrate distribution between layers is in increasing order
524    if (mTemporalLayers > 1) {
525        for (size_t i = 0; i < mTemporalLayers - 1; i++) {
526            if (vpxAndroidParams->nTemporalLayerBitrateRatio[i + 1] <=
527                    vpxAndroidParams->nTemporalLayerBitrateRatio[i]) {
528                ALOGE("Wrong bitrate ratio - should be in increasing order.");
529                return OMX_ErrorBadParameter;
530            }
531        }
532    }
533    mKeyFrameInterval = vpxAndroidParams->nKeyFrameInterval;
534    mMinQuantizer = vpxAndroidParams->nMinQuantizer;
535    mMaxQuantizer = vpxAndroidParams->nMaxQuantizer;
536    memcpy(mTemporalLayerBitrateRatio, vpxAndroidParams->nTemporalLayerBitrateRatio,
537            sizeof(mTemporalLayerBitrateRatio));
538    ALOGD("VPx: internalSetAndroidVpxParams. BRMode: %u. TS: %zu. KF: %u."
539            " QP: %u - %u BR0: %u. BR1: %u. BR2: %u",
540            (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
541            mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0],
542            mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]);
543    return OMX_ErrorNone;
544}
545
546vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() {
547    vpx_enc_frame_flags_t flags = 0;
548    if (mTemporalPatternLength > 0) {
549      int patternIdx = mTemporalPatternIdx % mTemporalPatternLength;
550      mTemporalPatternIdx++;
551      switch (mTemporalPattern[patternIdx]) {
552          case kTemporalUpdateLast:
553              flags |= VP8_EFLAG_NO_UPD_GF;
554              flags |= VP8_EFLAG_NO_UPD_ARF;
555              flags |= VP8_EFLAG_NO_REF_GF;
556              flags |= VP8_EFLAG_NO_REF_ARF;
557              break;
558          case kTemporalUpdateGoldenWithoutDependency:
559              flags |= VP8_EFLAG_NO_REF_GF;
560              // Deliberately no break here.
561          case kTemporalUpdateGolden:
562              flags |= VP8_EFLAG_NO_REF_ARF;
563              flags |= VP8_EFLAG_NO_UPD_ARF;
564              flags |= VP8_EFLAG_NO_UPD_LAST;
565              break;
566          case kTemporalUpdateAltrefWithoutDependency:
567              flags |= VP8_EFLAG_NO_REF_ARF;
568              flags |= VP8_EFLAG_NO_REF_GF;
569              // Deliberately no break here.
570          case kTemporalUpdateAltref:
571              flags |= VP8_EFLAG_NO_UPD_GF;
572              flags |= VP8_EFLAG_NO_UPD_LAST;
573              break;
574          case kTemporalUpdateNoneNoRefAltref:
575              flags |= VP8_EFLAG_NO_REF_ARF;
576              // Deliberately no break here.
577          case kTemporalUpdateNone:
578              flags |= VP8_EFLAG_NO_UPD_GF;
579              flags |= VP8_EFLAG_NO_UPD_ARF;
580              flags |= VP8_EFLAG_NO_UPD_LAST;
581              flags |= VP8_EFLAG_NO_UPD_ENTROPY;
582              break;
583          case kTemporalUpdateNoneNoRefGoldenRefAltRef:
584              flags |= VP8_EFLAG_NO_REF_GF;
585              flags |= VP8_EFLAG_NO_UPD_GF;
586              flags |= VP8_EFLAG_NO_UPD_ARF;
587              flags |= VP8_EFLAG_NO_UPD_LAST;
588              flags |= VP8_EFLAG_NO_UPD_ENTROPY;
589              break;
590          case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
591              flags |= VP8_EFLAG_NO_REF_GF;
592              flags |= VP8_EFLAG_NO_UPD_ARF;
593              flags |= VP8_EFLAG_NO_UPD_LAST;
594              break;
595          case kTemporalUpdateLastRefAltRef:
596              flags |= VP8_EFLAG_NO_UPD_GF;
597              flags |= VP8_EFLAG_NO_UPD_ARF;
598              flags |= VP8_EFLAG_NO_REF_GF;
599              break;
600          case kTemporalUpdateGoldenRefAltRef:
601              flags |= VP8_EFLAG_NO_UPD_ARF;
602              flags |= VP8_EFLAG_NO_UPD_LAST;
603              break;
604          case kTemporalUpdateLastAndGoldenRefAltRef:
605              flags |= VP8_EFLAG_NO_UPD_ARF;
606              flags |= VP8_EFLAG_NO_REF_GF;
607              break;
608          case kTemporalUpdateLastRefAll:
609              flags |= VP8_EFLAG_NO_UPD_ARF;
610              flags |= VP8_EFLAG_NO_UPD_GF;
611              break;
612      }
613    }
614    return flags;
615}
616
617void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
618    // Initialize encoder if not already
619    if (mCodecContext == NULL) {
620        if (OK != initEncoder()) {
621            ALOGE("Failed to initialize encoder");
622            notify(OMX_EventError,
623                   OMX_ErrorUndefined,
624                   0,  // Extra notification data
625                   NULL);  // Notification data pointer
626            return;
627        }
628    }
629
630    vpx_codec_err_t codec_return;
631    List<BufferInfo *> &inputBufferInfoQueue = getPortQueue(kInputPortIndex);
632    List<BufferInfo *> &outputBufferInfoQueue = getPortQueue(kOutputPortIndex);
633
634    while (!inputBufferInfoQueue.empty() && !outputBufferInfoQueue.empty()) {
635        BufferInfo *inputBufferInfo = *inputBufferInfoQueue.begin();
636        OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader;
637
638        BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin();
639        OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
640
641        if ((inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) &&
642                inputBufferHeader->nFilledLen == 0) {
643            inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
644            inputBufferInfo->mOwnedByUs = false;
645            notifyEmptyBufferDone(inputBufferHeader);
646
647            outputBufferHeader->nFilledLen = 0;
648            outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS;
649
650            outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
651            outputBufferInfo->mOwnedByUs = false;
652            notifyFillBufferDone(outputBufferHeader);
653            return;
654        }
655
656        OMX_ERRORTYPE error = validateInputBuffer(inputBufferHeader);
657        if (error != OMX_ErrorNone) {
658            ALOGE("b/27569635");
659            android_errorWriteLog(0x534e4554, "27569635");
660            notify(OMX_EventError, error, 0, 0);
661            return;
662        }
663        const uint8_t *source =
664            inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
665
666        size_t frameSize = mWidth * mHeight * 3 / 2;
667        if (mInputDataIsMeta) {
668            source = extractGraphicBuffer(
669                    mConversionBuffer, frameSize,
670                    source, inputBufferHeader->nFilledLen,
671                    mWidth, mHeight);
672            if (source == NULL) {
673                ALOGE("Unable to extract gralloc buffer in metadata mode");
674                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
675                return;
676            }
677        } else {
678            if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
679                ConvertYUV420SemiPlanarToYUV420Planar(
680                        source, mConversionBuffer, mWidth, mHeight);
681
682                source = mConversionBuffer;
683            }
684        }
685        vpx_image_t raw_frame;
686        vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
687                     kInputBufferAlignment, (uint8_t *)source);
688
689        vpx_enc_frame_flags_t flags = getEncodeFlags();
690        if (mKeyFrameRequested) {
691            flags |= VPX_EFLAG_FORCE_KF;
692            mKeyFrameRequested = false;
693        }
694
695        if (mBitrateUpdated) {
696            mCodecConfiguration->rc_target_bitrate = mBitrate/1000;
697            vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext,
698                                                           mCodecConfiguration);
699            if (res != VPX_CODEC_OK) {
700                ALOGE("vpx encoder failed to update bitrate: %s",
701                      vpx_codec_err_to_string(res));
702                notify(OMX_EventError,
703                       OMX_ErrorUndefined,
704                       0, // Extra notification data
705                       NULL); // Notification data pointer
706            }
707            mBitrateUpdated = false;
708        }
709
710        uint32_t frameDuration;
711        if (inputBufferHeader->nTimeStamp > mLastTimestamp) {
712            frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp);
713        } else {
714            // Use default of 30 fps in case of 0 frame rate.
715            uint32_t framerate = mFramerate ?: (30 << 16);
716            frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / framerate);
717        }
718        mLastTimestamp = inputBufferHeader->nTimeStamp;
719        codec_return = vpx_codec_encode(
720                mCodecContext,
721                &raw_frame,
722                inputBufferHeader->nTimeStamp,  // in timebase units
723                frameDuration,  // frame duration in timebase units
724                flags,  // frame flags
725                VPX_DL_REALTIME);  // encoding deadline
726        if (codec_return != VPX_CODEC_OK) {
727            ALOGE("vpx encoder failed to encode frame");
728            notify(OMX_EventError,
729                   OMX_ErrorUndefined,
730                   0,  // Extra notification data
731                   NULL);  // Notification data pointer
732            return;
733        }
734
735        vpx_codec_iter_t encoded_packet_iterator = NULL;
736        const vpx_codec_cx_pkt_t* encoded_packet;
737
738        while ((encoded_packet = vpx_codec_get_cx_data(
739                        mCodecContext, &encoded_packet_iterator))) {
740            if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) {
741                outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts;
742                outputBufferHeader->nFlags = 0;
743                if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY)
744                    outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
745                outputBufferHeader->nOffset = 0;
746                outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz;
747                if (outputBufferHeader->nFilledLen > outputBufferHeader->nAllocLen) {
748                    android_errorWriteLog(0x534e4554, "27569635");
749                    notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
750                    return;
751                }
752                memcpy(outputBufferHeader->pBuffer,
753                       encoded_packet->data.frame.buf,
754                       encoded_packet->data.frame.sz);
755                outputBufferInfo->mOwnedByUs = false;
756                outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
757                if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
758                    outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
759                }
760                notifyFillBufferDone(outputBufferHeader);
761            }
762        }
763
764        inputBufferInfo->mOwnedByUs = false;
765        inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
766        notifyEmptyBufferDone(inputBufferHeader);
767    }
768}
769
770void SoftVPXEncoder::onReset() {
771    releaseEncoder();
772    mLastTimestamp = 0x7FFFFFFFFFFFFFFFLL;
773}
774
775}  // namespace android
776
777android::SoftOMXComponent *createSoftOMXComponent(
778        const char *name, const OMX_CALLBACKTYPE *callbacks,
779        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
780  if (!strcmp(name, "OMX.google.vp8.encoder")) {
781      return new android::SoftVP8Encoder(name, callbacks, appData, component);
782  } else if (!strcmp(name, "OMX.google.vp9.encoder")) {
783      return new android::SoftVP9Encoder(name, callbacks, appData, component);
784  } else {
785      CHECK(!"Unknown component");
786  }
787  return NULL;
788}
789