mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
vaapipostproc: port to GStreamer 1.0.
Add support for interlaced streams with GStreamer 1.0 too. Basically, this enables vaapipostproc, though it is not auto-plugged yet. We also make sure to reply to CAPS queries, and happily handle CAPS events.
This commit is contained in:
parent
2909d0229d
commit
945516c9c7
6 changed files with 132 additions and 39 deletions
|
@ -58,7 +58,11 @@ gst_compat_structure_get_fourcc(const GstStructure *structure,
|
|||
typedef const guint8 *(*GstCompatTypeFindPeekFunction)(gpointer, gint64, guint);
|
||||
typedef void (*GstCompatTypeFindSuggestFunction)(gpointer, guint, GstCaps *);
|
||||
|
||||
/* GstQuery */
|
||||
/* GstPad */
|
||||
#define GST_PAD_CHAIN_FUNCTION_ARGS \
|
||||
GstPad *pad, GstObject *parent, GstBuffer *buffer
|
||||
#define GST_PAD_EVENT_FUNCTION_ARGS \
|
||||
GstPad *pad, GstObject *parent, GstEvent *event
|
||||
#define GST_PAD_QUERY_FUNCTION_ARGS \
|
||||
GstPad *pad, GstObject *parent, GstQuery *query
|
||||
#define GST_PAD_QUERY_FUNCTION_CALL(func, pad, parent, query) \
|
||||
|
@ -228,9 +232,22 @@ gst_compat_video_overlay_rectangle_get_pixels_unscaled_raw(
|
|||
&width, &height, &stride, flags);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
GST_VIDEO_BUFFER_FLAG_TFF = GST_VIDEO_BUFFER_TFF,
|
||||
GST_VIDEO_BUFFER_FLAG_RFF = GST_VIDEO_BUFFER_RFF,
|
||||
GST_VIDEO_BUFFER_FLAG_ONEFIELD = GST_VIDEO_BUFFER_ONEFIELD
|
||||
} GstVideoBufferFlags;
|
||||
|
||||
/* GstPad */
|
||||
#undef GST_FLOW_EOS
|
||||
#define GST_FLOW_EOS GST_FLOW_UNEXPECTED
|
||||
#undef GST_FLOW_FLUSHING
|
||||
#define GST_FLOW_FLUSHING GST_FLOW_WRONG_STATE
|
||||
|
||||
#define GST_PAD_CHAIN_FUNCTION_ARGS \
|
||||
GstPad *pad, GstBuffer *buffer
|
||||
#define GST_PAD_EVENT_FUNCTION_ARGS \
|
||||
GstPad *pad, GstEvent *event
|
||||
|
||||
/* GstElement */
|
||||
#undef gst_element_class_set_static_metadata
|
||||
|
|
|
@ -33,6 +33,7 @@ libgstvaapi_source_c = \
|
|||
gstvaapi.c \
|
||||
gstvaapidecode.c \
|
||||
gstvaapipluginutil.c \
|
||||
gstvaapipostproc.c \
|
||||
gstvaapisink.c \
|
||||
gstvaapiuploader.c \
|
||||
gstvaapivideobuffer.c \
|
||||
|
@ -42,6 +43,7 @@ libgstvaapi_source_c = \
|
|||
libgstvaapi_source_h = \
|
||||
gstvaapidecode.h \
|
||||
gstvaapipluginutil.h \
|
||||
gstvaapipostproc.h \
|
||||
gstvaapisink.h \
|
||||
gstvaapiuploader.h \
|
||||
gstvaapivideobuffer.h \
|
||||
|
@ -74,13 +76,11 @@ endif
|
|||
if USE_GST_API_0_10
|
||||
libgstvaapi_0_10_source_c = \
|
||||
gstvaapidownload.c \
|
||||
gstvaapipostproc.c \
|
||||
gstvaapiupload.c \
|
||||
$(NULL)
|
||||
|
||||
libgstvaapi_0_10_source_h = \
|
||||
gstvaapidownload.h \
|
||||
gstvaapipostproc.h \
|
||||
gstvaapiupload.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
|
|
@ -47,11 +47,9 @@ plugin_init (GstPlugin *plugin)
|
|||
gst_element_register(plugin, "vaapidecode",
|
||||
GST_RANK_PRIMARY,
|
||||
GST_TYPE_VAAPIDECODE);
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
gst_element_register(plugin, "vaapipostproc",
|
||||
GST_RANK_PRIMARY,
|
||||
GST_TYPE_VAAPIPOSTPROC);
|
||||
#endif
|
||||
gst_element_register(plugin, "vaapisink",
|
||||
GST_RANK_PRIMARY,
|
||||
GST_TYPE_VAAPISINK);
|
||||
|
|
|
@ -188,10 +188,11 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
|
|||
"pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d,
|
||||
NULL);
|
||||
|
||||
if (GST_VIDEO_INFO_IS_INTERLACED(vi))
|
||||
gst_caps_set_simple(state->caps, "interlaced", G_TYPE_BOOLEAN,
|
||||
TRUE, NULL);
|
||||
|
||||
if (GST_VIDEO_INFO_IS_INTERLACED(vi)) {
|
||||
GstStructure * const structure =
|
||||
gst_caps_get_structure(state->caps, 0);
|
||||
gst_structure_set_interlaced(structure, TRUE);
|
||||
}
|
||||
gst_caps_replace(&decode->srcpad_caps, state->caps);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -274,6 +275,7 @@ gst_vaapidecode_push_decoded_frames(GstVideoDecoder *vdec)
|
|||
GstVaapiVideoMeta *meta;
|
||||
GstVideoCodecFrame *out_frame;
|
||||
GstFlowReturn ret;
|
||||
guint flags;
|
||||
|
||||
/* Output all decoded frames */
|
||||
for (;;) {
|
||||
|
@ -296,6 +298,18 @@ gst_vaapidecode_push_decoded_frames(GstVideoDecoder *vdec)
|
|||
if (!meta)
|
||||
goto error_get_meta;
|
||||
gst_vaapi_video_meta_set_surface_proxy(meta, proxy);
|
||||
|
||||
flags = gst_vaapi_surface_proxy_get_flags(proxy);
|
||||
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
|
||||
guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED;
|
||||
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF)
|
||||
out_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
|
||||
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF)
|
||||
out_flags |= GST_VIDEO_BUFFER_FLAG_RFF;
|
||||
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD)
|
||||
out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD;
|
||||
GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags);
|
||||
}
|
||||
#else
|
||||
out_frame->output_buffer =
|
||||
gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
|
||||
|
|
|
@ -61,4 +61,43 @@ gst_vaapi_apply_composition(GstVaapiSurface *surface, GstBuffer *buffer);
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Helpers to handle interlaced contents */
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
# define GST_CAPS_INTERLACED_MODES \
|
||||
"interlace-mode = (string){ progressive, interleaved }"
|
||||
# define GST_CAPS_INTERLACED_FALSE \
|
||||
"interlace-mode = (string)progressive"
|
||||
|
||||
static inline void
|
||||
gst_structure_remove_interlaced_field(GstStructure *structure)
|
||||
{
|
||||
gst_structure_remove_field(structure, "interlace-mode");
|
||||
}
|
||||
|
||||
static inline void
|
||||
gst_structure_set_interlaced(GstStructure *structure, gboolean interlaced)
|
||||
{
|
||||
gst_structure_set(structure, "interlace-mode",
|
||||
G_TYPE_STRING, interlaced ? "interleaved" : "progressive", NULL);
|
||||
}
|
||||
#else
|
||||
# define GST_CAPS_INTERLACED_MODES \
|
||||
"interlaced = (boolean){ true, false }"
|
||||
# define GST_CAPS_INTERLACED_FALSE \
|
||||
"interlaced = (boolean)false"
|
||||
|
||||
static inline void
|
||||
gst_structure_remove_interlaced_field(GstStructure *structure)
|
||||
{
|
||||
gst_structure_remove_field(structure, "interlaced");
|
||||
}
|
||||
|
||||
static inline void
|
||||
gst_structure_set_interlaced(GstStructure *structure, gboolean interlaced)
|
||||
{
|
||||
gst_structure_set(structure, "interlaced",
|
||||
G_TYPE_BOOLEAN, interlaced, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GST_VAAPI_PLUGIN_UTIL_H */
|
||||
|
|
|
@ -45,11 +45,11 @@ GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapipostproc);
|
|||
/* Default templates */
|
||||
static const char gst_vaapipostproc_sink_caps_str[] =
|
||||
GST_VAAPI_SURFACE_CAPS ", "
|
||||
"interlaced = (boolean) { true, false }";
|
||||
GST_CAPS_INTERLACED_MODES;
|
||||
|
||||
static const char gst_vaapipostproc_src_caps_str[] =
|
||||
GST_VAAPI_SURFACE_CAPS ", "
|
||||
"interlaced = (boolean) false";
|
||||
GST_CAPS_INTERLACED_FALSE;
|
||||
|
||||
static GstStaticPadTemplate gst_vaapipostproc_sink_factory =
|
||||
GST_STATIC_PAD_TEMPLATE(
|
||||
|
@ -66,6 +66,7 @@ static GstStaticPadTemplate gst_vaapipostproc_src_factory =
|
|||
GST_STATIC_CAPS(gst_vaapipostproc_src_caps_str));
|
||||
|
||||
/* GstImplementsInterface interface */
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
static gboolean
|
||||
gst_vaapipostproc_implements_interface_supported(
|
||||
GstImplementsInterface *iface,
|
||||
|
@ -80,6 +81,7 @@ gst_vaapipostproc_implements_iface_init(GstImplementsInterfaceClass *iface)
|
|||
{
|
||||
iface->supported = gst_vaapipostproc_implements_interface_supported;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* GstVideoContext interface */
|
||||
static void
|
||||
|
@ -105,8 +107,10 @@ G_DEFINE_TYPE_WITH_CODE(
|
|||
GstVaapiPostproc,
|
||||
gst_vaapipostproc,
|
||||
GST_TYPE_ELEMENT,
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
|
||||
gst_vaapipostproc_implements_iface_init);
|
||||
#endif
|
||||
G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
|
||||
gst_video_context_interface_init))
|
||||
|
||||
|
@ -263,7 +267,7 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf)
|
|||
|
||||
timestamp = GST_BUFFER_TIMESTAMP(buf);
|
||||
proxy = gst_vaapi_video_meta_get_surface_proxy(meta);
|
||||
tff = GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_TFF);
|
||||
tff = GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_FLAG_TFF);
|
||||
|
||||
flags &= ~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
|
||||
GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
|
||||
|
@ -284,7 +288,9 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf)
|
|||
|
||||
GST_BUFFER_TIMESTAMP(outbuf) = timestamp;
|
||||
GST_BUFFER_DURATION(outbuf) = postproc->field_duration;
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
gst_buffer_set_caps(outbuf, postproc->srcpad_caps);
|
||||
#endif
|
||||
ret = gst_pad_push(postproc->srcpad, outbuf);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto error_push_buffer;
|
||||
|
@ -305,7 +311,9 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf)
|
|||
|
||||
GST_BUFFER_TIMESTAMP(outbuf) = timestamp + postproc->field_duration;
|
||||
GST_BUFFER_DURATION(outbuf) = postproc->field_duration;
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
gst_buffer_set_caps(outbuf, postproc->srcpad_caps);
|
||||
#endif
|
||||
ret = gst_pad_push(postproc->srcpad, outbuf);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto error_push_buffer;
|
||||
|
@ -318,39 +326,36 @@ error_invalid_buffer:
|
|||
{
|
||||
GST_ERROR("failed to receive a valid video buffer");
|
||||
gst_buffer_unref(buf);
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
return GST_FLOW_EOS;
|
||||
}
|
||||
error_create_buffer:
|
||||
{
|
||||
GST_ERROR("failed to create output buffer");
|
||||
gst_buffer_unref(buf);
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
return GST_FLOW_EOS;
|
||||
}
|
||||
error_push_buffer:
|
||||
{
|
||||
if (ret != GST_FLOW_WRONG_STATE)
|
||||
if (ret != GST_FLOW_FLUSHING)
|
||||
GST_ERROR("failed to push output buffer to video sink");
|
||||
gst_buffer_unref(buf);
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
return GST_FLOW_EOS;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapipostproc_update_sink_caps(GstVaapiPostproc *postproc, GstCaps *caps)
|
||||
{
|
||||
gint fps_n, fps_d;
|
||||
gboolean interlaced;
|
||||
GstVideoInfo vi;
|
||||
|
||||
if (!gst_video_parse_caps_framerate(caps, &fps_n, &fps_d))
|
||||
if (!gst_video_info_from_caps(&vi, caps))
|
||||
return FALSE;
|
||||
postproc->fps_n = fps_n;
|
||||
postproc->fps_d = fps_d;
|
||||
postproc->fps_n = GST_VIDEO_INFO_FPS_N(&vi);
|
||||
postproc->fps_d = GST_VIDEO_INFO_FPS_D(&vi);
|
||||
|
||||
switch (postproc->deinterlace_mode) {
|
||||
case GST_VAAPI_DEINTERLACE_MODE_AUTO:
|
||||
if (!gst_video_format_parse_caps_interlaced(caps, &interlaced))
|
||||
return FALSE;
|
||||
postproc->deinterlace = interlaced;
|
||||
postproc->deinterlace = GST_VIDEO_INFO_IS_INTERLACED(&vi);
|
||||
break;
|
||||
case GST_VAAPI_DEINTERLACE_MODE_INTERLACED:
|
||||
postproc->deinterlace = TRUE;
|
||||
|
@ -403,7 +408,7 @@ gst_vaapipostproc_update_src_caps(GstVaapiPostproc *postproc, GstCaps *caps)
|
|||
gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
|
||||
|
||||
if (!postproc->deinterlace)
|
||||
gst_structure_remove_field(structure, "interlaced");
|
||||
gst_structure_remove_interlaced_field(structure);
|
||||
else {
|
||||
/* Set double framerate in interlaced mode */
|
||||
if (!gst_util_fraction_multiply(postproc->fps_n, postproc->fps_d,
|
||||
|
@ -411,12 +416,9 @@ gst_vaapipostproc_update_src_caps(GstVaapiPostproc *postproc, GstCaps *caps)
|
|||
&fps_n, &fps_d))
|
||||
return FALSE;
|
||||
|
||||
gst_structure_set(
|
||||
structure,
|
||||
"interlaced", G_TYPE_BOOLEAN, FALSE,
|
||||
"framerate", GST_TYPE_FRACTION, fps_n, fps_d,
|
||||
NULL
|
||||
);
|
||||
gst_structure_set(structure, "framerate",
|
||||
GST_TYPE_FRACTION, fps_n, fps_d, NULL);
|
||||
gst_structure_set_interlaced(structure, FALSE);
|
||||
}
|
||||
return gst_pad_set_caps(postproc->srcpad, src_caps);
|
||||
}
|
||||
|
@ -473,32 +475,44 @@ gst_vaapipostproc_set_caps(GstPad *pad, GstCaps *caps)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_vaapipostproc_chain(GstPad *pad, GstBuffer *buf)
|
||||
gst_vaapipostproc_chain(GST_PAD_CHAIN_FUNCTION_ARGS)
|
||||
{
|
||||
GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = gst_vaapipostproc_process(postproc, buf);
|
||||
ret = gst_vaapipostproc_process(postproc, buffer);
|
||||
gst_object_unref(postproc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapipostproc_sink_event(GstPad *pad, GstEvent *event)
|
||||
gst_vaapipostproc_sink_event(GST_PAD_EVENT_FUNCTION_ARGS)
|
||||
{
|
||||
GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
|
||||
gboolean success;
|
||||
|
||||
GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
|
||||
|
||||
/* Propagate event downstream */
|
||||
success = gst_pad_push_event(postproc->srcpad, event);
|
||||
switch (GST_EVENT_TYPE(event)) {
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
case GST_EVENT_CAPS: {
|
||||
GstCaps *caps;
|
||||
gst_event_parse_caps(event, &caps);
|
||||
success = gst_vaapipostproc_set_caps(pad, caps);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* Propagate event downstream */
|
||||
success = gst_pad_push_event(postproc->srcpad, event);
|
||||
break;
|
||||
}
|
||||
gst_object_unref(postproc);
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapipostproc_src_event(GstPad *pad, GstEvent *event)
|
||||
gst_vaapipostproc_src_event(GST_PAD_EVENT_FUNCTION_ARGS)
|
||||
{
|
||||
GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
|
||||
gboolean success;
|
||||
|
@ -512,7 +526,7 @@ gst_vaapipostproc_src_event(GstPad *pad, GstEvent *event)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapipostproc_query(GstPad *pad, GstQuery *query)
|
||||
gst_vaapipostproc_query(GST_PAD_QUERY_FUNCTION_ARGS)
|
||||
{
|
||||
GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
|
||||
gboolean success;
|
||||
|
@ -521,8 +535,17 @@ gst_vaapipostproc_query(GstPad *pad, GstQuery *query)
|
|||
|
||||
if (gst_vaapi_reply_to_query(query, postproc->display))
|
||||
success = TRUE;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
else if (GST_PAD_IS_SINK(pad) && GST_QUERY_TYPE(query) == GST_QUERY_CAPS) {
|
||||
GstCaps * const caps = gst_vaapipostproc_get_caps(pad);
|
||||
gst_query_set_caps_result(query, caps);
|
||||
gst_caps_unref(caps);
|
||||
success = TRUE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
success = gst_pad_query_default(pad, query);
|
||||
success = GST_PAD_QUERY_FUNCTION_CALL(gst_pad_query_default, pad,
|
||||
parent, query);
|
||||
|
||||
gst_object_unref(postproc);
|
||||
return success;
|
||||
|
@ -714,8 +737,10 @@ gst_vaapipostproc_init(GstVaapiPostproc *postproc)
|
|||
);
|
||||
postproc->sinkpad_caps = NULL;
|
||||
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
gst_pad_set_getcaps_function(postproc->sinkpad, gst_vaapipostproc_get_caps);
|
||||
gst_pad_set_setcaps_function(postproc->sinkpad, gst_vaapipostproc_set_caps);
|
||||
#endif
|
||||
gst_pad_set_chain_function(postproc->sinkpad, gst_vaapipostproc_chain);
|
||||
gst_pad_set_event_function(postproc->sinkpad, gst_vaapipostproc_sink_event);
|
||||
gst_pad_set_query_function(postproc->sinkpad, gst_vaapipostproc_query);
|
||||
|
|
Loading…
Reference in a new issue