static av_cold int nvenc_encode_init(AVCodecContext *avctx)

{

    NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS encode_session_params = { 0 };

    NV_ENC_PRESET_CONFIG preset_config = { 0 };

    CUcontext cu_context_curr;

    CUresult cu_res;

    GUID encoder_preset = NV_ENC_PRESET_HQ_GUID;

    GUID codec;

    NVENCSTATUS nv_status = NV_ENC_SUCCESS;

    AVCPBProperties *cpb_props;

    int surfaceCount = 0;

    int i, num_mbs;

    int isLL = 0;

    int lossless = 0;

    int res = 0;

    int dw, dh;

    int qp_inter_p;

    NvencContext *ctx = avctx->priv_data;

    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;

    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;

    if (!nvenc_dyload_nvenc(avctx))

        return AVERROR_EXTERNAL;

    ctx->last_dts = AV_NOPTS_VALUE;

    ctx->encode_config.version = NV_ENC_CONFIG_VER;

    ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;

    preset_config.version = NV_ENC_PRESET_CONFIG_VER;

    preset_config.presetCfg.version = NV_ENC_CONFIG_VER;

    encode_session_params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;

    encode_session_params.apiVersion = NVENCAPI_VERSION;

    if (ctx->gpu >= dl_fn->nvenc_device_count) {

        av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->gpu, dl_fn->nvenc_device_count);

        res = AVERROR(EINVAL);

        goto error;

    }

    ctx->cu_context = NULL;

    cu_res = dl_fn->cu_ctx_create(&ctx->cu_context, 4, dl_fn->nvenc_devices[ctx->gpu]); // CU_CTX_SCHED_BLOCKING_SYNC=4, avoid CPU spins

    if (cu_res != CUDA_SUCCESS) {

        av_log(avctx, AV_LOG_FATAL, "Failed creating CUDA context for NVENC: 0x%x\n", (int)cu_res);

        res = AVERROR_EXTERNAL;

        goto error;

    }

    cu_res = dl_fn->cu_ctx_pop_current(&cu_context_curr);

    if (cu_res != CUDA_SUCCESS) {

        av_log(avctx, AV_LOG_FATAL, "Failed popping CUDA context: 0x%x\n", (int)cu_res);

        res = AVERROR_EXTERNAL;

        goto error;

    }

    encode_session_params.device = ctx->cu_context;

    encode_session_params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;

    nv_status = p_nvenc->nvEncOpenEncodeSessionEx(&encode_session_params, &ctx->nvencoder);

    if (nv_status != NV_ENC_SUCCESS) {

        ctx->nvencoder = NULL;

        av_log(avctx, AV_LOG_FATAL, "OpenEncodeSessionEx failed: 0x%x\n", (int)nv_status);

        res = AVERROR_EXTERNAL;

        goto error;

    }

    if (ctx->preset) {

        if (!strcmp(ctx->preset, "slow")) {

            encoder_preset = NV_ENC_PRESET_HQ_GUID;

            ctx->twopass = 1;

        } else if (!strcmp(ctx->preset, "medium")) {

            encoder_preset = NV_ENC_PRESET_HQ_GUID;

            ctx->twopass = 0;

        } else if (!strcmp(ctx->preset, "fast")) {

            encoder_preset = NV_ENC_PRESET_HP_GUID;

            ctx->twopass = 0;

        } else if (!strcmp(ctx->preset, "hq")) {

            encoder_preset = NV_ENC_PRESET_HQ_GUID;

        } else if (!strcmp(ctx->preset, "hp")) {

            encoder_preset = NV_ENC_PRESET_HP_GUID;

        } else if (!strcmp(ctx->preset, "bd")) {

            encoder_preset = NV_ENC_PRESET_BD_GUID;

        } else if (!strcmp(ctx->preset, "ll")) {

            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;

            isLL = 1;

        } else if (!strcmp(ctx->preset, "llhp")) {

            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;

            isLL = 1;

        } else if (!strcmp(ctx->preset, "llhq")) {

            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;

            isLL = 1;

        } else if (!strcmp(ctx->preset, "lossless")) {

            encoder_preset = NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID;

            lossless = 1;

        } else if (!strcmp(ctx->preset, "losslesshp")) {

            encoder_preset = NV_ENC_PRESET_LOSSLESS_HP_GUID;

            lossless = 1;

        } else if (!strcmp(ctx->preset, "default")) {

            encoder_preset = NV_ENC_PRESET_DEFAULT_GUID;

        } else {

            av_log(avctx, AV_LOG_FATAL, "Preset \"%s\" is unknown! Supported presets: slow, medium, fast, hp, hq, bd, ll, llhp, llhq, lossless, losslesshp, default\n", ctx->preset);

            res = AVERROR(EINVAL);

            goto error;

        }

    }

    if (ctx->twopass < 0) {

        ctx->twopass = isLL;

    }

    switch (avctx->codec->id) {

    case AV_CODEC_ID_H264:

        codec = NV_ENC_CODEC_H264_GUID;

        break;

    case AV_CODEC_ID_H265:

        codec = NV_ENC_CODEC_HEVC_GUID;

        break;

    default:

        av_log(avctx, AV_LOG_ERROR, "Unknown codec name\n");

        res = AVERROR(EINVAL);

        goto error;

    }

    nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, codec, encoder_preset, &preset_config);

    if (nv_status != NV_ENC_SUCCESS) {

        av_log(avctx, AV_LOG_FATAL, "GetEncodePresetConfig failed: 0x%x\n", (int)nv_status);

        res = AVERROR_EXTERNAL;

        goto error;

    }

    ctx->init_encode_params.encodeGUID = codec;

    ctx->init_encode_params.encodeHeight = avctx->height;

    ctx->init_encode_params.encodeWidth = avctx->width;

    if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&

        (avctx->sample_aspect_ratio.num != 1 || avctx->sample_aspect_ratio.num != 1)) {

        av_reduce(&dw, &dh,

                  avctx->width * avctx->sample_aspect_ratio.num,

                  avctx->height * avctx->sample_aspect_ratio.den,

                  1024 * 1024);

        ctx->init_encode_params.darHeight = dh;

        ctx->init_encode_params.darWidth = dw;

    } else {

        ctx->init_encode_params.darHeight = avctx->height;

        ctx->init_encode_params.darWidth = avctx->width;

    }

    // De-compensate for hardware, dubiously, trying to compensate for

    // playback at 704 pixel width.

    if (avctx->width == 720 &&

        (avctx->height == 480 || avctx->height == 576)) {

        av_reduce(&dw, &dh,

                  ctx->init_encode_params.darWidth * 44,

                  ctx->init_encode_params.darHeight * 45,

                  1024 * 1024);

        ctx->init_encode_params.darHeight = dh;

        ctx->init_encode_params.darWidth = dw;

    }

    ctx->init_encode_params.frameRateNum = avctx->time_base.den;

    ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame;

    num_mbs = ((avctx->width + 15) >> 4) * ((avctx->height + 15) >> 4);

    ctx->max_surface_count = (num_mbs >= 8160) ? 32 : 48;

    if (ctx->buffer_delay >= ctx->max_surface_count)

        ctx->buffer_delay = ctx->max_surface_count - 1;

    ctx->init_encode_params.enableEncodeAsync = 0;

    ctx->init_encode_params.enablePTD = 1;

    ctx->init_encode_params.presetGUID = encoder_preset;

    ctx->init_encode_params.encodeConfig = &ctx->encode_config;

    memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));

    ctx->encode_config.version = NV_ENC_CONFIG_VER;

    if (avctx->refs >= 0) {

        /* 0 means "let the hardware decide" */

        switch (avctx->codec->id) {

        case AV_CODEC_ID_H264:

            ctx->encode_config.encodeCodecConfig.h264Config.maxNumRefFrames = avctx->refs;

            break;

        case AV_CODEC_ID_H265:

            ctx->encode_config.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = avctx->refs;

            break;

        /* Earlier switch/case will return if unknown codec is passed. */

        }

    }

    if (avctx->gop_size > 0) {

        if (avctx->max_b_frames >= 0) {

            /* 0 is intra-only, 1 is I/P only, 2 is one B Frame, 3 two B frames, and so on. */

            ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1;

        }

        ctx->encode_config.gopLength = avctx->gop_size;

        switch (avctx->codec->id) {

        case AV_CODEC_ID_H264:

            ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = avctx->gop_size;

            break;

        case AV_CODEC_ID_H265:

            ctx->encode_config.encodeCodecConfig.hevcConfig.idrPeriod = avctx->gop_size;

            break;

        /* Earlier switch/case will return if unknown codec is passed. */

        }

    } else if (avctx->gop_size == 0) {

        ctx->encode_config.frameIntervalP = 0;

        ctx->encode_config.gopLength = 1;

        switch (avctx->codec->id) {

        case AV_CODEC_ID_H264:

            ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = 1;

            break;

        case AV_CODEC_ID_H265:

            ctx->encode_config.encodeCodecConfig.hevcConfig.idrPeriod = 1;

            break;

        /* Earlier switch/case will return if unknown codec is passed. */

        }

    }

    /* when there're b frames, set dts offset */

    if (ctx->encode_config.frameIntervalP >= 2)

        ctx->last_dts = -2;

    if (avctx->bit_rate > 0) {

        ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;

    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {

        ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate;

    }

    if (avctx->rc_max_rate > 0)

        ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;

    if (lossless) {

        if (avctx->codec->id == AV_CODEC_ID_H264)

            ctx->encode_config.encodeCodecConfig.h264Config.qpPrimeYZeroTransformBypassFlag = 1;

        ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;

        ctx->encode_config.rcParams.constQP.qpInterB = 0;

        ctx->encode_config.rcParams.constQP.qpInterP = 0;

        ctx->encode_config.rcParams.constQP.qpIntra = 0;

        avctx->qmin = -1;

        avctx->qmax = -1;

    } else if (ctx->cbr) {

        if (!ctx->twopass) {

            ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;

        } else {

            ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_QUALITY;

            if (avctx->codec->id == AV_CODEC_ID_H264) {

                ctx->encode_config.encodeCodecConfig.h264Config.adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;

                ctx->encode_config.encodeCodecConfig.h264Config.fmoMode = NV_ENC_H264_FMO_DISABLE;

            }

        }

        if (avctx->codec->id == AV_CODEC_ID_H264) {

            ctx->encode_config.encodeCodecConfig.h264Config.outputBufferingPeriodSEI = 1;

            ctx->encode_config.encodeCodecConfig.h264Config.outputPictureTimingSEI = 1;

        } else if(avctx->codec->id == AV_CODEC_ID_H265) {

            ctx->encode_config.encodeCodecConfig.hevcConfig.outputBufferingPeriodSEI = 1;

            ctx->encode_config.encodeCodecConfig.hevcConfig.outputPictureTimingSEI = 1;

        }

    } else if (avctx->global_quality > 0) {

        ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;

        ctx->encode_config.rcParams.constQP.qpInterB = avctx->global_quality;

        ctx->encode_config.rcParams.constQP.qpInterP = avctx->global_quality;

        ctx->encode_config.rcParams.constQP.qpIntra = avctx->global_quality;

        avctx->qmin = -1;

        avctx->qmax = -1;

    } else {

        if (avctx->qmin >= 0 && avctx->qmax >= 0) {

            ctx->encode_config.rcParams.enableMinQP = 1;

            ctx->encode_config.rcParams.enableMaxQP = 1;

            ctx->encode_config.rcParams.minQP.qpInterB = avctx->qmin;

            ctx->encode_config.rcParams.minQP.qpInterP = avctx->qmin;

            ctx->encode_config.rcParams.minQP.qpIntra = avctx->qmin;

            ctx->encode_config.rcParams.maxQP.qpInterB = avctx->qmax;

            ctx->encode_config.rcParams.maxQP.qpInterP = avctx->qmax;

            ctx->encode_config.rcParams.maxQP.qpIntra = avctx->qmax;

            qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin

            if (ctx->twopass) {

                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_VBR;

                if (avctx->codec->id == AV_CODEC_ID_H264) {

                    ctx->encode_config.encodeCodecConfig.h264Config.adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;

                    ctx->encode_config.encodeCodecConfig.h264Config.fmoMode = NV_ENC_H264_FMO_DISABLE;

                }

            } else {

                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR_MINQP;

            }

        } else {

            qp_inter_p = 26; // default to 26

            if (ctx->twopass) {

                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_VBR;

            } else {

                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;

            }

        }

        ctx->encode_config.rcParams.enableInitialRCQP = 1;

        ctx->encode_config.rcParams.initialRCQP.qpInterP  = qp_inter_p;

        if(avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {

            ctx->encode_config.rcParams.initialRCQP.qpIntra = av_clip(

                qp_inter_p * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);

            ctx->encode_config.rcParams.initialRCQP.qpInterB = av_clip(

                qp_inter_p * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);

        } else {

            ctx->encode_config.rcParams.initialRCQP.qpIntra = qp_inter_p;

            ctx->encode_config.rcParams.initialRCQP.qpInterB = qp_inter_p;

        }

    }

    if (avctx->rc_buffer_size > 0) {

        ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;

    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {

        ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;

    }

    if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {

        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;

    } else {

        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;

    }

    switch (avctx->codec->id) {

    case AV_CODEC_ID_H264:

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourMatrix = avctx->colorspace;

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourPrimaries = avctx->color_primaries;

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.transferCharacteristics = avctx->color_trc;

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG

            || avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || avctx->pix_fmt == AV_PIX_FMT_YUVJ444P);

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag =

            (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);

        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag =

            (ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag

            || ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFormat != 5

            || ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag != 0);

        ctx->encode_config.encodeCodecConfig.h264Config.sliceMode = 3;

        ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData = 1;

        ctx->encode_config.encodeCodecConfig.h264Config.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;

        ctx->encode_config.encodeCodecConfig.h264Config.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;

        ctx->encode_config.encodeCodecConfig.h264Config.outputAUD = 1;

        if (!ctx->profile && !lossless) {

            switch (avctx->profile) {

            case FF_PROFILE_H264_HIGH_444_PREDICTIVE:

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;

                break;

            case FF_PROFILE_H264_BASELINE:

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;

                break;

            case FF_PROFILE_H264_MAIN:

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;

                break;

            case FF_PROFILE_H264_HIGH:

            case FF_PROFILE_UNKNOWN:

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;

                break;

            default:

                av_log(avctx, AV_LOG_WARNING, "Unsupported profile requested, falling back to high\n");

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;

                break;

            }

        } else if(!lossless) {

            if (!strcmp(ctx->profile, "high")) {

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;

                avctx->profile = FF_PROFILE_H264_HIGH;

            } else if (!strcmp(ctx->profile, "main")) {

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;

                avctx->profile = FF_PROFILE_H264_MAIN;

            } else if (!strcmp(ctx->profile, "baseline")) {

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;

                avctx->profile = FF_PROFILE_H264_BASELINE;

            } else if (!strcmp(ctx->profile, "high444p")) {

                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;

                avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;

            } else {

                av_log(avctx, AV_LOG_FATAL, "Profile \"%s\" is unknown! Supported profiles: high, main, baseline\n", ctx->profile);

                res = AVERROR(EINVAL);

                goto error;

            }

        }

        // force setting profile as high444p if input is AV_PIX_FMT_YUV444P

        if (avctx->pix_fmt == AV_PIX_FMT_YUV444P) {

            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;

            avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;

        }

        ctx->encode_config.encodeCodecConfig.h264Config.chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;

        if (ctx->level) {

            res = input_string_to_uint32(avctx, nvenc_h264_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.h264Config.level);

            if (res) {

                av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5, 5.1\n", ctx->level);

                goto error;

            }

        } else {

            ctx->encode_config.encodeCodecConfig.h264Config.level = NV_ENC_LEVEL_AUTOSELECT;

        }

        break;

    case AV_CODEC_ID_H265:

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourMatrix = avctx->colorspace;

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourPrimaries = avctx->color_primaries;

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.transferCharacteristics = avctx->color_trc;

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG

            || avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || avctx->pix_fmt == AV_PIX_FMT_YUVJ444P);

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourDescriptionPresentFlag =

            (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);

        ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoSignalTypePresentFlag =

            (ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourDescriptionPresentFlag

            || ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFormat != 5

            || ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag != 0);

        ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode = 3;

        ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData = 1;

        ctx->encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;

        ctx->encode_config.encodeCodecConfig.hevcConfig.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;

        ctx->encode_config.encodeCodecConfig.hevcConfig.outputAUD = 1;

        /* No other profile is supported in the current SDK version 5 */

        ctx->encode_config.profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;

        avctx->profile = FF_PROFILE_HEVC_MAIN;

        if (ctx->level) {

            res = input_string_to_uint32(avctx, nvenc_hevc_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.hevcConfig.level);

            if (res) {

                av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2\n", ctx->level);

                goto error;

            }

        } else {

            ctx->encode_config.encodeCodecConfig.hevcConfig.level = NV_ENC_LEVEL_AUTOSELECT;

        }

        if (ctx->tier) {

            if (!strcmp(ctx->tier, "main")) {

                ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_MAIN;

            } else if (!strcmp(ctx->tier, "high")) {

                ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_HIGH;

            } else {

                av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier);

                res = AVERROR(EINVAL);

                goto error;

            }

        }

        break;

    /* Earlier switch/case will return if unknown codec is passed. */

    }

    nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);

    if (nv_status != NV_ENC_SUCCESS) {

        av_log(avctx, AV_LOG_FATAL, "InitializeEncoder failed: 0x%x\n", (int)nv_status);

        res = AVERROR_EXTERNAL;

        goto error;

    }

    ctx->input_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->input_surfaces));

    if (!ctx->input_surfaces) {

        res = AVERROR(ENOMEM);

        goto error;

    }

    ctx->output_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->output_surfaces));

    if (!ctx->output_surfaces) {

        res = AVERROR(ENOMEM);

        goto error;

    }

    for (surfaceCount = 0; surfaceCount < ctx->max_surface_count; ++surfaceCount) {

        NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };

        NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };

        allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;

        allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;

        allocSurf.width = (avctx->width + 31) & ~31;

        allocSurf.height = (avctx->height + 31) & ~31;

        allocSurf.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;

        switch (avctx->pix_fmt) {

        case AV_PIX_FMT_YUV420P:

            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YV12_PL;

            break;

        case AV_PIX_FMT_NV12:

            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12_PL;

            break;

        case AV_PIX_FMT_YUV444P:

            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YUV444_PL;

            break;

        default:

            av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n");

            res = AVERROR(EINVAL);

            goto error;

        }

        nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);

        if (nv_status != NV_ENC_SUCCESS) {

            av_log(avctx, AV_LOG_FATAL, "CreateInputBuffer failed\n");

            res = AVERROR_EXTERNAL;

            goto error;

        }

        ctx->input_surfaces[surfaceCount].lockCount = 0;

        ctx->input_surfaces[surfaceCount].input_surface = allocSurf.inputBuffer;

        ctx->input_surfaces[surfaceCount].format = allocSurf.bufferFmt;

        ctx->input_surfaces[surfaceCount].width = allocSurf.width;

        ctx->input_surfaces[surfaceCount].height = allocSurf.height;

        /* 1MB is large enough to hold most output frames. NVENC increases this automaticaly if it's not enough. */

        allocOut.size = 1024 * 1024;

        allocOut.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;

        nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);

        if (nv_status != NV_ENC_SUCCESS) {

            av_log(avctx, AV_LOG_FATAL, "CreateBitstreamBuffer failed\n");

            ctx->output_surfaces[surfaceCount++].output_surface = NULL;

            res = AVERROR_EXTERNAL;

            goto error;

        }

        ctx->output_surfaces[surfaceCount].output_surface = allocOut.bitstreamBuffer;

        ctx->output_surfaces[surfaceCount].size = allocOut.size;

        ctx->output_surfaces[surfaceCount].busy = 0;

    }

    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {

        uint32_t outSize = 0;

        char tmpHeader[256];

        NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };

        payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;

        payload.spsppsBuffer = tmpHeader;

        payload.inBufferSize = sizeof(tmpHeader);

        payload.outSPSPPSPayloadSize = &outSize;

        nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);

        if (nv_status != NV_ENC_SUCCESS) {

            av_log(avctx, AV_LOG_FATAL, "GetSequenceParams failed\n");

            goto error;

        }

        avctx->extradata_size = outSize;

        avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE);

        if (!avctx->extradata) {

            res = AVERROR(ENOMEM);

            goto error;

        }

        memcpy(avctx->extradata, tmpHeader, outSize);

    }

    if (ctx->encode_config.frameIntervalP > 1)

        avctx->has_b_frames = 2;

    if (ctx->encode_config.rcParams.averageBitRate > 0)

        avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;

    cpb_props = ff_add_cpb_side_data(avctx);

    if (!cpb_props)

        return AVERROR(ENOMEM);

    cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate;

    cpb_props->avg_bitrate = avctx->bit_rate;

    cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize;

    return 0;

