From: handbrake Date: Mon, 22 Jul 2013 19:24:04 +0000 (+0000) Subject: QSV: support of MSDK 2013 R2/API 1.7 release and new features, RB541 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c68ada70d14e54e46ab982b641b009be62e9d0e7;p=handbrake QSV: support of MSDK 2013 R2/API 1.7 release and new features, RB541 git-svn-id: svn://svn.handbrake.fr/HandBrake/branches/qsv@5658 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- diff --git a/contrib/libmfx/module.defs b/contrib/libmfx/module.defs index a83d32b7f..4377123b9 100644 --- a/contrib/libmfx/module.defs +++ b/contrib/libmfx/module.defs @@ -1,6 +1,6 @@ $(eval $(call import.MODULE.defs,LIBMFX,libmfx)) $(eval $(call import.CONTRIB.defs,LIBMFX)) -LIBMFX.FETCH.url = http://download.handbrake.fr/contrib/mfx_dispatcher_2013_4.0.tar.bz2 +LIBMFX.FETCH.url = http://download.handbrake.fr/contrib/libmfx_intel_msdk_2013r2.tar.bz2 LIBMFX.CONFIGURE.bootstrap = rm -fr aclocal.m4 autom4te.cache; autoreconf -fiv; diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 47536ca41..8e6e0bfb0 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -880,6 +880,9 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen pv->job->vcodec == HB_VCODEC_QSV_H264 && pv->job->title->video_codec_param == AV_CODEC_ID_H264 ){ pv->context->hwaccel_context = &pv->qsv_config; pv->qsv_config.io_pattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD) + pv->qsv_config.additional_buffers = 160; // LA might need more surfaces + else pv->qsv_config.additional_buffers = 64; // FIFO_LARGE for now // decode is async, sync only at encode pv->qsv_config.sync_need = 0; @@ -1204,7 +1207,7 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job ) int ret; hb_dict_t *qsv_opts = NULL; hb_dict_entry_t *entry = NULL; - qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info); + qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info,job); if (job->advanced_opts != NULL && *job->advanced_opts != '\0') { qsv_opts = hb_encopts_to_dict(job->advanced_opts, job->vcodec); @@ -1240,6 +1243,9 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job ) if(job && job->vcodec == HB_VCODEC_QSV_H264 ){ pv->context->hwaccel_context = &pv->qsv_config; pv->qsv_config.io_pattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD) + pv->qsv_config.additional_buffers = 160; + else pv->qsv_config.additional_buffers = 64; pv->qsv_config.sync_need = 0; pv->qsv_config.usage_threaded = 1; @@ -1290,6 +1296,9 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job ) if(job && job->vcodec == HB_VCODEC_QSV_H264 ){ pv->context->hwaccel_context = &pv->qsv_config; pv->qsv_config.io_pattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD) + pv->qsv_config.additional_buffers = 160; + else pv->qsv_config.additional_buffers = 64; pv->qsv_config.sync_need = 0; pv->qsv_config.usage_threaded = 1; diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c index f9976c789..4b490fafb 100644 --- a/libhb/enc_qsv.c +++ b/libhb/enc_qsv.c @@ -139,6 +139,9 @@ struct hb_work_private_s mfxExtCodingOption2 qsv_coding_option2_config; mfxExtCodingOption qsv_coding_option_config; int mbbrx_param_idx; + + // lookahead + mfxU16 la_depth; }; extern char* get_codec_id(hb_work_private_t *pv); @@ -278,17 +281,20 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ AV_QSV_ZERO_MEMORY(qsv_encode->m_mfxVideoParam); AV_QSV_ZERO_MEMORY(qsv_encode->m_mfxVideoParam.mfx); - qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info); + qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info,job); hb_dict_t *qsv_opts_dict = NULL; if( job->advanced_opts != NULL && *job->advanced_opts != '\0' ) qsv_opts_dict = hb_encopts_to_dict( job->advanced_opts, job->vcodec ); + int gop_pic_size_force = 0; int ret; hb_dict_entry_t *entry = NULL; while( ( entry = hb_dict_next( qsv_opts_dict, entry ) ) ) { ret = qsv_param_parse( &pv->qsv_config, entry->key, entry->value ); + if(!strcmp(entry->key,QSV_NAME_gop_pic_size)) + gop_pic_size_force = 1; if( ret == QSV_PARAM_BAD_NAME ) hb_log( "QSV options: Unknown suboption %s", entry->key ); else @@ -307,6 +313,8 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ qsv_encode->m_mfxVideoParam.mfx.TargetKbps = 2000; qsv_encode->m_mfxVideoParam.mfx.RateControlMethod = MFX_RATECONTROL_VBR; + int old_TargetKbps = qsv_encode->m_mfxVideoParam.mfx.TargetKbps; + if (job->vquality >= 0) { int cqp_offset_i,cqp_offset_p,cqp_offset_b; @@ -349,6 +357,7 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ // qsv_encode->m_mfxVideoParam.mfx.RateControlMethod = MFX_RATECONTROL_VBR; qsv_encode->m_mfxVideoParam.mfx.TargetKbps = job->vbitrate; + old_TargetKbps = qsv_encode->m_mfxVideoParam.mfx.TargetKbps; // make it work like x264 for ease of use // (more convenient if switching back and forth) @@ -392,24 +401,56 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ hb_error("wrong parameters setting"); } + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD) + { + int use_la = 0; + + if (qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_VBR || + qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_AVBR) + { + if ((entry = hb_dict_get(qsv_opts_dict, QSV_NAME_lookahead)) != NULL && entry->value != NULL) + use_la |= atoi(entry->value); + else + if (qsv_encode->m_mfxVideoParam.mfx.TargetUsage < 3) + use_la = 1; // sort of default value + } + if (use_la) + { + qsv_encode->m_mfxVideoParam.mfx.RateControlMethod = MFX_RATECONTROL_LA; + qsv_encode->m_mfxVideoParam.mfx.TargetKbps = old_TargetKbps; + } + } + + if (!gop_pic_size_force && qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_CQP) + { + pv->qsv_config.gop_pic_size = 32; // default for CQP, if not forced + } + // version-specific encoder options - if (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_1_6) + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_BRC) { if ((entry = hb_dict_get(qsv_opts_dict, QSV_NAME_mbbrc)) != NULL && entry->value != NULL) { pv->mbbrc =atoi(entry->value); } else - pv->mbbrc = 1; // MFX_CODINGOPTION_ON + pv->mbbrc = 1; // default: MFX_CODINGOPTION_ON if ((entry = hb_dict_get(qsv_opts_dict, QSV_NAME_extbrc)) != NULL && entry->value != NULL) { pv->extbrc =atoi(entry->value); } else - pv->extbrc = 2; //MFX_CODINGOPTION_OFF + pv->extbrc = 2; // default: MFX_CODINGOPTION_OFF } + + if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD) + if ((entry = hb_dict_get(qsv_opts_dict, QSV_NAME_lookaheaddepth)) != NULL && entry->value != NULL) + pv->la_depth = atoi(entry->value); + else + pv->la_depth = 40; // default: value + hb_dict_free( &qsv_opts_dict ); if(pv->qsv_config.async_depth) @@ -428,12 +469,17 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ break; case MFX_RATECONTROL_CQP : rc_method = "MFX_RATECONTROL_CQP"; break; + case MFX_RATECONTROL_LA : rc_method = "MFX_RATECONTROL_LA"; + break; default : rc_method = "unknown"; }; if( qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_CQP ) hb_log("qsv: RateControlMethod:%s(I:%d/P:%d/B:%d)",rc_method, qsv_encode->m_mfxVideoParam.mfx.QPI, qsv_encode->m_mfxVideoParam.mfx.QPP, qsv_encode->m_mfxVideoParam.mfx.QPB ); + else + if( qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA ) + hb_log("qsv: RateControlMethod:%s LookAheadDepth:%d TargetKbps:%d",rc_method , pv->la_depth, qsv_encode->m_mfxVideoParam.mfx.TargetKbps ); else hb_log("qsv: RateControlMethod:%s TargetKbps:%d",rc_method , qsv_encode->m_mfxVideoParam.mfx.TargetKbps ); @@ -517,7 +563,8 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ if(!pv->is_sys_mem) qsv_encode->p_ext_param_num = 1; // for MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION - if(pv->mbbrc || pv->extbrc){ + if (pv->mbbrc || pv->extbrc || qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA) + { qsv_encode->p_ext_param_num++; } @@ -525,7 +572,8 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ qsv_encode->m_mfxVideoParam.NumExtParam = qsv_encode->p_ext_param_num; - if(qsv_encode->m_mfxVideoParam.NumExtParam){ + if (qsv_encode->m_mfxVideoParam.NumExtParam) + { int cur_idx = 0; qsv_encode->p_ext_params = av_mallocz(sizeof(mfxExtBuffer *)*qsv_encode->p_ext_param_num); AV_QSV_CHECK_POINTER(qsv_encode->p_ext_params, MFX_ERR_MEMORY_ALLOC); @@ -537,7 +585,8 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ pv->qsv_coding_option_config.PicTimingSEI = MFX_CODINGOPTION_OFF; qsv_encode->p_ext_params[cur_idx++] = (mfxExtBuffer*)&pv->qsv_coding_option_config; - if(!pv->is_sys_mem){ + if (!pv->is_sys_mem) + { memset(&qsv_encode->ext_opaque_alloc, 0, sizeof(mfxExtOpaqueSurfaceAlloc)); qsv_encode->ext_opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; qsv_encode->ext_opaque_alloc.Header.BufferSz = sizeof(mfxExtOpaqueSurfaceAlloc); @@ -555,12 +604,14 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ qsv_encode->ext_opaque_alloc.In.Type = qsv_encode->request[0].Type; } - if(pv->mbbrc || pv->extbrc){ + if (pv->mbbrc || pv->extbrc || qsv_encode->m_mfxVideoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA) + { pv->qsv_coding_option2_config.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; pv->qsv_coding_option2_config.Header.BufferSz = sizeof(mfxExtCodingOption2); pv->qsv_coding_option2_config.MBBRC = pv->mbbrc << 4; // default is off pv->qsv_coding_option2_config.ExtBRC = pv->extbrc == 0 ? MFX_CODINGOPTION_OFF : pv->extbrc << 4; + pv->qsv_coding_option2_config.LookAheadDepth = pv->la_depth; // reset if out of the ranges if(pv->qsv_coding_option2_config.MBBRC > MFX_CODINGOPTION_ADAPTIVE) @@ -581,6 +632,7 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ if( pv->mbbrx_param_idx ){ pv->qsv_coding_option2_config.MBBRC = MFX_CODINGOPTION_UNKNOWN; pv->qsv_coding_option2_config.ExtBRC = MFX_CODINGOPTION_OFF; + pv->qsv_coding_option2_config.LookAheadDepth = 0; pv->mbbrx_param_idx = 0; } } @@ -635,7 +687,7 @@ int qsv_enc_init( av_qsv_context* qsv, hb_work_private_t * pv ){ pv->bfrm_delay = FFMAX(pv->bfrm_delay, 0); // check whether we need to generate DTS ourselves (MSDK API < 1.6 or VFR) pv->bfrm_workaround = job->cfr != 1 || !(hb_qsv_info->capabilities & - HB_QSV_CAP_MSDK_1_6); + HB_QSV_CAP_BITSTREAM_DTS); if (pv->bfrm_delay && pv->bfrm_workaround) { pv->bfrm_workaround = 1; @@ -1093,8 +1145,8 @@ int encqsvWork( hb_work_object_t * w, hb_buffer_t ** buf_in, { // MSDK API < 1.6 or VFR, so generate our own DTS if ((pv->frames_out == 0) && - (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_1_6) && - (hb_qsv_info->capabilities & HB_QSV_CAP_BPYRAMID)) + (hb_qsv_info->capabilities & HB_QSV_CAP_BITSTREAM_DTS) && + (hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID)) { // with B-pyramid, the delay may be more than 1 frame, // so compute the actual delay based on the initial DTS @@ -1302,7 +1354,9 @@ int qsv_param_parse( av_qsv_config* config, const char *name, const char *value) !strcmp(name,QSV_NAME_extbrc) || !strcmp(name,QSV_NAME_cqp_offset_i) || !strcmp(name,QSV_NAME_cqp_offset_p) || - !strcmp(name,QSV_NAME_cqp_offset_b) + !strcmp(name,QSV_NAME_cqp_offset_b) || + !strcmp(name,QSV_NAME_lookaheaddepth) || + !strcmp(name,QSV_NAME_lookahead) ) ret = QSV_PARAM_OK; else @@ -1311,12 +1365,15 @@ int qsv_param_parse( av_qsv_config* config, const char *name, const char *value) return ret; } -void qsv_param_set_defaults( av_qsv_config* config, hb_qsv_info_t *qsv_info ){ +void qsv_param_set_defaults( av_qsv_config* config, hb_qsv_info_t *qsv_info, hb_job_t *job ){ if(!config) return; config->async_depth = AV_QSV_ASYNC_DEPTH_DEFAULT; config->target_usage = MFX_TARGETUSAGE_BEST_QUALITY + 1; + config->num_ref_frame = 0; config->gop_ref_dist = 4; - config->gop_pic_size = 32; + + int used_rate = round((float)job->vrate/(float)job->vrate_base); + config->gop_pic_size = (used_rate * 5) + 1; } diff --git a/libhb/enc_qsv.h b/libhb/enc_qsv.h index c5c5fc735..5f5d8d4b3 100644 --- a/libhb/enc_qsv.h +++ b/libhb/enc_qsv.h @@ -50,6 +50,8 @@ void parse_nalus( uint8_t *nal_inits, size_t length, hb_buffer_t *buf, uint32_t #define QSV_NAME_cqp_offset_i "cqp-offset-i" #define QSV_NAME_cqp_offset_p "cqp-offset-p" #define QSV_NAME_cqp_offset_b "cqp-offset-b" +#define QSV_NAME_lookaheaddepth "lookahead-depth" +#define QSV_NAME_lookahead "lookahead" typedef enum { QSV_PARAM_OK = 0, @@ -59,6 +61,6 @@ typedef enum { } qsv_param_errors; int qsv_param_parse( av_qsv_config* config, const char *name, const char *value); -void qsv_param_set_defaults( av_qsv_config* config, hb_qsv_info_t *qsv_info ); +void qsv_param_set_defaults( av_qsv_config* config, hb_qsv_info_t *qsv_info, hb_job_t *job ); #endif //ENC_QSV_H diff --git a/libhb/hb.c b/libhb/hb.c index 4b0a34824..162dbe0e8 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -370,7 +370,7 @@ static int hb_qsv_info_init() return (hb_qsv_info == NULL); init_done = 1; - hb_qsv_info = malloc(sizeof(*hb_qsv_info)); + hb_qsv_info = calloc(sizeof(*hb_qsv_info),1); if (hb_qsv_info == NULL) { hb_error("hb_qsv_info_init: malloc failure"); @@ -440,7 +440,6 @@ static int hb_qsv_info_init() } mfxSession session; - hb_qsv_info->capabilities = 0; hb_qsv_info->minimum_version.Major = HB_QSV_MINVERSION_MAJOR; hb_qsv_info->minimum_version.Minor = HB_QSV_MINVERSION_MINOR; hb_qsv_info->software_available = hb_qsv_info->hardware_available = 0; @@ -475,19 +474,28 @@ static int hb_qsv_info_init() { if (HB_QSV_MIN_HARDWARE(1, 6)) { - hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_1_6; + hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_BRC; + hb_qsv_info->capabilities |= HB_QSV_CAP_BITSTREAM_DTS; } + if (HB_QSV_MIN_HARDWARE(1, 7)) + { if (hb_qsv_info->cpu_platform == HB_CPU_PLATFORM_INTEL_HSW) { - hb_qsv_info->capabilities |= HB_QSV_CAP_BPYRAMID; + hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_LOOKAHEAD; } } - else + if (hb_qsv_info->cpu_platform == HB_CPU_PLATFORM_INTEL_HSW) + { + hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID; + } + } + else if (hb_qsv_info->software_available) { if (HB_QSV_MIN_SOFTWARE(1, 6)) { - hb_qsv_info->capabilities |= HB_QSV_CAP_MSDK_1_6; - hb_qsv_info->capabilities |= HB_QSV_CAP_BPYRAMID; + hb_qsv_info->capabilities |= HB_QSV_CAP_OPTION2_BRC; + hb_qsv_info->capabilities |= HB_QSV_CAP_BITSTREAM_DTS; + hb_qsv_info->capabilities |= HB_QSV_CAP_H264_BPYRAMID; } } diff --git a/libhb/hb.h b/libhb/hb.h index 42a1755de..34bd93530 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -162,8 +162,10 @@ typedef struct hb_qsv_info_s // supported version-specific or hardware-specific capabilities int capabilities; -#define HB_QSV_CAP_MSDK_1_6 0x0000001 -#define HB_QSV_CAP_BPYRAMID 0x0000010 +#define HB_QSV_CAP_H264_BPYRAMID 1 << 0 // H.264: reference B-frames +#define HB_QSV_CAP_BITSTREAM_DTS 1 << 1 // mfxBitStream: DecodeTimeStamp +#define HB_QSV_CAP_OPTION2_BRC 1 << 2 // mfxExtCodingOption2: MBBRC/ExtBRC +#define HB_QSV_CAP_OPTION2_LOOKAHEAD 1 << 3 // mfxExtCodingOption2: LookAhead // if a feature depends on the cpu generation enum diff --git a/libhb/qsv_filter.c b/libhb/qsv_filter.c index 9b5a5e0f8..ad9cd3fc2 100644 --- a/libhb/qsv_filter.c +++ b/libhb/qsv_filter.c @@ -111,7 +111,7 @@ static int filter_init( av_qsv_context* qsv, hb_filter_private_t * pv ){ av_qsv_add_context_usage(qsv,HAVE_THREADS); - qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info); + qsv_param_set_defaults(&pv->qsv_config, hb_qsv_info,pv->job); hb_dict_t * qsv_opts = NULL; if( pv->job->advanced_opts != NULL && *pv->job->advanced_opts != '\0' ) qsv_opts = hb_encopts_to_dict( pv->job->advanced_opts, pv->job->vcodec ); diff --git a/test/test.c b/test/test.c index 5566ec313..23e36c40e 100644 --- a/test/test.c +++ b/test/test.c @@ -3473,17 +3473,44 @@ if (hb_qsv_available()) "### QSV Options, via --encopts=\"option1=value1:option2=value2\" -----------\n\n" " - target-usage A range of numbers that indicate trade-offs between\n" " quality and speed, from 1 to 7 inclusive.\n" - " - num-ref-frame Number of reference frames; if equal to 0, this parameter is\n" - " not specified.\n" - " - gop-pic-size Number of pictures within the current GOP (Group of Pictures);\n" - " if equal to 0, then the GOP size is unspecified.\n" + " Default is 2\n" + " - num-ref-frame Number of reference frames; if equal to 0,\n" + " this parameter is not specified.\n" + " - gop-pic-size Number of pictures within the current GOP.\n" + " If equal to 0, then the GOP size is unspecified.\n" " If equal to 1, only I-frames are used.\n" " - gop-ref-dist Distance between I- or P- key frames; if it is zero,\n" " the GOP structure is unspecified.\n" " Note: If GopRefDist = 1, there are no B-frames used.\n" - " - async-depth Specifies how many asynchronous operations an application performs\n" - " before the application explicitly synchronizes the result.\n" + " - async-depth Specifies how many asynchronous operations an\n" + " application performsbefore the application\n" + " explicitly synchronizes the result.\n" " If zero, the value is not specified. Default is 4\n" + " - mbbrc Setting this flag enables macroblock level bitrate\n" + " control that generally improves subjective\n" + " visual quality.\n" + " Enabling this flag may have negative impact on\n" + " performance and objective visual quality metric.\n" + " Default is ON\n" + " - extbrc Setting this flag instructs encoder to use extended\n" + " bitrate control algorithms. It generally improves\n" + " objective and subjective visual quality, but it\n" + " also leads to violation of HRD conformance and may\n" + " significantly reduce performance.\n" + " Default is OFF\n" + " - cqp-offset-i\n" + " - cqp-offset-p\n" + " - cqp-offset-b Specify shift/offset for QP(CQP) mode and each\n" + " Default is \"0:2:4\"\n" + " I, P and B frames respectively.\n" + " - lookahead Use the look ahead bitrate control algorithm.\n" + " Value more than 0 - enables the feature,\n" + " if supported by runtime hardware and driver\n" + " - lookahead-depth Specifies the depth of look ahead rate control\n" + " algorithm. It is number of frames that SDK\n" + " encoder analyzes before encoding. Valid value\n" + " range is from 10 to 100 inclusive.\n" + " Default is 40\n" "\n" ); } @@ -4268,7 +4295,9 @@ static int ParseOptions( int argc, char ** argv ) if (hb_qsv_available()) { /* XXX: for testing workarounds */ - hb_qsv_info->capabilities &= ~HB_QSV_CAP_MSDK_1_6; + hb_qsv_info->capabilities &= ~HB_QSV_CAP_BITSTREAM_DTS; + hb_qsv_info->capabilities &= ~HB_QSV_CAP_OPTION2_BRC; + hb_qsv_info->capabilities &= ~HB_QSV_CAP_OPTION2_LOOKAHEAD; } #endif break; diff --git a/win/CS/HandBrake.ApplicationServices/Factories/PlistPresetFactory.cs b/win/CS/HandBrake.ApplicationServices/Factories/PlistPresetFactory.cs index 6e738351a..00b41398a 100644 --- a/win/CS/HandBrake.ApplicationServices/Factories/PlistPresetFactory.cs +++ b/win/CS/HandBrake.ApplicationServices/Factories/PlistPresetFactory.cs @@ -238,7 +238,9 @@ namespace HandBrake.ApplicationServices.Factories case "h264Level": preset.Task.H264Level = kvp.Value; break; - + case "QsvPreset": + preset.Task.QsvPreset = EnumHelper.GetValue(kvp.Value, true); + break; // Chapter Markers Tab case "ChapterMarkers": preset.Task.IncludeChapterMarkers = kvp.Value == 1; diff --git a/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs b/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs index e40c44033..0b528b5ee 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/PresetService.cs @@ -522,8 +522,7 @@ namespace HandBrake.ApplicationServices.Services preset.Task.VideoEncoder = VideoEncoder.QuickSync; preset.Task.Quality = 20; - preset.Task.AdvancedEncoderOptions = - "gop-ref-dist=4:gop-pic-size=32:async-depth=4"; + preset.Task.AdvancedEncoderOptions = "async-depth=4"; preset.Task.AudioTracks = new ObservableCollection(); preset.Task.AudioTracks.Add(new AudioTrack { Bitrate = 224, Encoder = AudioEncoder.ffaac, MixDown = Mixdown.DolbyProLogicII}); preset.Task.Anamorphic = Anamorphic.Loose; diff --git a/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs index a6a91cce7..9017ee93d 100644 --- a/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs +++ b/win/CS/HandBrake.ApplicationServices/Utilities/PlistUtility.cs @@ -273,6 +273,7 @@ namespace HandBrake.ApplicationServices.Utilities AddEncodeElement(xmlWriter, "x264OptionExtra", "string", parsed.AdvancedEncoderOptions); AddEncodeElement(xmlWriter, "x264Preset", "string", parsed.X264Preset.ToString().ToLower()); AddEncodeElement(xmlWriter, "h264Profile", "string", parsed.H264Profile.ToString().ToLower()); + AddEncodeElement(xmlWriter, "QsvPreset", "string", parsed.QsvPreset.ToString()); string tune = parsed.X264Tune.ToString().ToLower(); if (parsed.FastDecode) { diff --git a/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs index 2dbaa3795..9931caf86 100644 --- a/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs @@ -33,7 +33,7 @@ namespace HandBrakeWPF.ViewModels public EncoderOptionsViewModel() { this.Task = new EncodeTask(); - cachedOptions.Add(VideoEncoder.QuickSync, "gop-ref-dist=4:gop-pic-size=32:async-depth=4"); + cachedOptions.Add(VideoEncoder.QuickSync, "async-depth=4"); } /// diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs index 67dcf4c09..e6cf6ce61 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs @@ -84,5 +84,7 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// Shutdown this View /// void Shutdown(); + + EncodeTask GetCurrentTask(); } } \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index 81ac6a688..4202dd7d7 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -1313,6 +1313,11 @@ namespace HandBrakeWPF.ViewModels this.scanService.Scan(task.Source, task.Title, this.UserSettingService.GetUserSetting(ASUserSettingConstants.PreviewScanCount), QueueEditAction); } + public EncodeTask GetCurrentTask() + { + return this.CurrentTask; + } + /// /// Pause an Encode /// diff --git a/win/CS/HandBrakeWPF/Views/VideoView.xaml b/win/CS/HandBrakeWPF/Views/VideoView.xaml index bb5f66691..a3b740568 100644 --- a/win/CS/HandBrakeWPF/Views/VideoView.xaml +++ b/win/CS/HandBrakeWPF/Views/VideoView.xaml @@ -94,7 +94,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -190,7 +190,7 @@ + IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight" ValueChanged="qsv_preset_ValueChanged"/> diff --git a/win/CS/HandBrakeWPF/Views/VideoView.xaml.cs b/win/CS/HandBrakeWPF/Views/VideoView.xaml.cs index 8a0842a96..b653dfc41 100644 --- a/win/CS/HandBrakeWPF/Views/VideoView.xaml.cs +++ b/win/CS/HandBrakeWPF/Views/VideoView.xaml.cs @@ -10,6 +10,14 @@ namespace HandBrakeWPF.Views { using System.Windows.Controls; + using System.Collections.Generic; + using System.Windows; + using Caliburn.Micro; + using HandBrake.ApplicationServices.Model; + using HandBrake.ApplicationServices.Utilities; + using HandBrake.Interop.Model.Encoding; + + using HandBrakeWPF.ViewModels.Interfaces; /// /// Interaction logic for VideoView.xaml @@ -23,5 +31,78 @@ namespace HandBrakeWPF.Views { InitializeComponent(); } + + private void qsv_preset_radiobutton(object sender, System.Windows.RoutedEventArgs e) + { + qsv_preset_ValueChanged(sender,null); + } + + private void qsv_preset_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + IMainViewModel mvm = IoC.Get(); + EncodeTask task = mvm.GetCurrentTask(); + string addon = ""; + + if (SystemInfo.IsHswOrNewer) + { + if (task.VideoEncodeRateType == VideoEncodeRateType.ConstantQuality) + { + if (task.QsvPreset == QsvPreset.Balanced || + task.QsvPreset == QsvPreset.Speed) + addon = "num-ref-frame=1"; +} + if (task.VideoEncodeRateType == VideoEncodeRateType.AverageBitrate) + { + if (task.QsvPreset == QsvPreset.Quality) + addon = "lookahead=1:gop-ref-dist=3"; + else + if (task.QsvPreset == QsvPreset.Balanced) + { + addon = "num-ref-frame=1:gop-ref-dist=1"; + } + else + if (task.QsvPreset == QsvPreset.Speed) + addon = "gop-ref-dist=1"; + } + } + + + string full_string = addon + ":"; + + IDictionary newOptions = new Dictionary(); + string[] existingSegments = full_string.Split(':'); + foreach (string existingSegment in existingSegments) + { + string optionName = existingSegment; + string optionValue = string.Empty; + int equalsIndex = existingSegment.IndexOf('='); + if (equalsIndex >= 0) + { + optionName = existingSegment.Substring( + 0, existingSegment.IndexOf("=", System.StringComparison.Ordinal)); + optionValue = existingSegment.Substring(equalsIndex); + } + + if (optionName != string.Empty) + { + if (newOptions.ContainsKey(optionName)) + newOptions.Remove(optionName); + newOptions.Add(optionName, optionValue); + } + } + + full_string = ""; + foreach (KeyValuePair entry in newOptions) + { + full_string += entry.Key; + if (entry.Value != string.Empty) + full_string += entry.Value; + full_string += ":"; + } + full_string = full_string.TrimEnd(':'); + + task.AdvancedEncoderOptions = full_string; + task.NotifyOfPropertyChange(() => task.AdvancedEncoderOptions); + } } }