EXTLIBS += vaapi
ENCODERS += h264_vaapi hevc_vaapi vp8_vaapi vp9_vaapi
HWACCELS += mpeg2_vaapi h264_vaapi hevc_vaapi vp9_vaapi
-FILTERS += deinterlace_vaapi scale_vaapi
+FILTERS += deinterlace_vaapi scale_vaapi denoise_vaapi sharpness_vaapi
FFMPEG_DIFFS += ffmpeg.vaapi_encode.diff
endif
double qscale;
int profile;
int low_power;
+ int filter_hw_denoise;
+ int filter_hw_sharpness;
char *device; // for hardware acceleration
LIST_ENTRY(tvh_codec_profile) link;
};
.off = offsetof(tvh_codec_profile_vaapi_t, bit_rate_scale_factor),
.def.d = 0,
},
+ {
+ .type = PT_INT,
+ .id = "hw_denoise", // Don't change
+ .name = N_("Denoise"),
+ .group = 2,
+ .desc = N_("Denoise only available with Hardware Acceleration (from 0 to 64, 0=skip, 0 default)"),
+ .get_opts = codec_profile_class_get_opts,
+ .off = offsetof(tvh_codec_profile_vaapi_t, filter_hw_denoise),
+ .intextra = INTEXTRA_RANGE(0, 64, 1),
+ .def.i = 0,
+ },
+ {
+ .type = PT_INT,
+ .id = "hw_sharpness", // Don't change
+ .name = N_("Sharpness"),
+ .group = 2,
+ .desc = N_("Sharpness only available with Hardware Acceleration (from 0 to 64, 0=skip, 44 default)"),
+ .get_opts = codec_profile_class_get_opts,
+ .off = offsetof(tvh_codec_profile_vaapi_t, filter_hw_sharpness),
+ .intextra = INTEXTRA_RANGE(0, 64, 1),
+ .def.i = 44,
+ },
{}
}
},
return -1;
}
+int
+hwaccels_get_denoise_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len)
+{
+ TVHContext *ctx = avctx->opaque;
+
+ if (ctx->hw_accel_ictx) {
+ switch (avctx->pix_fmt) {
+#if ENABLE_VAAPI
+ case AV_PIX_FMT_VAAPI:
+ return vaapi_get_denoise_filter(avctx, value, filter, filter_len);
+#endif
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+int
+hwaccels_get_sharpness_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len)
+{
+ TVHContext *ctx = avctx->opaque;
+
+ if (ctx->hw_accel_ictx) {
+ switch (avctx->pix_fmt) {
+#if ENABLE_VAAPI
+ case AV_PIX_FMT_VAAPI:
+ return vaapi_get_sharpness_filter(avctx, value, filter, filter_len);
+#endif
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
/* encoding ================================================================= */
int
hwaccels_get_deint_filter(AVCodecContext *avctx, char *filter, size_t filter_len);
+int
+hwaccels_get_denoise_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len);
+
+int
+hwaccels_get_sharpness_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len);
+
/* encoding ================================================================= */
return 0;
}
+
+int
+vaapi_get_denoise_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len)
+{
+ snprintf(filter, filter_len, "denoise_vaapi=%d", value);
+ return 0;
+}
+
+
+int
+vaapi_get_sharpness_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len)
+{
+ snprintf(filter, filter_len, "sharpness_vaapi=%d", value);
+ return 0;
+}
+
/* encoding ================================================================= */
int
int
vaapi_get_deint_filter(AVCodecContext *avctx, char *filter, size_t filter_len);
+int
+vaapi_get_denoise_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len);
+
+int
+vaapi_get_sharpness_filter(AVCodecContext *avctx, int value, char *filter, size_t filter_len);
+
/* encoding ================================================================= */
char scale[24];
char hw_scale[64];
char upload[48];
+ char hw_denoise[64];
+ char hw_sharpness[64];
int ihw = _video_filters_hw_pix_fmt(self->iavctx->pix_fmt);
int ohw = _video_filters_hw_pix_fmt(self->oavctx->pix_fmt);
int filter_scale = (self->iavctx->height != self->oavctx->height);
int filter_deint = 0, filter_download = 0, filter_upload = 0;
+#if ENABLE_HWACCELS
+ int filter_denoise = 0;
+ int filter_sharpness = 0;
+#endif
if (tvh_context_get_int_opt(opts, "tvh_filter_deint", &filter_deint)) {
return -1;
}
+#if ENABLE_VAAPI
+ filter_denoise = self->profile->filter_hw_denoise;
+ filter_sharpness = self->profile->filter_hw_sharpness;
+#endif
// in --> out | download | upload
// -------------|-------------|------------
// hw --> hw | 0 | 0
}
#endif
+ memset(hw_denoise, 0, sizeof(hw_denoise));
+#if ENABLE_HWACCELS
+ if (filter_denoise) {
+ // used only when hwaccel is enabled
+ if (ihw) {
+ // hw scale
+ hwaccels_get_denoise_filter(self->iavctx, filter_denoise, hw_denoise, sizeof(hw_denoise));
+ }
+ }
+#endif
+
+ memset(hw_sharpness, 0, sizeof(hw_sharpness));
+#if ENABLE_HWACCELS
+ if (filter_sharpness) {
+ // used only when hwaccel is enabled
+ if (ihw) {
+ // hw scale
+ hwaccels_get_sharpness_filter(self->iavctx, filter_sharpness, hw_sharpness, sizeof(hw_sharpness));
+ }
+ }
+#endif
+
#if ENABLE_HWACCELS
// no filter required.
#else
return -1;
}
- if (!(*filters = str_join(",", hw_deint, hw_scale, download, deint, scale, upload, NULL))) {
+ if (!(*filters = str_join(",", hw_deint, hw_scale, hw_denoise, hw_sharpness, download, deint, scale, upload, NULL))) {
return -1;
}
},
'codec_profile_vaapi_h264': function(form) {
+ function updateHWFilters(form) {
+ var hwaccel_field = form.findField('hwaccel');
+ form.findField('hw_denoise').setDisabled(!hwaccel_field.getValue());
+ form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
+ }
+
function updateFilters(form) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var low_power_field = form.findField('low_power');
+ var hwaccel_field = form.findField('hwaccel');
+
// first time we have to call this manually
updateFilters(form);
+ updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
low_power_field.on('check', function(checkbox, value) {
updateFilters(form);
});
+ // on hwaccel change
+ hwaccel_field.on('check', function(checkbox, value) {
+ updateHWFilters(form);
+ });
},
'codec_profile_vaapi_hevc': function(form) {
+ function updateHWFilters(form) {
+ var hwaccel_field = form.findField('hwaccel');
+ form.findField('hw_denoise').setDisabled(!hwaccel_field.getValue());
+ form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
+ }
+
function updateFilters(form) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var low_power_field = form.findField('low_power');
+ var hwaccel_field = form.findField('hwaccel');
+
// first time we have to call this manually
updateFilters(form);
+ updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
low_power_field.on('check', function(checkbox, value) {
updateFilters(form);
});
+ // on hwaccel change
+ hwaccel_field.on('check', function(checkbox, value) {
+ updateHWFilters(form);
+ });
},
'codec_profile_vaapi_vp8': function(form) {
+ function updateHWFilters(form) {
+ var hwaccel_field = form.findField('hwaccel');
+ form.findField('hw_denoise').setDisabled(!hwaccel_field.getValue());
+ form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
+ }
+
function updateFilters(form) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
+ var hwaccel_field = form.findField('hwaccel');
+
// first time we have to call this manually
updateFilters(form);
+ updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
rc_mode_field.on('select', function(combo, record, index) {
updateFilters(form);
});
+ // on hwaccel change
+ hwaccel_field.on('check', function(checkbox, value) {
+ updateHWFilters(form);
+ });
},
'codec_profile_vaapi_vp9': function(form) {
+ function updateHWFilters(form) {
+ var hwaccel_field = form.findField('hwaccel');
+ form.findField('hw_denoise').setDisabled(!hwaccel_field.getValue());
+ form.findField('hw_sharpness').setDisabled(!hwaccel_field.getValue());
+ }
+
function updateFilters(form) {
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
var platform_field = form.findField('platform');
var rc_mode_field = form.findField('rc_mode');
+ var hwaccel_field = form.findField('hwaccel');
+
// first time we have to call this manually
updateFilters(form);
+ updateHWFilters(form);
// on platform change
platform_field.on('select', function(combo, record, index) {
rc_mode_field.on('select', function(combo, record, index) {
updateFilters(form);
});
+ // on hwaccel change
+ hwaccel_field.on('check', function(checkbox, value) {
+ updateHWFilters(form);
+ });
}
};