error:

    for (i = 0; i < surfaceCount; ++i) {

        p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->input_surfaces[i].input_surface);

        if (ctx->output_surfaces[i].output_surface)

            p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->output_surfaces[i].output_surface);

    }

    if (ctx->nvencoder)

        p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);

    if (ctx->cu_context)

        dl_fn->cu_ctx_destroy(ctx->cu_context);

    nvenc_unload_nvenc(avctx);

    ctx->nvencoder = NULL;

    ctx->cu_context = NULL;

    return res;

}


static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,

	unsigned int width, unsigned int height,

	int lumStride, int chromStride, int dstStride)

{

	RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);

}


static void digic_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    dc->realize = digic_realize;
}


vcard_emul_mirror_card(VReader *vreader)

{

    /*

     * lookup certs using the C_FindObjects. The Stan Cert handle won't give

     * us the real certs until we log in.

     */

    PK11GenericObject *firstObj, *thisObj;

    int cert_count;

    unsigned char **certs;

    int *cert_len;

    VCardKey **keys;

    PK11SlotInfo *slot;

    PRBool ret;

    slot = vcard_emul_reader_get_slot(vreader);

    if (slot == NULL) {

        return NULL;

    }

    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);

    if (firstObj == NULL) {

        return NULL;

    }

    /* count the certs */

    cert_count = 0;

    for (thisObj = firstObj; thisObj;

                             thisObj = PK11_GetNextGenericObject(thisObj)) {

        cert_count++;

    }

    if (cert_count == 0) {

        PK11_DestroyGenericObjects(firstObj);

        return NULL;

    }

    /* allocate the arrays */

    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);

    if (ret == PR_FALSE) {

        return NULL;

    }

    /* fill in the arrays */

    cert_count = 0;

    for (thisObj = firstObj; thisObj;

                             thisObj = PK11_GetNextGenericObject(thisObj)) {

        SECItem derCert;

        CERTCertificate *cert;

        SECStatus rv;

        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,

                                   CKA_VALUE, &derCert);

        if (rv != SECSuccess) {

            continue;

        }

        /* create floating temp cert. This gives us a cert structure even if

         * the token isn't logged in */

        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,

                                       NULL, PR_FALSE, PR_TRUE);

        SECITEM_FreeItem(&derCert, PR_FALSE);

        if (cert == NULL) {

            continue;

        }

        certs[cert_count] = cert->derCert.data;

        cert_len[cert_count] = cert->derCert.len;

        keys[cert_count] = vcard_emul_make_key(slot, cert);

        cert_count++;

        CERT_DestroyCertificate(cert); /* key obj still has a reference */

    }

    /* now create the card */

    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);

}


