ext/mpeg2dec/gstmpeg2dec.c: Don't send things to NULL PAD_PEERs

Original commit message from CVS:
* ext/mpeg2dec/gstmpeg2dec.c:
Don't send things to NULL PAD_PEERs

* gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_chain):
Copy-on-write the incoming buffer.

* gst/mpegstream/gstdvddemux.h:
* gst/mpegstream/gstmpegclock.h:
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead),
(normal_seek), (gst_mpeg_demux_handle_src_event):
* gst/mpegstream/gstmpegdemux.h:
* gst/mpegstream/gstmpegpacketize.h:
* gst/mpegstream/gstmpegparse.c:
(gst_mpeg_parse_update_streaminfo), (gst_mpeg_parse_reset),
(gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead),
(gst_mpeg_parse_loop), (gst_mpeg_parse_get_rate),
(gst_mpeg_parse_convert_src), (gst_mpeg_parse_handle_src_query),
(gst_mpeg_parse_handle_src_event), (gst_mpeg_parse_change_state):
* gst/mpegstream/gstmpegparse.h:
* gst/mpegstream/gstrfc2250enc.h:
Various changes to the way time is computed that make seeking and
total time estimation much better here.
Use G_BEGIN/END_DECLS instead of __cplusplus

* gst/videocrop/gstvideocrop.c: (gst_video_crop_chain):
Use gst_buffer_stamp instead of only copying the TIMESTAMP
This commit is contained in:
Jan Schmidt 2005-02-01 16:40:10 +00:00
parent 501290be01
commit 3ef22c4774
10 changed files with 322 additions and 167 deletions

View file

@ -1,3 +1,32 @@
2005-02-02 Jan Schmidt <thaytan@mad.scientist.com>
* ext/mpeg2dec/gstmpeg2dec.c:
Don't send things to NULL PAD_PEERs
* gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_chain):
Copy-on-write the incoming buffer.
* gst/mpegstream/gstdvddemux.h:
* gst/mpegstream/gstmpegclock.h:
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead),
(normal_seek), (gst_mpeg_demux_handle_src_event):
* gst/mpegstream/gstmpegdemux.h:
* gst/mpegstream/gstmpegpacketize.h:
* gst/mpegstream/gstmpegparse.c:
(gst_mpeg_parse_update_streaminfo), (gst_mpeg_parse_reset),
(gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead),
(gst_mpeg_parse_loop), (gst_mpeg_parse_get_rate),
(gst_mpeg_parse_convert_src), (gst_mpeg_parse_handle_src_query),
(gst_mpeg_parse_handle_src_event), (gst_mpeg_parse_change_state):
* gst/mpegstream/gstmpegparse.h:
* gst/mpegstream/gstrfc2250enc.h:
Various changes to the way time is computed that make seeking and
total time estimation much better here.
Use G_BEGIN/END_DECLS instead of __cplusplus
* gst/videocrop/gstvideocrop.c: (gst_video_crop_chain):
Use gst_buffer_stamp instead of only copying the TIMESTAMP
2005-02-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net> 2005-02-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/subparse/gstsubparse.c: * gst/subparse/gstsubparse.c:

View file

@ -1062,7 +1062,7 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQueryType type,
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstMpeg2dec *mpeg2dec; GstMpeg2dec *mpeg2dec;
static const GstFormat *formats; static const GstFormat *formats = NULL;
mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad)); mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
@ -1077,10 +1077,11 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQueryType type,
res = FALSE; res = FALSE;
/* get our peer formats */ /* get our peer formats */
formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad)); if (GST_PAD_PEER (mpeg2dec->sinkpad))
formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
/* while we did not exhaust our seek formats without result */ /* while we did not exhaust our seek formats without result */
while (formats && *formats) { while (formats && *formats && !res) {
GstFormat peer_format; GstFormat peer_format;
gint64 peer_value; gint64 peer_value;
@ -1152,7 +1153,7 @@ index_seek (GstPad * pad, GstEvent * event)
GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT, GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
GST_EVENT_SEEK_FORMAT (event), GST_EVENT_SEEK_OFFSET (event)); GST_EVENT_SEEK_FORMAT (event), GST_EVENT_SEEK_OFFSET (event));
if (entry) { if ((entry) && GST_PAD_PEER (mpeg2dec->sinkpad)) {
const GstFormat *peer_formats, *try_formats; const GstFormat *peer_formats, *try_formats;
/* since we know the exact byteoffset of the frame, make sure to seek on bytes first */ /* since we know the exact byteoffset of the frame, make sure to seek on bytes first */
@ -1202,7 +1203,7 @@ normal_seek (GstPad * pad, GstEvent * event)
gint64 src_offset; gint64 src_offset;
gboolean flush; gboolean flush;
GstFormat format; GstFormat format;
const GstFormat *peer_formats; const GstFormat *peer_formats = NULL;
gboolean res = FALSE; gboolean res = FALSE;
GstMpeg2dec *mpeg2dec; GstMpeg2dec *mpeg2dec;
@ -1222,7 +1223,8 @@ normal_seek (GstPad * pad, GstEvent * event)
flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH; flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
/* get our peer formats */ /* get our peer formats */
peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad)); if (GST_PAD_PEER (mpeg2dec->sinkpad))
peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
/* while we did not exhaust our seek formats without result */ /* while we did not exhaust our seek formats without result */
while (peer_formats && *peer_formats) { while (peer_formats && *peer_formats) {
@ -1288,7 +1290,11 @@ gst_mpeg2dec_src_event (GstPad * pad, GstEvent * event)
break; break;
case GST_EVENT_NAVIGATION: case GST_EVENT_NAVIGATION:
/* Forward a navigation event unchanged */ /* Forward a navigation event unchanged */
return gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), event); if (GST_PAD_PEER (mpeg2dec->sinkpad))
return gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), event);
res = FALSE;
break;
default: default:
res = FALSE; res = FALSE;
break; break;

