mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
vaapipostproc: add support for advanced deinterlacing.
Add initial support for advanced deinterlacing. The history buffer size is arbitrarily set to 3 references for now.
This commit is contained in:
parent
49e2d040fa
commit
c8bea66d33
2 changed files with 101 additions and 0 deletions
|
@ -371,6 +371,51 @@ append_output_buffer_metadata(GstBuffer *outbuf, GstBuffer *inbuf, guint flags)
|
||||||
0, -1);
|
0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ds_reset(GstVaapiDeinterlaceState *ds)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS(ds->buffers); i++)
|
||||||
|
gst_buffer_replace(&ds->buffers[i], NULL);
|
||||||
|
ds->buffers_index = 0;
|
||||||
|
ds->num_surfaces = 0;
|
||||||
|
ds->deint = FALSE;
|
||||||
|
ds->tff = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ds_add_buffer(GstVaapiDeinterlaceState *ds, GstBuffer *buf)
|
||||||
|
{
|
||||||
|
gst_buffer_replace(&ds->buffers[ds->buffers_index], buf);
|
||||||
|
ds->buffers_index = (ds->buffers_index + 1) % G_N_ELEMENTS(ds->buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GstBuffer *
|
||||||
|
ds_get_buffer(GstVaapiDeinterlaceState *ds, guint index)
|
||||||
|
{
|
||||||
|
const guint n = ds->buffers_index + G_N_ELEMENTS(ds->buffers) - index - 1;
|
||||||
|
return ds->buffers[n % G_N_ELEMENTS(ds->buffers)];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ds_set_surfaces(GstVaapiDeinterlaceState *ds)
|
||||||
|
{
|
||||||
|
GstVaapiVideoMeta *meta;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
ds->num_surfaces = 0;
|
||||||
|
for (i = 0; i < G_N_ELEMENTS(ds->buffers); i++) {
|
||||||
|
GstBuffer * const buf = ds_get_buffer(ds, i);
|
||||||
|
if (!buf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
meta = gst_buffer_get_vaapi_video_meta(buf);
|
||||||
|
ds->surfaces[ds->num_surfaces++] =
|
||||||
|
gst_vaapi_video_meta_get_surface(meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstVaapiDeinterlaceMethod
|
static GstVaapiDeinterlaceMethod
|
||||||
get_next_deint_method(GstVaapiDeinterlaceMethod deint_method)
|
get_next_deint_method(GstVaapiDeinterlaceMethod deint_method)
|
||||||
{
|
{
|
||||||
|
@ -409,6 +454,7 @@ gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
GstBuffer *outbuf)
|
GstBuffer *outbuf)
|
||||||
{
|
{
|
||||||
GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
|
GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
|
||||||
|
GstVaapiDeinterlaceState * const ds = &postproc->deinterlace_state;
|
||||||
GstVaapiVideoMeta *inbuf_meta, *outbuf_meta;
|
GstVaapiVideoMeta *inbuf_meta, *outbuf_meta;
|
||||||
GstVaapiSurface *inbuf_surface, *outbuf_surface;
|
GstVaapiSurface *inbuf_surface, *outbuf_surface;
|
||||||
GstVaapiFilterStatus status;
|
GstVaapiFilterStatus status;
|
||||||
|
@ -433,6 +479,12 @@ gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
tff = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF);
|
tff = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF);
|
||||||
deint = is_interlaced_buffer(postproc, inbuf);
|
deint = is_interlaced_buffer(postproc, inbuf);
|
||||||
|
|
||||||
|
/* Drop references if deinterlacing conditions changed */
|
||||||
|
if (deint != ds->deint || (ds->num_surfaces > 0 && tff != ds->tff))
|
||||||
|
ds_reset(ds);
|
||||||
|
ds->deint = deint;
|
||||||
|
ds->tff = tff;
|
||||||
|
|
||||||
flags = gst_vaapi_video_meta_get_render_flags(inbuf_meta) &
|
flags = gst_vaapi_video_meta_get_render_flags(inbuf_meta) &
|
||||||
~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
|
~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
|
||||||
GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
|
GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
|
||||||
|
@ -451,8 +503,16 @@ gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
|
|
||||||
if (deint) {
|
if (deint) {
|
||||||
deint_flags = (tff ? GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD : 0);
|
deint_flags = (tff ? GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD : 0);
|
||||||
|
if (tff)
|
||||||
|
deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF;
|
||||||
if (!set_best_deint_method(postproc, deint_flags, &deint_method))
|
if (!set_best_deint_method(postproc, deint_flags, &deint_method))
|
||||||
goto error_op_deinterlace;
|
goto error_op_deinterlace;
|
||||||
|
|
||||||
|
ds_set_surfaces(ds);
|
||||||
|
if (!gst_vaapi_filter_set_deinterlacing_references(postproc->filter,
|
||||||
|
ds->surfaces, ds->num_surfaces, NULL, 0))
|
||||||
|
goto error_op_deinterlace;
|
||||||
|
|
||||||
if (deint_method != postproc->deinterlace_method) {
|
if (deint_method != postproc->deinterlace_method) {
|
||||||
GST_DEBUG("unsupported deinterlace-method %u. Using %u instead",
|
GST_DEBUG("unsupported deinterlace-method %u. Using %u instead",
|
||||||
postproc->deinterlace_method, deint_method);
|
postproc->deinterlace_method, deint_method);
|
||||||
|
@ -484,9 +544,15 @@ gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
|
|
||||||
if (deint) {
|
if (deint) {
|
||||||
deint_flags = (tff ? 0 : GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD);
|
deint_flags = (tff ? 0 : GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD);
|
||||||
|
if (tff)
|
||||||
|
deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF;
|
||||||
if (!gst_vaapi_filter_set_deinterlacing(postproc->filter,
|
if (!gst_vaapi_filter_set_deinterlacing(postproc->filter,
|
||||||
deint_method, deint_flags))
|
deint_method, deint_flags))
|
||||||
goto error_op_deinterlace;
|
goto error_op_deinterlace;
|
||||||
|
|
||||||
|
if (!gst_vaapi_filter_set_deinterlacing_references(postproc->filter,
|
||||||
|
ds->surfaces, ds->num_surfaces, NULL, 0))
|
||||||
|
goto error_op_deinterlace;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gst_vaapi_filter_process(postproc->filter, inbuf_surface,
|
status = gst_vaapi_filter_process(postproc->filter, inbuf_surface,
|
||||||
|
@ -502,6 +568,7 @@ gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf,
|
||||||
}
|
}
|
||||||
gst_buffer_set_vaapi_video_meta(outbuf, outbuf_meta);
|
gst_buffer_set_vaapi_video_meta(outbuf, outbuf_meta);
|
||||||
gst_vaapi_video_meta_unref(outbuf_meta);
|
gst_vaapi_video_meta_unref(outbuf_meta);
|
||||||
|
ds_add_buffer(ds, inbuf);
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
|
|
@ -57,6 +57,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _GstVaapiPostproc GstVaapiPostproc;
|
typedef struct _GstVaapiPostproc GstVaapiPostproc;
|
||||||
typedef struct _GstVaapiPostprocClass GstVaapiPostprocClass;
|
typedef struct _GstVaapiPostprocClass GstVaapiPostprocClass;
|
||||||
|
typedef struct _GstVaapiDeinterlaceState GstVaapiDeinterlaceState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstVaapiDeinterlaceMode:
|
* GstVaapiDeinterlaceMode:
|
||||||
|
@ -70,6 +71,18 @@ typedef enum {
|
||||||
GST_VAAPI_DEINTERLACE_MODE_DISABLED,
|
GST_VAAPI_DEINTERLACE_MODE_DISABLED,
|
||||||
} GstVaapiDeinterlaceMode;
|
} GstVaapiDeinterlaceMode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GST_VAAPI_DEINTERLACE_MAX_REFERENCES:
|
||||||
|
*
|
||||||
|
* This represents the maximum number of VA surfaces we could keep as
|
||||||
|
* references for advanced deinterlacing.
|
||||||
|
*
|
||||||
|
* Note: if the upstream element is vaapidecode, then the maximum
|
||||||
|
* number of allowed surfaces used as references shall be less than
|
||||||
|
* the actual number of scratch surfaces used for decoding (4).
|
||||||
|
*/
|
||||||
|
#define GST_VAAPI_DEINTERLACE_MAX_REFERENCES 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstVaapiPostprocFlags:
|
* GstVaapiPostprocFlags:
|
||||||
* @GST_VAAPI_POSTPROC_FLAG_FORMAT: Pixel format conversion.
|
* @GST_VAAPI_POSTPROC_FLAG_FORMAT: Pixel format conversion.
|
||||||
|
@ -99,6 +112,26 @@ typedef enum {
|
||||||
GST_VAAPI_POSTPROC_FLAG_SIZE = GST_VAAPI_POSTPROC_FLAG_CUSTOM,
|
GST_VAAPI_POSTPROC_FLAG_SIZE = GST_VAAPI_POSTPROC_FLAG_CUSTOM,
|
||||||
} GstVaapiPostprocFlags;
|
} GstVaapiPostprocFlags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GstVaapiDeinterlaceState:
|
||||||
|
* @buffers: history buffer, maintained as a cyclic array
|
||||||
|
* @buffers_index: next free slot in the history buffer
|
||||||
|
* @surfaces: array of surfaces used as references
|
||||||
|
* @num_surfaces: number of active surfaces in that array
|
||||||
|
* @deint: flag: previous buffers were interlaced?
|
||||||
|
* @tff: flag: previous buffers were organized as top-field-first?
|
||||||
|
*
|
||||||
|
* Context used to maintain deinterlacing state.
|
||||||
|
*/
|
||||||
|
struct _GstVaapiDeinterlaceState {
|
||||||
|
GstBuffer *buffers[GST_VAAPI_DEINTERLACE_MAX_REFERENCES];
|
||||||
|
guint buffers_index;
|
||||||
|
GstVaapiSurface *surfaces[GST_VAAPI_DEINTERLACE_MAX_REFERENCES];
|
||||||
|
guint num_surfaces;
|
||||||
|
guint deint : 1;
|
||||||
|
guint tff : 1;
|
||||||
|
};
|
||||||
|
|
||||||
struct _GstVaapiPostproc {
|
struct _GstVaapiPostproc {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstBaseTransform parent_instance;
|
GstBaseTransform parent_instance;
|
||||||
|
@ -129,6 +162,7 @@ struct _GstVaapiPostproc {
|
||||||
/* Deinterlacing */
|
/* Deinterlacing */
|
||||||
GstVaapiDeinterlaceMode deinterlace_mode;
|
GstVaapiDeinterlaceMode deinterlace_mode;
|
||||||
GstVaapiDeinterlaceMethod deinterlace_method;
|
GstVaapiDeinterlaceMethod deinterlace_method;
|
||||||
|
GstVaapiDeinterlaceState deinterlace_state;
|
||||||
GstClockTime field_duration;
|
GstClockTime field_duration;
|
||||||
|
|
||||||
guint is_raw_yuv : 1;
|
guint is_raw_yuv : 1;
|
||||||
|
|
Loading…
Reference in a new issue