static void gen_neon_trn_u8(TCGv t0, TCGv t1)

{

    TCGv rd, tmp;

    rd = new_tmp();

    tmp = new_tmp();

    tcg_gen_shli_i32(rd, t0, 8);

    tcg_gen_andi_i32(rd, rd, 0xff00ff00);

    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);

    tcg_gen_or_i32(rd, rd, tmp);

    tcg_gen_shri_i32(t1, t1, 8);

    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);

    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);

    tcg_gen_or_i32(t1, t1, tmp);

    tcg_gen_mov_i32(t0, rd);

    dead_tmp(tmp);

    dead_tmp(rd);

}


static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, unsigned src_size)

{

	const uint16_t *end;

#ifdef HAVE_MMX

	const uint16_t *mm_end;

#endif

	uint8_t *d = (uint8_t *)dst;

	const uint16_t *s = (const uint16_t *)src;

	end = s + src_size/2;

#ifdef HAVE_MMX

	__asm __volatile(PREFETCH"	%0"::"m"(*s):"memory");

	__asm __volatile("pxor	%%mm7,%%mm7\n\t":::"memory");

	mm_end = end - 3;

	while(s < mm_end)

	{

	    __asm __volatile(

		PREFETCH" 32%1\n\t"

		"movq	%1, %%mm0\n\t"

		"movq	%1, %%mm1\n\t"

		"movq	%1, %%mm2\n\t"

		"pand	%2, %%mm0\n\t"

		"pand	%3, %%mm1\n\t"

		"pand	%4, %%mm2\n\t"

		"psllq	$3, %%mm0\n\t"

		"psrlq	$2, %%mm1\n\t"

		"psrlq	$7, %%mm2\n\t"

		"movq	%%mm0, %%mm3\n\t"

		"movq	%%mm1, %%mm4\n\t"

		"movq	%%mm2, %%mm5\n\t"

		"punpcklwd %%mm7, %%mm0\n\t"

		"punpcklwd %%mm7, %%mm1\n\t"

		"punpcklwd %%mm7, %%mm2\n\t"

		"punpckhwd %%mm7, %%mm3\n\t"

		"punpckhwd %%mm7, %%mm4\n\t"

		"punpckhwd %%mm7, %%mm5\n\t"

		"psllq	$8, %%mm1\n\t"

		"psllq	$16, %%mm2\n\t"

		"por	%%mm1, %%mm0\n\t"

		"por	%%mm2, %%mm0\n\t"

		"psllq	$8, %%mm4\n\t"

		"psllq	$16, %%mm5\n\t"

		"por	%%mm4, %%mm3\n\t"

		"por	%%mm5, %%mm3\n\t"

		MOVNTQ"	%%mm0, %0\n\t"

		MOVNTQ"	%%mm3, 8%0\n\t"

		:"=m"(*d)

		:"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)

		:"memory");

		d += 16;

		s += 4;

	}

	__asm __volatile(SFENCE:::"memory");

	__asm __volatile(EMMS:::"memory");

#endif

	while(s < end)

	{

#if 0 //slightly slower on athlon

		int bgr= *s++;

		*((uint32_t*)d)++ = ((bgr&0x1F)<<3) + ((bgr&0x3E0)<<6) + ((bgr&0x7C00)<<9);

#else

//FIXME this is very likely wrong for bigendian (and the following converters too)

		register uint16_t bgr;

		bgr = *s++;

#ifdef WORDS_BIGENDIAN

		*d++ = 0;

		*d++ = (bgr&0x1F)<<3;

		*d++ = (bgr&0x3E0)>>2;

		*d++ = (bgr&0x7C00)>>7;

#else

		*d++ = (bgr&0x1F)<<3;

		*d++ = (bgr&0x3E0)>>2;

		*d++ = (bgr&0x7C00)>>7;

		*d++ = 0;

#endif

#endif

	}

}