View file

@ -25,11 +25,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstmpegdemux.h" #include "gstmpegdemux.h"
G_BEGIN_DECLS
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_DVD_DEMUX \ #define GST_TYPE_DVD_DEMUX \
(gst_dvd_demux_get_type()) (gst_dvd_demux_get_type())
@ -139,10 +135,6 @@ GType gst_dvd_demux_get_type (void);
gboolean gst_dvd_demux_plugin_init (GstPlugin *plugin); gboolean gst_dvd_demux_plugin_init (GstPlugin *plugin);
G_END_DECLS
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __DVD_DEMUX_H__ */ #endif /* __DVD_DEMUX_H__ */

View file

@ -26,10 +26,7 @@
#include <gst/gstsystemclock.h> #include <gst/gstsystemclock.h>
#ifdef __cplusplus G_BEGIN_DECLS
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_MPEG_CLOCK \ #define GST_TYPE_MPEG_CLOCK \
(gst_mpeg_clock_get_type()) (gst_mpeg_clock_get_type())
@ -63,9 +60,6 @@ GType gst_mpeg_clock_get_type (void);
GstClock* gst_mpeg_clock_new (gchar *name, GstMPEGClockGetTimeFunc func, GstClock* gst_mpeg_clock_new (gchar *name, GstMPEGClockGetTimeFunc func,
gpointer user_data); gpointer user_data);
#ifdef __cplusplus G_END_DECLS
}
#endif /* __cplusplus */
#endif /* __GST_MPEG_CLOCK_H__ */ #endif /* __GST_MPEG_CLOCK_H__ */

View file

