1 /* GStreamer libswscale wrapper
2 * Copyright (C) 2005 Luca Ognibene <luogni@tin.it>
3 * Copyright (C) 2006 Martin Zlomek <martin.zlomek@itonis.tv>
4 * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
26 #ifdef HAVE_FFMPEG_UNINSTALLED
29 #include <libswscale/swscale.h>
33 #include <gst/base/gstbasetransform.h>
34 #include <gst/video/video.h>
42 typedef struct _GstFFMpegScale
44 GstBaseTransform element;
47 GstPad *sinkpad, *srcpad;
50 gint in_width, in_height;
51 gint out_width, out_height;
53 enum PixelFormat in_pixfmt, out_pixfmt;
54 struct SwsContext *ctx;
56 /* cached auxiliary data */
57 gint in_stride[3], in_offset[3];
58 gint out_stride[3], out_offset[3];
64 typedef struct _GstFFMpegScaleClass
66 GstBaseTransformClass parent_class;
67 } GstFFMpegScaleClass;
69 #define GST_TYPE_FFMPEGSCALE \
70 (gst_ffmpegscale_get_type())
71 #define GST_FFMPEGSCALE(obj) \
72 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGSCALE,GstFFMpegScale))
73 #define GST_FFMPEGSCALE_CLASS(klass) \
74 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGSCALE,GstFFMpegScaleClass))
75 #define GST_IS_FFMPEGSCALE(obj) \
76 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGSCALE))
77 #define GST_IS_FFMPEGSCALE_CLASS(klass) \
78 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGSCALE))
80 GType gst_ffmpegscale_get_type (void);
82 GST_DEBUG_CATEGORY (ffmpegscale_debug);
83 #define GST_CAT_DEFAULT ffmpegscale_debug
85 /* libswscale supported formats depend on endianness */
86 #if G_BYTE_ORDER == G_BIG_ENDIAN
88 GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
89 GST_VIDEO_CAPS_xRGB "; " GST_VIDEO_CAPS_xBGR "; " \
90 GST_VIDEO_CAPS_ARGB "; " GST_VIDEO_CAPS_ABGR "; " \
91 GST_VIDEO_CAPS_YUV ("{ I420, YUY2, Y41B, Y42B }")
94 GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
95 GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_BGRx "; " \
96 GST_VIDEO_CAPS_RGBA "; " GST_VIDEO_CAPS_BGRA "; " \
97 GST_VIDEO_CAPS_YUV ("{ I420, YUY2, Y41B, Y42B }")
100 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
103 GST_STATIC_CAPS (VIDEO_CAPS)
106 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
109 GST_STATIC_CAPS (VIDEO_CAPS)
112 static gint gst_ffmpegscale_method_flags[] = {
126 #define GST_TYPE_FFMPEGSCALE_METHOD (gst_ffmpegscale_method_get_type())
128 gst_ffmpegscale_method_get_type (void)
130 static GType ffmpegscale_method_type = 0;
132 static const GEnumValue ffmpegscale_methods[] = {
133 {0, "Fast Bilinear", "fast-bilinear"},
134 {1, "Bilinear", "bilinear"},
135 {2, "Bicubic", "bicubic"},
136 {3, "Experimental", "experimental"},
137 {4, "Nearest Neighbour", "nearest-neighbour"},
139 {6, "Luma Bicubic / Chroma Linear", "bicubic-lin"},
140 {7, "Gauss", "gauss"},
141 {8, "SincR", "sincr"},
142 {9, "Lanczos", "lanczos"},
143 {10, "Natural Bicubic Spline", "bicubic-spline"},
147 if (!ffmpegscale_method_type) {
148 ffmpegscale_method_type =
149 g_enum_register_static ("GstFFMpegVideoScaleMethod",
150 ffmpegscale_methods);
152 return ffmpegscale_method_type;
155 #define DEFAULT_PROP_METHOD 2
164 GST_BOILERPLATE (GstFFMpegScale, gst_ffmpegscale, GstBaseTransform,
165 GST_TYPE_BASE_TRANSFORM);
167 static void gst_ffmpegscale_finalize (GObject * object);
168 static void gst_ffmpegscale_set_property (GObject * object, guint prop_id,
169 const GValue * value, GParamSpec * pspec);
170 static void gst_ffmpegscale_get_property (GObject * object, guint prop_id,
171 GValue * value, GParamSpec * pspec);
173 static gboolean gst_ffmpegscale_stop (GstBaseTransform * trans);
174 static GstCaps *gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
175 GstPadDirection direction, GstCaps * caps);
176 static void gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
177 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
178 static gboolean gst_ffmpegscale_get_unit_size (GstBaseTransform * trans,
179 GstCaps * caps, guint * size);
180 static gboolean gst_ffmpegscale_set_caps (GstBaseTransform * trans,
181 GstCaps * incaps, GstCaps * outcaps);
182 static GstFlowReturn gst_ffmpegscale_transform (GstBaseTransform * trans,
183 GstBuffer * inbuf, GstBuffer * outbuf);
185 static gboolean gst_ffmpegscale_handle_src_event (GstPad * pad,
189 gst_ffmpegscale_base_init (gpointer g_class)
191 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
193 gst_element_class_add_pad_template (element_class,
194 gst_static_pad_template_get (&src_factory));
195 gst_element_class_add_pad_template (element_class,
196 gst_static_pad_template_get (&sink_factory));
197 gst_element_class_set_details_simple (element_class, "FFMPEG Scale element",
198 "Filter/Converter/Video",
199 "Converts video from one resolution to another",
200 "Luca Ognibene <luogni@tin.it>, Mark Nauwelaerts <mnauw@users.sf.net>");
204 gst_ffmpegscale_class_init (GstFFMpegScaleClass * klass)
206 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
207 GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
209 gobject_class->finalize = gst_ffmpegscale_finalize;
210 gobject_class->set_property = gst_ffmpegscale_set_property;
211 gobject_class->get_property = gst_ffmpegscale_get_property;
213 g_object_class_install_property (gobject_class, PROP_METHOD,
214 g_param_spec_enum ("method", "method", "method",
215 GST_TYPE_FFMPEGSCALE_METHOD, DEFAULT_PROP_METHOD,
216 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218 trans_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegscale_stop);
219 trans_class->transform_caps =
220 GST_DEBUG_FUNCPTR (gst_ffmpegscale_transform_caps);
221 trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_ffmpegscale_fixate_caps);
222 trans_class->get_unit_size =
223 GST_DEBUG_FUNCPTR (gst_ffmpegscale_get_unit_size);
224 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_ffmpegscale_set_caps);
225 trans_class->transform = GST_DEBUG_FUNCPTR (gst_ffmpegscale_transform);
227 trans_class->passthrough_on_same_caps = TRUE;
231 gst_ffmpegscale_init (GstFFMpegScale * scale, GstFFMpegScaleClass * klass)
233 GstBaseTransform *trans = GST_BASE_TRANSFORM (scale);
235 gst_pad_set_event_function (trans->srcpad, gst_ffmpegscale_handle_src_event);
237 scale->method = DEFAULT_PROP_METHOD;
239 scale->in_pixfmt = PIX_FMT_NONE;
240 scale->out_pixfmt = PIX_FMT_NONE;
244 gst_ffmpegscale_reset (GstFFMpegScale * scale)
246 if (scale->ctx != NULL) {
247 sws_freeContext (scale->ctx);
251 scale->in_pixfmt = PIX_FMT_NONE;
252 scale->out_pixfmt = PIX_FMT_NONE;
256 gst_ffmpegscale_finalize (GObject * object)
258 GstFFMpegScale *scale = GST_FFMPEGSCALE (object);
260 gst_ffmpegscale_reset (scale);
262 G_OBJECT_CLASS (parent_class)->finalize (object);
265 /* copies the given caps */
267 gst_ffmpegscale_caps_remove_format_info (GstCaps * caps)
270 GstStructure *structure;
274 caps = gst_caps_copy (caps);
276 for (i = 0; i < gst_caps_get_size (caps); i++) {
277 structure = gst_caps_get_structure (caps, i);
279 gst_structure_set_name (structure, "video/x-raw-yuv");
280 gst_structure_remove_field (structure, "format");
281 gst_structure_remove_field (structure, "endianness");
282 gst_structure_remove_field (structure, "depth");
283 gst_structure_remove_field (structure, "bpp");
284 gst_structure_remove_field (structure, "red_mask");
285 gst_structure_remove_field (structure, "green_mask");
286 gst_structure_remove_field (structure, "blue_mask");
287 gst_structure_remove_field (structure, "alpha_mask");
288 gst_structure_remove_field (structure, "palette_data");
291 rgbcaps = gst_caps_copy (caps);
293 for (i = 0; i < gst_caps_get_size (rgbcaps); i++) {
294 structure = gst_caps_get_structure (rgbcaps, i);
296 gst_structure_set_name (structure, "video/x-raw-rgb");
298 graycaps = gst_caps_copy (caps);
300 for (i = 0; i < gst_caps_get_size (graycaps); i++) {
301 structure = gst_caps_get_structure (graycaps, i);
303 gst_structure_set_name (structure, "video/x-raw-gray");
306 gst_caps_append (caps, graycaps);
307 gst_caps_append (caps, rgbcaps);
313 gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
314 GstPadDirection direction, GstCaps * caps)
316 GstFFMpegScale *scale;
318 GstStructure *structure;
321 /* this function is always called with a simple caps */
322 g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL);
324 scale = GST_FFMPEGSCALE (trans);
326 structure = gst_caps_get_structure (caps, 0);
328 ret = gst_caps_copy (caps);
329 structure = gst_structure_copy (gst_caps_get_structure (ret, 0));
331 gst_structure_set (structure,
332 "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
333 "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
335 gst_caps_merge_structure (ret, gst_structure_copy (structure));
337 /* if pixel aspect ratio, make a range of it */
338 if ((par = gst_structure_get_value (structure, "pixel-aspect-ratio"))) {
339 gst_structure_set (structure,
340 "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
342 gst_caps_merge_structure (ret, structure);
344 gst_structure_free (structure);
347 /* now also unfix colour space format */
348 gst_caps_append (ret, gst_ffmpegscale_caps_remove_format_info (ret));
350 GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);
356 gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
357 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
359 GstStructure *ins, *outs;
360 const GValue *from_par, *to_par;
362 g_return_if_fail (gst_caps_is_fixed (caps));
364 GST_DEBUG_OBJECT (trans, "trying to fixate othercaps %" GST_PTR_FORMAT
365 " based on caps %" GST_PTR_FORMAT, othercaps, caps);
367 ins = gst_caps_get_structure (caps, 0);
368 outs = gst_caps_get_structure (othercaps, 0);
370 from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
371 to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
373 /* we have both PAR but they might not be fixated */
374 if (from_par && to_par) {
375 gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
376 gint count = 0, w = 0, h = 0;
379 /* from_par should be fixed */
380 g_return_if_fail (gst_value_is_fixed (from_par));
382 from_par_n = gst_value_get_fraction_numerator (from_par);
383 from_par_d = gst_value_get_fraction_denominator (from_par);
385 /* fixate the out PAR */
386 if (!gst_value_is_fixed (to_par)) {
387 GST_DEBUG_OBJECT (trans, "fixating to_par to %dx%d", from_par_n,
389 gst_structure_fixate_field_nearest_fraction (outs, "pixel-aspect-ratio",
390 from_par_n, from_par_d);
393 to_par_n = gst_value_get_fraction_numerator (to_par);
394 to_par_d = gst_value_get_fraction_denominator (to_par);
396 /* if both width and height are already fixed, we can't do anything
397 * about it anymore */
398 if (gst_structure_get_int (outs, "width", &w))
400 if (gst_structure_get_int (outs, "height", &h))
403 GST_DEBUG_OBJECT (trans, "dimensions already set to %dx%d, not fixating",
408 gst_structure_get_int (ins, "width", &from_w);
409 gst_structure_get_int (ins, "height", &from_h);
411 if (!gst_video_calculate_display_ratio (&num, &den, from_w, from_h,
412 from_par_n, from_par_d, to_par_n, to_par_d)) {
413 GST_ELEMENT_ERROR (trans, CORE, NEGOTIATION, (NULL),
414 ("Error calculating the output scaled size - integer overflow"));
418 GST_DEBUG_OBJECT (trans,
419 "scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
420 from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
421 GST_DEBUG_OBJECT (trans, "resulting output should respect ratio of %d/%d",
424 /* now find a width x height that respects this display ratio.
425 * prefer those that have one of w/h the same as the incoming video
426 * using wd / hd = num / den */
428 /* if one of the output width or height is fixed, we work from there */
430 GST_DEBUG_OBJECT (trans, "height is fixed,scaling width");
431 w = (guint) gst_util_uint64_scale_int (h, num, den);
433 GST_DEBUG_OBJECT (trans, "width is fixed, scaling height");
434 h = (guint) gst_util_uint64_scale_int (w, den, num);
436 /* none of width or height is fixed, figure out both of them based only on
437 * the input width and height */
438 /* check hd / den is an integer scale factor, and scale wd with the PAR */
439 if (from_h % den == 0) {
440 GST_DEBUG_OBJECT (trans, "keeping video height");
442 w = (guint) gst_util_uint64_scale_int (h, num, den);
443 } else if (from_w % num == 0) {
444 GST_DEBUG_OBJECT (trans, "keeping video width");
446 h = (guint) gst_util_uint64_scale_int (w, den, num);
448 GST_DEBUG_OBJECT (trans, "approximating but keeping video height");
450 w = (guint) gst_util_uint64_scale_int (h, num, den);
453 GST_DEBUG_OBJECT (trans, "scaling to %dx%d", w, h);
456 gst_structure_fixate_field_nearest_int (outs, "width", w);
457 gst_structure_fixate_field_nearest_int (outs, "height", h);
461 if (gst_structure_get_int (ins, "width", &width)) {
462 if (gst_structure_has_field (outs, "width")) {
463 gst_structure_fixate_field_nearest_int (outs, "width", width);
466 if (gst_structure_get_int (ins, "height", &height)) {
467 if (gst_structure_has_field (outs, "height")) {
468 gst_structure_fixate_field_nearest_int (outs, "height", height);
473 GST_DEBUG_OBJECT (trans, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
477 gst_ffmpegscale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
481 GstVideoFormat format;
483 if (!gst_video_format_parse_caps (caps, &format, &width, &height))
486 *size = gst_video_format_get_size (format, width, height);
488 GST_DEBUG_OBJECT (trans, "unit size = %d for format %d w %d height %d",
489 *size, format, width, height);
494 /* Convert a GstCaps (video/raw) to a FFMPEG PixFmt
496 static enum PixelFormat
497 gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps)
499 GstStructure *structure;
500 enum PixelFormat pix_fmt = PIX_FMT_NONE;
502 GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
503 g_return_val_if_fail (gst_caps_get_size (caps) == 1, PIX_FMT_NONE);
504 structure = gst_caps_get_structure (caps, 0);
506 if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) {
509 if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
511 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
512 pix_fmt = PIX_FMT_YUYV422;
514 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
515 pix_fmt = PIX_FMT_YUV420P;
517 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
518 pix_fmt = PIX_FMT_YUV411P;
520 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
521 pix_fmt = PIX_FMT_YUV422P;
523 case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
524 pix_fmt = PIX_FMT_YUV410P;
528 } else if (strcmp (gst_structure_get_name (structure),
529 "video/x-raw-rgb") == 0) {
530 gint bpp = 0, rmask = 0, endianness = 0;
532 if (gst_structure_get_int (structure, "bpp", &bpp) &&
533 gst_structure_get_int (structure, "endianness", &endianness) &&
534 endianness == G_BIG_ENDIAN) {
535 if (gst_structure_get_int (structure, "red_mask", &rmask)) {
538 if (rmask == 0x00ff0000)
539 pix_fmt = PIX_FMT_ARGB;
540 else if (rmask == 0xff000000)
541 pix_fmt = PIX_FMT_RGBA;
542 else if (rmask == 0xff00)
543 pix_fmt = PIX_FMT_BGRA;
544 else if (rmask == 0xff)
545 pix_fmt = PIX_FMT_ABGR;
548 if (rmask == 0x0000FF)
549 pix_fmt = PIX_FMT_BGR24;
551 pix_fmt = PIX_FMT_RGB24;
554 if (endianness == G_BYTE_ORDER)
555 pix_fmt = PIX_FMT_RGB565;
558 if (endianness == G_BYTE_ORDER)
559 pix_fmt = PIX_FMT_RGB555;
567 pix_fmt = PIX_FMT_PAL8;
577 gst_ffmpegscale_fill_info (GstFFMpegScale * scale, GstVideoFormat format,
578 guint width, guint height, gint stride[], gint offset[])
582 for (i = 0; i < 3; i++) {
583 stride[i] = gst_video_format_get_row_stride (format, i, width);
584 offset[i] = gst_video_format_get_component_offset (format, i, width,
586 /* stay close to the ffmpeg offset way */
589 GST_DEBUG_OBJECT (scale, "format %d, component %d; stride %d, offset %d",
590 format, i, stride[i], offset[i]);
595 gst_ffmpegscale_set_caps (GstBaseTransform * trans, GstCaps * incaps,
598 GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
599 guint mmx_flags, altivec_flags;
601 GstVideoFormat in_format, out_format;
604 g_return_val_if_fail (scale->method <
605 G_N_ELEMENTS (gst_ffmpegscale_method_flags), FALSE);
608 sws_freeContext (scale->ctx);
612 ok = gst_video_format_parse_caps (incaps, &in_format, &scale->in_width,
614 ok &= gst_video_format_parse_caps (outcaps, &out_format, &scale->out_width,
616 scale->in_pixfmt = gst_ffmpeg_caps_to_pixfmt (incaps);
617 scale->out_pixfmt = gst_ffmpeg_caps_to_pixfmt (outcaps);
619 if (!ok || scale->in_pixfmt == PIX_FMT_NONE ||
620 scale->out_pixfmt == PIX_FMT_NONE ||
621 in_format == GST_VIDEO_FORMAT_UNKNOWN ||
622 out_format == GST_VIDEO_FORMAT_UNKNOWN)
625 GST_DEBUG_OBJECT (scale, "format %d => %d, from=%dx%d -> to=%dx%d", in_format,
626 out_format, scale->in_width, scale->in_height, scale->out_width,
629 gst_ffmpegscale_fill_info (scale, in_format, scale->in_width,
630 scale->in_height, scale->in_stride, scale->in_offset);
631 gst_ffmpegscale_fill_info (scale, out_format, scale->out_width,
632 scale->out_height, scale->out_stride, scale->out_offset);
635 mmx_flags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
637 orc_target_get_default_flags (orc_target_get_by_name ("altivec"));
638 swsflags = (mmx_flags & ORC_TARGET_MMX_MMX ? SWS_CPU_CAPS_MMX : 0)
639 | (mmx_flags & ORC_TARGET_MMX_MMXEXT ? SWS_CPU_CAPS_MMX2 : 0)
640 | (mmx_flags & ORC_TARGET_MMX_3DNOW ? SWS_CPU_CAPS_3DNOW : 0)
641 | (altivec_flags & ORC_TARGET_ALTIVEC_ALTIVEC ? SWS_CPU_CAPS_ALTIVEC : 0);
649 scale->ctx = sws_getContext (scale->in_width, scale->in_height,
650 scale->in_pixfmt, scale->out_width, scale->out_height, scale->out_pixfmt,
651 swsflags | gst_ffmpegscale_method_flags[scale->method], NULL, NULL, NULL);
660 GST_ELEMENT_ERROR (trans, LIBRARY, INIT, (NULL), (NULL));
665 GST_DEBUG_OBJECT (trans, "refused caps %" GST_PTR_FORMAT, incaps);
671 gst_ffmpegscale_transform (GstBaseTransform * trans, GstBuffer * inbuf,
674 GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
675 guint8 *in_data[3] = { NULL, NULL, NULL };
676 guint8 *out_data[3] = { NULL, NULL, NULL };
679 for (i = 0; i < 3; i++) {
680 /* again; stay close to the ffmpeg offset way */
681 if (!i || scale->in_offset[i])
682 in_data[i] = GST_BUFFER_DATA (inbuf) + scale->in_offset[i];
683 if (!i || scale->out_offset[i])
684 out_data[i] = GST_BUFFER_DATA (outbuf) + scale->out_offset[i];
687 sws_scale (scale->ctx, (const guint8 **) in_data, scale->in_stride, 0,
688 scale->in_height, out_data, scale->out_stride);
694 gst_ffmpegscale_handle_src_event (GstPad * pad, GstEvent * event)
696 GstFFMpegScale *scale;
697 GstStructure *structure;
701 scale = GST_FFMPEGSCALE (gst_pad_get_parent (pad));
703 switch (GST_EVENT_TYPE (event)) {
704 case GST_EVENT_NAVIGATION:
706 GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));
708 structure = (GstStructure *) gst_event_get_structure (event);
709 if (gst_structure_get_double (structure, "pointer_x", &pointer)) {
710 gst_structure_set (structure,
711 "pointer_x", G_TYPE_DOUBLE,
712 pointer * scale->in_width / scale->out_width, NULL);
714 if (gst_structure_get_double (structure, "pointer_y", &pointer)) {
715 gst_structure_set (structure,
716 "pointer_y", G_TYPE_DOUBLE,
717 pointer * scale->in_height / scale->out_height, NULL);
724 res = gst_pad_event_default (pad, event);
726 gst_object_unref (scale);
732 gst_ffmpegscale_stop (GstBaseTransform * trans)
734 GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
736 gst_ffmpegscale_reset (scale);
742 gst_ffmpegscale_set_property (GObject * object, guint prop_id,
743 const GValue * value, GParamSpec * pspec)
745 GstFFMpegScale *scale = GST_FFMPEGSCALE (object);
749 scale->method = g_value_get_enum (value);
752 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
758 gst_ffmpegscale_get_property (GObject * object, guint prop_id, GValue * value,
761 GstFFMpegScale *scale = GST_FFMPEGSCALE (object);
765 g_value_set_enum (value, scale->method);
768 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
773 #ifndef GST_DISABLE_GST_DEBUG
775 gst_ffmpeg_log_callback (void *ptr, int level, const char *fmt, va_list vl)
777 GstDebugLevel gst_level;
781 gst_level = GST_LEVEL_NONE;
784 gst_level = GST_LEVEL_ERROR;
787 gst_level = GST_LEVEL_INFO;
790 gst_level = GST_LEVEL_DEBUG;
793 gst_level = GST_LEVEL_INFO;
797 gst_debug_log_valist (ffmpegscale_debug, gst_level, "", "", 0, NULL, fmt, vl);
802 plugin_init (GstPlugin * plugin)
804 GST_DEBUG_CATEGORY_INIT (ffmpegscale_debug, "ffvideoscale", 0,
805 "video scaling element");
811 #ifndef GST_DISABLE_GST_DEBUG
812 av_log_set_callback (gst_ffmpeg_log_callback);
815 return gst_element_register (plugin, "ffvideoscale",
816 GST_RANK_NONE, GST_TYPE_FFMPEGSCALE);
819 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
822 "videoscaling element (" FFMPEG_SOURCE ")",
824 PACKAGE_VERSION, "GPL", "FFMpeg", "http://ffmpeg.sourceforge.net/")