static int xio3130_upstream_initfn(PCIDevice *d)

{

    PCIEPort *p = PCIE_PORT(d);

    int rc;

    Error *err = NULL;

    pci_bridge_initfn(d, TYPE_PCIE_BUS);

    pcie_port_init_reg(d);

    rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,

                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,

                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT, &err);

    if (rc < 0) {

        assert(rc == -ENOTSUP);

        error_report_err(err);

        goto err_bridge;

    }

    rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,

                               XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);

    if (rc < 0) {

        goto err_bridge;

    }

    rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,

                       p->port);

    if (rc < 0) {

        goto err_msi;

    }

    pcie_cap_flr_init(d);

    pcie_cap_deverr_init(d);

    rc = pcie_aer_init(d, XIO3130_AER_OFFSET, PCI_ERR_SIZEOF);

    if (rc < 0) {

        goto err;

    }

    return 0;

err:

    pcie_cap_exit(d);

err_msi:

    msi_uninit(d);

err_bridge:

    pci_bridge_exitfn(d);

    return rc;

}


int qemu_register_machine(QEMUMachine *m)

{

    TypeInfo ti = {

        .name       = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL),

        .parent     = TYPE_MACHINE,

        .class_init = machine_class_init,

        .class_data = (void *)m,

    };

    type_register(&ti);

    return 0;

}


