GstPad *sinkpad, *srcpad;
/* state */
- gint in_width, in_height;
- gint out_width, out_height;
+ GstVideoInfo in_info, out_info;
enum PixelFormat in_pixfmt, out_pixfmt;
struct SwsContext *ctx;
- /* cached auxiliary data */
- gint in_stride[3], in_offset[3];
- gint out_stride[3], out_offset[3];
-
/* property */
gint method;
} GstFFMpegScale;
/* libswscale supported formats depend on endianness */
#if G_BYTE_ORDER == G_BIG_ENDIAN
#define VIDEO_CAPS \
- GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
- GST_VIDEO_CAPS_xRGB "; " GST_VIDEO_CAPS_xBGR "; " \
- GST_VIDEO_CAPS_ARGB "; " GST_VIDEO_CAPS_ABGR "; " \
- GST_VIDEO_CAPS_YUV ("{ I420, YUY2, UYVY, Y41B, Y42B }")
+ GST_VIDEO_CAPS_MAKE ("{ RGB, BGR, xRGB, xBGR, ARGB, ABGR, I420, YUY2, UYVY, Y41B, Y42B }")
#else
#define VIDEO_CAPS \
- GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " \
- GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_BGRx "; " \
- GST_VIDEO_CAPS_RGBA "; " GST_VIDEO_CAPS_BGRA "; " \
- GST_VIDEO_CAPS_YUV ("{ I420, YUY2, UYVY, Y41B, Y42B }")
+ GST_VIDEO_CAPS_MAKE ("{ RGB, BGR, RGBx, BGRx, RGBA, BGRA, I420, YUY2, UYVY, Y41B, Y42B }")
#endif
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
/* FILL ME */
};
-GST_BOILERPLATE (GstFFMpegScale, gst_ffmpegscale, GstBaseTransform,
- GST_TYPE_BASE_TRANSFORM);
+#define gst_ffmpegscale_parent_class parent_class
+G_DEFINE_TYPE (GstFFMpegScale, gst_ffmpegscale, GST_TYPE_BASE_TRANSFORM);
static void gst_ffmpegscale_finalize (GObject * object);
static void gst_ffmpegscale_set_property (GObject * object, guint prop_id,
static gboolean gst_ffmpegscale_stop (GstBaseTransform * trans);
static GstCaps *gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps);
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter);
static void gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static gboolean gst_ffmpegscale_get_unit_size (GstBaseTransform * trans,
- GstCaps * caps, guint * size);
+ GstCaps * caps, gsize * size);
static gboolean gst_ffmpegscale_set_caps (GstBaseTransform * trans,
GstCaps * incaps, GstCaps * outcaps);
static GstFlowReturn gst_ffmpegscale_transform (GstBaseTransform * trans,
GstEvent * event);
static void
-gst_ffmpegscale_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
- gst_element_class_set_details_simple (element_class, "FFMPEG Scale element",
- "Filter/Converter/Video",
- "Converts video from one resolution to another",
- "Luca Ognibene <luogni@tin.it>, Mark Nauwelaerts <mnauw@users.sf.net>");
-}
-
-static void
gst_ffmpegscale_class_init (GstFFMpegScaleClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
gobject_class->finalize = gst_ffmpegscale_finalize;
GST_TYPE_FFMPEGSCALE_METHOD, DEFAULT_PROP_METHOD,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "FFMPEG Scale element", "Filter/Converter/Video",
+ "Converts video from one resolution to another",
+ "Luca Ognibene <luogni@tin.it>, Mark Nauwelaerts <mnauw@users.sf.net>");
+
trans_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegscale_stop);
trans_class->transform_caps =
GST_DEBUG_FUNCPTR (gst_ffmpegscale_transform_caps);
}
static void
-gst_ffmpegscale_init (GstFFMpegScale * scale, GstFFMpegScaleClass * klass)
+gst_ffmpegscale_init (GstFFMpegScale * scale)
{
GstBaseTransform *trans = GST_BASE_TRANSFORM (scale);
static GstCaps *
gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps)
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
GstCaps *ret;
GstStructure *structure;
static gboolean
gst_ffmpegscale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
- guint * size)
+ gsize * size)
{
- gint width, height;
- GstVideoFormat format;
+ GstVideoInfo info;
- if (!gst_video_format_parse_caps (caps, &format, &width, &height))
+ if (!gst_video_info_from_caps (&info, caps))
return FALSE;
- *size = gst_video_format_get_size (format, width, height);
+ *size = info.size;
GST_DEBUG_OBJECT (trans, "unit size = %d for format %d w %d height %d",
- *size, format, width, height);
+ *size, GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+ GST_VIDEO_INFO_HEIGHT (&info));
return TRUE;
}
static enum PixelFormat
gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps)
{
- GstStructure *structure;
- enum PixelFormat pix_fmt = PIX_FMT_NONE;
+ GstVideoInfo info;
+ enum PixelFormat pix_fmt;
GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
- g_return_val_if_fail (gst_caps_get_size (caps) == 1, PIX_FMT_NONE);
- structure = gst_caps_get_structure (caps, 0);
- if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) {
- guint32 fourcc;
-
- if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
- switch (fourcc) {
- case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
- pix_fmt = PIX_FMT_YUYV422;
- break;
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- pix_fmt = PIX_FMT_UYVY422;
- break;
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- pix_fmt = PIX_FMT_YUV420P;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
- pix_fmt = PIX_FMT_YUV411P;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
- pix_fmt = PIX_FMT_YUV422P;
- break;
- case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
- pix_fmt = PIX_FMT_YUV410P;
- break;
- }
- }
- } else if (strcmp (gst_structure_get_name (structure),
- "video/x-raw-rgb") == 0) {
- gint bpp = 0, rmask = 0, endianness = 0;
-
- if (gst_structure_get_int (structure, "bpp", &bpp) &&
- gst_structure_get_int (structure, "endianness", &endianness) &&
- endianness == G_BIG_ENDIAN) {
- if (gst_structure_get_int (structure, "red_mask", &rmask)) {
- switch (bpp) {
- case 32:
- if (rmask == 0x00ff0000)
- pix_fmt = PIX_FMT_ARGB;
- else if (rmask == 0xff000000)
- pix_fmt = PIX_FMT_RGBA;
- else if (rmask == 0xff00)
- pix_fmt = PIX_FMT_BGRA;
- else if (rmask == 0xff)
- pix_fmt = PIX_FMT_ABGR;
- break;
- case 24:
- if (rmask == 0x0000FF)
- pix_fmt = PIX_FMT_BGR24;
- else
- pix_fmt = PIX_FMT_RGB24;
- break;
- case 16:
- if (endianness == G_BYTE_ORDER)
- pix_fmt = PIX_FMT_RGB565;
- break;
- case 15:
- if (endianness == G_BYTE_ORDER)
- pix_fmt = PIX_FMT_RGB555;
- break;
- default:
- /* nothing */
- break;
- }
- } else {
- if (bpp == 8) {
- pix_fmt = PIX_FMT_PAL8;
- }
- }
- }
- }
+ if (gst_video_info_from_caps (&info, caps))
+ goto invalid_caps;
+ switch (GST_VIDEO_INFO_FORMAT (&info)) {
+ case GST_VIDEO_FORMAT_YUY2:
+ pix_fmt = PIX_FMT_YUYV422;
+ break;
+ case GST_VIDEO_FORMAT_UYVY:
+ pix_fmt = PIX_FMT_UYVY422;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case GST_VIDEO_FORMAT_Y41B:
+ pix_fmt = PIX_FMT_YUV411P;
+ break;
+ case GST_VIDEO_FORMAT_Y42B:
+ pix_fmt = PIX_FMT_YUV422P;
+ break;
+ case GST_VIDEO_FORMAT_YUV9:
+ pix_fmt = PIX_FMT_YUV410P;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ pix_fmt = PIX_FMT_ARGB;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ pix_fmt = PIX_FMT_RGBA;
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ pix_fmt = PIX_FMT_BGRA;
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ pix_fmt = PIX_FMT_ABGR;
+ break;
+ case GST_VIDEO_FORMAT_BGR:
+ pix_fmt = PIX_FMT_BGR24;
+ break;
+ case GST_VIDEO_FORMAT_RGB:
+ pix_fmt = PIX_FMT_RGB24;
+ break;
+ case GST_VIDEO_FORMAT_RGB16:
+ pix_fmt = PIX_FMT_RGB565;
+ break;
+ case GST_VIDEO_FORMAT_RGB15:
+ pix_fmt = PIX_FMT_RGB555;
+ break;
+ case GST_VIDEO_FORMAT_RGB8_PALETTED:
+ pix_fmt = PIX_FMT_PAL8;
+ break;
+ default:
+ pix_fmt = PIX_FMT_NONE;
+ break;
+ }
return pix_fmt;
-}
-static void
-gst_ffmpegscale_fill_info (GstFFMpegScale * scale, GstVideoFormat format,
- guint width, guint height, gint stride[], gint offset[])
-{
- gint i;
-
- for (i = 0; i < 3; i++) {
- stride[i] = gst_video_format_get_row_stride (format, i, width);
- offset[i] = gst_video_format_get_component_offset (format, i, width,
- height);
- /* stay close to the ffmpeg offset way */
- if (offset[i] < 3)
- offset[i] = 0;
- GST_DEBUG_OBJECT (scale, "format %d, component %d; stride %d, offset %d",
- format, i, stride[i], offset[i]);
+ /* ERROR */
+invalid_caps:
+ {
+ return PIX_FMT_NONE;
}
}
GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
guint mmx_flags, altivec_flags;
gint swsflags;
- GstVideoFormat in_format, out_format;
gboolean ok;
g_return_val_if_fail (scale->method <
scale->ctx = NULL;
}
- ok = gst_video_format_parse_caps (incaps, &in_format, &scale->in_width,
- &scale->in_height);
- ok &= gst_video_format_parse_caps (outcaps, &out_format, &scale->out_width,
- &scale->out_height);
+ ok = gst_video_info_from_caps (&scale->in_info, incaps);
+ ok &= gst_video_info_from_caps (&scale->out_info, outcaps);
+
scale->in_pixfmt = gst_ffmpeg_caps_to_pixfmt (incaps);
scale->out_pixfmt = gst_ffmpeg_caps_to_pixfmt (outcaps);
if (!ok || scale->in_pixfmt == PIX_FMT_NONE ||
scale->out_pixfmt == PIX_FMT_NONE ||
- in_format == GST_VIDEO_FORMAT_UNKNOWN ||
- out_format == GST_VIDEO_FORMAT_UNKNOWN)
+ GST_VIDEO_INFO_FORMAT (&scale->in_info) == GST_VIDEO_FORMAT_UNKNOWN ||
+ GST_VIDEO_INFO_FORMAT (&scale->out_info) == GST_VIDEO_FORMAT_UNKNOWN)
goto refuse_caps;
- GST_DEBUG_OBJECT (scale, "format %d => %d, from=%dx%d -> to=%dx%d", in_format,
- out_format, scale->in_width, scale->in_height, scale->out_width,
- scale->out_height);
-
- gst_ffmpegscale_fill_info (scale, in_format, scale->in_width,
- scale->in_height, scale->in_stride, scale->in_offset);
- gst_ffmpegscale_fill_info (scale, out_format, scale->out_width,
- scale->out_height, scale->out_stride, scale->out_offset);
+ GST_DEBUG_OBJECT (scale, "format %d => %d, from=%dx%d -> to=%dx%d",
+ GST_VIDEO_INFO_FORMAT (&scale->in_info),
+ GST_VIDEO_INFO_FORMAT (&scale->out_info),
+ GST_VIDEO_INFO_WIDTH (&scale->in_info),
+ GST_VIDEO_INFO_HEIGHT (&scale->in_info),
+ GST_VIDEO_INFO_WIDTH (&scale->out_info),
+ GST_VIDEO_INFO_HEIGHT (&scale->out_info));
#ifdef HAVE_ORC
mmx_flags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
swsflags = 0;
#endif
-
- scale->ctx = sws_getContext (scale->in_width, scale->in_height,
- scale->in_pixfmt, scale->out_width, scale->out_height, scale->out_pixfmt,
- swsflags | gst_ffmpegscale_method_flags[scale->method], NULL, NULL, NULL);
+ scale->ctx = sws_getContext (scale->in_info.width, scale->in_info.height,
+ scale->in_pixfmt, scale->out_info.width, scale->out_info.height,
+ scale->out_pixfmt, swsflags | gst_ffmpegscale_method_flags[scale->method],
+ NULL, NULL, NULL);
if (!scale->ctx)
goto setup_failed;
GstBuffer * outbuf)
{
GstFFMpegScale *scale = GST_FFMPEGSCALE (trans);
- guint8 *in_data[3] = { NULL, NULL, NULL };
- guint8 *out_data[3] = { NULL, NULL, NULL };
- gint i;
-
- for (i = 0; i < 3; i++) {
- /* again; stay close to the ffmpeg offset way */
- if (!i || scale->in_offset[i])
- in_data[i] = GST_BUFFER_DATA (inbuf) + scale->in_offset[i];
- if (!i || scale->out_offset[i])
- out_data[i] = GST_BUFFER_DATA (outbuf) + scale->out_offset[i];
- }
+ GstVideoFrame in_frame, out_frame;
- sws_scale (scale->ctx, (const guint8 **) in_data, scale->in_stride, 0,
- scale->in_height, out_data, scale->out_stride);
+ if (!gst_video_frame_map (&in_frame, &scale->in_info, inbuf, GST_MAP_READ))
+ goto invalid_buffer;
+
+ if (!gst_video_frame_map (&out_frame, &scale->out_info, outbuf,
+ GST_MAP_WRITE))
+ goto invalid_buffer;
+
+ sws_scale (scale->ctx, (const guint8 **) in_frame.data, in_frame.info.stride,
+ 0, scale->in_info.height, (guint8 **) out_frame.data,
+ out_frame.info.stride);
+
+ gst_video_frame_unmap (&in_frame);
+ gst_video_frame_unmap (&out_frame);
return GST_FLOW_OK;
+
+ /* ERRORS */
+invalid_buffer:
+ {
+ return GST_FLOW_OK;
+ }
}
static gboolean
if (gst_structure_get_double (structure, "pointer_x", &pointer)) {
gst_structure_set (structure,
"pointer_x", G_TYPE_DOUBLE,
- pointer * scale->in_width / scale->out_width, NULL);
+ pointer * scale->in_info.width / scale->out_info.width, NULL);
}
if (gst_structure_get_double (structure, "pointer_y", &pointer)) {
gst_structure_set (structure,
"pointer_y", G_TYPE_DOUBLE,
- pointer * scale->in_height / scale->out_height, NULL);
+ pointer * scale->in_info.height / scale->out_info.height, NULL);
}
break;
default: