# define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
#endif
-GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
-
-#define _do_init(type) \
- gst_pulsesink_init_contexts (); \
- gst_pulsesink_init_interfaces (type);
-
-GST_BOILERPLATE_FULL (GstPulseSink, gst_pulsesink, GstBaseAudioSink,
- GST_TYPE_BASE_AUDIO_SINK, _do_init);
-
-static gboolean
-gst_pulsesink_interface_supported (GstImplementsInterface *
- iface, GType interface_type)
-{
- GstPulseSink *this = GST_PULSESINK_CAST (iface);
-
- if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
- return TRUE;
- if (interface_type == GST_TYPE_STREAM_VOLUME)
- return TRUE;
-
- return FALSE;
-}
-
-static void
-gst_pulsesink_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
- klass->supported = gst_pulsesink_interface_supported;
-}
-
-static void
-gst_pulsesink_init_interfaces (GType type)
-{
- static const GInterfaceInfo implements_iface_info = {
- (GInterfaceInitFunc) gst_pulsesink_implements_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo probe_iface_info = {
- (GInterfaceInitFunc) gst_pulsesink_property_probe_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo svol_iface_info = {
- NULL, NULL, NULL
- };
-
- g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
- g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
- &implements_iface_info);
- g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
- &probe_iface_info);
-}
-
-static void
-gst_pulsesink_base_init (gpointer g_class)
-{
- static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) { " ENDIANNESS " }, "
- "signed = (boolean) TRUE, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-raw-float, "
- "endianness = (int) { " ENDIANNESS " }, "
- "width = (int) 32, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-raw-int, "
- "endianness = (int) { " ENDIANNESS " }, "
- "signed = (boolean) TRUE, "
- "width = (int) 32, "
- "depth = (int) 32, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- "audio/x-raw-int, "
- "endianness = (int) { " ENDIANNESS " }, "
- "signed = (boolean) TRUE, "
- "width = (int) 24, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-raw-int, "
- "endianness = (int) { " ENDIANNESS " }, "
- "signed = (boolean) TRUE, "
- "width = (int) 32, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- "audio/x-raw-int, "
- "signed = (boolean) FALSE, "
- "width = (int) 8, "
- "depth = (int) 8, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-alaw, "
- "rate = (int) [ 1, MAX], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-mulaw, "
- "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
+static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) { " ENDIANNESS " }, "
+ "signed = (boolean) TRUE, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 32 ];"
+ "audio/x-raw-float, "
+ "endianness = (int) { " ENDIANNESS " }, "
+ "width = (int) 32, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 32 ];"
+ "audio/x-raw-int, "
+ "endianness = (int) { " ENDIANNESS " }, "
+ "signed = (boolean) TRUE, "
+ "width = (int) 32, "
+ "depth = (int) 32, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- #ifdef HAVE_PULSE_0_9_15
+ "audio/x-raw-int, "
+ "endianness = (int) { " ENDIANNESS " }, "
+ "signed = (boolean) TRUE, "
+ "width = (int) 24, "
+ "depth = (int) 24, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 32 ];"
+ "audio/x-raw-int, "
+ "endianness = (int) { " ENDIANNESS " }, "
+ "signed = (boolean) TRUE, "
+ "width = (int) 32, "
+ "depth = (int) 24, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- #endif
+ "audio/x-raw-int, "
+ "signed = (boolean) FALSE, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 32 ];"
+ "audio/x-alaw, "
+ "rate = (int) [ 1, MAX], "
+ "channels = (int) [ 1, 32 ];"
+ "audio/x-mulaw, "
- "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
- );
++ "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
+ #ifdef HAVE_PULSE_1_0
- "audio/x-ac3, framed = (boolean) true;"
- "audio/x-eac3, framed = (boolean) true; "
- "audio/x-dts, framed = (boolean) true, "
- " block_size = (int) { 512, 1024, 2048 }; "
- "audio/mpeg, mpegversion = (int)1, "
- " mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true; "
++ "audio/x-ac3, framed = (boolean) true;"
++ "audio/x-eac3, framed = (boolean) true; "
++ "audio/x-dts, framed = (boolean) true, "
++ " block_size = (int) { 512, 1024, 2048 }; "
++ "audio/mpeg, mpegversion = (int)1, "
++ " mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true; "
+ #endif
- ));
++ ));
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
- #define _do_init(type) \
- gst_pulsesink_init_contexts (); \
- gst_pulsesink_init_interfaces (type);
-
- gst_element_class_set_details_simple (element_class,
- "PulseAudio Audio Sink",
- "Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&pad_template));
-}
+#define gst_pulsesink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstPulseSink, gst_pulsesink, GST_TYPE_BASE_AUDIO_SINK,
+ gst_pulsesink_init_contexts ();
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
+ gst_pulsesink_property_probe_interface_init);
+ G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL)
+ );
static GstRingBuffer *
gst_pulsesink_create_ringbuffer (GstBaseAudioSink * sink)
}
static void
-gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
+ gst_pulsesink_sink_info_cb (pa_context * c, const pa_sink_info * i, int eol,
+ void *userdata)
+ {
+ GstPulseRingBuffer *pbuf;
+ GstPulseSink *psink;
+ #ifdef HAVE_PULSE_1_0
+ GList *l;
+ guint8 j;
+ #endif
+
+ pbuf = GST_PULSERING_BUFFER_CAST (userdata);
+ psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
+
+ if (!i)
+ goto done;
+
+ g_free (psink->device_description);
+ psink->device_description = g_strdup (i->description);
+
+ #ifdef HAVE_PULSE_1_0
+ g_mutex_lock (psink->sink_formats_lock);
+
+ for (l = g_list_first (psink->sink_formats); l; l = g_list_next (l))
+ pa_format_info_free ((pa_format_info *) l->data);
+
+ g_list_free (psink->sink_formats);
+ psink->sink_formats = NULL;
+
+ for (j = 0; j < i->n_formats; j++)
+ psink->sink_formats = g_list_prepend (psink->sink_formats,
+ pa_format_info_copy (i->formats[j]));
+
+ g_mutex_unlock (psink->sink_formats_lock);
+ #endif
+
+ done:
+ pa_threaded_mainloop_signal (mainloop, 0);
+ }
+
+ #ifdef HAVE_PULSE_1_0
+ static gboolean
+ gst_pulsesink_pad_acceptcaps (GstPad * pad, GstCaps * caps)
+ {
+ GstPulseSink *psink = GST_PULSESINK (gst_pad_get_parent_element (pad));
+ GstPulseRingBuffer *pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK
+ (psink)->ringbuffer);
+ GstCaps *pad_caps;
+ GstStructure *st;
+ gboolean ret = FALSE;
+
+ GstRingBufferSpec spec = { 0 };
+ pa_stream *stream = NULL;
+ pa_operation *o = NULL;
+ pa_channel_map channel_map;
+ pa_stream_flags_t flags;
+ pa_format_info *format = NULL, *formats[1];
+ guint channels;
+
+ pad_caps = gst_pad_get_caps_reffed (pad);
+ if (pad_caps) {
+ ret = gst_caps_can_intersect (pad_caps, caps);
+ gst_caps_unref (pad_caps);
+ }
+
+ /* Either template caps didn't match, or we're still in NULL state */
+ if (!ret || !pbuf->context)
+ goto done;
+
+ /* If we've not got fixed caps, creating a stream might fail, so let's just
+ * return from here with default acceptcaps behaviour */
+ if (!gst_caps_is_fixed (caps))
+ goto done;
+
+ ret = FALSE;
+
+ pa_threaded_mainloop_lock (mainloop);
+
+ spec.latency_time = GST_BASE_AUDIO_SINK (psink)->latency_time;
+ if (!gst_ring_buffer_parse_caps (&spec, caps))
+ goto out;
+
+ if (!gst_pulse_fill_format_info (&spec, &format, &channels))
+ goto out;
+
+ /* Make sure input is framed (one frame per buffer) and can be payloaded */
+ if (!pa_format_info_is_pcm (format)) {
+ gboolean framed = FALSE, parsed = FALSE;
+ st = gst_caps_get_structure (caps, 0);
+
+ gst_structure_get_boolean (st, "framed", &framed);
+ gst_structure_get_boolean (st, "parsed", &parsed);
+ if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
+ goto out;
+ }
+
+ /* initialize the channel map */
+ if (pa_format_info_is_pcm (format) &&
+ gst_pulse_gst_to_channel_map (&channel_map, &spec))
+ pa_format_info_set_channel_map (format, &channel_map);
+
+ if (pbuf->stream) {
+ /* We're already in PAUSED or above, so just reuse this stream to query
+ * sink formats and use those. */
+ GList *i;
+
+ if (!(o = pa_context_get_sink_info_by_name (pbuf->context, psink->device,
+ gst_pulsesink_sink_info_cb, pbuf)))
+ goto info_failed;
+
+ while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
+ pa_threaded_mainloop_wait (mainloop);
+ if (gst_pulsering_is_dead (psink, pbuf, TRUE))
+ goto out;
+ }
+
+ g_mutex_lock (psink->sink_formats_lock);
+ for (i = g_list_first (psink->sink_formats); i; i = g_list_next (i)) {
+ if (pa_format_info_is_compatible ((pa_format_info *) i->data, format)) {
+ ret = TRUE;
+ break;
+ }
+ }
+ g_mutex_unlock (psink->sink_formats_lock);
+ } else {
+ /* We're in READY, let's connect a stream to see if the format is
+ * accpeted by whatever sink we're routed to */
+ formats[0] = format;
+
+ if (!(stream = pa_stream_new_extended (pbuf->context, "pulsesink probe",
+ formats, 1, psink->proplist)))
+ goto out;
+
+ /* construct the flags */
+ flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
+ PA_STREAM_ADJUST_LATENCY | PA_STREAM_START_CORKED;
+
+ pa_stream_set_state_callback (stream, gst_pulsering_stream_state_cb, pbuf);
+
+ if (pa_stream_connect_playback (stream, psink->device, NULL, flags, NULL,
+ NULL) < 0)
+ goto out;
+
+ ret = gst_pulsering_wait_for_stream_ready (psink, stream);
+ }
+
+ out:
+ if (format)
+ pa_format_info_free (format);
+
+ if (o)
+ pa_operation_unref (o);
+
+ if (stream) {
+ pa_stream_set_state_callback (stream, NULL, NULL);
+ pa_stream_disconnect (stream);
+ pa_stream_unref (stream);
+ }
+
+ pa_threaded_mainloop_unlock (mainloop);
+
+ done:
+ gst_object_unref (psink);
+ return ret;
+
+ info_failed:
+ {
+ GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
+ ("pa_context_get_sink_input_info() failed: %s",
+ pa_strerror (pa_context_errno (pbuf->context))), (NULL));
+ goto out;
+ }
+ }
+ #endif
+
+ static void
+gst_pulsesink_init (GstPulseSink * pulsesink)
{
pulsesink->server = NULL;
pulsesink->device = NULL;
g_param_spec_boxed ("stream-properties", "stream properties",
"list of pulseaudio stream properties",
GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
+ /**
+ * GstPulseSrc:source-output-index
+ *
+ * The index of the PulseAudio source output corresponding to this element.
+ *
+ * Since: 0.10.31
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_SOURCE_OUTPUT_INDEX,
+ g_param_spec_uint ("source-output-index", "source output index",
+ "The index of the PulseAudio source output corresponding to this "
+ "record stream", 0, G_MAXUINT, PA_INVALID_INDEX,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "PulseAudio Audio Source",
+ "Source/Audio",
+ "Captures audio from a PulseAudio server", "Lennart Poettering");
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&pad_template));
}
static void
GstBaseParseFrame * frame, guint * size, gint * skipsize);
static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
+ static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
+ GstEvent * event);
-GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
+#define gst_ac3_parse_parent_class parent_class
+G_DEFINE_TYPE (GstAc3Parse, gst_ac3_parse, GST_TYPE_BASE_PARSE);
static void
-gst_ac3_parse_base_init (gpointer klass)
+gst_ac3_parse_class_init (GstAc3ParseClass * klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
+ "AC3 audio stream parser");
+
+ object_class->finalize = gst_ac3_parse_finalize;
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
return TRUE;
}
+ static void
+ gst_ac3_parse_set_alignment (GstAc3Parse * ac3parse, gboolean eac)
+ {
+ GstCaps *caps;
+ GstStructure *st;
+ const gchar *str = NULL;
+ int i;
+
+ if (G_LIKELY (!eac))
+ goto done;
+
+ caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (ac3parse));
+
+ if (!caps)
+ goto done;
+
+ for (i = 0; i < gst_caps_get_size (caps); i++) {
+ st = gst_caps_get_structure (caps, i);
+
+ if (!g_str_equal (gst_structure_get_name (st), "audio/x-eac3"))
+ continue;
+
+ if ((str = gst_structure_get_string (st, "alignment"))) {
+ if (g_str_equal (str, "iec61937")) {
+ g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_IEC61937);
+ GST_DEBUG_OBJECT (ac3parse, "picked iec61937 alignment");
+ } else if (g_str_equal (str, "frame") == 0) {
+ g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+ GST_DEBUG_OBJECT (ac3parse, "picked frame alignment");
+ } else {
+ g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+ GST_WARNING_OBJECT (ac3parse, "unknown alignment: %s", str);
+ }
+ break;
+ }
+ }
+
+ if (caps)
+ gst_caps_unref (caps);
+
+ done:
+ /* default */
+ if (ac3parse->align == GST_AC3_PARSE_ALIGN_NONE) {
+ g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+ GST_DEBUG_OBJECT (ac3parse, "picked syncframe alignment");
+ }
+ }
+
static gboolean
gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
- guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+ gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
+ guint * sid)
{
- GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ GstBitReader bits;
+ gpointer data;
+ gsize size;
guint8 fscod, frmsizcod, bsid, acmod, lfe_on;
+ gboolean ret = FALSE;
GST_LOG_OBJECT (ac3parse, "parsing ac3");
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+ gst_bit_reader_init (&bits, data, size);
+ gst_bit_reader_skip_unchecked (&bits, skip * 8);
gst_bit_reader_skip_unchecked (&bits, 16 + 16);
fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
static gboolean
gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
- guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+ gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
+ guint * sid)
{
- GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ GstBitReader bits;
+ gpointer data;
+ gsize size;
guint16 frmsiz, sample_rate, blocks;
guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
+ gboolean ret = FALSE;
GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+ gst_bit_reader_init (&bits, data, size);
+ gst_bit_reader_skip_unchecked (&bits, skip * 8);
gst_bit_reader_skip_unchecked (&bits, 16);
strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp */
guint * framesize, guint * rate, guint * chans, guint * blocks,
guint * sid, gboolean * eac)
{
- GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ GstBitReader bits;
guint16 sync;
guint8 bsid;
+ gpointer data;
+ gsize size;
+ gboolean ret = FALSE;
+
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+ gst_bit_reader_init (&bits, data, size);
- GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", GST_BUFFER_DATA (buf), 16);
+ GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", data, MIN (size, 16));
+ gst_bit_reader_skip_unchecked (&bits, skip * 8);
+
sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
gst_bit_reader_skip_unchecked (&bits, 16 + 8);
bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
if (bsid <= 10) {
if (eac)
*eac = FALSE;
- ret = gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
- blocks, sid);
- return gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate,
++ ret = gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate,
+ chans, blocks, sid);
+ goto cleanup;
- }
-
- if (bsid <= 16) {
+ } else if (bsid <= 16) {
if (eac)
*eac = TRUE;
- ret = gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
- blocks, sid);
- return gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate,
++ ret = gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate,
+ chans, blocks, sid);
+ goto cleanup;
+ } else {
+ GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
+ return FALSE;
}
+
+ GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
+
+cleanup:
+ gst_buffer_unmap (buf, data, size);
+
+ return ret;
}
static gboolean
{
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
GstBuffer *buf = frame->buffer;
- GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ GstByteReader reader;
gint off;
- gboolean lost_sync, draining;
+ gboolean lost_sync, draining, eac, more = FALSE;
+ guint frmsiz, blocks, sid;
+ gint have_blocks = 0;
+ gpointer data;
+ gsize size;
+ gboolean ret = FALSE;
- if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
- return FALSE;
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
+ if (G_UNLIKELY (size < 6))
+ goto cleanup;
off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
- 0, GST_BUFFER_SIZE (buf));
+ 0, size);
GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
}
/* make sure the values in the frame header look sane */
- if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
- NULL, NULL, NULL)) {
+ if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, NULL, NULL,
+ &blocks, &sid, &eac)) {
*skipsize = off + 2;
- return FALSE;
+ goto cleanup;
}
+ *framesize = frmsiz;
+
+ if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
+ GST_AC3_PARSE_ALIGN_NONE))
+ gst_ac3_parse_set_alignment (ac3parse, eac);
+
GST_LOG_OBJECT (parse, "got frame");
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
"framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
"channels", G_TYPE_INT, chans, NULL);
- gst_buffer_set_caps (buf, caps);
+ gst_caps_set_simple (caps, "alignment", G_TYPE_STRING,
+ g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937 ?
+ "iec61937" : "frame", NULL);
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
gst_caps_unref (caps);
GstBuffer * buf);
static gboolean gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * filter,
GstCaps * caps);
+ static gboolean gst_rtp_h264_depay_handle_event (GstBaseRTPDepayload * depay,
+ GstEvent * event);
static void
-gst_rtp_h264_depay_base_init (gpointer klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_rtp_h264_depay_src_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_rtp_h264_depay_sink_template));
-
- gst_element_class_set_details_simple (element_class, "RTP H264 depayloader",
- "Codec/Depayloader/Network/RTP",
- "Extracts H264 video from RTP packets (RFC 3984)",
- "Wim Taymans <wim.taymans@gmail.com>");
-}
-
-static void
gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
{
GObjectClass *gobject_class;
timestamp = GST_BUFFER_TIMESTAMP (buf);
- payload_len = gst_rtp_buffer_get_payload_len (buf);
- payload = gst_rtp_buffer_get_payload (buf);
- marker = gst_rtp_buffer_get_marker (buf);
+ gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
+
+ payload_len = gst_rtp_buffer_get_payload_len (&rtp);
+ payload = gst_rtp_buffer_get_payload (&rtp);
++ marker = gst_rtp_buffer_get_marker (&rtp);
GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);
outdata[2] = nalu_size >> 8;
outdata[3] = nalu_size & 0xff;
}
- outdata += sizeof (sync_bytes);
- memcpy (outdata, payload, nalu_size);
+ memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
+ gst_buffer_unmap (outbuf, outdata, outsize);
- gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
+ gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp, marker);
break;
}
}
GstRtpH264Pay *rtph264pay;
GstStructure *str;
const GValue *value;
- guint8 *data;
- guint size;
+ guint8 *data, *bdata;
+ gsize size, bsize;
+ GstBuffer *buffer;
+ const gchar *alignment;
rtph264pay = GST_RTP_H264_PAY (basepayload);
* NALs */
gst_basertppayload_set_options (basepayload, "video", TRUE, "H264", 90000);
+ alignment = gst_structure_get_string (str, "alignment");
+ if (alignment && !strcmp (alignment, "au"))
+ rtph264pay->au_alignment = TRUE;
+ else
+ rtph264pay->au_alignment = FALSE;
+
/* packetized AVC video has a codec_data */
if ((value = gst_structure_get_value (str, "codec_data"))) {
- GstBuffer *buffer;
guint num_sps, num_pps;
gint i, nal_size;
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
/* resend SPS */
+ data = gst_buffer_map (sps_buf, &size, NULL, GST_MAP_READ);
ret = gst_rtp_h264_pay_payload_nal (basepayload,
- data, size, timestamp, sps_buf);
- GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp,
- sps_buf, FALSE);
++ data, size, timestamp, sps_buf, FALSE);
+ gst_buffer_unmap (sps_buf, data, size);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing SPS");
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
/* resend PPS */
+ data = gst_buffer_map (pps_buf, &size, NULL, GST_MAP_READ);
ret = gst_rtp_h264_pay_payload_nal (basepayload,
- data, size, timestamp, pps_buf);
- GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp,
- pps_buf, FALSE);
++ data, size, timestamp, pps_buf, FALSE);
+ gst_buffer_unmap (pps_buf, data, size);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing PPS");
outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
}
+ gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
+
/* only set the marker bit on packets containing access units */
- if (IS_ACCESS_UNIT (nalType)) {
+ if (IS_ACCESS_UNIT (nalType) && end_of_au) {
- gst_rtp_buffer_set_marker (outbuf, 1);
+ gst_rtp_buffer_set_marker (&rtp, 1);
}
/* timestamp the outbuffer */
end = 1;
}
if (IS_ACCESS_UNIT (nalType)) {
- gst_rtp_buffer_set_marker (&rtp, end);
- gst_rtp_buffer_set_marker (outbuf, end && end_of_au);
++ gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
}
/* FU indicator */
GstRtpSsrcDemux *demux;
guint32 ssrc;
GstRtpSsrcDemuxPad *dpad;
+ GstRTPBuffer rtp;
+ GstPad *srcpad;
demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));
guint32 ssrc;
GstRtpSsrcDemuxPad *dpad;
GstRTCPPacket packet;
+ GstRTCPBuffer rtcp;
+ GstPad *srcpad;
demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));