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);
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))
return FALSE;

View file

@ -331,6 +331,50 @@ tsmux_stream_bytes_in_buffer (TsMuxStream * stream)
return stream->bytes_avail;
}
/**
* tsmux_stream_initialize_pes_packet:
* @stream: a #TsMuxStream
*
* Initializes the PES packet.
*
* Returns: TRUE if we the packet was initialized.
*/
gboolean
tsmux_stream_initialize_pes_packet (TsMuxStream * stream)
{
if (stream->state != TSMUX_STREAM_STATE_HEADER)
return TRUE;
if (stream->pes_payload_size != 0) {
/* Use prescribed fixed PES payload size */
stream->cur_pes_payload_size = stream->pes_payload_size;
tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
&stream->pts, &stream->dts);
} else if (stream->is_video_stream) {
/* Unbounded for video streams */
stream->cur_pes_payload_size = 0;
tsmux_stream_find_pts_dts_within (stream,
tsmux_stream_bytes_in_buffer (stream), &stream->pts, &stream->dts);
} else {
/* Output a PES packet of all currently available bytes otherwise */
stream->cur_pes_payload_size = tsmux_stream_bytes_in_buffer (stream);
tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
&stream->pts, &stream->dts);
}
stream->pi.flags &= ~(TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS |
TSMUX_PACKET_FLAG_PES_WRITE_PTS);
if (stream->pts != -1 && stream->dts != -1)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS;
else {
if (stream->pts != -1)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS;
}
return TRUE;
}
/**
* tsmux_stream_get_data:
* @stream: a #TsMuxStream
@ -350,33 +394,6 @@ tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len)
if (stream->state == TSMUX_STREAM_STATE_HEADER) {
guint8 pes_hdr_length;
if (stream->pes_payload_size != 0) {
/* Use prescribed fixed PES payload size */
stream->cur_pes_payload_size = stream->pes_payload_size;
tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
&stream->pts, &stream->dts);
} else if (stream->is_video_stream) {
/* Unbounded for video streams */
stream->cur_pes_payload_size = 0;
tsmux_stream_find_pts_dts_within (stream,
tsmux_stream_bytes_in_buffer (stream), &stream->pts, &stream->dts);
} else {
/* Output a PES packet of all currently available bytes otherwise */
stream->cur_pes_payload_size = tsmux_stream_bytes_in_buffer (stream);
tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
&stream->pts, &stream->dts);
}
stream->pi.flags &= ~(TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS |
TSMUX_PACKET_FLAG_PES_WRITE_PTS);
if (stream->pts != -1 && stream->dts != -1)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS;
else {
if (stream->pts != -1)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS;
}
pes_hdr_length = tsmux_stream_pes_header_length (stream);
/* 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_avail (TsMuxStream *stream);
gboolean tsmux_stream_initialize_pes_packet (TsMuxStream *stream);
gboolean tsmux_stream_get_data (TsMuxStream *stream, guint8 *buf, guint len);
guint64 tsmux_stream_get_pts (TsMuxStream *stream);