summaryrefslogtreecommitdiffstats
path: root/gst/xingheader/gstxingmux.c
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@circular-chaos.org>2008-01-14 08:56:31 +0000
committerSebastian Dröge <slomo@circular-chaos.org>2008-01-14 08:56:31 +0000
commitdc01d9af1df7c2343239b5c6cec460d5a17e1984 (patch)
tree5807f05b3e837e609fffc8156f4a0f1840251d57 /gst/xingheader/gstxingmux.c
parent881b80513ef753bbbc35f58e57915712cbdd1e84 (diff)
downloadgst-plugins-bad-dc01d9af1df7c2343239b5c6cec460d5a17e1984.tar.gz
gst-plugins-bad-dc01d9af1df7c2343239b5c6cec460d5a17e1984.tar.bz2
gst-plugins-bad-dc01d9af1df7c2343239b5c6cec460d5a17e1984.zip
gst/xingheader/gstxingmux.c: Choose smallest possible frame size for the Xing header, properly set the timestamp, dur...
Original commit message from CVS: * gst/xingheader/gstxingmux.c: (has_xing_header), (generate_xing_header), (gst_xing_mux_chain), (gst_xing_mux_sink_event): Choose smallest possible frame size for the Xing header, properly set the timestamp, duration and offset on the outgoing buffers, only send NEWSEGMENT events in BYTE format downstream and also drop VBRI headers if already existing.
Diffstat (limited to 'gst/xingheader/gstxingmux.c')
-rw-r--r--gst/xingheader/gstxingmux.c76
1 files changed, 61 insertions, 15 deletions
diff --git a/gst/xingheader/gstxingmux.c b/gst/xingheader/gstxingmux.c
index 7db203d7..5f6f95e7 100644
--- a/gst/xingheader/gstxingmux.c
+++ b/gst/xingheader/gstxingmux.c
@@ -202,7 +202,8 @@ has_xing_header (guint32 header, guchar * data, gsize size)
data += 4;
data += get_xing_offset (header);
- if (memcmp (data, "Xing", 4) == 0 || memcmp (data, "Info", 4) == 0)
+ if (memcmp (data, "Xing", 4) == 0 ||
+ memcmp (data, "Info", 4) == 0 || memcmp (data, "VBRI", 4) == 0)
return TRUE;
else
return FALSE;
@@ -217,19 +218,32 @@ generate_xing_header (GstXingMux * xing)
guint32 header;
guint32 header_be;
- guint size, spf;
+ guint size, spf, xing_offset;
gulong rate;
+ guint bitrate = 0x00;
gint64 duration;
gint64 byte_count;
header = xing->first_header;
- /* Set bitrate */
- /* TODO: Choose smallest possible value */
- header &= 0xffff0fff;
- header |= 0xa << 12; /* 0101b */
- parse_header (header, &size, &spf, &rate);
+ /* Set bitrate and choose lowest possible size */
+ do {
+ bitrate++;
+
+ header &= 0xffff0fff;
+ header |= bitrate << 12;
+
+ parse_header (header, &size, &spf, &rate);
+ xing_offset = get_xing_offset (header);
+ } while (size < (4 + xing_offset + 4 + 4 + 4 + 4 + 100) && bitrate < 0xfe);
+
+ g_print ("0x%x\n", bitrate);
+
+ if (bitrate == 0xfe) {
+ GST_ERROR ("No usable bitrate found!");
+ return NULL;
+ }
if (gst_pad_alloc_buffer_and_set_caps (xing->srcpad, 0, size,
GST_PAD_CAPS (xing->srcpad), &xing_header) != GST_FLOW_OK) {
@@ -243,7 +257,7 @@ generate_xing_header (GstXingMux * xing)
memcpy (data, &header_be, 4);
data += 4;
- data += get_xing_offset (header);
+ data += xing_offset;
memcpy (data, "Xing", 4);
data += 4;
@@ -455,6 +469,13 @@ gst_xing_mux_chain (GstPad * pad, GstBuffer * buffer)
xing->first_header = header;
xing_header = generate_xing_header (xing);
+
+ if (xing_header == NULL) {
+ GST_ERROR ("Can't generate Xing header");
+ gst_buffer_unref (outbuf);
+ return GST_FLOW_ERROR;
+ }
+
xing_header_size = GST_BUFFER_SIZE (xing_header);
if (GST_FLOW_IS_FATAL (ret = gst_pad_push (xing->srcpad, xing_header))) {
@@ -477,9 +498,17 @@ gst_xing_mux_chain (GstPad * pad, GstBuffer * buffer)
seek_entry->byte = (seek_entry->timestamp == 0) ? 0 : xing->byte_count;
xing->seek_table = g_list_append (xing->seek_table, seek_entry);
+ duration = gst_util_uint64_scale (spf, GST_SECOND, rate);
+
+ GST_BUFFER_TIMESTAMP (outbuf) =
+ (xing->duration == GST_CLOCK_TIME_NONE) ? 0 : xing->duration;
+ GST_BUFFER_DURATION (outbuf) = duration;
+ GST_BUFFER_OFFSET (outbuf) = xing->byte_count;
+ GST_BUFFER_OFFSET_END (outbuf) =
+ xing->byte_count + GST_BUFFER_SIZE (outbuf);
+
xing->byte_count += GST_BUFFER_SIZE (outbuf);
- duration = gst_util_uint64_scale (spf, GST_SECOND, rate);
if (xing->duration == GST_CLOCK_TIME_NONE)
xing->duration = duration;
else
@@ -508,11 +537,23 @@ gst_xing_mux_sink_event (GstPad * pad, GstEvent * event)
case GST_EVENT_NEWSEGMENT:
if (xing->sent_xing) {
GST_ERROR ("Already sent Xing header, dropping NEWSEGMENT event!");
-
gst_event_unref (event);
result = FALSE;
} else {
- result = gst_pad_push_event (xing->srcpad, event);
+ GstFormat fmt;
+
+ gst_event_parse_new_segment (event, NULL, NULL, &fmt, NULL, NULL, NULL);
+
+ if (fmt == GST_FORMAT_BYTES) {
+ result = gst_pad_push_event (xing->srcpad, event);
+ } else {
+ gst_event_unref (event);
+
+ event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
+ 0, GST_CLOCK_TIME_NONE, 0);
+
+ result = gst_pad_push_event (xing->srcpad, event);
+ }
}
break;
@@ -535,11 +576,16 @@ gst_xing_mux_sink_event (GstPad * pad, GstEvent * event)
header = generate_xing_header (xing);
- GST_INFO ("Writing real Xing header to beginning of stream");
+ if (header == NULL) {
+ GST_ERROR ("Can't generate Xing header");
+ } else {
+
+ GST_INFO ("Writing real Xing header to beginning of stream");
- if (GST_FLOW_IS_FATAL (ret = gst_pad_push (xing->srcpad, header)))
- GST_WARNING ("Failed to push updated Xing header: %s\n",
- gst_flow_get_name (ret));
+ if (GST_FLOW_IS_FATAL (ret = gst_pad_push (xing->srcpad, header)))
+ GST_WARNING ("Failed to push updated Xing header: %s\n",
+ gst_flow_get_name (ret));
+ }
}
}
result = gst_pad_push_event (xing->srcpad, event);