mpegtsmux: Initialize PES packet before getting the header size.

The PES header length is calculated before setting the dynamic flags, returning
a wrong value. Small frames that should be sent in a single TS packet are
spawned to a new packet because of that error. For audio streams where a single
frame can cope in one TS packet it introduces a huge overhead.

For a 100B packet, we prepare a TS packet with a payload of(100+9)B. Then, we
write the TS header using this value in tsmux_write_ts_header, and call
tsmux_stream_get_data(). The dynamic flags where not set yet and now
tsmux_stream_pes_header_length() returns 14B instead of 9B. The payload of the
TS packet is 114B, 5B more than what was calculated. 109B are sent in a first
packet and the remaining 5B are sent in another one.

Fixes bug #628548.
This commit is contained in:
Andoni Morales Alastruey 2010-09-01 22:05:43 +02:00 committed by Sebastian Dröge
parent 8af858cf8f
commit 4668330bdc
3 changed files with 48 additions and 28 deletions

View file

@ -767,8 +767,10 @@ tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
} }
} }
pi->stream_avail = tsmux_stream_bytes_avail (stream);
pi->packet_start_unit_indicator = tsmux_stream_at_pes_start (stream); pi->packet_start_unit_indicator = tsmux_stream_at_pes_start (stream);
if (pi->packet_start_unit_indicator)
tsmux_stream_initialize_pes_packet (stream);
pi->stream_avail = tsmux_stream_bytes_avail (stream);
if (!tsmux_write_ts_header (mux->packet_buf, pi, &payload_len, &payload_offs)) if (!tsmux_write_ts_header (mux->packet_buf, pi, &payload_len, &payload_offs))
return FALSE; return FALSE;

View file

@ -332,23 +332,18 @@ tsmux_stream_bytes_in_buffer (TsMuxStream * stream)
} }
/** /**
* tsmux_stream_get_data: * tsmux_stream_initialize_pes_packet:
* @stream: a #TsMuxStream * @stream: a #TsMuxStream
* @buf: a buffer to hold the result
* @len: the length of @buf
* *
* Copy up to @len available data in @stream into the buffer @buf. * Initializes the PES packet.
* *
* Returns: TRUE if @len bytes could be retrieved. * Returns: TRUE if we the packet was initialized.
*/ */
gboolean gboolean
tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len) tsmux_stream_initialize_pes_packet (TsMuxStream * stream)
{ {
g_return_val_if_fail (stream != NULL, FALSE); if (stream->state != TSMUX_STREAM_STATE_HEADER)
g_return_val_if_fail (buf != NULL, FALSE); return TRUE;
if (stream->state == TSMUX_STREAM_STATE_HEADER) {
guint8 pes_hdr_length;
if (stream->pes_payload_size != 0) { if (stream->pes_payload_size != 0) {
/* Use prescribed fixed PES payload size */ /* Use prescribed fixed PES payload size */
@ -377,6 +372,28 @@ tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS; stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS;
} }
return TRUE;
}
/**
* tsmux_stream_get_data:
* @stream: a #TsMuxStream
* @buf: a buffer to hold the result
* @len: the length of @buf
*
* Copy up to @len available data in @stream into the buffer @buf.
*
* Returns: TRUE if @len bytes could be retrieved.
*/
gboolean
tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len)
{
g_return_val_if_fail (stream != NULL, FALSE);
g_return_val_if_fail (buf != NULL, FALSE);
if (stream->state == TSMUX_STREAM_STATE_HEADER) {
guint8 pes_hdr_length;
pes_hdr_length = tsmux_stream_pes_header_length (stream); pes_hdr_length = tsmux_stream_pes_header_length (stream);
/* Submitted buffer must be at least as large as the PES header */ /* Submitted buffer must be at least as large as the PES header */

View file

@ -212,6 +212,7 @@ void tsmux_stream_get_es_descrs (TsMuxStream *stream, guint8 *buf, guint16 *l
gint tsmux_stream_bytes_in_buffer (TsMuxStream *stream); gint tsmux_stream_bytes_in_buffer (TsMuxStream *stream);
gint tsmux_stream_bytes_avail (TsMuxStream *stream); gint tsmux_stream_bytes_avail (TsMuxStream *stream);
gboolean tsmux_stream_initialize_pes_packet (TsMuxStream *stream);
gboolean tsmux_stream_get_data (TsMuxStream *stream, guint8 *buf, guint len); gboolean tsmux_stream_get_data (TsMuxStream *stream, guint8 *buf, guint len);
guint64 tsmux_stream_get_pts (TsMuxStream *stream); guint64 tsmux_stream_get_pts (TsMuxStream *stream);