mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 00:01:23 +00:00
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:
parent
93ee0f26d9
commit
389904f624
4 changed files with 101 additions and 11 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ struct _MpegTSParse {
|
|||
GList *pads_to_add;
|
||||
GList *pads_to_remove;
|
||||
GHashTable *programs;
|
||||
guint req_pads;
|
||||
|
||||
GValueArray *pat_info;
|
||||
MpegTSPacketizer *packetizer;
|
||||
|
|
Loading…
Reference in a new issue