static void gst_validate_ssim_configure_converter (GstValidateSsim * self, gint index, gboolean force, GstVideoFormat in_format, gint width, gint height) { SSimConverterInfo *info = g_list_nth_data (self->priv->converters, index); if (!info) { info = g_slice_new0 (SSimConverterInfo); self->priv->converters = g_list_insert (self->priv->converters, info, index); } if (force || info->in_info.height != height || info->in_info.width != width || info->in_info.finfo->format != in_format) { gst_video_info_init (&info->in_info); gst_video_info_set_format (&info->in_info, in_format, width, height); if (info->converter) gst_video_converter_free (info->converter); info->out_info = self->priv->out_info; if (gst_video_info_is_equal (&info->in_info, &info->out_info)) info->converter = NULL; else info->converter = gst_video_converter_new (&info->in_info, &info->out_info, NULL); } }
static void gst_video_scale_finalize (GstVideoScale * videoscale) { if (videoscale->convert) gst_video_converter_free (videoscale->convert); G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (videoscale)); }
static void ssim_convert_info_free (SSimConverterInfo * info) { if (info->converter) gst_video_converter_free (info->converter); g_slice_free (SSimConverterInfo, info); }
static void gst_video_convert_finalize (GObject * obj) { GstVideoConvert *space = GST_VIDEO_CONVERT (obj); if (space->convert) { gst_video_converter_free (space->convert); } G_OBJECT_CLASS (parent_class)->finalize (obj); }
static gboolean gst_video_convert_set_info (GstVideoFilter * filter, GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info) { GstVideoConvert *space; space = GST_VIDEO_CONVERT_CAST (filter); if (space->convert) { gst_video_converter_free (space->convert); space->convert = NULL; } /* these must match */ if (in_info->width != out_info->width || in_info->height != out_info->height || in_info->fps_n != out_info->fps_n || in_info->fps_d != out_info->fps_d) goto format_mismatch; /* if present, these must match too */ if (in_info->par_n != out_info->par_n || in_info->par_d != out_info->par_d) goto format_mismatch; /* if present, these must match too */ if (in_info->interlace_mode != out_info->interlace_mode) goto format_mismatch; space->convert = gst_video_converter_new (in_info, out_info, gst_structure_new ("GstVideoConvertConfig", GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, space->dither, GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, G_TYPE_UINT, space->dither_quantization, NULL)); if (space->convert == NULL) goto no_convert; GST_DEBUG ("reconfigured %d %d", GST_VIDEO_INFO_FORMAT (in_info), GST_VIDEO_INFO_FORMAT (out_info)); return TRUE; /* ERRORS */ format_mismatch: { GST_ERROR_OBJECT (space, "input and output formats do not match"); return FALSE; } no_convert: { GST_ERROR_OBJECT (space, "could not create converter"); return FALSE; } }
static void gst_validate_ssim_finalize (GObject * object) { GstValidateSsim *self = GST_VALIDATE_SSIM (object); void (*chain_up) (GObject *) = ((GObjectClass *) gst_validate_ssim_parent_class)->finalize; g_list_free_full (self->priv->converters, (GDestroyNotify) ssim_convert_info_free); if (self->priv->outconverter_info.converter) gst_video_converter_free (self->priv->outconverter_info.converter); g_hash_table_unref (self->priv->ref_frames_cache); chain_up (object); }
static gboolean gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in, GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info) { GstVideoScale *videoscale = GST_VIDEO_SCALE (filter); gint from_dar_n, from_dar_d, to_dar_n, to_dar_d; if (!gst_util_fraction_multiply (in_info->width, in_info->height, in_info->par_n, in_info->par_d, &from_dar_n, &from_dar_d)) { from_dar_n = from_dar_d = -1; } if (!gst_util_fraction_multiply (out_info->width, out_info->height, out_info->par_n, out_info->par_d, &to_dar_n, &to_dar_d)) { to_dar_n = to_dar_d = -1; } videoscale->borders_w = videoscale->borders_h = 0; if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) { if (videoscale->add_borders) { gint n, d, to_h, to_w; if (from_dar_n != -1 && from_dar_d != -1 && gst_util_fraction_multiply (from_dar_n, from_dar_d, out_info->par_d, out_info->par_n, &n, &d)) { to_h = gst_util_uint64_scale_int (out_info->width, d, n); if (to_h <= out_info->height) { videoscale->borders_h = out_info->height - to_h; videoscale->borders_w = 0; } else { to_w = gst_util_uint64_scale_int (out_info->height, n, d); g_assert (to_w <= out_info->width); videoscale->borders_h = 0; videoscale->borders_w = out_info->width - to_w; } } else { GST_WARNING_OBJECT (videoscale, "Can't calculate borders"); } } else { GST_WARNING_OBJECT (videoscale, "Can't keep DAR!"); } } if (in_info->width == out_info->width && in_info->height == out_info->height && videoscale->borders_w == 0 && videoscale->borders_h == 0) { gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE); } else { GstStructure *options; GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, "setup videoscaling"); gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE); options = gst_structure_new_empty ("videoscale"); switch (videoscale->method) { case GST_VIDEO_SCALE_NEAREST: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_NEAREST, NULL); break; case GST_VIDEO_SCALE_BILINEAR: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LINEAR, GST_VIDEO_RESAMPLER_OPT_MAX_TAPS, G_TYPE_INT, 2, NULL); break; case GST_VIDEO_SCALE_4TAP: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_SINC, GST_VIDEO_RESAMPLER_OPT_MAX_TAPS, G_TYPE_INT, 4, NULL); break; case GST_VIDEO_SCALE_LANCZOS: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LANCZOS, NULL); break; case GST_VIDEO_SCALE_BILINEAR2: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LINEAR, NULL); break; case GST_VIDEO_SCALE_SINC: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_SINC, NULL); break; case GST_VIDEO_SCALE_HERMITE: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC, GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 0.0, GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.0, NULL); break; case GST_VIDEO_SCALE_SPLINE: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC, GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 1.0, GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.0, NULL); break; case GST_VIDEO_SCALE_CATROM: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC, GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 0.0, GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.5, NULL); break; case GST_VIDEO_SCALE_MITCHELL: gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC, GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 1.0 / 3.0, GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 1.0 / 3.0, NULL); break; } gst_structure_set (options, GST_VIDEO_RESAMPLER_OPT_ENVELOPE, G_TYPE_DOUBLE, videoscale->envelope, GST_VIDEO_RESAMPLER_OPT_SHARPNESS, G_TYPE_DOUBLE, videoscale->sharpness, GST_VIDEO_RESAMPLER_OPT_SHARPEN, G_TYPE_DOUBLE, videoscale->sharpen, GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, videoscale->borders_w / 2, GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, videoscale->borders_h / 2, GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, out_info->width - videoscale->borders_w, GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, out_info->height - videoscale->borders_h, GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, GST_TYPE_VIDEO_MATRIX_MODE, GST_VIDEO_MATRIX_MODE_NONE, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, GST_VIDEO_DITHER_NONE, GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE, GST_VIDEO_CHROMA_MODE_NONE, NULL); if (videoscale->gamma_decode) { gst_structure_set (options, GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, GST_TYPE_VIDEO_GAMMA_MODE, GST_VIDEO_GAMMA_MODE_REMAP, NULL); } if (videoscale->convert) gst_video_converter_free (videoscale->convert); videoscale->convert = gst_video_converter_new (in_info, out_info, options); } GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %" G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), " "size %" G_GSIZE_FORMAT, in_info->width, in_info->height, in_info->par_n, in_info->par_d, from_dar_n, from_dar_d, in_info->size, out_info->width, out_info->height, out_info->par_n, out_info->par_d, to_dar_n, to_dar_d, videoscale->borders_w, videoscale->borders_h, out_info->size); return TRUE; }
static void gst_validate_ssim_save_out (GstValidateSsim * self, GstBuffer * buffer, const gchar * ref_file, const gchar * file, const gchar * outfolder) { GstVideoFrame frame, converted; if (!g_file_test (outfolder, G_FILE_TEST_IS_DIR)) { if (g_mkdir_with_parents (outfolder, 0755) != 0) { GST_VALIDATE_REPORT (self, GENERAL_INPUT_ERROR, "Could not create output directory %s", outfolder); return; } } if (self->priv->outconverter_info.converter == NULL || self->priv->width != self->priv->outconverter_info.out_info.width || self->priv->height != self->priv->outconverter_info.out_info.height) { if (self->priv->outconverter_info.converter) gst_video_converter_free (self->priv->outconverter_info.converter); gst_video_info_init (&self->priv->outconverter_info.in_info); gst_video_info_set_format (&self->priv->outconverter_info.in_info, GST_VIDEO_FORMAT_GRAY8, self->priv->width, self->priv->height); gst_video_info_init (&self->priv->outconverter_info.out_info); gst_video_info_set_format (&self->priv->outconverter_info.out_info, GST_VIDEO_FORMAT_RGBx, self->priv->width, self->priv->height); self->priv->outconverter_info.converter = gst_video_converter_new (&self->priv->outconverter_info.in_info, &self->priv->outconverter_info.out_info, NULL); } if (!gst_video_frame_map (&frame, &self->priv->outconverter_info.in_info, buffer, GST_MAP_READ)) { GST_VALIDATE_REPORT (self, GENERAL_INPUT_ERROR, "Could not map output frame"); return; } if (gst_validate_ssim_convert (self, &self->priv->outconverter_info, &frame, &converted)) { cairo_status_t status; cairo_surface_t *surface; gchar *bn1 = g_path_get_basename (ref_file); gchar *bn2 = g_path_get_basename (file); gchar *fname = g_strdup_printf ("%s.VS.%s.result.png", bn1, bn2); gchar *outfile = g_build_path (G_DIR_SEPARATOR_S, outfolder, fname, NULL); surface = cairo_image_surface_create_for_data (GST_VIDEO_FRAME_PLANE_DATA (&converted, 0), CAIRO_FORMAT_RGB24, GST_VIDEO_FRAME_WIDTH (&converted), GST_VIDEO_FRAME_HEIGHT (&converted), GST_VIDEO_FRAME_PLANE_STRIDE (&converted, 0)); if ((status = cairo_surface_write_to_png (surface, outfile)) != CAIRO_STATUS_SUCCESS) { GST_VALIDATE_REPORT (self, GENERAL_INPUT_ERROR, "Could not save '%s', cairo status is '%s'", outfile, cairo_status_to_string (status)); } cairo_surface_destroy (surface); gst_video_frame_unmap (&frame); gst_video_frame_unmap (&converted); g_free (bn1); g_free (bn2); g_free (fname); g_free (outfile); } }
static gboolean gst_video_convert_set_info (GstVideoFilter * filter, GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info) { GstVideoConvert *space; space = GST_VIDEO_CONVERT_CAST (filter); if (space->convert) { gst_video_converter_free (space->convert); space->convert = NULL; } /* these must match */ if (in_info->width != out_info->width || in_info->height != out_info->height || in_info->fps_n != out_info->fps_n || in_info->fps_d != out_info->fps_d) goto format_mismatch; /* if present, these must match too */ if (in_info->par_n != out_info->par_n || in_info->par_d != out_info->par_d) goto format_mismatch; /* if present, these must match too */ if (in_info->interlace_mode != out_info->interlace_mode) goto format_mismatch; space->convert = gst_video_converter_new (in_info, out_info, gst_structure_new ("GstVideoConvertConfig", GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, space->dither, GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, G_TYPE_UINT, space->dither_quantization, GST_VIDEO_CONVERTER_OPT_CHROMA_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, space->chroma_resampler, GST_VIDEO_CONVERTER_OPT_ALPHA_MODE, GST_TYPE_VIDEO_ALPHA_MODE, space->alpha_mode, GST_VIDEO_CONVERTER_OPT_ALPHA_VALUE, G_TYPE_DOUBLE, space->alpha_value, GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE, space->chroma_mode, GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, GST_TYPE_VIDEO_MATRIX_MODE, space->matrix_mode, GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, GST_TYPE_VIDEO_GAMMA_MODE, space->gamma_mode, GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE, GST_TYPE_VIDEO_PRIMARIES_MODE, space->primaries_mode, GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, space->n_threads, NULL)); if (space->convert == NULL) goto no_convert; GST_DEBUG ("reconfigured %d %d", GST_VIDEO_INFO_FORMAT (in_info), GST_VIDEO_INFO_FORMAT (out_info)); return TRUE; /* ERRORS */ format_mismatch: { GST_ERROR_OBJECT (space, "input and output formats do not match"); return FALSE; } no_convert: { GST_ERROR_OBJECT (space, "could not create converter"); return FALSE; } }