mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
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.
This commit is contained in:
parent
881b80513e
commit
dc01d9af1d
3 changed files with 72 additions and 16 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
2008-01-14 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2008-01-12 Sebastian Dröge <slomo@circular-chaos.org>
|
2008-01-12 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
* gst/xingheader/Makefile.am:
|
* gst/xingheader/Makefile.am:
|
||||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit bd02d788384b40ff511cac0e32aa77f51a68912d
|
Subproject commit 36e8d05157d6c831e0d3919ae2ee9c342498eda8
|
|
@ -202,7 +202,8 @@ has_xing_header (guint32 header, guchar * data, gsize size)
|
||||||
data += 4;
|
data += 4;
|
||||||
data += get_xing_offset (header);
|
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;
|
return TRUE;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -217,19 +218,32 @@ generate_xing_header (GstXingMux * xing)
|
||||||
|
|
||||||
guint32 header;
|
guint32 header;
|
||||||
guint32 header_be;
|
guint32 header_be;
|
||||||
guint size, spf;
|
guint size, spf, xing_offset;
|
||||||
gulong rate;
|
gulong rate;
|
||||||
|
guint bitrate = 0x00;
|
||||||
|
|
||||||
gint64 duration;
|
gint64 duration;
|
||||||
gint64 byte_count;
|
gint64 byte_count;
|
||||||
|
|
||||||
header = xing->first_header;
|
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,
|
if (gst_pad_alloc_buffer_and_set_caps (xing->srcpad, 0, size,
|
||||||
GST_PAD_CAPS (xing->srcpad), &xing_header) != GST_FLOW_OK) {
|
GST_PAD_CAPS (xing->srcpad), &xing_header) != GST_FLOW_OK) {
|
||||||
|
@ -243,7 +257,7 @@ generate_xing_header (GstXingMux * xing)
|
||||||
memcpy (data, &header_be, 4);
|
memcpy (data, &header_be, 4);
|
||||||
|
|
||||||
data += 4;
|
data += 4;
|
||||||
data += get_xing_offset (header);
|
data += xing_offset;
|
||||||
|
|
||||||
memcpy (data, "Xing", 4);
|
memcpy (data, "Xing", 4);
|
||||||
data += 4;
|
data += 4;
|
||||||
|
@ -455,6 +469,13 @@ gst_xing_mux_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
xing->first_header = header;
|
xing->first_header = header;
|
||||||
|
|
||||||
xing_header = generate_xing_header (xing);
|
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);
|
xing_header_size = GST_BUFFER_SIZE (xing_header);
|
||||||
|
|
||||||
if (GST_FLOW_IS_FATAL (ret = gst_pad_push (xing->srcpad, 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;
|
seek_entry->byte = (seek_entry->timestamp == 0) ? 0 : xing->byte_count;
|
||||||
xing->seek_table = g_list_append (xing->seek_table, seek_entry);
|
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);
|
xing->byte_count += GST_BUFFER_SIZE (outbuf);
|
||||||
|
|
||||||
duration = gst_util_uint64_scale (spf, GST_SECOND, rate);
|
|
||||||
if (xing->duration == GST_CLOCK_TIME_NONE)
|
if (xing->duration == GST_CLOCK_TIME_NONE)
|
||||||
xing->duration = duration;
|
xing->duration = duration;
|
||||||
else
|
else
|
||||||
|
@ -508,11 +537,23 @@ gst_xing_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
case GST_EVENT_NEWSEGMENT:
|
case GST_EVENT_NEWSEGMENT:
|
||||||
if (xing->sent_xing) {
|
if (xing->sent_xing) {
|
||||||
GST_ERROR ("Already sent Xing header, dropping NEWSEGMENT event!");
|
GST_ERROR ("Already sent Xing header, dropping NEWSEGMENT event!");
|
||||||
|
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
} else {
|
} 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;
|
break;
|
||||||
|
|
||||||
|
@ -535,11 +576,16 @@ gst_xing_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
header = generate_xing_header (xing);
|
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 {
|
||||||
|
|
||||||
if (GST_FLOW_IS_FATAL (ret = gst_pad_push (xing->srcpad, header)))
|
GST_INFO ("Writing real Xing header to beginning of stream");
|
||||||
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);
|
result = gst_pad_push_event (xing->srcpad, event);
|
||||||
|
|
Loading…
Reference in a new issue