mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/cairo/gsttextoverlay.c ext/pulse/pulseaudiosink.c gst/audioparsers/gstaacparse.c gst/avi/gstavimux.c gst/flv/gstflvmux.c gst/interleave/interleave.c gst/isomp4/gstqtmux.c gst/matroska/matroska-demux.c gst/matroska/matroska-mux.c gst/matroska/matroska-mux.h gst/matroska/matroska-read-common.c gst/multifile/gstmultifilesink.c gst/multipart/multipartmux.c gst/shapewipe/gstshapewipe.c gst/smpte/gstsmpte.c gst/udp/gstmultiudpsink.c gst/videobox/gstvideobox.c gst/videocrop/gstaspectratiocrop.c gst/videomixer/videomixer.c gst/videomixer/videomixer2.c gst/wavparse/gstwavparse.c po/ja.po po/lv.po po/sr.po tests/check/Makefile.am tests/check/elements/qtmux.c tests/check/elements/rgvolume.c
This commit is contained in:
commit
93e3ed5a86
85 changed files with 2634 additions and 680 deletions
|
@ -26,7 +26,8 @@ DISTCLEANFILES = _stdint.h
|
|||
|
||||
noinst_HEADERS = \
|
||||
gst-libs/gst/gettext.h \
|
||||
gst-libs/gst/gst-i18n-plugin.h
|
||||
gst-libs/gst/gst-i18n-plugin.h \
|
||||
gst-libs/gst/glib-compat-private.h
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 -I common/m4
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ AC_CHECK_TYPE([struct ip_mreqn], [
|
|||
dnl *** checks for dependency libraries ***
|
||||
|
||||
dnl GLib is required
|
||||
AG_GST_GLIB_CHECK([2.20])
|
||||
AG_GST_GLIB_CHECK([2.24])
|
||||
PKG_CHECK_MODULES(GIO, [ gio-2.0 >= 2.20 ], , AC_MSG_ERROR([gio is required]))
|
||||
|
||||
dnl Orc
|
||||
|
@ -438,6 +438,12 @@ int main ()
|
|||
AC_SUBST(HAVE_DIRECTSOUND)
|
||||
])
|
||||
|
||||
dnl *** Win32 WaveOut ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_WAVEFORM, true)
|
||||
AG_GST_CHECK_FEATURE(WAVEFORM, [Win32 WaveForm], waveformsink, [
|
||||
AC_CHECK_HEADER(mmsystem.h, HAVE_WAVEFORM="yes", HAVE_WAVEFORM="no", [#include <windows.h>])
|
||||
])
|
||||
|
||||
dnl *** OSS audio *** (Linux, *BSD)
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_OSS, true)
|
||||
AG_GST_CHECK_FEATURE(OSS, [OSS audio], ossaudio, [
|
||||
|
@ -1005,6 +1011,7 @@ AM_CONDITIONAL(USE_SOUP, false)
|
|||
AM_CONDITIONAL(USE_SPEEX, false)
|
||||
AM_CONDITIONAL(USE_SUNAUDIO, false)
|
||||
AM_CONDITIONAL(USE_TAGLIB, false)
|
||||
AM_CONDITIONAL(USE_WAVEFORM, false)
|
||||
AM_CONDITIONAL(USE_WAVPACK, false)
|
||||
AM_CONDITIONAL(USE_X, false)
|
||||
AM_CONDITIONAL(USE_XSHM, false)
|
||||
|
|
|
@ -106,7 +106,7 @@ static gboolean gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps);
|
|||
static GstPadLinkReturn gst_text_overlay_text_pad_linked (GstPad * pad,
|
||||
GstPad * peer);
|
||||
static void gst_text_overlay_text_pad_unlinked (GstPad * pad);
|
||||
static GstFlowReturn gst_text_overlay_collected (GstCollectPads * pads,
|
||||
static GstFlowReturn gst_text_overlay_collected (GstCollectPads2 * pads,
|
||||
gpointer data);
|
||||
static void gst_text_overlay_finalize (GObject * object);
|
||||
static void gst_text_overlay_font_init (GstCairoTextOverlay * overlay);
|
||||
|
@ -215,7 +215,7 @@ gst_text_overlay_finalize (GObject * object)
|
|||
{
|
||||
GstCairoTextOverlay *overlay = GST_CAIRO_TEXT_OVERLAY (object);
|
||||
|
||||
gst_collect_pads_stop (overlay->collect);
|
||||
gst_collect_pads2_stop (overlay->collect);
|
||||
gst_object_unref (overlay->collect);
|
||||
|
||||
g_free (overlay->text_fill_image);
|
||||
|
@ -279,16 +279,16 @@ gst_text_overlay_init (GstCairoTextOverlay * overlay,
|
|||
overlay->fps_n = 0;
|
||||
overlay->fps_d = 1;
|
||||
|
||||
overlay->collect = gst_collect_pads_new ();
|
||||
overlay->collect = gst_collect_pads2_new ();
|
||||
|
||||
gst_collect_pads_set_function (overlay->collect,
|
||||
gst_collect_pads2_set_function (overlay->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_text_overlay_collected), overlay);
|
||||
|
||||
overlay->video_collect_data = gst_collect_pads_add_pad (overlay->collect,
|
||||
overlay->video_sinkpad, sizeof (GstCollectData), NULL);
|
||||
overlay->video_collect_data = gst_collect_pads2_add_pad (overlay->collect,
|
||||
overlay->video_sinkpad, sizeof (GstCollectData2));
|
||||
|
||||
/* FIXME: hacked way to override/extend the event function of
|
||||
* GstCollectPads; because it sets its own event function giving the
|
||||
* GstCollectPads2; 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);
|
||||
|
@ -640,8 +640,8 @@ gst_text_overlay_text_pad_linked (GstPad * pad, GstPad * peer)
|
|||
GST_DEBUG_OBJECT (overlay, "Text pad linked");
|
||||
|
||||
if (overlay->text_collect_data == NULL) {
|
||||
overlay->text_collect_data = gst_collect_pads_add_pad (overlay->collect,
|
||||
overlay->text_sinkpad, sizeof (GstCollectData), NULL);
|
||||
overlay->text_collect_data = gst_collect_pads2_add_pad (overlay->collect,
|
||||
overlay->text_sinkpad, sizeof (GstCollectData2));
|
||||
}
|
||||
|
||||
overlay->need_render = TRUE;
|
||||
|
@ -660,7 +660,7 @@ gst_text_overlay_text_pad_unlinked (GstPad * pad)
|
|||
GST_DEBUG_OBJECT (overlay, "Text pad unlinked");
|
||||
|
||||
if (overlay->text_collect_data) {
|
||||
gst_collect_pads_remove_pad (overlay->collect, overlay->text_sinkpad);
|
||||
gst_collect_pads2_remove_pad (overlay->collect, overlay->text_sinkpad);
|
||||
overlay->text_collect_data = NULL;
|
||||
}
|
||||
|
||||
|
@ -807,7 +807,7 @@ gst_text_overlay_pop_video (GstCairoTextOverlay * overlay)
|
|||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_collect_pads_pop (overlay->collect, overlay->video_collect_data);
|
||||
buf = gst_collect_pads2_pop (overlay->collect, overlay->video_collect_data);
|
||||
g_return_if_fail (buf != NULL);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
@ -818,7 +818,7 @@ gst_text_overlay_pop_text (GstCairoTextOverlay * overlay)
|
|||
GstBuffer *buf;
|
||||
|
||||
if (overlay->text_collect_data) {
|
||||
buf = gst_collect_pads_pop (overlay->collect, overlay->text_collect_data);
|
||||
buf = gst_collect_pads2_pop (overlay->collect, overlay->text_collect_data);
|
||||
g_return_if_fail (buf != NULL);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ gst_text_overlay_pop_text (GstCairoTextOverlay * overlay)
|
|||
|
||||
/* This function is called when there is data on all pads */
|
||||
static GstFlowReturn
|
||||
gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
|
||||
gst_text_overlay_collected (GstCollectPads2 * pads, gpointer data)
|
||||
{
|
||||
GstCairoTextOverlay *overlay;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
@ -842,14 +842,14 @@ gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
|
|||
|
||||
GST_DEBUG ("Collecting");
|
||||
|
||||
video_frame = gst_collect_pads_peek (overlay->collect,
|
||||
video_frame = gst_collect_pads2_peek (overlay->collect,
|
||||
overlay->video_collect_data);
|
||||
|
||||
/* send EOS if video stream EOSed regardless of text stream */
|
||||
if (video_frame == NULL) {
|
||||
GST_DEBUG ("Video stream at EOS");
|
||||
if (overlay->text_collect_data) {
|
||||
text_buf = gst_collect_pads_pop (overlay->collect,
|
||||
text_buf = gst_collect_pads2_pop (overlay->collect,
|
||||
overlay->text_collect_data);
|
||||
}
|
||||
gst_pad_push_event (overlay->srcpad, gst_event_new_eos ());
|
||||
|
@ -892,7 +892,7 @@ gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
|
|||
goto done;
|
||||
}
|
||||
|
||||
text_buf = gst_collect_pads_peek (overlay->collect,
|
||||
text_buf = gst_collect_pads2_peek (overlay->collect,
|
||||
overlay->text_collect_data);
|
||||
|
||||
/* just push the video frame if the text stream has EOSed */
|
||||
|
@ -1004,7 +1004,7 @@ gst_text_overlay_video_event (GstPad * pad, GstEvent * event)
|
|||
gst_pad_push_event (overlay->srcpad, event);
|
||||
}
|
||||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
ret = overlay->collect_event (pad, event);
|
||||
gst_object_unref (overlay);
|
||||
return ret;
|
||||
|
@ -1018,12 +1018,12 @@ gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
|
|||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_collect_pads_start (overlay->collect);
|
||||
gst_collect_pads2_start (overlay->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
/* need to unblock the collectpads before calling the
|
||||
* parent change_state so that streaming can finish */
|
||||
gst_collect_pads_stop (overlay->collect);
|
||||
gst_collect_pads2_stop (overlay->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#define __GST_CAIRO_TEXT_OVERLAY_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -45,9 +45,9 @@ struct _GstCairoTextOverlay {
|
|||
GstPad *text_sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
GstCollectPads *collect;
|
||||
GstCollectData *video_collect_data;
|
||||
GstCollectData *text_collect_data;
|
||||
GstCollectPads2 *collect;
|
||||
GstCollectData2 *video_collect_data;
|
||||
GstCollectData2 *text_collect_data;
|
||||
GstPadEventFunction collect_event;
|
||||
|
||||
gint width;
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gstflacdec.h"
|
||||
|
|
|
@ -271,7 +271,7 @@ gst_gdk_pixbuf_sink_set_caps (GstBaseSink * basesink, GstCaps * caps)
|
|||
|
||||
GST_INFO_OBJECT (sink, "format : %d", fmt);
|
||||
GST_INFO_OBJECT (sink, "width x height : %d x %d", w, h);
|
||||
GST_INFO_OBJECT (sink, "pixel-aspect-ratio : %d/%d", par_d, par_n);
|
||||
GST_INFO_OBJECT (sink, "pixel-aspect-ratio : %d/%d", par_n, par_d);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ gst_gdk_pixbuf_sink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf,
|
|||
* The structure will take its own ref to the pixbuf. */
|
||||
s = gst_structure_new (msg_name,
|
||||
"pixbuf", GDK_TYPE_PIXBUF, pixbuf,
|
||||
"pixel-aspect-ratio", GST_TYPE_FRACTION, sink->par_d, sink->par_n,
|
||||
"pixel-aspect-ratio", GST_TYPE_FRACTION, sink->par_n, sink->par_d,
|
||||
NULL);
|
||||
|
||||
msg = gst_message_new_element (GST_OBJECT_CAST (sink), s);
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "gstjackaudioclient.h"
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug);
|
||||
#define GST_CAT_DEFAULT gst_jack_audio_client_debug
|
||||
|
||||
|
|
|
@ -329,7 +329,11 @@ gst_jack_ring_buffer_open_device (GstAudioRingBuffer * buf)
|
|||
|
||||
GST_DEBUG_OBJECT (sink, "open");
|
||||
|
||||
name = g_get_application_name ();
|
||||
if (sink->client_name) {
|
||||
name = sink->client_name;
|
||||
} else {
|
||||
name = g_get_application_name ();
|
||||
}
|
||||
if (!name)
|
||||
name = "GStreamer";
|
||||
|
||||
|
@ -648,8 +652,9 @@ enum
|
|||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
|
||||
#define DEFAULT_PROP_SERVER NULL
|
||||
#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
|
||||
#define DEFAULT_PROP_SERVER NULL
|
||||
#define DEFAULT_PROP_CLIENT_NAME NULL
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -657,6 +662,7 @@ enum
|
|||
PROP_CONNECT,
|
||||
PROP_SERVER,
|
||||
PROP_CLIENT,
|
||||
PROP_CLIENT_NAME,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -705,6 +711,19 @@ gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass)
|
|||
"The Jack server to connect to (NULL = default)",
|
||||
DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstJackAudioSink:client-name
|
||||
*
|
||||
* The client name to use.
|
||||
*
|
||||
* Since: 0.10.31
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
|
||||
g_param_spec_string ("client-name", "Client name",
|
||||
"The client name of the Jack instance (NULL = default)",
|
||||
DEFAULT_PROP_CLIENT_NAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CLIENT,
|
||||
g_param_spec_boxed ("client", "JackClient", "Handle for jack client",
|
||||
GST_TYPE_JACK_CLIENT,
|
||||
|
@ -738,6 +757,7 @@ gst_jack_audio_sink_init (GstJackAudioSink * sink)
|
|||
sink->jclient = NULL;
|
||||
sink->ports = NULL;
|
||||
sink->port_count = 0;
|
||||
sink->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
|
||||
sink->buffers = NULL;
|
||||
}
|
||||
|
||||
|
@ -747,6 +767,12 @@ gst_jack_audio_sink_dispose (GObject * object)
|
|||
GstJackAudioSink *sink = GST_JACK_AUDIO_SINK (object);
|
||||
|
||||
gst_caps_replace (&sink->caps, NULL);
|
||||
|
||||
if (sink->client_name != NULL) {
|
||||
g_free (sink->client_name);
|
||||
sink->client_name = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -759,6 +785,10 @@ gst_jack_audio_sink_set_property (GObject * object, guint prop_id,
|
|||
sink = GST_JACK_AUDIO_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CLIENT_NAME:
|
||||
g_free (sink->client_name);
|
||||
sink->client_name = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_CONNECT:
|
||||
sink->connect = g_value_get_enum (value);
|
||||
break;
|
||||
|
@ -787,6 +817,9 @@ gst_jack_audio_sink_get_property (GObject * object, guint prop_id,
|
|||
sink = GST_JACK_AUDIO_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CLIENT_NAME:
|
||||
g_value_set_string (value, sink->client_name);
|
||||
break;
|
||||
case PROP_CONNECT:
|
||||
g_value_set_enum (value, sink->connect);
|
||||
break;
|
||||
|
|
|
@ -58,6 +58,7 @@ struct _GstJackAudioSink {
|
|||
GstJackConnect connect;
|
||||
gchar *server;
|
||||
jack_client_t *jclient;
|
||||
gchar *client_name;
|
||||
|
||||
/* our client */
|
||||
GstJackAudioClient *client;
|
||||
|
|
|
@ -336,7 +336,11 @@ gst_jack_ring_buffer_open_device (GstAudioRingBuffer * buf)
|
|||
|
||||
GST_DEBUG_OBJECT (src, "open");
|
||||
|
||||
name = g_get_application_name ();
|
||||
if (src->client_name) {
|
||||
name = src->client_name;
|
||||
} else {
|
||||
name = g_get_application_name ();
|
||||
}
|
||||
if (!name)
|
||||
name = "GStreamer";
|
||||
|
||||
|
@ -651,8 +655,9 @@ enum
|
|||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
|
||||
#define DEFAULT_PROP_SERVER NULL
|
||||
#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
|
||||
#define DEFAULT_PROP_SERVER NULL
|
||||
#define DEFAULT_PROP_CLIENT_NAME NULL
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -660,6 +665,7 @@ enum
|
|||
PROP_CONNECT,
|
||||
PROP_SERVER,
|
||||
PROP_CLIENT,
|
||||
PROP_CLIENT_NAME,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -726,6 +732,19 @@ gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass)
|
|||
"The Jack server to connect to (NULL = default)",
|
||||
DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstJackAudioSrc:client-name
|
||||
*
|
||||
* The client name to use.
|
||||
*
|
||||
* Since: 0.10.31
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
|
||||
g_param_spec_string ("client-name", "Client name",
|
||||
"The client name of the Jack instance (NULL = default)",
|
||||
DEFAULT_PROP_CLIENT_NAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CLIENT,
|
||||
g_param_spec_boxed ("client", "JackClient", "Handle for jack client",
|
||||
GST_TYPE_JACK_CLIENT,
|
||||
|
@ -765,6 +784,7 @@ gst_jack_audio_src_init (GstJackAudioSrc * src)
|
|||
src->ports = NULL;
|
||||
src->port_count = 0;
|
||||
src->buffers = NULL;
|
||||
src->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -773,6 +793,12 @@ gst_jack_audio_src_dispose (GObject * object)
|
|||
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
|
||||
|
||||
gst_caps_replace (&src->caps, NULL);
|
||||
|
||||
if (src->client_name != NULL) {
|
||||
g_free (src->client_name);
|
||||
src->client_name = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -783,6 +809,10 @@ gst_jack_audio_src_set_property (GObject * object, guint prop_id,
|
|||
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CLIENT_NAME:
|
||||
g_free (src->client_name);
|
||||
src->client_name = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_CONNECT:
|
||||
src->connect = g_value_get_enum (value);
|
||||
break;
|
||||
|
@ -809,6 +839,9 @@ gst_jack_audio_src_get_property (GObject * object, guint prop_id,
|
|||
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CLIENT_NAME:
|
||||
g_value_set_string (value, src->client_name);
|
||||
break;
|
||||
case PROP_CONNECT:
|
||||
g_value_set_enum (value, src->connect);
|
||||
break;
|
||||
|
|
|
@ -75,6 +75,7 @@ struct _GstJackAudioSrc
|
|||
GstJackConnect connect;
|
||||
gchar *server;
|
||||
jack_client_t *jclient;
|
||||
gchar *client_name;
|
||||
|
||||
/* our client */
|
||||
GstJackAudioClient *client;
|
||||
|
|
|
@ -761,7 +761,7 @@ gst_jpeg_dec_getcaps (GstPad * pad, GstCaps * filter)
|
|||
templ_caps = gst_pad_get_pad_template_caps (pad);
|
||||
caps = gst_caps_intersect_full (peer_caps, templ_caps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
|
||||
gst_caps_unref (peer_caps);
|
||||
gst_object_unref (peer);
|
||||
} else {
|
||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
|
||||
#include <gst/pbutils/pbutils.h> /* only used for GST_PLUGINS_BASE_VERSION_* */
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
#include "pulsesink.h"
|
||||
#include "pulseutil.h"
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <gst/base/gstbasesink.h>
|
||||
#include "gstsouphttpclientsink.h"
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (souphttpclientsink_dbg);
|
||||
#define GST_CAT_DEFAULT souphttpclientsink_dbg
|
||||
|
||||
|
@ -445,6 +447,20 @@ gst_soup_http_client_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
|
|||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
thread_ready_idle_cb (gpointer data)
|
||||
{
|
||||
GstSoupHttpClientSink *souphttpsink = GST_SOUP_HTTP_CLIENT_SINK (data);
|
||||
|
||||
GST_LOG_OBJECT (souphttpsink, "thread ready");
|
||||
|
||||
g_mutex_lock (souphttpsink->mutex);
|
||||
g_cond_signal (souphttpsink->cond);
|
||||
g_mutex_unlock (souphttpsink->mutex);
|
||||
|
||||
return FALSE; /* only run once */
|
||||
}
|
||||
|
||||
static gpointer
|
||||
thread_func (gpointer ptr)
|
||||
{
|
||||
|
@ -452,7 +468,6 @@ thread_func (gpointer ptr)
|
|||
|
||||
GST_DEBUG ("thread start");
|
||||
|
||||
souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
|
||||
g_main_loop_run (souphttpsink->loop);
|
||||
|
||||
GST_DEBUG ("thread quit");
|
||||
|
@ -468,12 +483,35 @@ gst_soup_http_client_sink_start (GstBaseSink * sink)
|
|||
if (souphttpsink->prop_session) {
|
||||
souphttpsink->session = souphttpsink->prop_session;
|
||||
} else {
|
||||
GSource *source;
|
||||
GError *error = NULL;
|
||||
|
||||
souphttpsink->context = g_main_context_new ();
|
||||
|
||||
/* set up idle source to signal when the main loop is running and
|
||||
* it's safe for ::stop() to call g_main_loop_quit() */
|
||||
source = g_idle_source_new ();
|
||||
g_source_set_callback (source, thread_ready_idle_cb, sink, NULL);
|
||||
g_source_attach (source, souphttpsink->context);
|
||||
g_source_unref (source);
|
||||
|
||||
souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
|
||||
|
||||
g_mutex_lock (souphttpsink->mutex);
|
||||
|
||||
/* FIXME: error handling */
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
souphttpsink->thread = g_thread_create (thread_func, souphttpsink,
|
||||
TRUE, &error);
|
||||
#else
|
||||
souphttpsink->thread = g_thread_try_new ("souphttpclientsink-thread",
|
||||
thread_func, souphttpsink, &error);
|
||||
#endif
|
||||
|
||||
GST_LOG_OBJECT (souphttpsink, "waiting for main loop thread to start up");
|
||||
g_cond_wait (souphttpsink->cond, souphttpsink->mutex);
|
||||
g_mutex_unlock (souphttpsink->mutex);
|
||||
GST_LOG_OBJECT (souphttpsink, "main loop thread running");
|
||||
|
||||
souphttpsink->session =
|
||||
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
|
|
135
gst-libs/gst/glib-compat-private.h
Normal file
135
gst-libs/gst/glib-compat-private.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* glib-compat.c
|
||||
* Functions copied from glib 2.10
|
||||
*
|
||||
* Copyright 2005 David Schleef <ds@schleef.org>
|
||||
*
|
||||
* 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 __GLIB_COMPAT_PRIVATE_H__
|
||||
#define __GLIB_COMPAT_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,25,0)
|
||||
|
||||
#if defined (_MSC_VER) && !defined(_WIN64)
|
||||
typedef struct _stat32 GStatBuf;
|
||||
#else
|
||||
typedef struct stat GStatBuf;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if GLIB_CHECK_VERSION(2,26,0)
|
||||
#define GLIB_HAS_GDATETIME
|
||||
#endif
|
||||
|
||||
/* See bug #651514 */
|
||||
#if GLIB_CHECK_VERSION(2,29,5)
|
||||
#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
|
||||
g_atomic_pointer_compare_and_exchange ((a),(b),(c))
|
||||
#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
|
||||
g_atomic_int_compare_and_exchange ((a),(b),(c))
|
||||
#else
|
||||
#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
|
||||
g_atomic_pointer_compare_and_exchange ((volatile gpointer *)(a),(b),(c))
|
||||
#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
|
||||
g_atomic_int_compare_and_exchange ((volatile int *)(a),(b),(c))
|
||||
#endif
|
||||
|
||||
/* See bug #651514 */
|
||||
#if GLIB_CHECK_VERSION(2,29,5)
|
||||
#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_add ((a),(b))
|
||||
#else
|
||||
#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_exchange_and_add ((a),(b))
|
||||
#endif
|
||||
|
||||
/* copies */
|
||||
|
||||
#if GLIB_CHECK_VERSION (2, 31, 0)
|
||||
#define g_mutex_new gst_g_mutex_new
|
||||
static inline GMutex *
|
||||
gst_g_mutex_new (void)
|
||||
{
|
||||
GMutex *mutex = g_slice_new (GMutex);
|
||||
g_mutex_init (mutex);
|
||||
return mutex;
|
||||
}
|
||||
#define g_mutex_free gst_g_mutex_free
|
||||
static inline void
|
||||
gst_g_mutex_free (GMutex *mutex)
|
||||
{
|
||||
g_mutex_clear (mutex);
|
||||
g_slice_free (GMutex, mutex);
|
||||
}
|
||||
#define g_static_rec_mutex_init gst_g_static_rec_mutex_init
|
||||
static inline void
|
||||
gst_g_static_rec_mutex_init (GStaticRecMutex *mutex)
|
||||
{
|
||||
static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
|
||||
|
||||
*mutex = init_mutex;
|
||||
}
|
||||
#define g_cond_new gst_g_cond_new
|
||||
static inline GCond *
|
||||
gst_g_cond_new (void)
|
||||
{
|
||||
GCond *cond = g_slice_new (GCond);
|
||||
g_cond_init (cond);
|
||||
return cond;
|
||||
}
|
||||
#define g_cond_free gst_g_cond_free
|
||||
static inline void
|
||||
gst_g_cond_free (GCond *cond)
|
||||
{
|
||||
g_cond_clear (cond);
|
||||
g_slice_free (GCond, cond);
|
||||
}
|
||||
#define g_cond_timed_wait gst_g_cond_timed_wait
|
||||
static inline gboolean
|
||||
gst_g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *abs_time)
|
||||
{
|
||||
gint64 end_time;
|
||||
|
||||
if (abs_time == NULL) {
|
||||
g_cond_wait (cond, mutex);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
end_time = abs_time->tv_sec;
|
||||
end_time *= 1000000;
|
||||
end_time += abs_time->tv_usec;
|
||||
|
||||
/* would be nice if we had clock_rtoffset, but that didn't seem to
|
||||
* make it into the kernel yet...
|
||||
*/
|
||||
/* if CLOCK_MONOTONIC is not defined then g_get_montonic_time() and
|
||||
* g_get_real_time() are returning the same clock and we'd add ~0
|
||||
*/
|
||||
end_time += g_get_monotonic_time () - g_get_real_time ();
|
||||
return g_cond_wait_until (cond, mutex, end_time);
|
||||
}
|
||||
#endif /* GLIB_CHECK_VERSION (2, 31, 0) */
|
||||
|
||||
/* adaptations */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
|
@ -145,6 +145,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
static GstStaticCaps gst_alpha_alpha_caps =
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
|
||||
|
||||
/* FIXME: why do we need our own lock for this? */
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
#define GST_ALPHA_LOCK(alpha) G_STMT_START { \
|
||||
GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
|
||||
g_static_mutex_lock (&alpha->lock); \
|
||||
|
@ -155,6 +157,18 @@ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
|
|||
GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
|
||||
g_static_mutex_unlock (&alpha->lock); \
|
||||
} G_STMT_END
|
||||
#else
|
||||
#define GST_ALPHA_LOCK(alpha) G_STMT_START { \
|
||||
GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
|
||||
g_mutex_lock (&alpha->lock); \
|
||||
GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
|
||||
} G_STMT_END
|
||||
|
||||
#define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
|
||||
GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
|
||||
g_mutex_unlock (&alpha->lock); \
|
||||
} G_STMT_END
|
||||
#endif
|
||||
|
||||
static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
|
||||
|
@ -296,7 +310,11 @@ gst_alpha_init (GstAlpha * alpha)
|
|||
alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
|
||||
alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
g_static_mutex_init (&alpha->lock);
|
||||
#else
|
||||
g_mutex_init (&alpha->lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -304,7 +322,11 @@ gst_alpha_finalize (GObject * object)
|
|||
{
|
||||
GstAlpha *alpha = GST_ALPHA (object);
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
g_static_mutex_free (&alpha->lock);
|
||||
#else
|
||||
g_mutex_clear (&alpha->lock);
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,11 @@ struct _GstAlpha
|
|||
/* <private> */
|
||||
|
||||
/* caps */
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
GStaticMutex lock;
|
||||
#else
|
||||
GMutex lock;
|
||||
#endif
|
||||
|
||||
gboolean in_sdtv, out_sdtv;
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@
|
|||
|
||||
#include "audiochebband.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_cheb_band_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
|
||||
#include "audiocheblimit.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_cheb_limit_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
|
||||
#include "audiofirfilter.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_fir_filter_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
|
||||
#include "audioiirfilter.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_iir_filter_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
|
||||
#include "audiowsincband.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_gst_audio_wsincband_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
|
||||
#include "audiowsinclimit.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_wsinclimit_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/base/gstbitreader.h>
|
||||
#include "gstaacparse.h"
|
||||
|
||||
|
||||
|
@ -52,7 +53,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/mpeg, "
|
||||
"framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
|
||||
"stream-format = (string) { raw, adts, adif };"));
|
||||
"stream-format = (string) { raw, adts, adif, loas };"));
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
|
@ -65,10 +66,21 @@ GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
|
|||
|
||||
#define ADIF_MAX_SIZE 40 /* Should be enough */
|
||||
#define ADTS_MAX_SIZE 10 /* Should be enough */
|
||||
#define LOAS_MAX_SIZE 3 /* Should be enough */
|
||||
|
||||
|
||||
#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
|
||||
|
||||
static const gint loas_sample_rate_table[32] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000, 7350, 0, 0, 0
|
||||
};
|
||||
|
||||
static const gint loas_channels_table[32] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 8,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static gboolean gst_aac_parse_start (GstBaseParse * parse);
|
||||
static gboolean gst_aac_parse_stop (GstBaseParse * parse);
|
||||
|
||||
|
@ -190,6 +202,9 @@ gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
|
|||
case DSPAAC_HEADER_ADIF:
|
||||
stream_format = "adif";
|
||||
break;
|
||||
case DSPAAC_HEADER_LOAS:
|
||||
stream_format = "loas";
|
||||
break;
|
||||
default:
|
||||
stream_format = NULL;
|
||||
}
|
||||
|
@ -329,6 +344,8 @@ gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
|
|||
const guint8 * data, const guint avail, gboolean drain,
|
||||
guint * framesize, guint * needed_data)
|
||||
{
|
||||
*needed_data = 0;
|
||||
|
||||
if (G_UNLIKELY (avail < 2))
|
||||
return FALSE;
|
||||
|
||||
|
@ -367,6 +384,292 @@ gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_aac_parse_latm_get_value (GstAacParse * aacparse, GstBitReader * br,
|
||||
guint32 * value)
|
||||
{
|
||||
guint8 bytes, i, byte;
|
||||
|
||||
*value = 0;
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, &bytes, 2))
|
||||
return FALSE;
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
*value <<= 8;
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, &byte, 8))
|
||||
return FALSE;
|
||||
*value += byte;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_aac_parse_get_audio_object_type (GstAacParse * aacparse, GstBitReader * br,
|
||||
guint8 * audio_object_type)
|
||||
{
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 5))
|
||||
return FALSE;
|
||||
if (*audio_object_type == 31) {
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 6))
|
||||
return FALSE;
|
||||
*audio_object_type += 32;
|
||||
}
|
||||
GST_LOG_OBJECT (aacparse, "audio object type %u", *audio_object_type);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_aac_parse_get_audio_sample_rate (GstAacParse * aacparse, GstBitReader * br,
|
||||
gint * sample_rate)
|
||||
{
|
||||
guint8 sampling_frequency_index;
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, &sampling_frequency_index, 4))
|
||||
return FALSE;
|
||||
GST_LOG_OBJECT (aacparse, "sampling_frequency_index: %u",
|
||||
sampling_frequency_index);
|
||||
if (sampling_frequency_index == 0xf) {
|
||||
guint32 sampling_rate;
|
||||
if (!gst_bit_reader_get_bits_uint32 (br, &sampling_rate, 24))
|
||||
return FALSE;
|
||||
*sample_rate = sampling_rate;
|
||||
} else {
|
||||
*sample_rate = loas_sample_rate_table[sampling_frequency_index];
|
||||
if (!*sample_rate)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* See table 1.13 in ISO/IEC 14496-3 */
|
||||
static gboolean
|
||||
gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse,
|
||||
GstBitReader * br, gint * sample_rate, gint * channels, guint32 * bits)
|
||||
{
|
||||
guint8 audio_object_type, channel_configuration;
|
||||
|
||||
if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_bit_reader_get_bits_uint8 (br, &channel_configuration, 4))
|
||||
return FALSE;
|
||||
GST_LOG_OBJECT (aacparse, "channel_configuration: %d", channel_configuration);
|
||||
*channels = loas_channels_table[channel_configuration];
|
||||
if (!*channels)
|
||||
return FALSE;
|
||||
|
||||
if (audio_object_type == 5) {
|
||||
GST_LOG_OBJECT (aacparse,
|
||||
"Audio object type 5, so rereading sampling rate...");
|
||||
if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (aacparse, "Found LOAS config: %d Hz, %d channels",
|
||||
*sample_rate, *channels);
|
||||
|
||||
/* There's LOTS of stuff next, but we ignore it for now as we have
|
||||
what we want (sample rate and number of channels */
|
||||
GST_DEBUG_OBJECT (aacparse,
|
||||
"Need more code to parse humongous LOAS data, currently ignored");
|
||||
if (bits)
|
||||
*bits = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_aac_parse_read_loas_config (GstAacParse * aacparse, const guint8 * data,
|
||||
guint avail, gint * sample_rate, gint * channels, gint * version)
|
||||
{
|
||||
GstBitReader br;
|
||||
guint8 u8, v, vA;
|
||||
|
||||
/* No version in the bitstream, but the spec has LOAS in the MPEG-4 section */
|
||||
if (version)
|
||||
*version = 4;
|
||||
|
||||
gst_bit_reader_init (&br, data, avail);
|
||||
|
||||
/* skip sync word (11 bits) and size (13 bits) */
|
||||
gst_bit_reader_skip (&br, 11 + 13);
|
||||
|
||||
/* First bit is "use last config" */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &u8, 1))
|
||||
return FALSE;
|
||||
if (u8) {
|
||||
GST_DEBUG_OBJECT (aacparse, "Frame uses previous config");
|
||||
if (!aacparse->sample_rate || !aacparse->channels) {
|
||||
GST_WARNING_OBJECT (aacparse, "No previous config to use");
|
||||
}
|
||||
*sample_rate = aacparse->sample_rate;
|
||||
*channels = aacparse->channels;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (aacparse, "Frame contains new config");
|
||||
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &v, 1))
|
||||
return FALSE;
|
||||
if (v) {
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &vA, 1))
|
||||
return FALSE;
|
||||
} else
|
||||
vA = 0;
|
||||
|
||||
GST_LOG_OBJECT (aacparse, "v %d, vA %d", v, vA);
|
||||
if (vA == 0) {
|
||||
guint8 same_time, subframes, num_program, prog;
|
||||
if (v == 1) {
|
||||
guint32 value;
|
||||
if (!gst_aac_parse_latm_get_value (aacparse, &br, &value))
|
||||
return FALSE;
|
||||
}
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &same_time, 1))
|
||||
return FALSE;
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &subframes, 6))
|
||||
return FALSE;
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &num_program, 4))
|
||||
return FALSE;
|
||||
GST_LOG_OBJECT (aacparse, "same_time %d, subframes %d, num_program %d",
|
||||
same_time, subframes, num_program);
|
||||
|
||||
for (prog = 0; prog <= num_program; ++prog) {
|
||||
guint8 num_layer, layer;
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &num_layer, 3))
|
||||
return FALSE;
|
||||
GST_LOG_OBJECT (aacparse, "Program %d: %d layers", prog, num_layer);
|
||||
|
||||
for (layer = 0; layer <= num_layer; ++layer) {
|
||||
guint8 use_same_config;
|
||||
if (prog == 0 && layer == 0) {
|
||||
use_same_config = 0;
|
||||
} else {
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, &use_same_config, 1))
|
||||
return FALSE;
|
||||
}
|
||||
if (!use_same_config) {
|
||||
if (v == 0) {
|
||||
if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br,
|
||||
sample_rate, channels, NULL))
|
||||
return FALSE;
|
||||
} else {
|
||||
guint32 bits, asc_len;
|
||||
if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len))
|
||||
return FALSE;
|
||||
if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br,
|
||||
sample_rate, channels, &bits))
|
||||
return FALSE;
|
||||
asc_len -= bits;
|
||||
gst_bit_reader_skip (&br, asc_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GST_WARNING_OBJECT (aacparse, "More data ignored");
|
||||
} else {
|
||||
GST_WARNING_OBJECT (aacparse, "Spec says \"TBD\"...");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_aac_parse_loas_get_frame_len:
|
||||
* @data: block of data containing a LOAS header.
|
||||
*
|
||||
* This function calculates LOAS frame length from the given header.
|
||||
*
|
||||
* Returns: size of the LOAS frame.
|
||||
*/
|
||||
static inline guint
|
||||
gst_aac_parse_loas_get_frame_len (const guint8 * data)
|
||||
{
|
||||
return (((data[1] & 0x1f) << 8) | data[2]) + 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aac_parse_check_loas_frame:
|
||||
* @aacparse: #GstAacParse.
|
||||
* @data: Data to be checked.
|
||||
* @avail: Amount of data passed.
|
||||
* @framesize: If valid LOAS frame was found, this will be set to tell the
|
||||
* found frame size in bytes.
|
||||
* @needed_data: If frame was not found, this may be set to tell how much
|
||||
* more data is needed in the next round to detect the frame
|
||||
* reliably. This may happen when a frame header candidate
|
||||
* is found but it cannot be guaranteed to be the header without
|
||||
* peeking the following data.
|
||||
*
|
||||
* Check if the given data contains contains LOAS frame. The algorithm
|
||||
* will examine LOAS frame header and calculate the frame size. Also, another
|
||||
* consecutive LOAS frame header need to be present after the found frame.
|
||||
* Otherwise the data is not considered as a valid LOAS frame. However, this
|
||||
* "extra check" is omitted when EOS has been received. In this case it is
|
||||
* enough when data[0] contains a valid LOAS header.
|
||||
*
|
||||
* This function may set the #needed_data to indicate that a possible frame
|
||||
* candidate has been found, but more data (#needed_data bytes) is needed to
|
||||
* be absolutely sure. When this situation occurs, FALSE will be returned.
|
||||
*
|
||||
* When a valid frame is detected, this function will use
|
||||
* gst_base_parse_set_min_frame_size() function from #GstBaseParse class
|
||||
* to set the needed bytes for next frame.This way next data chunk is already
|
||||
* of correct size.
|
||||
*
|
||||
* LOAS can have three different formats, if I read the spec correctly. Only
|
||||
* one of them is supported here, as the two samples I have use this one.
|
||||
*
|
||||
* Returns: TRUE if the given data contains a valid LOAS header.
|
||||
*/
|
||||
static gboolean
|
||||
gst_aac_parse_check_loas_frame (GstAacParse * aacparse,
|
||||
const guint8 * data, const guint avail, gboolean drain,
|
||||
guint * framesize, guint * needed_data)
|
||||
{
|
||||
*needed_data = 0;
|
||||
|
||||
/* 3 byte header */
|
||||
if (G_UNLIKELY (avail < 3))
|
||||
return FALSE;
|
||||
|
||||
if ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) {
|
||||
*framesize = gst_aac_parse_loas_get_frame_len (data);
|
||||
GST_DEBUG_OBJECT (aacparse, "Found %u byte LOAS frame", *framesize);
|
||||
|
||||
/* In EOS mode this is enough. No need to examine the data further.
|
||||
We also relax the check when we have sync, on the assumption that
|
||||
if we're not looking at random data, we have a much higher chance
|
||||
to get the correct sync, and this avoids losing two frames when
|
||||
a single bit corruption happens. */
|
||||
if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (*framesize + LOAS_MAX_SIZE > avail) {
|
||||
/* We have found a possible frame header candidate, but can't be
|
||||
sure since we don't have enough data to check the next frame */
|
||||
GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
|
||||
*framesize + LOAS_MAX_SIZE, avail);
|
||||
*needed_data = *framesize + LOAS_MAX_SIZE;
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
*framesize + LOAS_MAX_SIZE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((data[*framesize] == 0x56) && ((data[*framesize + 1] & 0xe0) == 0xe0)) {
|
||||
guint nextlen = gst_aac_parse_loas_get_frame_len (data + (*framesize));
|
||||
|
||||
GST_LOG ("LOAS frame found, len: %d bytes", *framesize);
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
nextlen + LOAS_MAX_SIZE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* caller ensure sufficient data */
|
||||
static inline void
|
||||
gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
|
||||
|
@ -412,7 +715,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||
guint * framesize, gint * skipsize)
|
||||
{
|
||||
gboolean found = FALSE;
|
||||
guint need_data = 0;
|
||||
guint need_data_adts = 0, need_data_loas;
|
||||
guint i = 0;
|
||||
|
||||
GST_DEBUG_OBJECT (aacparse, "Parsing header data");
|
||||
|
@ -421,12 +724,16 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||
stream */
|
||||
|
||||
/* Can we even parse the header? */
|
||||
if (avail < ADTS_MAX_SIZE)
|
||||
if (avail < MAX (ADTS_MAX_SIZE, LOAS_MAX_SIZE)) {
|
||||
GST_DEBUG_OBJECT (aacparse, "Not enough data to check");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < avail - 4; i++) {
|
||||
if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
|
||||
((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) ||
|
||||
strncmp ((char *) data + i, "ADIF", 4) == 0) {
|
||||
GST_DEBUG_OBJECT (aacparse, "Found ADIF signature at offset %u", i);
|
||||
found = TRUE;
|
||||
|
||||
if (i) {
|
||||
|
@ -446,7 +753,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||
}
|
||||
|
||||
if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
|
||||
framesize, &need_data)) {
|
||||
framesize, &need_data_adts)) {
|
||||
gint rate, channels;
|
||||
|
||||
GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
|
||||
|
@ -464,7 +771,38 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||
gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
|
||||
|
||||
return TRUE;
|
||||
} else if (need_data) {
|
||||
}
|
||||
|
||||
if (gst_aac_parse_check_loas_frame (aacparse, data, avail, drain,
|
||||
framesize, &need_data_loas)) {
|
||||
gint rate, channels;
|
||||
|
||||
GST_INFO ("LOAS, framesize: %d", *framesize);
|
||||
|
||||
aacparse->header_type = DSPAAC_HEADER_LOAS;
|
||||
|
||||
if (!gst_aac_parse_read_loas_config (aacparse, data, avail, &rate,
|
||||
&channels, &aacparse->mpegversion)) {
|
||||
GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rate && channels) {
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
|
||||
aacparse->frame_samples, 2, 2);
|
||||
|
||||
GST_DEBUG ("LOAS: samplerate %d, channels %d, objtype %d, version %d",
|
||||
rate, channels, aacparse->object_type, aacparse->mpegversion);
|
||||
aacparse->sample_rate = rate;
|
||||
aacparse->channels = channels;
|
||||
}
|
||||
|
||||
gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (need_data_adts || need_data_loas) {
|
||||
/* This tells the parent class not to skip any data */
|
||||
*skipsize = 0;
|
||||
return FALSE;
|
||||
|
@ -612,6 +950,18 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
needed_data);
|
||||
}
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aac_parse_check_loas_frame (aacparse, data,
|
||||
size, GST_BASE_PARSE_DRAINING (parse), framesize, &needed_data);
|
||||
|
||||
if (!ret) {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
needed_data);
|
||||
}
|
||||
|
||||
} else {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
|
@ -632,7 +982,7 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
*
|
||||
* Also determines frame overhead.
|
||||
* ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
|
||||
* a per-frame header.
|
||||
* a per-frame header. LOAS has 3 bytes.
|
||||
*
|
||||
* We're making a couple of simplifying assumptions:
|
||||
*
|
||||
|
@ -659,36 +1009,70 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
aacparse = GST_AAC_PARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
|
||||
if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
|
||||
return ret;
|
||||
if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||
/* see above */
|
||||
frame->overhead = 7;
|
||||
|
||||
/* see above */
|
||||
frame->overhead = 7;
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
gst_aac_parse_parse_adts_header (aacparse, data,
|
||||
&rate, &channels, NULL, NULL);
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
gst_aac_parse_parse_adts_header (aacparse, data,
|
||||
&rate, &channels, NULL, NULL);
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
||||
|
||||
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
||||
if (G_UNLIKELY (rate != aacparse->sample_rate
|
||||
|| channels != aacparse->channels)) {
|
||||
GstCaps *sinkcaps;
|
||||
|
||||
if (G_UNLIKELY (rate != aacparse->sample_rate
|
||||
|| channels != aacparse->channels)) {
|
||||
GstCaps *sinkcaps;
|
||||
aacparse->sample_rate = rate;
|
||||
aacparse->channels = channels;
|
||||
|
||||
aacparse->sample_rate = rate;
|
||||
aacparse->channels = channels;
|
||||
|
||||
sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
gst_caps_unref (sinkcaps);
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
gst_caps_unref (sinkcaps);
|
||||
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
||||
}
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
|
||||
gboolean setcaps = FALSE;
|
||||
|
||||
/* see above */
|
||||
frame->overhead = 3;
|
||||
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
if (!gst_aac_parse_read_loas_config (aacparse, data, size, &rate, &channels,
|
||||
NULL)) {
|
||||
GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
|
||||
} else if (G_UNLIKELY (rate != aacparse->sample_rate
|
||||
|| channels != aacparse->channels)) {
|
||||
aacparse->sample_rate = rate;
|
||||
aacparse->channels = channels;
|
||||
setcaps = TRUE;
|
||||
GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
|
||||
channels);
|
||||
}
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
|
||||
/* We want to set caps both at start, and when rate/channels change.
|
||||
Since only some LOAS frames have that info, we may receive frames
|
||||
before knowing about rate/channels. */
|
||||
if (setcaps
|
||||
|| !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
|
||||
GstCaps *sinkcaps =
|
||||
gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
gst_caps_unref (sinkcaps);
|
||||
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -45,6 +45,7 @@ G_BEGIN_DECLS
|
|||
* @DSPAAC_HEADER_UNKNOWN: Unknown (not recognized) header.
|
||||
* @DSPAAC_HEADER_ADIF: ADIF header found.
|
||||
* @DSPAAC_HEADER_ADTS: ADTS header found.
|
||||
* @DSPAAC_HEADER_LOAS: LOAS header found.
|
||||
* @DSPAAC_HEADER_NONE: Raw stream, no header.
|
||||
*
|
||||
* Type header enumeration set in #header_type.
|
||||
|
@ -54,6 +55,7 @@ typedef enum {
|
|||
DSPAAC_HEADER_UNKNOWN,
|
||||
DSPAAC_HEADER_ADIF,
|
||||
DSPAAC_HEADER_ADTS,
|
||||
DSPAAC_HEADER_LOAS,
|
||||
DSPAAC_HEADER_NONE
|
||||
} GstAacHeaderType;
|
||||
|
||||
|
|
|
@ -324,7 +324,9 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
|
|||
|
||||
/* spec not quite clear here: decoder should decode if less than 8,
|
||||
* but seemingly only defines 6 and 8 cases */
|
||||
if (bsid > 8) {
|
||||
/* Files with 9 and 10 happen, and seem to comply with the <= 8
|
||||
format, so let them through. The spec says nothing about 9 and 10 */
|
||||
if (bsid > 10) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
|
||||
goto cleanup;
|
||||
} else if (bsid != 8 && bsid != 6) {
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
|
@ -190,10 +190,10 @@ static GstStaticPadTemplate audio_sink_factory =
|
|||
|
||||
static void gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free);
|
||||
|
||||
static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads * pads,
|
||||
static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads2 * pads,
|
||||
GstAviMux * avimux);
|
||||
static gboolean gst_avi_mux_handle_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
static gboolean gst_avi_mux_handle_event (GstCollectPads2 * pad,
|
||||
GstCollectData2 * data, GstEvent * event, gpointer user_data);
|
||||
static GstPad *gst_avi_mux_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||
static void gst_avi_mux_release_pad (GstElement * element, GstPad * pad);
|
||||
|
@ -378,10 +378,13 @@ gst_avi_mux_init (GstAviMux * avimux)
|
|||
/* property */
|
||||
avimux->enable_large_avi = DEFAULT_BIGFILE;
|
||||
|
||||
avimux->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (avimux->collect,
|
||||
(GstCollectPadsFunction) (GST_DEBUG_FUNCPTR (gst_avi_mux_collect_pads)),
|
||||
avimux->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_function (avimux->collect,
|
||||
(GstCollectPads2Function) (GST_DEBUG_FUNCPTR (gst_avi_mux_collect_pads)),
|
||||
avimux);
|
||||
gst_collect_pads2_set_event_function (avimux->collect,
|
||||
(GstCollectPads2EventFunction) (GST_DEBUG_FUNCPTR
|
||||
(gst_avi_mux_handle_event)), avimux);
|
||||
|
||||
/* set to clean state */
|
||||
gst_avi_mux_reset (avimux);
|
||||
|
@ -977,15 +980,9 @@ gst_avi_mux_request_new_pad (GstElement * element,
|
|||
|
||||
g_free (name);
|
||||
|
||||
avipad->collect = gst_collect_pads_add_pad (avimux->collect,
|
||||
newpad, sizeof (GstAviCollectData), NULL);
|
||||
avipad->collect = gst_collect_pads2_add_pad (avimux->collect,
|
||||
newpad, sizeof (GstAviCollectData));
|
||||
((GstAviCollectData *) (avipad->collect))->avipad = avipad;
|
||||
/* 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 */
|
||||
avimux->collect_event = GST_PAD_EVENTFUNC (newpad);
|
||||
gst_pad_set_event_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_avi_mux_handle_event));
|
||||
|
||||
if (!gst_element_add_pad (element, newpad))
|
||||
goto pad_add_failed;
|
||||
|
@ -1038,7 +1035,7 @@ gst_avi_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
* as it also represent number of streams present */
|
||||
avipad->collect = NULL;
|
||||
GST_DEBUG_OBJECT (avimux, "removed pad '%s'", GST_PAD_NAME (pad));
|
||||
gst_collect_pads_remove_pad (avimux->collect, pad);
|
||||
gst_collect_pads2_remove_pad (avimux->collect, pad);
|
||||
gst_element_remove_pad (element, pad);
|
||||
/* if not started yet, we can remove any sign this pad ever existed */
|
||||
/* in this case _start will take care of the real pad count */
|
||||
|
@ -1833,12 +1830,13 @@ gst_avi_mux_restart_file (GstAviMux * avimux)
|
|||
|
||||
/* handle events (search) */
|
||||
static gboolean
|
||||
gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
gst_avi_mux_handle_event (GstCollectPads2 * pads, GstCollectData2 * data,
|
||||
GstEvent * event, gpointer user_data)
|
||||
{
|
||||
GstAviMux *avimux;
|
||||
gboolean ret = TRUE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
avimux = GST_AVI_MUX (parent);
|
||||
avimux = GST_AVI_MUX (user_data);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:
|
||||
|
@ -1850,15 +1848,15 @@ gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
gst_event_parse_caps (event, &caps);
|
||||
|
||||
/* find stream data */
|
||||
collect_pad = (GstAviCollectData *) gst_pad_get_element_private (pad);
|
||||
collect_pad = (GstAviCollectData *) data;
|
||||
g_assert (collect_pad);
|
||||
avipad = (GstAviVideoPad *) collect_pad->avipad;
|
||||
g_assert (avipad);
|
||||
|
||||
if (avipad->parent.is_video) {
|
||||
ret = gst_avi_mux_vidsink_set_caps (pad, caps);
|
||||
ret = gst_avi_mux_vidsink_set_caps (GST_PAD (avipad), caps);
|
||||
} else {
|
||||
ret = gst_avi_mux_audsink_set_caps (pad, caps);
|
||||
ret = gst_avi_mux_audsink_set_caps (GST_PAD (avipad), caps);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1875,10 +1873,7 @@ gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
if (ret)
|
||||
ret = avimux->collect_event (pad, parent, event);
|
||||
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1909,7 +1904,7 @@ gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
|
|||
guint flags;
|
||||
gsize datasize;
|
||||
|
||||
data = gst_collect_pads_pop (avimux->collect, avipad->collect);
|
||||
data = gst_collect_pads2_pop (avimux->collect, avipad->collect);
|
||||
/* arrange downstream running time */
|
||||
data = gst_buffer_make_writable (data);
|
||||
GST_BUFFER_TIMESTAMP (data) =
|
||||
|
@ -2033,7 +2028,7 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
|
|||
if (!avipad->hdr.fcc_handler)
|
||||
goto not_negotiated;
|
||||
|
||||
buffer = gst_collect_pads_peek (avimux->collect, avipad->collect);
|
||||
buffer = gst_collect_pads2_peek (avimux->collect, avipad->collect);
|
||||
if (!buffer)
|
||||
continue;
|
||||
time = GST_BUFFER_TIMESTAMP (buffer);
|
||||
|
@ -2046,7 +2041,7 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
|
|||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
GST_DEBUG_OBJECT (avimux, "clipping buffer on pad %s outside segment",
|
||||
GST_PAD_NAME (avipad->collect->pad));
|
||||
buffer = gst_collect_pads_pop (avimux->collect, avipad->collect);
|
||||
buffer = gst_collect_pads2_pop (avimux->collect, avipad->collect);
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
@ -2085,7 +2080,7 @@ not_negotiated:
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_avi_mux_collect_pads (GstCollectPads * pads, GstAviMux * avimux)
|
||||
gst_avi_mux_collect_pads (GstCollectPads2 * pads, GstAviMux * avimux)
|
||||
{
|
||||
GstFlowReturn res;
|
||||
|
||||
|
@ -2144,12 +2139,12 @@ gst_avi_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_collect_pads_start (avimux->collect);
|
||||
gst_collect_pads2_start (avimux->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
gst_collect_pads_stop (avimux->collect);
|
||||
gst_collect_pads2_stop (avimux->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
#include <gst/riff/riff-ids.h>
|
||||
#include "avi-ids.h"
|
||||
|
||||
|
@ -74,7 +74,7 @@ typedef GstFlowReturn (*GstAviPadHook) (GstAviMux * avi, GstAviPad * avipad,
|
|||
struct _GstAviPad {
|
||||
/* do not extend, link to it */
|
||||
/* is NULL if original sink request pad has been removed */
|
||||
GstCollectData *collect;
|
||||
GstCollectData2 *collect;
|
||||
|
||||
/* type */
|
||||
gboolean is_video;
|
||||
|
@ -129,7 +129,7 @@ typedef struct _GstAviAudioPad {
|
|||
|
||||
typedef struct _GstAviCollectData {
|
||||
/* extend the CollectData */
|
||||
GstCollectData collect;
|
||||
GstCollectData2 collect;
|
||||
|
||||
GstAviPad *avipad;
|
||||
} GstAviCollectData;
|
||||
|
@ -143,8 +143,7 @@ struct _GstAviMux {
|
|||
GSList *sinkpads;
|
||||
/* video restricted to 1 pad */
|
||||
guint video_pads, audio_pads;
|
||||
GstCollectPads *collect;
|
||||
GstPadEventFunction collect_event;
|
||||
GstCollectPads2 *collect;
|
||||
|
||||
/* the AVI header */
|
||||
/* still some single stream video data in mux struct */
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "gstiirequalizer3bands.h"
|
||||
#include "gstiirequalizer10bands.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY (equalizer_debug);
|
||||
#define GST_CAT_DEFAULT equalizer_debug
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "gstflvdemux.h"
|
||||
#include "gstflvmux.h"
|
||||
|
||||
|
|
|
@ -89,7 +89,11 @@ G_DEFINE_TYPE_WITH_CODE (GstFlvMux, gst_flv_mux, GST_TYPE_ELEMENT,
|
|||
|
||||
static void gst_flv_mux_finalize (GObject * object);
|
||||
static GstFlowReturn
|
||||
gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data);
|
||||
gst_flv_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
|
||||
GstBuffer * buf, gpointer user_data);
|
||||
static gboolean
|
||||
gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
|
||||
GstEvent * event, gpointer user_data);
|
||||
|
||||
static gboolean gst_flv_mux_handle_src_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
|
@ -209,9 +213,13 @@ gst_flv_mux_init (GstFlvMux * mux)
|
|||
|
||||
mux->new_tags = FALSE;
|
||||
|
||||
mux->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (mux->collect,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_flv_mux_collected), mux);
|
||||
mux->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_buffer_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_flv_mux_handle_buffer), mux);
|
||||
gst_collect_pads2_set_event_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event), mux);
|
||||
gst_collect_pads2_set_clip_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), mux);
|
||||
|
||||
gst_flv_mux_reset (GST_ELEMENT (mux));
|
||||
}
|
||||
|
@ -273,11 +281,11 @@ gst_flv_mux_handle_src_event (GstPad * pad, GstObject * parent,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
|
||||
GstEvent * event, gpointer user_data)
|
||||
{
|
||||
GstFlvMux *mux = GST_FLV_MUX (parent);
|
||||
gboolean ret = TRUE;
|
||||
GstFlvMux *mux = GST_FLV_MUX (user_data);
|
||||
gboolean ret = FALSE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:
|
||||
|
@ -288,13 +296,13 @@ gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
gst_event_parse_caps (event, &caps);
|
||||
|
||||
/* find stream data */
|
||||
flvpad = (GstFlvPad *) gst_pad_get_element_private (pad);
|
||||
flvpad = (GstFlvPad *) data;
|
||||
g_assert (flvpad);
|
||||
|
||||
if (flvpad->video) {
|
||||
ret = gst_flv_mux_video_pad_setcaps (pad, caps);
|
||||
ret = gst_flv_mux_video_pad_setcaps (data->pad, caps);
|
||||
} else {
|
||||
ret = gst_flv_mux_audio_pad_setcaps (pad, caps);
|
||||
ret = gst_flv_mux_audio_pad_setcaps (data->pad, caps);
|
||||
}
|
||||
/* and eat */
|
||||
ret = FALSE;
|
||||
|
@ -315,10 +323,7 @@ gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
break;
|
||||
}
|
||||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
if (ret)
|
||||
ret = mux->collect_event (pad, parent, event);
|
||||
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -567,20 +572,12 @@ gst_flv_mux_request_new_pad (GstElement * element,
|
|||
|
||||
pad = gst_pad_new_from_template (templ, name);
|
||||
cpad = (GstFlvPad *)
|
||||
gst_collect_pads_add_pad (mux->collect, pad, sizeof (GstFlvPad), NULL);
|
||||
gst_collect_pads2_add_pad (mux->collect, pad, sizeof (GstFlvPad));
|
||||
|
||||
cpad->audio_codec_data = NULL;
|
||||
cpad->video_codec_data = NULL;
|
||||
gst_flv_mux_reset_pad (mux, cpad, video);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (pad);
|
||||
gst_pad_set_event_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event));
|
||||
|
||||
gst_pad_set_active (pad, TRUE);
|
||||
gst_element_add_pad (element, pad);
|
||||
|
||||
|
@ -594,7 +591,7 @@ gst_flv_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
GstFlvPad *cpad = (GstFlvPad *) gst_pad_get_element_private (pad);
|
||||
|
||||
gst_flv_mux_reset_pad (mux, cpad, cpad->video);
|
||||
gst_collect_pads_remove_pad (mux->collect, pad);
|
||||
gst_collect_pads2_remove_pad (mux->collect, pad);
|
||||
gst_element_remove_pad (element, pad);
|
||||
}
|
||||
|
||||
|
@ -677,7 +674,7 @@ gst_flv_mux_create_number_script_value (const gchar * name, gdouble value)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_flv_mux_create_metadata (GstFlvMux * mux)
|
||||
gst_flv_mux_create_metadata (GstFlvMux * mux, gboolean full)
|
||||
{
|
||||
const GstTagList *tags;
|
||||
GstBuffer *script_tag, *tmp;
|
||||
|
@ -719,6 +716,9 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
|
|||
GST_WRITE_UINT32_BE (data + 1, n_tags);
|
||||
script_tag = gst_buffer_join (script_tag, tmp);
|
||||
|
||||
if (!full)
|
||||
goto tags;
|
||||
|
||||
/* Some players expect the 'duration' to be always set. Fill it out later,
|
||||
after querying the pads or after getting EOS */
|
||||
if (!mux->streamable) {
|
||||
|
@ -739,6 +739,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
|
|||
GST_DEBUG_OBJECT (mux, "not preallocating index, streamable mode");
|
||||
}
|
||||
|
||||
tags:
|
||||
for (i = 0; tags && i < n_tags; i++) {
|
||||
const gchar *tag_name =
|
||||
gst_structure_nth_field_name ((const GstStructure *) tags, i);
|
||||
|
@ -777,12 +778,15 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
|
|||
}
|
||||
}
|
||||
|
||||
if (!full)
|
||||
goto end;
|
||||
|
||||
if (mux->duration == GST_CLOCK_TIME_NONE) {
|
||||
GSList *l;
|
||||
guint64 dur;
|
||||
|
||||
for (l = mux->collect->data; l; l = l->next) {
|
||||
GstCollectData *cdata = l->data;
|
||||
GstCollectData2 *cdata = l->data;
|
||||
|
||||
if (gst_pad_peer_query_duration (cdata->pad, GST_FORMAT_TIME,
|
||||
(gint64 *) & dur) && dur != GST_CLOCK_TIME_NONE) {
|
||||
|
@ -958,6 +962,14 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
|
|||
tags_written++;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
if (!tags_written) {
|
||||
gst_buffer_unref (script_tag);
|
||||
script_tag = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
_gst_buffer_new_and_alloc (2 + 0 + 1, &tmp, &data);
|
||||
data[0] = 0; /* 0 byte size */
|
||||
data[1] = 0;
|
||||
|
@ -977,6 +989,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
|
|||
GST_WRITE_UINT32_BE (data + 11 + 13 + 1, tags_written);
|
||||
gst_buffer_unmap (script_tag, data, -1);
|
||||
|
||||
exit:
|
||||
return script_tag;
|
||||
}
|
||||
|
||||
|
@ -1125,7 +1138,7 @@ gst_flv_mux_write_header (GstFlvMux * mux)
|
|||
GstFlowReturn ret;
|
||||
|
||||
header = gst_flv_mux_create_header (mux);
|
||||
metadata = gst_flv_mux_create_metadata (mux);
|
||||
metadata = gst_flv_mux_create_metadata (mux, TRUE);
|
||||
video_codec_data = NULL;
|
||||
audio_codec_data = NULL;
|
||||
|
||||
|
@ -1228,18 +1241,12 @@ gst_flv_mux_update_index (GstFlvMux * mux, GstBuffer * buffer, GstFlvPad * cpad)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad)
|
||||
gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad, GstBuffer * buffer)
|
||||
{
|
||||
GstBuffer *tag;
|
||||
GstBuffer *buffer =
|
||||
gst_collect_pads_pop (mux->collect, (GstCollectData *) cpad);
|
||||
GstFlowReturn ret;
|
||||
|
||||
/* arrange downstream running time */
|
||||
buffer = gst_buffer_make_writable (buffer);
|
||||
GST_BUFFER_TIMESTAMP (buffer) =
|
||||
gst_segment_to_running_time (&cpad->collect.segment,
|
||||
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
|
||||
/* clipping function arranged for running_time */
|
||||
|
||||
if (!mux->streamable)
|
||||
gst_flv_mux_update_index (mux, buffer, cpad);
|
||||
|
@ -1276,12 +1283,6 @@ gst_flv_mux_determine_duration (GstFlvMux * mux)
|
|||
}
|
||||
}
|
||||
|
||||
if (duration == GST_CLOCK_TIME_NONE) {
|
||||
GST_DEBUG_OBJECT (mux, "not able to determine duration "
|
||||
"from pad timestamps, assuming 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
|
@ -1296,6 +1297,7 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
|
|||
guint32 index_len, allocate_size;
|
||||
guint32 i, index_skip;
|
||||
GstSegment segment;
|
||||
GstClockTime dur;
|
||||
|
||||
if (mux->streamable)
|
||||
return GST_FLOW_OK;
|
||||
|
@ -1309,9 +1311,12 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* if we were not able to determine the duration before, set it now */
|
||||
if (mux->duration == GST_CLOCK_TIME_NONE)
|
||||
mux->duration = gst_flv_mux_determine_duration (mux);
|
||||
/* determine duration now based on our own timestamping,
|
||||
* so that it is likely many times better and consistent
|
||||
* than whatever obtained by some query */
|
||||
dur = gst_flv_mux_determine_duration (mux);
|
||||
if (dur != GST_CLOCK_TIME_NONE)
|
||||
mux->duration = dur;
|
||||
|
||||
/* rewrite the duration tag */
|
||||
d = gst_guint64_to_gdouble (mux->duration);
|
||||
|
@ -1420,14 +1425,13 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||
gst_flv_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
|
||||
GstBuffer * buffer, gpointer user_data)
|
||||
{
|
||||
GstFlvMux *mux = GST_FLV_MUX (user_data);
|
||||
GstFlvPad *best;
|
||||
GstClockTime best_time;
|
||||
GstFlowReturn ret;
|
||||
GSList *sl;
|
||||
gboolean eos = TRUE;
|
||||
|
||||
if (mux->state == GST_FLV_MUX_STATE_HEADER) {
|
||||
GstSegment segment;
|
||||
|
@ -1450,51 +1454,18 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
}
|
||||
|
||||
if (mux->new_tags) {
|
||||
GstBuffer *buf = gst_flv_mux_create_metadata (mux);
|
||||
gst_flv_mux_push (mux, buf);
|
||||
GstBuffer *buf = gst_flv_mux_create_metadata (mux, FALSE);
|
||||
if (buf)
|
||||
gst_flv_mux_push (mux, buf);
|
||||
mux->new_tags = FALSE;
|
||||
}
|
||||
|
||||
|
||||
best = NULL;
|
||||
best_time = GST_CLOCK_TIME_NONE;
|
||||
for (sl = mux->collect->data; sl; sl = sl->next) {
|
||||
GstFlvPad *cpad = sl->data;
|
||||
GstBuffer *buffer = gst_collect_pads_peek (pads, (GstCollectData *) cpad);
|
||||
GstClockTime time;
|
||||
|
||||
if (!buffer)
|
||||
continue;
|
||||
|
||||
eos = FALSE;
|
||||
|
||||
time = GST_BUFFER_TIMESTAMP (buffer);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* Use buffers without valid timestamp first */
|
||||
if (!GST_CLOCK_TIME_IS_VALID (time)) {
|
||||
GST_WARNING_OBJECT (pads, "Buffer without valid timestamp");
|
||||
|
||||
best_time = cpad->last_timestamp;
|
||||
best = cpad;
|
||||
break;
|
||||
}
|
||||
|
||||
time = gst_segment_to_running_time (&cpad->collect.segment,
|
||||
GST_FORMAT_TIME, time);
|
||||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
GST_DEBUG_OBJECT (mux, "clipping buffer on pad %s outside segment",
|
||||
GST_PAD_NAME (cpad->collect.pad));
|
||||
buffer = gst_collect_pads_pop (pads, (GstCollectData *) cpad);
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (best == NULL || (GST_CLOCK_TIME_IS_VALID (best_time)
|
||||
&& time < best_time)) {
|
||||
best = cpad;
|
||||
best_time = time;
|
||||
}
|
||||
best = (GstFlvPad *) cdata;
|
||||
if (best) {
|
||||
g_assert (buffer);
|
||||
best_time = GST_BUFFER_TIMESTAMP (buffer);
|
||||
} else {
|
||||
best_time = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
/* The FLV timestamp is an int32 field. For non-live streams error out if a
|
||||
|
@ -1503,17 +1474,17 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
if (!mux->streamable && GST_CLOCK_TIME_IS_VALID (best_time)
|
||||
&& best_time / GST_MSECOND > G_MAXINT32) {
|
||||
GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS");
|
||||
eos = TRUE;
|
||||
gst_buffer_unref (buffer);
|
||||
buffer = NULL;
|
||||
best = NULL;
|
||||
}
|
||||
|
||||
if (!eos && best) {
|
||||
return gst_flv_mux_write_buffer (mux, best);
|
||||
} else if (eos) {
|
||||
if (best) {
|
||||
return gst_flv_mux_write_buffer (mux, best, buffer);
|
||||
} else {
|
||||
gst_flv_mux_rewrite_header (mux);
|
||||
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
|
||||
return GST_FLOW_EOS;
|
||||
} else {
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1565,12 +1536,12 @@ gst_flv_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_collect_pads_start (mux->collect);
|
||||
gst_collect_pads2_start (mux->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
gst_collect_pads_stop (mux->collect);
|
||||
gst_collect_pads2_stop (mux->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define __GST_FLV_MUX_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -39,7 +39,7 @@ G_BEGIN_DECLS
|
|||
|
||||
typedef struct
|
||||
{
|
||||
GstCollectData collect;
|
||||
GstCollectData2 collect;
|
||||
|
||||
gboolean video;
|
||||
|
||||
|
@ -65,11 +65,9 @@ typedef struct _GstFlvMux {
|
|||
GstElement element;
|
||||
|
||||
GstPad *srcpad;
|
||||
GstCollectPads *collect;
|
||||
GstCollectPads2 *collect;
|
||||
|
||||
/* <private> */
|
||||
GstPadEventFunction collect_event;
|
||||
|
||||
GstFlvMuxState state;
|
||||
gboolean have_audio;
|
||||
gboolean have_video;
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
#include "gstimagefreeze.h"
|
||||
|
||||
static void gst_image_freeze_finalize (GObject * object);
|
||||
|
|
|
@ -227,7 +227,7 @@ static gboolean gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps);
|
|||
|
||||
static GstCaps *gst_interleave_sink_getcaps (GstPad * pad);
|
||||
|
||||
static GstFlowReturn gst_interleave_collected (GstCollectPads * pads,
|
||||
static GstFlowReturn gst_interleave_collected (GstCollectPads2 * pads,
|
||||
GstInterleave * self);
|
||||
|
||||
static void
|
||||
|
@ -407,9 +407,9 @@ gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass)
|
|||
|
||||
gst_element_add_pad (GST_ELEMENT (self), self->src);
|
||||
|
||||
self->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (self->collect,
|
||||
(GstCollectPadsFunction) gst_interleave_collected, self);
|
||||
self->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_function (self->collect,
|
||||
(GstCollectPads2Function) gst_interleave_collected, self);
|
||||
|
||||
self->input_channel_positions = g_value_array_new (0);
|
||||
self->channel_positions_from_input = TRUE;
|
||||
|
@ -500,11 +500,10 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
|||
gst_pad_set_getcaps_function (new_pad,
|
||||
GST_DEBUG_FUNCPTR (gst_interleave_sink_getcaps));
|
||||
|
||||
gst_collect_pads_add_pad (self->collect, new_pad, sizeof (GstCollectData),
|
||||
NULL);
|
||||
gst_collect_pads2_add_pad (self->collect, new_pad, sizeof (GstCollectData2));
|
||||
|
||||
/* FIXME: hacked way to override/extend the event function of
|
||||
* GstCollectPads; because it sets its own event function giving the
|
||||
* GstCollectPads2; because it sets its own event function giving the
|
||||
* element no access to events */
|
||||
self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (new_pad);
|
||||
gst_pad_set_event_function (new_pad,
|
||||
|
@ -550,7 +549,7 @@ not_sink_pad:
|
|||
could_not_add:
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "could not add pad %s", GST_PAD_NAME (new_pad));
|
||||
gst_collect_pads_remove_pad (self->collect, new_pad);
|
||||
gst_collect_pads2_remove_pad (self->collect, new_pad);
|
||||
gst_object_unref (new_pad);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -604,7 +603,7 @@ gst_interleave_release_pad (GstElement * element, GstPad * pad)
|
|||
|
||||
GST_OBJECT_UNLOCK (self->collect);
|
||||
|
||||
gst_collect_pads_remove_pad (self->collect, pad);
|
||||
gst_collect_pads2_remove_pad (self->collect, pad);
|
||||
gst_element_remove_pad (element, pad);
|
||||
}
|
||||
|
||||
|
@ -626,7 +625,7 @@ gst_interleave_change_state (GstElement * element, GstStateChange transition)
|
|||
self->segment_position = 0;
|
||||
self->segment_rate = 1.0;
|
||||
gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
|
||||
gst_collect_pads_start (self->collect);
|
||||
gst_collect_pads2_start (self->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
|
@ -635,11 +634,11 @@ gst_interleave_change_state (GstElement * element, GstStateChange transition)
|
|||
}
|
||||
|
||||
/* Stop before calling the parent's state change function as
|
||||
* GstCollectPads might take locks and we would deadlock in that
|
||||
* GstCollectPads2 might take locks and we would deadlock in that
|
||||
* case
|
||||
*/
|
||||
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
|
||||
gst_collect_pads_stop (self->collect);
|
||||
gst_collect_pads2_stop (self->collect);
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
|
@ -879,7 +878,7 @@ gst_interleave_sink_event (GstPad * pad, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
ret = self->collect_event (pad, event);
|
||||
|
||||
gst_object_unref (self);
|
||||
|
@ -1160,7 +1159,7 @@ gst_interleave_src_event (GstPad * pad, GstEvent * event)
|
|||
/* check if we are flushing */
|
||||
if (flags & GST_SEEK_FLAG_FLUSH) {
|
||||
/* make sure we accept nothing anymore and return WRONG_STATE */
|
||||
gst_collect_pads_set_flushing (self->collect, TRUE);
|
||||
gst_collect_pads2_set_flushing (self->collect, TRUE);
|
||||
|
||||
/* flushing seek, start flush downstream, the flush will be done
|
||||
* when all pads received a FLUSH_STOP. */
|
||||
|
@ -1195,7 +1194,7 @@ gst_interleave_src_event (GstPad * pad, GstEvent * event)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
|
||||
gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
|
||||
{
|
||||
guint size;
|
||||
GstBuffer *outbuf;
|
||||
|
@ -1211,7 +1210,7 @@ gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
|
|||
g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED);
|
||||
g_return_val_if_fail (self->rate > 0, GST_FLOW_NOT_NEGOTIATED);
|
||||
|
||||
size = gst_collect_pads_available (pads);
|
||||
size = gst_collect_pads2_available (pads);
|
||||
|
||||
g_return_val_if_fail (size % width == 0, GST_FLOW_ERROR);
|
||||
|
||||
|
@ -1238,13 +1237,13 @@ gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
|
|||
memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels);
|
||||
|
||||
for (collected = pads->data; collected != NULL; collected = collected->next) {
|
||||
GstCollectData *cdata;
|
||||
GstCollectData2 *cdata;
|
||||
GstBuffer *inbuf;
|
||||
guint8 *outdata;
|
||||
|
||||
cdata = (GstCollectData *) collected->data;
|
||||
cdata = (GstCollectData2 *) collected->data;
|
||||
|
||||
inbuf = gst_collect_pads_take_buffer (pads, cdata, size);
|
||||
inbuf = gst_collect_pads2_take_buffer (pads, cdata, size);
|
||||
if (inbuf == NULL) {
|
||||
GST_DEBUG_OBJECT (cdata->pad, "No buffer available");
|
||||
goto next;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define __INTERLEAVE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -49,7 +49,7 @@ struct _GstInterleave
|
|||
GstElement element;
|
||||
|
||||
/*< private >*/
|
||||
GstCollectPads *collect;
|
||||
GstCollectPads2 *collect;
|
||||
|
||||
gint channels;
|
||||
gint padcounter;
|
||||
|
|
|
@ -65,6 +65,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
|
|
|
@ -226,11 +226,11 @@ static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
|
|||
static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
/* event */
|
||||
static gboolean gst_qt_mux_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
static gboolean gst_qt_mux_sink_event (GstCollectPads2 * pads,
|
||||
GstCollectData2 * data, GstEvent * event, gpointer user_data);
|
||||
|
||||
static GstFlowReturn gst_qt_mux_collected (GstCollectPads * pads,
|
||||
gpointer user_data);
|
||||
static GstFlowReturn gst_qt_mux_handle_buffer (GstCollectPads2 * pads,
|
||||
GstCollectData2 * cdata, GstBuffer * buf, gpointer user_data);
|
||||
static GstFlowReturn gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
|
||||
GstBuffer * buf);
|
||||
|
||||
|
@ -482,9 +482,13 @@ gst_qt_mux_init (GstQTMux * qtmux, GstQTMuxClass * qtmux_klass)
|
|||
gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad);
|
||||
|
||||
qtmux->sinkpads = NULL;
|
||||
qtmux->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (qtmux->collect,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_qt_mux_collected), qtmux);
|
||||
qtmux->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_buffer_function (qtmux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_qt_mux_handle_buffer), qtmux);
|
||||
gst_collect_pads2_set_event_function (qtmux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event), qtmux);
|
||||
gst_collect_pads2_set_clip_function (qtmux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), qtmux);
|
||||
|
||||
/* properties set to default upon construction */
|
||||
|
||||
|
@ -1661,7 +1665,7 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
|||
gst_buffer_unref (prefix);
|
||||
|
||||
for (walk = qtmux->sinkpads; walk && !fail; walk = g_slist_next (walk)) {
|
||||
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
|
||||
GstQTPad *qpad = (GstQTPad *) cdata;
|
||||
/* write info for each stream */
|
||||
fail = atoms_recov_write_trak_info (qtmux->moov_recov_file, qpad->trak);
|
||||
|
@ -1761,7 +1765,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
|||
|
||||
/* pushing last buffers for each pad */
|
||||
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
|
||||
GstQTPad *qtpad = (GstQTPad *) cdata;
|
||||
|
||||
/* avoid add_buffer complaining if not negotiated
|
||||
|
@ -1853,7 +1857,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
|||
/* check for late streams */
|
||||
first_ts = GST_CLOCK_TIME_NONE;
|
||||
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
|
||||
GstQTPad *qtpad = (GstQTPad *) cdata;
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
|
||||
|
@ -1866,7 +1870,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
|||
GST_TIME_ARGS (first_ts));
|
||||
/* add EDTSs for late streams */
|
||||
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
|
||||
GstQTPad *qtpad = (GstQTPad *) cdata;
|
||||
guint32 lateness;
|
||||
guint32 duration;
|
||||
|
@ -2520,14 +2524,13 @@ not_negotiated:
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||
gst_qt_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
|
||||
GstBuffer * buf, gpointer user_data)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstQTMux *qtmux = GST_QT_MUX_CAST (user_data);
|
||||
GSList *walk;
|
||||
GstQTPad *best_pad = NULL;
|
||||
GstClockTime time, best_time = GST_CLOCK_TIME_NONE;
|
||||
GstBuffer *buf;
|
||||
GstClockTime best_time = GST_CLOCK_TIME_NONE;
|
||||
|
||||
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_STARTED)) {
|
||||
if ((ret = gst_qt_mux_start_file (qtmux)) != GST_FLOW_OK)
|
||||
|
@ -2539,52 +2542,14 @@ gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
|
||||
return GST_FLOW_EOS;
|
||||
|
||||
/* select the best buffer */
|
||||
walk = qtmux->collect->data;
|
||||
while (walk) {
|
||||
GstQTPad *pad;
|
||||
GstCollectData *data;
|
||||
|
||||
data = (GstCollectData *) walk->data;
|
||||
pad = (GstQTPad *) data;
|
||||
|
||||
walk = g_slist_next (walk);
|
||||
|
||||
buf = gst_collect_pads_peek (pads, data);
|
||||
if (buf == NULL) {
|
||||
GST_LOG_OBJECT (qtmux, "Pad %s has no buffers",
|
||||
GST_PAD_NAME (pad->collect.pad));
|
||||
continue;
|
||||
}
|
||||
time = GST_BUFFER_TIMESTAMP (buf);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
/* invalid should pass */
|
||||
if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
time =
|
||||
gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME, time);
|
||||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
GST_DEBUG_OBJECT (qtmux, "clipping buffer on pad %s outside segment",
|
||||
GST_PAD_NAME (data->pad));
|
||||
buf = gst_collect_pads_pop (pads, data);
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time) ||
|
||||
(GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
|
||||
best_pad = pad;
|
||||
best_time = time;
|
||||
}
|
||||
}
|
||||
best_pad = (GstQTPad *) cdata;
|
||||
|
||||
/* clipping already converted to running time */
|
||||
if (best_pad != NULL) {
|
||||
g_assert (buf);
|
||||
best_time = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
|
||||
GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
|
||||
buf = gst_collect_pads_pop (pads, &best_pad->collect);
|
||||
buf = gst_buffer_make_writable (buf);
|
||||
GST_BUFFER_TIMESTAMP (buf) = best_time;
|
||||
ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
|
||||
} else {
|
||||
ret = gst_qt_mux_stop_file (qtmux);
|
||||
|
@ -3284,14 +3249,14 @@ refuse_renegotiation:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
gst_qt_mux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
|
||||
GstEvent * event, gpointer user_data)
|
||||
{
|
||||
gboolean ret;
|
||||
GstQTMux *qtmux;
|
||||
guint32 avg_bitrate = 0, max_bitrate = 0;
|
||||
GstPad *pad = data->pad;
|
||||
|
||||
qtmux = GST_QT_MUX_CAST (parent);
|
||||
|
||||
qtmux = GST_QT_MUX_CAST (user_data);
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:
|
||||
{
|
||||
|
@ -3316,8 +3281,9 @@ gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
GST_OBJECT_LOCK (qtmux);
|
||||
mode = gst_tag_setter_get_tag_merge_mode (setter);
|
||||
|
||||
GST_DEBUG_OBJECT (qtmux, "received tag event");
|
||||
gst_event_parse_tag (event, &list);
|
||||
GST_DEBUG_OBJECT (qtmux, "received tag event on pad %s:%s : %"
|
||||
GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (pad), list);
|
||||
|
||||
gst_tag_setter_merge_tags (setter, list, mode);
|
||||
GST_OBJECT_UNLOCK (qtmux);
|
||||
|
@ -3339,9 +3305,8 @@ gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
ret = qtmux->collect_event (pad, parent, event);
|
||||
|
||||
return ret;
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3363,7 +3328,7 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
}
|
||||
}
|
||||
|
||||
gst_collect_pads_remove_pad (mux->collect, pad);
|
||||
gst_collect_pads2_remove_pad (mux->collect, pad);
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
|
@ -3407,8 +3372,8 @@ gst_qt_mux_request_new_pad (GstElement * element,
|
|||
newpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
collect_pad = (GstQTPad *)
|
||||
gst_collect_pads_add_pad (qtmux->collect, newpad, sizeof (GstQTPad),
|
||||
(GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
|
||||
gst_collect_pads2_add_pad_full (qtmux->collect, newpad, sizeof (GstQTPad),
|
||||
(GstCollectData2DestroyNotify) (gst_qt_mux_pad_reset), TRUE);
|
||||
/* set up pad */
|
||||
gst_qt_mux_pad_reset (collect_pad);
|
||||
collect_pad->trak = atom_trak_new (qtmux->context);
|
||||
|
@ -3422,14 +3387,6 @@ gst_qt_mux_request_new_pad (GstElement * element,
|
|||
else
|
||||
collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
qtmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
|
||||
gst_pad_set_event_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event));
|
||||
|
||||
gst_pad_set_active (newpad, TRUE);
|
||||
gst_element_add_pad (element, newpad);
|
||||
|
||||
|
@ -3566,13 +3523,13 @@ gst_qt_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_collect_pads_start (qtmux->collect);
|
||||
gst_collect_pads2_start (qtmux->collect);
|
||||
qtmux->state = GST_QT_MUX_STATE_STARTED;
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
gst_collect_pads_stop (qtmux->collect);
|
||||
gst_collect_pads2_stop (qtmux->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#define __GST_QT_MUX_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
#include "fourcc.h"
|
||||
#include "atoms.h"
|
||||
|
@ -82,7 +82,7 @@ typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
|
|||
|
||||
struct _GstQTPad
|
||||
{
|
||||
GstCollectData collect; /* we extend the CollectData */
|
||||
GstCollectData2 collect; /* we extend the CollectData2 */
|
||||
|
||||
/* fourcc id of stream */
|
||||
guint32 fourcc;
|
||||
|
@ -145,7 +145,7 @@ struct _GstQTMux
|
|||
GstElement element;
|
||||
|
||||
GstPad *srcpad;
|
||||
GstCollectPads *collect;
|
||||
GstCollectPads2 *collect;
|
||||
GSList *sinkpads;
|
||||
|
||||
/* state */
|
||||
|
@ -192,9 +192,6 @@ struct _GstQTMux
|
|||
guint32 fragment_duration;
|
||||
gboolean streamable;
|
||||
|
||||
/* for collect pads event handling function */
|
||||
GstPadEventFunction collect_event;
|
||||
|
||||
/* for request pad naming */
|
||||
guint video_pads, audio_pads;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "gst/gst-i18n-plugin.h"
|
||||
|
||||
#include <glib/gprintf.h>
|
||||
|
@ -5317,8 +5321,13 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
|||
GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
|
||||
|
||||
/* make sure there's enough data */
|
||||
if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 2 * 4))
|
||||
goto corrupt_file;
|
||||
if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
|
||||
stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
|
||||
GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
|
||||
stream->n_sample_times);
|
||||
if (!stream->n_sample_times)
|
||||
goto corrupt_file;
|
||||
}
|
||||
|
||||
/* sync sample atom */
|
||||
stream->stps_present = FALSE;
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
@ -482,6 +486,8 @@ gst_matroska_demux_reset (GstElement * element)
|
|||
gst_buffer_unref (demux->common.cached_buffer);
|
||||
demux->common.cached_buffer = NULL;
|
||||
}
|
||||
|
||||
demux->invalid_duration = FALSE;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
|
@ -1356,10 +1362,12 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad,
|
|||
GST_OBJECT_LOCK (demux);
|
||||
if (context)
|
||||
gst_query_set_position (query, GST_FORMAT_TIME,
|
||||
context->pos - demux->stream_start_time);
|
||||
MAX (context->pos, demux->stream_start_time) -
|
||||
demux->stream_start_time);
|
||||
else
|
||||
gst_query_set_position (query, GST_FORMAT_TIME,
|
||||
demux->common.segment.position - demux->stream_start_time);
|
||||
MAX (demux->common.segment.position, demux->stream_start_time) -
|
||||
demux->stream_start_time);
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
} else if (format == GST_FORMAT_DEFAULT && context
|
||||
&& context->default_duration) {
|
||||
|
@ -1740,8 +1748,11 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time)
|
|||
otime = demux->common.segment.position;
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
|
||||
/* sanitize */
|
||||
time = MAX (time, demux->stream_start_time);
|
||||
|
||||
/* avoid division by zero in first estimation below */
|
||||
if (otime == 0)
|
||||
if (otime <= demux->stream_start_time)
|
||||
otime = time;
|
||||
|
||||
retry:
|
||||
|
@ -1918,6 +1929,14 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
* segment when we close the current segment. */
|
||||
memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment));
|
||||
|
||||
/* pull mode without index means that the actual duration is not known,
|
||||
* we might be playing a file that's still being recorded
|
||||
* so, invalidate our current duration, which is only a moving target,
|
||||
* and should not be used to clamp anything */
|
||||
if (!demux->streaming && !demux->common.index && demux->invalid_duration) {
|
||||
seeksegment.duration = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
GST_DEBUG_OBJECT (demux, "configuring seek");
|
||||
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
||||
|
@ -1932,6 +1951,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
}
|
||||
}
|
||||
|
||||
/* restore segment duration (if any effect),
|
||||
* would be determined again when parsing, but anyway ... */
|
||||
seeksegment.duration = demux->common.segment.duration;
|
||||
|
||||
flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
|
||||
keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
|
||||
|
||||
|
@ -1952,7 +1975,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
seeksegment.position, &demux->seek_index, &demux->seek_entry)) ==
|
||||
NULL) {
|
||||
/* pull mode without index can scan later on */
|
||||
if (demux->common.index || demux->streaming) {
|
||||
if (demux->streaming) {
|
||||
GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
return FALSE;
|
||||
|
@ -1989,7 +2012,7 @@ next:
|
|||
GST_PAD_STREAM_LOCK (demux->common.sinkpad);
|
||||
|
||||
/* pull mode without index can do some scanning */
|
||||
if (!demux->streaming && !demux->common.index) {
|
||||
if (!demux->streaming && !entry) {
|
||||
/* need to stop flushing upstream as we need it next */
|
||||
if (flush)
|
||||
gst_pad_push_event (demux->common.sinkpad,
|
||||
|
@ -2011,9 +2034,9 @@ next:
|
|||
if (keyunit) {
|
||||
GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
|
||||
seeksegment.start = entry->time;
|
||||
seeksegment.position = entry->time;
|
||||
seeksegment.time = entry->time - demux->stream_start_time;
|
||||
seeksegment.start = MAX (entry->time, demux->stream_start_time);
|
||||
seeksegment.position = seeksegment.start;
|
||||
seeksegment.time = seeksegment.start - demux->stream_start_time;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -3347,9 +3370,9 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
|||
else if (GST_CLOCK_TIME_IS_VALID (segment->position))
|
||||
segment_duration = segment->position - segment->start;
|
||||
segment->base += segment_duration / fabs (segment->rate);
|
||||
segment->start = lace_time;
|
||||
segment->start = MAX (lace_time, demux->stream_start_time);
|
||||
segment->stop = GST_CLOCK_TIME_NONE;
|
||||
segment->position = lace_time - demux->stream_start_time;
|
||||
segment->position = segment->start - demux->stream_start_time;
|
||||
/* now convey our segment notion downstream */
|
||||
gst_matroska_demux_send_event (demux, gst_event_new_segment (segment));
|
||||
demux->need_segment = FALSE;
|
||||
|
@ -3535,14 +3558,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
|||
|
||||
GST_OBJECT_LOCK (demux);
|
||||
if (demux->common.segment.duration == -1 ||
|
||||
demux->common.segment.duration <
|
||||
lace_time - demux->stream_start_time) {
|
||||
demux->stream_start_time + demux->common.segment.duration <
|
||||
last_stop_end) {
|
||||
demux->common.segment.duration =
|
||||
last_stop_end - demux->stream_start_time;
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
gst_element_post_message (GST_ELEMENT_CAST (demux),
|
||||
gst_message_new_duration (GST_OBJECT_CAST (demux),
|
||||
GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
|
||||
demux->invalid_duration = TRUE;
|
||||
} else {
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
}
|
||||
|
@ -4475,11 +4499,13 @@ pause:
|
|||
/* Close the segment, i.e. update segment stop with the duration
|
||||
* if no stop was set */
|
||||
if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
|
||||
!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) {
|
||||
!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) &&
|
||||
GST_CLOCK_TIME_IS_VALID (demux->common.segment.start) &&
|
||||
demux->last_stop_end > demux->common.segment.start) {
|
||||
GstSegment segment = demux->common.segment;
|
||||
GstEvent *event;
|
||||
|
||||
segment.stop = MAX (demux->last_stop_end, segment.start);
|
||||
segment.stop = demux->last_stop_end;
|
||||
event = gst_event_new_segment (&segment);
|
||||
gst_matroska_demux_send_event (demux, event);
|
||||
}
|
||||
|
|
|
@ -95,6 +95,9 @@ typedef struct _GstMatroskaDemux {
|
|||
|
||||
/* gap handling */
|
||||
guint64 max_gap_time;
|
||||
|
||||
/* for non-finalized files, with invalid segment duration */
|
||||
gboolean invalid_duration;
|
||||
} GstMatroskaDemux;
|
||||
|
||||
typedef struct _GstMatroskaDemuxClass {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
* (c) 2005 Michal Benes <michal.benes@xeris.cz>
|
||||
* (c) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
* (c) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
|
||||
*
|
||||
* matroska-mux.c: matroska file/stream muxer
|
||||
*
|
||||
|
@ -183,10 +184,14 @@ static GstStaticPadTemplate audiosink_templ =
|
|||
);
|
||||
|
||||
static GstStaticPadTemplate subtitlesink_templ =
|
||||
GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
|
||||
GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("subtitle/x-kate"));
|
||||
GST_STATIC_CAPS ("subtitle/x-kate; "
|
||||
"text/plain; application/x-ssa; application/x-ass; "
|
||||
"application/x-usf; video/x-dvd-subpicture; "
|
||||
"application/x-subtitle-unknown")
|
||||
);
|
||||
|
||||
static GArray *used_uids;
|
||||
G_LOCK_DEFINE_STATIC (used_uids);
|
||||
|
@ -199,8 +204,10 @@ G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT,
|
|||
static void gst_matroska_mux_finalize (GObject * object);
|
||||
|
||||
/* Pads collected callback */
|
||||
static GstFlowReturn
|
||||
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data);
|
||||
static GstFlowReturn gst_matroska_mux_handle_buffer (GstCollectPads2 * pads,
|
||||
GstCollectData2 * data, GstBuffer * buf, gpointer user_data);
|
||||
static gboolean gst_matroska_mux_handle_sink_event (GstCollectPads2 * pads,
|
||||
GstCollectData2 * data, GstEvent * event, gpointer user_data);
|
||||
|
||||
/* pad functions */
|
||||
static gboolean gst_matroska_mux_handle_src_event (GstPad * pad,
|
||||
|
@ -415,10 +422,13 @@ gst_matroska_mux_init (GstMatroskaMux * mux)
|
|||
gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
|
||||
gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
|
||||
|
||||
mux->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (mux->collect,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_matroska_mux_collected),
|
||||
mux);
|
||||
mux->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_clip_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), mux);
|
||||
gst_collect_pads2_set_buffer_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_buffer), mux);
|
||||
gst_collect_pads2_set_event_function (mux->collect,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event), mux);
|
||||
|
||||
mux->ebml_write = gst_ebml_write_new (mux->srcpad);
|
||||
mux->doctype = GST_MATROSKA_DOCTYPE_MATROSKA;
|
||||
|
@ -535,12 +545,6 @@ gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
|
|||
collect_pad->track = NULL;
|
||||
}
|
||||
|
||||
/* free cached buffer */
|
||||
if (collect_pad->buffer != NULL) {
|
||||
gst_buffer_unref (collect_pad->buffer);
|
||||
collect_pad->buffer = NULL;
|
||||
}
|
||||
|
||||
if (!full && type != 0) {
|
||||
GstMatroskaTrackContext *context;
|
||||
|
||||
|
@ -568,7 +572,6 @@ gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
|
|||
/* TODO: check default values for the context */
|
||||
context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
|
||||
collect_pad->track = context;
|
||||
collect_pad->buffer = NULL;
|
||||
collect_pad->duration = 0;
|
||||
collect_pad->start_ts = GST_CLOCK_TIME_NONE;
|
||||
collect_pad->end_ts = GST_CLOCK_TIME_NONE;
|
||||
|
@ -665,6 +668,44 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
|
|||
return gst_pad_event_default (pad, parent, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_matroska_mux_build_vobsub_private (GstMatroskaTrackContext * context,
|
||||
const guint * clut)
|
||||
{
|
||||
gchar *clutv[17];
|
||||
gchar *sclut;
|
||||
gint i;
|
||||
guint32 col;
|
||||
gdouble y, u, v;
|
||||
guint8 r, g, b;
|
||||
|
||||
/* produce comma-separated list in hex format */
|
||||
for (i = 0; i < 16; ++i) {
|
||||
col = clut[i];
|
||||
/* replicate vobsub's slightly off RGB conversion calculation */
|
||||
y = (((col >> 16) & 0xff) - 16) * 255 / 219;
|
||||
u = ((col >> 8) & 0xff) - 128;
|
||||
v = (col & 0xff) - 128;
|
||||
r = CLAMP (1.0 * y + 1.4022 * u, 0, 255);
|
||||
g = CLAMP (1.0 * y - 0.3456 * u - 0.7145 * v, 0, 255);
|
||||
b = CLAMP (1.0 * y + 1.7710 * v, 0, 255);
|
||||
clutv[i] = g_strdup_printf ("%02x%02x%02x", r, g, b);
|
||||
}
|
||||
clutv[i] = NULL;
|
||||
sclut = g_strjoinv (",", clutv);
|
||||
|
||||
/* build codec private; only palette for now */
|
||||
g_free (context->codec_priv);
|
||||
context->codec_priv = (guint8 *) g_strdup_printf ("palette: %s", sclut);
|
||||
/* include terminating 0 */
|
||||
context->codec_priv_size = strlen ((gchar *) context->codec_priv) + 1;
|
||||
g_free (sclut);
|
||||
for (i = 0; i < 16; ++i) {
|
||||
g_free (clutv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_handle_sink_event:
|
||||
* @pad: Pad which received the event.
|
||||
|
@ -675,14 +716,21 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
|
|||
* Returns: #TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
gst_matroska_mux_handle_sink_event (GstCollectPads2 * pads,
|
||||
GstCollectData2 * data, GstEvent * event, gpointer user_data)
|
||||
{
|
||||
GstMatroskaTrackContext *context;
|
||||
GstMatroskaPad *collect_pad;
|
||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
|
||||
GstMatroskaTrackContext *context;
|
||||
GstMatroskaMux *mux;
|
||||
GstPad *pad;
|
||||
GstTagList *list;
|
||||
gboolean ret = TRUE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
mux = GST_MATROSKA_MUX (user_data);
|
||||
collect_pad = (GstMatroskaPad *) data;
|
||||
pad = data->pad;
|
||||
context = collect_pad->track;
|
||||
g_assert (context);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:{
|
||||
|
@ -702,11 +750,6 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
GST_DEBUG_OBJECT (mux, "received tag event");
|
||||
gst_event_parse_tag (event, &list);
|
||||
|
||||
collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
|
||||
g_assert (collect_pad);
|
||||
context = collect_pad->track;
|
||||
g_assert (context);
|
||||
|
||||
/* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
|
||||
if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
|
||||
const gchar *lang_code;
|
||||
|
@ -735,7 +778,6 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
|
||||
gst_event_parse_segment (event, &segment);
|
||||
if (segment->format != GST_FORMAT_TIME) {
|
||||
ret = FALSE;
|
||||
gst_event_unref (event);
|
||||
event = NULL;
|
||||
}
|
||||
|
@ -749,6 +791,31 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
gst_event_replace (&mux->force_key_unit_event, NULL);
|
||||
mux->force_key_unit_event = event;
|
||||
event = NULL;
|
||||
} else if (gst_structure_has_name (structure, "application/x-gst-dvd") &&
|
||||
!strcmp ("dvd-spu-clut-change",
|
||||
gst_structure_get_string (structure, "event"))) {
|
||||
gchar name[16];
|
||||
gint i, value;
|
||||
guint clut[16];
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "New DVD colour table received");
|
||||
if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
|
||||
GST_DEBUG_OBJECT (pad, "... discarding");
|
||||
break;
|
||||
}
|
||||
/* first transform event data into table form */
|
||||
for (i = 0; i < 16; i++) {
|
||||
g_snprintf (name, sizeof (name), "clut%02d", i);
|
||||
if (!gst_structure_get_int (structure, name, &value)) {
|
||||
GST_ERROR_OBJECT (mux, "dvd-spu-clut-change event did not "
|
||||
"contain %s field", name);
|
||||
break;
|
||||
}
|
||||
clut[i] = value;
|
||||
}
|
||||
|
||||
/* transform into private data for stream; text form */
|
||||
gst_matroska_mux_build_vobsub_private (context, clut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -756,13 +823,19 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
|||
break;
|
||||
}
|
||||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
if (event)
|
||||
ret = mux->collect_event (pad, parent, event);
|
||||
|
||||
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
|
||||
const char *id)
|
||||
{
|
||||
g_assert (context && id);
|
||||
if (context->codec_id)
|
||||
g_free (context->codec_id);
|
||||
context->codec_id = g_strdup (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_video_pad_setcaps:
|
||||
|
@ -872,12 +945,13 @@ skip_details:
|
|||
/* find type */
|
||||
if (!strcmp (mimetype, "video/x-raw")) {
|
||||
const gchar *fstr;
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
|
||||
fstr = gst_structure_get_string (structure, "format");
|
||||
if (fstr && strlen (fstr) == 4)
|
||||
videocontext->fourcc = GST_STR_FOURCC (fstr);
|
||||
} else if (!strcmp (mimetype, "image/jpeg")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
|
||||
} else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
|
||||
||!strcmp (mimetype, "video/x-huffyuv")
|
||||
|| !strcmp (mimetype, "video/x-divx")
|
||||
|
@ -970,11 +1044,13 @@ skip_details:
|
|||
(guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
|
||||
}
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
|
||||
context->codec_priv = (gpointer) bih;
|
||||
context->codec_priv_size = size;
|
||||
} else if (!strcmp (mimetype, "video/x-h264")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
|
||||
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
|
@ -991,7 +1067,7 @@ skip_details:
|
|||
} else if (!strcmp (mimetype, "video/x-theora")) {
|
||||
const GValue *streamheader;
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
|
||||
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
|
@ -1006,22 +1082,25 @@ skip_details:
|
|||
goto refuse_caps;
|
||||
}
|
||||
} else if (!strcmp (mimetype, "video/x-dirac")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
|
||||
} else if (!strcmp (mimetype, "video/x-vp8")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VP8);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP8);
|
||||
} else if (!strcmp (mimetype, "video/mpeg")) {
|
||||
gint mpegversion;
|
||||
|
||||
gst_structure_get_int (structure, "mpegversion", &mpegversion);
|
||||
switch (mpegversion) {
|
||||
case 1:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
|
||||
break;
|
||||
case 2:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
|
||||
break;
|
||||
case 4:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
|
||||
break;
|
||||
default:
|
||||
goto refuse_caps;
|
||||
|
@ -1044,16 +1123,20 @@ skip_details:
|
|||
gst_structure_get_int (structure, "rmversion", &rmversion);
|
||||
switch (rmversion) {
|
||||
case 1:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
|
||||
break;
|
||||
case 2:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
|
||||
break;
|
||||
case 3:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
|
||||
break;
|
||||
case 4:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
|
||||
break;
|
||||
default:
|
||||
goto refuse_caps;
|
||||
|
@ -1551,13 +1634,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
|
||||
switch (layer) {
|
||||
case 1:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
|
||||
break;
|
||||
case 2:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
|
||||
break;
|
||||
case 3:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
|
||||
break;
|
||||
default:
|
||||
goto refuse_caps;
|
||||
|
@ -1620,14 +1706,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
goto refuse_caps;
|
||||
}
|
||||
if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
|
||||
else
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
|
||||
break;
|
||||
|
||||
case GST_AUDIO_FORMAT_F32LE:
|
||||
case GST_AUDIO_FORMAT_F64LE:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1636,11 +1724,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
}
|
||||
|
||||
audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
|
||||
|
||||
} else if (!strcmp (mimetype, "audio/x-vorbis")) {
|
||||
const GValue *streamheader;
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
|
||||
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
|
@ -1657,7 +1744,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
} else if (!strcmp (mimetype, "audio/x-flac")) {
|
||||
const GValue *streamheader;
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
context->codec_priv = NULL;
|
||||
|
@ -1673,7 +1760,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
} else if (!strcmp (mimetype, "audio/x-speex")) {
|
||||
const GValue *streamheader;
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
context->codec_priv = NULL;
|
||||
|
@ -1687,11 +1774,11 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
goto refuse_caps;
|
||||
}
|
||||
} else if (!strcmp (mimetype, "audio/x-ac3")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AC3);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_AC3);
|
||||
} else if (!strcmp (mimetype, "audio/x-eac3")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
|
||||
} else if (!strcmp (mimetype, "audio/x-dts")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_DTS);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_DTS);
|
||||
} else if (!strcmp (mimetype, "audio/x-tta")) {
|
||||
gint width;
|
||||
|
||||
|
@ -1700,7 +1787,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
|
||||
gst_structure_get_int (structure, "width", &width);
|
||||
audiocontext->bitdepth = width;
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_TTA);
|
||||
|
||||
} else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
|
||||
gint raversion;
|
||||
|
@ -1709,13 +1796,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gst_structure_get_int (structure, "raversion", &raversion);
|
||||
switch (raversion) {
|
||||
case 1:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
|
||||
break;
|
||||
case 2:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
|
||||
break;
|
||||
case 8:
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
|
||||
break;
|
||||
default:
|
||||
goto refuse_caps;
|
||||
|
@ -1816,7 +1906,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
(guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
|
||||
}
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
|
||||
context->codec_priv = (gpointer) codec_priv;
|
||||
context->codec_priv_size = codec_priv_size;
|
||||
}
|
||||
|
@ -1832,6 +1922,10 @@ refuse_caps:
|
|||
}
|
||||
}
|
||||
|
||||
/* we probably don't have the data at start,
|
||||
* so have to reserve (a maximum) space to write this at the end.
|
||||
* bit spacy, but some formats can hold quite some */
|
||||
#define SUBTITLE_MAX_CODEC_PRIVATE 2048 /* must be > 128 */
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_subtitle_pad_setcaps:
|
||||
|
@ -1845,11 +1939,6 @@ refuse_caps:
|
|||
static gboolean
|
||||
gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
/* FIXME:
|
||||
* Consider this as boilerplate code for now. There is
|
||||
* no single subtitle creation element in GStreamer,
|
||||
* neither do I know how subtitling works at all. */
|
||||
|
||||
/* There is now (at least) one such alement (kateenc), and I'm going
|
||||
to handle it here and claim it works when it can be piped back
|
||||
through GStreamer and VLC */
|
||||
|
@ -1860,6 +1949,10 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstMatroskaPad *collect_pad;
|
||||
const gchar *mimetype;
|
||||
GstStructure *structure;
|
||||
const GValue *value = NULL;
|
||||
GstBuffer *buf = NULL;
|
||||
gchar *id = NULL;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
|
||||
|
||||
|
@ -1874,17 +1967,19 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
structure = gst_caps_get_structure (caps, 0);
|
||||
mimetype = gst_structure_get_name (structure);
|
||||
|
||||
/* keep track of default set in request_pad */
|
||||
id = context->codec_id;
|
||||
|
||||
/* general setup */
|
||||
scontext->check_utf8 = 1;
|
||||
scontext->invalid_utf8 = 0;
|
||||
context->default_duration = 0;
|
||||
|
||||
/* TODO: - other format than Kate */
|
||||
|
||||
if (!strcmp (mimetype, "subtitle/x-kate")) {
|
||||
const GValue *streamheader;
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
|
||||
|
||||
if (context->codec_priv != NULL) {
|
||||
g_free (context->codec_priv);
|
||||
|
@ -1896,12 +1991,64 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
if (!kate_streamheader_to_codecdata (streamheader, context)) {
|
||||
GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
|
||||
("kate stream headers missing or malformed"));
|
||||
return FALSE;
|
||||
ret = FALSE;
|
||||
goto exit;
|
||||
}
|
||||
return TRUE;
|
||||
} else if (!strcmp (mimetype, "text/plain")) {
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
|
||||
} else if (!strcmp (mimetype, "application/x-ssa")) {
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
|
||||
} else if (!strcmp (mimetype, "application/x-ass")) {
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
|
||||
} else if (!strcmp (mimetype, "application/x-usf")) {
|
||||
gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
|
||||
} else if (!strcmp (mimetype, "video/x-dvd-subpicture")) {
|
||||
gst_matroska_mux_set_codec_id (context,
|
||||
GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
|
||||
} else {
|
||||
id = NULL;
|
||||
ret = FALSE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
/* maybe some private data, e.g. vobsub */
|
||||
value = gst_structure_get_value (structure, "codec_data");
|
||||
if (value)
|
||||
buf = gst_value_get_buffer (value);
|
||||
if (buf != NULL) {
|
||||
guint8 *priv_data = NULL, *priv_buffer_data;
|
||||
gsize priv_data_size = 0;
|
||||
|
||||
priv_buffer_data =
|
||||
gst_buffer_map (buf, &priv_data_size, NULL, GST_MAP_READ);
|
||||
if (priv_data_size > SUBTITLE_MAX_CODEC_PRIVATE) {
|
||||
GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
|
||||
" exceeded maximum (%d); discarding", pad,
|
||||
SUBTITLE_MAX_CODEC_PRIVATE);
|
||||
gst_buffer_unmap (buf, priv_data, priv_data_size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (context->codec_priv != NULL)
|
||||
g_free (context->codec_priv);
|
||||
|
||||
priv_data = g_malloc0 (priv_data_size);
|
||||
memcpy (priv_data, priv_buffer_data, priv_data_size);
|
||||
context->codec_priv = priv_data;
|
||||
context->codec_priv_size = priv_data_size;
|
||||
gst_buffer_unmap (buf, priv_buffer_data, priv_data_size);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %u",
|
||||
GST_STR_NULL (context->codec_id), context->codec_priv_size);
|
||||
|
||||
exit:
|
||||
/* free default if modified */
|
||||
if (id)
|
||||
g_free (id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1928,6 +2075,8 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
GstMatroskaCapsFunc capsfunc = NULL;
|
||||
GstMatroskaTrackContext *context = NULL;
|
||||
gint pad_id;
|
||||
gboolean locked = TRUE;
|
||||
gchar *id = NULL;
|
||||
|
||||
if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
|
||||
/* don't mix named and unnamed pads, if the pad already exists we fail when
|
||||
|
@ -1971,6 +2120,9 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
g_new0 (GstMatroskaTrackSubtitleContext, 1);
|
||||
context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
|
||||
context->name = g_strdup ("Subtitle");
|
||||
/* setcaps may only provide proper one a lot later */
|
||||
id = g_strdup ("S_SUB_UNKNOWN");
|
||||
locked = FALSE;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (mux, "This is not our template!");
|
||||
return NULL;
|
||||
|
@ -1982,24 +2134,13 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
|
||||
gst_matroskamux_pad_init (newpad);
|
||||
collect_pad = (GstMatroskaPad *)
|
||||
gst_collect_pads_add_pad (mux->collect, GST_PAD (newpad),
|
||||
sizeof (GstMatroskaPad),
|
||||
(GstCollectDataDestroyNotify) gst_matroska_pad_free);
|
||||
gst_collect_pads2_add_pad_full (mux->collect, GST_PAD (newpad),
|
||||
sizeof (GstMatroskamuxPad),
|
||||
(GstCollectData2DestroyNotify) gst_matroska_pad_free, locked);
|
||||
|
||||
collect_pad->track = context;
|
||||
gst_matroska_pad_reset (collect_pad, FALSE);
|
||||
|
||||
/* 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.
|
||||
* TODO GstCollectPads should really give its 'users' a clean chance to
|
||||
* properly handle events that are not meant for collectpads itself.
|
||||
* Perhaps a callback or so, though rejected (?) in #340060.
|
||||
* This would allow (clean) transcoding of info from demuxer/streams
|
||||
* to another muxer */
|
||||
mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
|
||||
gst_pad_set_event_function (GST_PAD (newpad),
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event));
|
||||
collect_pad->track->codec_id = id;
|
||||
|
||||
collect_pad->capsfunc = capsfunc;
|
||||
gst_pad_set_active (GST_PAD (newpad), TRUE);
|
||||
|
@ -2037,7 +2178,7 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
|
||||
|
||||
for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
|
||||
GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
|
||||
|
||||
if (cdata->pad == pad) {
|
||||
|
@ -2058,7 +2199,7 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
|
|||
}
|
||||
}
|
||||
|
||||
gst_collect_pads_remove_pad (mux->collect, pad);
|
||||
gst_collect_pads2_remove_pad (mux->collect, pad);
|
||||
if (gst_element_remove_pad (element, pad))
|
||||
mux->num_streams--;
|
||||
}
|
||||
|
@ -2095,6 +2236,14 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
|
|||
context->language);
|
||||
}
|
||||
|
||||
/* FIXME: until we have a nice way of getting the codecname
|
||||
* out of the caps, I'm not going to enable this. Too much
|
||||
* (useless, double, boring) work... */
|
||||
/* TODO: Use value from tags if any */
|
||||
/*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
|
||||
context->codec_name); */
|
||||
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
|
||||
|
||||
/* type-specific stuff */
|
||||
switch (context->type) {
|
||||
case GST_MATROSKA_TRACK_TYPE_VIDEO:{
|
||||
|
@ -2145,6 +2294,24 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
|
|||
break;
|
||||
}
|
||||
|
||||
/* this is what we write for now and must be filled
|
||||
* and remainder void'ed later on */
|
||||
#define SUBTITLE_DUMMY_SIZE (1 + 1 + 14 + 1 + 2 + SUBTITLE_MAX_CODEC_PRIVATE)
|
||||
|
||||
case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
|
||||
gpointer buf;
|
||||
|
||||
context->pos = ebml->pos;
|
||||
/* CodecID is mandatory ... */
|
||||
gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, "S_SUB_UNKNOWN");
|
||||
/* reserve space */
|
||||
buf = g_malloc0 (SUBTITLE_MAX_CODEC_PRIVATE);
|
||||
gst_ebml_write_binary (ebml, GST_EBML_ID_VOID, buf,
|
||||
SUBTITLE_MAX_CODEC_PRIVATE);
|
||||
g_free (buf);
|
||||
/* real data has to be written at finish */
|
||||
return;
|
||||
}
|
||||
default:
|
||||
/* doesn't need type-specific data */
|
||||
break;
|
||||
|
@ -2154,13 +2321,6 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
|
|||
if (context->codec_priv)
|
||||
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
|
||||
context->codec_priv, context->codec_priv_size);
|
||||
/* FIXME: until we have a nice way of getting the codecname
|
||||
* out of the caps, I'm not going to enable this. Too much
|
||||
* (useless, double, boring) work... */
|
||||
/* TODO: Use value from tags if any */
|
||||
/*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
|
||||
context->codec_name); */
|
||||
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2230,7 +2390,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||
if (tags != NULL && !gst_tag_list_is_empty (tags)) {
|
||||
guint64 master_tags, master_tag;
|
||||
|
||||
GST_DEBUG ("Writing tags");
|
||||
GST_DEBUG_OBJECT (mux, "Writing tags");
|
||||
|
||||
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
|
||||
mux->tags_pos = ebml->pos;
|
||||
|
@ -2304,7 +2464,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||
child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
|
||||
gst_matroska_mux_track_header (mux, collect_pad->track);
|
||||
gst_ebml_write_master_finish (ebml, child);
|
||||
/* some remaing pad/track setup */
|
||||
/* some remaining pad/track setup */
|
||||
collect_pad->default_duration_scaled =
|
||||
gst_util_uint64_scale (collect_pad->track->default_duration,
|
||||
1, mux->time_scale);
|
||||
|
@ -2431,7 +2591,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||
if (tags != NULL && !gst_tag_list_is_empty (tags)) {
|
||||
guint64 master_tags, master_tag;
|
||||
|
||||
GST_DEBUG ("Writing tags");
|
||||
GST_DEBUG_OBJECT (mux, "Writing tags");
|
||||
|
||||
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
|
||||
mux->tags_pos = ebml->pos;
|
||||
|
@ -2479,16 +2639,23 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||
gst_ebml_write_seek (ebml, my_pos);
|
||||
}
|
||||
|
||||
/* update duration */
|
||||
/* first get the overall duration */
|
||||
/* a released track may have left a duration in here */
|
||||
/* loop tracks:
|
||||
* - first get the overall duration
|
||||
* (a released track may have left a duration in here)
|
||||
* - write some track header data for subtitles
|
||||
*/
|
||||
duration = mux->duration;
|
||||
pos = ebml->pos;
|
||||
for (collected = mux->collect->data; collected;
|
||||
collected = g_slist_next (collected)) {
|
||||
GstMatroskaPad *collect_pad;
|
||||
GstClockTime min_duration; /* observed minimum duration */
|
||||
GstMatroskaTrackContext *context;
|
||||
gint voidleft = 0, fill = 0;
|
||||
gpointer codec_id;
|
||||
|
||||
collect_pad = (GstMatroskaPad *) collected->data;
|
||||
context = collect_pad->track;
|
||||
|
||||
GST_DEBUG_OBJECT (mux,
|
||||
"Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
|
||||
|
@ -2510,7 +2677,41 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||
if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
|
||||
duration < collect_pad->duration)
|
||||
duration = collect_pad->duration;
|
||||
|
||||
if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE || !context->pos)
|
||||
continue;
|
||||
|
||||
again:
|
||||
/* write subtitle type and possible private data */
|
||||
gst_ebml_write_seek (ebml, context->pos);
|
||||
/* complex way to write ascii to account for extra filling */
|
||||
codec_id = g_malloc0 (strlen (context->codec_id) + 1 + fill);
|
||||
strcpy (codec_id, context->codec_id);
|
||||
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECID,
|
||||
codec_id, strlen (context->codec_id) + 1 + fill);
|
||||
g_free (codec_id);
|
||||
if (context->codec_priv)
|
||||
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
|
||||
context->codec_priv, context->codec_priv_size);
|
||||
voidleft = SUBTITLE_DUMMY_SIZE - (ebml->pos - context->pos);
|
||||
/* void'ify; sigh, variable sized length field */
|
||||
if (voidleft == 1) {
|
||||
fill = 1;
|
||||
goto again;
|
||||
} else if (voidleft && voidleft <= 128)
|
||||
gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 2);
|
||||
else if (voidleft >= 130)
|
||||
gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 3);
|
||||
else if (voidleft == 129) {
|
||||
gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 64);
|
||||
gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 63);
|
||||
}
|
||||
}
|
||||
|
||||
/* seek back (optional, but do anyway) */
|
||||
gst_ebml_write_seek (ebml, pos);
|
||||
|
||||
/* update duration */
|
||||
if (duration != 0) {
|
||||
GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (duration));
|
||||
|
@ -2533,77 +2734,6 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||
gst_ebml_write_master_finish (ebml, mux->segment_pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_best_pad:
|
||||
* @mux: #GstMatroskaMux
|
||||
* @popped: True if at least one buffer was popped from #GstCollectPads
|
||||
*
|
||||
* Find a pad with the oldest data
|
||||
* (data from this pad should be written first).
|
||||
*
|
||||
* Returns: Selected pad.
|
||||
*/
|
||||
static GstMatroskaPad *
|
||||
gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
|
||||
{
|
||||
GSList *collected;
|
||||
GstMatroskaPad *best = NULL;
|
||||
|
||||
*popped = FALSE;
|
||||
for (collected = mux->collect->data; collected;
|
||||
collected = g_slist_next (collected)) {
|
||||
GstMatroskaPad *collect_pad;
|
||||
|
||||
collect_pad = (GstMatroskaPad *) collected->data;
|
||||
/* fetch a new buffer if needed */
|
||||
if (collect_pad->buffer == NULL) {
|
||||
collect_pad->buffer = gst_collect_pads_pop (mux->collect,
|
||||
(GstCollectData *) collect_pad);
|
||||
|
||||
if (collect_pad->buffer != NULL) {
|
||||
GstClockTime time;
|
||||
|
||||
*popped = TRUE;
|
||||
/* convert to running time */
|
||||
time = GST_BUFFER_TIMESTAMP (collect_pad->buffer);
|
||||
/* invalid should pass */
|
||||
if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
time = gst_segment_to_running_time (&collect_pad->collect.segment,
|
||||
GST_FORMAT_TIME, time);
|
||||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
|
||||
GST_DEBUG_OBJECT (mux, "clipping buffer on pad %s outside segment",
|
||||
GST_PAD_NAME (collect_pad->collect.pad));
|
||||
gst_buffer_unref (collect_pad->buffer);
|
||||
collect_pad->buffer = NULL;
|
||||
return NULL;
|
||||
} else {
|
||||
GST_LOG_OBJECT (mux, "buffer ts %" GST_TIME_FORMAT " -> %"
|
||||
GST_TIME_FORMAT " running time",
|
||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
|
||||
GST_TIME_ARGS (time));
|
||||
collect_pad->buffer =
|
||||
gst_buffer_make_writable (collect_pad->buffer);
|
||||
GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if we have a buffer check if it is better then the current best one */
|
||||
if (collect_pad->buffer != NULL) {
|
||||
if (best == NULL || !GST_BUFFER_TIMESTAMP_IS_VALID (collect_pad->buffer)
|
||||
|| (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)
|
||||
&& GST_BUFFER_TIMESTAMP (collect_pad->buffer) <
|
||||
GST_BUFFER_TIMESTAMP (best->buffer))) {
|
||||
best = collect_pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_buffer_header:
|
||||
* @track: Track context.
|
||||
|
@ -2749,10 +2879,11 @@ gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
|
|||
* Returns: Result of the gst_pad_push issued to write the data.
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
||||
gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||
GstBuffer * buf)
|
||||
{
|
||||
GstEbmlWrite *ebml = mux->ebml_write;
|
||||
GstBuffer *buf, *hdr;
|
||||
GstBuffer *hdr;
|
||||
guint64 blockgroup;
|
||||
gboolean write_duration;
|
||||
gint16 relative_timestamp;
|
||||
|
@ -2762,8 +2893,6 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
|||
GstMatroskamuxPad *pad;
|
||||
|
||||
/* write data */
|
||||
buf = collect_pad->buffer;
|
||||
collect_pad->buffer = NULL;
|
||||
pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
|
||||
|
||||
/* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
|
||||
|
@ -2953,10 +3082,9 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_matroska_mux_collected:
|
||||
* @pads: #GstCollectPads
|
||||
* gst_matroska_mux_handle_buffer:
|
||||
* @pads: #GstCollectPads2
|
||||
* @uuser_data: #GstMatroskaMux
|
||||
*
|
||||
* Collectpads callback.
|
||||
|
@ -2964,12 +3092,12 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
|||
* Returns: #GstFlowReturn
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||
gst_matroska_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
|
||||
GstBuffer * buf, gpointer user_data)
|
||||
{
|
||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
||||
GstEbmlWrite *ebml = mux->ebml_write;
|
||||
GstMatroskaPad *best;
|
||||
gboolean popped;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
GST_DEBUG_OBJECT (mux, "Collected pads");
|
||||
|
@ -2988,53 +3116,53 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
|||
mux->state = GST_MATROSKA_MUX_STATE_DATA;
|
||||
}
|
||||
|
||||
do {
|
||||
/* which stream to write from? */
|
||||
best = gst_matroska_mux_best_pad (mux, &popped);
|
||||
/* provided with stream to write from */
|
||||
best = (GstMatroskaPad *) data;
|
||||
|
||||
/* if there is no best pad, we have reached EOS */
|
||||
if (best == NULL) {
|
||||
/* buffer popped, but none returned means it was clipped */
|
||||
if (popped)
|
||||
break;
|
||||
GST_DEBUG_OBJECT (mux, "No best pad finishing...");
|
||||
if (!mux->streamable) {
|
||||
gst_matroska_mux_finish (mux);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
|
||||
}
|
||||
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
|
||||
ret = GST_FLOW_EOS;
|
||||
break;
|
||||
/* if there is no best pad, we have reached EOS */
|
||||
if (best == NULL) {
|
||||
GST_DEBUG_OBJECT (mux, "No best pad finishing...");
|
||||
if (!mux->streamable) {
|
||||
gst_matroska_mux_finish (mux);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
|
||||
}
|
||||
GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
|
||||
GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
|
||||
GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
|
||||
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
|
||||
ret = GST_FLOW_EOS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* make note of first and last encountered timestamps, so we can calculate
|
||||
* the actual duration later when we send an updated header on eos */
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
|
||||
GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
|
||||
GstClockTime end_ts = start_ts;
|
||||
/* if we have a best stream, should also have a buffer */
|
||||
g_assert (buf);
|
||||
|
||||
if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
|
||||
end_ts += GST_BUFFER_DURATION (best->buffer);
|
||||
else if (best->track->default_duration)
|
||||
end_ts += best->track->default_duration;
|
||||
GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
|
||||
GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
|
||||
best->end_ts = end_ts;
|
||||
/* make note of first and last encountered timestamps, so we can calculate
|
||||
* the actual duration later when we send an updated header on eos */
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
|
||||
GstClockTime end_ts = start_ts;
|
||||
|
||||
if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
|
||||
start_ts < best->start_ts))
|
||||
best->start_ts = start_ts;
|
||||
}
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buf))
|
||||
end_ts += GST_BUFFER_DURATION (buf);
|
||||
else if (best->track->default_duration)
|
||||
end_ts += best->track->default_duration;
|
||||
|
||||
/* write one buffer */
|
||||
ret = gst_matroska_mux_write_data (mux, best);
|
||||
} while (ret == GST_FLOW_OK && !popped);
|
||||
if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
|
||||
best->end_ts = end_ts;
|
||||
|
||||
if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
|
||||
start_ts < best->start_ts))
|
||||
best->start_ts = start_ts;
|
||||
}
|
||||
|
||||
/* write one buffer */
|
||||
ret = gst_matroska_mux_write_data (mux, best, buf);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3058,12 +3186,12 @@ gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_collect_pads_start (mux->collect);
|
||||
gst_collect_pads2_start (mux->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
gst_collect_pads_stop (mux->collect);
|
||||
gst_collect_pads2_stop (mux->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define __GST_MATROSKA_MUX_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
#include "ebml-write.h"
|
||||
#include "matroska-ids.h"
|
||||
|
@ -58,12 +58,10 @@ typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps);
|
|||
/* all information needed for one matroska stream */
|
||||
typedef struct
|
||||
{
|
||||
GstCollectData collect; /* we extend the CollectData */
|
||||
GstCollectData2 collect; /* we extend the CollectData */
|
||||
GstMatroskaCapsFunc capsfunc;
|
||||
GstMatroskaTrackContext *track;
|
||||
|
||||
GstBuffer *buffer; /* the queued buffer for this pad */
|
||||
|
||||
guint64 duration;
|
||||
GstClockTime start_ts;
|
||||
GstClockTime end_ts; /* last timestamp + (if available) duration */
|
||||
|
@ -79,8 +77,7 @@ typedef struct _GstMatroskaMux {
|
|||
|
||||
/* pads */
|
||||
GstPad *srcpad;
|
||||
GstCollectPads *collect;
|
||||
GstPadEventFunction collect_event;
|
||||
GstCollectPads2 *collect;
|
||||
GstEbmlWrite *ebml_write;
|
||||
|
||||
guint num_streams,
|
||||
|
|
|
@ -999,6 +999,21 @@ gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
|
|||
|
||||
DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
|
||||
|
||||
/* (e.g.) lavf typically creates entries without a block number,
|
||||
* which is bogus and leads to contradictory information */
|
||||
if (common->index->len) {
|
||||
GstMatroskaIndex *last_idx;
|
||||
|
||||
last_idx = &g_array_index (common->index, GstMatroskaIndex,
|
||||
common->index->len - 1);
|
||||
if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
|
||||
last_idx->track == idx.track && idx.time > last_idx->time) {
|
||||
GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
|
||||
"but has different time than previous entry; discarding");
|
||||
idx.track = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
|
||||
&& idx.pos != (guint64) - 1 && idx.track > 0) {
|
||||
g_array_append_val (common->index, idx);
|
||||
|
|
|
@ -655,12 +655,17 @@ write_error:
|
|||
return GST_FLOW_ERROR;
|
||||
}
|
||||
stdio_write_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
|
||||
("Error while writing to file."), (NULL));
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
return GST_FLOW_ERROR;
|
||||
switch (errno) {
|
||||
case ENOSPC:
|
||||
GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT,
|
||||
("Error while writing to file."), ("%s", g_strerror (errno)));
|
||||
break;
|
||||
default:
|
||||
GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
|
||||
("Error while writing to file."), ("%s", g_strerror (errno)));
|
||||
}
|
||||
gst_buffer_unmap (buffer, data, size);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -84,7 +84,7 @@ static GstPad *gst_multipart_mux_request_new_pad (GstElement * element,
|
|||
static GstStateChangeReturn gst_multipart_mux_change_state (GstElement *
|
||||
element, GstStateChange transition);
|
||||
|
||||
static GstFlowReturn gst_multipart_mux_collected (GstCollectPads * pads,
|
||||
static GstFlowReturn gst_multipart_mux_collected (GstCollectPads2 * pads,
|
||||
GstMultipartMux * mux);
|
||||
|
||||
static void gst_multipart_mux_set_property (GObject * object, guint prop_id,
|
||||
|
@ -148,9 +148,9 @@ gst_multipart_mux_init (GstMultipartMux * multipart_mux)
|
|||
|
||||
multipart_mux->boundary = g_strdup (DEFAULT_BOUNDARY);
|
||||
|
||||
multipart_mux->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (multipart_mux->collect,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_multipart_mux_collected),
|
||||
multipart_mux->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_function (multipart_mux->collect,
|
||||
(GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_multipart_mux_collected),
|
||||
multipart_mux);
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,8 @@ gst_multipart_mux_request_new_pad (GstElement * element,
|
|||
GstMultipartPadData *multipartpad;
|
||||
|
||||
multipartpad = (GstMultipartPadData *)
|
||||
gst_collect_pads_add_pad (multipart_mux->collect, newpad,
|
||||
sizeof (GstMultipartPadData), NULL);
|
||||
gst_collect_pads2_add_pad (multipart_mux->collect, newpad,
|
||||
sizeof (GstMultipartPadData));
|
||||
|
||||
/* save a pointer to our data in the pad */
|
||||
multipartpad->pad = newpad;
|
||||
|
@ -340,7 +340,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
|
|||
/* try to make sure we have a buffer from each usable pad first */
|
||||
walk = mux->collect->data;
|
||||
while (walk) {
|
||||
GstCollectData *data = (GstCollectData *) walk->data;
|
||||
GstCollectData2 *data = (GstCollectData2 *) walk->data;
|
||||
GstMultipartPadData *pad = (GstMultipartPadData *) data;
|
||||
|
||||
walk = g_slist_next (walk);
|
||||
|
@ -349,7 +349,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
|
|||
if (pad->buffer == NULL) {
|
||||
GstBuffer *buf = NULL;
|
||||
|
||||
buf = gst_collect_pads_pop (mux->collect, data);
|
||||
buf = gst_collect_pads2_pop (mux->collect, data);
|
||||
|
||||
/* Store timestamp with segment_start and preroll */
|
||||
if (buf && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
|
@ -383,7 +383,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
|
|||
* 3) push both buffers on best pad, go to 1
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
|
||||
gst_multipart_mux_collected (GstCollectPads2 * pads, GstMultipartMux * mux)
|
||||
{
|
||||
GstMultipartPadData *best;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
@ -605,11 +605,11 @@ gst_multipart_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
multipart_mux->negotiated = FALSE;
|
||||
multipart_mux->need_segment = TRUE;
|
||||
GST_DEBUG_OBJECT (multipart_mux, "starting collect pads");
|
||||
gst_collect_pads_start (multipart_mux->collect);
|
||||
gst_collect_pads2_start (multipart_mux->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
GST_DEBUG_OBJECT (multipart_mux, "stopping collect pads");
|
||||
gst_collect_pads_stop (multipart_mux->collect);
|
||||
gst_collect_pads2_stop (multipart_mux->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define __GST_MULTIPART_MUX__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -42,7 +42,7 @@ typedef struct _GstMultipartMuxClass GstMultipartMuxClass;
|
|||
/* all information needed for one multipart stream */
|
||||
typedef struct
|
||||
{
|
||||
GstCollectData collect; /* we extend the CollectData */
|
||||
GstCollectData2 collect; /* we extend the CollectData2 */
|
||||
|
||||
GstBuffer *buffer; /* the queued buffer for this pad */
|
||||
GstClockTime timestamp; /* its timestamp, converted to running_time so that we can
|
||||
|
@ -64,7 +64,7 @@ struct _GstMultipartMux
|
|||
GstPad *srcpad;
|
||||
|
||||
/* sinkpads */
|
||||
GstCollectPads *collect;
|
||||
GstCollectPads2 *collect;
|
||||
|
||||
gint numpads;
|
||||
|
||||
|
|
|
@ -129,6 +129,8 @@
|
|||
#include "gstrtpsession.h"
|
||||
#include "gstrtpjitterbuffer.h"
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
|
||||
#define GST_CAT_DEFAULT gst_rtp_bin_debug
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@
|
|||
#include "rtpjitterbuffer.h"
|
||||
#include "rtpstats.h"
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
GST_DEBUG_CATEGORY (rtpjitterbuffer_debug);
|
||||
#define GST_CAT_DEFAULT (rtpjitterbuffer_debug)
|
||||
|
||||
|
|
|
@ -114,6 +114,8 @@
|
|||
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
#include "gstrtpbin-marshal.h"
|
||||
#include "gstrtpsession.h"
|
||||
#include "rtpsession.h"
|
||||
|
@ -908,8 +910,13 @@ start_rtcp_thread (GstRtpSession * rtpsession)
|
|||
g_thread_join (rtpsession->priv->thread);
|
||||
/* only create a new thread if the old one was stopped. Otherwise we can
|
||||
* just reuse the currently running one. */
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
rtpsession->priv->thread =
|
||||
g_thread_create ((GThreadFunc) rtcp_thread, rtpsession, TRUE, &error);
|
||||
#else
|
||||
rtpsession->priv->thread = g_thread_try_new ("rtpsession-rtcp-thread",
|
||||
(GThreadFunc) rtcp_thread, rtpsession, &error);
|
||||
#endif
|
||||
rtpsession->priv->thread_stopped = FALSE;
|
||||
}
|
||||
GST_RTP_SESSION_UNLOCK (rtpsession);
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/rtp/gstrtcpbuffer.h>
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/rtp/gstrtcpbuffer.h>
|
||||
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
#include "gstrtpbin-marshal.h"
|
||||
#include "rtpsession.h"
|
||||
|
||||
|
|
|
@ -81,6 +81,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
|
|
@ -152,7 +152,7 @@ static void gst_smpte_base_init (GstSMPTEClass * klass);
|
|||
static void gst_smpte_init (GstSMPTE * smpte);
|
||||
static void gst_smpte_finalize (GstSMPTE * smpte);
|
||||
|
||||
static GstFlowReturn gst_smpte_collected (GstCollectPads * pads,
|
||||
static GstFlowReturn gst_smpte_collected (GstCollectPads2 * pads,
|
||||
GstSMPTE * smpte);
|
||||
|
||||
static void gst_smpte_set_property (GObject * object, guint prop_id,
|
||||
|
@ -360,15 +360,15 @@ gst_smpte_init (GstSMPTE * smpte)
|
|||
gst_pad_new_from_static_template (&gst_smpte_src_template, "src");
|
||||
gst_element_add_pad (GST_ELEMENT (smpte), smpte->srcpad);
|
||||
|
||||
smpte->collect = gst_collect_pads_new ();
|
||||
gst_collect_pads_set_function (smpte->collect,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
|
||||
gst_collect_pads_start (smpte->collect);
|
||||
smpte->collect = gst_collect_pads2_new ();
|
||||
gst_collect_pads2_set_function (smpte->collect,
|
||||
(GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
|
||||
gst_collect_pads2_start (smpte->collect);
|
||||
|
||||
gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad1,
|
||||
sizeof (GstCollectData), NULL);
|
||||
gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad2,
|
||||
sizeof (GstCollectData), NULL);
|
||||
gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad1,
|
||||
sizeof (GstCollectData2));
|
||||
gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad2,
|
||||
sizeof (GstCollectData2));
|
||||
|
||||
smpte->fps = DEFAULT_PROP_FPS;
|
||||
smpte->type = DEFAULT_PROP_TYPE;
|
||||
|
@ -441,7 +441,7 @@ gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
|
||||
gst_smpte_collected (GstCollectPads2 * pads, GstSMPTE * smpte)
|
||||
{
|
||||
GstBuffer *outbuf;
|
||||
GstClockTime ts;
|
||||
|
@ -458,14 +458,14 @@ gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
|
|||
smpte->fps_denom, smpte->fps_num);
|
||||
|
||||
for (collected = pads->data; collected; collected = g_slist_next (collected)) {
|
||||
GstCollectData *data;
|
||||
GstCollectData2 *data;
|
||||
|
||||
data = (GstCollectData *) collected->data;
|
||||
data = (GstCollectData2 *) collected->data;
|
||||
|
||||
if (data->pad == smpte->sinkpad1)
|
||||
in1 = gst_collect_pads_pop (pads, data);
|
||||
in1 = gst_collect_pads2_pop (pads, data);
|
||||
else if (data->pad == smpte->sinkpad2)
|
||||
in2 = gst_collect_pads_pop (pads, data);
|
||||
in2 = gst_collect_pads2_pop (pads, data);
|
||||
}
|
||||
|
||||
if (in1 == NULL) {
|
||||
|
@ -623,11 +623,11 @@ gst_smpte_change_state (GstElement * element, GstStateChange transition)
|
|||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_smpte_reset (smpte);
|
||||
GST_LOG_OBJECT (smpte, "starting collectpads");
|
||||
gst_collect_pads_start (smpte->collect);
|
||||
gst_collect_pads2_start (smpte->collect);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
GST_LOG_OBJECT (smpte, "stopping collectpads");
|
||||
gst_collect_pads_stop (smpte->collect);
|
||||
gst_collect_pads2_stop (smpte->collect);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define __GST_SMPTE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstcollectpads2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -49,7 +49,7 @@ struct _GstSMPTE {
|
|||
GstPad *srcpad,
|
||||
*sinkpad1,
|
||||
*sinkpad2;
|
||||
GstCollectPads *collect;
|
||||
GstCollectPads2 *collect;
|
||||
|
||||
/* properties */
|
||||
gint type;
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (multiudpsink_debug);
|
||||
#define GST_CAT_DEFAULT (multiudpsink_debug)
|
||||
|
||||
|
|
|
@ -471,12 +471,21 @@ retry:
|
|||
IOCTL_SOCKET (udpsrc->sock.fd, FIONREAD, &readsize)) < 0))
|
||||
goto ioctl_failed;
|
||||
|
||||
/* if we get here and there is nothing to read from the socket, the select got
|
||||
* woken up by activity on the socket but it was not a read. We know someone
|
||||
* will also do something with the socket so that we don't go into an infinite
|
||||
* loop in the select(). */
|
||||
/* If we get here and the readsize is zero, then either select was woken up
|
||||
* by activity that is not a read, or a poll error occurred, or a UDP packet
|
||||
* was received that has no data. Since we cannot identify which case it is,
|
||||
* we handle all of them. This could possibly lead to a UDP packet getting
|
||||
* lost, but since UDP is not reliable, we can accept this. */
|
||||
if (G_UNLIKELY (!readsize)) {
|
||||
/* try to read a packet (and it will be ignored),
|
||||
* in case a packet with no data arrived */
|
||||
slen = sizeof (sa);
|
||||
recvfrom (udpsrc->sock.fd, (char *) &slen, 0, 0, &sa.sa, &slen);
|
||||
|
||||
/* clear any error, in case a poll error occurred */
|
||||
clear_error (udpsrc);
|
||||
|
||||
/* poll again */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
|
||||
#include "gstaspectratiocrop.h"
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (aspect_ratio_crop_debug);
|
||||
#define GST_CAT_DEFAULT aspect_ratio_crop_debug
|
||||
|
||||
|
|
|
@ -86,6 +86,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "videomixer2.h"
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -85,6 +90,19 @@ static void gst_wavparse_loop (GstPad * pad);
|
|||
static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
|
||||
static void gst_wavparse_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_wavparse_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
#define DEFAULT_IGNORE_LENGTH FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_IGNORE_LENGTH,
|
||||
};
|
||||
|
||||
static GstStaticPadTemplate sink_template_factory =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
|
@ -113,6 +131,27 @@ gst_wavparse_class_init (GstWavParseClass * klass)
|
|||
|
||||
object_class->dispose = gst_wavparse_dispose;
|
||||
|
||||
object_class->set_property = gst_wavparse_set_property;
|
||||
object_class->get_property = gst_wavparse_get_property;
|
||||
|
||||
/**
|
||||
* GstWavParse:ignore-length
|
||||
*
|
||||
* This selects whether the length found in a data chunk
|
||||
* should be ignored. This may be useful for streamed audio
|
||||
* where the length is unknown until the end of streaming,
|
||||
* and various software/hardware just puts some random value
|
||||
* in there and hopes it doesn't break too much.
|
||||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
g_object_class_install_property (object_class, PROP_IGNORE_LENGTH,
|
||||
g_param_spec_boolean ("ignore-length",
|
||||
"Ignore length",
|
||||
"Ignore length from the Wave header",
|
||||
DEFAULT_IGNORE_LENGTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
gstelement_class->change_state = gst_wavparse_change_state;
|
||||
gstelement_class->send_event = gst_wavparse_send_event;
|
||||
|
||||
|
@ -212,37 +251,6 @@ gst_wavparse_init (GstWavParse * wavparse)
|
|||
gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
|
||||
}
|
||||
|
||||
/* Compute (value * nom) % denom, avoiding overflow. This can be used
|
||||
* to perform ceiling or rounding division together with
|
||||
* gst_util_uint64_scale[_int]. */
|
||||
#define uint64_scale_modulo(val, nom, denom) \
|
||||
((val % denom) * (nom % denom) % denom)
|
||||
|
||||
/* Like gst_util_uint64_scale, but performs ceiling division. */
|
||||
static guint64
|
||||
uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
|
||||
{
|
||||
guint64 result = gst_util_uint64_scale_int (val, num, denom);
|
||||
|
||||
if (uint64_scale_modulo (val, num, denom) == 0)
|
||||
return result;
|
||||
else
|
||||
return result + 1;
|
||||
}
|
||||
|
||||
/* Like gst_util_uint64_scale, but performs ceiling division. */
|
||||
static guint64
|
||||
uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
|
||||
{
|
||||
guint64 result = gst_util_uint64_scale (val, num, denom);
|
||||
|
||||
if (uint64_scale_modulo (val, num, denom) == 0)
|
||||
return result;
|
||||
else
|
||||
return result + 1;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: why is that not in use? */
|
||||
#if 0
|
||||
static void
|
||||
|
@ -531,7 +539,7 @@ gst_wavparse_fmt (GstWavParse * wav)
|
|||
gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
|
||||
gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
|
||||
|
||||
GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
|
||||
GST_DEBUG ("frequency %u, channels %u", wav->rate, wav->channels);
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
@ -572,8 +580,8 @@ gst_wavparse_other (GstWavParse * wav)
|
|||
GST_WARNING_OBJECT (wav, "could not peek head");
|
||||
return FALSE;
|
||||
}
|
||||
GST_DEBUG_OBJECT (wav, "got tag (%08x) %4.4s, length %d", tag,
|
||||
(gchar *) & tag, length);
|
||||
GST_DEBUG_OBJECT (wav, "got tag (%08x) %4.4s, length %u", tag,
|
||||
(const gchar *) &tag, length);
|
||||
|
||||
switch (tag) {
|
||||
case GST_RIFF_TAG_LIST:
|
||||
|
@ -724,12 +732,12 @@ gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
|
|||
}
|
||||
|
||||
if (wav->bps > 0) {
|
||||
*bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
|
||||
*bytepos = gst_util_uint64_scale_ceil (ts, (guint64) wav->bps, GST_SECOND);
|
||||
return TRUE;
|
||||
} else if (wav->fact) {
|
||||
guint64 bps =
|
||||
gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
|
||||
*bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND);
|
||||
*bytepos = gst_util_uint64_scale_ceil (ts, bps, GST_SECOND);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1008,7 +1016,7 @@ gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
|
|||
*size = GST_READ_UINT32_LE (data + 4);
|
||||
gst_adapter_unmap (wav->adapter);
|
||||
|
||||
GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
|
||||
GST_DEBUG ("Next chunk size is %u bytes, type %" GST_FOURCC_FORMAT, *size,
|
||||
GST_FOURCC_ARGS (*tag));
|
||||
|
||||
return TRUE;
|
||||
|
@ -1038,7 +1046,7 @@ gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
|
|||
* so we throw poor man's exception, which can be caught if caller really
|
||||
* wants to handle 0 size chunk */
|
||||
if (!(*size) || (*size) >= (1 << 30)) {
|
||||
GST_INFO ("Invalid/unexpected chunk size %d for tag %" GST_FOURCC_FORMAT,
|
||||
GST_INFO ("Invalid/unexpected chunk size %u for tag %" GST_FOURCC_FORMAT,
|
||||
*size, GST_FOURCC_ARGS (*tag));
|
||||
/* chain should give up */
|
||||
wav->abort_buffering = TRUE;
|
||||
|
@ -1073,12 +1081,14 @@ gst_wavparse_calculate_duration (GstWavParse * wav)
|
|||
if (wav->bps > 0) {
|
||||
GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
|
||||
wav->duration =
|
||||
uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
|
||||
gst_util_uint64_scale_ceil (wav->datasize, GST_SECOND,
|
||||
(guint64) wav->bps);
|
||||
GST_INFO_OBJECT (wav, "Got duration (bps) %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (wav->duration));
|
||||
return TRUE;
|
||||
} else if (wav->fact) {
|
||||
wav->duration = uint64_ceiling_scale_int (GST_SECOND, wav->fact, wav->rate);
|
||||
wav->duration =
|
||||
gst_util_uint64_scale_int_ceil (GST_SECOND, wav->fact, wav->rate);
|
||||
GST_INFO_OBJECT (wav, "Got duration (fact) %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (wav->duration));
|
||||
return TRUE;
|
||||
|
@ -1211,12 +1221,12 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
{
|
||||
/* Note: workaround for mp2/mp3 embedded in wav, that relies on the
|
||||
* bitrate inside the mpeg stream */
|
||||
GST_INFO ("resetting bps from %d to 0 for mp2/3", wav->av_bps);
|
||||
GST_INFO ("resetting bps from %u to 0 for mp2/3", wav->av_bps);
|
||||
wav->bps = 0;
|
||||
break;
|
||||
}
|
||||
case GST_RIFF_WAVE_FORMAT_PCM:
|
||||
if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
|
||||
if (wav->blockalign > wav->channels * ((wav->depth + 7) / 8))
|
||||
goto invalid_blockalign;
|
||||
/* fall through */
|
||||
default:
|
||||
|
@ -1298,7 +1308,11 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
*/
|
||||
switch (tag) {
|
||||
case GST_RIFF_TAG_data:{
|
||||
GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
|
||||
GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %u", size);
|
||||
if (wav->ignore_length) {
|
||||
GST_DEBUG_OBJECT (wav, "Ignoring length");
|
||||
size = 0;
|
||||
}
|
||||
if (wav->streaming) {
|
||||
gst_adapter_flush (wav->adapter, 8);
|
||||
gotdata = TRUE;
|
||||
|
@ -1323,7 +1337,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
/* We will continue parsing tags 'till end */
|
||||
wav->offset += size;
|
||||
}
|
||||
GST_DEBUG_OBJECT (wav, "datasize = %d", size);
|
||||
GST_DEBUG_OBJECT (wav, "datasize = %u", size);
|
||||
break;
|
||||
}
|
||||
case GST_RIFF_TAG_fact:{
|
||||
|
@ -1337,7 +1351,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
/* need more data */
|
||||
goto exit;
|
||||
}
|
||||
GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
|
||||
GST_DEBUG_OBJECT (wav, "need %u, available %u; ignoring chunk",
|
||||
data_size, size);
|
||||
break;
|
||||
}
|
||||
|
@ -1385,7 +1399,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
/* need more data */
|
||||
goto exit;
|
||||
}
|
||||
GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
|
||||
GST_DEBUG_OBJECT (wav, "need %u, available %u; ignoring chunk",
|
||||
data_size, size);
|
||||
break;
|
||||
}
|
||||
|
@ -1520,18 +1534,20 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
wav->bps =
|
||||
(guint32) gst_util_uint64_scale ((guint64) wav->rate, wav->datasize,
|
||||
(guint64) wav->fact);
|
||||
GST_INFO_OBJECT (wav, "calculated bps : %d, enabling VBR", wav->bps);
|
||||
GST_INFO_OBJECT (wav, "calculated bps : %u, enabling VBR", wav->bps);
|
||||
#endif
|
||||
wav->vbr = TRUE;
|
||||
}
|
||||
|
||||
if (gst_wavparse_calculate_duration (wav)) {
|
||||
gst_segment_init (&wav->segment, GST_FORMAT_TIME);
|
||||
wav->segment.duration = wav->duration;
|
||||
if (!wav->ignore_length)
|
||||
wav->segment.duration = wav->duration;
|
||||
} else {
|
||||
/* no bitrate, let downstream peer do the math, we'll feed it bytes. */
|
||||
gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
|
||||
wav->segment.duration = wav->datasize;
|
||||
if (!wav->ignore_length)
|
||||
wav->segment.duration = wav->datasize;
|
||||
}
|
||||
|
||||
/* now we have all the info to perform a pending seek if any, if no
|
||||
|
@ -1558,7 +1574,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
|
|||
if (wav->blockalign > 0)
|
||||
wav->max_buf_size -= (wav->max_buf_size % wav->blockalign);
|
||||
|
||||
GST_DEBUG_OBJECT (wav, "max buffer size %d", wav->max_buf_size);
|
||||
GST_DEBUG_OBJECT (wav, "max buffer size %u", wav->max_buf_size);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
|
@ -1607,7 +1623,7 @@ invalid_blockalign:
|
|||
{
|
||||
GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
|
||||
("Stream claims blockalign = %u, which is more than %u - invalid data",
|
||||
wav->blockalign, wav->channels * (guint) ceil (wav->depth / 8.0)));
|
||||
wav->blockalign, wav->channels * ((wav->depth + 7) / 8)));
|
||||
goto fail;
|
||||
}
|
||||
invalid_bps:
|
||||
|
@ -1626,7 +1642,7 @@ no_bytes_per_sample:
|
|||
unknown_format:
|
||||
{
|
||||
GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
|
||||
("No caps found for format 0x%x, %d channels, %d Hz",
|
||||
("No caps found for format 0x%x, %u channels, %u Hz",
|
||||
wav->format, wav->channels, wav->rate));
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1818,13 +1834,13 @@ iterate_adapter:
|
|||
if (G_UNLIKELY (extra)) {
|
||||
extra = wav->bytes_per_sample - extra;
|
||||
if (extra <= avail) {
|
||||
GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra);
|
||||
GST_DEBUG_OBJECT (wav, "flushing %u bytes to sample boundary", extra);
|
||||
gst_adapter_flush (wav->adapter, extra);
|
||||
wav->offset += extra;
|
||||
wav->dataleft -= extra;
|
||||
goto iterate_adapter;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail);
|
||||
GST_DEBUG_OBJECT (wav, "flushing %u bytes", avail);
|
||||
gst_adapter_clear (wav->adapter);
|
||||
wav->offset += avail;
|
||||
wav->dataleft -= avail;
|
||||
|
@ -1833,7 +1849,7 @@ iterate_adapter:
|
|||
}
|
||||
|
||||
if (avail < desired) {
|
||||
GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
|
||||
GST_LOG_OBJECT (wav, "Got only %u bytes of data from the sinkpad", avail);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
@ -1885,9 +1901,10 @@ iterate_adapter:
|
|||
|
||||
if (wav->bps > 0) {
|
||||
/* and timestamps if we have a bitrate, be careful for overflows */
|
||||
timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
|
||||
timestamp =
|
||||
gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) wav->bps);
|
||||
next_timestamp =
|
||||
uint64_ceiling_scale (nextpos, GST_SECOND, (guint64) wav->bps);
|
||||
gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) wav->bps);
|
||||
duration = next_timestamp - timestamp;
|
||||
|
||||
/* update current running segment position */
|
||||
|
@ -1897,8 +1914,8 @@ iterate_adapter:
|
|||
guint64 bps =
|
||||
gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
|
||||
/* and timestamps if we have a bitrate, be careful for overflows */
|
||||
timestamp = uint64_ceiling_scale (pos, GST_SECOND, bps);
|
||||
next_timestamp = uint64_ceiling_scale (nextpos, GST_SECOND, bps);
|
||||
timestamp = gst_util_uint64_scale_ceil (pos, GST_SECOND, bps);
|
||||
next_timestamp = gst_util_uint64_scale_ceil (nextpos, GST_SECOND, bps);
|
||||
duration = next_timestamp - timestamp;
|
||||
} else {
|
||||
/* no bitrate, all we know is that the first sample has timestamp 0, all
|
||||
|
@ -2191,10 +2208,12 @@ gst_wavparse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
if (bps) {
|
||||
if (start >= 0)
|
||||
start =
|
||||
uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps);
|
||||
gst_util_uint64_scale_ceil (start, GST_SECOND,
|
||||
(guint64) wav->bps);
|
||||
if (stop >= 0)
|
||||
stop =
|
||||
uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps);
|
||||
gst_util_uint64_scale_ceil (stop, GST_SECOND,
|
||||
(guint64) wav->bps);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2319,13 +2338,14 @@ gst_wavparse_pad_convert (GstPad * pad,
|
|||
"src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
|
||||
wavparse->offset);
|
||||
if (wavparse->bps > 0)
|
||||
*dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
|
||||
*dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
|
||||
(guint64) wavparse->bps);
|
||||
else if (wavparse->fact) {
|
||||
guint64 bps = uint64_ceiling_scale_int (wavparse->datasize,
|
||||
guint64 bps = gst_util_uint64_scale_int_ceil (wavparse->datasize,
|
||||
wavparse->rate, wavparse->fact);
|
||||
|
||||
*dest_value = uint64_ceiling_scale_int (src_value, GST_SECOND, bps);
|
||||
*dest_value =
|
||||
gst_util_uint64_scale_int_ceil (src_value, GST_SECOND, bps);
|
||||
} else {
|
||||
res = FALSE;
|
||||
}
|
||||
|
@ -2438,6 +2458,11 @@ gst_wavparse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
|||
gint64 duration = 0;
|
||||
GstFormat format;
|
||||
|
||||
if (wav->ignore_length) {
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
gst_query_parse_duration (query, &format, NULL);
|
||||
|
||||
switch (format) {
|
||||
|
@ -2626,6 +2651,43 @@ gst_wavparse_change_state (GstElement * element, GstStateChange transition)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wavparse_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWavParse *self;
|
||||
|
||||
g_return_if_fail (GST_IS_WAVPARSE (object));
|
||||
self = GST_WAVPARSE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_IGNORE_LENGTH:
|
||||
self->ignore_length = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wavparse_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWavParse *self;
|
||||
|
||||
g_return_if_fail (GST_IS_WAVPARSE (object));
|
||||
self = GST_WAVPARSE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_IGNORE_LENGTH:
|
||||
g_value_set_boolean (value, self->ignore_length);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,8 @@ struct _GstWavParse {
|
|||
gboolean first;
|
||||
/* discont after seek */
|
||||
gboolean discont;
|
||||
|
||||
gboolean ignore_length;
|
||||
};
|
||||
|
||||
struct _GstWavParseClass {
|
||||
|
|
|
@ -1 +1 @@
|
|||
af az bg ca cs da de el en_GB es eu fi fr gl hu id it ja lt lv mt nb nl or pl pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_HK zh_TW
|
||||
af az bg ca cs da de el en_GB eo es eu fi fr gl hu id it ja lt lv mt nb nl or pl pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_HK zh_TW
|
||||
|
|
832
po/eo.po
Normal file
832
po/eo.po
Normal file
|
@ -0,0 +1,832 @@
|
|||
# Esperanto translation for gst-plugins-good.
|
||||
# Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gst-plugins-good package.
|
||||
# Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gst-plugins-good 0.10.28.2\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
|
||||
"POT-Creation-Date: 2011-04-16 16:25+0100\n"
|
||||
"PO-Revision-Date: 2011-06-04 21:48+0100\n"
|
||||
"Last-Translator: Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>\n"
|
||||
"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
|
||||
"Language: eo\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ext/esd/esdsink.c:253 ext/esd/esdsink.c:358
|
||||
msgid "Could not establish connection to sound server"
|
||||
msgstr ""
|
||||
|
||||
#: ext/esd/esdsink.c:260
|
||||
msgid "Failed to query sound server capabilities"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: 'song title' by 'artist name'
|
||||
#: ext/pulse/pulsesink.c:2686
|
||||
#, c-format
|
||||
msgid "'%s' by '%s'"
|
||||
msgstr "'%s' de '%s'"
|
||||
|
||||
#: ext/flac/gstflacdec.c:1117 ext/libpng/gstpngdec.c:349
|
||||
#: ext/libpng/gstpngdec.c:360 ext/libpng/gstpngdec.c:559
|
||||
#: ext/wavpack/gstwavpackparse.c:1170 gst/avi/gstavidemux.c:5203
|
||||
msgid "Internal data stream error."
|
||||
msgstr "Interna datumflu-eraro."
|
||||
|
||||
#: ext/jpeg/gstjpegdec.c:286
|
||||
msgid "Failed to decode JPEG image"
|
||||
msgstr ""
|
||||
|
||||
#: ext/shout2/gstshout2.c:578
|
||||
msgid "Could not connect to server"
|
||||
msgstr "Ne eblis konekti al servilo"
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:871
|
||||
msgid "Server does not support seeking."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1078
|
||||
msgid "Could not resolve server name."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1084
|
||||
msgid "Could not establish connection to server."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1089
|
||||
msgid "Secure connection setup failed."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1094
|
||||
msgid "A network error occured, or the server closed the connection unexpectedly."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1100
|
||||
msgid "Server sent bad data."
|
||||
msgstr ""
|
||||
|
||||
#: ext/soup/gstsouphttpsrc.c:1249
|
||||
msgid "No URL set."
|
||||
msgstr ""
|
||||
|
||||
#: gst/avi/gstavimux.c:1810
|
||||
msgid "No or invalid input audio, AVI stream will be corrupt."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:519 gst/quicktime/qtdemux.c:523
|
||||
msgid "This file contains no playable streams."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:558 gst/quicktime/qtdemux.c:4009
|
||||
#: gst/quicktime/qtdemux.c:4071 gst/quicktime/qtdemux.c:4219
|
||||
msgid "This file is invalid and cannot be played."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:2439 gst/quicktime/qtdemux.c:2515
|
||||
#: gst/quicktime/qtdemux.c:2558 gst/quicktime/qtdemux.c:4798
|
||||
#: gst/quicktime/qtdemux.c:4805 gst/quicktime/qtdemux.c:5391
|
||||
#: gst/quicktime/qtdemux.c:5817 gst/quicktime/qtdemux.c:5824
|
||||
#: gst/quicktime/qtdemux.c:7305
|
||||
msgid "This file is corrupt and cannot be played."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:2647
|
||||
msgid "Invalid atom size."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:2716
|
||||
msgid "This file is incomplete and cannot be played."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:4994
|
||||
msgid "The video in this file might not play correctly."
|
||||
msgstr ""
|
||||
|
||||
#: gst/quicktime/qtdemux.c:7334
|
||||
#, c-format
|
||||
msgid "This file contains too many streams. Only playing first %d"
|
||||
msgstr ""
|
||||
|
||||
#: gst/rtsp/gstrtspsrc.c:5187
|
||||
msgid "No supported stream was found. You might need to install a GStreamer RTSP extension plugin for Real media streams."
|
||||
msgstr ""
|
||||
|
||||
#: gst/rtsp/gstrtspsrc.c:5192
|
||||
msgid "No supported stream was found. You might need to allow more transport protocols or may otherwise be missing the right GStreamer RTSP extension plugin."
|
||||
msgstr ""
|
||||
|
||||
#: gst/wavparse/gstwavparse.c:2103
|
||||
msgid "Internal data flow error."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:98 sys/oss4/oss4-mixer.c:722
|
||||
#: sys/sunaudio/gstsunaudiomixertrack.c:69
|
||||
msgid "Volume"
|
||||
msgstr "Laŭteco"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:99 sys/oss4/oss4-mixer.c:735
|
||||
msgid "Bass"
|
||||
msgstr "Baso"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:100 sys/oss4/oss4-mixer.c:736
|
||||
msgid "Treble"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:101
|
||||
msgid "Synth"
|
||||
msgstr "Sintezilo"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:102 sys/oss4/oss4-mixer.c:750
|
||||
msgid "PCM"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:103
|
||||
msgid "Speaker"
|
||||
msgstr "Parolilo"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:104
|
||||
msgid "Line-in"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:105 sys/oss4/oss4-mixer.c:741
|
||||
msgid "Microphone"
|
||||
msgstr "Mikrofono"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:106
|
||||
msgid "CD"
|
||||
msgstr "KD"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:107
|
||||
msgid "Mixer"
|
||||
msgstr "Miksilo"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:108
|
||||
msgid "PCM-2"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:109
|
||||
msgid "Record"
|
||||
msgstr "Registri"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:110
|
||||
msgid "In-gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:111
|
||||
msgid "Out-gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:112
|
||||
msgid "Line-1"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:113
|
||||
msgid "Line-2"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:114
|
||||
msgid "Line-3"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:115
|
||||
msgid "Digital-1"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:116
|
||||
msgid "Digital-2"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:117
|
||||
msgid "Digital-3"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:118
|
||||
msgid "Phone-in"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:119
|
||||
msgid "Phone-out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:120
|
||||
msgid "Video"
|
||||
msgstr "Video"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:121
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: sys/oss/gstossmixertrack.c:122 sys/oss4/oss4-mixer.c:764
|
||||
#: sys/sunaudio/gstsunaudiomixertrack.c:71
|
||||
msgid "Monitor"
|
||||
msgstr "Ekrano"
|
||||
|
||||
#: sys/oss/gstosssink.c:399 sys/oss4/oss4-sink.c:494
|
||||
#: sys/oss4/oss4-source.c:361
|
||||
msgid "Could not open audio device for playback. Device is being used by another application."
|
||||
msgstr "Ne eblis malfermi la sonaparaton por reproduktado. Ĝi estas uzate de alia aplikaĵo."
|
||||
|
||||
#: sys/oss/gstosssink.c:406 sys/oss4/oss4-sink.c:504
|
||||
#: sys/oss4/oss4-source.c:371
|
||||
msgid "Could not open audio device for playback. You don't have permission to open the device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstosssink.c:414 sys/oss4/oss4-sink.c:515
|
||||
#: sys/oss4/oss4-source.c:382
|
||||
msgid "Could not open audio device for playback."
|
||||
msgstr "Ne eblis malfermi la sonaparaton por reproduktado."
|
||||
|
||||
#: sys/oss/gstosssrc.c:370
|
||||
msgid "Could not open audio device for recording. You don't have permission to open the device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss/gstosssrc.c:378
|
||||
msgid "Could not open audio device for recording."
|
||||
msgstr "Ne eblis malfermi sonaparaton por registrado."
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:302
|
||||
msgid "Could not open audio device for mixer control handling."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:316
|
||||
msgid "Could not open audio device for mixer control handling. This version of the Open Sound System is not supported by this element."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:723
|
||||
msgid "Master"
|
||||
msgstr "Ĉefe"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:724
|
||||
msgid "Front"
|
||||
msgstr "Antaŭe"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:725
|
||||
msgid "Rear"
|
||||
msgstr "Malantaŭe"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:726
|
||||
msgid "Headphones"
|
||||
msgstr "Kaptelefono"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:727
|
||||
msgid "Center"
|
||||
msgstr "Centre"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:728
|
||||
msgid "LFE"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:729
|
||||
msgid "Surround"
|
||||
msgstr "Ĉirkaŭe"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:730
|
||||
msgid "Side"
|
||||
msgstr "Flanke"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:731 sys/sunaudio/gstsunaudiomixertrack.c:72
|
||||
msgid "Built-in Speaker"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:732 sys/sunaudio/gstsunaudiomixertrack.c:76
|
||||
msgid "AUX 1 Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:733 sys/sunaudio/gstsunaudiomixertrack.c:77
|
||||
msgid "AUX 2 Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:734
|
||||
msgid "AUX Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:737
|
||||
msgid "3D Depth"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:738
|
||||
msgid "3D Center"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:739
|
||||
msgid "3D Enhance"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:740
|
||||
msgid "Telephone"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:742 sys/sunaudio/gstsunaudiomixertrack.c:74
|
||||
msgid "Line Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:743 sys/oss4/oss4-mixer.c:744
|
||||
msgid "Line In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:745
|
||||
msgid "Internal CD"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:746
|
||||
msgid "Video In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:747
|
||||
msgid "AUX 1 In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:748
|
||||
msgid "AUX 2 In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:749
|
||||
msgid "AUX In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:751 sys/oss4/oss4-mixer.c:752
|
||||
msgid "Record Gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:753
|
||||
msgid "Output Gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:754
|
||||
msgid "Microphone Boost"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:755
|
||||
msgid "Loopback"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:756
|
||||
msgid "Diagnostic"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:757
|
||||
msgid "Bass Boost"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:758
|
||||
msgid "Playback Ports"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:759
|
||||
msgid "Input"
|
||||
msgstr "Enigo"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:760 sys/oss4/oss4-mixer.c:761
|
||||
msgid "Record Source"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:762
|
||||
msgid "Monitor Source"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:763
|
||||
msgid "Keyboard Beep"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:765
|
||||
msgid "Simulate Stereo"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:766 sys/oss4/oss4-mixer.c:786
|
||||
msgid "Stereo"
|
||||
msgstr "Dukanale"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:767
|
||||
msgid "Surround Sound"
|
||||
msgstr "Ĉirkaŭa sono"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:768
|
||||
msgid "Microphone Gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:769
|
||||
msgid "Speaker Source"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:770
|
||||
msgid "Microphone Source"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:771
|
||||
msgid "Jack"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:772
|
||||
msgid "Center / LFE"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:773
|
||||
msgid "Stereo Mix"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:774
|
||||
msgid "Mono Mix"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:775
|
||||
msgid "Input Mix"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:776
|
||||
msgid "SPDIF In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:777 sys/sunaudio/gstsunaudiomixertrack.c:75
|
||||
msgid "SPDIF Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:778
|
||||
msgid "Microphone 1"
|
||||
msgstr "Mikrofono 1"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:779
|
||||
msgid "Microphone 2"
|
||||
msgstr "Mikrofono 2"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:780
|
||||
msgid "Digital Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:781
|
||||
msgid "Digital In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:782
|
||||
msgid "HDMI"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:783
|
||||
msgid "Modem"
|
||||
msgstr "Modemo"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:784
|
||||
msgid "Handset"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:785
|
||||
msgid "Other"
|
||||
msgstr "Alia"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:787
|
||||
msgid "None"
|
||||
msgstr "Neniu"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:788
|
||||
msgid "On"
|
||||
msgstr "Enŝaltite"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:789
|
||||
msgid "Off"
|
||||
msgstr "Elŝaltite"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:790
|
||||
msgid "Mute"
|
||||
msgstr "Silentigi"
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:791
|
||||
msgid "Fast"
|
||||
msgstr "Rapide"
|
||||
|
||||
#. TRANSLATORS: "Very Low" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:793
|
||||
msgid "Very Low"
|
||||
msgstr "Tre malalte"
|
||||
|
||||
#. TRANSLATORS: "Low" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:795
|
||||
msgid "Low"
|
||||
msgstr "Malalte"
|
||||
|
||||
#. TRANSLATORS: "Medium" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:797
|
||||
msgid "Medium"
|
||||
msgstr "Meze"
|
||||
|
||||
#. TRANSLATORS: "High" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:799
|
||||
msgid "High"
|
||||
msgstr "Alte"
|
||||
|
||||
#. TRANSLATORS: "Very High" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:801 sys/oss4/oss4-mixer.c:802
|
||||
msgid "Very High"
|
||||
msgstr "Tre alte"
|
||||
|
||||
#. TRANSLATORS: "Production" is a quality setting here
|
||||
#: sys/oss4/oss4-mixer.c:804
|
||||
msgid "Production"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:805
|
||||
msgid "Front Panel Microphone"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:806
|
||||
msgid "Front Panel Line In"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:807
|
||||
msgid "Front Panel Headphones"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:808
|
||||
msgid "Front Panel Line Out"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:809
|
||||
msgid "Green Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:810
|
||||
msgid "Pink Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:811
|
||||
msgid "Blue Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:812
|
||||
msgid "White Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:813
|
||||
msgid "Black Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:814
|
||||
msgid "Gray Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:815
|
||||
msgid "Orange Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:816
|
||||
msgid "Red Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:817
|
||||
msgid "Yellow Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:818
|
||||
msgid "Green Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:819
|
||||
msgid "Pink Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:820
|
||||
msgid "Blue Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:821
|
||||
msgid "White Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:822
|
||||
msgid "Black Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:823
|
||||
msgid "Gray Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:824
|
||||
msgid "Orange Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:825
|
||||
msgid "Red Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:826
|
||||
msgid "Yellow Front Panel Connector"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:827
|
||||
msgid "Spread Output"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:828
|
||||
msgid "Downmix"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:872
|
||||
msgid "Virtual Mixer Input"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:874
|
||||
msgid "Virtual Mixer Output"
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-mixer.c:876
|
||||
msgid "Virtual Mixer Channels"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: name + number of a volume mixer control
|
||||
#: sys/oss4/oss4-mixer.c:927
|
||||
#, c-format
|
||||
msgid "%s %d Function"
|
||||
msgstr "%s %d funkcio"
|
||||
|
||||
#. TRANSLATORS: name of a volume mixer control
|
||||
#: sys/oss4/oss4-mixer.c:934
|
||||
#, c-format
|
||||
msgid "%s Function"
|
||||
msgstr "%s funcio"
|
||||
|
||||
#: sys/oss4/oss4-sink.c:524 sys/oss4/oss4-source.c:392
|
||||
msgid "Could not open audio device for playback. This version of the Open Sound System is not supported by this element."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-sink.c:640
|
||||
msgid "Playback is not supported by this audio device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-sink.c:647
|
||||
msgid "Audio playback error."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-source.c:514
|
||||
msgid "Recording is not supported by this audio device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/oss4/oss4-source.c:521
|
||||
msgid "Error recording from audio device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/sunaudio/gstsunaudiomixertrack.c:70
|
||||
msgid "Gain"
|
||||
msgstr ""
|
||||
|
||||
#: sys/sunaudio/gstsunaudiomixertrack.c:73
|
||||
msgid "Headphone"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/gstv4l2src.c:887
|
||||
#, c-format
|
||||
msgid "Error reading %d bytes from device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/gstv4l2src.c:913
|
||||
#, c-format
|
||||
msgid "Got unexpected frame size of %u instead of %u."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/gstv4l2src.c:931
|
||||
#, c-format
|
||||
msgid "Error reading %d bytes on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:99
|
||||
#, c-format
|
||||
msgid "Error getting capabilities for device '%s': It isn't a v4l2 driver. Check if it is a v4l1 driver."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:139
|
||||
#, c-format
|
||||
msgid "Failed to query attributes of input %d in device %s"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:169
|
||||
#, c-format
|
||||
msgid "Failed to get setting of tuner %d on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:213
|
||||
#, c-format
|
||||
msgid "Failed to query norm on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:264 sys/v4l2/v4l2_calls.c:347
|
||||
#, c-format
|
||||
msgid "Failed getting controls attributes on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:492
|
||||
#, c-format
|
||||
msgid "Cannot identify device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:499
|
||||
#, c-format
|
||||
msgid "This isn't a device '%s'."
|
||||
msgstr "Tio ne estas '%s'-aparato."
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:506
|
||||
#, c-format
|
||||
msgid "Could not open device '%s' for reading and writing."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:513
|
||||
#, c-format
|
||||
msgid "Device '%s' is not a capture device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:522
|
||||
#, c-format
|
||||
msgid "Device '%s' is not a output device."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:622
|
||||
#, c-format
|
||||
msgid "Failed to set norm for device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:660
|
||||
#, c-format
|
||||
msgid "Failed to get current tuner frequency for device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:702
|
||||
#, c-format
|
||||
msgid "Failed to set current tuner frequency for device '%s' to %lu Hz."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:736
|
||||
#, c-format
|
||||
msgid "Failed to get signal strength for device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:772
|
||||
#, c-format
|
||||
msgid "Failed to get value for control %d on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:807
|
||||
#, c-format
|
||||
msgid "Failed to set value %d for control %d on device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:839
|
||||
#, c-format
|
||||
msgid "Failed to get current input on device '%s'. May be it is a radio device"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:864
|
||||
#, c-format
|
||||
msgid "Failed to set input %d on device %s."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:896
|
||||
#, c-format
|
||||
msgid "Failed to get current output on device '%s'. May be it is a radio device"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2_calls.c:921
|
||||
#, c-format
|
||||
msgid "Failed to set output %d on device %s."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:81
|
||||
#, c-format
|
||||
msgid "Could not enqueue buffers in device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:197
|
||||
#, c-format
|
||||
msgid "Failed trying to get video frames from device '%s'."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:199
|
||||
#, c-format
|
||||
msgid "Failed after %d tries. device %s. system error: %s"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:239
|
||||
#, c-format
|
||||
msgid "Could not get parameters on device '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:267
|
||||
msgid "Video input device did not accept new frame rate setting."
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:339
|
||||
#, c-format
|
||||
msgid "Could not map buffers from device '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: sys/v4l2/v4l2src_calls.c:347
|
||||
#, c-format
|
||||
msgid "The driver of device '%s' does not support any known capture method."
|
||||
msgstr ""
|
||||
|
||||
#: sys/ximage/gstximagesrc.c:719
|
||||
msgid "Changing resolution at runtime is not yet supported."
|
||||
msgstr ""
|
||||
|
||||
#: sys/ximage/gstximagesrc.c:733
|
||||
msgid "Cannot operate without a clock"
|
||||
msgstr ""
|
|
@ -23,6 +23,12 @@ else
|
|||
DIRECTSOUND_DIR=
|
||||
endif
|
||||
|
||||
if USE_WAVEFORM
|
||||
WAVEFORM_DIR=waveform
|
||||
else
|
||||
WAVEFORM_DIR=
|
||||
endif
|
||||
|
||||
if USE_SUNAUDIO
|
||||
SUNAUDIO_DIR=sunaudio
|
||||
else
|
||||
|
@ -77,7 +83,7 @@ else
|
|||
XIMAGE_DIR=
|
||||
endif
|
||||
|
||||
SUBDIRS=$(DIRECTSOUND_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
|
||||
SUBDIRS=$(DIRECTSOUND_DIR) $(WAVEFORM_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
|
||||
|
||||
DIST_SUBDIRS=directsound oss oss4 osxaudio osxvideo sunaudio v4l2 waveform ximage
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#include <gst/interfaces/mixer.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
|
@ -541,8 +542,13 @@ gst_oss4_mixer_start_watch_task (GstOss4Mixer * mixer)
|
|||
mixer->watch_cond = g_cond_new ();
|
||||
mixer->watch_shutdown = FALSE;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
mixer->watch_thread = g_thread_create (gst_oss4_mixer_watch_thread,
|
||||
gst_object_ref (mixer), TRUE, &err);
|
||||
#else
|
||||
mixer->watch_thread = g_thread_try_new ("oss4-mixer-thread",
|
||||
gst_oss4_mixer_watch_thread, gst_object_ref (mixer), &err);
|
||||
#endif
|
||||
|
||||
if (mixer->watch_thread == NULL) {
|
||||
GST_ERROR_OBJECT (mixer, "Could not create watch thread: %s", err->message);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "gstv4l2sink.h"
|
||||
#include "v4l2_calls.h"
|
||||
#include "gst/gst-i18n-plugin.h"
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
/* videodev2.h is not versioned and we can't easily check for the presence
|
||||
* of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "v4l2_calls.h"
|
||||
|
||||
#include "gst/gst-i18n-plugin.h"
|
||||
#include <gst/glib-compat-private.h>
|
||||
|
||||
struct _GstV4l2Xv
|
||||
{
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
plugin_LTLIBRARIES = libgstwaveformsink.la
|
||||
|
||||
# FIXME: Replace DIRECTSOUND CFLAGS+LIBS with waveform related ones and fix
|
||||
# the configure.ac + sys/Makefile.am to get this stuff building in MingW
|
||||
# For now, it's just disted for use in the VS builds.
|
||||
|
||||
libgstwaveformsink_la_SOURCES = gstwaveformsink.c gstwaveformplugin.c
|
||||
libgstwaveformsink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) $(DIRECTSOUND_CFLAGS)
|
||||
$(GST_PLUGINS_BASE_CFLAGS)
|
||||
libgstwaveformsink_la_LIBADD = \
|
||||
$(GST_PLUGINS_BASE_LIBS) \
|
||||
-lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
|
||||
$(GST_BASE_LIBS) \
|
||||
$(GST_LIBS) \
|
||||
$(DIRECTSOUND_LIBS)
|
||||
libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
|
||||
-lwinmm
|
||||
libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstwaveformsink_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstwaveformsink.h
|
||||
|
|
|
@ -49,10 +49,6 @@
|
|||
|
||||
GST_DEBUG_CATEGORY_STATIC (waveformsink_debug);
|
||||
|
||||
static void gst_waveform_sink_base_init (gpointer g_class);
|
||||
static void gst_waveform_sink_class_init (GstWaveFormSinkClass * klass);
|
||||
static void gst_waveform_sink_init (GstWaveFormSink * wfsink,
|
||||
GstWaveFormSinkClass * g_class);
|
||||
static void gst_waveform_sink_finalise (GObject * object);
|
||||
static void gst_waveform_sink_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
|
@ -154,7 +150,7 @@ static void
|
|||
gst_waveform_sink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
|
||||
/* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object); */
|
||||
|
||||
switch (prop_id) {
|
||||
default:
|
||||
|
@ -167,7 +163,7 @@ static void
|
|||
gst_waveform_sink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
|
||||
/* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object); */
|
||||
|
||||
switch (prop_id) {
|
||||
default:
|
||||
|
@ -348,7 +344,7 @@ gst_waveform_sink_getcaps (GstBaseSink * bsink)
|
|||
static gboolean
|
||||
gst_waveform_sink_open (GstAudioSink * asink)
|
||||
{
|
||||
GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
|
||||
/* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink); */
|
||||
|
||||
/* nothing to do here as the device needs to be opened with the format we will use */
|
||||
|
||||
|
@ -448,7 +444,7 @@ gst_waveform_sink_unprepare (GstAudioSink * asink)
|
|||
static gboolean
|
||||
gst_waveform_sink_close (GstAudioSink * asink)
|
||||
{
|
||||
GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
|
||||
/* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink); */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_debug_ximage_src);
|
||||
#define GST_CAT_DEFAULT gst_debug_ximage_src
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ check_PROGRAMS = \
|
|||
elements/shapewipe \
|
||||
elements/spectrum \
|
||||
elements/udpsink \
|
||||
elements/udpsrc \
|
||||
elements/videocrop \
|
||||
elements/videofilter \
|
||||
elements/y4menc \
|
||||
|
@ -296,6 +297,9 @@ elements_sunaudio_LDADD = \
|
|||
$(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_MAJORMINOR@ \
|
||||
$(LDADD)
|
||||
|
||||
elements_udpsrc_CFLAGS = $(AM_CFLAGS) $(GIO_CFLAGS)
|
||||
elements_udpsrc_LDADD = $(LDADD) $(GIO_LIBS)
|
||||
|
||||
elements_videocrop_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(LDADD)
|
||||
elements_videocrop_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
|
||||
|
||||
|
|
1
tests/check/elements/.gitignore
vendored
1
tests/check/elements/.gitignore
vendored
|
@ -53,6 +53,7 @@ souphttpsrc
|
|||
spectrum
|
||||
sunaudio
|
||||
udpsink
|
||||
udpsrc
|
||||
videocrop
|
||||
videofilter
|
||||
wavpackdec
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
|
||||
|
@ -830,7 +832,12 @@ test_average_bitrate_custom (const gchar * elementname,
|
|||
(guint) gst_util_uint64_scale_round ((guint64) total_bytes,
|
||||
(guint64) 8 * GST_SECOND, (guint64) total_duration);
|
||||
fail_unless (bitrate == expected);
|
||||
gst_tag_list_free (taglist);
|
||||
}
|
||||
|
||||
/* delete file */
|
||||
g_unlink (location);
|
||||
g_free (location);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_average_bitrate)
|
||||
|
|
|
@ -49,6 +49,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING)
|
||||
);
|
||||
|
||||
static GstBuffer *test_buffer_new (gfloat value);
|
||||
|
||||
/* gstcheck sets up a chain function that appends buffers to a global list.
|
||||
* This is our equivalent of that for event handling. */
|
||||
static gboolean
|
||||
|
@ -78,6 +80,37 @@ setup_rgvolume (void)
|
|||
return element;
|
||||
}
|
||||
|
||||
static void
|
||||
send_newsegment_and_empty_buffer (void)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstEvent *ev;
|
||||
GstSegment segment;
|
||||
|
||||
fail_unless (g_list_length (events) == 0);
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
ev = gst_event_new_segment (&segment);
|
||||
fail_unless (gst_pad_push_event (mysrcpad, ev),
|
||||
"Pushing newsegment event failed");
|
||||
|
||||
buf = test_buffer_new (0.0);
|
||||
GST_BUFFER_SIZE (buf) = 0;
|
||||
GST_BUFFER_DURATION (buf) = 0;
|
||||
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf);
|
||||
fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
|
||||
|
||||
fail_unless (g_list_length (events) == 1);
|
||||
fail_unless (events->data == ev);
|
||||
gst_mini_object_unref ((GstMiniObject *) events->data);
|
||||
events = g_list_remove (events, ev);
|
||||
|
||||
fail_unless (g_list_length (buffers) == 1);
|
||||
fail_unless (buffers->data == buf);
|
||||
gst_mini_object_unref ((GstMiniObject *) buffers->data);
|
||||
buffers = g_list_remove (buffers, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_rgvolume (GstElement * element)
|
||||
{
|
||||
|
@ -292,6 +325,8 @@ GST_START_TEST (test_events)
|
|||
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463,
|
||||
|
@ -340,6 +375,8 @@ GST_START_TEST (test_simple)
|
|||
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
|
||||
|
@ -380,6 +417,8 @@ GST_START_TEST (test_fallback_gain)
|
|||
"pre-amp", -6.00, "fallback-gain", -3.00, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0,
|
||||
|
@ -423,6 +462,8 @@ GST_START_TEST (test_fallback_track)
|
|||
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL);
|
||||
|
@ -448,6 +489,8 @@ GST_START_TEST (test_fallback_album)
|
|||
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL);
|
||||
|
@ -470,6 +513,8 @@ GST_START_TEST (test_headroom)
|
|||
"pre-amp", +0.00, "fallback-gain", +1.23, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL);
|
||||
|
@ -512,6 +557,8 @@ GST_START_TEST (test_reference_level)
|
|||
"headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
|
||||
set_playing_state (element);
|
||||
|
||||
send_newsegment_and_empty_buffer ();
|
||||
|
||||
tag_list = gst_tag_list_new_empty ();
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2,
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <libsoup/soup-address.h>
|
||||
|
@ -444,8 +446,11 @@ souphttpsrc_suite (void)
|
|||
TCase *tc_chain, *tc_internet;
|
||||
|
||||
g_type_init ();
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
#endif
|
||||
|
||||
s = suite_create ("souphttpsrc");
|
||||
tc_chain = tcase_create ("general");
|
||||
|
@ -453,7 +458,7 @@ souphttpsrc_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
run_server (&http_port, &https_port);
|
||||
g_atexit (stop_server);
|
||||
atexit (stop_server);
|
||||
tcase_add_test (tc_chain, test_first_buffer_has_offset);
|
||||
tcase_add_test (tc_chain, test_redirect_yes);
|
||||
tcase_add_test (tc_chain, test_redirect_no);
|
||||
|
|
120
tests/check/elements/udpsrc.c
Normal file
120
tests/check/elements/udpsrc.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/* GStreamer UDP source unit tests
|
||||
* Copyright (C) 2011 Tim-Philipp Müller <tim centricular net>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GST_START_TEST (test_udpsrc_empty_packet)
|
||||
{
|
||||
GstElement *udpsrc;
|
||||
GSocket *socket;
|
||||
GstPad *sinkpad;
|
||||
int port = 0;
|
||||
|
||||
udpsrc = gst_check_setup_element ("udpsrc");
|
||||
fail_unless (udpsrc != NULL);
|
||||
g_object_set (udpsrc, "port", 0, NULL);
|
||||
|
||||
sinkpad = gst_check_setup_sink_pad_by_name (udpsrc, &sinktemplate, "src");
|
||||
fail_unless (sinkpad != NULL);
|
||||
gst_pad_set_active (sinkpad, TRUE);
|
||||
|
||||
gst_element_set_state (udpsrc, GST_STATE_PLAYING);
|
||||
g_object_get (udpsrc, "port", &port, NULL);
|
||||
GST_INFO ("udpsrc port = %d", port);
|
||||
|
||||
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
|
||||
G_SOCKET_PROTOCOL_UDP, NULL);
|
||||
|
||||
if (socket != NULL) {
|
||||
GSocketAddress *sa;
|
||||
GInetAddress *ia;
|
||||
gchar *s;
|
||||
|
||||
ia = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
|
||||
s = g_inet_address_to_string (ia);
|
||||
GST_LOG ("inet address %s", s);
|
||||
g_free (s);
|
||||
sa = g_inet_socket_address_new (ia, port);
|
||||
|
||||
if (g_socket_send_to (socket, sa, "HeLL0", 0, NULL, NULL) == 0) {
|
||||
GST_INFO ("sent 0 bytes");
|
||||
if (g_socket_send_to (socket, sa, "HeLL0", 6, NULL, NULL) == 6) {
|
||||
GstBuffer *buf;
|
||||
guint len;
|
||||
|
||||
GST_INFO ("sent 6 bytes");
|
||||
|
||||
g_usleep (G_USEC_PER_SEC / 2);
|
||||
|
||||
len = g_list_length (buffers);
|
||||
GST_INFO ("%u buffers", len);
|
||||
fail_unless (len == 1 || len == 2);
|
||||
|
||||
/* last buffer should be our HeLL0 string */
|
||||
buf = GST_BUFFER (g_list_nth_data (buffers, len - 1));
|
||||
fail_unless_equals_int (GST_BUFFER_SIZE (buf), 6);
|
||||
fail_unless_equals_string ((gchar *) GST_BUFFER_DATA (buf), "HeLL0");
|
||||
|
||||
/* if there's another buffer, it should be 0 bytes */
|
||||
if (len == 2) {
|
||||
buf = GST_BUFFER (g_list_nth_data (buffers, 0));
|
||||
fail_unless_equals_int (GST_BUFFER_SIZE (buf), 0);
|
||||
}
|
||||
} else {
|
||||
GST_WARNING ("send_to(6 bytes) failed");
|
||||
}
|
||||
} else {
|
||||
GST_WARNING ("send_to(0 bytes) failed");
|
||||
}
|
||||
|
||||
g_object_unref (sa);
|
||||
g_object_unref (ia);
|
||||
} else {
|
||||
GST_WARNING ("Could not create IPv4 UDP socket for unit test");
|
||||
}
|
||||
|
||||
gst_element_set_state (udpsrc, GST_STATE_NULL);
|
||||
|
||||
gst_check_teardown_pad_by_name (udpsrc, "src");
|
||||
gst_check_teardown_element (udpsrc);
|
||||
|
||||
g_object_unref (socket);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
udpsrc_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("udpsrc");
|
||||
TCase *tc_chain = tcase_create ("udpsrc");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_udpsrc_empty_packet);
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (udpsrc)
|
|
@ -7,6 +7,7 @@ EXTRA_DIST = \
|
|||
id3-577468-unsynced-tag.tag \
|
||||
id3-588148-unsynced-v24.tag \
|
||||
pcm16sine.flv \
|
||||
pinknoise-vorbis.mkv \
|
||||
test-cert.pem \
|
||||
test-key.pem
|
||||
|
||||
|
|
|
@ -179,8 +179,10 @@ main (int argc, char **argv)
|
|||
GstPad *eq_sinkpad;
|
||||
gchar *uri;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
#endif
|
||||
|
||||
/* command line option parsing */
|
||||
ctx = g_option_context_new ("FILENAME");
|
||||
|
|
|
@ -330,8 +330,10 @@ main (int argc, char **argv)
|
|||
GOptionContext *ctx;
|
||||
GError *opt_err = NULL;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
#endif
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
|
|
|
@ -233,8 +233,10 @@ main (int argc, char **argv)
|
|||
GOptionContext *ctx;
|
||||
GError *err = NULL;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
#endif
|
||||
|
||||
ctx = g_option_context_new ("");
|
||||
g_option_context_add_main_entries (ctx, options, NULL);
|
||||
|
|
|
@ -491,7 +491,13 @@ main (int argc, char *argv[])
|
|||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (!(input_thread = g_thread_create (read_user, source, TRUE, NULL))) {
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
input_thread = g_thread_create (read_user, source, TRUE, NULL);
|
||||
#else
|
||||
input_thread = g_thread_try_new ("v4l2src-test", read_user, source, NULL);
|
||||
#endif
|
||||
|
||||
if (input_thread == NULL) {
|
||||
fprintf (stderr, "error: g_thread_create return NULL");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -193,8 +193,10 @@ main (int argc, char **argv)
|
|||
GstCaps *filter_caps = NULL;
|
||||
GList *caps_list, *l;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 31, 0)
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
#endif
|
||||
|
||||
/* command line option parsing */
|
||||
ctx = g_option_context_new ("");
|
||||
|
|
Loading…
Reference in a new issue