Merge branch 'master' into 0.11

Conflicts:
	sys/ximage/ximageutil.c
This commit is contained in:
Wim Taymans 2011-06-02 18:51:29 +02:00
commit 0b1bdcf7cb
24 changed files with 2007 additions and 1722 deletions

View file

@ -108,6 +108,8 @@ static GstFlowReturn gst_text_overlay_collected (GstCollectPads * pads,
gpointer data);
static void gst_text_overlay_finalize (GObject * object);
static void gst_text_overlay_font_init (GstCairoTextOverlay * overlay);
static gboolean gst_text_overlay_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_text_overlay_video_event (GstPad * pad, GstEvent * event);
/* These macros are adapted from videotestsrc.c */
#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
@ -248,6 +250,8 @@ gst_text_overlay_init (GstCairoTextOverlay * overlay,
(&cairo_text_overlay_src_template_factory, "src");
gst_pad_set_getcaps_function (overlay->srcpad,
GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps));
gst_pad_set_event_function (overlay->srcpad,
GST_DEBUG_FUNCPTR (gst_text_overlay_src_event));
gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad);
overlay->halign = GST_CAIRO_TEXT_OVERLAY_HALIGN_CENTER;
@ -274,6 +278,14 @@ gst_text_overlay_init (GstCairoTextOverlay * overlay,
overlay->video_collect_data = gst_collect_pads_add_pad (overlay->collect,
overlay->video_sinkpad, sizeof (GstCollectData));
/* FIXME: hacked way to override/extend the event function of
* GstCollectPads; because it sets its own event function giving the
* element no access to events. Nicked from avimux. */
overlay->collect_event =
(GstPadEventFunction) GST_PAD_EVENTFUNC (overlay->video_sinkpad);
gst_pad_set_event_function (overlay->video_sinkpad,
GST_DEBUG_FUNCPTR (gst_text_overlay_video_event));
/* text pad will be added when it is linked */
overlay->text_collect_data = NULL;
}
@ -942,6 +954,45 @@ done:
}
}
static gboolean
gst_text_overlay_src_event (GstPad * pad, GstEvent * event)
{
GstCairoTextOverlay *overlay =
GST_CAIRO_TEXT_OVERLAY (gst_pad_get_parent (pad));
gboolean ret = TRUE;
/* forward events to the video sink, and, if it is linked, the text sink */
if (overlay->text_collect_data) {
gst_event_ref (event);
ret &= gst_pad_push_event (overlay->text_sinkpad, event);
}
ret &= gst_pad_push_event (overlay->video_sinkpad, event);
gst_object_unref (overlay);
return ret;
}
static gboolean
gst_text_overlay_video_event (GstPad * pad, GstEvent * event)
{
gboolean ret = FALSE;
GstCairoTextOverlay *overlay = NULL;
overlay = GST_CAIRO_TEXT_OVERLAY (gst_pad_get_parent (pad));
if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
GST_DEBUG_OBJECT (overlay,
"received new segment on video sink pad, forwarding");
gst_event_ref (event);
gst_pad_push_event (overlay->srcpad, event);
}
/* now GstCollectPads can take care of the rest, e.g. EOS */
ret = overlay->collect_event (pad, event);
gst_object_unref (overlay);
return ret;
}
static GstStateChangeReturn
gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
{

View file

@ -48,6 +48,7 @@ struct _GstCairoTextOverlay {
GstCollectPads *collect;
GstCollectData *video_collect_data;
GstCollectData *text_collect_data;
GstPadEventFunction collect_event;
gint width;
gint height;

View file

@ -574,26 +574,23 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
GstFormat format;
GstFormat format2;
gint64 end;
GstPad *peer;
/* First ask the peer in the original format */
if (!gst_pad_peer_query (dvdemux->sinkpad, query)) {
/* get target format */
gst_query_parse_duration (query, &format, NULL);
/* change query to bytes to perform on peer */
gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
if ((peer = gst_pad_get_peer (dvdemux->sinkpad))) {
/* ask peer for total length */
if (!(res = gst_pad_query (peer, query))) {
gst_object_unref (peer);
/* Now ask the peer in BYTES format and try to convert */
if (!gst_pad_peer_query (dvdemux->sinkpad, query)) {
goto error;
}
/* get peer total length */
gst_query_parse_duration (query, NULL, &end);
gst_object_unref (peer);
/* convert end to requested format */
if (end != -1) {
format2 = format;
@ -601,11 +598,9 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
GST_FORMAT_BYTES, end, &format2, &end))) {
goto error;
}
}
} else {
end = -1;
}
gst_query_set_duration (query, format, end);
}
}
break;
}
case GST_QUERY_CONVERT:

View file

@ -1,10 +1,10 @@
plugin_LTLIBRARIES = libgstsouphttpsrc.la
libgstsouphttpsrc_la_SOURCES = gstsouphttpsrc.c
libgstsouphttpsrc_la_SOURCES = gstsouphttpsrc.c gstsouphttpsink.c gstsoup.c
libgstsouphttpsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(SOUP_CFLAGS)
libgstsouphttpsrc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_MAJORMINOR@ $(GST_BASE_LIBS) $(SOUP_LIBS)
libgstsouphttpsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstsouphttpsrc_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstsouphttpsrc.h
noinst_HEADERS = gstsouphttpsrc.h gstsouphttpsink.h

47
ext/soup/gstsoup.c Normal file
View file

