⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gstadapter.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* GStreamer * Copyright (C) 2004 Benjamin Otte <otte@gnome.org> *               2005 Wim Taymans <wim@fluendo.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//** * SECTION:gstadapter * @short_description: adapts incoming data on a sink pad into chunks of N bytes * * This class is for elements that receive buffers in an undesired size. * While for example raw video contains one image per buffer, the same is not * true for a lot of other formats, especially those that come directly from * a file. So if you have undefined buffer sizes and require a specific size, * this object is for you. * * An adapter is created with gst_adapter_new(). It can be freed again with * g_object_unref(). * * The theory of operation is like this: All buffers received are put * into the adapter using gst_adapter_push() and the data is then read back * in chunks of the desired size using gst_adapter_peek(). After the data is * processed, it is freed using gst_adapter_flush(). * * For example, a sink pad's chain function that needs to pass data to a library * in 512-byte chunks could be implemented like this: * <programlisting> * static GstFlowReturn * sink_pad_chain (GstPad *pad, GstBuffer *buffer) * { *   MyElement *this; *   GstAdapter *adapter; *   GstFlowReturn ret = GST_FLOW_OK; *    *   // will give the element an extra ref; remember to drop it  *   this = MY_ELEMENT (gst_pad_get_parent (pad)); *   adapter = this->adapter; *    *   // put buffer into adapter *   gst_adapter_push (adapter, buffer); *   // while we can read out 512 bytes, process them *   while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) { *     // use flowreturn as an error value *     ret = my_library_foo (gst_adapter_peek (adapter, 512)); *     gst_adapter_flush (adapter, 512); *   } *    *   gst_object_unref (this); *   return ret; * } * </programlisting> * For another example, a simple element inside GStreamer that uses GstAdapter * is the libvisual element. * * An element using GstAdapter in its sink pad chain function should ensure that * when the FLUSH_STOP event is received, that any queued data is cleared using * gst_adapter_clear(). Data should also be cleared or processed on EOS and * when changing state from #GST_STATE_PAUSED to #GST_STATE_READY. * * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might * need to clear the adapter after a discontinuity. * * A last thing to note is that while GstAdapter is pretty optimized, * merging buffers still might be an operation that requires a memcpy() * operation, and this operation is not the fastest. Because of this, some * functions like gst_adapter_available_fast() are provided to help speed up * such cases should you want to. * * GstAdapter is not MT safe. All operations on an adapter must be serialized by * the caller. This is not normally a problem, however, as the normal use case * of GstAdapter is inside one pad's chain function, in which case access is * serialized via the pad's STREAM_LOCK. * * Note that gst_adapter_push() takes ownership of the buffer passed. Use  * gst_buffer_ref() before pushing it into the adapter if you still want to * access the buffer later. The adapter will never modify the data in the * buffer pushed in it. * * Last reviewed on 2006-04-04 (0.10.6). */#include "gstadapter.h"#include <string.h>/* default size for the assembled data buffer */#define DEFAULT_SIZE 16GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);#define GST_CAT_DEFAULT gst_adapter_debug#define _do_init(thing) \  GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,    _do_init);static void gst_adapter_dispose (GObject * object);static void gst_adapter_finalize (GObject * object);static voidgst_adapter_base_init (gpointer g_class){  /* nop */}static voidgst_adapter_class_init (GstAdapterClass * klass){  GObjectClass *object = G_OBJECT_CLASS (klass);  object->dispose = gst_adapter_dispose;  object->finalize = gst_adapter_finalize;}static voidgst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class){  adapter->assembled_data = g_malloc (DEFAULT_SIZE);  adapter->assembled_size = DEFAULT_SIZE;}static voidgst_adapter_dispose (GObject * object){  GstAdapter *adapter = GST_ADAPTER (object);  gst_adapter_clear (adapter);  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));}static voidgst_adapter_finalize (GObject * object){  GstAdapter *adapter = GST_ADAPTER (object);  g_free (adapter->assembled_data);  GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));}/** * gst_adapter_new: * * Creates a new #GstAdapter. Free with g_object_unref(). * * Returns: a new #GstAdapter */GstAdapter *gst_adapter_new (void){  return g_object_new (GST_TYPE_ADAPTER, NULL);}/** * gst_adapter_clear: * @adapter: a #GstAdapter * * Removes all buffers from @adapter. */voidgst_adapter_clear (GstAdapter * adapter){  g_return_if_fail (GST_IS_ADAPTER (adapter));  g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL);  g_slist_free (adapter->buflist);  adapter->buflist = NULL;  adapter->buflist_end = NULL;  adapter->size = 0;  adapter->skip = 0;  adapter->assembled_len = 0;}/** * gst_adapter_push: * @adapter: a #GstAdapter * @buf: a #GstBuffer to add to queue in the adapter * * Adds the data from @buf to the data stored inside @adapter and takes * ownership of the buffer. */voidgst_adapter_push (GstAdapter * adapter, GstBuffer * buf){  g_return_if_fail (GST_IS_ADAPTER (adapter));  g_return_if_fail (GST_IS_BUFFER (buf));  adapter->size += GST_BUFFER_SIZE (buf);  /* Note: merging buffers at this point is premature. */  if (G_UNLIKELY (adapter->buflist == NULL)) {    adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);  } else {    /* Otherwise append to the end, and advance our end pointer */    adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);    adapter->buflist_end = g_slist_next (adapter->buflist_end);  }}/* Internal function that copies data into the given buffer, size must be  * bigger than the first buffer */static voidgst_adapter_peek_into (GstAdapter * adapter, guint8 * data, guint size){  GstBuffer *cur;  GSList *cur_list;  guint copied, to_copy;  /* The first buffer might be partly consumed, so need to handle   * 'skipped' bytes. */  cur = adapter->buflist->data;  copied = to_copy = MIN (GST_BUFFER_SIZE (cur) - adapter->skip, size);  memcpy (data, GST_BUFFER_DATA (cur) + adapter->skip, copied);  data += copied;  cur_list = g_slist_next (adapter->buflist);  while (copied < size) {    g_assert (cur_list);    cur = cur_list->data;    cur_list = g_slist_next (cur_list);    to_copy = MIN (GST_BUFFER_SIZE (cur), size - copied);    memcpy (data, GST_BUFFER_DATA (cur), to_copy);    data += to_copy;    copied += to_copy;  }}/* Internal method only. Tries to merge buffers at the head of the queue * to form a single larger buffer of size 'size'. Only merges buffers that * where 'gst_buffer_is_span_fast' returns TRUE. * * Returns TRUE if it managed to merge anything. */static gbooleangst_adapter_try_to_merge_up (GstAdapter * adapter, guint size){  GstBuffer *cur, *head;  GSList *g;  g = adapter->buflist;  if (g == NULL)    return FALSE;  head = g->data;  g = g_slist_next (g);  /* How large do we want our head buffer? The requested size, plus whatever's   * been skipped already */  size += adapter->skip;  while (g != NULL && GST_BUFFER_SIZE (head) < size) {    cur = g->data;    if (!gst_buffer_is_span_fast (head, cur))      return TRUE;    /* Merge the head buffer and the next in line */    GST_LOG_OBJECT (adapter,        "Merging buffers of size %u & %u in search of target %u",        GST_BUFFER_SIZE (head), GST_BUFFER_SIZE (cur), size);    head = gst_buffer_join (head, cur);    /* Delete the front list item, and store our new buffer in the 2nd list      * item */    adapter->buflist = g_slist_delete_link (adapter->buflist, adapter->buflist);    g->data = head;  }  return FALSE;}/** * gst_adapter_peek: * @adapter: a #GstAdapter * @size: the number of bytes to peek * * Gets the first @size bytes stored in the @adapter. The returned pointer is * valid until the next function is called on the adapter. * * Note that setting the returned pointer as the data of a #GstBuffer is * incorrect for general-purpose plugins. The reason is that if a downstream * element stores the buffer so that it has access to it outside of the bounds * of its chain function, the buffer will have an invalid data pointer after * your element flushes the bytes. In that case you should use * gst_adapter_take(), which returns a freshly-allocated buffer that you can set * as #GstBuffer malloc_data or the potentially more performant  * gst_adapter_take_buffer(). * * Returns #NULL if @size bytes are not available. * * Returns: a pointer to the first @size bytes of data, or NULL. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -