470 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
// Copyright 2020 The Chromium Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style license that can be
 | 
						|
// found in the LICENSE file.
 | 
						|
 | 
						|
//#define LOG_NDEBUG 0
 | 
						|
#define LOG_TAG "V4L2EncodeInterface"
 | 
						|
 | 
						|
#include <v4l2_codec2/components/V4L2EncodeInterface.h>
 | 
						|
 | 
						|
#include <inttypes.h>
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
#include <C2PlatformSupport.h>
 | 
						|
#include <SimpleC2Interface.h>
 | 
						|
#include <android/hardware/graphics/common/1.0/types.h>
 | 
						|
#include <media/stagefright/MediaDefs.h>
 | 
						|
#include <utils/Log.h>
 | 
						|
 | 
						|
#include <v4l2_codec2/common/V4L2ComponentCommon.h>
 | 
						|
#include <v4l2_codec2/common/V4L2Device.h>
 | 
						|
#include <v4l2_codec2/common/VideoTypes.h>
 | 
						|
 | 
						|
using android::hardware::graphics::common::V1_0::BufferUsage;
 | 
						|
 | 
						|
namespace android {
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
// Use basic linear block pool/allocator as default.
 | 
						|
constexpr C2BlockPool::local_id_t kDefaultOutputBlockPool = C2BlockPool::BASIC_LINEAR;
 | 
						|
// Default input and output allocators.
 | 
						|
constexpr C2Allocator::id_t kDefaultInputAllocator = C2PlatformAllocatorStore::GRALLOC;
 | 
						|
constexpr C2Allocator::id_t kDefaultOutputAllocator = C2PlatformAllocatorStore::BLOB;
 | 
						|
 | 
						|
// The default output framerate in frames per second.
 | 
						|
// TODO: increase to 60 fps in the future.
 | 
						|
constexpr float kDefaultFrameRate = 30.0;
 | 
						|
// The default output bitrate in bits per second. Use the max bitrate of AVC Level1.0 as default.
 | 
						|
constexpr uint32_t kDefaultBitrate = 64000;
 | 
						|
 | 
						|
// The maximal output bitrate in bits per second. It's the max bitrate of AVC Level4.1.
 | 
						|
// TODO: increase this in the future for supporting higher level/resolution encoding.
 | 
						|
constexpr uint32_t kMaxBitrate = 50000000;
 | 
						|
 | 
						|
std::optional<VideoCodec> getCodecFromComponentName(const std::string& name) {
 | 
						|
    if (name == V4L2ComponentName::kH264Encoder) return VideoCodec::H264;
 | 
						|
    if (name == V4L2ComponentName::kVP8Encoder) return VideoCodec::VP8;
 | 
						|
    if (name == V4L2ComponentName::kVP9Encoder) return VideoCodec::VP9;
 | 
						|
 | 
						|
    ALOGE("Unknown name: %s", name.c_str());
 | 
						|
    return std::nullopt;
 | 
						|
}
 | 
						|
 | 
						|
// Check whether the specified profile is a valid profile for the specified codec.
 | 
						|
bool IsValidProfileForCodec(VideoCodec codec, C2Config::profile_t profile) {
 | 
						|
    switch (codec) {
 | 
						|
    case VideoCodec::H264:
 | 
						|
        return ((profile >= C2Config::PROFILE_AVC_BASELINE) &&
 | 
						|
                (profile <= C2Config::PROFILE_AVC_ENHANCED_MULTIVIEW_DEPTH_HIGH));
 | 
						|
    case VideoCodec::VP8:
 | 
						|
        return ((profile >= C2Config::PROFILE_VP8_0) && (profile <= C2Config::PROFILE_VP8_3));
 | 
						|
    case VideoCodec::VP9:
 | 
						|
        return ((profile >= C2Config::PROFILE_VP9_0) && (profile <= C2Config::PROFILE_VP9_3));
 | 
						|
    default:
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
// static
 | 
						|
C2R V4L2EncodeInterface::H264ProfileLevelSetter(
 | 
						|
        bool /*mayBlock*/, C2P<C2StreamProfileLevelInfo::output>& info,
 | 
						|
        const C2P<C2StreamPictureSizeInfo::input>& videoSize,
 | 
						|
        const C2P<C2StreamFrameRateInfo::output>& frameRate,
 | 
						|
        const C2P<C2StreamBitrateInfo::output>& bitrate) {
 | 
						|
    static C2Config::level_t lowestConfigLevel = C2Config::LEVEL_UNUSED;
 | 
						|
 | 
						|
    // Adopt default minimal profile instead if the requested profile is not supported, or lower
 | 
						|
    // than the default minimal one.
 | 
						|
    constexpr C2Config::profile_t minProfile = C2Config::PROFILE_AVC_BASELINE;
 | 
						|
    if (!info.F(info.v.profile).supportsAtAll(info.v.profile) || info.v.profile < minProfile) {
 | 
						|
        if (info.F(info.v.profile).supportsAtAll(minProfile)) {
 | 
						|
            ALOGV("Set profile to default (%u) instead.", minProfile);
 | 
						|
            info.set().profile = minProfile;
 | 
						|
        } else {
 | 
						|
            ALOGE("Unable to set either requested profile (%u) or default profile (%u).",
 | 
						|
                  info.v.profile, minProfile);
 | 
						|
            return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.profile)));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // Table A-1 in spec
 | 
						|
    struct LevelLimits {
 | 
						|
        C2Config::level_t level;
 | 
						|
        float maxMBPS;   // max macroblock processing rate in macroblocks per second
 | 
						|
        uint64_t maxFS;  // max frame size in macroblocks
 | 
						|
        uint32_t maxBR;  // max video bitrate in bits per second
 | 
						|
    };
 | 
						|
    constexpr LevelLimits kLimits[] = {
 | 
						|
            {C2Config::LEVEL_AVC_1, 1485, 99, 64000},
 | 
						|
            {C2Config::LEVEL_AVC_1B, 1485, 99, 128000},
 | 
						|
            {C2Config::LEVEL_AVC_1_1, 3000, 396, 192000},
 | 
						|
            {C2Config::LEVEL_AVC_1_2, 6000, 396, 384000},
 | 
						|
            {C2Config::LEVEL_AVC_1_3, 11880, 396, 768000},
 | 
						|
            {C2Config::LEVEL_AVC_2, 11880, 396, 2000000},
 | 
						|
            {C2Config::LEVEL_AVC_2_1, 19800, 792, 4000000},
 | 
						|
            {C2Config::LEVEL_AVC_2_2, 20250, 1620, 4000000},
 | 
						|
            {C2Config::LEVEL_AVC_3, 40500, 1620, 10000000},
 | 
						|
            {C2Config::LEVEL_AVC_3_1, 108000, 3600, 14000000},
 | 
						|
            {C2Config::LEVEL_AVC_3_2, 216000, 5120, 20000000},
 | 
						|
            {C2Config::LEVEL_AVC_4, 245760, 8192, 20000000},
 | 
						|
            {C2Config::LEVEL_AVC_4_1, 245760, 8192, 50000000},
 | 
						|
            {C2Config::LEVEL_AVC_4_2, 522240, 8704, 50000000},
 | 
						|
            {C2Config::LEVEL_AVC_5, 589824, 22080, 135000000},
 | 
						|
            {C2Config::LEVEL_AVC_5_1, 983040, 36864, 240000000},
 | 
						|
            {C2Config::LEVEL_AVC_5_2, 2073600, 36864, 240000000},
 | 
						|
    };
 | 
						|
 | 
						|
    uint64_t targetFS =
 | 
						|
            static_cast<uint64_t>((videoSize.v.width + 15) / 16) * ((videoSize.v.height + 15) / 16);
 | 
						|
    float targetMBPS = static_cast<float>(targetFS) * frameRate.v.value;
 | 
						|
 | 
						|
    // Try the recorded lowest configed level. This level should become adaptable after input size,
 | 
						|
    // frame rate, and bitrate are all set.
 | 
						|
    if (lowestConfigLevel != C2Config::LEVEL_UNUSED && lowestConfigLevel < info.v.level) {
 | 
						|
        info.set().level = lowestConfigLevel;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check if the supplied level meets the requirements. If not, update the level with the lowest
 | 
						|
    // level meeting the requirements.
 | 
						|
 | 
						|
    bool found = false;
 | 
						|
    bool needsUpdate = !info.F(info.v.level).supportsAtAll(info.v.level);
 | 
						|
    for (const LevelLimits& limit : kLimits) {
 | 
						|
        if (!info.F(info.v.level).supportsAtAll(limit.level)) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        // Table A-2 in spec
 | 
						|
        // The maximum bit rate for High Profile is 1.25 times that of the Base/Extended/Main
 | 
						|
        // Profiles, 3 times for Hi10P, and 4 times for Hi422P/Hi444PP.
 | 
						|
        uint32_t maxBR = limit.maxBR;
 | 
						|
        if (info.v.profile >= C2Config::PROFILE_AVC_HIGH_422) {
 | 
						|
            maxBR *= 4;
 | 
						|
        } else if (info.v.profile >= C2Config::PROFILE_AVC_HIGH_10) {
 | 
						|
            maxBR *= 3;
 | 
						|
        } else if (info.v.profile >= C2Config::PROFILE_AVC_HIGH) {
 | 
						|
            maxBR = maxBR * 5.0 / 4.0;
 | 
						|
        }
 | 
						|
 | 
						|
        if (targetFS <= limit.maxFS && targetMBPS <= limit.maxMBPS && bitrate.v.value <= maxBR) {
 | 
						|
            // This is the lowest level that meets the requirements, and if
 | 
						|
            // we haven't seen the supplied level yet, that means we don't
 | 
						|
            // need the update.
 | 
						|
            if (needsUpdate) {
 | 
						|
                // Since current config update is sequential, there is an issue when we want to set
 | 
						|
                // lower level for small input size, frame rate, and bitrate, if we set level first,
 | 
						|
                // it will be adjusted to a higher one because the default input size or others are
 | 
						|
                // above the limit. Use lowestConfigLevel to record the level we have tried to
 | 
						|
                // config (but failed).
 | 
						|
                // TODO(johnylin): remove this solution after b/140407694 has proper fix.
 | 
						|
                lowestConfigLevel = info.v.level;
 | 
						|
 | 
						|
                ALOGD("Given level %u does not cover current configuration: "
 | 
						|
                      "adjusting to %u",
 | 
						|
                      info.v.level, limit.level);
 | 
						|
                info.set().level = limit.level;
 | 
						|
            }
 | 
						|
            found = true;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (info.v.level <= limit.level) {
 | 
						|
            // We break out of the loop when the lowest feasible level is found. The fact that we're
 | 
						|
            // here means that our level doesn't meet the requirement and needs to be updated.
 | 
						|
            needsUpdate = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (!found) {
 | 
						|
        ALOGE("Unable to find proper level with current config, requested level (%u).",
 | 
						|
              info.v.level);
 | 
						|
        return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.level)));
 | 
						|
    }
 | 
						|
 | 
						|
    return C2R::Ok();
 | 
						|
}
 | 
						|
 | 
						|
C2R V4L2EncodeInterface::VP9ProfileLevelSetter(
 | 
						|
        bool /*mayBlock*/, C2P<C2StreamProfileLevelInfo::output>& info,
 | 
						|
        const C2P<C2StreamPictureSizeInfo::input>& /*videoSize*/,
 | 
						|
        const C2P<C2StreamFrameRateInfo::output>& /*frameRate*/,
 | 
						|
        const C2P<C2StreamBitrateInfo::output>& /*bitrate*/) {
 | 
						|
    // Adopt default minimal profile instead if the requested profile is not supported, or lower
 | 
						|
    // than the default minimal one.
 | 
						|
    constexpr C2Config::profile_t defaultMinProfile = C2Config::PROFILE_VP9_0;
 | 
						|
    if (!info.F(info.v.profile).supportsAtAll(info.v.profile) ||
 | 
						|
        info.v.profile < defaultMinProfile) {
 | 
						|
        if (info.F(info.v.profile).supportsAtAll(defaultMinProfile)) {
 | 
						|
            ALOGV("Set profile to default (%u) instead.", defaultMinProfile);
 | 
						|
            info.set().profile = defaultMinProfile;
 | 
						|
        } else {
 | 
						|
            ALOGE("Unable to set either requested profile (%u) or default profile (%u).",
 | 
						|
                  info.v.profile, defaultMinProfile);
 | 
						|
            return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.profile)));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return C2R::Ok();
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
C2R V4L2EncodeInterface::SizeSetter(bool mayBlock, C2P<C2StreamPictureSizeInfo::input>& videoSize) {
 | 
						|
    (void)mayBlock;
 | 
						|
    // TODO: maybe apply block limit?
 | 
						|
    return videoSize.F(videoSize.v.width)
 | 
						|
            .validatePossible(videoSize.v.width)
 | 
						|
            .plus(videoSize.F(videoSize.v.height).validatePossible(videoSize.v.height));
 | 
						|
}
 | 
						|
 | 
						|
// static
 | 
						|
C2R V4L2EncodeInterface::IntraRefreshPeriodSetter(bool mayBlock,
 | 
						|
                                                  C2P<C2StreamIntraRefreshTuning::output>& period) {
 | 
						|
    (void)mayBlock;
 | 
						|
    if (period.v.period < 1) {
 | 
						|
        period.set().mode = C2Config::INTRA_REFRESH_DISABLED;
 | 
						|
        period.set().period = 0;
 | 
						|
    } else {
 | 
						|
        // Only support arbitrary mode (cyclic in our case).
 | 
						|
        period.set().mode = C2Config::INTRA_REFRESH_ARBITRARY;
 | 
						|
    }
 | 
						|
    return C2R::Ok();
 | 
						|
}
 | 
						|
 | 
						|
V4L2EncodeInterface::V4L2EncodeInterface(const C2String& name,
 | 
						|
                                         std::shared_ptr<C2ReflectorHelper> helper)
 | 
						|
      : C2InterfaceHelper(std::move(helper)) {
 | 
						|
    ALOGV("%s(%s)", __func__, name.c_str());
 | 
						|
 | 
						|
    setDerivedInstance(this);
 | 
						|
 | 
						|
    Initialize(name);
 | 
						|
}
 | 
						|
 | 
						|
void V4L2EncodeInterface::Initialize(const C2String& name) {
 | 
						|
    scoped_refptr<V4L2Device> device = V4L2Device::create();
 | 
						|
    if (!device) {
 | 
						|
        ALOGE("Failed to create V4L2 device");
 | 
						|
        mInitStatus = C2_CORRUPTED;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    auto codec = getCodecFromComponentName(name);
 | 
						|
    if (!codec) {
 | 
						|
        ALOGE("Invalid component name");
 | 
						|
        mInitStatus = C2_BAD_VALUE;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    V4L2Device::SupportedEncodeProfiles supported_profiles = device->getSupportedEncodeProfiles();
 | 
						|
 | 
						|
    // Compile the list of supported profiles.
 | 
						|
    // Note: unsigned int is used here, since std::vector<C2Config::profile_t> cannot convert to
 | 
						|
    // std::vector<unsigned int> required by the c2 framework below.
 | 
						|
    std::vector<unsigned int> profiles;
 | 
						|
    ui::Size maxSize;
 | 
						|
    for (const auto& supportedProfile : supported_profiles) {
 | 
						|
        if (!IsValidProfileForCodec(codec.value(), supportedProfile.profile)) {
 | 
						|
            continue;  // Ignore unrecognizable or unsupported profiles.
 | 
						|
        }
 | 
						|
        ALOGV("Queried c2_profile = 0x%x : max_size = %d x %d", supportedProfile.profile,
 | 
						|
              supportedProfile.max_resolution.width, supportedProfile.max_resolution.height);
 | 
						|
        profiles.push_back(static_cast<unsigned int>(supportedProfile.profile));
 | 
						|
        maxSize.setWidth(std::max(maxSize.width, supportedProfile.max_resolution.width));
 | 
						|
        maxSize.setHeight(std::max(maxSize.height, supportedProfile.max_resolution.height));
 | 
						|
    }
 | 
						|
 | 
						|
    if (profiles.empty()) {
 | 
						|
        ALOGE("No supported profiles");
 | 
						|
        mInitStatus = C2_BAD_VALUE;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Special note: the order of addParameter matters if your setters are dependent on other
 | 
						|
    //               parameters. Please make sure the dependent parameters are added prior to the
 | 
						|
    //               one needs the setter dependency.
 | 
						|
 | 
						|
    addParameter(DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND)
 | 
						|
                         .withConstValue(new C2ComponentKindSetting(C2Component::KIND_ENCODER))
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mInputVisibleSize, C2_PARAMKEY_PICTURE_SIZE)
 | 
						|
                         .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
 | 
						|
                         .withFields({
 | 
						|
                                 C2F(mInputVisibleSize, width).inRange(2, maxSize.width, 2),
 | 
						|
                                 C2F(mInputVisibleSize, height).inRange(2, maxSize.height, 2),
 | 
						|
                         })
 | 
						|
                         .withSetter(SizeSetter)
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
 | 
						|
                         .withDefault(new C2StreamFrameRateInfo::output(0u, kDefaultFrameRate))
 | 
						|
                         // TODO: More restriction?
 | 
						|
                         .withFields({C2F(mFrameRate, value).greaterThan(0.)})
 | 
						|
                         .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
 | 
						|
                         .withDefault(new C2StreamBitrateInfo::output(0u, kDefaultBitrate))
 | 
						|
                         .withFields({C2F(mBitrate, value).inRange(0, kMaxBitrate)})
 | 
						|
                         .withSetter(Setter<decltype(*mBitrate)>::StrictValueWithNoDeps)
 | 
						|
                         .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());
 | 
						|
 | 
						|
    std::string outputMime;
 | 
						|
    if (getCodecFromComponentName(name) == VideoCodec::H264) {
 | 
						|
        outputMime = MEDIA_MIMETYPE_VIDEO_AVC;
 | 
						|
        C2Config::profile_t minProfile = static_cast<C2Config::profile_t>(
 | 
						|
                *std::min_element(profiles.begin(), profiles.end()));
 | 
						|
        addParameter(
 | 
						|
                DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
 | 
						|
                        .withDefault(new C2StreamProfileLevelInfo::output(0u, minProfile,
 | 
						|
                                                                          C2Config::LEVEL_AVC_4_1))
 | 
						|
                        .withFields(
 | 
						|
                                {C2F(mProfileLevel, profile).oneOf(profiles),
 | 
						|
                                 C2F(mProfileLevel, level)
 | 
						|
                                         // TODO: query supported levels from adaptor.
 | 
						|
                                         .oneOf({C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B,
 | 
						|
                                                 C2Config::LEVEL_AVC_1_1, C2Config::LEVEL_AVC_1_2,
 | 
						|
                                                 C2Config::LEVEL_AVC_1_3, C2Config::LEVEL_AVC_2,
 | 
						|
                                                 C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2,
 | 
						|
                                                 C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1,
 | 
						|
                                                 C2Config::LEVEL_AVC_3_2, C2Config::LEVEL_AVC_4,
 | 
						|
                                                 C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2,
 | 
						|
                                                 C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1})})
 | 
						|
                        .withSetter(H264ProfileLevelSetter, mInputVisibleSize, mFrameRate, mBitrate)
 | 
						|
                        .build());
 | 
						|
    } else if (getCodecFromComponentName(name) == VideoCodec::VP8) {
 | 
						|
        outputMime = MEDIA_MIMETYPE_VIDEO_VP8;
 | 
						|
        // VP8 doesn't have conventional profiles, we'll use profile0 if the VP8 codec is requested.
 | 
						|
        addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
 | 
						|
                             .withConstValue(new C2StreamProfileLevelInfo::output(
 | 
						|
                                     0u, C2Config::PROFILE_VP8_0, C2Config::LEVEL_UNUSED))
 | 
						|
                             .build());
 | 
						|
    } else if (getCodecFromComponentName(name) == VideoCodec::VP9) {
 | 
						|
        outputMime = MEDIA_MIMETYPE_VIDEO_VP9;
 | 
						|
        C2Config::profile_t minProfile = static_cast<C2Config::profile_t>(
 | 
						|
                *std::min_element(profiles.begin(), profiles.end()));
 | 
						|
        addParameter(
 | 
						|
                DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
 | 
						|
                        .withDefault(new C2StreamProfileLevelInfo::output(0u, minProfile,
 | 
						|
                                                                          C2Config::LEVEL_VP9_1))
 | 
						|
                        .withFields(
 | 
						|
                                {C2F(mProfileLevel, profile).oneOf(profiles),
 | 
						|
                                 C2F(mProfileLevel, level)
 | 
						|
                                         // TODO(dstaessens) query supported levels from adaptor.
 | 
						|
                                         .oneOf({C2Config::LEVEL_VP9_1, C2Config::LEVEL_VP9_1_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_2, C2Config::LEVEL_VP9_2_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_3, C2Config::LEVEL_VP9_3_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_4, C2Config::LEVEL_VP9_4_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_5, C2Config::LEVEL_VP9_5_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_5_2, C2Config::LEVEL_VP9_6,
 | 
						|
                                                 C2Config::LEVEL_VP9_6_1,
 | 
						|
                                                 C2Config::LEVEL_VP9_6_2})})
 | 
						|
                        .withSetter(VP9ProfileLevelSetter, mInputVisibleSize, mFrameRate, mBitrate)
 | 
						|
                        .build());
 | 
						|
    } else {
 | 
						|
        ALOGE("Unsupported component name: %s", name.c_str());
 | 
						|
        mInitStatus = C2_BAD_VALUE;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    addParameter(
 | 
						|
            DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE)
 | 
						|
                    .withConstValue(new C2StreamBufferTypeSetting::input(0u, C2BufferData::GRAPHIC))
 | 
						|
                    .build());
 | 
						|
 | 
						|
    // TODO(b/167640667) Add VIDEO_ENCODER flag once input convertor is not enabled by default.
 | 
						|
    // When using the format convertor (which is currently always enabled) it's not useful to add
 | 
						|
    // the VIDEO_ENCODER buffer flag for input buffers here. Currently zero-copy is not supported
 | 
						|
    // yet, so when using this flag an additional buffer will be allocated on host side and a copy
 | 
						|
    // will be performed between the guest and host buffer to keep them in sync. This is wasteful as
 | 
						|
    // the buffer is only used on guest side by the format convertor which converts and copies the
 | 
						|
    // buffer into another buffer.
 | 
						|
    //addParameter(DefineParam(mInputMemoryUsage, C2_PARAMKEY_INPUT_STREAM_USAGE)
 | 
						|
    //                     .withConstValue(new C2StreamUsageTuning::input(
 | 
						|
    //                             0u, static_cast<uint64_t>(BufferUsage::VIDEO_ENCODER)))
 | 
						|
    //                     .build());
 | 
						|
 | 
						|
    addParameter(
 | 
						|
            DefineParam(mOutputFormat, C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE)
 | 
						|
                    .withConstValue(new C2StreamBufferTypeSetting::output(0u, C2BufferData::LINEAR))
 | 
						|
                    .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
 | 
						|
                         .withConstValue(AllocSharedString<C2PortMediaTypeSetting::input>(
 | 
						|
                                 MEDIA_MIMETYPE_VIDEO_RAW))
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
 | 
						|
                         .withConstValue(AllocSharedString<C2PortMediaTypeSetting::output>(
 | 
						|
                                 outputMime.c_str()))
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mIntraRefreshPeriod, C2_PARAMKEY_INTRA_REFRESH)
 | 
						|
                         .withDefault(new C2StreamIntraRefreshTuning::output(
 | 
						|
                                 0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
 | 
						|
                         .withFields({C2F(mIntraRefreshPeriod, mode)
 | 
						|
                                              .oneOf({C2Config::INTRA_REFRESH_DISABLED,
 | 
						|
                                                      C2Config::INTRA_REFRESH_ARBITRARY}),
 | 
						|
                                      C2F(mIntraRefreshPeriod, period).any()})
 | 
						|
                         .withSetter(IntraRefreshPeriodSetter)
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mRequestKeyFrame, C2_PARAMKEY_REQUEST_SYNC_FRAME)
 | 
						|
                         .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
 | 
						|
                         .withFields({C2F(mRequestKeyFrame, value).oneOf({C2_FALSE, C2_TRUE})})
 | 
						|
                         .withSetter(Setter<decltype(*mRequestKeyFrame)>::NonStrictValueWithNoDeps)
 | 
						|
                         .build());
 | 
						|
 | 
						|
    addParameter(DefineParam(mKeyFramePeriodUs, C2_PARAMKEY_SYNC_FRAME_INTERVAL)
 | 
						|
                         .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000))
 | 
						|
                         .withFields({C2F(mKeyFramePeriodUs, value).any()})
 | 
						|
                         .withSetter(Setter<decltype(*mKeyFramePeriodUs)>::StrictValueWithNoDeps)
 | 
						|
                         .build());
 | 
						|
 | 
						|
    C2Allocator::id_t inputAllocators[] = {kDefaultInputAllocator};
 | 
						|
 | 
						|
    C2Allocator::id_t outputAllocators[] = {kDefaultOutputAllocator};
 | 
						|
 | 
						|
    addParameter(
 | 
						|
            DefineParam(mInputAllocatorIds, C2_PARAMKEY_INPUT_ALLOCATORS)
 | 
						|
                    .withConstValue(C2PortAllocatorsTuning::input::AllocShared(inputAllocators))
 | 
						|
                    .build());
 | 
						|
 | 
						|
    addParameter(
 | 
						|
            DefineParam(mOutputAllocatorIds, C2_PARAMKEY_OUTPUT_ALLOCATORS)
 | 
						|
                    .withConstValue(C2PortAllocatorsTuning::output::AllocShared(outputAllocators))
 | 
						|
                    .build());
 | 
						|
 | 
						|
    C2BlockPool::local_id_t outputBlockPools[] = {kDefaultOutputBlockPool};
 | 
						|
 | 
						|
    addParameter(
 | 
						|
            DefineParam(mOutputBlockPoolIds, C2_PARAMKEY_OUTPUT_BLOCK_POOLS)
 | 
						|
                    .withDefault(C2PortBlockPoolsTuning::output::AllocShared(outputBlockPools))
 | 
						|
                    .withFields({C2F(mOutputBlockPoolIds, m.values[0]).any(),
 | 
						|
                                 C2F(mOutputBlockPoolIds, m.values).inRange(0, 1)})
 | 
						|
                    .withSetter(Setter<C2PortBlockPoolsTuning::output>::NonStrictValuesWithNoDeps)
 | 
						|
                    .build());
 | 
						|
 | 
						|
    mInitStatus = C2_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t V4L2EncodeInterface::getKeyFramePeriod() const {
 | 
						|
    if (mKeyFramePeriodUs->value < 0 || mKeyFramePeriodUs->value == INT64_MAX) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    double period = mKeyFramePeriodUs->value / 1e6 * mFrameRate->value;
 | 
						|
    return static_cast<uint32_t>(std::max(std::min(std::round(period), double(UINT32_MAX)), 1.));
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace android
 |