int64_t migrate_xbzrle_cache_size(void)

{

    MigrationState *s;

    s = migrate_get_current();

    return s->xbzrle_cache_size;

}


static int line_out_init (HWVoiceOut *hw, struct audsettings *as)

{

    SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);

    struct audsettings settings;

#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3

    settings.freq       = spice_server_get_best_playback_rate(NULL);

#else

    settings.freq       = SPICE_INTERFACE_PLAYBACK_FREQ;

#endif

    settings.nchannels  = SPICE_INTERFACE_PLAYBACK_CHAN;

    settings.fmt        = AUD_FMT_S16;

    settings.endianness = AUDIO_HOST_ENDIANNESS;

    audio_pcm_init_info (&hw->info, &settings);

    hw->samples = LINE_OUT_SAMPLES;

    out->active = 0;

    out->sin.base.sif = &playback_sif.base;

    qemu_spice_add_interface (&out->sin.base);

#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3

    spice_server_set_playback_rate(&out->sin, settings.freq);

#endif

    return 0;

}


static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)

{

    int y;

    unsigned char P[2];

    /* 4-color block encoding: each 4x4 block is a different color */

    CHECK_STREAM_PTR(4);

    for (y = 0; y < 8; y++) {

        if (!(y & 3)) {

            P[0] = *s->stream_ptr++;

            P[1] = *s->stream_ptr++;

        }

        memset(s->pixel_ptr,     P[0], 4);

        memset(s->pixel_ptr + 4, P[1], 4);

        s->pixel_ptr += s->stride;

    }

    /* report success */

    return 0;

}


void socket_listen_cleanup(int fd, Error **errp)

{

    SocketAddress *addr;

    addr = socket_local_address(fd, errp);

    if (addr->type == SOCKET_ADDRESS_TYPE_UNIX

        && addr->u.q_unix.path) {

        if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) {

            error_setg_errno(errp, errno,

                             "Failed to unlink socket %s",

                             addr->u.q_unix.path);

    qapi_free_SocketAddress(addr);


int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)

{

    int ret;

    sigset_t val;

    sigset_t *temp = NULL;

    CPUState *cpu = thread_cpu;

    TaskState *ts = (TaskState *)cpu->opaque;

    bool segv_was_blocked = ts->sigsegv_blocked;

    if (set) {

        bool has_sigsegv = sigismember(set, SIGSEGV);

        val = *set;

        temp = &val;

        sigdelset(temp, SIGSEGV);

        switch (how) {

        case SIG_BLOCK:

            if (has_sigsegv) {

                ts->sigsegv_blocked = true;

            }

            break;

        case SIG_UNBLOCK:

            if (has_sigsegv) {

                ts->sigsegv_blocked = false;

            }

            break;

        case SIG_SETMASK:

            ts->sigsegv_blocked = has_sigsegv;

            break;

        default:

            g_assert_not_reached();

        }

    }

    ret = sigprocmask(how, temp, oldset);

    if (oldset && segv_was_blocked) {

        sigaddset(oldset, SIGSEGV);

    }

    return ret;

}


static int process_work_frame(AVFilterContext *ctx)

{

    FrameRateContext *s = ctx->priv;

    int64_t work_pts;

    int interpolate;

    int ret;

    if (!s->f1)

        return 0;

    if (!s->f0 && !s->flush)

        return 0;

    work_pts = s->start_pts + av_rescale_q(s->n, av_inv_q(s->dest_frame_rate), s->dest_time_base);

    if (work_pts >= s->pts1 && !s->flush)

        return 0;

    if (!s->f0) {

        s->work = av_frame_clone(s->f1);

    } else {

        if (work_pts >= s->pts1 + s->delta && s->flush)

            return 0;

        interpolate = av_rescale(work_pts - s->pts0, s->max, s->delta);

        ff_dlog(ctx, "process_work_frame() interpolate:%d/%d\n", interpolate, s->max);

        if (interpolate > s->interp_end) {

            s->work = av_frame_clone(s->f1);

        } else if (interpolate < s->interp_start) {

            s->work = av_frame_clone(s->f0);

        } else {

            ret = blend_frames(ctx, interpolate);

            if (ret < 0)

                return ret;

            if (ret == 0)

                s->work = av_frame_clone(interpolate > (s->max >> 1) ? s->f1 : s->f0);

        }

    }

    if (!s->work)

        return AVERROR(ENOMEM);

    s->work->pts = work_pts;

    s->n++;

    return 1;

}


int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,

                          void *logctx, int is_nalff, int nal_length_size,

                          enum AVCodecID codec_id)

{

    int consumed, ret = 0;

    const uint8_t *next_avc = buf + (is_nalff ? 0 : length);

    pkt->nb_nals = 0;

    while (length >= 4) {

        H2645NAL *nal;

        int extract_length = 0;

        int skip_trailing_zeros = 1;

        /*

         * Only parse an AVC1 length field if one is expected at the current

         * buffer position. There are unfortunately streams with multiple

         * NAL units covered by the length field. Those NAL units are delimited

         * by Annex B start code prefixes. ff_h2645_extract_rbsp() detects it

         * correctly and consumes only the first NAL unit. The additional NAL

         * units are handled here in the Annex B parsing code.

         */

        if (buf == next_avc) {

            int i;

            for (i = 0; i < nal_length_size; i++)

                extract_length = (extract_length << 8) | buf[i];

            if (extract_length > length) {

                av_log(logctx, AV_LOG_ERROR,

                       "Invalid NAL unit size (%d > %d).\n",

                       extract_length, length);

                return AVERROR_INVALIDDATA;

            }

            buf     += nal_length_size;

            length  -= nal_length_size;

            // keep track of the next AVC1 length field

            next_avc = buf + extract_length;

        } else {

            /*

             * expected to return immediately except for streams with mixed

             * NAL unit coding

             */

            int buf_index = find_next_start_code(buf, next_avc);

            buf    += buf_index;

            length -= buf_index;

            /*

             * break if an AVC1 length field is expected at the current buffer

             * position

             */

            if (buf == next_avc)

                continue;

            if (length > 0) {

                extract_length = length;

            } else if (pkt->nb_nals == 0) {

                av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n");

                return AVERROR_INVALIDDATA;

            } else {

                break;

            }

        }

        if (pkt->nals_allocated < pkt->nb_nals + 1) {

            int new_size = pkt->nals_allocated + 1;

            H2645NAL *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*tmp));

