gst/mpegtsparse/: Add request pad for getting the full transport stream coming in.

Original commit message from CVS:
patch by: Alessandro Decina
* gst/mpegtsparse/mpegtspacketizer.c:
* gst/mpegtsparse/mpegtsparse.c:
* gst/mpegtsparse/mpegtsparse.h:
Add request pad for getting the full transport stream coming in.
This commit is contained in:
Alessandro Decina 2007-10-16 16:51:23 +00:00 committed by Zaheer Abbas Merali
parent 93ee0f26d9
commit 389904f624
4 changed files with 101 additions and 11 deletions

View file

@ -1,3 +1,12 @@
2007-10-16 Zaheer Abbas Merali <zaheerabbas at merali dot org>
patch by: Alessandro Decina
* gst/mpegtsparse/mpegtspacketizer.c:
* gst/mpegtsparse/mpegtsparse.c:
* gst/mpegtsparse/mpegtsparse.h:
Add request pad for getting the full transport stream coming in.
2007-10-14 Sebastian Dröge <slomo@circular-chaos.org>
* configure.ac:

View file

@ -105,7 +105,8 @@ mpegts_packetizer_dispose (GObject * object)
packetizer->disposed = TRUE;
}
G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose (object);
if (G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose)
G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose (object);
}
static gboolean
@ -128,7 +129,8 @@ mpegts_packetizer_finalize (GObject * object)
stream_foreach_remove, packetizer);
g_hash_table_destroy (packetizer->streams);
G_OBJECT_CLASS (mpegts_packetizer_parent_class)->finalize (object);
if (G_OBJECT_CLASS (mpegts_packetizer_parent_class)->finalize)
G_OBJECT_CLASS (mpegts_packetizer_parent_class)->finalize (object);
}
static gboolean
@ -142,20 +144,21 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer * packetizer,
if (packet->adaptation_field_control == 0x02) {
/* no payload, adaptation field of 183 bytes */
if (length != 183) {
GST_WARNING ("PID %d afc == 0x%x and length %d != 183",
GST_DEBUG ("PID %d afc == 0x%x and length %d != 183",
packet->pid, packet->adaptation_field_control, length);
}
} else if (length > 182) {
GST_WARNING ("PID %d afc == 0x%01x and length %d > 182",
GST_DEBUG ("PID %d afc == 0x%01x and length %d > 182",
packet->pid, packet->adaptation_field_control, length);
}
/* skip the adaptation field body for now */
if (packet->data + length > packet->data_end) {
GST_ERROR ("PID %d afc length overflows the buffer %d",
GST_DEBUG ("PID %d afc length overflows the buffer %d",
packet->pid, length);
return FALSE;
}
packet->data += length;
return TRUE;
@ -280,7 +283,13 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer * packetizer,
g_value_unset (&value);
}
g_assert (data == end - 4);
if (data != end - 4) {
/* FIXME: check the CRC before parsing the packet */
GST_ERROR ("at the end of PAT data != end - 4");
g_value_array_free (pat);
return NULL;
}
return pat;
}

View file

@ -48,6 +48,7 @@ typedef struct
{
gint program_number;
guint16 pmt_pid;
guint16 pcr_pid;
GObject *pmt_info;
GHashTable *streams;
gint patcount;
@ -83,6 +84,12 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
);
static GstStaticPadTemplate src_template =
GST_STATIC_PAD_TEMPLATE ("src%d", GST_PAD_SRC,
GST_PAD_REQUEST,
GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
);
static GstStaticPadTemplate program_template =
GST_STATIC_PAD_TEMPLATE ("program_%d", GST_PAD_SRC,
GST_PAD_SOMETIMES,
@ -123,6 +130,9 @@ static void mpegts_parse_reset_selected_programs (MpegTSParse * parse,
gchar * programs);
static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad);
static GstPad *mpegts_parse_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name);
static void mpegts_parse_release_pad (GstElement * element, GstPad * pad);
static GstFlowReturn mpegts_parse_chain (GstPad * pad, GstBuffer * buf);
static gboolean mpegts_parse_sink_event (GstPad * pad, GstEvent * event);
static GstStateChangeReturn mpegts_parse_change_state (GstElement * element,
@ -139,6 +149,8 @@ mpegts_parse_base_init (gpointer klass)
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&program_template));
@ -153,6 +165,8 @@ mpegts_parse_class_init (MpegTSParseClass * klass)
element_class = GST_ELEMENT_CLASS (klass);
element_class->pad_removed = mpegts_parse_pad_removed;
element_class->request_new_pad = mpegts_parse_request_new_pad;
element_class->release_pad = mpegts_parse_release_pad;
element_class->change_state = mpegts_parse_change_state;
gobject_class = G_OBJECT_CLASS (klass);
@ -230,7 +244,8 @@ mpegts_parse_dispose (GObject * object)
parse->disposed = TRUE;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
if (G_OBJECT_CLASS (parent_class)->dispose)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
@ -244,7 +259,8 @@ mpegts_parse_finalize (GObject * object)
g_hash_table_destroy (parse->programs);
g_hash_table_destroy (parse->psi_pids);
G_OBJECT_CLASS (parent_class)->finalize (object);
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
@ -289,6 +305,7 @@ mpegts_parse_add_program (MpegTSParse * parse,
program = g_new0 (MpegTSParseProgram, 1);
program->program_number = program_number;
program->pmt_pid = pmt_pid;
program->pcr_pid = G_MAXUINT16;
program->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) mpegts_parse_free_stream);
program->patcount = 1;
@ -529,6 +546,43 @@ mpegts_parse_pad_removed (GstElement * element, GstPad * pad)
tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad);
mpegts_parse_destroy_tspad (parse, tspad);
if (GST_ELEMENT_CLASS (parent_class)->pad_removed)
GST_ELEMENT_CLASS (parent_class)->pad_removed (element, pad);
}
static GstPad *
mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template,
const gchar * unused)
{
MpegTSParse *parse;
gchar *name;
GstPad *pad;
g_return_val_if_fail (template != NULL, NULL);
g_return_val_if_fail (GST_IS_MPEGTS_PARSE (element), NULL);
parse = GST_MPEGTS_PARSE (element);
GST_OBJECT_LOCK (element);
name = g_strdup_printf ("src%d", parse->req_pads++);
GST_OBJECT_UNLOCK (element);
pad = mpegts_parse_create_tspad (parse, name)->pad;
gst_pad_set_active (pad, TRUE);
gst_element_add_pad (element, pad);
return pad;
}
static void
mpegts_parse_release_pad (GstElement * element, GstPad * pad)
{
g_return_if_fail (GST_IS_MPEGTS_PARSE (element));
gst_pad_set_active (pad, FALSE);
/* we do the cleanup in GstElement::pad-removed */
gst_element_remove_pad (element, pad);
}
static GstFlowReturn
@ -538,11 +592,13 @@ mpegts_parse_tspad_push (MpegTSParse * parse, MpegTSParsePad * tspad,
GstFlowReturn ret = GST_FLOW_NOT_LINKED;
GHashTable *pad_pids = NULL;
guint16 pmt_pid = G_MAXUINT16;
guint16 pcr_pid = G_MAXUINT16;
if (tspad->program_number != -1) {
if (tspad->program) {
pad_pids = tspad->program->streams;
pmt_pid = tspad->program->pmt_pid;
pcr_pid = tspad->program->pcr_pid;
} else {
/* there's a program filter on the pad but the PMT for the program has not
* been parsed yet, ignore the pad until we get a PMT */
@ -553,13 +609,12 @@ mpegts_parse_tspad_push (MpegTSParse * parse, MpegTSParsePad * tspad,
}
/* FIXME: send all the SI pids not only PAT and PMT */
if (pad_pids == NULL || pid == 0 || pid == pmt_pid ||
if (pad_pids == NULL || pid == pcr_pid || pid == pmt_pid || pid == 0 ||
g_hash_table_lookup (pad_pids, GINT_TO_POINTER ((gint) pid)) != NULL) {
/* push if there's no filter or if the pid is in the filter */
ret = gst_pad_push (tspad->pad, buffer);
} else {
gst_buffer_unref (buffer);
/* caps don't include this pid */
if (gst_pad_is_linked (tspad->pad))
ret = GST_FLOW_OK;
}
@ -586,15 +641,22 @@ mpegts_parse_push (MpegTSParse * parse, MpegTSPacketizerPacket * packet)
MpegTSParsePad *tspad;
guint16 pid;
GstBuffer *buffer;
GstFlowReturn ret = GST_FLOW_OK;
GstFlowReturn ret;
pid = packet->pid;
buffer = packet->buffer;
/* we have the same caps on all the src pads */
gst_buffer_set_caps (buffer,
gst_static_pad_template_get_caps (&src_template));
GST_OBJECT_LOCK (parse);
/* clear tspad->pushed on pads */
g_list_foreach (GST_ELEMENT_CAST (parse)->srcpads,
(GFunc) pad_clear_for_push, parse);
if (GST_ELEMENT_CAST (parse)->srcpads)
ret = GST_FLOW_NOT_LINKED;
else
ret = GST_FLOW_OK;
GST_OBJECT_UNLOCK (parse);
iterator = gst_element_iterate_src_pads (GST_ELEMENT_CAST (parse));
@ -717,6 +779,12 @@ mpegts_parse_apply_pat (MpegTSParse * parse, GValueArray * pat_info)
"program-number", &program_number, "pid", &pid, NULL);
program = mpegts_parse_get_program (parse, program_number);
if (program == NULL) {
GST_DEBUG_OBJECT (parse, "broken PAT, duplicated entry for program %d",
program_number);
continue;
}
if (--program->patcount > 0)
/* the program has been referenced by the new pat, keep it */
continue;
@ -790,6 +858,8 @@ mpegts_parse_apply_pmt (MpegTSParse * parse,
/* activate new pmt */
program->pmt_info = pmt_info;
program->pmt_pid = pmt_pid;
/* FIXME: check if the pcr pid is changed */
program->pcr_pid = pcr_pid;
mpegts_parse_program_add_stream (parse, program, (guint16) pcr_pid, -1);
for (i = 0; i < new_streams->n_values; ++i) {
@ -797,6 +867,7 @@ mpegts_parse_apply_pmt (MpegTSParse * parse,
stream = g_value_get_object (value);
g_object_get (stream, "pid", &pid, "stream-type", &stream_type, NULL);
GST_DEBUG_OBJECT (parse, "PMT program %d pid %d", program_number, pid);
mpegts_parse_program_add_stream (parse, program, (guint16) pid,
(guint8) stream_type);
}

View file

@ -55,6 +55,7 @@ struct _MpegTSParse {
GList *pads_to_add;
GList *pads_to_remove;
GHashTable *programs;
guint req_pads;
GValueArray *pat_info;
MpegTSPacketizer *packetizer;