decoder: allow pictures to be cloned for field decoding.

Add gst_vaapi_picture_new_field() function that clones a picture, while
preserving the parent picture surface. i.e. the surface proxy reference
count is increased and other fields copied as is. Besides, the picture
is reset into a "non-output" mode.
This commit is contained in:
Gwenole Beauchesne 2012-03-28 16:05:58 +02:00
parent c27385aa8d
commit 195a61fa02
4 changed files with 85 additions and 9 deletions

View file

@ -94,6 +94,7 @@ gst_vaapi_codec_object_new(
args.param_size = param_size; args.param_size = param_size;
args.data = data; args.data = data;
args.data_size = data_size; args.data_size = data_size;
args.flags = 0;
if (gst_vaapi_codec_object_construct(va_obj, &args)) if (gst_vaapi_codec_object_construct(va_obj, &args))
return va_obj; return va_obj;

View file

@ -80,6 +80,7 @@ typedef struct {
guint param_size; guint param_size;
gconstpointer data; gconstpointer data;
guint data_size; guint data_size;
guint flags;
} GstVaapiCodecObjectConstructorArgs; } GstVaapiCodecObjectConstructorArgs;
/** /**

View file

@ -44,6 +44,11 @@ GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPicture,
gst_vaapi_picture, gst_vaapi_picture,
GST_VAAPI_TYPE_CODEC_OBJECT) GST_VAAPI_TYPE_CODEC_OBJECT)
enum {
GST_VAAPI_CREATE_PICTURE_FLAG_CLONE = 1 << 0,
GST_VAAPI_CREATE_PICTURE_FLAG_FIELD = 1 << 1,
};
static void static void
destroy_slice_cb(gpointer data, gpointer user_data) destroy_slice_cb(gpointer data, gpointer user_data)
{ {
@ -94,17 +99,51 @@ gst_vaapi_picture_create(
{ {
gboolean success; gboolean success;
if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
picture->proxy = g_object_ref(parent_picture->proxy);
picture->surface = gst_vaapi_surface_proxy_get_surface(picture->proxy);
picture->type = parent_picture->type;
picture->pts = parent_picture->pts;
// Copy all picture flags but "output"
GST_VAAPI_PICTURE_FLAG_SET(
picture,
GST_VAAPI_PICTURE_FLAGS(parent_picture) &
(GST_VAAPI_PICTURE_FLAG_SKIPPED |
GST_VAAPI_PICTURE_FLAG_REFERENCE |
GST_VAAPI_PICTURE_FLAG_INTERLACED |
GST_VAAPI_PICTURE_FLAG_TFF)
);
picture->structure = parent_picture->structure;
if ((args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD) &&
GST_VAAPI_PICTURE_IS_INTERLACED(picture)) {
switch (picture->structure) {
case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
break;
case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
break;
}
}
}
else {
picture->surface = gst_vaapi_context_get_surface(GET_CONTEXT(picture)); picture->surface = gst_vaapi_context_get_surface(GET_CONTEXT(picture));
if (!picture->surface) if (!picture->surface)
return FALSE; return FALSE;
picture->surface_id = gst_vaapi_surface_get_id(picture->surface);
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
picture->proxy = picture->proxy =
gst_vaapi_surface_proxy_new(GET_CONTEXT(picture), picture->surface); gst_vaapi_surface_proxy_new(GET_CONTEXT(picture), picture->surface);
if (!picture->proxy) if (!picture->proxy)
return FALSE; return FALSE;
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
}
picture->surface_id = gst_vaapi_surface_get_id(picture->surface);
success = vaapi_create_buffer( success = vaapi_create_buffer(
GET_VA_DISPLAY(picture), GET_VA_DISPLAY(picture),
GET_VA_CONTEXT(picture), GET_VA_CONTEXT(picture),
@ -116,6 +155,7 @@ gst_vaapi_picture_create(
); );
if (!success) if (!success)
return FALSE; return FALSE;
picture->param_size = args->param_size;
picture->slices = g_ptr_array_new(); picture->slices = g_ptr_array_new();
if (!picture->slices) if (!picture->slices)
@ -132,6 +172,7 @@ gst_vaapi_picture_init(GstVaapiPicture *picture)
picture->surface_id = VA_INVALID_ID; picture->surface_id = VA_INVALID_ID;
picture->param = NULL; picture->param = NULL;
picture->param_id = VA_INVALID_ID; picture->param_id = VA_INVALID_ID;
picture->param_size = 0;
picture->slices = NULL; picture->slices = NULL;
picture->iq_matrix = NULL; picture->iq_matrix = NULL;
picture->bitplane = NULL; picture->bitplane = NULL;
@ -160,6 +201,34 @@ gst_vaapi_picture_new(
return GST_VAAPI_PICTURE_CAST(object); return GST_VAAPI_PICTURE_CAST(object);
} }
GstVaapiPicture *
gst_vaapi_picture_new_field(GstVaapiPicture *picture)
{
GstMiniObject *obj;
GstVaapiCodecObject *va_obj;
GstVaapiCodecObjectConstructorArgs args;
g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), NULL);
obj = gst_mini_object_new(GST_VAAPI_TYPE_PICTURE);
if (!obj)
return NULL;
va_obj = GST_VAAPI_CODEC_OBJECT(obj);
args.codec = GST_VAAPI_CODEC_BASE(GET_DECODER(picture));
args.param = NULL;
args.param_size = picture->param_size;
args.data = picture;
args.data_size = 0;
args.flags = (GST_VAAPI_CREATE_PICTURE_FLAG_CLONE|
GST_VAAPI_CREATE_PICTURE_FLAG_FIELD);
if (gst_vaapi_codec_object_construct(va_obj, &args))
return GST_VAAPI_PICTURE_CAST(va_obj);
gst_mini_object_unref(obj);
return NULL;
}
void void
gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice) gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice)
{ {

View file

@ -126,6 +126,7 @@ struct _GstVaapiPicture {
GstVaapiSurface *surface; GstVaapiSurface *surface;
GstVaapiSurfaceProxy *proxy; GstVaapiSurfaceProxy *proxy;
VABufferID param_id; VABufferID param_id;
guint param_size;
/*< public >*/ /*< public >*/
GstVaapiPictureType type; GstVaapiPictureType type;
@ -159,6 +160,10 @@ gst_vaapi_picture_new(
guint param_size guint param_size
) attribute_hidden; ) attribute_hidden;
GstVaapiPicture *
gst_vaapi_picture_new_field(GstVaapiPicture *picture)
attribute_hidden;
void void
gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice) gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice)
attribute_hidden; attribute_hidden;