@ -0,0 +1,47 @@
/* GStreamer
* Copyright (C) 2007-2008 Wouter Cloetens <wouter@mind.be>
*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst-i18n-plugin.h>
#include "gstsouphttpsrc.h"
#include "gstsouphttpsink.h"
static gboolean
plugin_init (GstPlugin * plugin)
{
#ifdef ENABLE_NLS
GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
LOCALEDIR);
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
gst_element_register (plugin, "souphttpsrc", GST_RANK_PRIMARY,
GST_TYPE_SOUP_HTTP_SRC);
gst_element_register (plugin, "souphttpsink", GST_RANK_NONE,
GST_TYPE_SOUP_HTTP_SINK);
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"soup",
"libsoup HTTP client src/sink",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

673
ext/soup/gstsouphttpsink.c Normal file
View file

@ -0,0 +1,673 @@
/* GStreamer
* Copyright (C) 2011 David Schleef <ds@entropywave.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., 51 Franklin Street, Suite 500,
* Boston, MA 02110-1335, USA.
*/
/**
* SECTION:element-gstsouphttpsink
*
* The souphttpsink element sends pipeline data to an HTTP server
* using HTTP PUT commands.
*
* <refsect2>
* <title>Example launch line</title>
* |[
* gst-launch -v videotestsrc num-buffers=300 ! theoraenc ! oggmux !
* souphttpsink location=http://server/filename.ogv
* ]|
*
* This example encodes 10 seconds of video and sends it to the HTTP
* server "server" using HTTP PUT commands.
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include "gstsouphttpsink.h"
GST_DEBUG_CATEGORY_STATIC (gst_soup_http_sink_debug_category);
#define GST_CAT_DEFAULT gst_soup_http_sink_debug_category
/* prototypes */
static void gst_soup_http_sink_set_property (GObject * object,
guint property_id, const GValue * value, GParamSpec * pspec);
static void gst_soup_http_sink_get_property (GObject * object,
guint property_id, GValue * value, GParamSpec * pspec);
static void gst_soup_http_sink_dispose (GObject * object);
static void gst_soup_http_sink_finalize (GObject * object);
static gboolean gst_soup_http_sink_set_caps (GstBaseSink * sink,
GstCaps * caps);
static void gst_soup_http_sink_get_times (GstBaseSink * sink,
GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
static gboolean gst_soup_http_sink_start (GstBaseSink * sink);
static gboolean gst_soup_http_sink_stop (GstBaseSink * sink);
static gboolean gst_soup_http_sink_unlock (GstBaseSink * sink);
static gboolean gst_soup_http_sink_event (GstBaseSink * sink, GstEvent * event);
static GstFlowReturn
gst_soup_http_sink_preroll (GstBaseSink * sink, GstBuffer * buffer);
static GstFlowReturn
gst_soup_http_sink_render (GstBaseSink * sink, GstBuffer * buffer);
static void free_buffer_list (GList * list);
static void gst_soup_http_sink_reset (GstSoupHttpSink * souphttpsink);
static void authenticate (SoupSession * session, SoupMessage * msg,
SoupAuth * auth, gboolean retrying, gpointer user_data);
static void
callback (SoupSession * session, SoupMessage * msg, gpointer user_data);
enum
{
PROP_0,
PROP_LOCATION,
PROP_USER_AGENT,
PROP_AUTOMATIC_REDIRECT,
PROP_PROXY,
PROP_USER_ID,
PROP_USER_PW,
PROP_PROXY_ID,
PROP_PROXY_PW,
PROP_COOKIES,
PROP_SESSION,
};
#define DEFAULT_USER_AGENT "GStreamer souphttpsink "
/* pad templates */
static GstStaticPadTemplate gst_soup_http_sink_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
/* class initialization */
#define DEBUG_INIT(bla) \
GST_DEBUG_CATEGORY_INIT (gst_soup_http_sink_debug_category, "souphttpsink", 0, \
"debug category for souphttpsink element");
GST_BOILERPLATE_FULL (GstSoupHttpSink, gst_soup_http_sink, GstBaseSink,
GST_TYPE_BASE_SINK, DEBUG_INIT);
static void
gst_soup_http_sink_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_soup_http_sink_sink_template));
gst_element_class_set_details_simple (element_class, "HTTP client sink",
"Generic", "Sends streams to HTTP server via PUT",
"David Schleef <ds@entropywave.com>");
}
static void
gst_soup_http_sink_class_init (GstSoupHttpSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS (klass);
gobject_class->set_property = gst_soup_http_sink_set_property;
gobject_class->get_property = gst_soup_http_sink_get_property;
gobject_class->dispose = gst_soup_http_sink_dispose;
gobject_class->finalize = gst_soup_http_sink_finalize;
base_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_soup_http_sink_set_caps);
if (0)
base_sink_class->get_times =
GST_DEBUG_FUNCPTR (gst_soup_http_sink_get_times);
base_sink_class->start = GST_DEBUG_FUNCPTR (gst_soup_http_sink_start);
base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_soup_http_sink_stop);
base_sink_class->unlock = GST_DEBUG_FUNCPTR (gst_soup_http_sink_unlock);
base_sink_class->event = GST_DEBUG_FUNCPTR (gst_soup_http_sink_event);
if (0)
base_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_soup_http_sink_preroll);
base_sink_class->render = GST_DEBUG_FUNCPTR (gst_soup_http_sink_render);
g_object_class_install_property (gobject_class,
PROP_LOCATION,
g_param_spec_string ("location", "Location",
"URI to send to", "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_USER_AGENT,
g_param_spec_string ("user-agent", "User-Agent",
"Value of the User-Agent HTTP request header field",
DEFAULT_USER_AGENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_AUTOMATIC_REDIRECT,
g_param_spec_boolean ("automatic-redirect", "automatic-redirect",
"Automatically follow HTTP redirects (HTTP Status Code 3xx)",
TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#if 0
g_object_class_install_property (gobject_class,
PROP_PROXY,
g_param_spec_string ("proxy", "Proxy",
"HTTP proxy server URI", "",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#endif
g_object_class_install_property (gobject_class,
PROP_USER_ID,
g_param_spec_string ("user-id", "user-id",
"user id for authentication", "",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_USER_PW,
g_param_spec_string ("user-pw", "user-pw",
"user password for authentication", "",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PROXY_ID,
g_param_spec_string ("proxy-id", "proxy-id",
"user id for proxy authentication", "",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PROXY_PW,
g_param_spec_string ("proxy-pw", "proxy-pw",
"user password for proxy authentication", "",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SESSION,
g_param_spec_object ("session", "session",
"SoupSession object to use for communication",
SOUP_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
gst_soup_http_sink_init (GstSoupHttpSink * souphttpsink,
GstSoupHttpSinkClass * souphttpsink_class)
{
#if 0
const char *proxy;
#endif
souphttpsink->sinkpad =
gst_pad_new_from_static_template (&gst_soup_http_sink_sink_template,
"sink");
souphttpsink->mutex = g_mutex_new ();
souphttpsink->cond = g_cond_new ();
souphttpsink->location = NULL;
souphttpsink->automatic_redirect = TRUE;
souphttpsink->user_agent = g_strdup (DEFAULT_USER_AGENT);
souphttpsink->user_id = NULL;
souphttpsink->user_pw = NULL;
souphttpsink->proxy_id = NULL;
souphttpsink->proxy_pw = NULL;
souphttpsink->prop_session = NULL;
souphttpsink->timeout = 1;
#if 0
proxy = g_getenv ("http_proxy");
if (proxy && !gst_soup_http_sink_set_proxy (souphttpsink, proxy)) {
GST_WARNING_OBJECT (souphttpsink,
"The proxy in the http_proxy env var (\"%s\") cannot be parsed.",
proxy);
}
#endif
gst_soup_http_sink_reset (souphttpsink);
}
static void
gst_soup_http_sink_reset (GstSoupHttpSink * souphttpsink)
{
g_free (souphttpsink->reason_phrase);
souphttpsink->reason_phrase = NULL;
souphttpsink->status_code = 0;
souphttpsink->offset = 0;
}
void
gst_soup_http_sink_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (object);
g_mutex_lock (souphttpsink->mutex);
switch (property_id) {
case PROP_SESSION:
if (souphttpsink->prop_session) {
g_object_unref (souphttpsink->prop_session);
}
souphttpsink->prop_session = g_value_dup_object (value);
break;
case PROP_LOCATION:
g_free (souphttpsink->location);
souphttpsink->location = g_value_dup_string (value);
souphttpsink->offset = 0;
break;
case PROP_USER_AGENT:
g_free (souphttpsink->user_agent);
souphttpsink->user_agent = g_value_dup_string (value);
break;
case PROP_AUTOMATIC_REDIRECT:
souphttpsink->automatic_redirect = g_value_get_boolean (value);
break;
case PROP_USER_ID:
g_free (souphttpsink->user_id);
souphttpsink->user_id = g_value_dup_string (value);
break;
case PROP_USER_PW:
g_free (souphttpsink->user_pw);
souphttpsink->user_pw = g_value_dup_string (value);
break;
case PROP_PROXY_ID:
g_free (souphttpsink->proxy_id);
souphttpsink->proxy_id = g_value_dup_string (value);
break;
case PROP_PROXY_PW:
g_free (souphttpsink->proxy_pw);
souphttpsink->proxy_pw = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
g_mutex_unlock (souphttpsink->mutex);
}
void
gst_soup_http_sink_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (object);
switch (property_id) {
case PROP_SESSION:
g_value_set_object (value, souphttpsink->prop_session);
break;
case PROP_LOCATION:
g_value_set_string (value, souphttpsink->location);
break;
case PROP_AUTOMATIC_REDIRECT:
g_value_set_boolean (value, souphttpsink->automatic_redirect);
break;
case PROP_USER_AGENT:
g_value_set_string (value, souphttpsink->user_agent);
break;
case PROP_USER_ID:
g_value_set_string (value, souphttpsink->user_id);
break;
case PROP_USER_PW:
g_value_set_string (value, souphttpsink->user_pw);
break;
case PROP_PROXY_ID:
g_value_set_string (value, souphttpsink->proxy_id);
break;
case PROP_PROXY_PW:
g_value_set_string (value, souphttpsink->proxy_pw);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
void
gst_soup_http_sink_dispose (GObject * object)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (object);
/* clean up as possible. may be called multiple times */
if (souphttpsink->prop_session)
g_object_unref (souphttpsink->prop_session);
souphttpsink->prop_session = NULL;
G_OBJECT_CLASS (parent_class)->dispose (object);
}
void
gst_soup_http_sink_finalize (GObject * object)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (object);
/* clean up object here */
g_free (souphttpsink->user_agent);
g_free (souphttpsink->user_id);
g_free (souphttpsink->user_pw);
g_free (souphttpsink->proxy_id);
g_free (souphttpsink->proxy_pw);
g_free (souphttpsink->location);
g_cond_free (souphttpsink->cond);
g_mutex_free (souphttpsink->mutex);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
gst_soup_http_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink);
GstStructure *structure;
const GValue *value_array;
int i, n;
structure = gst_caps_get_structure (caps, 0);
value_array = gst_structure_get_value (structure, "streamheader");
if (value_array) {
free_buffer_list (souphttpsink->streamheader_buffers);
souphttpsink->streamheader_buffers = NULL;
n = gst_value_array_get_size (value_array);
for (i = 0; i < n; i++) {
const GValue *value;
GstBuffer *buffer;
value = gst_value_array_get_value (value_array, i);
buffer = GST_BUFFER (gst_value_get_buffer (value));
souphttpsink->streamheader_buffers =
g_list_append (souphttpsink->streamheader_buffers,
gst_buffer_ref (buffer));
}
}
return TRUE;
}
static void
gst_soup_http_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
GstClockTime * start, GstClockTime * end)
{
}
static gpointer
thread_func (gpointer ptr)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (ptr);
GST_DEBUG ("thread start");
souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
g_main_loop_run (souphttpsink->loop);
GST_DEBUG ("thread quit");
return NULL;
}
static gboolean
gst_soup_http_sink_start (GstBaseSink * sink)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink);
if (souphttpsink->prop_session) {
souphttpsink->session = souphttpsink->prop_session;
} else {
GError *error = NULL;
souphttpsink->context = g_main_context_new ();
souphttpsink->thread = g_thread_create (thread_func, souphttpsink,
TRUE, &error);
souphttpsink->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
souphttpsink->context, SOUP_SESSION_USER_AGENT,
souphttpsink->user_agent, SOUP_SESSION_TIMEOUT, souphttpsink->timeout,
NULL);
//soup_session_add_feature (souphttpsink->session,
// SOUP_SESSION_FEATURE (soup_logger_new (SOUP_LOGGER_LOG_BODY, 100)));
g_signal_connect (souphttpsink->session, "authenticate",
G_CALLBACK (authenticate), souphttpsink);
}
return TRUE;
}
static gboolean
gst_soup_http_sink_stop (GstBaseSink * sink)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink);
GST_DEBUG ("stop");
if (souphttpsink->prop_session == NULL) {
soup_session_abort (souphttpsink->session);
g_object_unref (souphttpsink->session);
}
if (souphttpsink->loop) {
g_main_loop_quit (souphttpsink->loop);
g_thread_join (souphttpsink->thread);
g_main_loop_unref (souphttpsink->loop);
souphttpsink->loop = NULL;
}
if (souphttpsink->context) {
g_main_context_unref (souphttpsink->context);
souphttpsink->context = NULL;
}
gst_soup_http_sink_reset (souphttpsink);
return TRUE;
}
static gboolean
gst_soup_http_sink_unlock (GstBaseSink * sink)
{
GST_DEBUG ("unlock");
return TRUE;
}
static gboolean
gst_soup_http_sink_event (GstBaseSink * sink, GstEvent * event)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink);
GST_DEBUG ("event");
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
GST_DEBUG ("got eos");
g_mutex_lock (souphttpsink->mutex);
while (souphttpsink->message) {
GST_DEBUG ("waiting");
g_cond_wait (souphttpsink->cond, souphttpsink->mutex);
}
g_mutex_unlock (souphttpsink->mutex);
GST_DEBUG ("finished eos");
}
return TRUE;
}
static GstFlowReturn
gst_soup_http_sink_preroll (GstBaseSink * sink, GstBuffer * buffer)
{
GST_DEBUG ("preroll");
return GST_FLOW_OK;
}
static void
free_buffer_list (GList * list)
{
GList *g;
for (g = list; g; g = g_list_next (g)) {
GstBuffer *buffer = g->data;
gst_buffer_unref (buffer);
}
g_list_free (list);
}
static void
send_message_locked (GstSoupHttpSink * souphttpsink)
{
GList *g;
guint64 n;
if (souphttpsink->queued_buffers == NULL || souphttpsink->message) {
return;
}
/* If the URI went away, drop all these buffers */
if (souphttpsink->location == NULL) {
free_buffer_list (souphttpsink->queued_buffers);
souphttpsink->queued_buffers = NULL;
return;
}
souphttpsink->message = soup_message_new ("PUT", souphttpsink->location);
//soup_message_body_set_accumulate (souphttpsink->message->request_body, TRUE);
n = 0;
if (souphttpsink->offset == 0) {
for (g = souphttpsink->streamheader_buffers; g; g = g_list_next (g)) {
GstBuffer *buffer = g->data;
soup_message_body_append (souphttpsink->message->request_body,
SOUP_MEMORY_STATIC, GST_BUFFER_DATA (buffer),
GST_BUFFER_SIZE (buffer));
n += GST_BUFFER_SIZE (buffer);
}
}
for (g = souphttpsink->queued_buffers; g; g = g_list_next (g)) {
GstBuffer *buffer = g->data;
if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) {
soup_message_body_append (souphttpsink->message->request_body,
SOUP_MEMORY_STATIC, GST_BUFFER_DATA (buffer),
GST_BUFFER_SIZE (buffer));
n += GST_BUFFER_SIZE (buffer);
}
}
if (souphttpsink->offset != 0) {
char *s;
s = g_strdup_printf ("bytes %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT "/*",
souphttpsink->offset, souphttpsink->offset + n - 1);
soup_message_headers_append (souphttpsink->message->request_headers,
"Content-Range", s);
g_free (s);
}
if (n == 0) {
free_buffer_list (souphttpsink->queued_buffers);
souphttpsink->queued_buffers = NULL;
g_object_unref (souphttpsink->message);
souphttpsink->message = NULL;
return;
}
souphttpsink->sent_buffers = souphttpsink->queued_buffers;
souphttpsink->queued_buffers = NULL;
GST_DEBUG ("queue message %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT,
souphttpsink->offset, n);
soup_session_queue_message (souphttpsink->session,
souphttpsink->message, callback, souphttpsink);
souphttpsink->offset += n;
}
static gboolean
send_message (GstSoupHttpSink * souphttpsink)
{
g_mutex_lock (souphttpsink->mutex);
send_message_locked (souphttpsink);
g_mutex_unlock (souphttpsink->mutex);
return FALSE;
}
static void
callback (SoupSession * session, SoupMessage * msg, gpointer user_data)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (user_data);
GST_DEBUG_OBJECT (souphttpsink, "callback status=%d %s",
msg->status_code, msg->reason_phrase);
g_mutex_lock (souphttpsink->mutex);
g_cond_signal (souphttpsink->cond);
souphttpsink->message = NULL;
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
souphttpsink->status_code = msg->status_code;
souphttpsink->reason_phrase = g_strdup (msg->reason_phrase);
g_mutex_unlock (souphttpsink->mutex);
return;
}
free_buffer_list (souphttpsink->sent_buffers);
souphttpsink->sent_buffers = NULL;
send_message_locked (souphttpsink);
g_mutex_unlock (souphttpsink->mutex);
}
static GstFlowReturn
gst_soup_http_sink_render (GstBaseSink * sink, GstBuffer * buffer)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink);
GSource *source;
gboolean wake;
if (souphttpsink->status_code != 0) {
GST_ELEMENT_ERROR (souphttpsink, RESOURCE, WRITE,
("Could not write to HTTP URI"),
("error: %d %s", souphttpsink->status_code,
souphttpsink->reason_phrase));
return GST_FLOW_ERROR;
}
g_mutex_lock (souphttpsink->mutex);
if (souphttpsink->location != NULL) {
wake = (souphttpsink->queued_buffers == NULL);
souphttpsink->queued_buffers =
g_list_append (souphttpsink->queued_buffers, gst_buffer_ref (buffer));
if (wake) {
source = g_idle_source_new ();
//g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_callback (source, (GSourceFunc) (send_message),
souphttpsink, NULL);
g_source_attach (source, souphttpsink->context);
g_source_unref (source);
}
}
g_mutex_unlock (souphttpsink->mutex);
return GST_FLOW_OK;
}
static void
authenticate (SoupSession * session, SoupMessage * msg,
SoupAuth * auth, gboolean retrying, gpointer user_data)
{
GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (user_data);
if (!retrying) {
if (souphttpsink->user_id && souphttpsink->user_pw) {
soup_auth_authenticate (auth,
souphttpsink->user_id, souphttpsink->user_pw);
}
}
}

View file

@ -0,0 +1,81 @@
/* GStreamer
* Copyright (C) 2011 FIXME <fixme@example.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.
*/
#ifndef _GST_SOUP_HTTP_SINK_H_
#define _GST_SOUP_HTTP_SINK_H_
#include <gst/base/gstbasesink.h>
#include <libsoup/soup.h>
G_BEGIN_DECLS
#define GST_TYPE_SOUP_HTTP_SINK (gst_soup_http_sink_get_type())
#define GST_SOUP_HTTP_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SOUP_HTTP_SINK,GstSoupHttpSink))
#define GST_SOUP_HTTP_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SOUP_HTTP_SINK,GstSoupHttpSinkClass))
#define GST_IS_SOUP_HTTP_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SOUP_HTTP_SINK))
#define GST_IS_SOUP_HTTP_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SOUP_HTTP_SINK))
typedef struct _GstSoupHttpSink GstSoupHttpSink;
typedef struct _GstSoupHttpSinkClass GstSoupHttpSinkClass;
struct _GstSoupHttpSink
{
GstBaseSink base_souphttpsink;
GstPad *sinkpad;
GMutex *mutex;
GCond *cond;
GMainContext *context;
GMainLoop *loop;
GThread *thread;
SoupMessage *message;
SoupSession *session;
GList *queued_buffers;
GList *sent_buffers;
GList *streamheader_buffers;
int status_code;
char *reason_phrase;
guint64 offset;
int timeout;
/* properties */
SoupSession *prop_session;
char *location;
char *user_id;
char *user_pw;
char *proxy_id;
char *proxy_pw;
char *user_agent;
gboolean automatic_redirect;
};
struct _GstSoupHttpSinkClass
{
GstBaseSinkClass base_souphttpsink_class;
};
GType gst_soup_http_sink_get_type (void);
G_END_DECLS
#endif

View file

@ -1488,26 +1488,3 @@ gst_soup_http_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
iface->get_uri = gst_soup_http_src_uri_get_uri;
iface->set_uri = gst_soup_http_src_uri_set_uri;
}
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (souphttpsrc_debug, "souphttpsrc", 0,
"SOUP HTTP Client Source");
#ifdef ENABLE_NLS
GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
LOCALEDIR);
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
return gst_element_register (plugin, "souphttpsrc", GST_RANK_PRIMARY,
GST_TYPE_SOUP_HTTP_SRC);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"soup",
"libsoup HTTP client src",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -142,9 +142,6 @@ static GstStaticPadTemplate video_sink_factory =
"video/x-huffyuv, "
"width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ];"
"video/x-dirac, "
"width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ];"
"video/x-wmv, "
"width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ], "
@ -560,8 +557,6 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
avipad->vids.compression = GST_MAKE_FOURCC ('M', 'P', 'E', 'G');
break;
}
} else if (!strcmp (mimetype, "video/x-dirac")) {
avipad->vids.compression = GST_MAKE_FOURCC ('d', 'r', 'a', 'c');
} else if (!strcmp (mimetype, "video/x-wmv")) {
gint wmvversion;

View file

@ -991,6 +991,7 @@ static const GstTagToFourcc tag_matches_mp4[] = {
{FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
gst_qt_mux_add_mp4_tag},
{FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, gst_qt_mux_add_mp4_cover},
{FOURCC_covr, GST_TAG_IMAGE, NULL, gst_qt_mux_add_mp4_cover},
{0, NULL,}
};

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,6 @@
#define __GST_MATROSKA_DEMUX_H__
#include <gst/gst.h>
#include <gst/base/gstadapter.h>
#include "ebml-read.h"
#include "matroska-ids.h"
@ -51,7 +50,6 @@ typedef struct _GstMatroskaDemux {
GstMatroskaReadCommon common;
/* pads */
GstPad *sinkpad;
GstClock *clock;
guint num_v_streams;
guint num_a_streams;
@ -85,21 +83,13 @@ typedef struct _GstMatroskaDemux {
GstEvent *close_segment;
GstEvent *new_segment;
GstTagList *global_tags;
/* pull mode caching */
GstBuffer *cached_buffer;
/* push and pull mode */
guint64 offset;
/* some state saving */
GstClockTime cluster_time;
guint64 cluster_offset;
guint64 first_cluster_offset;
guint64 next_cluster_offset;
/* push based mode usual suspects */
GstAdapter *adapter;
/* index stuff */
gboolean seekable;
gboolean building_index;

View file

@ -567,6 +567,7 @@ typedef struct _GstMatroskaTrackSubtitleContext {
gboolean check_utf8; /* buffers should be valid UTF-8 */
gboolean invalid_utf8; /* work around broken files */
gboolean seen_markup_tag; /* markup found in text */
} GstMatroskaTrackSubtitleContext;
typedef struct _GstMatroskaIndex {

View file

@ -258,6 +258,9 @@ static gboolean kate_streamheader_to_codecdata (const GValue * streamheader,
GstMatroskaTrackContext * context);
static gboolean flac_streamheader_to_codecdata (const GValue * streamheader,
GstMatroskaTrackContext * context);
static void
gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
gpointer data);
static void
gst_matroska_mux_add_interfaces (GType type)
@ -2117,6 +2120,27 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
gst_ebml_write_master_finish (ebml, master);
}
if (mux->streamable) {
const GstTagList *tags;
/* tags */
tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
if (tags != NULL && !gst_tag_list_is_empty (tags)) {
guint64 master_tags, master_tag;
GST_DEBUG ("Writing tags");
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
mux->tags_pos = ebml->pos;
master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
gst_ebml_write_master_finish (ebml, master_tag);
gst_ebml_write_master_finish (ebml, master_tags);
}
}
/* segment info */
mux->info_pos = ebml->pos;
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,6 @@
#define __GST_MATROSKA_PARSE_H__
#include <gst/gst.h>
#include <gst/base/gstadapter.h>
#include "ebml-read.h"
#include "matroska-ids.h"
@ -51,7 +50,6 @@ typedef struct _GstMatroskaParse {
GstMatroskaReadCommon common;
/* pads */
GstPad *sinkpad;
GstPad *srcpad;
GstClock *clock;
guint num_v_streams;
@ -87,21 +85,13 @@ typedef struct _GstMatroskaParse {
GstEvent *close_segment;
GstEvent *new_segment;
GstTagList *global_tags;
/* pull mode caching */
GstBuffer *cached_buffer;
/* push and pull mode */
guint64 offset;
/* some state saving */
GstClockTime cluster_time;
guint64 cluster_offset;
guint64 first_cluster_offset;
guint64 next_cluster_offset;
/* push based mode usual suspects */
GstAdapter *adapter;
/* index stuff */
gboolean seekable;
gboolean building_index;

View file

@ -52,50 +52,7 @@ GST_DEBUG_CATEGORY_STATIC (matroskareadcommon_debug);
GST_DEBUG_OBJECT (common, "Parsing " element " element " \
" finished with '%s'", gst_flow_get_name (ret))
GstFlowReturn
gst_matroska_decode_content_encodings (GArray * encodings)
{
gint i;
if (encodings == NULL)
return GST_FLOW_OK;
for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
guint8 *data = NULL;
guint size;
if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
== 0)
continue;
/* Encryption not supported yet */
if (enc->type != 0)
return GST_FLOW_ERROR;
if (i + 1 >= encodings->len)
return GST_FLOW_ERROR;
if (enc->comp_settings_length == 0)
continue;
data = enc->comp_settings;
size = enc->comp_settings_length;
if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
return GST_FLOW_ERROR;
g_free (enc->comp_settings);
enc->comp_settings = data;
enc->comp_settings_length = size;
}
return GST_FLOW_OK;
}
gboolean
static gboolean
gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
guint8 ** data_out, guint * size_out,
GstMatroskaTrackCompressionAlgorithm algo)
@ -265,6 +222,111 @@ out:
return ret;
}
GstFlowReturn
gst_matroska_decode_content_encodings (GArray * encodings)
{
gint i;
if (encodings == NULL)
return GST_FLOW_OK;
for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
guint8 *data = NULL;
guint size;
if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
== 0)
continue;
/* Encryption not supported yet */
if (enc->type != 0)
return GST_FLOW_ERROR;
if (i + 1 >= encodings->len)
return GST_FLOW_ERROR;
if (enc->comp_settings_length == 0)
continue;
data = enc->comp_settings;
size = enc->comp_settings_length;
if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
return GST_FLOW_ERROR;
g_free (enc->comp_settings);
enc->comp_settings = data;
enc->comp_settings_length = size;
}
return GST_FLOW_OK;
}
gboolean
gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
{
guint8 *data;
guint size;
gboolean ret = TRUE;
gint i;
g_return_val_if_fail (encodings != NULL, FALSE);
g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
g_return_val_if_fail (size_out != NULL, FALSE);
data = *data_out;
size = *size_out;
for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
guint8 *new_data = NULL;
guint new_size = 0;
if ((enc->scope & scope) == 0)
continue;
/* Encryption not supported yet */
if (enc->type != 0) {
ret = FALSE;
break;
}
new_data = data;
new_size = size;
ret =
gst_matroska_decompress_data (enc, &new_data, &new_size,
enc->comp_algo);
if (!ret)
break;
if ((data == *data_out && free) || (data != *data_out))
g_free (data);
data = new_data;
size = new_size;
}
if (!ret) {
if ((data == *data_out && free) || (data != *data_out))
g_free (data);
*data_out = NULL;
*size_out = 0;
} else {
*data_out = data;
*size_out = size;
}
return ret;
}
static gint
gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
{
@ -280,6 +342,131 @@ gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
return 0;
}
gint
gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
gpointer user_data)
{
if (i1->time < *time)
return -1;
else if (i1->time > *time)
return 1;
else
return 0;
}
GstMatroskaIndex *
gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
gint * _entry_index)
{
GstMatroskaIndex *entry = NULL;
GArray *index;
if (!common->index || !common->index->len)
return NULL;
/* find entry just before or at the requested position */
if (track && track->index_table)
index = track->index_table;
else
index = common->index;
entry =
gst_util_array_binary_search (index->data, index->len,
sizeof (GstMatroskaIndex),
(GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE,
&seek_pos, NULL);
if (entry == NULL)
entry = &g_array_index (index, GstMatroskaIndex, 0);
if (_index)
*_index = index;
if (_entry_index)
*_entry_index = entry - (GstMatroskaIndex *) index->data;
return entry;
}
static gint
gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
GstMatroskaTrackEncoding * b)
{
if (b->order > a->order)
return 1;
else if (b->order < a->order)
return -1;
else
return 0;
}
static gboolean
gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
order)
{
gint i;
if (encodings == NULL || encodings->len == 0)
return TRUE;
for (i = 0; i < encodings->len; i++)
if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
return FALSE;
return TRUE;
}
/* takes ownership of taglist */
void
gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
GstElement * el, GstTagList * taglist)
{
if (common->global_tags) {
/* nothing sent yet, add to cache */
gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
gst_tag_list_free (taglist);
} else {
/* hm, already sent, no need to cache and wait anymore */
GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
taglist);
gst_element_found_tags (el, taglist);
}
}
gint64
gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
{
GstFormat fmt = GST_FORMAT_BYTES;
gint64 end = -1;
if (!gst_pad_query_peer_duration (common->sinkpad, &fmt, &end) ||
fmt != GST_FORMAT_BYTES || end < 0)
GST_DEBUG_OBJECT (common, "no upstream length");
return end;
}
/* determine track to seek in */
GstMatroskaTrackContext *
gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
GstMatroskaTrackContext * track)
{
gint i;
if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
return track;
for (i = 0; i < common->src->len; i++) {
GstMatroskaTrackContext *stream;
stream = g_ptr_array_index (common->src, i);
if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
track = stream;
}
return track;
}
/* skip unknown or alike element */
GstFlowReturn
gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
@ -297,6 +484,164 @@ gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
return gst_ebml_read_skip (ebml);
}
GstFlowReturn
gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
GstEbmlRead * ebml)
{
GstFlowReturn ret;
gchar *doctype;
guint version;
guint32 id;
/* this function is the first to be called */
/* default init */
doctype = NULL;
version = 1;
ret = gst_ebml_peek_id (ebml, &id);
if (ret != GST_FLOW_OK)
return ret;
GST_DEBUG_OBJECT (common, "id: %08x", id);
if (id != GST_EBML_ID_HEADER) {
GST_ERROR_OBJECT (common, "Failed to read header");
goto exit;
}
ret = gst_ebml_read_master (ebml, &id);
if (ret != GST_FLOW_OK)
return ret;
while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
ret = gst_ebml_peek_id (ebml, &id);
if (ret != GST_FLOW_OK)
return ret;
switch (id) {
/* is our read version uptodate? */
case GST_EBML_ID_EBMLREADVERSION:{
guint64 num;
ret = gst_ebml_read_uint (ebml, &id, &num);
if (ret != GST_FLOW_OK)
return ret;
if (num != GST_EBML_VERSION) {
GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
num);
return GST_FLOW_ERROR;
}
GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
break;
}
/* we only handle 8 byte lengths at max */
case GST_EBML_ID_EBMLMAXSIZELENGTH:{
guint64 num;
ret = gst_ebml_read_uint (ebml, &id, &num);
if (ret != GST_FLOW_OK)
return ret;
if (num > sizeof (guint64)) {
GST_ERROR_OBJECT (ebml,
"Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
return GST_FLOW_ERROR;
}
GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
break;
}
/* we handle 4 byte IDs at max */
case GST_EBML_ID_EBMLMAXIDLENGTH:{
guint64 num;
ret = gst_ebml_read_uint (ebml, &id, &num);
if (ret != GST_FLOW_OK)
return ret;
if (num > sizeof (guint32)) {
GST_ERROR_OBJECT (ebml,
"Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
return GST_FLOW_ERROR;
}
GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
break;
}
case GST_EBML_ID_DOCTYPE:{
gchar *text;
ret = gst_ebml_read_ascii (ebml, &id, &text);
if (ret != GST_FLOW_OK)
return ret;
GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
if (doctype)
g_free (doctype);
doctype = text;
break;
}
case GST_EBML_ID_DOCTYPEREADVERSION:{
guint64 num;
ret = gst_ebml_read_uint (ebml, &id, &num);
if (ret != GST_FLOW_OK)
return ret;
version = num;
GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
break;
}
default:
ret = gst_matroska_read_common_parse_skip (common, ebml,
"EBML header", id);
if (ret != GST_FLOW_OK)
return ret;
break;
/* we ignore these two, as they don't tell us anything we care about */
case GST_EBML_ID_EBMLVERSION:
case GST_EBML_ID_DOCTYPEVERSION:
ret = gst_ebml_read_skip (ebml);
if (ret != GST_FLOW_OK)
return ret;
break;
}
}
exit:
if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
(doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
(doctype == NULL)) {
if (version <= 2) {
if (doctype) {
GST_INFO_OBJECT (common, "Input is %s version %d", doctype, version);
} else {
GST_WARNING_OBJECT (common, "Input is EBML without doctype, assuming "
"matroska (version %d)", version);
}
ret = GST_FLOW_OK;
} else {
GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
("Demuxer version (2) is too old to read %s version %d",
GST_STR_NULL (doctype), version));
ret = GST_FLOW_ERROR;
}
g_free (doctype);
} else {
GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
("Input is not a matroska stream (doctype=%s)", doctype));
ret = GST_FLOW_ERROR;
g_free (doctype);
}
return ret;
}
static GstFlowReturn
gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
GstEbmlRead * ebml, guint * nentries)
@ -607,3 +952,375 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
return ret;
}
static const guint8 *
gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
peek)
{
return gst_adapter_peek (common->adapter, peek);
}
/*
* Calls pull_range for (offset,size) without advancing our offset
*/
GstFlowReturn
gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
{
GstFlowReturn ret;
/* Caching here actually makes much less difference than one would expect.
* We do it mainly to avoid pulling buffers of 1 byte all the time */
if (common->cached_buffer) {
guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
guint cache_size = GST_BUFFER_SIZE (common->cached_buffer);
if (cache_offset <= common->offset &&
(common->offset + size) <= (cache_offset + cache_size)) {
if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer,
common->offset - cache_offset, size);
if (bytes)
*bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset -
cache_offset;
return GST_FLOW_OK;
}
/* not enough data in the cache, free cache and get a new one */
gst_buffer_unref (common->cached_buffer);
common->cached_buffer = NULL;
}
/* refill the cache */
ret = gst_pad_pull_range (common->sinkpad, common->offset,
MAX (size, 64 * 1024), &common->cached_buffer);
if (ret != GST_FLOW_OK) {
common->cached_buffer = NULL;
return ret;
}
if (GST_BUFFER_SIZE (common->cached_buffer) >= size) {
if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
if (bytes)
*bytes = GST_BUFFER_DATA (common->cached_buffer);
return GST_FLOW_OK;
}
/* Not possible to get enough data, try a last time with
* requesting exactly the size we need */
gst_buffer_unref (common->cached_buffer);
common->cached_buffer = NULL;
ret =
gst_pad_pull_range (common->sinkpad, common->offset, size,
&common->cached_buffer);
if (ret != GST_FLOW_OK) {
GST_DEBUG_OBJECT (common, "pull_range returned %d", ret);
if (p_buf)
*p_buf = NULL;
if (bytes)
*bytes = NULL;
return ret;
}
if (GST_BUFFER_SIZE (common->cached_buffer) < size) {
GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->offset,
size, GST_BUFFER_SIZE (common->cached_buffer));
gst_buffer_unref (common->cached_buffer);
common->cached_buffer = NULL;
if (p_buf)
*p_buf = NULL;
if (bytes)
*bytes = NULL;
return GST_FLOW_UNEXPECTED;
}
if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
if (bytes)
*bytes = GST_BUFFER_DATA (common->cached_buffer);
return GST_FLOW_OK;
}
static const guint8 *
gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek)
{
guint8 *data = NULL;
gst_matroska_read_common_peek_bytes (common, common->offset, peek, NULL,
&data);
return data;
}
GstFlowReturn
gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
{
return gst_ebml_peek_id_length (_id, _length, _needed,
(GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
common->offset);
}
GstFlowReturn
gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
{
return gst_ebml_peek_id_length (_id, _length, _needed,
(GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
el, common->offset);
}
static GstFlowReturn
gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
GstEbmlRead * ebml, GstMatroskaTrackContext * context)
{
GstMatroskaTrackEncoding enc = { 0, };
GstFlowReturn ret;
guint32 id;
DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
/* Set default values */
enc.scope = 1;
/* All other default values are 0 */
if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
return ret;
}
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
break;
switch (id) {
case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
guint64 num;
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
break;
if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
num)) {
GST_ERROR_OBJECT (common, "ContentEncodingOrder %" G_GUINT64_FORMAT
"is not unique for track %d", num, context->num);
ret = GST_FLOW_ERROR;
break;
}
GST_DEBUG_OBJECT (common, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
num);
enc.order = num;
break;
}
case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
guint64 num;
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
break;
if (num > 7 && num == 0) {
GST_ERROR_OBJECT (common, "Invalid ContentEncodingScope %"
G_GUINT64_FORMAT, num);
ret = GST_FLOW_ERROR;
break;
}
GST_DEBUG_OBJECT (common, "ContentEncodingScope: %" G_GUINT64_FORMAT,
num);
enc.scope = num;
break;
}
case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
guint64 num;
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
break;
if (num > 1) {
GST_ERROR_OBJECT (common, "Invalid ContentEncodingType %"
G_GUINT64_FORMAT, num);
ret = GST_FLOW_ERROR;
break;
} else if (num != 0) {
GST_ERROR_OBJECT (common, "Encrypted tracks are not supported yet");
ret = GST_FLOW_ERROR;
break;
}
GST_DEBUG_OBJECT (common, "ContentEncodingType: %" G_GUINT64_FORMAT,
num);
enc.type = num;
break;
}
case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
break;
while (ret == GST_FLOW_OK &&
gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
break;
switch (id) {
case GST_MATROSKA_ID_CONTENTCOMPALGO:{
guint64 num;
if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
break;
}
if (num > 3) {
GST_ERROR_OBJECT (common, "Invalid ContentCompAlgo %"
G_GUINT64_FORMAT, num);
ret = GST_FLOW_ERROR;
break;
}
GST_DEBUG_OBJECT (common, "ContentCompAlgo: %" G_GUINT64_FORMAT,
num);
enc.comp_algo = num;
break;
}
case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
guint8 *data;
guint64 size;
if ((ret =
gst_ebml_read_binary (ebml, &id, &data,
&size)) != GST_FLOW_OK) {
break;
}
enc.comp_settings = data;
enc.comp_settings_length = size;
GST_DEBUG_OBJECT (common,
"ContentCompSettings of size %" G_GUINT64_FORMAT, size);
break;
}
default:
GST_WARNING_OBJECT (common,
"Unknown ContentCompression subelement 0x%x - ignoring", id);
ret = gst_ebml_read_skip (ebml);
break;
}
}
DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
break;
}
case GST_MATROSKA_ID_CONTENTENCRYPTION:
GST_ERROR_OBJECT (common, "Encrypted tracks not yet supported");
gst_ebml_read_skip (ebml);
ret = GST_FLOW_ERROR;
break;
default:
GST_WARNING_OBJECT (common,
"Unknown ContentEncoding subelement 0x%x - ignoring", id);
ret = gst_ebml_read_skip (ebml);
break;
}
}
DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
return ret;
/* TODO: Check if the combination of values is valid */
g_array_append_val (context->encodings, enc);
return ret;
}
GstFlowReturn
gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
GstEbmlRead * ebml, GstMatroskaTrackContext * context)
{
GstFlowReturn ret;
guint32 id;
DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
return ret;
}
context->encodings =
g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
break;
switch (id) {
case GST_MATROSKA_ID_CONTENTENCODING:
ret = gst_matroska_read_common_read_track_encoding (common, ebml,
context);
break;
default:
GST_WARNING_OBJECT (common,
"Unknown ContentEncodings subelement 0x%x - ignoring", id);
ret = gst_ebml_read_skip (ebml);
break;
}
}
DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
return ret;
/* Sort encodings according to their order */
g_array_sort (context->encodings,
(GCompareFunc) gst_matroska_read_common_encoding_cmp);
return gst_matroska_decode_content_encodings (context->encodings);
}
/* call with object lock held */
void
gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
GstClockTime time, gboolean full)
{
gint i;
GST_DEBUG_OBJECT (common, "resetting stream state");
g_assert (common->src->len == common->num_streams);
for (i = 0; i < common->src->len; i++) {
GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
context->pos = time;
context->set_discont = TRUE;
context->eos = FALSE;
context->from_time = GST_CLOCK_TIME_NONE;
if (full)
context->last_flow = GST_FLOW_OK;
if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
GstMatroskaTrackVideoContext *videocontext =
(GstMatroskaTrackVideoContext *) context;
/* demux object lock held by caller */
videocontext->earliest_time = GST_CLOCK_TIME_NONE;
}
}
}
gboolean
gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
guint64 num)
{
gint i;
g_assert (common->src->len == common->num_streams);
for (i = 0; i < common->src->len; i++) {
GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
if (context->num == num)
return FALSE;
}
return TRUE;
}