@ -551,6 +551,9 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
gint stream_count = (header_length - 6) / 3; gint stream_count = (header_length - 6) / 3;
gint i, j = 0; gint i, j = 0;
/* Reset the total_size_bound before counting it up */
mpeg_demux->total_size_bound = 0;
GST_DEBUG_OBJECT (mpeg_demux, "number of streams: %d ", stream_count); GST_DEBUG_OBJECT (mpeg_demux, "number of streams: %d ", stream_count);
for (i = 0; i < stream_count; i++) { for (i = 0; i < stream_count; i++) {
@ -618,19 +621,6 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
outstream->index_id = outstream->index_id =
_demux_get_writer_id (mpeg_demux->index, outstream->pad); _demux_get_writer_id (mpeg_demux->index, outstream->pad);
} }
if (GST_PAD_IS_USABLE (outstream->pad)) {
GstEvent *event;
GstClockTime time;
time = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr
+ mpeg_parse->adjust) + mpeg_demux->adjust;
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
time, NULL);
gst_pad_push (outstream->pad, GST_DATA (event));
}
} }
j++; j++;
@ -1024,7 +1014,7 @@ normal_seek (GstPad * pad, GstEvent * event, gint64 * offset)
if (res) { if (res) {
*offset = MAX (GST_EVENT_SEEK_OFFSET (event) - adjust, 0); *offset = MAX (GST_EVENT_SEEK_OFFSET (event) - adjust, 0);
GST_CAT_DEBUG (GST_CAT_SEEK, "%s:%s guestimate %" G_GINT64_FORMAT GST_CAT_DEBUG (GST_CAT_SEEK, "%s:%s guesstimate %" G_GINT64_FORMAT
" %s -> %" G_GINT64_FORMAT " %s -> %" G_GINT64_FORMAT
" (total_size_bound = %" G_GINT64_FORMAT ")", " (total_size_bound = %" G_GINT64_FORMAT ")",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (pad),
@ -1063,9 +1053,12 @@ gst_mpeg_demux_handle_src_event (GstPad * pad, GstEvent * event)
break; break;
} }
case GST_EVENT_NAVIGATION: case GST_EVENT_NAVIGATION:
return gst_pad_send_event (GST_PAD_PEER (GST_MPEG_PARSE (mpeg_demux)-> {
sinkpad), event); GstPad *out = GST_PAD_PEER (GST_MPEG_PARSE (mpeg_demux)->sinkpad);
break;
if (out && GST_PAD_IS_USABLE (out))
return gst_pad_send_event (out, event);
}
default: default:
gst_event_unref (event); gst_event_unref (event);
break; break;

View file

@ -25,11 +25,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstmpegparse.h" #include "gstmpegparse.h"
G_BEGIN_DECLS
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_MPEG_DEMUX \ #define GST_TYPE_MPEG_DEMUX \
(gst_mpeg_demux_get_type()) (gst_mpeg_demux_get_type())
@ -188,9 +184,6 @@ GType gst_mpeg_demux_get_type (void);
gboolean gst_mpeg_demux_plugin_init (GstPlugin *plugin); gboolean gst_mpeg_demux_plugin_init (GstPlugin *plugin);
#ifdef __cplusplus G_END_DECLS
}
#endif /* __cplusplus */
#endif /* __MPEG_DEMUX_H__ */ #endif /* __MPEG_DEMUX_H__ */

View file

@ -25,10 +25,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/bytestream/bytestream.h> #include <gst/bytestream/bytestream.h>
G_BEGIN_DECLS
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define PICTURE_START_CODE 0x00 #define PICTURE_START_CODE 0x00
#define SLICE_MIN_START_CODE 0x01 #define SLICE_MIN_START_CODE 0x01
@ -71,9 +68,6 @@ void gst_mpeg_packetize_destroy (GstMPEGPacketize *packetize);
GstData* gst_mpeg_packetize_read (GstMPEGPacketize *packetize); GstData* gst_mpeg_packetize_read (GstMPEGPacketize *packetize);
#ifdef __cplusplus G_END_DECLS
}
#endif /* __cplusplus */
#endif /* __MPEGPACKETIZE_H__ */ #endif /* __MPEGPACKETIZE_H__ */

View file

