mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
Fix mpegdemux, implement caching
Original commit message from CVS: Fix mpegdemux, implement caching
This commit is contained in:
parent
ce28203420
commit
a82c0aa533
5 changed files with 254 additions and 132 deletions
|
@ -134,9 +134,14 @@ static gboolean gst_mpeg_demux_parse_packhead (GstMPEGParse *mpeg_parse, GstBuf
|
||||||
static gboolean gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
static gboolean gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
||||||
static gboolean gst_mpeg_demux_parse_packet (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
static gboolean gst_mpeg_demux_parse_packet (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
||||||
static gboolean gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
static gboolean gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
|
||||||
static void gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse, GstData *data, GstClockTime time);
|
static void gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse,
|
||||||
|
GstData *data, GstClockTime time);
|
||||||
|
|
||||||
static void gst_mpeg_demux_handle_discont (GstMPEGParse *mpeg_parse);
|
static void gst_mpeg_demux_handle_discont (GstMPEGParse *mpeg_parse);
|
||||||
|
|
||||||
|
static void gst_mpeg_demux_set_cache (GstElement *element, GstCache *cache);
|
||||||
|
static GstCache* gst_mpeg_demux_get_cache (GstElement *element);
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
gst_mpeg_demux_change_state (GstElement *element);
|
gst_mpeg_demux_change_state (GstElement *element);
|
||||||
|
|
||||||
|
@ -177,6 +182,8 @@ gst_mpeg_demux_class_init (GstMPEGDemuxClass *klass)
|
||||||
gstelement_class = (GstElementClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
gstelement_class->change_state = gst_mpeg_demux_change_state;
|
gstelement_class->change_state = gst_mpeg_demux_change_state;
|
||||||
|
gstelement_class->set_cache = gst_mpeg_demux_set_cache;
|
||||||
|
gstelement_class->get_cache = gst_mpeg_demux_get_cache;
|
||||||
|
|
||||||
mpeg_parse_class->parse_packhead = gst_mpeg_demux_parse_packhead;
|
mpeg_parse_class->parse_packhead = gst_mpeg_demux_parse_packhead;
|
||||||
mpeg_parse_class->parse_syshead = gst_mpeg_demux_parse_syshead;
|
mpeg_parse_class->parse_syshead = gst_mpeg_demux_parse_syshead;
|
||||||
|
@ -200,23 +207,33 @@ gst_mpeg_demux_init (GstMPEGDemux *mpeg_demux)
|
||||||
gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
|
gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
|
||||||
|
|
||||||
/* i think everything is already zero'd, but oh well*/
|
/* i think everything is already zero'd, but oh well*/
|
||||||
for (i=0;i<NUM_PRIVATE_1_PADS;i++) {
|
for (i=0;i<NUM_PRIVATE_1_STREAMS;i++) {
|
||||||
mpeg_demux->private_1_pad[i] = NULL;
|
mpeg_demux->private_1_stream[i] = NULL;
|
||||||
}
|
}
|
||||||
for (i=0;i<NUM_SUBTITLE_PADS;i++) {
|
for (i=0;i<NUM_SUBTITLE_STREAMS;i++) {
|
||||||
mpeg_demux->subtitle_pad[i] = NULL;
|
mpeg_demux->subtitle_stream[i] = NULL;
|
||||||
}
|
}
|
||||||
mpeg_demux->private_2_pad = NULL;
|
mpeg_demux->private_2_stream = NULL;
|
||||||
for (i=0;i<NUM_VIDEO_PADS;i++) {
|
for (i=0;i<NUM_VIDEO_STREAMS;i++) {
|
||||||
mpeg_demux->video_pad[i] = NULL;
|
mpeg_demux->video_stream[i] = NULL;
|
||||||
}
|
}
|
||||||
for (i=0;i<NUM_AUDIO_PADS;i++) {
|
for (i=0;i<NUM_AUDIO_STREAMS;i++) {
|
||||||
mpeg_demux->audio_pad[i] = NULL;
|
mpeg_demux->audio_stream[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_FLAG_SET (mpeg_demux, GST_ELEMENT_EVENT_AWARE);
|
GST_FLAG_SET (mpeg_demux, GST_ELEMENT_EVENT_AWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstMPEGStream*
|
||||||
|
gst_mpeg_demux_new_stream (void)
|
||||||
|
{
|
||||||
|
GstMPEGStream *stream;
|
||||||
|
|
||||||
|
stream = g_new0 (GstMPEGStream, 1);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse, GstData *data, GstClockTime time)
|
gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse, GstData *data, GstClockTime time)
|
||||||
{
|
{
|
||||||
|
@ -245,26 +262,26 @@ gst_mpeg_demux_handle_discont (GstMPEGParse *mpeg_parse)
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_EVENT, "discont %llu\n", current_time);
|
GST_DEBUG (GST_CAT_EVENT, "discont %llu\n", current_time);
|
||||||
|
|
||||||
for (i=0;i<NUM_VIDEO_PADS;i++) {
|
for (i=0;i<NUM_VIDEO_STREAMS;i++) {
|
||||||
if (mpeg_demux->video_pad[i] &&
|
if (mpeg_demux->video_stream[i] &&
|
||||||
GST_PAD_IS_USABLE (mpeg_demux->video_pad[i]))
|
GST_PAD_IS_USABLE (mpeg_demux->video_stream[i]->pad))
|
||||||
{
|
{
|
||||||
GstEvent *discont;
|
GstEvent *discont;
|
||||||
|
|
||||||
discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
|
discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
|
||||||
current_time, NULL);
|
current_time, NULL);
|
||||||
|
|
||||||
gst_pad_push (mpeg_demux->video_pad[i], GST_BUFFER (discont));
|
gst_pad_push (mpeg_demux->video_stream[i]->pad, GST_BUFFER (discont));
|
||||||
}
|
}
|
||||||
if (mpeg_demux->audio_pad[i] &&
|
if (mpeg_demux->audio_stream[i] &&
|
||||||
GST_PAD_IS_USABLE (mpeg_demux->audio_pad[i]))
|
GST_PAD_IS_USABLE (mpeg_demux->audio_stream[i]->pad))
|
||||||
{
|
{
|
||||||
GstEvent *discont;
|
GstEvent *discont;
|
||||||
|
|
||||||
discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
|
discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
|
||||||
current_time, NULL);
|
current_time, NULL);
|
||||||
|
|
||||||
gst_pad_push (mpeg_demux->audio_pad[i], GST_BUFFER (discont));
|
gst_pad_push (mpeg_demux->audio_stream[i]->pad, GST_BUFFER (discont));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +342,7 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
guint16 STD_buffer_size_bound;
|
guint16 STD_buffer_size_bound;
|
||||||
guint32 buf_byte_size_bound;
|
guint32 buf_byte_size_bound;
|
||||||
gchar *name = NULL;
|
gchar *name = NULL;
|
||||||
GstPad **outpad = NULL;
|
GstMPEGStream **outstream = NULL;
|
||||||
GstPadTemplate *newtemp = NULL;
|
GstPadTemplate *newtemp = NULL;
|
||||||
|
|
||||||
stream_id = *buf++;
|
stream_id = *buf++;
|
||||||
|
@ -355,24 +372,24 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
/* private_stream_1 */
|
/* private_stream_1 */
|
||||||
case 0xBD:
|
case 0xBD:
|
||||||
name = NULL;
|
name = NULL;
|
||||||
outpad = NULL;
|
outstream = NULL;
|
||||||
break;
|
break;
|
||||||
/* private_stream_2 */
|
/* private_stream_2 */
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
name = g_strdup_printf ("private_stream_2");
|
name = g_strdup_printf ("private_stream_2");
|
||||||
outpad = &mpeg_demux->private_2_pad;
|
outstream = &mpeg_demux->private_2_stream;
|
||||||
newtemp = GST_PAD_TEMPLATE_GET (private2_factory);
|
newtemp = GST_PAD_TEMPLATE_GET (private2_factory);
|
||||||
break;
|
break;
|
||||||
/* Audio */
|
/* Audio */
|
||||||
case 0xC0 ... 0xDF:
|
case 0xC0 ... 0xDF:
|
||||||
name = g_strdup_printf ("audio_%02d", stream_id & 0x1F);
|
name = g_strdup_printf ("audio_%02d", stream_id & 0x1F);
|
||||||
outpad = &mpeg_demux->audio_pad[stream_id & 0x1F];
|
outstream = &mpeg_demux->audio_stream[stream_id & 0x1F];
|
||||||
newtemp = GST_PAD_TEMPLATE_GET (audio_factory);
|
newtemp = GST_PAD_TEMPLATE_GET (audio_factory);
|
||||||
break;
|
break;
|
||||||
/* Video */
|
/* Video */
|
||||||
case 0xE0 ... 0xEF:
|
case 0xE0 ... 0xEF:
|
||||||
name = g_strdup_printf ("video_%02d", stream_id & 0x0F);
|
name = g_strdup_printf ("video_%02d", stream_id & 0x0F);
|
||||||
outpad = &mpeg_demux->video_pad[stream_id & 0x0F];
|
outstream = &mpeg_demux->video_stream[stream_id & 0x0F];
|
||||||
if (!GST_MPEG_PARSE_IS_MPEG2 (mpeg_demux)) {
|
if (!GST_MPEG_PARSE_IS_MPEG2 (mpeg_demux)) {
|
||||||
newtemp = GST_PAD_TEMPLATE_GET (video_mpeg1_factory);
|
newtemp = GST_PAD_TEMPLATE_GET (video_mpeg1_factory);
|
||||||
}
|
}
|
||||||
|
@ -394,7 +411,12 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
* this should trigger the NEW_PAD signal, which should be caught by
|
* this should trigger the NEW_PAD signal, which should be caught by
|
||||||
* the app and used to attach to desired streams.
|
* the app and used to attach to desired streams.
|
||||||
*/
|
*/
|
||||||
if (outpad && *outpad == NULL) {
|
if (outstream && *outstream == NULL) {
|
||||||
|
GstPad **outpad;
|
||||||
|
|
||||||
|
*outstream = gst_mpeg_demux_new_stream ();
|
||||||
|
outpad = &((*outstream)->pad);
|
||||||
|
|
||||||
*outpad = gst_pad_new_from_template (newtemp, name);
|
*outpad = gst_pad_new_from_template (newtemp, name);
|
||||||
gst_pad_try_set_caps (*outpad, gst_pad_get_pad_template_caps (*outpad));
|
gst_pad_try_set_caps (*outpad, gst_pad_get_pad_template_caps (*outpad));
|
||||||
|
|
||||||
|
@ -406,6 +428,11 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
|
|
||||||
gst_element_add_pad (GST_ELEMENT (mpeg_demux), (*outpad));
|
gst_element_add_pad (GST_ELEMENT (mpeg_demux), (*outpad));
|
||||||
|
|
||||||
|
if (mpeg_demux->cache) {
|
||||||
|
gst_cache_get_writer_id (mpeg_demux->cache, GST_OBJECT (*outpad),
|
||||||
|
&(*outstream)->cache_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (GST_PAD_IS_USABLE (*outpad)) {
|
if (GST_PAD_IS_USABLE (*outpad)) {
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
gint64 time;
|
gint64 time;
|
||||||
|
@ -424,12 +451,6 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpeg_demux->STD_buffer_info[j].stream_id = stream_id;
|
|
||||||
mpeg_demux->STD_buffer_info[j].STD_buffer_bound_scale =
|
|
||||||
STD_buffer_bound_scale;
|
|
||||||
mpeg_demux->STD_buffer_info[j].STD_buffer_size_bound =
|
|
||||||
STD_buffer_size_bound;
|
|
||||||
|
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,9 +474,11 @@ gst_mpeg_demux_parse_packet (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
|
|
||||||
guint16 datalen;
|
guint16 datalen;
|
||||||
|
|
||||||
GstPad **outpad = NULL;
|
GstMPEGStream **outstream = NULL;
|
||||||
|
GstPad *outpad = NULL;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
guint8 *buf, *basebuf;
|
guint8 *buf, *basebuf;
|
||||||
|
gint64 timestamp;
|
||||||
|
|
||||||
GST_DEBUG (0, "in parse_packet");
|
GST_DEBUG (0, "in parse_packet");
|
||||||
|
|
||||||
|
@ -559,7 +582,7 @@ done:
|
||||||
case 0x80 ... 0x87:
|
case 0x80 ... 0x87:
|
||||||
GST_DEBUG (0, "0x%02X: we have a private_stream_1 (AC3) packet, track %d",
|
GST_DEBUG (0, "0x%02X: we have a private_stream_1 (AC3) packet, track %d",
|
||||||
id, ps_id_code - 0x80);
|
id, ps_id_code - 0x80);
|
||||||
outpad = &mpeg_demux->private_1_pad[ps_id_code - 0x80];
|
outstream = &mpeg_demux->private_1_stream[ps_id_code - 0x80];
|
||||||
/* scrap first 4 bytes (so-called "mystery AC3 tag") */
|
/* scrap first 4 bytes (so-called "mystery AC3 tag") */
|
||||||
headerlen += 4;
|
headerlen += 4;
|
||||||
datalen -= 4;
|
datalen -= 4;
|
||||||
|
@ -571,55 +594,66 @@ done:
|
||||||
/* private_stream_2 */
|
/* private_stream_2 */
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
GST_DEBUG (0, "0x%02X: we have a private_stream_2 packet", id);
|
GST_DEBUG (0, "0x%02X: we have a private_stream_2 packet", id);
|
||||||
outpad = &mpeg_demux->private_2_pad;
|
outstream = &mpeg_demux->private_2_stream;
|
||||||
break;
|
break;
|
||||||
/* audio */
|
/* audio */
|
||||||
case 0xC0 ... 0xDF:
|
case 0xC0 ... 0xDF:
|
||||||
GST_DEBUG (0, "0x%02X: we have an audio packet", id);
|
GST_DEBUG (0, "0x%02X: we have an audio packet", id);
|
||||||
outpad = &mpeg_demux->audio_pad[id & 0x1F];
|
outstream = &mpeg_demux->audio_stream[id & 0x1F];
|
||||||
break;
|
break;
|
||||||
/* video */
|
/* video */
|
||||||
case 0xE0 ... 0xEF:
|
case 0xE0 ... 0xEF:
|
||||||
GST_DEBUG (0, "0x%02X: we have a video packet", id);
|
GST_DEBUG (0, "0x%02X: we have a video packet", id);
|
||||||
outpad = &mpeg_demux->video_pad[id & 0x0F];
|
outstream = &mpeg_demux->video_stream[id & 0x0F];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we don't know what it is, bail */
|
/* if we don't know what it is, bail */
|
||||||
if (outpad == NULL) {
|
if (outstream == NULL) {
|
||||||
GST_DEBUG (0, "unknown packet id 0x%02X !!", id);
|
GST_DEBUG (0, "unknown packet id 0x%02X !!", id);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outpad = (*outstream)->pad;
|
||||||
|
|
||||||
/* the pad should have been created in parse_syshead */
|
/* the pad should have been created in parse_syshead */
|
||||||
if ((*outpad) == NULL) {
|
if (outpad == NULL) {
|
||||||
GST_DEBUG (0, "unexpected packet id 0x%02X!!", id);
|
GST_DEBUG (0, "unexpected packet id 0x%02X!!", id);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attach pts, if any */
|
||||||
|
if (pts != -1) {
|
||||||
|
pts += mpeg_parse->adjust;
|
||||||
|
timestamp = MPEGTIME_TO_GSTTIME (pts);
|
||||||
|
|
||||||
|
if (mpeg_demux->cache) {
|
||||||
|
gst_cache_add_association (mpeg_demux->cache,
|
||||||
|
(*outstream)->cache_id, 0,
|
||||||
|
GST_FORMAT_BYTES, GST_BUFFER_OFFSET (buffer),
|
||||||
|
GST_FORMAT_TIME, timestamp,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timestamp = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* create the buffer and send it off to the Other Side */
|
/* create the buffer and send it off to the Other Side */
|
||||||
if (GST_PAD_IS_CONNECTED(*outpad) && datalen > 0) {
|
if (GST_PAD_IS_CONNECTED (outpad) && datalen > 0) {
|
||||||
GST_DEBUG (0, "creating subbuffer len %d", datalen);
|
GST_DEBUG (0, "creating subbuffer len %d", datalen);
|
||||||
|
|
||||||
/* if this is part of the buffer, create a subbuffer */
|
/* if this is part of the buffer, create a subbuffer */
|
||||||
outbuf = gst_buffer_create_sub (buffer, headerlen + 4, datalen);
|
outbuf = gst_buffer_create_sub (buffer, headerlen + 4, datalen);
|
||||||
|
|
||||||
/* attach pts, if any */
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
if (pts != -1) {
|
|
||||||
pts += mpeg_parse->adjust;
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = MPEGTIME_TO_GSTTIME (pts);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = -1LL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG (0, "pushing buffer of len %d id %d, ts %lld",
|
GST_DEBUG (0, "pushing buffer of len %d id %d, ts %lld",
|
||||||
datalen, id, GST_BUFFER_TIMESTAMP (outbuf));
|
datalen, id, GST_BUFFER_TIMESTAMP (outbuf));
|
||||||
|
|
||||||
gst_pad_push ((*outpad), outbuf);
|
gst_pad_push (outpad, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -639,6 +673,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
guint16 headerlen;
|
guint16 headerlen;
|
||||||
guint8 ps_id_code = 0x80;
|
guint8 ps_id_code = 0x80;
|
||||||
|
|
||||||
|
GstMPEGStream **outstream = NULL;
|
||||||
GstPad **outpad = NULL;
|
GstPad **outpad = NULL;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
GstPadTemplate *newtemp = NULL;
|
GstPadTemplate *newtemp = NULL;
|
||||||
|
@ -723,7 +758,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
case 0x80 ... 0x87:
|
case 0x80 ... 0x87:
|
||||||
GST_DEBUG (0, "we have a private_stream_1 (AC3) packet, track %d",
|
GST_DEBUG (0, "we have a private_stream_1 (AC3) packet, track %d",
|
||||||
ps_id_code - 0x80);
|
ps_id_code - 0x80);
|
||||||
outpad = &mpeg_demux->private_1_pad[ps_id_code - 0x80];
|
outstream = &mpeg_demux->private_1_stream[ps_id_code - 0x80];
|
||||||
/* scrap first 4 bytes (so-called "mystery AC3 tag") */
|
/* scrap first 4 bytes (so-called "mystery AC3 tag") */
|
||||||
headerlen += 4;
|
headerlen += 4;
|
||||||
datalen -= 4;
|
datalen -= 4;
|
||||||
|
@ -731,7 +766,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
case 0x20 ... 0x2f:
|
case 0x20 ... 0x2f:
|
||||||
GST_DEBUG (0, "we have a subtitle_stream packet, track %d",
|
GST_DEBUG (0, "we have a subtitle_stream packet, track %d",
|
||||||
ps_id_code - 0x20);
|
ps_id_code - 0x20);
|
||||||
outpad = &mpeg_demux->subtitle_pad[ps_id_code - 0x20];
|
outstream = &mpeg_demux->subtitle_stream[ps_id_code - 0x20];
|
||||||
headerlen += 1;
|
headerlen += 1;
|
||||||
datalen -= 1;
|
datalen -= 1;
|
||||||
break;
|
break;
|
||||||
|
@ -744,17 +779,17 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
/* private_stream_2 */
|
/* private_stream_2 */
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
GST_DEBUG (0, "we have a private_stream_2 packet");
|
GST_DEBUG (0, "we have a private_stream_2 packet");
|
||||||
outpad = &mpeg_demux->private_2_pad;
|
outstream = &mpeg_demux->private_2_stream;
|
||||||
break;
|
break;
|
||||||
/* audio */
|
/* audio */
|
||||||
case 0xC0 ... 0xDF:
|
case 0xC0 ... 0xDF:
|
||||||
GST_DEBUG (0, "we have an audio packet");
|
GST_DEBUG (0, "we have an audio packet");
|
||||||
outpad = &mpeg_demux->audio_pad[id - 0xC0];
|
outstream = &mpeg_demux->audio_stream[id - 0xC0];
|
||||||
break;
|
break;
|
||||||
/* video */
|
/* video */
|
||||||
case 0xE0 ... 0xEF:
|
case 0xE0 ... 0xEF:
|
||||||
GST_DEBUG (0, "we have a video packet");
|
GST_DEBUG (0, "we have a video packet");
|
||||||
outpad = &mpeg_demux->video_pad[id - 0xE0];
|
outstream = &mpeg_demux->video_stream[id - 0xE0];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GST_DEBUG (0, "we have a unkown packet");
|
GST_DEBUG (0, "we have a unkown packet");
|
||||||
|
@ -762,13 +797,13 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we don't know what it is, bail */
|
/* if we don't know what it is, bail */
|
||||||
if (outpad == NULL)
|
if (outstream == NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* create the pad and add it if we don't already have one. */
|
/* create the pad and add it if we don't already have one. */
|
||||||
/* this should trigger the NEW_PAD signal, which should be caught by */
|
/* this should trigger the NEW_PAD signal, which should be caught by */
|
||||||
/* the app and used to attach to desired streams. */
|
/* the app and used to attach to desired streams. */
|
||||||
if ((*outpad) == NULL) {
|
if ((*outstream) == NULL) {
|
||||||
gchar *name = NULL;
|
gchar *name = NULL;
|
||||||
|
|
||||||
/* we have to name the stream approriately */
|
/* we have to name the stream approriately */
|
||||||
|
@ -811,9 +846,12 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newtemp) {
|
if (newtemp) {
|
||||||
|
*outstream = gst_mpeg_demux_new_stream ();
|
||||||
|
outpad = &((*outstream)->pad);
|
||||||
|
|
||||||
/* create the pad and add it to self */
|
/* create the pad and add it to self */
|
||||||
(*outpad) = gst_pad_new_from_template (newtemp, name);
|
*outpad = gst_pad_new_from_template (newtemp, name);
|
||||||
gst_pad_try_set_caps ((*outpad), gst_pad_get_pad_template_caps (*outpad));
|
gst_pad_try_set_caps (*outpad, gst_pad_get_pad_template_caps (*outpad));
|
||||||
|
|
||||||
gst_pad_set_formats_function (*outpad, gst_mpeg_parse_get_src_formats);
|
gst_pad_set_formats_function (*outpad, gst_mpeg_parse_get_src_formats);
|
||||||
gst_pad_set_event_mask_function (*outpad, gst_mpeg_parse_get_src_event_masks);
|
gst_pad_set_event_mask_function (*outpad, gst_mpeg_parse_get_src_event_masks);
|
||||||
|
@ -821,7 +859,12 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
gst_pad_set_query_type_function (*outpad, gst_mpeg_parse_get_src_query_types);
|
gst_pad_set_query_type_function (*outpad, gst_mpeg_parse_get_src_query_types);
|
||||||
gst_pad_set_query_function (*outpad, gst_mpeg_parse_handle_src_query);
|
gst_pad_set_query_function (*outpad, gst_mpeg_parse_handle_src_query);
|
||||||
|
|
||||||
gst_element_add_pad(GST_ELEMENT(mpeg_demux),(*outpad));
|
gst_element_add_pad(GST_ELEMENT(mpeg_demux), *outpad);
|
||||||
|
|
||||||
|
if (mpeg_demux->cache) {
|
||||||
|
gst_cache_get_writer_id (mpeg_demux->cache, GST_OBJECT (*outpad),
|
||||||
|
&(*outstream)->cache_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g_warning ("cannot create pad %s, no template for %02x", name, id);
|
g_warning ("cannot create pad %s, no template for %02x", name, id);
|
||||||
|
@ -830,23 +873,39 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*outstream) {
|
||||||
|
gint64 timestamp;
|
||||||
|
|
||||||
|
outpad = &((*outstream)->pad);
|
||||||
|
|
||||||
|
/* attach pts, if any */
|
||||||
|
if (pts != -1) {
|
||||||
|
pts += mpeg_parse->adjust;
|
||||||
|
timestamp = MPEGTIME_TO_GSTTIME (pts);
|
||||||
|
|
||||||
|
if (mpeg_demux->cache) {
|
||||||
|
gst_cache_add_association (mpeg_demux->cache,
|
||||||
|
(*outstream)->cache_id, 0,
|
||||||
|
GST_FORMAT_BYTES, GST_BUFFER_OFFSET (buffer),
|
||||||
|
GST_FORMAT_TIME, timestamp,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timestamp = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* create the buffer and send it off to the Other Side */
|
/* create the buffer and send it off to the Other Side */
|
||||||
if (GST_PAD_IS_USABLE(*outpad)) {
|
if (*outpad && GST_PAD_IS_USABLE(*outpad)) {
|
||||||
/* if this is part of the buffer, create a subbuffer */
|
/* if this is part of the buffer, create a subbuffer */
|
||||||
GST_DEBUG (0,"creating subbuffer len %d", datalen);
|
GST_DEBUG (0,"creating subbuffer len %d", datalen);
|
||||||
|
|
||||||
outbuf = gst_buffer_create_sub (buffer, headerlen+4, datalen);
|
outbuf = gst_buffer_create_sub (buffer, headerlen+4, datalen);
|
||||||
|
|
||||||
if (pts != -1) {
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||||
pts += mpeg_parse->adjust;
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = MPEGTIME_TO_GSTTIME (pts);
|
gst_pad_push(*outpad,outbuf);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = -1LL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_pad_push((*outpad),outbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -871,6 +930,28 @@ gst_mpeg_demux_change_state (GstElement *element)
|
||||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_mpeg_demux_set_cache (GstElement *element, GstCache *cache)
|
||||||
|
{
|
||||||
|
GstMPEGDemux *mpeg_demux;
|
||||||
|
|
||||||
|
GST_ELEMENT_CLASS (parent_class)->set_cache (element, cache);
|
||||||
|
|
||||||
|
mpeg_demux = GST_MPEG_DEMUX (element);
|
||||||
|
|
||||||
|
mpeg_demux->cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCache*
|
||||||
|
gst_mpeg_demux_get_cache (GstElement *element)
|
||||||
|
{
|
||||||
|
GstMPEGDemux *mpeg_demux;
|
||||||
|
|
||||||
|
mpeg_demux = GST_MPEG_DEMUX (element);
|
||||||
|
|
||||||
|
return mpeg_demux->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_mpeg_demux_plugin_init (GModule *module, GstPlugin *plugin)
|
gst_mpeg_demux_plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
|
|
|
@ -46,41 +46,23 @@ extern "C" {
|
||||||
typedef struct _GstMPEGDemux GstMPEGDemux;
|
typedef struct _GstMPEGDemux GstMPEGDemux;
|
||||||
typedef struct _GstMPEGDemuxClass GstMPEGDemuxClass;
|
typedef struct _GstMPEGDemuxClass GstMPEGDemuxClass;
|
||||||
|
|
||||||
typedef struct _MPEG1Stream MPEG1Stream;
|
typedef struct _GstMPEGStream GstMPEGStream;
|
||||||
|
|
||||||
struct _MPEG1Stream {
|
struct _GstMPEGStream {
|
||||||
guchar stream_id;
|
|
||||||
gint8 STD_buffer_bound_scale;
|
gint8 STD_buffer_bound_scale;
|
||||||
gint16 STD_buffer_size_bound;
|
gint16 STD_buffer_size_bound;
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _GstMPEG1StreamContext GstMPEG1StreamContext;
|
|
||||||
|
|
||||||
struct _GstMPEGStreamContext {
|
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
guint64 pts;
|
guint64 pts;
|
||||||
|
gint cache_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMPEGDemux {
|
struct _GstMPEGDemux {
|
||||||
GstMPEGParse parent;
|
GstMPEGParse parent;
|
||||||
|
|
||||||
/* current parse state */
|
|
||||||
guchar id;
|
|
||||||
|
|
||||||
/* previous partial chunk and bytes remaining in it */
|
/* previous partial chunk and bytes remaining in it */
|
||||||
gboolean in_flush;
|
gboolean in_flush;
|
||||||
|
|
||||||
/* counters */
|
|
||||||
gulong packs;
|
|
||||||
|
|
||||||
/* pack header values */
|
|
||||||
gboolean have_packhead;
|
|
||||||
guint64 scr_base;
|
|
||||||
guint16 scr_extension;
|
|
||||||
guint32 bit_rate;
|
|
||||||
|
|
||||||
/* program stream header values */
|
/* program stream header values */
|
||||||
gboolean have_syshead;
|
|
||||||
guint16 header_length;
|
guint16 header_length;
|
||||||
guint32 rate_bound;
|
guint32 rate_bound;
|
||||||
guint8 audio_bound;
|
guint8 audio_bound;
|
||||||
|
@ -90,19 +72,20 @@ struct _GstMPEGDemux {
|
||||||
gboolean video_lock;
|
gboolean video_lock;
|
||||||
guint8 video_bound;
|
guint8 video_bound;
|
||||||
gboolean packet_rate_restriction;
|
gboolean packet_rate_restriction;
|
||||||
struct _MPEG1Stream STD_buffer_info[48];
|
|
||||||
|
|
||||||
#define NUM_PRIVATE_1_PADS 8
|
#define NUM_PRIVATE_1_STREAMS 8
|
||||||
#define NUM_SUBTITLE_PADS 16
|
#define NUM_SUBTITLE_STREAMS 16
|
||||||
#define NUM_VIDEO_PADS 16
|
#define NUM_VIDEO_STREAMS 16
|
||||||
#define NUM_AUDIO_PADS 32
|
#define NUM_AUDIO_STREAMS 32
|
||||||
|
|
||||||
/* stream output pads */
|
/* stream output */
|
||||||
GstPad *private_1_pad[NUM_PRIVATE_1_PADS]; /* up to 8 ac3 audio tracks */
|
GstMPEGStream *private_1_stream[NUM_PRIVATE_1_STREAMS]; /* up to 8 ac3 audio tracks */
|
||||||
GstPad *subtitle_pad[NUM_SUBTITLE_PADS];
|
GstMPEGStream *subtitle_stream[NUM_SUBTITLE_STREAMS];
|
||||||
GstPad *private_2_pad;
|
GstMPEGStream *private_2_stream;
|
||||||
GstPad *video_pad[NUM_VIDEO_PADS];
|
GstMPEGStream *video_stream[NUM_VIDEO_STREAMS];
|
||||||
GstPad *audio_pad[NUM_AUDIO_PADS];
|
GstMPEGStream *audio_stream[NUM_AUDIO_STREAMS];
|
||||||
|
|
||||||
|
GstCache *cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMPEGDemuxClass {
|
struct _GstMPEGDemuxClass {
|
||||||
|
|
|
@ -250,6 +250,8 @@ gst_mpeg_packetize_read (GstMPEGPacketize *packetize)
|
||||||
gst_bytestream_get_status (packetize->bs, &remaining, &event);
|
gst_bytestream_get_status (packetize->bs, &remaining, &event);
|
||||||
etype = event? GST_EVENT_TYPE (event) : GST_EVENT_EOS;
|
etype = event? GST_EVENT_TYPE (event) : GST_EVENT_EOS;
|
||||||
|
|
||||||
|
g_print ("remaining %d\n", remaining);
|
||||||
|
|
||||||
switch (etype) {
|
switch (etype) {
|
||||||
case GST_EVENT_DISCONTINUOUS:
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
GST_DEBUG (GST_CAT_EVENT, "packetize: discont\n");
|
GST_DEBUG (GST_CAT_EVENT, "packetize: discont\n");
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "gstmpegparse.h"
|
#include "gstmpegparse.h"
|
||||||
#include "gstmpegclock.h"
|
#include "gstmpegclock.h"
|
||||||
|
|
||||||
|
static GstFormat scr_format;
|
||||||
|
|
||||||
/* elementfactory information */
|
/* elementfactory information */
|
||||||
static GstElementDetails mpeg_parse_details = {
|
static GstElementDetails mpeg_parse_details = {
|
||||||
"MPEG System Parser",
|
"MPEG System Parser",
|
||||||
|
@ -36,6 +38,8 @@ static GstElementDetails mpeg_parse_details = {
|
||||||
|
|
||||||
#define CLASS(o) GST_MPEG_PARSE_CLASS (G_OBJECT_GET_CLASS (o))
|
#define CLASS(o) GST_MPEG_PARSE_CLASS (G_OBJECT_GET_CLASS (o))
|
||||||
|
|
||||||
|
#define DEFAULT_MAX_DISCONT 10000
|
||||||
|
|
||||||
/* GstMPEGParse signals and args */
|
/* GstMPEGParse signals and args */
|
||||||
enum {
|
enum {
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
|
@ -47,6 +51,7 @@ enum {
|
||||||
ARG_BIT_RATE,
|
ARG_BIT_RATE,
|
||||||
ARG_MPEG2,
|
ARG_MPEG2,
|
||||||
ARG_SYNC,
|
ARG_SYNC,
|
||||||
|
ARG_MAX_DISCONT,
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,6 +99,8 @@ static void gst_mpeg_parse_get_property (GObject *object, guint prop_id,
|
||||||
GValue *value, GParamSpec *pspec);
|
GValue *value, GParamSpec *pspec);
|
||||||
static void gst_mpeg_parse_set_property (GObject *object, guint prop_id,
|
static void gst_mpeg_parse_set_property (GObject *object, guint prop_id,
|
||||||
const GValue *value, GParamSpec *pspec);
|
const GValue *value, GParamSpec *pspec);
|
||||||
|
static void gst_mpeg_parse_set_cache (GstElement *element, GstCache *tc);
|
||||||
|
static GstCache* gst_mpeg_parse_get_cache (GstElement *element);
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
/*static guint gst_mpeg_parse_signals[LAST_SIGNAL] = { 0 };*/
|
/*static guint gst_mpeg_parse_signals[LAST_SIGNAL] = { 0 };*/
|
||||||
|
@ -139,11 +146,19 @@ gst_mpeg_parse_class_init (GstMPEGParseClass *klass)
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
|
||||||
g_param_spec_boolean ("sync", "Sync", "Synchronize on the stream SCR",
|
g_param_spec_boolean ("sync", "Sync", "Synchronize on the stream SCR",
|
||||||
FALSE, G_PARAM_READWRITE));
|
FALSE, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_DISCONT,
|
||||||
|
g_param_spec_int ("max_discont", "Max Discont", "The maximun allowed SCR discontinuity",
|
||||||
|
0, G_MAXINT, DEFAULT_MAX_DISCONT, G_PARAM_READWRITE));
|
||||||
|
|
||||||
gobject_class->get_property = gst_mpeg_parse_get_property;
|
gobject_class->get_property = gst_mpeg_parse_get_property;
|
||||||
gobject_class->set_property = gst_mpeg_parse_set_property;
|
gobject_class->set_property = gst_mpeg_parse_set_property;
|
||||||
|
|
||||||
gstelement_class->change_state = gst_mpeg_parse_change_state;
|
gstelement_class->change_state = gst_mpeg_parse_change_state;
|
||||||
|
gstelement_class->get_clock = gst_mpeg_parse_get_clock;
|
||||||
|
gstelement_class->set_clock = gst_mpeg_parse_set_clock;
|
||||||
|
gstelement_class->get_cache = gst_mpeg_parse_get_cache;
|
||||||
|
gstelement_class->set_cache = gst_mpeg_parse_set_cache;
|
||||||
|
|
||||||
|
|
||||||
klass->parse_packhead = gst_mpeg_parse_parse_packhead;
|
klass->parse_packhead = gst_mpeg_parse_parse_packhead;
|
||||||
klass->parse_syshead = NULL;
|
klass->parse_syshead = NULL;
|
||||||
|
@ -182,12 +197,10 @@ gst_mpeg_parse_init (GstMPEGParse *mpeg_parse)
|
||||||
mpeg_parse->mux_rate = 0;
|
mpeg_parse->mux_rate = 0;
|
||||||
mpeg_parse->discont_pending = FALSE;
|
mpeg_parse->discont_pending = FALSE;
|
||||||
mpeg_parse->scr_pending = TRUE;
|
mpeg_parse->scr_pending = TRUE;
|
||||||
|
mpeg_parse->max_discont = DEFAULT_MAX_DISCONT;
|
||||||
mpeg_parse->provided_clock = gst_mpeg_clock_new ("MPEGParseClock",
|
mpeg_parse->provided_clock = gst_mpeg_clock_new ("MPEGParseClock",
|
||||||
gst_mpeg_parse_get_time, mpeg_parse);
|
gst_mpeg_parse_get_time, mpeg_parse);
|
||||||
|
|
||||||
GST_ELEMENT (mpeg_parse)->getclockfunc = gst_mpeg_parse_get_clock;
|
|
||||||
GST_ELEMENT (mpeg_parse)->setclockfunc = gst_mpeg_parse_set_clock;
|
|
||||||
|
|
||||||
GST_FLAG_SET (mpeg_parse, GST_ELEMENT_EVENT_AWARE);
|
GST_FLAG_SET (mpeg_parse, GST_ELEMENT_EVENT_AWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +283,7 @@ static gboolean
|
||||||
gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
{
|
{
|
||||||
guint8 *buf;
|
guint8 *buf;
|
||||||
guint64 scr, scr_adj;
|
guint64 scr, scr_adj, scr_orig;
|
||||||
guint32 scr1, scr2;
|
guint32 scr1, scr2;
|
||||||
guint32 new_rate;
|
guint32 new_rate;
|
||||||
|
|
||||||
|
@ -299,8 +312,6 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
scr, scr_ext, scr1, scr2, mpeg_parse->bytes_since_scr,
|
scr, scr_ext, scr1, scr2, mpeg_parse->bytes_since_scr,
|
||||||
scr - mpeg_parse->current_scr);
|
scr - mpeg_parse->current_scr);
|
||||||
|
|
||||||
mpeg_parse->bytes_since_scr = 0;
|
|
||||||
|
|
||||||
buf += 6;
|
buf += 6;
|
||||||
new_rate = (GUINT32_FROM_BE ((*(guint32 *) buf)) & 0xfffffc00) >> 10;
|
new_rate = (GUINT32_FROM_BE ((*(guint32 *) buf)) & 0xfffffc00) >> 10;
|
||||||
}
|
}
|
||||||
|
@ -310,12 +321,12 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
scr |= (scr1 & 0x000000ff) << 7;
|
scr |= (scr1 & 0x000000ff) << 7;
|
||||||
scr |= (scr2 & 0xfe000000) >> 25;
|
scr |= (scr2 & 0xfe000000) >> 25;
|
||||||
|
|
||||||
mpeg_parse->bytes_since_scr = 0;
|
|
||||||
|
|
||||||
buf += 5;
|
buf += 5;
|
||||||
new_rate = (GUINT32_FROM_BE ((*(guint32 *) buf)) & 0x7ffffe00) >> 9;
|
new_rate = (GUINT32_FROM_BE ((*(guint32 *) buf)) & 0x7ffffe00) >> 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scr_orig = scr;
|
||||||
|
mpeg_parse->bytes_since_scr = 0;
|
||||||
scr_adj = scr + mpeg_parse->adjust;
|
scr_adj = scr + mpeg_parse->adjust;
|
||||||
|
|
||||||
GST_DEBUG (0, "SCR is %llu (%llu) next: %lld (%lld) diff: %lld (%lld)",
|
GST_DEBUG (0, "SCR is %llu (%llu) next: %lld (%lld) diff: %lld (%lld)",
|
||||||
|
@ -327,7 +338,7 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
MPEGTIME_TO_GSTTIME (scr) -
|
MPEGTIME_TO_GSTTIME (scr) -
|
||||||
MPEGTIME_TO_GSTTIME (mpeg_parse->next_scr));
|
MPEGTIME_TO_GSTTIME (mpeg_parse->next_scr));
|
||||||
|
|
||||||
if (ABS ((gint64)mpeg_parse->next_scr - (gint64)(scr_adj)) > 10000) {
|
if (ABS ((gint64)mpeg_parse->next_scr - (gint64)(scr_adj)) > mpeg_parse->max_discont) {
|
||||||
GST_DEBUG (0, "discontinuity detected; expected: %llu got: %llu real:%lld adjust:%lld",
|
GST_DEBUG (0, "discontinuity detected; expected: %llu got: %llu real:%lld adjust:%lld",
|
||||||
mpeg_parse->next_scr, scr_adj, scr, mpeg_parse->adjust);
|
mpeg_parse->next_scr, scr_adj, scr, mpeg_parse->adjust);
|
||||||
|
|
||||||
|
@ -340,8 +351,16 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
|
||||||
scr = scr_adj;
|
scr = scr_adj;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpeg_parse->current_scr = scr;
|
if (mpeg_parse->cache) {
|
||||||
|
/* update cache if any */
|
||||||
|
gst_cache_add_association (mpeg_parse->cache, mpeg_parse->cache_id,
|
||||||
|
GST_ACCOCIATION_FLAG_KEY_UNIT,
|
||||||
|
GST_FORMAT_BYTES, GST_BUFFER_OFFSET (buffer),
|
||||||
|
GST_FORMAT_TIME, MPEGTIME_TO_GSTTIME (scr),
|
||||||
|
scr_format, scr_orig, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpeg_parse->current_scr = scr;
|
||||||
mpeg_parse->scr_pending = FALSE;
|
mpeg_parse->scr_pending = FALSE;
|
||||||
|
|
||||||
if (mpeg_parse->mux_rate != new_rate) {
|
if (mpeg_parse->mux_rate != new_rate) {
|
||||||
|
@ -466,6 +485,7 @@ gst_mpeg_parse_loop (GstElement *element)
|
||||||
bss = mpeg_parse->bytes_since_scr;
|
bss = mpeg_parse->bytes_since_scr;
|
||||||
br = mpeg_parse->mux_rate * 50;
|
br = mpeg_parse->mux_rate * 50;
|
||||||
|
|
||||||
|
if (br) {
|
||||||
if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) {
|
if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) {
|
||||||
/*
|
/*
|
||||||
* The mpeg spec says something like this, but that doesn't really work:
|
* The mpeg spec says something like this, but that doesn't really work:
|
||||||
|
@ -478,6 +498,11 @@ gst_mpeg_parse_loop (GstElement *element)
|
||||||
/* we are interpolating the scr here */
|
/* we are interpolating the scr here */
|
||||||
mpeg_parse->next_scr = scr + (bss * 90000LL) / br;
|
mpeg_parse->next_scr = scr + (bss * 90000LL) / br;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* no bitrate known */
|
||||||
|
mpeg_parse->next_scr = scr;
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG (0, "size: %lld, total since SCR: %lld, next SCR: %lld",
|
GST_DEBUG (0, "size: %lld, total since SCR: %lld, next SCR: %lld",
|
||||||
size, bss, mpeg_parse->next_scr);
|
size, bss, mpeg_parse->next_scr);
|
||||||
|
@ -660,6 +685,9 @@ gst_mpeg_parse_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
||||||
case ARG_SYNC:
|
case ARG_SYNC:
|
||||||
g_value_set_boolean (value, mpeg_parse->sync);
|
g_value_set_boolean (value, mpeg_parse->sync);
|
||||||
break;
|
break;
|
||||||
|
case ARG_MAX_DISCONT:
|
||||||
|
g_value_set_int (value, mpeg_parse->max_discont);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -672,19 +700,44 @@ gst_mpeg_parse_set_property (GObject *object, guint prop_id,
|
||||||
{
|
{
|
||||||
GstMPEGParse *mpeg_parse;
|
GstMPEGParse *mpeg_parse;
|
||||||
|
|
||||||
/* it's not null if we got it, but it might not be ours */
|
mpeg_parse = GST_MPEG_PARSE (object);
|
||||||
mpeg_parse = GST_MPEG_PARSE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_SYNC:
|
case ARG_SYNC:
|
||||||
mpeg_parse->sync = g_value_get_boolean (value);
|
mpeg_parse->sync = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case ARG_MAX_DISCONT:
|
||||||
|
mpeg_parse->max_discont = g_value_get_int (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_mpeg_parse_set_cache (GstElement *element, GstCache *cache)
|
||||||
|
{
|
||||||
|
GstMPEGParse *mpeg_parse;
|
||||||
|
|
||||||
|
mpeg_parse = GST_MPEG_PARSE (element);
|
||||||
|
|
||||||
|
mpeg_parse->cache = cache;
|
||||||
|
|
||||||
|
gst_cache_get_writer_id (cache, GST_OBJECT (mpeg_parse->sinkpad),
|
||||||
|
&mpeg_parse->cache_id);
|
||||||
|
gst_cache_add_format (cache, mpeg_parse->cache_id, scr_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCache*
|
||||||
|
gst_mpeg_parse_get_cache (GstElement *element)
|
||||||
|
{
|
||||||
|
GstMPEGParse *mpeg_parse;
|
||||||
|
|
||||||
|
mpeg_parse = GST_MPEG_PARSE (element);
|
||||||
|
|
||||||
|
return mpeg_parse->cache;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_mpeg_parse_plugin_init (GModule *module, GstPlugin *plugin)
|
gst_mpeg_parse_plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
|
@ -700,6 +753,8 @@ gst_mpeg_parse_plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
&mpeg_parse_details);
|
&mpeg_parse_details);
|
||||||
g_return_val_if_fail(factory != NULL, FALSE);
|
g_return_val_if_fail(factory != NULL, FALSE);
|
||||||
|
|
||||||
|
scr_format = gst_format_register ("scr", "The MPEG system clock reference time");
|
||||||
|
|
||||||
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_factory));
|
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_factory));
|
||||||
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory));
|
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory));
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,10 @@
|
||||||
#ifndef __MPEG_PARSE_H__
|
#ifndef __MPEG_PARSE_H__
|
||||||
#define __MPEG_PARSE_H__
|
#define __MPEG_PARSE_H__
|
||||||
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/bytestream/bytestream.h>
|
#include <gst/bytestream/bytestream.h>
|
||||||
#include "gstmpegpacketize.h"
|
#include "gstmpegpacketize.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@ -68,10 +65,14 @@ struct _GstMPEGParse {
|
||||||
|
|
||||||
gboolean discont_pending;
|
gboolean discont_pending;
|
||||||
gboolean scr_pending;
|
gboolean scr_pending;
|
||||||
|
gint max_discont;
|
||||||
|
|
||||||
GstClock *provided_clock;
|
GstClock *provided_clock;
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
gboolean sync;
|
gboolean sync;
|
||||||
|
|
||||||
|
GstCache *cache;
|
||||||
|
gint cache_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMPEGParseClass {
|
struct _GstMPEGParseClass {
|
||||||
|
|
Loading…
Reference in a new issue