From: Gwenole Beauchesne Date: Tue, 3 Dec 2013 15:11:46 +0000 (+0100) Subject: encoder: rework GstVaapiCodedBuffer and related proxy. X-Git-Tag: 0.5.8~140 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0fb7c605080e926a4ff3a7b01337281d968148b5;p=platform%2Fupstream%2Fgstreamer-vaapi.git encoder: rework GstVaapiCodedBuffer and related proxy. Refactor the GstVaapiCodedBuffer APIs so that to more clearly separate public and private interfaces. Besides, the map/unmap APIs should not be exposed as is but appropriate accessors should be provided instead. * GstVaapiCodedBuffer: VA coded buffer abstraction - gst_vaapi_coded_buffer_get_size(): get coded buffer size. - gst_vaapi_coded_buffer_copy_into(): copy coded buffer into GstBuffer * GstVaapiCodedBufferPool: pool of VA coded buffer objects - gst_vaapi_coded_buffer_pool_new(): create a pool of coded buffers of the specified max size, and bound to the supplied encoder * GstVaapiCodedBufferProxy: pool-allocated VA coded buffer object proxy - gst_vaapi_coded_buffer_proxy_new_from_pool(): create coded buf from pool - gst_vaapi_coded_buffer_proxy_get_buffer(): get underlying coded buffer - gst_vaapi_coded_buffer_proxy_get_buffer_size(): get coded buffer size Rationale: more optimized transfer functions might be provided in the future, thus rendering the map/unmap mechanism obsolete or sub-optimal. https://bugzilla.gnome.org/show_bug.cgi?id=719775 --- diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 0b5eb66..e402da0 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -135,6 +135,9 @@ libgstvaapi_source_h += $(libgstvaapi_jpegdec_source_h) endif libgstvaapi_enc_source_c = \ + gstvaapicodedbuffer.c \ + gstvaapicodedbufferpool.c \ + gstvaapicodedbufferproxy.c \ gstvaapiencoder.c \ gstvaapiencoder_h264.c \ gstvaapiencoder_mpeg2.c \ @@ -142,12 +145,17 @@ libgstvaapi_enc_source_c = \ $(NULL) libgstvaapi_enc_source_h = \ + gstvaapicodedbuffer.h \ + gstvaapicodedbufferpool.h \ + gstvaapicodedbufferproxy.h \ gstvaapiencoder.h \ gstvaapiencoder_h264.h \ gstvaapiencoder_mpeg2.h \ $(NULL) libgstvaapi_enc_source_priv_h = \ + gstvaapicodedbuffer_priv.h \ + gstvaapicodedbufferpool_priv.h \ gstvaapiencoder_objects.h \ gstvaapiencoder_priv.h \ $(NULL) diff --git a/gst-libs/gst/vaapi/gstvaapicodedbuffer.c b/gst-libs/gst/vaapi/gstvaapicodedbuffer.c new file mode 100644 index 0000000..acdc106 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbuffer.c @@ -0,0 +1,232 @@ +/* + * gstvaapicodedbuffer.c - VA coded buffer abstraction + * + * Copyright (C) 2013 Intel Corporation + * Author: Wind Yuan + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "sysdeps.h" +#include "gstvaapicodedbuffer.h" +#include "gstvaapicodedbuffer_priv.h" +#include "gstvaapiencoder_priv.h" +#include "gstvaapiutils.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +static gboolean +coded_buffer_create (GstVaapiCodedBuffer * buf, guint buf_size, + GstVaapiContext * context) +{ + GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf); + VABufferID buf_id; + gboolean success; + + GST_VAAPI_DISPLAY_LOCK (display); + success = vaapi_create_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), + GST_VAAPI_OBJECT_ID (context), VAEncCodedBufferType, buf_size, NULL, + &buf_id, NULL); + GST_VAAPI_DISPLAY_UNLOCK (display); + if (!success) + return FALSE; + + GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id)); + GST_VAAPI_OBJECT_ID (buf) = buf_id; + return TRUE; +} + +static void +coded_buffer_destroy (GstVaapiCodedBuffer * buf) +{ + GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf); + VABufferID buf_id; + + buf_id = GST_VAAPI_OBJECT_ID (buf); + GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id)); + + if (buf_id != VA_INVALID_ID) { + GST_VAAPI_DISPLAY_LOCK (display); + vaapi_destroy_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), &buf_id); + GST_VAAPI_DISPLAY_UNLOCK (display); + GST_VAAPI_OBJECT_ID (buf) = VA_INVALID_ID; + } +} + +static gboolean +coded_buffer_map (GstVaapiCodedBuffer * buf) +{ + if (buf->segment_list) + return TRUE; + + GST_VAAPI_OBJECT_LOCK_DISPLAY (buf); + buf->segment_list = vaapi_map_buffer (GST_VAAPI_OBJECT_VADISPLAY (buf), + GST_VAAPI_OBJECT_ID (buf)); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY (buf); + return buf->segment_list != NULL; +} + +static void +coded_buffer_unmap (GstVaapiCodedBuffer * buf) +{ + if (!buf->segment_list) + return; + + GST_VAAPI_OBJECT_LOCK_DISPLAY (buf); + vaapi_unmap_buffer (GST_VAAPI_OBJECT_VADISPLAY (buf), + GST_VAAPI_OBJECT_ID (buf), (void **) &buf->segment_list); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY (buf); +} + +#define gst_vaapi_coded_buffer_finalize coded_buffer_destroy +GST_VAAPI_OBJECT_DEFINE_CLASS (GstVaapiCodedBuffer, gst_vaapi_coded_buffer) + +/* + * gst_vaapi_coded_buffer_new: + * @context: the parent #GstVaapiContext object + * @buf_size: the buffer size in bytes + * + * Creates a new VA coded buffer bound to the supplied @context. + * + * Return value: the newly allocated #GstVaapiCodedBuffer object, or + * %NULL if an error occurred + */ +GstVaapiCodedBuffer * +gst_vaapi_coded_buffer_new (GstVaapiContext * context, guint buf_size) +{ + GstVaapiCodedBuffer *buf; + GstVaapiDisplay *display; + + g_return_val_if_fail (context != NULL, NULL); + g_return_val_if_fail (buf_size > 0, NULL); + + display = GST_VAAPI_OBJECT_DISPLAY (context); + g_return_val_if_fail (display != NULL, NULL); + + buf = gst_vaapi_object_new (gst_vaapi_coded_buffer_class (), display); + if (!buf) + return NULL; + + if (!coded_buffer_create (buf, buf_size, context)) + goto error; + return buf; + +error: + gst_vaapi_object_unref (buf); + return NULL; +} + +/* + * gst_vaapi_coded_buffer_map: + * @buf: a #GstVaapiCodedBuffer + * @data: pointer to the mapped buffer data (VACodedBufferSegment) + * + * Maps the VA coded buffer and returns the data pointer into @data. + * + * Return value: %TRUE if successful, %FALSE otherwise + */ +gboolean +gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf, + VACodedBufferSegment ** out_segment_list_ptr) +{ + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (out_segment_list_ptr != NULL, FALSE); + + if (!coded_buffer_map (buf)) + return FALSE; + + *out_segment_list_ptr = buf->segment_list; + return TRUE; +} + +/* + * gst_vaapi_coded_buffer_unmap: + * @buf: a #GstVaapiCodedBuffer + * + * Unamps the VA coded buffer. + */ +void +gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf) +{ + g_return_if_fail (buf != NULL); + + coded_buffer_unmap (buf); +} + +/** + * gst_vaapi_coded_buffer_get_size: + * @buf: a #GstVaapiCodedBuffer + * + * Returns the VA coded buffer size in bytes. That represents the + * exact buffer size, as filled in so far, not the size of the + * allocated buffer. + * + * Return value: the size of the VA coded buffer, or -1 on error + */ +gssize +gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf) +{ + VACodedBufferSegment *segment; + gssize size; + + g_return_val_if_fail (buf != NULL, -1); + + if (!coded_buffer_map (buf)) + return -1; + + size = 0; + for (segment = buf->segment_list; segment != NULL; segment = segment->next) + size += segment->size; + + coded_buffer_unmap (buf); + return size; +} + +/** + * gst_vaapi_coded_buffer_copy_into: + * @dest: the destination #GstBuffer + * @src: the source #GstVaapiCodedBuffer + * + * Copies the coded buffer data from @src into the regular buffer @dest. + * + * Return value: %TRUE if successful, %FALSE otherwise + */ +gboolean +gst_vaapi_coded_buffer_copy_into (GstBuffer * dest, GstVaapiCodedBuffer * src) +{ + VACodedBufferSegment *segment; + goffset offset; + gsize size; + + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + if (!coded_buffer_map (src)) + return FALSE; + + offset = 0; + for (segment = src->segment_list; segment != NULL; segment = segment->next) { + size = gst_buffer_fill (dest, offset, segment->buf, segment->size); + if (size != segment->size) + break; + offset += segment->size; + } + + coded_buffer_unmap (src); + return segment == NULL; +} diff --git a/gst-libs/gst/vaapi/gstvaapicodedbuffer.h b/gst-libs/gst/vaapi/gstvaapicodedbuffer.h new file mode 100644 index 0000000..4980e9c --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbuffer.h @@ -0,0 +1,53 @@ +/* + * gstvaapicodedbuffer.h - VA coded buffer abstraction + * + * Copyright (C) 2013 Intel Corporation + * Author: Wind Yuan + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_CODED_BUFFER_H +#define GST_VAAPI_CODED_BUFFER_H + +G_BEGIN_DECLS + +#define GST_VAAPI_CODED_BUFFER(obj) \ + ((GstVaapiCodedBuffer *)(obj)) + +/** + * GST_VAAPI_CODED_BUFFER_SIZE: + * @buf: a #GstVaapiCodedBuffer + * + * Macro that evaluates to the size of the underlying VA coded buffer @buf + */ +#define GST_VAAPI_CODED_BUFFER_SIZE(buf) \ + gst_vaapi_coded_buffer_get_size (GST_VAAPI_CODED_BUFFER(buf)) + +typedef struct _GstVaapiCodedBuffer GstVaapiCodedBuffer; +typedef struct _GstVaapiCodedBufferProxy GstVaapiCodedBufferProxy; +typedef struct _GstVaapiCodedBufferPool GstVaapiCodedBufferPool; + +gssize +gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf); + +gboolean +gst_vaapi_coded_buffer_copy_into (GstBuffer * dest, GstVaapiCodedBuffer * src); + +G_END_DECLS + +#endif /* GST_VAAPI_CODED_BUFFER_H */ diff --git a/gst-libs/gst/vaapi/gstvaapicodedbuffer_priv.h b/gst-libs/gst/vaapi/gstvaapicodedbuffer_priv.h new file mode 100644 index 0000000..8d0de4d --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbuffer_priv.h @@ -0,0 +1,78 @@ +/* + * gstvaapicodedbuffer_priv.h - VA coded buffer abstraction (private defs) + * + * Copyright (C) 2013 Intel Corporation + * Author: Wind Yuan + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_CODED_BUFFER_PRIV_H +#define GST_VAAPI_CODED_BUFFER_PRIV_H + +#include +#include "gstvaapicodedbuffer.h" +#include "gstvaapiobject_priv.h" + +G_BEGIN_DECLS + +#define GST_VAAPI_CODED_BUFFER_CAST(obj) \ + ((GstVaapiCodedBuffer *)(obj)) + +typedef struct _GstVaapiCodedBufferClass GstVaapiCodedBufferClass; + +/** + * GstVaapiCodedBuffer: + * + * A VA coded buffer object wrapper. + */ +struct _GstVaapiCodedBuffer +{ + /*< private >*/ + GstVaapiObject parent_instance; + + GstVaapiContext *context; + VACodedBufferSegment *segment_list; +}; + +/** + * GstVaapiCodedBufferClass: + * + * A VA coded buffer object wrapper class. + */ +struct _GstVaapiCodedBufferClass +{ + /*< private >*/ + GstVaapiObjectClass parent_class; +}; + +G_GNUC_INTERNAL +GstVaapiCodedBuffer * +gst_vaapi_coded_buffer_new (GstVaapiContext * context, guint buf_size); + +G_GNUC_INTERNAL +gboolean +gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf, + VACodedBufferSegment ** out_segment_list_ptr); + +G_GNUC_INTERNAL +void +gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf); + +G_END_DECLS + +#endif /* GST_VAAPI_CODED_BUFFER_PRIV_H */ diff --git a/gst-libs/gst/vaapi/gstvaapicodedbufferpool.c b/gst-libs/gst/vaapi/gstvaapicodedbufferpool.c new file mode 100644 index 0000000..c5a8acd --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbufferpool.c @@ -0,0 +1,113 @@ +/* + * gstvaapicodedbufferpool.c - VA coded buffer pool + * + * Copyright (C) 2013 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "sysdeps.h" +#include "gstvaapicodedbufferpool.h" +#include "gstvaapicodedbuffer_priv.h" +#include "gstvaapivideopool_priv.h" +#include "gstvaapiencoder_priv.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +/** + * GstVaapiCodedBufferPool: + * + * A pool of lazily allocated #GstVaapiCodedBuffer objects. + */ +struct _GstVaapiCodedBufferPool +{ + /*< private >*/ + GstVaapiVideoPool parent_instance; + + GstVaapiContext *context; + gsize buf_size; +}; + +static void +coded_buffer_pool_init (GstVaapiCodedBufferPool * pool, + GstVaapiContext * context, gsize buf_size) +{ + pool->context = gst_vaapi_object_ref (context); + pool->buf_size = buf_size; +} + +static void +coded_buffer_pool_finalize (GstVaapiCodedBufferPool * pool) +{ + gst_vaapi_object_replace (&pool->context, NULL); +} + +static gpointer +coded_buffer_pool_alloc_object (GstVaapiVideoPool * base_pool) +{ + GstVaapiCodedBufferPool *const pool = GST_VAAPI_CODED_BUFFER_POOL (base_pool); + + return gst_vaapi_coded_buffer_new (pool->context, pool->buf_size); +} + +static inline const GstVaapiMiniObjectClass * +gst_vaapi_coded_buffer_pool_class (void) +{ + static const GstVaapiVideoPoolClass GstVaapiCodedBufferPoolClass = { + { sizeof (GstVaapiCodedBufferPool), + (GDestroyNotify)coded_buffer_pool_finalize }, + + .alloc_object = coded_buffer_pool_alloc_object + }; + return GST_VAAPI_MINI_OBJECT_CLASS (&GstVaapiCodedBufferPoolClass); +} + +/** + * gst_vaapi_coded_buffer_pool_new: + * @encoder: a #GstVaapiEncoder + * @buf_size: the max size of #GstVaapiCodedBuffer objects, in bytes + * + * Creates a new #GstVaapiVideoPool of #GstVaapiCodedBuffer objects + * with the supplied maximum size in bytes, and bound to the specified + * @encoder object. + * + * Return value: the newly allocated #GstVaapiVideoPool + */ +GstVaapiVideoPool * +gst_vaapi_coded_buffer_pool_new (GstVaapiEncoder * encoder, gsize buf_size) +{ + GstVaapiVideoPool *pool; + GstVaapiContext *context; + + g_return_val_if_fail (encoder != NULL, NULL); + g_return_val_if_fail (buf_size > 0, NULL); + + context = GST_VAAPI_ENCODER_CONTEXT (encoder); + g_return_val_if_fail (context != NULL, NULL); + + pool = (GstVaapiVideoPool *) + gst_vaapi_mini_object_new (gst_vaapi_coded_buffer_pool_class ()); + if (!pool) + return NULL; + + gst_vaapi_video_pool_init (pool, GST_VAAPI_OBJECT_DISPLAY (context), + GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER); + coded_buffer_pool_init (GST_VAAPI_CODED_BUFFER_POOL (pool), + context, buf_size); + return pool; +} diff --git a/gst-libs/gst/vaapi/gstvaapicodedbufferpool.h b/gst-libs/gst/vaapi/gstvaapicodedbufferpool.h new file mode 100644 index 0000000..3480d48 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbufferpool.h @@ -0,0 +1,42 @@ +/* + * gstvaapicodedbufferpool.h - VA coded buffer pool + * + * Copyright (C) 2013 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_CODED_BUFFER_POOL_H +#define GST_VAAPI_CODED_BUFFER_POOL_H + +#include +#include + +G_BEGIN_DECLS + +#define GST_VAAPI_CODED_BUFFER_POOL(obj) \ + ((GstVaapiCodedBufferPool *)(obj)) + +struct _GstVaapiEncoder; + +GstVaapiVideoPool * +gst_vaapi_coded_buffer_pool_new (struct _GstVaapiEncoder * encoder, + gsize buf_size); + +G_END_DECLS + +#endif /* GST_VAAPI_CODED_BUFFER_POOL_H */ diff --git a/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.c b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.c new file mode 100644 index 0000000..bf173ab --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.c @@ -0,0 +1,253 @@ +/* + * gstvaapicodedbufferproxy.c - VA coded buffer proxy + * + * Copyright (C) 2013 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "sysdeps.h" +#include "gstvaapicodedbufferproxy.h" +#include "gstvaapicodedbufferproxy_priv.h" +#include "gstvaapivideopool_priv.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +static void +coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy, + gpointer user_data, GDestroyNotify destroy_func) +{ + if (proxy->user_data_destroy) + proxy->user_data_destroy (proxy->user_data); + + proxy->user_data = user_data; + proxy->user_data_destroy = destroy_func; +} + +static void +coded_buffer_proxy_finalize (GstVaapiCodedBufferProxy * proxy) +{ + if (proxy->buffer) { + if (proxy->pool) + gst_vaapi_video_pool_put_object (proxy->pool, proxy->buffer); + gst_vaapi_object_unref (proxy->buffer); + proxy->buffer = NULL; + } + gst_vaapi_video_pool_replace (&proxy->pool, NULL); + coded_buffer_proxy_set_user_data (proxy, NULL, NULL); + + /* Notify the user function that the object is now destroyed */ + if (proxy->destroy_func) + proxy->destroy_func (proxy->destroy_data); +} + +static inline const GstVaapiMiniObjectClass * +gst_vaapi_coded_buffer_proxy_class (void) +{ + static const GstVaapiMiniObjectClass GstVaapiCodedBufferProxyClass = { + sizeof (GstVaapiCodedBufferProxy), + (GDestroyNotify)coded_buffer_proxy_finalize + }; + return &GstVaapiCodedBufferProxyClass; +} + +/** + * gst_vaapi_coded_buffer_proxy_new_from_pool: + * @pool: a #GstVaapiCodedBufferPool + * + * Allocates a new coded buffer from the supplied @pool and creates + * the wrapped coded buffer proxy object from it. When the last + * reference to the proxy object is released, then the underlying VA + * coded buffer is pushed back to its parent pool. + * + * Returns: The same newly allocated @proxy object, or %NULL on error + */ +GstVaapiCodedBufferProxy * +gst_vaapi_coded_buffer_proxy_new_from_pool (GstVaapiCodedBufferPool * pool) +{ + GstVaapiCodedBufferProxy *proxy; + + g_return_val_if_fail (pool != NULL, NULL); + g_return_val_if_fail (GST_VAAPI_VIDEO_POOL (pool)->object_type == + GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER, NULL); + + proxy = (GstVaapiCodedBufferProxy *) + gst_vaapi_mini_object_new (gst_vaapi_coded_buffer_proxy_class ()); + if (!proxy) + return NULL; + + proxy->destroy_func = NULL; + proxy->user_data_destroy = NULL; + proxy->pool = gst_vaapi_video_pool_ref (pool); + proxy->buffer = gst_vaapi_video_pool_get_object (proxy->pool); + if (!proxy->buffer) + goto error; + gst_vaapi_object_ref (proxy->buffer); + return proxy; + +error: + gst_vaapi_coded_buffer_proxy_unref (proxy); + return NULL; +} + +/** + * gst_vaapi_coded_buffer_proxy_ref: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Atomically increases the reference count of the given @proxy by one. + * + * Returns: The same @proxy argument + */ +GstVaapiCodedBufferProxy * +gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy) +{ + g_return_val_if_fail (proxy != NULL, NULL); + + return GST_VAAPI_CODED_BUFFER_PROXY (gst_vaapi_mini_object_ref + (GST_VAAPI_MINI_OBJECT (proxy))); +} + +/** + * gst_vaapi_coded_buffer_proxy_unref: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Atomically decreases the reference count of the @proxy by one. If + * the reference count reaches zero, the object will be free'd. + */ +void +gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy) +{ + g_return_if_fail (proxy != NULL); + + gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (proxy)); +} + +/** + * gst_vaapi_coded_buffer_proxy_replace: + * @old_proxy_ptr: a pointer to a #GstVaapiCodedBufferProxy + * @new_proxy: a #GstVaapiCodedBufferProxy + * + * Atomically replaces the proxy object held in @old_proxy_ptr with + * @new_proxy. This means that @old_proxy_ptr shall reference a valid + * object. However, @new_proxy can be NULL. + */ +void +gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr, + GstVaapiCodedBufferProxy * new_proxy) +{ + g_return_if_fail (old_proxy_ptr != NULL); + + gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) old_proxy_ptr, + GST_VAAPI_MINI_OBJECT (new_proxy)); +} + +/** + * gst_vaapi_coded_buffer_proxy_get_buffer: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Returns the #GstVaapiCodedBuffer stored in the @proxy. + * + * Return value: the #GstVaapiCodedBuffer, or %NULL if an error occurred + */ +GstVaapiCodedBuffer * +gst_vaapi_coded_buffer_proxy_get_buffer (GstVaapiCodedBufferProxy * proxy) +{ + g_return_val_if_fail (proxy != NULL, NULL); + + return GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (proxy); +} + +/** + * gst_vaapi_coded_buffer_proxy_get_buffer_size: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Returns the size of the underlying #GstVaapiCodedBuffer object + * stored in the @proxy. + * + * Return value: the underlying #GstVaapiCodedBuffer size, or -1 if an + * error occurred + */ +gssize +gst_vaapi_coded_buffer_proxy_get_buffer_size (GstVaapiCodedBufferProxy * proxy) +{ + g_return_val_if_fail (proxy != NULL, -1); + + return GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE (proxy); +} + +/** + * gst_vaapi_coded_buffer_proxy_set_destroy_notify: + * @proxy: a @GstVaapiCodedBufferProxy + * @destroy_func: a #GDestroyNotify function + * @user_data: some extra data to pass to the @destroy_func function + * + * Sets @destroy_func as the function to call when the coded buffer + * @proxy was released. At this point, the proxy object is considered + * released, i.e. the underlying data storage is no longer valid and + * the callback function shall not expect anything from that. + */ +void +gst_vaapi_coded_buffer_proxy_set_destroy_notify (GstVaapiCodedBufferProxy * + proxy, GDestroyNotify destroy_func, gpointer user_data) +{ + g_return_if_fail (proxy != NULL); + + proxy->destroy_func = destroy_func; + proxy->destroy_data = user_data; +} + +/** + * gst_vaapi_coded_buffer_proxy_get_user_data: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Gets private data previously set on the VA coded buffer proxy + * object through the gst_vaapi_coded_buffer_proxy_set_user_data() + * function. + * + * Return value: the previously set user-data + */ +gpointer +gst_vaapi_coded_buffer_proxy_get_user_data (GstVaapiCodedBufferProxy * proxy) +{ + g_return_val_if_fail (proxy != NULL, NULL); + + return proxy->user_data; +} + +/** + * gst_vaapi_coded_buffer_proxy_set_user_data: + * @proxy: a #GstVaapiCodedBufferProxy + * @user_data: user-defined data + * @destroy_func: a #GDestroyNotify + * + * Sets @user_data on the VA coded buffer proxy object and the + * #GDestroyNotify function that will be called when the coded buffer + * proxy object is released. + * + * If a @user_data was previously set, then the previously set + * @destroy_func function, if any, will be called before the + * @user_data is replaced. + */ +void +gst_vaapi_coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy, + gpointer user_data, GDestroyNotify destroy_func) +{ + g_return_if_fail (proxy != NULL); + + coded_buffer_proxy_set_user_data (proxy, user_data, destroy_func); +} diff --git a/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.h b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.h new file mode 100644 index 0000000..4968c63 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy.h @@ -0,0 +1,82 @@ +/* + * gstvaapicodedbufferproxy_priv.h - VA coded buffer proxy + * + * Copyright (C) 2013 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_CODED_BUFFER_PROXY_H +#define GST_VAAPI_CODED_BUFFER_PROXY_H + +#include +#include + +G_BEGIN_DECLS + +/** + * GST_VAAPI_CODED_BUFFER_PROXY_BUFFER: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Macro that evaluated to the underlying #GstVaapiCodedBuffer of @proxy. + */ +#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy) \ + gst_vaapi_coded_buffer_proxy_get_buffer(proxy) + +/** + * GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Macro that evaluated to the underlying #GstVaapiCodedBuffer size of + * @proxy. + */ +#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE(proxy) \ + gst_vaapi_coded_buffer_proxy_get_buffer_size(proxy) + +GstVaapiCodedBufferProxy * +gst_vaapi_coded_buffer_proxy_new_from_pool (GstVaapiCodedBufferPool * pool); + +GstVaapiCodedBufferProxy * +gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy); + +void +gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy); + +void +gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr, + GstVaapiCodedBufferProxy * new_proxy); + +GstVaapiCodedBuffer * +gst_vaapi_coded_buffer_proxy_get_buffer (GstVaapiCodedBufferProxy * proxy); + +gssize +gst_vaapi_coded_buffer_proxy_get_buffer_size (GstVaapiCodedBufferProxy * proxy); + +void +gst_vaapi_coded_buffer_proxy_set_destroy_notify (GstVaapiCodedBufferProxy * + proxy, GDestroyNotify destroy_func, gpointer user_data); + +gpointer +gst_vaapi_coded_buffer_proxy_get_user_data (GstVaapiCodedBufferProxy * proxy); + +void +gst_vaapi_coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy, + gpointer user_data, GDestroyNotify destroy_func); + +G_END_DECLS + +#endif /* GST_VAAPI_CODED_BUFFER_PROXY_H */ diff --git a/gst-libs/gst/vaapi/gstvaapicodedbufferproxy_priv.h b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy_priv.h new file mode 100644 index 0000000..6feb8f9 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapicodedbufferproxy_priv.h @@ -0,0 +1,70 @@ +/* + * gstvaapicodedbufferproxy_priv.h - VA coded buffer proxy (private defs) + * + * Copyright (C) 2013 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_CODED_BUFFER_PROXY_PRIV_H +#define GST_VAAPI_CODED_BUFFER_PROXY_PRIV_H + +#include "gstvaapicodedbuffer_priv.h" +#include "gstvaapiminiobject.h" + +G_BEGIN_DECLS + +#define GST_VAAPI_CODED_BUFFER_PROXY(proxy) \ + ((GstVaapiCodedBufferProxy *)(proxy)) + +struct _GstVaapiCodedBufferProxy +{ + /*< private >*/ + GstVaapiMiniObject parent_instance; + + GstVaapiVideoPool *pool; + GstVaapiCodedBuffer *buffer; + GDestroyNotify destroy_func; + gpointer destroy_data; + GDestroyNotify user_data_destroy; + gpointer user_data; +}; + +/** + * GST_VAAPI_CODED_BUFFER_PROXY_BUFFER: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Macro that evaluated to the underlying #GstVaapiCodedBuffer of @proxy. + */ +#undef GST_VAAPI_CODED_BUFFER_PROXY_BUFFER +#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy) \ + GST_VAAPI_CODED_BUFFER_PROXY(proxy)->buffer + +/** + * GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE: + * @proxy: a #GstVaapiCodedBufferProxy + * + * Macro that evaluated to the underlying #GstVaapiCodedBuffer size of + * @proxy. + */ +#undef GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE +#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE(proxy) \ + GST_VAAPI_CODED_BUFFER_SIZE(GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy)) + +G_END_DECLS + +#endif /* GST_VAAPI_CODED_BUFFER_PROXY_PRIV_H */ diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c index 519e8f7..61f063a 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder.c @@ -28,8 +28,6 @@ #define DEBUG 1 #include "gstvaapidebug.h" -typedef struct _GstVaapiCodedBufferProxyClass GstVaapiCodedBufferProxyClass; - #define GST_VAAPI_ENCODER_LOCK(encoder) \ G_STMT_START { \ g_mutex_lock (&(GST_VAAPI_ENCODER_CAST(encoder))->lock); \ @@ -74,100 +72,12 @@ GST_VAAPI_ENCODER_SYNC_WAIT_TIMEOUT (GstVaapiEncoder * encoder, gint64 timeout) return g_cond_wait_until (&encoder->sync_ready, &encoder->lock, end_time); } -static GstVaapiCodedBuffer * -gst_vaapi_encoder_dequeue_coded_buffer (GstVaapiEncoder * encoder); - -static void -gst_vaapi_encoder_queue_coded_buffer (GstVaapiEncoder * encoder, - GstVaapiCodedBuffer * buf); - typedef struct { GstVaapiEncPicture *picture; GstVaapiCodedBufferProxy *buf; } GstVaapiEncoderSyncPic; -static void -gst_vaapi_coded_buffer_proxy_finalize (GstVaapiCodedBufferProxy * proxy) -{ - if (proxy->buffer) { - gst_vaapi_coded_buffer_unmap (proxy->buffer); - if (proxy->encoder) - gst_vaapi_encoder_queue_coded_buffer (proxy->encoder, proxy->buffer); - else { - g_assert (FALSE); - gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (proxy->buffer)); - } - proxy->buffer = NULL; - } - gst_vaapi_encoder_replace (&proxy->encoder, NULL); -} - -static void -gst_vaapi_coded_buffer_proxy_class_init (GstVaapiCodedBufferProxyClass * klass) -{ - GstVaapiMiniObjectClass *const object_class = - GST_VAAPI_MINI_OBJECT_CLASS (klass); - - object_class->size = sizeof (GstVaapiCodedBufferProxy); - object_class->finalize = - (GDestroyNotify) gst_vaapi_coded_buffer_proxy_finalize; -} - -static inline const GstVaapiCodedBufferProxyClass * -gst_vaapi_coded_buffer_proxy_class (void) -{ - static GstVaapiCodedBufferProxyClass g_class; - static gsize g_class_init = FALSE; - - if (g_once_init_enter (&g_class_init)) { - gst_vaapi_coded_buffer_proxy_class_init (&g_class); - g_once_init_leave (&g_class_init, TRUE); - } - return (&g_class); -} - -GstVaapiCodedBufferProxy * -gst_vaapi_coded_buffer_proxy_new (GstVaapiEncoder * encoder) -{ - GstVaapiCodedBuffer *buf; - GstVaapiCodedBufferProxy *ret; - - g_assert (encoder); - buf = gst_vaapi_encoder_dequeue_coded_buffer (encoder); - if (!buf) - return NULL; - - ret = (GstVaapiCodedBufferProxy *) - gst_vaapi_mini_object_new0 (GST_VAAPI_MINI_OBJECT_CLASS - (gst_vaapi_coded_buffer_proxy_class ())); - g_assert (ret); - ret->encoder = gst_vaapi_encoder_ref (encoder); - ret->buffer = buf; - return ret; -} - -GstVaapiCodedBufferProxy * -gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy) -{ - return (GstVaapiCodedBufferProxy *) - gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (proxy)); -} - -void -gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy) -{ - gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (proxy)); -} - -void -gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr, - GstVaapiCodedBufferProxy * new_proxy) -{ - gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) old_proxy_ptr, - GST_VAAPI_MINI_OBJECT (new_proxy)); -} - GstVaapiEncoder * gst_vaapi_encoder_ref (GstVaapiEncoder * encoder) { @@ -187,90 +97,38 @@ gst_vaapi_encoder_replace (GstVaapiEncoder ** old_encoder_ptr, gst_vaapi_object_replace (old_encoder_ptr, new_encoder); } -static gboolean -gst_vaapi_encoder_init_coded_buffer_queue (GstVaapiEncoder * encoder, - guint count) -{ - GstVaapiCodedBuffer *buf; - guint i = 0; - - GST_VAAPI_ENCODER_LOCK (encoder); - if (count > encoder->max_buf_num) - count = encoder->max_buf_num; - - g_assert (encoder->buf_size); - for (i = 0; i < count; ++i) { - buf = GST_VAAPI_CODED_BUFFER_NEW (encoder, encoder->buf_size); - g_queue_push_tail (&encoder->coded_buffers, buf); - ++encoder->buf_count; - } - g_assert (encoder->buf_count <= encoder->max_buf_num); - - GST_VAAPI_ENCODER_UNLOCK (encoder); - return TRUE; -} - -static GstVaapiCodedBuffer * -gst_vaapi_encoder_dequeue_coded_buffer (GstVaapiEncoder * encoder) -{ - GstVaapiCodedBuffer *ret = NULL; - - GST_VAAPI_ENCODER_LOCK (encoder); - while (encoder->buf_count >= encoder->max_buf_num && - g_queue_is_empty (&encoder->coded_buffers)) { - GST_VAAPI_ENCODER_BUF_FREE_WAIT (encoder); - } - if (!g_queue_is_empty (&encoder->coded_buffers)) { - ret = (GstVaapiCodedBuffer *) g_queue_pop_head (&encoder->coded_buffers); - goto end; - } - - g_assert (encoder->buf_size); - ret = GST_VAAPI_CODED_BUFFER_NEW (encoder, encoder->buf_size); - if (ret) - ++encoder->buf_count; - -end: - GST_VAAPI_ENCODER_UNLOCK (encoder); - return ret; -} - static void -gst_vaapi_encoder_queue_coded_buffer (GstVaapiEncoder * encoder, - GstVaapiCodedBuffer * buf) +_coded_buffer_proxy_released_notify (GstVaapiEncoder * encoder) { - g_assert (buf); - g_return_if_fail (buf); - GST_VAAPI_ENCODER_LOCK (encoder); - g_queue_push_tail (&encoder->coded_buffers, buf); GST_VAAPI_ENCODER_BUF_FREE_SIGNAL (encoder); GST_VAAPI_ENCODER_UNLOCK (encoder); } -static gboolean -gst_vaapi_encoder_free_coded_buffers (GstVaapiEncoder * encoder) +static GstVaapiCodedBufferProxy * +gst_vaapi_encoder_create_coded_buffer (GstVaapiEncoder * encoder) { - GstVaapiCodedBuffer *buf; - guint count = 0; - gboolean ret; + GstVaapiCodedBufferPool *const pool = + GST_VAAPI_CODED_BUFFER_POOL (encoder->codedbuf_pool); + GstVaapiCodedBufferProxy *codedbuf_proxy; GST_VAAPI_ENCODER_LOCK (encoder); - while (!g_queue_is_empty (&encoder->coded_buffers)) { - buf = (GstVaapiCodedBuffer *) g_queue_pop_head (&encoder->coded_buffers); - g_assert (buf); - gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (buf)); - ++count; - } - ret = (count == encoder->buf_count); - GST_VAAPI_ENCODER_UNLOCK (encoder); + do { + codedbuf_proxy = gst_vaapi_coded_buffer_proxy_new_from_pool (pool); + if (codedbuf_proxy) + break; - if (!ret) { - GST_ERROR ("coded buffer leak, freed count:%d, total buf:%d", - count, encoder->buf_count); - } + /* Wait for a free coded buffer to become available */ + GST_VAAPI_ENCODER_BUF_FREE_WAIT (encoder); + codedbuf_proxy = gst_vaapi_coded_buffer_proxy_new_from_pool (pool); + } while (0); + GST_VAAPI_ENCODER_UNLOCK (encoder); + if (!codedbuf_proxy) + return NULL; - return ret; + gst_vaapi_coded_buffer_proxy_set_destroy_notify (codedbuf_proxy, + (GDestroyNotify)_coded_buffer_proxy_released_notify, encoder); + return codedbuf_proxy; } static void @@ -343,7 +201,9 @@ gst_vaapi_encoder_free_sync_pictures (GstVaapiEncoder * encoder) while (!g_queue_is_empty (&encoder->sync_pictures)) { sync = (GstVaapiEncoderSyncPic *) g_queue_pop_head (&encoder->sync_pictures); + GST_VAAPI_ENCODER_UNLOCK (encoder); _free_sync_picture (encoder, sync); + GST_VAAPI_ENCODER_LOCK (encoder); } GST_VAAPI_ENCODER_UNLOCK (encoder); } @@ -420,7 +280,7 @@ again: goto error; } - coded_buf = gst_vaapi_coded_buffer_proxy_new (encoder); + coded_buf = gst_vaapi_encoder_create_coded_buffer (encoder); if (!coded_buf) { ret = GST_VAAPI_ENCODER_STATUS_OBJECT_ERR; goto error; @@ -577,13 +437,16 @@ gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, if (!gst_vaapi_encoder_ensure_context (encoder)) goto error; - encoder->buf_size = (GST_VAAPI_ENCODER_WIDTH (encoder) * + encoder->codedbuf_size = (GST_VAAPI_ENCODER_WIDTH (encoder) * GST_VAAPI_ENCODER_HEIGHT (encoder) * 400) / (16 * 16); - if (!gst_vaapi_encoder_init_coded_buffer_queue (encoder, 5)) { - GST_ERROR ("encoder init coded buffer failed"); + encoder->codedbuf_pool = gst_vaapi_coded_buffer_pool_new (encoder, + encoder->codedbuf_size); + if (!encoder->codedbuf_pool) { + GST_ERROR ("failed to initialized coded buffer pool"); goto error; } + gst_vaapi_video_pool_set_capacity (encoder->codedbuf_pool, 5); return out_caps; @@ -613,14 +476,9 @@ gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display) gst_video_info_init (&encoder->video_info); - encoder->buf_count = 0; - encoder->max_buf_num = 10; - encoder->buf_size = 0; - g_mutex_init (&encoder->lock); g_cond_init (&encoder->codedbuf_free); g_cond_init (&encoder->surface_free); - g_queue_init (&encoder->coded_buffers); g_queue_init (&encoder->sync_pictures); g_cond_init (&encoder->sync_ready); @@ -637,8 +495,8 @@ gst_vaapi_encoder_destroy (GstVaapiEncoder * encoder) if (klass->destroy) klass->destroy (encoder); - gst_vaapi_encoder_free_coded_buffers (encoder); gst_vaapi_encoder_free_sync_pictures (encoder); + gst_vaapi_video_pool_replace (&encoder->codedbuf_pool, NULL); gst_vaapi_object_replace (&encoder->context, NULL); gst_vaapi_display_replace (&encoder->display, NULL); @@ -646,7 +504,6 @@ gst_vaapi_encoder_destroy (GstVaapiEncoder * encoder) g_mutex_clear (&encoder->lock); g_cond_clear (&encoder->codedbuf_free); g_cond_clear (&encoder->surface_free); - g_queue_clear (&encoder->coded_buffers); g_queue_clear (&encoder->sync_pictures); g_cond_clear (&encoder->sync_ready); } diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h index 1779b59..8741c9a 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder.h @@ -22,10 +22,8 @@ #ifndef GST_VAAPI_ENCODER_H #define GST_VAAPI_ENCODER_H -#include #include -#include -#include +#include G_BEGIN_DECLS @@ -49,7 +47,6 @@ typedef enum } GstVaapiEncoderStatus; typedef struct _GstVaapiEncoder GstVaapiEncoder; -typedef struct _GstVaapiCodedBufferProxy GstVaapiCodedBufferProxy; #define GST_VAAPI_ENCODER(encoder) \ ((GstVaapiEncoder *)(encoder)) diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c index 818bdf7..a7fa921 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c @@ -24,6 +24,7 @@ #include "gstvaapiencoder_h264.h" #include "gstvaapiencoder_h264_priv.h" #include "gstvaapiencoder_priv.h" +#include "gstvaapicodedbufferproxy_priv.h" #include #include @@ -948,7 +949,7 @@ fill_va_picture_param (GstVaapiEncoderH264 * encoder, for (; i < 16; ++i) { pic->ReferenceFrames[i].picture_id = VA_INVALID_ID; } - pic->coded_buf = codedbuf->buf_id; + pic->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf); pic->pic_parameter_set_id = 0; pic->seq_parameter_set_id = 0; @@ -1148,11 +1149,11 @@ error: } static gboolean -ensure_picture (GstVaapiEncoderH264 * encoder, - GstVaapiEncPicture * picture, - GstVaapiCodedBufferProxy * buf_proxy, GstVaapiSurfaceProxy * surface) +ensure_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture, + GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface) { - GstVaapiCodedBuffer *codedbuf = buf_proxy->buffer; + GstVaapiCodedBuffer *const codedbuf = + GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy); if (!fill_va_picture_param (encoder, picture, codedbuf, surface)) return FALSE; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c index 4b5ae8e..70decdb 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c @@ -25,6 +25,7 @@ #include "gstvaapiencoder_mpeg2.h" #include "gstvaapiencoder_mpeg2_priv.h" #include "gstvaapiencoder_priv.h" +#include "gstvaapicodedbufferproxy_priv.h" #include #include @@ -228,7 +229,7 @@ fill_picture (GstVaapiEncoderMpeg2 * encoder, memset (pic, 0, sizeof (VAEncPictureParameterBufferMPEG2)); pic->reconstructed_picture = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface); - pic->coded_buf = codedbuf->buf_id; + pic->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf); pic->picture_type = get_va_enc_picture_type (picture->type); pic->temporal_reference = picture->frame_num & (1024 - 1); pic->vbv_delay = 0xFFFF; @@ -385,11 +386,11 @@ error: } static gboolean -ensure_picture (GstVaapiEncoderMpeg2 * encoder, - GstVaapiEncPicture * picture, - GstVaapiCodedBufferProxy * buf_proxy, GstVaapiSurfaceProxy * surface) +ensure_picture (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncPicture * picture, + GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface) { - GstVaapiCodedBuffer *codedbuf = buf_proxy->buffer; + GstVaapiCodedBuffer *const codedbuf = + GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy); if (!fill_picture (encoder, picture, codedbuf, surface)) return FALSE; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_objects.c b/gst-libs/gst/vaapi/gstvaapiencoder_objects.c index 2a61736..5f730e3 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_objects.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_objects.c @@ -36,108 +36,6 @@ #define GET_VA_CONTEXT(obj) GST_VAAPI_ENCODER_VA_CONTEXT(GET_ENCODER(obj)) /* ------------------------------------------------------------------------- */ -/* --- Encoder Coded Data --- */ -/* ------------------------------------------------------------------------- */ - -GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiCodedBuffer, gst_vaapi_coded_buffer); - -void -gst_vaapi_coded_buffer_destroy (GstVaapiCodedBuffer * buffer) -{ - gst_vaapi_coded_buffer_unmap (buffer); - vaapi_destroy_buffer (GET_VA_DISPLAY (buffer), &buffer->buf_id); - buffer->segment_list = NULL; -} - -gboolean -gst_vaapi_coded_buffer_create (GstVaapiCodedBuffer * codec_buffer, - const GstVaapiCodecObjectConstructorArgs * args) -{ - codec_buffer->buf_id = VA_INVALID_ID; - codec_buffer->segment_list = NULL; - return vaapi_create_buffer (GET_VA_DISPLAY (codec_buffer), - GET_VA_CONTEXT (codec_buffer), - VAEncCodedBufferType, - args->param_size, args->param, &codec_buffer->buf_id, NULL); -} - -GstVaapiCodedBuffer * -gst_vaapi_coded_buffer_new (GstVaapiEncoder * encoder, - gconstpointer param, guint param_size) -{ - GstVaapiCodecObject *object; - - object = gst_vaapi_codec_object_new (&GstVaapiCodedBufferClass, - GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0); - if (!object) - return NULL; - return GST_VAAPI_CODED_BUFFER_CAST (object); -} - -gboolean -gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf, void **data) -{ - g_return_val_if_fail (buf->buf_id != VA_INVALID_ID, FALSE); - - if (buf->segment_list) - goto end; - buf->segment_list = vaapi_map_buffer (GET_VA_DISPLAY (buf), buf->buf_id); - if (!buf->segment_list) - return FALSE; -end: - if (data) - *data = buf->segment_list; - return TRUE; -} - -void -gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf) -{ - if (buf->buf_id != VA_INVALID_ID && buf->segment_list) - vaapi_unmap_buffer (GET_VA_DISPLAY (buf), - buf->buf_id, (void **) (&buf->segment_list)); -} - -gint32 -gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf) -{ - gint32 size; - VACodedBufferSegment *segment; - if (!gst_vaapi_coded_buffer_map (buf, NULL)) - return -1; - - size = 0; - segment = buf->segment_list; - while (segment) { - size += segment->size; - segment = (VACodedBufferSegment *) segment->next; - } - return size; -} - -gboolean -gst_vaapi_coded_buffer_get_buffer (GstVaapiCodedBuffer * buf, - GstBuffer * output) -{ - gint32 offset; - VACodedBufferSegment *segment; - - g_assert (output); - g_return_val_if_fail (output, FALSE); - - offset = 0; - segment = buf->segment_list; - while (segment) { - if (gst_buffer_fill (output, offset, segment->buf, segment->size) - != segment->size) - return FALSE; - offset += segment->size; - segment = (VACodedBufferSegment *) segment->next; - } - return TRUE; -} - -/* ------------------------------------------------------------------------- */ /* --- Encoder Packed Header --- */ /* ------------------------------------------------------------------------- */ diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_objects.h b/gst-libs/gst/vaapi/gstvaapiencoder_objects.h index fdc960e..d57ad50 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_objects.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_objects.h @@ -36,52 +36,6 @@ typedef struct _GstVaapiCodedBuffer GstVaapiCodedBuffer; typedef struct _GstVaapiEncPackedHeader GstVaapiEncPackedHeader; /* ------------------------------------------------------------------------- */ -/* --- Encoder Coded Buffer --- */ -/* ------------------------------------------------------------------------- */ - -#define GST_VAAPI_CODED_BUFFER_CAST(obj) \ - ((GstVaapiCodedBuffer *)(obj)) - -#define GST_VAAPI_CODED_BUFFER(obj) \ - GST_VAAPI_CODED_BUFFER_CAST(obj) - -#define GST_VAAPI_IS_CODED_BUFFER(obj) \ - (GST_VAAPI_CODED_BUFFER(obj) != NULL) - -/** - * GstVaapiCodedBuffer: - * - * A #GstVaapiCodecObject holding an encoded buffer. - */ -struct _GstVaapiCodedBuffer -{ - /*< private > */ - GstVaapiCodecObject parent_instance; - VABufferID buf_id; - - /*< public > */ - VACodedBufferSegment *segment_list; -}; - -G_GNUC_INTERNAL -GstVaapiCodedBuffer * -gst_vaapi_coded_buffer_new (GstVaapiEncoder * encoder, - gconstpointer param, guint param_size); - -gboolean -gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf, void **data); - -void -gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf); - -gint32 -gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf); - -gboolean -gst_vaapi_coded_buffer_get_buffer (GstVaapiCodedBuffer * buf, - GstBuffer * output); - -/* ------------------------------------------------------------------------- */ /* --- Encoder Packed Header --- */ /* ------------------------------------------------------------------------- */ diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h index 71fff0c..8b78ac9 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h @@ -25,6 +25,7 @@ #include #include #include +#include #include G_BEGIN_DECLS @@ -75,7 +76,6 @@ G_BEGIN_DECLS goto end; \ } -typedef struct _GstVaapiCodedBufferProxyClass GstVaapiCodedBufferProxyClass; typedef struct _GstVaapiEncoderClass GstVaapiEncoderClass; struct _GstVaapiEncoder @@ -92,13 +92,11 @@ struct _GstVaapiEncoder GstVideoInfo video_info; GstVaapiRateControl rate_control; - guint buf_count; - guint max_buf_num; - guint buf_size; GMutex lock; - GCond codedbuf_free; GCond surface_free; - GQueue coded_buffers; + GCond codedbuf_free; + guint codedbuf_size; + GstVaapiVideoPool *codedbuf_pool; /* queue for sync */ GQueue sync_pictures; @@ -134,21 +132,6 @@ struct _GstVaapiEncoderClass GstBuffer ** codec_data); }; -struct _GstVaapiCodedBufferProxy -{ - /*< private >*/ - GstVaapiMiniObject parent_instance; - GstVaapiEncoder *encoder; - - /*< public >*/ - GstVaapiCodedBuffer *buffer; -}; - -struct _GstVaapiCodedBufferProxyClass -{ - GstVaapiMiniObjectClass parent_class; -}; - void gst_vaapi_encoder_class_init (GstVaapiEncoderClass * klass); @@ -167,22 +150,6 @@ void gst_vaapi_encoder_release_surface (GstVaapiEncoder * encoder, GstVaapiSurfaceProxy * surface); -/* ------------------ GstVaapiCodedBufferProxy ---------------------------- */ - -GstVaapiCodedBufferProxy * -gst_vaapi_coded_buffer_proxy_new (GstVaapiEncoder * - encoder); - -GstVaapiCodedBufferProxy * -gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy); - -void -gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy); - -void -gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr, - GstVaapiCodedBufferProxy * new_proxy); - G_END_DECLS #endif /* GST_VAAPI_ENCODER_PRIV_H */ diff --git a/gst-libs/gst/vaapi/gstvaapivideopool.h b/gst-libs/gst/vaapi/gstvaapivideopool.h index 1942d62..84210ed 100644 --- a/gst-libs/gst/vaapi/gstvaapivideopool.h +++ b/gst-libs/gst/vaapi/gstvaapivideopool.h @@ -39,12 +39,14 @@ typedef struct _GstVaapiVideoPool GstVaapiVideoPool; * GstVaapiVideoPoolObjectType: * @GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_IMAGE: #GstVaapiImage objects. * @GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_SURFACE: #GstVaapiSurface objects. + * @GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER: #GstVaapiCodedBuffer objects. * * The set of all supported #GstVaapiVideoPool object types. */ typedef enum { GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_IMAGE = 1, - GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_SURFACE + GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_SURFACE, + GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER } GstVaapiVideoPoolObjectType; GstVaapiVideoPool * diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index c3b2f55..adb2474 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -22,8 +22,6 @@ #include "gst/vaapi/sysdeps.h" #include #include -#include -#include #include "gstvaapiencode.h" #include "gstvaapivideocontext.h" #include "gstvaapipluginutil.h" @@ -182,9 +180,6 @@ gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode, g_return_val_if_fail (coded_buf != NULL, GST_FLOW_ERROR); g_return_val_if_fail (outbuf_ptr != NULL, GST_FLOW_ERROR); - if (!gst_vaapi_coded_buffer_map (coded_buf, NULL)) - return GST_VAAPI_ENCODE_FLOW_MEM_ERROR; - buf_size = gst_vaapi_coded_buffer_get_size (coded_buf); if (buf_size <= 0) goto error_invalid_buffer; @@ -198,10 +193,9 @@ gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode, #endif if (!buf) goto error_create_buffer; - if (!gst_vaapi_coded_buffer_get_buffer (coded_buf, buf)) + if (!gst_vaapi_coded_buffer_copy_into (buf, coded_buf)) goto error_copy_buffer; - gst_vaapi_coded_buffer_unmap (coded_buf); *outbuf_ptr = buf; return GST_FLOW_OK; @@ -209,20 +203,17 @@ gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode, error_invalid_buffer: { GST_ERROR ("invalid GstVaapiCodedBuffer size (%d)", buf_size); - gst_vaapi_coded_buffer_unmap (coded_buf); return GST_VAAPI_ENCODE_FLOW_MEM_ERROR; } error_create_buffer: { GST_ERROR ("failed to create output buffer of size %d", buf_size); - gst_vaapi_coded_buffer_unmap (coded_buf); return GST_VAAPI_ENCODE_FLOW_MEM_ERROR; } error_copy_buffer: { GST_ERROR ("failed to copy GstVaapiCodedBuffer data"); gst_buffer_unref (buf); - gst_vaapi_coded_buffer_unmap (coded_buf); return GST_VAAPI_ENCODE_FLOW_MEM_ERROR; } } @@ -233,13 +224,13 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout) GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode); GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode); GstVideoCodecFrame *out_frame = NULL; - GstVaapiCodedBufferProxy *coded_buf_proxy = NULL; + GstVaapiCodedBufferProxy *codedbuf_proxy = NULL; GstVaapiEncoderStatus status; GstBuffer *out_buffer; GstFlowReturn ret; status = gst_vaapi_encoder_get_buffer (encode->encoder, - &out_frame, &coded_buf_proxy, timeout); + &out_frame, &codedbuf_proxy, timeout); if (status == GST_VAAPI_ENCODER_STATUS_TIMEOUT) return GST_VAAPI_ENCODE_FLOW_TIMEOUT; if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) @@ -249,8 +240,9 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout) /* Allocate and copy buffer into system memory */ out_buffer = NULL; - ret = klass->allocate_buffer (encode, coded_buf_proxy->buffer, &out_buffer); - gst_vaapi_coded_buffer_proxy_replace (&coded_buf_proxy, NULL); + ret = klass->allocate_buffer (encode, + GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy), &out_buffer); + gst_vaapi_coded_buffer_proxy_replace (&codedbuf_proxy, NULL); if (ret != GST_FLOW_OK) goto error_allocate_buffer; @@ -297,8 +289,8 @@ error_get_buffer: GST_ERROR ("failed to get encoded buffer (status %d)", status); if (out_frame) gst_video_codec_frame_unref (out_frame); - if (coded_buf_proxy) - gst_vaapi_coded_buffer_proxy_unref (coded_buf_proxy); + if (codedbuf_proxy) + gst_vaapi_coded_buffer_proxy_unref (codedbuf_proxy); return GST_FLOW_ERROR; } error_allocate_buffer: diff --git a/gst/vaapi/gstvaapiencode.h b/gst/vaapi/gstvaapiencode.h index 6d59980..09a97c7 100644 --- a/gst/vaapi/gstvaapiencode.h +++ b/gst/vaapi/gstvaapiencode.h @@ -25,7 +25,6 @@ #include #include #include -#include "gst/vaapi/gstvaapiencoder_objects.h" #include "gstvaapiuploader.h" G_BEGIN_DECLS diff --git a/gst/vaapi/gstvaapivideometa.c b/gst/vaapi/gstvaapivideometa.c index b1d2462..7b4bc2d 100644 --- a/gst/vaapi/gstvaapivideometa.c +++ b/gst/vaapi/gstvaapivideometa.c @@ -282,6 +282,7 @@ GstVaapiVideoMeta * gst_vaapi_video_meta_new_from_pool(GstVaapiVideoPool *pool) { GstVaapiVideoMeta *meta; + GstVaapiVideoPoolObjectType object_type; g_return_val_if_fail(pool != NULL, NULL); @@ -289,7 +290,8 @@ gst_vaapi_video_meta_new_from_pool(GstVaapiVideoPool *pool) if (G_UNLIKELY(!meta)) return NULL; - switch (gst_vaapi_video_pool_get_object_type(pool)) { + object_type = gst_vaapi_video_pool_get_object_type(pool); + switch (object_type) { case GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_IMAGE: if (!set_image_from_pool(meta, pool)) goto error; @@ -298,6 +300,9 @@ gst_vaapi_video_meta_new_from_pool(GstVaapiVideoPool *pool) if (!set_surface_proxy_from_pool(meta, pool)) goto error; break; + default: + GST_ERROR("unsupported video buffer pool of type %d", object_type); + goto error; } set_display(meta, gst_vaapi_video_pool_get_display(pool)); return meta;