@ -27,12 +27,20 @@
static GstFormat scr_format; static GstFormat scr_format;
GST_DEBUG_CATEGORY_STATIC (gstmpegparse_debug); GST_DEBUG_CATEGORY_STATIC (gstmpegparse_debug);
#define GST_CAT_DEFAULT (gstmpegparse_debug) #define GST_CAT_DEFAULT (gstmpegparse_debug)
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_SEEK); GST_DEBUG_CATEGORY_EXTERN (GST_CAT_SEEK);
#define MP_INVALID_SCR ((guint64)(-1))
#define MP_MUX_RATE_MULT 50
#define MP_MIN_VALID_BSS 8192
#define MP_MAX_VALID_BSS 16384
/*
* Hysteresis value to limit the
* total predicted time skipping about
*/
#define MP_SCR_RATE_HYST 0.08
/* elementfactory information */ /* elementfactory information */
static GstElementDetails mpeg_parse_details = { static GstElementDetails mpeg_parse_details = {
@ -266,7 +274,7 @@ gst_mpeg_parse_update_streaminfo (GstMPEGParse * mpeg_parse)
gst_props_add_entry (props, (GstPropsEntry *) entry); gst_props_add_entry (props, (GstPropsEntry *) entry);
entry = entry =
gst_props_entry_new ("bitrate", G_TYPE_INT (mpeg_parse->mux_rate * 400)); gst_props_entry_new ("bitrate", G_TYPE_INT (mpeg_parse->mux_rate * 8));
gst_props_add_entry (props, (GstPropsEntry *) entry); gst_props_add_entry (props, (GstPropsEntry *) entry);
caps = gst_caps_new ("mpeg_streaminfo", caps = gst_caps_new ("mpeg_streaminfo",
@ -277,6 +285,27 @@ gst_mpeg_parse_update_streaminfo (GstMPEGParse * mpeg_parse)
} }
#endif #endif
static void
gst_mpeg_parse_reset (GstMPEGParse * mpeg_parse)
{
mpeg_parse->current_scr = 0;
mpeg_parse->bytes_since_scr = 0;
mpeg_parse->avg_bitrate_time = 0;
mpeg_parse->avg_bitrate_bytes = 0;
mpeg_parse->first_scr = MP_INVALID_SCR;
mpeg_parse->first_scr_pos = 0;
mpeg_parse->last_scr = MP_INVALID_SCR;
mpeg_parse->last_scr_pos = 0;
mpeg_parse->scr_rate = 0;
mpeg_parse->adjust = 0;
mpeg_parse->next_scr = 0;
mpeg_parse->mux_rate = 0;
mpeg_parse->discont_pending = FALSE;
mpeg_parse->scr_pending = FALSE;
}
static void static void
gst_mpeg_parse_handle_discont (GstMPEGParse * mpeg_parse, GstEvent * event) gst_mpeg_parse_handle_discont (GstMPEGParse * mpeg_parse, GstEvent * event)
{ {
@ -284,6 +313,10 @@ gst_mpeg_parse_handle_discont (GstMPEGParse * mpeg_parse, GstEvent * event)
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS); g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS);
if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
gst_mpeg_parse_reset (mpeg_parse);
}
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time) if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)
&& (GST_CLOCK_TIME_IS_VALID (time))) { && (GST_CLOCK_TIME_IS_VALID (time))) {
GST_DEBUG_OBJECT (mpeg_parse, "forwarding discontinuity, time: %0.3fs", GST_DEBUG_OBJECT (mpeg_parse, "forwarding discontinuity, time: %0.3fs",
@ -423,15 +456,28 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
new_rate |= ((gint32) buf[1]) << 7; new_rate |= ((gint32) buf[1]) << 7;
new_rate |= buf[2] >> 1; new_rate |= buf[2] >> 1;
} }
new_rate *= MP_MUX_RATE_MULT;
prev_scr = mpeg_parse->current_scr; prev_scr = mpeg_parse->current_scr;
mpeg_parse->current_scr = scr; mpeg_parse->current_scr = scr;
mpeg_parse->scr_pending = FALSE; mpeg_parse->scr_pending = FALSE;
if (mpeg_parse->next_scr == -1) { if (mpeg_parse->next_scr == MP_INVALID_SCR) {
mpeg_parse->next_scr = mpeg_parse->current_scr; mpeg_parse->next_scr = mpeg_parse->current_scr;
} }
if ((mpeg_parse->first_scr == MP_INVALID_SCR) ||
(mpeg_parse->current_scr < mpeg_parse->first_scr)) {
mpeg_parse->first_scr = mpeg_parse->current_scr;
mpeg_parse->first_scr_pos = gst_bytestream_tell (mpeg_parse->packetize->bs);
}
if ((mpeg_parse->last_scr == MP_INVALID_SCR) ||
(mpeg_parse->current_scr > mpeg_parse->last_scr)) {
mpeg_parse->last_scr = mpeg_parse->current_scr;
mpeg_parse->last_scr_pos = gst_bytestream_tell (mpeg_parse->packetize->bs);
}
GST_LOG_OBJECT (mpeg_parse, GST_LOG_OBJECT (mpeg_parse,
"SCR is %" G_GUINT64_FORMAT "SCR is %" G_GUINT64_FORMAT
" (%" G_GUINT64_FORMAT ") next: %" " (%" G_GUINT64_FORMAT ") next: %"
@ -449,9 +495,9 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
if (ABS ((gint64) mpeg_parse->next_scr - (gint64) (scr)) > if (ABS ((gint64) mpeg_parse->next_scr - (gint64) (scr)) >
mpeg_parse->max_discont) { mpeg_parse->max_discont) {
GST_DEBUG ("discontinuity detected; expected: %" G_GUINT64_FORMAT " got: %" GST_DEBUG ("discontinuity detected; expected: %" G_GUINT64_FORMAT " got: %"
G_GUINT64_FORMAT " real:%" G_GINT64_FORMAT " adjust:%" G_GINT64_FORMAT, G_GUINT64_FORMAT " adjusted:%" G_GINT64_FORMAT " adjust:%"
mpeg_parse->next_scr, mpeg_parse->current_scr + mpeg_parse->adjust, G_GINT64_FORMAT, mpeg_parse->next_scr, mpeg_parse->current_scr,
mpeg_parse->current_scr, mpeg_parse->adjust); mpeg_parse->current_scr + mpeg_parse->adjust, mpeg_parse->adjust);
if (mpeg_parse->do_adjust) { if (mpeg_parse->do_adjust) {
if (mpeg_parse->use_adjust) { if (mpeg_parse->use_adjust) {
@ -472,23 +518,39 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
GST_FORMAT_TIME, MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr), 0); GST_FORMAT_TIME, MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr), 0);
} }
if (mpeg_parse->current_scr > prev_scr) {
mpeg_parse->avg_bitrate_time +=
MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr - prev_scr);
mpeg_parse->avg_bitrate_bytes += mpeg_parse->bytes_since_scr;
}
if (mpeg_parse->mux_rate != new_rate) { if (mpeg_parse->mux_rate != new_rate) {
if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) { if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) {
mpeg_parse->mux_rate = new_rate; mpeg_parse->mux_rate = new_rate;
} else { } else if (mpeg_parse->avg_bitrate_bytes > MP_MIN_VALID_BSS) {
mpeg_parse->mux_rate = mpeg_parse->mux_rate =
(double) mpeg_parse->bytes_since_scr / GST_SECOND * mpeg_parse->avg_bitrate_bytes /
MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr - mpeg_parse->avg_bitrate_time;
prev_scr) / 50 * 1000000000;
} }
//gst_mpeg_parse_update_streaminfo (mpeg_parse); //gst_mpeg_parse_update_streaminfo (mpeg_parse);
GST_DEBUG ("stream is %1.3fMbs, calculated over %1.3fkB", GST_DEBUG ("stream current is %1.3fMbs, calculated over %1.3fkB",
(mpeg_parse->mux_rate * 400) / 1000000.0, (mpeg_parse->mux_rate * 8) / 1048576.0,
mpeg_parse->bytes_since_scr / 1000.0); mpeg_parse->bytes_since_scr / 1024.0);
}
if (mpeg_parse->avg_bitrate_bytes > MP_MAX_VALID_BSS) {
mpeg_parse->avg_bitrate_bytes = 0;
mpeg_parse->avg_bitrate_time = 0;
} }
mpeg_parse->bytes_since_scr = 0; mpeg_parse->bytes_since_scr = 0;
if (mpeg_parse->avg_bitrate_bytes) {
GST_DEBUG ("stream avg is %1.3fMbs, calculated over %1.3fkB",
(float) (mpeg_parse->avg_bitrate_bytes) * 8 * GST_SECOND
/ mpeg_parse->avg_bitrate_time / 1048576.0,
mpeg_parse->avg_bitrate_bytes / 1024.0);
}
return TRUE; return TRUE;
} }
@ -607,12 +669,12 @@ gst_mpeg_parse_loop (GstElement * element)
gst_element_wait (GST_ELEMENT (mpeg_parse), time); gst_element_wait (GST_ELEMENT (mpeg_parse), time);
} }
if (mpeg_parse->current_scr != -1) { if (mpeg_parse->current_scr != MP_INVALID_SCR) {
guint64 scr, bss, br; guint64 scr, bss, br;
scr = mpeg_parse->current_scr; scr = mpeg_parse->current_scr;
bss = mpeg_parse->bytes_since_scr; bss = mpeg_parse->bytes_since_scr;
br = mpeg_parse->mux_rate * 50; br = mpeg_parse->mux_rate;
if (br) { if (br) {
if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) { if (GST_MPEG_PACKETIZE_IS_MPEG2 (mpeg_parse->packetize)) {
@ -621,6 +683,7 @@ gst_mpeg_parse_loop (GstElement * element)
* *
* mpeg_parse->next_scr = (scr * br + bss * CLOCK_FREQ) / (CLOCK_FREQ + br); * mpeg_parse->next_scr = (scr * br + bss * CLOCK_FREQ) / (CLOCK_FREQ + br);
*/ */
mpeg_parse->next_scr = scr + (bss * CLOCK_FREQ) / br; mpeg_parse->next_scr = scr + (bss * CLOCK_FREQ) / br;
} else { } else {
/* we are interpolating the scr here */ /* we are interpolating the scr here */
@ -632,8 +695,8 @@ gst_mpeg_parse_loop (GstElement * element)
} }
GST_LOG_OBJECT (mpeg_parse, "size: %" G_GINT64_FORMAT GST_LOG_OBJECT (mpeg_parse, "size: %" G_GINT64_FORMAT
", total since SCR: %" G_GINT64_FORMAT ", total since SCR: %" G_GINT64_FORMAT ", br: %" G_GINT64_FORMAT
", next SCR: %" G_GINT64_FORMAT, size, bss, mpeg_parse->next_scr); ", next SCR: %" G_GINT64_FORMAT, size, bss, br, mpeg_parse->next_scr);
} }
} }
} }
@ -650,12 +713,81 @@ gst_mpeg_parse_get_src_formats (GstPad * pad)
return formats; return formats;
} }
/*
* Return the bitrate to the nearest byte/sec
*/
static gboolean
gst_mpeg_parse_get_rate (GstMPEGParse * mpeg_parse, gint64 * rate)
{
GstFormat time_format = GST_FORMAT_TIME;
GstFormat bytes_format = GST_FORMAT_BYTES;
gint64 total_time = 0;
gint64 total_bytes = 0;
/* If upstream knows the total time and the total bytes,
* use those to compute an average byterate
*/
if (gst_pad_query (GST_PAD_PEER (mpeg_parse->sinkpad),
GST_QUERY_TOTAL, &time_format, &total_time)
&&
gst_pad_query (GST_PAD_PEER (mpeg_parse->sinkpad),
GST_QUERY_TOTAL, &bytes_format, &total_bytes)
&& total_time != 0) {
*rate = GST_SECOND * total_bytes / total_time;
return TRUE;
}
if ((mpeg_parse->first_scr != MP_INVALID_SCR) &&
(mpeg_parse->last_scr != MP_INVALID_SCR) &&
(mpeg_parse->last_scr_pos - mpeg_parse->first_scr_pos > MP_MIN_VALID_BSS)
&& (mpeg_parse->last_scr != mpeg_parse->first_scr)) {
*rate =
GST_SECOND * (mpeg_parse->last_scr_pos -
mpeg_parse->first_scr_pos) / MPEGTIME_TO_GSTTIME (mpeg_parse->last_scr -
mpeg_parse->first_scr);
if (*rate != 0) {
/*
* check if we need to update scr_rate
*/
if ((mpeg_parse->scr_rate == 0) ||
(((double) (ABS (mpeg_parse->scr_rate -
*rate)) / mpeg_parse->scr_rate)
>= MP_SCR_RATE_HYST)) {
mpeg_parse->scr_rate = *rate;
return TRUE;
}
}
if (mpeg_parse->scr_rate != 0) {
*rate = mpeg_parse->scr_rate;
return TRUE;
}
}
if (mpeg_parse->avg_bitrate_time != 0 && mpeg_parse->avg_bitrate_bytes != 0) {
*rate =
GST_SECOND * mpeg_parse->avg_bitrate_bytes /
mpeg_parse->avg_bitrate_time;
if (*rate != 0) {
return TRUE;
}
}
if (mpeg_parse->mux_rate != 0) {
*rate = mpeg_parse->mux_rate;
return TRUE;
}
return FALSE;
}
gboolean gboolean
gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format, gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value) gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (gst_pad_get_parent (pad)); GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (gst_pad_get_parent (pad));
gint64 rate;
switch (src_format) { switch (src_format) {
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
@ -663,10 +795,11 @@ gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format,
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
*dest_format = GST_FORMAT_TIME; *dest_format = GST_FORMAT_TIME;
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
if (mpeg_parse->mux_rate == 0) if (!gst_mpeg_parse_get_rate (mpeg_parse, &rate))
res = FALSE; res = FALSE;
else else {
*dest_value = src_value * GST_SECOND / (mpeg_parse->mux_rate * 50); *dest_value = GST_SECOND * src_value / rate;
}
break; break;
default: default:
res = FALSE; res = FALSE;
@ -677,7 +810,11 @@ gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format,
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
*dest_format = GST_FORMAT_BYTES; *dest_format = GST_FORMAT_BYTES;
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
*dest_value = mpeg_parse->mux_rate * 50 * src_value / GST_SECOND; if (!gst_mpeg_parse_get_rate (mpeg_parse, &rate))
res = FALSE;
else {
*dest_value = src_value * rate / GST_SECOND;
}
break; break;
default: default:
res = FALSE; res = FALSE;
@ -687,6 +824,7 @@ gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format,
res = FALSE; res = FALSE;
break; break;
} }
return res; return res;
} }
@ -708,8 +846,8 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQueryType type,
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (gst_pad_get_parent (pad)); GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (gst_pad_get_parent (pad));
GstFormat src_format; GstFormat src_format = GST_FORMAT_UNDEFINED;
gint64 src_value; gint64 src_value = 0;
switch (type) { switch (type) {
case GST_QUERY_TOTAL: case GST_QUERY_TOTAL:
@ -718,6 +856,18 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQueryType type,
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
*format = GST_FORMAT_TIME; *format = GST_FORMAT_TIME;
/* fallthrough */ /* fallthrough */
case GST_FORMAT_TIME:
/*
* Try asking upstream if it knows the time - a DVD might know
*/
src_format = GST_FORMAT_TIME;
if (gst_pad_query (GST_PAD_PEER (mpeg_parse->sinkpad),
GST_QUERY_TOTAL, &src_format, &src_value)) {
res = TRUE;
break;
}
/* Otherwise fallthrough */
default: default:
src_format = GST_FORMAT_BYTES; src_format = GST_FORMAT_BYTES;
if (!gst_pad_query (GST_PAD_PEER (mpeg_parse->sinkpad), if (!gst_pad_query (GST_PAD_PEER (mpeg_parse->sinkpad),
@ -736,7 +886,14 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQueryType type,
/* fallthrough */ /* fallthrough */
default: default:
src_format = GST_FORMAT_TIME; src_format = GST_FORMAT_TIME;
src_value = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr); if ((mpeg_parse->current_scr == MP_INVALID_SCR) ||
(mpeg_parse->first_scr == MP_INVALID_SCR))
res = FALSE;
else {
gint64 cur =
(gint64) (mpeg_parse->current_scr) - mpeg_parse->first_scr;
src_value = MPEGTIME_TO_GSTTIME (MAX (0, cur));
}
break; break;
} }
break; break;
@ -838,13 +995,16 @@ gst_mpeg_parse_handle_src_event (GstPad * pad, GstEvent * event)
if (!res) if (!res)
break; break;
GST_DEBUG ("sending seek to %" G_GINT64_FORMAT, desired_offset); GST_DEBUG ("sending seek to %" G_GINT64_FORMAT " expected SCR: %"
G_GUINT64_FORMAT " (%" G_GUINT64_FORMAT ")", desired_offset,
expected_scr, MPEGTIME_TO_GSTTIME (expected_scr));
if (gst_bytestream_seek (mpeg_parse->packetize->bs, desired_offset, if (gst_bytestream_seek (mpeg_parse->packetize->bs, desired_offset,
GST_SEEK_METHOD_SET)) { GST_SEEK_METHOD_SET)) {
mpeg_parse->discont_pending = TRUE; mpeg_parse->discont_pending = TRUE;
mpeg_parse->scr_pending = TRUE; mpeg_parse->scr_pending = TRUE;
mpeg_parse->next_scr = expected_scr; mpeg_parse->next_scr = expected_scr;
mpeg_parse->current_scr = -1; mpeg_parse->current_scr = MP_INVALID_SCR;
mpeg_parse->adjust = 0; mpeg_parse->adjust = 0;
res = TRUE; res = TRUE;
} }
@ -870,15 +1030,7 @@ gst_mpeg_parse_change_state (GstElement * element)
GST_MPEG_PACKETIZE_SYSTEM); GST_MPEG_PACKETIZE_SYSTEM);
} }
/* initialize parser state */ /* initialize parser state */
mpeg_parse->current_scr = 0; gst_mpeg_parse_reset (mpeg_parse);
mpeg_parse->bytes_since_scr = 0;
mpeg_parse->adjust = 0;
mpeg_parse->next_scr = 0;
/* zero counters (should be done at RUNNING?) */
mpeg_parse->mux_rate = 0;
mpeg_parse->discont_pending = FALSE;
mpeg_parse->scr_pending = FALSE;
break; break;
case GST_STATE_PAUSED_TO_READY: case GST_STATE_PAUSED_TO_READY:
if (mpeg_parse->packetize) { if (mpeg_parse->packetize) {

View file

@ -25,10 +25,7 @@
#include <gst/bytestream/bytestream.h> #include <gst/bytestream/bytestream.h>
#include "gstmpegpacketize.h" #include "gstmpegpacketize.h"
#ifdef __cplusplus G_BEGIN_DECLS
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_MPEG_PARSE \ #define GST_TYPE_MPEG_PARSE \
(gst_mpeg_parse_get_type()) (gst_mpeg_parse_get_type())
@ -49,80 +46,93 @@ extern "C" {
#define MPEGTIME_TO_GSTTIME(time) (((time) * (GST_MSECOND/10)) / CLOCK_BASE) #define MPEGTIME_TO_GSTTIME(time) (((time) * (GST_MSECOND/10)) / CLOCK_BASE)
#define GSTTIME_TO_MPEGTIME(time) (((time) * CLOCK_BASE) / (GST_MSECOND/10)) #define GSTTIME_TO_MPEGTIME(time) (((time) * CLOCK_BASE) / (GST_MSECOND/10))
typedef struct _GstMPEGParse GstMPEGParse; typedef struct _GstMPEGParse GstMPEGParse;
typedef struct _GstMPEGParseClass GstMPEGParseClass; typedef struct _GstMPEGParseClass GstMPEGParseClass;
struct _GstMPEGParse { struct _GstMPEGParse
GstElement element; {
GstElement element;
GstPad *sinkpad, *srcpad; GstPad *sinkpad, *srcpad;
GstMPEGPacketize *packetize; GstMPEGPacketize *packetize;
/* pack header values */ /*
guint32 mux_rate; * Keep track of total rate using SCR
guint64 current_scr; /* Current SCR from the stream. */ * and use hysteresis.
guint64 next_scr; /* Expected next SCR. */ */
guint64 bytes_since_scr; guint64 first_scr; /* Earliest SCR value for reference */
guint64 first_scr_pos; /* Byte position of reference SCR */
guint64 last_scr; /* Latest SCR value for reference */
guint64 last_scr_pos; /* Byte position of reference SCR */
guint64 scr_rate; /* Remember the last rate for hysteresis */
gboolean do_adjust; /* If false, send discont events on SCR /*
* jumps * Compute a rolling average for SCR interpolation (for MPEG1)
*/ */
gboolean use_adjust; /* Collect SCR jumps into 'adjust' in guint64 avg_bitrate_time; /* Time total for local average bitrate */
* order to adjust timestamps to smooth guint64 avg_bitrate_bytes; /* bytes total for local average bitrate */
* discontinuities. */
gint64 adjust; /* Current timestamp adjust value. */
gboolean discont_pending; /* pack header values */
gboolean scr_pending; guint32 mux_rate; /* mux rate in bytes/sec derived from Pack
gint max_discont; * header */
guint64 current_scr; /* Current SCR from the stream. */
guint64 next_scr; /* Expected next SCR. */
guint64 bytes_since_scr; /* Bytes since current_scr */
GstClock *clock; gboolean do_adjust; /* If false, send discont events on SCR
gboolean sync; * jumps
GstClockID id; */
gboolean use_adjust; /* Collect SCR jumps into 'adjust' in
* order to adjust timestamps to smooth
* discontinuities. */
gint64 adjust; /* Current timestamp adjust value. */
GstIndex *index; gboolean discont_pending;
gint index_id; gboolean scr_pending;
}; gint max_discont;
struct _GstMPEGParseClass { GstClock *clock;
GstElementClass parent_class; gboolean sync;
GstClockID id;
/* process packet types */ GstIndex *index;
gboolean (*parse_packhead) (GstMPEGParse *parse, GstBuffer *buffer); gint index_id;
gboolean (*parse_syshead) (GstMPEGParse *parse, GstBuffer *buffer); };
gboolean (*parse_packet) (GstMPEGParse *parse, GstBuffer *buffer);
gboolean (*parse_pes) (GstMPEGParse *parse, GstBuffer *buffer);
/* process events */ struct _GstMPEGParseClass
void (*handle_discont) (GstMPEGParse *parse, GstEvent *event); {
GstElementClass parent_class;
/* optional method to send out the data */ /* process packet types */
void (*send_data) (GstMPEGParse *parse, GstData *data, GstClockTime time); gboolean (*parse_packhead) (GstMPEGParse * parse, GstBuffer * buffer);
void (*send_discont) (GstMPEGParse *parse, GstClockTime time); gboolean (*parse_syshead) (GstMPEGParse * parse, GstBuffer * buffer);
}; gboolean (*parse_packet) (GstMPEGParse * parse, GstBuffer * buffer);
gboolean (*parse_pes) (GstMPEGParse * parse, GstBuffer * buffer);
GType gst_mpeg_parse_get_type(void); /* process events */
void (*handle_discont) (GstMPEGParse * parse, GstEvent * event);
gboolean gst_mpeg_parse_plugin_init (GstPlugin *plugin); /* optional method to send out the data */
void (*send_data) (GstMPEGParse * parse, GstData * data, GstClockTime time);
void (*send_discont) (GstMPEGParse * parse, GstClockTime time);
};
const GstFormat* GType gst_mpeg_parse_get_type (void);
gst_mpeg_parse_get_src_formats (GstPad *pad);
gboolean gst_mpeg_parse_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
GstFormat *dest_format, gint64 *dest_value);
const GstEventMask*
gst_mpeg_parse_get_src_event_masks (GstPad *pad);
gboolean gst_mpeg_parse_handle_src_event (GstPad *pad, GstEvent *event);
const GstQueryType* gboolean gst_mpeg_parse_plugin_init (GstPlugin * plugin);
gst_mpeg_parse_get_src_query_types (GstPad *pad);
gboolean gst_mpeg_parse_handle_src_query (GstPad *pad, GstQueryType type,
GstFormat *format, gint64 *value);
#ifdef __cplusplus const GstFormat *gst_mpeg_parse_get_src_formats (GstPad * pad);
}
#endif /* __cplusplus */
gboolean gst_mpeg_parse_convert_src (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
const GstEventMask *gst_mpeg_parse_get_src_event_masks (GstPad * pad);
gboolean gst_mpeg_parse_handle_src_event (GstPad * pad, GstEvent * event);
#endif /* __MPEG_PARSE_H__ */ const GstQueryType *gst_mpeg_parse_get_src_query_types (GstPad * pad);
gboolean gst_mpeg_parse_handle_src_query (GstPad * pad, GstQueryType type,
GstFormat * format, gint64 * value);
G_END_DECLS
#endif /* __MPEG_PARSE_H__ */

View file

@ -26,11 +26,7 @@
#include <gst/bytestream/bytestream.h> #include <gst/bytestream/bytestream.h>
#include "gstmpegpacketize.h" #include "gstmpegpacketize.h"
G_BEGIN_DECLS
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_RFC2250_ENC \ #define GST_TYPE_RFC2250_ENC \
(gst_rfc2250_enc_get_type()) (gst_rfc2250_enc_get_type())
@ -79,10 +75,6 @@ GType gst_rfc2250_enc_get_type(void);
gboolean gst_rfc2250_enc_plugin_init (GstPlugin *plugin); gboolean gst_rfc2250_enc_plugin_init (GstPlugin *plugin);
G_END_DECLS
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __RFC2250_ENC_H__ */ #endif /* __RFC2250_ENC_H__ */