            if (!tmp)

                return AVERROR(ENOMEM);

            pkt->nals = tmp;

            memset(pkt->nals + pkt->nals_allocated, 0,

                   (new_size - pkt->nals_allocated) * sizeof(*tmp));

            pkt->nals_allocated = new_size;

        }

        nal = &pkt->nals[pkt->nb_nals++];

        consumed = ff_h2645_extract_rbsp(buf, extract_length, nal);

        if (consumed < 0)

            return consumed;

        /* see commit 3566042a0 */

        if (consumed < length - 3 &&

            buf[consumed]     == 0x00 && buf[consumed + 1] == 0x00 &&

            buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0)

            skip_trailing_zeros = 0;

        nal->size_bits = get_bit_length(nal, skip_trailing_zeros);

        ret = init_get_bits(&nal->gb, nal->data, nal->size_bits);

        if (ret < 0)

            return ret;

        if (codec_id == AV_CODEC_ID_HEVC)

            ret = hevc_parse_nal_header(nal, logctx);

        else

            ret = h264_parse_nal_header(nal, logctx);

        if (ret <= 0) {

            if (ret < 0) {

                av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",

                       nal->type);

            }

            pkt->nb_nals--;

        }

        buf    += consumed;

        length -= consumed;

    }

    return 0;

}


static void gen_check_interrupts(DisasContext *dc)

{

    if (dc->tb->cflags & CF_USE_ICOUNT) {

        gen_io_start();

    }

    gen_helper_check_interrupts(cpu_env);

    if (dc->tb->cflags & CF_USE_ICOUNT) {

        gen_io_end();

    }

}


static void put_buffer(QEMUFile *f, void *pv, size_t size)

{

    uint8_t *v = pv;

    qemu_put_buffer(f, v, size);

}


static void boston_lcd_write(void *opaque, hwaddr addr,

                             uint64_t val, unsigned size)

{

    BostonState *s = opaque;

    switch (size) {

    case 8:

        s->lcd_content[(addr + 7) & 0x7] = val >> 56;

        s->lcd_content[(addr + 6) & 0x7] = val >> 48;

        s->lcd_content[(addr + 5) & 0x7] = val >> 40;

        s->lcd_content[(addr + 4) & 0x7] = val >> 32;

        /* fall through */

    case 4:

        s->lcd_content[(addr + 3) & 0x7] = val >> 24;

        s->lcd_content[(addr + 2) & 0x7] = val >> 16;

        /* fall through */

    case 2:

        s->lcd_content[(addr + 1) & 0x7] = val >> 8;

        /* fall through */

    case 1:

        s->lcd_content[(addr + 0) & 0x7] = val;

        break;

    }

    qemu_chr_fe_printf(&s->lcd_display,

                       "\r%-8.8s", s->lcd_content);

}


int qemu_loadvm_state(QEMUFile *f)

{

    QLIST_HEAD(, LoadStateEntry) loadvm_handlers =

        QLIST_HEAD_INITIALIZER(loadvm_handlers);

    LoadStateEntry *le, *new_le;

    Error *local_err = NULL;

    uint8_t section_type;

    unsigned int v;

    int ret;

    int file_error_after_eof = -1;

    if (qemu_savevm_state_blocked(&local_err)) {

        error_report_err(local_err);

        return -EINVAL;

    }

    v = qemu_get_be32(f);

    if (v != QEMU_VM_FILE_MAGIC) {

        error_report("Not a migration stream");

        return -EINVAL;

    }

    v = qemu_get_be32(f);

    if (v == QEMU_VM_FILE_VERSION_COMPAT) {

        error_report("SaveVM v2 format is obsolete and don't work anymore");

        return -ENOTSUP;

    }

    if (v != QEMU_VM_FILE_VERSION) {

        error_report("Unsupported migration stream version");

        return -ENOTSUP;

    }

    while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {

        uint32_t instance_id, version_id, section_id;

        SaveStateEntry *se;

        char idstr[257];

        int len;

        trace_qemu_loadvm_state_section(section_type);

        switch (section_type) {

        case QEMU_VM_SECTION_START:

        case QEMU_VM_SECTION_FULL:

            /* Read section start */

            section_id = qemu_get_be32(f);

            len = qemu_get_byte(f);

            qemu_get_buffer(f, (uint8_t *)idstr, len);

            idstr[len] = 0;

            instance_id = qemu_get_be32(f);

            version_id = qemu_get_be32(f);

            trace_qemu_loadvm_state_section_startfull(section_id, idstr,

                                                      instance_id, version_id);

            /* Find savevm section */

            se = find_se(idstr, instance_id);

            if (se == NULL) {

                error_report("Unknown savevm section or instance '%s' %d",

                             idstr, instance_id);

                ret = -EINVAL;

                goto out;

            }

            /* Validate version */

            if (version_id > se->version_id) {

                error_report("savevm: unsupported version %d for '%s' v%d",

                             version_id, idstr, se->version_id);

                ret = -EINVAL;

                goto out;

            }

            /* Add entry */

            le = g_malloc0(sizeof(*le));

            le->se = se;

            le->section_id = section_id;

            le->version_id = version_id;

            QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);

            ret = vmstate_load(f, le->se, le->version_id);

            if (ret < 0) {

                error_report("error while loading state for instance 0x%x of"

                             " device '%s'", instance_id, idstr);

                goto out;

            }

            break;

        case QEMU_VM_SECTION_PART:

        case QEMU_VM_SECTION_END:

            section_id = qemu_get_be32(f);

            trace_qemu_loadvm_state_section_partend(section_id);

            QLIST_FOREACH(le, &loadvm_handlers, entry) {

                if (le->section_id == section_id) {

                    break;

                }

            }

            if (le == NULL) {

                error_report("Unknown savevm section %d", section_id);

                ret = -EINVAL;

                goto out;

            }

            ret = vmstate_load(f, le->se, le->version_id);

            if (ret < 0) {

                error_report("error while loading state section id %d(%s)",

                             section_id, le->se->idstr);

                goto out;

            }

            break;

        default:

            error_report("Unknown savevm section type %d", section_type);

            ret = -EINVAL;

            goto out;

        }

    }

    file_error_after_eof = qemu_file_get_error(f);

    /*

     * Try to read in the VMDESC section as well, so that dumping tools that

     * intercept our migration stream have the chance to see it.

     */

    if (qemu_get_byte(f) == QEMU_VM_VMDESCRIPTION) {

        uint32_t size = qemu_get_be32(f);

        uint8_t *buf = g_malloc(0x1000);

        while (size > 0) {

            uint32_t read_chunk = MIN(size, 0x1000);

            qemu_get_buffer(f, buf, read_chunk);

            size -= read_chunk;

        }

        g_free(buf);

    }

    cpu_synchronize_all_post_init();

    ret = 0;