View file

@ -25,6 +25,7 @@
#include <glib.h>
#include <gst/gst.h>
#include <gst/base/gstadapter.h>
#include "matroska-ids.h"
@ -44,6 +45,7 @@ typedef struct _GstMatroskaReadCommon {
gint element_index_writer_id;
/* pads */
GstPad *sinkpad;
GPtrArray *src;
guint num_streams;
@ -61,18 +63,55 @@ typedef struct _GstMatroskaReadCommon {
/* timescale in the file */
guint64 time_scale;
GstTagList *global_tags;
/* pull mode caching */
GstBuffer *cached_buffer;
/* push and pull mode */
guint64 offset;
/* push based mode usual suspects */
GstAdapter *adapter;
} GstMatroskaReadCommon;
GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings);
gboolean gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
guint8 ** data_out, guint * size_out,
GstMatroskaTrackCompressionAlgorithm algo);
gboolean gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free);
gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
gpointer user_data);
GstMatroskaIndex * gst_matroska_read_common_do_index_seek (
GstMatroskaReadCommon * common, GstMatroskaTrackContext * track, gint64
seek_pos, GArray ** _index, gint * _entry_index);
void gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
GstElement * el, GstTagList * taglist);
gint64 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common);
GstMatroskaTrackContext * gst_matroska_read_common_get_seek_track (
GstMatroskaReadCommon * common, GstMatroskaTrackContext * track);
GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon *
common, GstEbmlRead * ebml);
GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon *
common, GstEbmlRead * ebml);
GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon *
common, GstEbmlRead * ebml, const gchar * parent_name, guint id);
GstFlowReturn gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon *
common, guint64 offset, guint size, GstBuffer ** p_buf, guint8 ** bytes);
GstFlowReturn gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon *
common, GstElement * el, guint32 * _id, guint64 * _length, guint *
_needed);
GstFlowReturn gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon *
common, GstElement * el, guint32 * _id, guint64 * _length, guint *
_needed);
gint gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
guint track_num);
GstFlowReturn gst_matroska_read_common_read_track_encodings (
GstMatroskaReadCommon * common, GstEbmlRead * ebml,
GstMatroskaTrackContext * context);
void gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
GstClockTime time, gboolean full);
gboolean gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon *
common, guint64 num);
G_END_DECLS

