Move Codec2-related code from hardware/google/av

Test: None
Bug: 112362730
Change-Id: Ie2f8ff431d65c40333f267ab9877d47089adeea4
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
new file mode 100644
index 0000000..87ed1a9
--- /dev/null
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_C2_SOFT_VPX_ENC_H__
+#define ANDROID_C2_SOFT_VPX_ENC_H__
+
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include <C2PlatformSupport.h>
+#include <Codec2BufferUtils.h>
+#include <SimpleC2Component.h>
+#include <SimpleC2Interface.h>
+#include <util/C2InterfaceHelper.h>
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_image.h"
+#include "vpx/vp8cx.h"
+
+namespace android {
+
+// TODO: These defs taken from deprecated OMX_VideoExt.h. Move these definitions
+// to a new header file and include it.
+
+/** Maximum number of temporal layers */
+#define MAXTEMPORALLAYERS 3
+
+/** temporal layer patterns */
+typedef enum TemporalPatternType {
+    VPXTemporalLayerPatternNone = 0,
+    VPXTemporalLayerPatternWebRTC = 1,
+    VPXTemporalLayerPatternMax = 0x7FFFFFFF
+} TemporalPatternType;
+
+// Base class for a VPX Encoder Component
+//
+// Only following encoder settings are available (codec specific settings might
+// be available in the sub-classes):
+//    - video resolution
+//    - target bitrate
+//    - rate control (constant / variable)
+//    - frame rate
+//    - error resilience
+//    - reconstruction & loop filters (g_profile)
+//
+// Only following color formats are recognized
+//    - C2PlanarLayout::TYPE_RGB
+//    - C2PlanarLayout::TYPE_RGBA
+//
+// Following settings are not configurable by the client
+//    - encoding deadline is realtime
+//    - multithreaded encoding utilizes a number of threads equal
+// to online cpu's available
+//    - the algorithm interface for encoder is decided by the sub-class in use
+//    - fractional bits of frame rate is discarded
+//    - timestamps are in microseconds, therefore encoder timebase is fixed
+// to 1/1000000
+
+struct C2SoftVpxEnc : public SimpleC2Component {
+    class IntfImpl;
+
+    C2SoftVpxEnc(const char* name, c2_node_id_t id,
+                 const std::shared_ptr<IntfImpl>& intfImpl);
+
+    // From SimpleC2Component
+    c2_status_t onInit() override final;
+    c2_status_t onStop() override final;
+    void onReset() override final;
+    void onRelease() override final;
+    c2_status_t onFlush_sm() override final;
+
+    void process(
+            const std::unique_ptr<C2Work> &work,
+            const std::shared_ptr<C2BlockPool> &pool) override final;
+    c2_status_t drain(
+            uint32_t drainMode,
+            const std::shared_ptr<C2BlockPool> &pool) override final;
+
+ protected:
+     std::shared_ptr<IntfImpl> mIntf;
+     virtual ~C2SoftVpxEnc();
+
+     // Initializes vpx encoder with available settings.
+     status_t initEncoder();
+
+     // Populates mCodecInterface with codec specific settings.
+     virtual void setCodecSpecificInterface() = 0;
+
+     // Sets codec specific configuration.
+     virtual void setCodecSpecificConfiguration() = 0;
+
+     // Sets codec specific encoder controls.
+     virtual vpx_codec_err_t setCodecSpecificControls() = 0;
+
+     // Get current encode flags.
+     virtual vpx_enc_frame_flags_t getEncodeFlags();
+
+     enum TemporalReferences {
+         // For 1 layer case: reference all (last, golden, and alt ref), but only
+         // update last.
+         kTemporalUpdateLastRefAll = 12,
+         // First base layer frame for 3 temporal layers, which updates last and
+         // golden with alt ref dependency.
+         kTemporalUpdateLastAndGoldenRefAltRef = 11,
+         // First enhancement layer with alt ref dependency.
+         kTemporalUpdateGoldenRefAltRef = 10,
+         // First enhancement layer with alt ref dependency.
+         kTemporalUpdateGoldenWithoutDependencyRefAltRef = 9,
+         // Base layer with alt ref dependency.
+         kTemporalUpdateLastRefAltRef = 8,
+         // Highest enhacement layer without dependency on golden with alt ref
+         // dependency.
+         kTemporalUpdateNoneNoRefGoldenRefAltRef = 7,
+         // Second layer and last frame in cycle, for 2 layers.
+         kTemporalUpdateNoneNoRefAltref = 6,
+         // Highest enhancement layer.
+         kTemporalUpdateNone = 5,
+         // Second enhancement layer.
+         kTemporalUpdateAltref = 4,
+         // Second enhancement layer without dependency on previous frames in
+         // the second enhancement layer.
+         kTemporalUpdateAltrefWithoutDependency = 3,
+         // First enhancement layer.
+         kTemporalUpdateGolden = 2,
+         // First enhancement layer without dependency on previous frames in
+         // the first enhancement layer.
+         kTemporalUpdateGoldenWithoutDependency = 1,
+         // Base layer.
+         kTemporalUpdateLast = 0,
+     };
+     enum {
+         kMaxTemporalPattern = 8
+     };
+
+     // vpx specific opaque data structure that
+     // stores encoder state
+     vpx_codec_ctx_t* mCodecContext;
+
+     // vpx specific data structure that
+     // stores encoder configuration
+     vpx_codec_enc_cfg_t* mCodecConfiguration;
+
+     // vpx specific read-only data structure
+     // that specifies algorithm interface (e.g. vp8)
+     vpx_codec_iface_t* mCodecInterface;
+
+     // align stride to the power of 2
+     int32_t mStrideAlign;
+
+     // Color format for the input port
+     vpx_img_fmt_t mColorFormat;
+
+     // Bitrate control mode, either constant or variable
+     vpx_rc_mode mBitrateControlMode;
+
+     // Parameter that denotes whether error resilience
+     // is enabled in encoder
+     bool mErrorResilience;
+
+     // Minimum (best quality) quantizer
+     uint32_t mMinQuantizer;
+
+     // Maximum (worst quality) quantizer
+     uint32_t mMaxQuantizer;
+
+     // Number of coding temporal layers to be used.
+     size_t mTemporalLayers;
+
+     // Temporal layer bitrare ratio in percentage
+     uint32_t mTemporalLayerBitrateRatio[MAXTEMPORALLAYERS];
+
+     // Temporal pattern type
+     TemporalPatternType mTemporalPatternType;
+
+     // Temporal pattern length
+     size_t mTemporalPatternLength;
+
+     // Temporal pattern current index
+     size_t mTemporalPatternIdx;
+
+     // Frame type temporal pattern
+     TemporalReferences mTemporalPattern[kMaxTemporalPattern];
+
+     // Last input buffer timestamp
+     uint64_t mLastTimestamp;
+
+     // Number of input frames
+     int64_t mNumInputFrames;
+
+     // Conversion buffer is needed to input to
+     // yuv420 planar format.
+     MemoryBlock mConversionBuffer;
+
+     // Signalled EOS
+     bool mSignalledOutputEos;
+
+     // Signalled Error
+     bool mSignalledError;
+
+    // configurations used by component in process
+    // (TODO: keep this in intf but make them internal only)
+    std::shared_ptr<C2StreamPictureSizeInfo::input> mSize;
+    std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
+    std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
+    std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+    std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+
+     C2_DO_NOT_COPY(C2SoftVpxEnc);
+};
+
+class C2SoftVpxEnc::IntfImpl : public C2InterfaceHelper {
+   public:
+    explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
+        : C2InterfaceHelper(helper) {
+        setDerivedInstance(this);
+
+        addParameter(
+            DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING)
+                .withConstValue(
+                    new C2StreamFormatConfig::input(0u, C2FormatVideo))
+                .build());
+
+        addParameter(
+            DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING)
+                .withConstValue(
+                    new C2StreamFormatConfig::output(0u, C2FormatCompressed))
+                .build());
+
+        addParameter(
+            DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING)
+                .withConstValue(AllocSharedString<C2PortMimeConfig::input>(
+                    MEDIA_MIMETYPE_VIDEO_RAW))
+                .build());
+
+        addParameter(
+            DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING)
+                .withConstValue(AllocSharedString<C2PortMimeConfig::output>(
+#ifdef VP9
+                    MEDIA_MIMETYPE_VIDEO_VP9
+#else
+                    MEDIA_MIMETYPE_VIDEO_VP8
+#endif
+                    ))
+                .build());
+
+        addParameter(DefineParam(mUsage, C2_NAME_INPUT_STREAM_USAGE_SETTING)
+                         .withConstValue(new C2StreamUsageTuning::input(
+                             0u, (uint64_t)C2MemoryUsage::CPU_READ))
+                         .build());
+
+        addParameter(
+            DefineParam(mSize, C2_NAME_STREAM_VIDEO_SIZE_SETTING)
+                .withDefault(new C2VideoSizeStreamTuning::input(0u, 320, 240))
+                .withFields({
+                    C2F(mSize, width).inRange(2, 2048, 2),
+                    C2F(mSize, height).inRange(2, 2048, 2),
+                })
+                .withSetter(SizeSetter)
+                .build());
+
+        addParameter(
+            DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE)
+                .withDefault(new C2StreamBitrateModeTuning::output(
+                        0u, C2Config::BITRATE_CONST))
+                .withFields({
+                    C2F(mBitrateMode, value).oneOf({
+                        C2Config::BITRATE_CONST, C2Config::BITRATE_VARIABLE })
+                })
+                .withSetter(
+                    Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+            DefineParam(mFrameRate, C2_NAME_STREAM_FRAME_RATE_SETTING)
+                .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
+                // TODO: More restriction?
+                .withFields({C2F(mFrameRate, value).greaterThan(0.)})
+                .withSetter(
+                    Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+            DefineParam(mLayering, C2_PARAMKEY_TEMPORAL_LAYERING)
+                .withDefault(C2StreamTemporalLayeringTuning::output::AllocShared(0u, 0, 0, 0))
+                .withFields({
+                    C2F(mLayering, m.layerCount).inRange(0, 4),
+                    C2F(mLayering, m.bLayerCount).inRange(0, 0),
+                    C2F(mLayering, m.bitrateRatios).inRange(0., 1.)
+                })
+                .withSetter(LayeringSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL)
+                .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000))
+                .withFields({C2F(mSyncFramePeriod, value).any()})
+                .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+            DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING)
+                .withDefault(new C2BitrateTuning::output(0u, 64000))
+                .withFields({C2F(mBitrate, value).inRange(4096, 40000000)})
+                .withSetter(BitrateSetter)
+                .build());
+
+        addParameter(
+                DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH)
+                .withConstValue(new C2StreamIntraRefreshTuning::output(
+                             0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
+                .build());
+
+        addParameter(
+        DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+        .withDefault(new C2StreamProfileLevelInfo::output(
+                0u, PROFILE_VP9_0, LEVEL_VP9_4_1))
+        .withFields({
+            C2F(mProfileLevel, profile).equalTo(
+                PROFILE_VP9_0
+            ),
+            C2F(mProfileLevel, level).equalTo(
+                LEVEL_VP9_4_1),
+        })
+        .withSetter(ProfileLevelSetter)
+        .build());
+
+        addParameter(
+                DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
+                .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
+                .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) })
+                .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps)
+                .build());
+    }
+
+    static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
+        (void)mayBlock;
+        C2R res = C2R::Ok();
+        if (me.v.value <= 4096) {
+            me.set().value = 4096;
+        }
+        return res;
+    }
+
+    static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe,
+                          C2P<C2StreamPictureSizeInfo::input> &me) {
+        (void)mayBlock;
+        C2R res = C2R::Ok();
+        if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+            me.set().width = oldMe.v.width;
+        }
+        if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
+            me.set().height = oldMe.v.height;
+        }
+        return res;
+    }
+
+    static C2R ProfileLevelSetter(
+            bool mayBlock,
+            C2P<C2StreamProfileLevelInfo::output> &me) {
+        (void)mayBlock;
+        if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
+            me.set().profile = PROFILE_VP9_0;
+        }
+        if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+            me.set().level = LEVEL_VP9_4_1;
+        }
+        return C2R::Ok();
+    }
+
+    static C2R LayeringSetter(bool mayBlock, C2P<C2StreamTemporalLayeringTuning::output>& me) {
+        (void)mayBlock;
+        C2R res = C2R::Ok();
+        if (me.v.m.layerCount > 4) {
+            me.set().m.layerCount = 4;
+        }
+        me.set().m.bLayerCount = 0;
+        // ensure ratios are monotonic and clamped between 0 and 1
+        for (size_t ix = 0; ix < me.v.flexCount(); ++ix) {
+            me.set().m.bitrateRatios[ix] = c2_clamp(
+                ix > 0 ? me.v.m.bitrateRatios[ix - 1] : 0, me.v.m.bitrateRatios[ix], 1.);
+        }
+        ALOGI("setting temporal layering %u + %u", me.v.m.layerCount, me.v.m.bLayerCount);
+        return res;
+    }
+
+    // unsafe getters
+    std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; }
+    std::shared_ptr<C2StreamIntraRefreshTuning::output> getIntraRefresh_l() const { return mIntraRefresh; }
+    std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
+    std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
+    std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const { return mBitrateMode; }
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; }
+    std::shared_ptr<C2StreamTemporalLayeringTuning::output> getTemporalLayers_l() const { return mLayering; }
+    uint32_t getSyncFramePeriod() const {
+        if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) {
+            return 0;
+        }
+        double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value;
+        return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
+    }
+
+   private:
+    std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
+    std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
+    std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
+    std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
+    std::shared_ptr<C2StreamUsageTuning::input> mUsage;
+    std::shared_ptr<C2VideoSizeStreamTuning::input> mSize;
+    std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
+    std::shared_ptr<C2StreamTemporalLayeringTuning::output> mLayering;
+    std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+    std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
+    std::shared_ptr<C2BitrateTuning::output> mBitrate;
+    std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
+    std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_C2_SOFT_VPX_ENC_H__