out:

    QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {

        QLIST_REMOVE(le, entry);

        g_free(le);

    }

    if (ret == 0) {

        /* We may not have a VMDESC section, so ignore relative errors */

        ret = file_error_after_eof;

    }

    return ret;

}


int inet_connect(const char *str, bool block, Error **errp)

{

    QemuOpts *opts;

    int sock = -1;

    opts = qemu_opts_create(&dummy_opts, NULL, 0);

    if (inet_parse(opts, str) == 0) {

        if (block) {

            qemu_opt_set(opts, "block", "on");

        }

        sock = inet_connect_opts(opts, errp);

    } else {

        error_set(errp, QERR_SOCKET_CREATE_FAILED);

    }

    qemu_opts_del(opts);

    return sock;

}


static void blkverify_verify_readv(BlkverifyAIOCB *acb)

{

    ssize_t offset = qemu_iovec_compare(acb->qiov, &acb->raw_qiov);

    if (offset != -1) {

        blkverify_err(acb, "contents mismatch in sector %" PRId64,

                      acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE));

    }

}


static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type,

                           uint8_t *src, uint8_t *top, int size, int bpp)

{

    int i;

    switch(filter_type) {

    case PNG_FILTER_VALUE_NONE:

        memcpy(dst, src, size);

        break;

    case PNG_FILTER_VALUE_SUB:

        dsp->diff_bytes(dst, src, src-bpp, size);

        memcpy(dst, src, bpp);

        break;

    case PNG_FILTER_VALUE_UP:

        dsp->diff_bytes(dst, src, top, size);

        break;

    case PNG_FILTER_VALUE_AVG:

        for(i = 0; i < bpp; i++)

            dst[i] = src[i] - (top[i] >> 1);

        for(; i < size; i++)

            dst[i] = src[i] - ((src[i-bpp] + top[i]) >> 1);

        break;

    case PNG_FILTER_VALUE_PAETH:

        for(i = 0; i < bpp; i++)

            dst[i] = src[i] - top[i];

        sub_png_paeth_prediction(dst+i, src+i, top+i, size-i, bpp);

        break;

    }

}


static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)

{

    V9fsVirtioState *v = (V9fsVirtioState *)vdev;

    V9fsState *s = &v->state;

    V9fsPDU *pdu;

    ssize_t len;

    while ((pdu = pdu_alloc(s))) {

        struct {

            uint32_t size_le;

            uint8_t id;

            uint16_t tag_le;

        } QEMU_PACKED out;

        VirtQueueElement *elem;

        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));

        if (!elem) {

            pdu_free(pdu);

            break;

        }

        BUG_ON(elem->out_num == 0 || elem->in_num == 0);

        QEMU_BUILD_BUG_ON(sizeof(out) != 7);

        v->elems[pdu->idx] = elem;

        len = iov_to_buf(elem->out_sg, elem->out_num, 0,

                         &out, sizeof(out));

        BUG_ON(len != sizeof(out));

        pdu->size = le32_to_cpu(out.size_le);

        pdu->id = out.id;

        pdu->tag = le16_to_cpu(out.tag_le);

        qemu_co_queue_init(&pdu->complete);

        pdu_submit(pdu);

    }

}


static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) {

    if (keysym < MAX_NORMAL_KEYCODE) {

        trace_keymap_add("normal", keysym, keycode, line);

        k->keysym2keycode[keysym] = keycode;

    } else {

        if (k->extra_count >= MAX_EXTRA_COUNT) {

            fprintf(stderr, "Warning: Could not assign keysym %s (0x%x)"

                    " because of memory constraints.\n", line, keysym);

        } else {

            trace_keymap_add("extra", keysym, keycode, line);

            k->keysym2keycode_extra[k->extra_count].

            keysym = keysym;

            k->keysym2keycode_extra[k->extra_count].

            keycode = keycode;

            k->extra_count++;

        }

    }

}


static int local_unlinkat(FsContext *ctx, V9fsPath *dir,

                          const char *name, int flags)

{

    int ret;

    V9fsString fullname;

    char buffer[PATH_MAX];

    v9fs_string_init(&fullname);

    v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);

    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {

        if (flags == AT_REMOVEDIR) {

            /*

             * If directory remove .virtfs_metadata contained in the

             * directory

             */

            snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s", ctx->fs_root,

                     fullname.data, VIRTFS_META_DIR);

            ret = remove(buffer);

            if (ret < 0 && errno != ENOENT) {

                /*

                 * We didn't had the .virtfs_metadata file. May be file created

                 * in non-mapped mode ?. Ignore ENOENT.

                 */

                goto err_out;

            }

        }

        /*

         * Now remove the name from parent directory

         * .virtfs_metadata directory.

         */

        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));

        if (ret < 0 && errno != ENOENT) {

            /*

             * We didn't had the .virtfs_metadata file. May be file created

             * in non-mapped mode ?. Ignore ENOENT.

             */

            goto err_out;

        }

    }

    /* Remove the name finally */

    ret = remove(rpath(ctx, fullname.data, buffer));

err_out:

    v9fs_string_free(&fullname);

    return ret;

}


static int dnxhd_init_vlc(DNXHDEncContext *ctx)

{

    int i, j, level, run;

    int max_level = 1<<(ctx->cid_table->bit_depth+2);

    FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, max_level*4*sizeof(*ctx->vlc_codes), fail);

    FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_bits,  max_level*4*sizeof(*ctx->vlc_bits) , fail);

    FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, 63*2,                                fail);

    FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits,  63,                                  fail);

    ctx->vlc_codes += max_level*2;

    ctx->vlc_bits  += max_level*2;

    for (level = -max_level; level < max_level; level++) {

        for (run = 0; run < 2; run++) {

            int index = (level<<1)|run;

            int sign, offset = 0, alevel = level;

            MASK_ABS(sign, alevel);

            if (alevel > 64) {

                offset = (alevel-1)>>6;

                alevel -= offset<<6;

            }

            for (j = 0; j < 257; j++) {

                if (ctx->cid_table->ac_level[j] >> 1 == alevel &&

                    (!offset || (ctx->cid_table->ac_index_flag[j] && offset)) &&

                    (!run    || (ctx->cid_table->ac_run_flag  [j] && run))) {

                    assert(!ctx->vlc_codes[index]);

                    if (alevel) {

                        ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j]<<1)|(sign&1);

                        ctx->vlc_bits [index] = ctx->cid_table->ac_bits[j]+1;

                    } else {

                        ctx->vlc_codes[index] = ctx->cid_table->ac_codes[j];

                        ctx->vlc_bits [index] = ctx->cid_table->ac_bits [j];

                    }

                    break;

                }

            }

            assert(!alevel || j < 257);

            if (offset) {

                ctx->vlc_codes[index] = (ctx->vlc_codes[index]<<ctx->cid_table->index_bits)|offset;

                ctx->vlc_bits [index]+= ctx->cid_table->index_bits;

            }

        }

    }

    for (i = 0; i < 62; i++) {

        int run = ctx->cid_table->run[i];

        assert(run < 63);

        ctx->run_codes[run] = ctx->cid_table->run_codes[i];

        ctx->run_bits [run] = ctx->cid_table->run_bits[i];

    }

    return 0;

 fail:

    return -1;

}