View file

@ -64,12 +64,14 @@ enum
#define DEFAULT_AUTOSCAN FALSE
#define DEFAULT_BOUNDARY NULL
#define DEFAULT_SINGLE_STREAM FALSE
enum
{
PROP_0,
PROP_AUTOSCAN,
PROP_BOUNDARY
PROP_BOUNDARY,
PROP_SINGLE_STREAM
};
static GstStaticPadTemplate multipart_demux_src_template_factory =
@ -165,6 +167,20 @@ gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
"Try to autofind the prefix (deprecated unused, see boundary)",
DEFAULT_AUTOSCAN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstMultipartDemux::single-stream:
*
* Assume that there is only one stream whose content-type will
* not change and emit no-more-pads as soon as the first boundary
* content is parsed, decoded, and pads are linked.
*
* Since: 0.10.30
*/
g_object_class_install_property (gobject_class, PROP_SINGLE_STREAM,
g_param_spec_boolean ("single-stream", "Single Stream",
"Assume that there is only one stream whose content-type will not change and emit no-more-pads as soon as the first boundary content is parsed, decoded, and pads are linked",
DEFAULT_SINGLE_STREAM, G_PARAM_READWRITE));
/* populate gst names and mime types pairs */
klass->gstnames = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; gstnames[i].key; i++) {
@ -194,6 +210,7 @@ gst_multipart_demux_init (GstMultipartDemux * multipart,
multipart->header_completed = FALSE;
multipart->scanpos = 0;
multipart->autoscan = DEFAULT_AUTOSCAN;
multipart->singleStream = DEFAULT_SINGLE_STREAM;
}
static void
@ -324,6 +341,10 @@ gst_multipart_find_pad_by_mime (GstMultipartDemux * demux, gchar * mime,
*created = TRUE;
}
if (demux->singleStream) {
gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
}
return mppad;
}
}
@ -664,6 +685,9 @@ gst_multipart_set_property (GObject * object, guint prop_id,
case PROP_AUTOSCAN:
filter->autoscan = g_value_get_boolean (value);
break;
case PROP_SINGLE_STREAM:
filter->singleStream = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -686,6 +710,9 @@ gst_multipart_get_property (GObject * object, guint prop_id,
case PROP_AUTOSCAN:
g_value_set_boolean (value, filter->autoscan);
break;
case PROP_SINGLE_STREAM:
g_value_set_boolean (value, filter->singleStream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -84,6 +84,8 @@ struct _GstMultipartDemux
/* Index inside the current data when manually looking for the boundary */
gint scanpos;
gboolean singleStream;
};
struct _GstMultipartDemuxClass

View file

@ -112,7 +112,8 @@ gst_rtp_mp4v_pay_class_init (GstRtpMP4VPayClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SEND_CONFIG,
g_param_spec_boolean ("send-config", "Send Config",
"Send the config parameters in RTP packets as well",
"Send the config parameters in RTP packets as well(deprecated "
"see config-interval)",
DEFAULT_SEND_CONFIG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFER_LIST,
@ -491,7 +492,7 @@ gst_rtp_mp4v_pay_handle_buffer (GstBaseRTPPayload * basepayload,
flush = gst_rtp_mp4v_pay_depay_data (rtpmp4vpay, data, size, &strip, &vopi);
if (strip) {
/* strip off config if requested */
if (!rtpmp4vpay->send_config) {
if (!(rtpmp4vpay->config_interval > 0)) {
GstBuffer *subbuf;
GST_LOG_OBJECT (rtpmp4vpay, "stripping config at %d, size %d", strip,
@ -511,8 +512,7 @@ gst_rtp_mp4v_pay_handle_buffer (GstBaseRTPPayload * basepayload,
}
/* there is a config request, see if we need to insert it */
if (rtpmp4vpay->send_config && vopi && (rtpmp4vpay->config_interval > 0) &&
rtpmp4vpay->config) {
if (vopi && (rtpmp4vpay->config_interval > 0) && rtpmp4vpay->config) {
if (rtpmp4vpay->last_config != -1) {
guint64 diff;
@ -629,6 +629,10 @@ gst_rtp_mp4v_pay_set_property (GObject * object, guint prop_id,
switch (prop_id) {
case ARG_SEND_CONFIG:
rtpmp4vpay->send_config = g_value_get_boolean (value);
/* send the configuration once every minute */
if (rtpmp4vpay->send_config && !(rtpmp4vpay->config_interval > 0)) {
rtpmp4vpay->config_interval = 60;
}
break;
case ARG_BUFFER_LIST:
rtpmp4vpay->buffer_list = g_value_get_boolean (value);

View file

@ -4460,11 +4460,14 @@ next:
/* ok, a response is good */
GST_DEBUG_OBJECT (src, "received response message");
break;
default:
case GST_RTSP_MESSAGE_DATA:
/* get next response */
GST_DEBUG_OBJECT (src, "ignoring data response message");
goto next;
default:
GST_WARNING_OBJECT (src, "ignoring unknown message type %d",
response->type);
goto next;
}
thecode = response->type_data.response.code;

View file

@ -517,7 +517,7 @@ no_select:
/* patch pktdata and len when stripping off the headers */
if (G_UNLIKELY (udpsrc->skip_first_bytes != 0)) {
if (G_UNLIKELY (readsize <= udpsrc->skip_first_bytes))
if (G_UNLIKELY (readsize < udpsrc->skip_first_bytes))
goto skip_error;
offset += udpsrc->skip_first_bytes;

View file

@ -373,7 +373,12 @@ gst_ximageutil_ximage_new (GstXContext * xcontext,
xcontext->visual, xcontext->depth,
ZPixmap, NULL, &meta->SHMInfo, meta->width, meta->height);
if (!meta->ximage) {
goto beach;
GST_WARNING_OBJECT (parent,
"could not XShmCreateImage a %dx%d image", meta->width, meta->height);
/* Retry without XShm */
xcontext->use_xshm = FALSE;
goto no_xshm;
}
/* we have to use the returned bytes_per_line for our shm size */
@ -398,6 +403,7 @@ gst_ximageutil_ximage_new (GstXContext * xcontext,
XSync (xcontext->disp, FALSE);
} else
no_xshm:
#endif /* HAVE_XSHM */
{
meta->ximage = XCreateImage (xcontext->disp,