static GstFlowReturn gst_ffmpegscale_transform(GstBaseTransform* trans, GstBuffer* inbuf, GstBuffer* outbuf) { GstFFMpegScale* scale = GST_FFMPEGSCALE(trans); guint8* in_data[3] = { NULL, NULL, NULL }; guint8* out_data[3] = { NULL, NULL, NULL }; gint i; FFVSImage dest = { NULL, }; FFVSImage dest_u = { NULL, }; FFVSImage dest_v = { NULL, }; 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]; } } if (scale->add_borders) { const guint8* black = get_black_for_format(scale->out_format); gst_video_scale_setup_vs_image(&dest, scale->out_format, 0, scale->out_width, scale->out_height, scale->borders_w, scale->borders_h, GST_BUFFER_DATA(outbuf)); if (scale->out_format == GST_VIDEO_FORMAT_I420 || scale->out_format == GST_VIDEO_FORMAT_YV12 || scale->out_format == GST_VIDEO_FORMAT_Y444 || scale->out_format == GST_VIDEO_FORMAT_Y42B || scale->out_format == GST_VIDEO_FORMAT_Y41B) { gst_video_scale_setup_vs_image(&dest_u, scale->out_format, 1, scale->out_width, scale->out_height, scale->borders_w, scale->borders_h, GST_BUFFER_DATA(outbuf)); gst_video_scale_setup_vs_image(&dest_v, scale->out_format, 2, scale->out_width, scale->out_height, scale->borders_w, scale->borders_h, GST_BUFFER_DATA(outbuf)); } switch (scale->out_format) { case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_AYUV: vs_fill_borders_RGBA(&dest, black); break; case GST_VIDEO_FORMAT_ARGB64: case GST_VIDEO_FORMAT_AYUV64: vs_fill_borders_AYUV64(&dest, black); break; case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_v308: vs_fill_borders_RGB(&dest, black); break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_YVYU: vs_fill_borders_YUYV(&dest, black); break; case GST_VIDEO_FORMAT_UYVY: vs_fill_borders_UYVY(&dest, black); break; case GST_VIDEO_FORMAT_GRAY8: vs_fill_borders_Y(&dest, black); break; case GST_VIDEO_FORMAT_GRAY16_LE: case GST_VIDEO_FORMAT_GRAY16_BE: vs_fill_borders_Y16(&dest, 0); break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B: vs_fill_borders_Y(&dest, black); vs_fill_borders_Y(&dest_u, black + 1); vs_fill_borders_Y(&dest_v, black + 2); break; case GST_VIDEO_FORMAT_RGB16: vs_fill_borders_RGB565(&dest, black); break; case GST_VIDEO_FORMAT_RGB15: vs_fill_borders_RGB555(&dest, black); break; default: break; } } sws_scale(scale->ctx, (const guint8**) in_data, scale->in_stride, 0, scale->in_height, out_data, scale->out_stride); return GST_FLOW_OK; }
static GstFlowReturn gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out) { GstVideoScale *videoscale = GST_VIDEO_SCALE (trans); GstFlowReturn ret = GST_FLOW_OK; VSImage dest = { NULL, }; VSImage src = { NULL, }; VSImage dest_u = { NULL, }; VSImage dest_v = { NULL, }; VSImage src_u = { NULL, }; VSImage src_v = { NULL, }; gint method; const guint8 *black = _get_black_for_format (videoscale->format); gboolean add_borders; GST_OBJECT_LOCK (videoscale); method = videoscale->method; add_borders = videoscale->add_borders; GST_OBJECT_UNLOCK (videoscale); if (videoscale->from_width == 1) { method = GST_VIDEO_SCALE_NEAREST; } if (method == GST_VIDEO_SCALE_4TAP && (videoscale->from_width < 4 || videoscale->from_height < 4)) { method = GST_VIDEO_SCALE_BILINEAR; } gst_video_scale_setup_vs_image (&src, videoscale->format, 0, videoscale->from_width, videoscale->from_height, 0, 0, GST_BUFFER_DATA (in)); gst_video_scale_setup_vs_image (&dest, videoscale->format, 0, videoscale->to_width, videoscale->to_height, videoscale->borders_w, videoscale->borders_h, GST_BUFFER_DATA (out)); if (videoscale->format == GST_VIDEO_FORMAT_I420 || videoscale->format == GST_VIDEO_FORMAT_YV12 || videoscale->format == GST_VIDEO_FORMAT_Y444 || videoscale->format == GST_VIDEO_FORMAT_Y42B || videoscale->format == GST_VIDEO_FORMAT_Y41B) { gst_video_scale_setup_vs_image (&src_u, videoscale->format, 1, videoscale->from_width, videoscale->from_height, 0, 0, GST_BUFFER_DATA (in)); gst_video_scale_setup_vs_image (&src_v, videoscale->format, 2, videoscale->from_width, videoscale->from_height, 0, 0, GST_BUFFER_DATA (in)); gst_video_scale_setup_vs_image (&dest_u, videoscale->format, 1, videoscale->to_width, videoscale->to_height, videoscale->borders_w, videoscale->borders_h, GST_BUFFER_DATA (out)); gst_video_scale_setup_vs_image (&dest_v, videoscale->format, 2, videoscale->to_width, videoscale->to_height, videoscale->borders_w, videoscale->borders_h, GST_BUFFER_DATA (out)); } switch (videoscale->format) { case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_AYUV: if (add_borders) vs_fill_borders_RGBA (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_ARGB64: case GST_VIDEO_FORMAT_AYUV64: if (add_borders) vs_fill_borders_AYUV64 (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_AYUV64 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_AYUV64 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_AYUV64 (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_v308: if (add_borders) vs_fill_borders_RGB (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_RGB (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_RGB (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_RGB (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_YVYU: if (add_borders) vs_fill_borders_YUYV (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_YUYV (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_YUYV (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_YUYV (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_UYVY: if (add_borders) vs_fill_borders_UYVY (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_UYVY (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_UYVY (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_UYVY (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_Y800: case GST_VIDEO_FORMAT_GRAY8: if (add_borders) vs_fill_borders_Y (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_GRAY16_LE: case GST_VIDEO_FORMAT_GRAY16_BE: case GST_VIDEO_FORMAT_Y16: if (add_borders) vs_fill_borders_Y16 (&dest, 0); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_Y16 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_Y16 (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B: if (add_borders) { vs_fill_borders_Y (&dest, black); vs_fill_borders_Y (&dest_u, black + 1); vs_fill_borders_Y (&dest_v, black + 2); } switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf); vs_image_scale_nearest_Y (&dest_u, &src_u, videoscale->tmp_buf); vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf); vs_image_scale_linear_Y (&dest_u, &src_u, videoscale->tmp_buf); vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf); vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf); vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_RGB16: if (add_borders) vs_fill_borders_RGB565 (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_RGB565 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_RGB565 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_RGB565 (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; case GST_VIDEO_FORMAT_RGB15: if (add_borders) vs_fill_borders_RGB555 (&dest, black); switch (method) { case GST_VIDEO_SCALE_NEAREST: vs_image_scale_nearest_RGB555 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_BILINEAR: vs_image_scale_linear_RGB555 (&dest, &src, videoscale->tmp_buf); break; case GST_VIDEO_SCALE_4TAP: vs_image_scale_4tap_RGB555 (&dest, &src, videoscale->tmp_buf); break; default: goto unknown_mode; } break; default: goto unsupported; } GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes", GST_BUFFER_SIZE (out)); return ret; /* ERRORS */ unsupported: { GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL), ("Unsupported format %d for scaling method %d", videoscale->format, method)); return GST_FLOW_ERROR; } unknown_mode: { GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL), ("Unknown scaling method %d", videoscale->method)); return GST_FLOW_ERROR; } }