static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,

                                                   sPAPREnvironment *spapr,

                                                   uint32_t token,

                                                   uint32_t nargs,

                                                   target_ulong args,

                                                   uint32_t nret,

                                                   target_ulong rets)

{

    uint32_t config_addr = rtas_ld(args, 0);

    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);

    unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);

    sPAPRPHBState *phb = NULL;

    PCIDevice *pdev = NULL;

    spapr_pci_msi *msi;

    /* Find sPAPRPHBState */

    phb = find_phb(spapr, buid);

    if (phb) {

        pdev = find_dev(spapr, buid, config_addr);

    }

    if (!phb || !pdev) {

        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);

        return;

    }

    /* Find device descriptor and start IRQ */

    msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr);

    if (!msi || !msi->first_irq || !msi->num || (ioa_intr_num >= msi->num)) {

        trace_spapr_pci_msi("Failed to return vector", config_addr);

        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);

        return;

    }

    intr_src_num = msi->first_irq + ioa_intr_num;

    trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num,

                                                           intr_src_num);

    rtas_st(rets, 0, RTAS_OUT_SUCCESS);

    rtas_st(rets, 1, intr_src_num);

    rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */

}


void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value,

                         Error **errp)

{

    CPUPPCState *env = &cpu->env;

    target_ulong htabsize = value & SDR_64_HTABSIZE;

    env->spr[SPR_SDR1] = value;

    if (htabsize > 28) {

        error_setg(errp,

                   "Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",

                   htabsize);

        htabsize = 28;

    }

    env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1;

    env->htab_base = value & SDR_64_HTABORG;

}


static coroutine_fn int cow_co_write(BlockDriverState *bs, int64_t sector_num,

                                     const uint8_t *buf, int nb_sectors)

{

    int ret;

    BDRVCowState *s = bs->opaque;

    qemu_co_mutex_lock(&s->lock);

    ret = cow_write(bs, sector_num, buf, nb_sectors);

    qemu_co_mutex_unlock(&s->lock);

    return ret;

}


static void x86_cpu_reset(CPUState *s)

{

    X86CPU *cpu = X86_CPU(s);

    X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);

    CPUX86State *env = &cpu->env;

    target_ulong cr4;

    uint64_t xcr0;

    int i;

    xcc->parent_reset(s);

    memset(env, 0, offsetof(CPUX86State, end_reset_fields));

    tlb_flush(s, 1);

    env->old_exception = -1;

    /* init to reset state */

    env->hflags2 |= HF2_GIF_MASK;

    cpu_x86_update_cr0(env, 0x60000010);

    env->a20_mask = ~0x0;

    env->smbase = 0x30000;

    env->idt.limit = 0xffff;

    env->gdt.limit = 0xffff;

    env->ldt.limit = 0xffff;

    env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);

    env->tr.limit = 0xffff;

    env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);

    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |

                           DESC_R_MASK | DESC_A_MASK);

    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |

                           DESC_A_MASK);

    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |

                           DESC_A_MASK);

    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |

                           DESC_A_MASK);

    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |

                           DESC_A_MASK);

    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,

                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |

                           DESC_A_MASK);

    env->eip = 0xfff0;

    env->regs[R_EDX] = env->cpuid_version;

    env->eflags = 0x2;

    /* FPU init */

    for (i = 0; i < 8; i++) {

        env->fptags[i] = 1;

    }

    cpu_set_fpuc(env, 0x37f);

    env->mxcsr = 0x1f80;

    /* All units are in INIT state.  */

    env->xstate_bv = 0;

    env->pat = 0x0007040600070406ULL;

    env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;

    memset(env->dr, 0, sizeof(env->dr));

    env->dr[6] = DR6_FIXED_1;

    env->dr[7] = DR7_FIXED_1;

    cpu_breakpoint_remove_all(s, BP_CPU);

    cpu_watchpoint_remove_all(s, BP_CPU);

    cr4 = 0;

    xcr0 = XSTATE_FP_MASK;

#ifdef CONFIG_USER_ONLY

    /* Enable all the features for user-mode.  */

    if (env->features[FEAT_1_EDX] & CPUID_SSE) {

        xcr0 |= XSTATE_SSE_MASK;

    }

    for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {

        const ExtSaveArea *esa = &x86_ext_save_areas[i];

        if ((env->features[esa->feature] & esa->bits) == esa->bits) {

            xcr0 |= 1ull << i;

        }

    }

    if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) {

        cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK;

    }

    if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FSGSBASE) {

        cr4 |= CR4_FSGSBASE_MASK;

    }

#endif

    env->xcr0 = xcr0;

    cpu_x86_update_cr4(env, cr4);

    /*

     * SDM 11.11.5 requires:

     *  - IA32_MTRR_DEF_TYPE MSR.E = 0

     *  - IA32_MTRR_PHYSMASKn.V = 0

     * All other bits are undefined.  For simplification, zero it all.

     */

    env->mtrr_deftype = 0;

    memset(env->mtrr_var, 0, sizeof(env->mtrr_var));

    memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed));

#if !defined(CONFIG_USER_ONLY)

    /* We hard-wire the BSP to the first CPU. */

    apic_designate_bsp(cpu->apic_state, s->cpu_index == 0);

    s->halted = !cpu_is_bsp(cpu);

    if (kvm_enabled()) {

        kvm_arch_reset_vcpu(cpu);

    }

#endif

}


static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,

                             const int *const_args)

{

    tcg_out_cmp2(s, args, const_args);

    tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, args[5]);

}


static int net_rx_ok(NetClientState *nc)

{

    struct XenNetDev *netdev = qemu_get_nic_opaque(nc);

    RING_IDX rc, rp;

    if (netdev->xendev.be_state != XenbusStateConnected) {

        return 0;

    }

    rc = netdev->rx_ring.req_cons;

    rp = netdev->rx_ring.sring->req_prod;

    xen_rmb();

    if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {

        xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",

                      __FUNCTION__, rc, rp);

        return 0;

    }

    return 1;

}


static void page_flush_tb_1(int level, void **lp)

{

    int i;

    if (*lp == NULL) {

        return;

    }

    if (level == 0) {

        PageDesc *pd = *lp;

        for (i = 0; i < L2_SIZE; ++i) {

            pd[i].first_tb = NULL;

            invalidate_page_bitmap(pd + i);

        }

    } else {

        void **pp = *lp;

        for (i = 0; i < L2_SIZE; ++i) {

            page_flush_tb_1(level - 1, pp + i);

        }

    }

}