Commit 891ce00c authored by Jindřich Makovička's avatar Jindřich Makovička Committed by Anton Khirnov

mpegts: adjustable minimum PES payload

With the current default PES packet size, and very small audio bitrates,
audio packet duration gets too long. For players, which wait for a whole
audio packet (or more) it takes a very long time to start playing sound.

For 24kbps audio, one PES packet is about 1 second long. On Motorola STBs,
we observe about 3 second delay before the playback starts with the
default setting.
Signed-off-by: 's avatarAnton Khirnov <anton@khirnov.net>
parent 6fa9843b
...@@ -68,6 +68,7 @@ typedef struct MpegTSWrite { ...@@ -68,6 +68,7 @@ typedef struct MpegTSWrite {
int tsid; int tsid;
int64_t first_pcr; int64_t first_pcr;
int mux_rate; ///< set to 1 when VBR int mux_rate; ///< set to 1 when VBR
int pes_payload_size;
int transport_stream_id; int transport_stream_id;
int original_network_id; int original_network_id;
...@@ -77,6 +78,10 @@ typedef struct MpegTSWrite { ...@@ -77,6 +78,10 @@ typedef struct MpegTSWrite {
int start_pid; int start_pid;
} MpegTSWrite; } MpegTSWrite;
/* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
#define DEFAULT_PES_HEADER_FREQ 16
#define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
static const AVOption options[] = { static const AVOption options[] = {
{ "mpegts_transport_stream_id", "Set transport_stream_id field.", { "mpegts_transport_stream_id", "Set transport_stream_id field.",
offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, {.dbl = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM}, offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, {.dbl = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM},
...@@ -89,6 +94,8 @@ static const AVOption options[] = { ...@@ -89,6 +94,8 @@ static const AVOption options[] = {
{ "mpegts_start_pid", "Set the first pid.", { "mpegts_start_pid", "Set the first pid.",
offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT, {.dbl = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM}, offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT, {.dbl = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM},
{ "muxrate", NULL, offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, {1}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "muxrate", NULL, offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, {1}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
{ "pes_payload_size", "Minimum PES packet payload in bytes",
offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, {DEFAULT_PES_PAYLOAD_SIZE}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL }, { NULL },
}; };
...@@ -188,10 +195,6 @@ static int mpegts_write_section1(MpegTSSection *s, int tid, int id, ...@@ -188,10 +195,6 @@ static int mpegts_write_section1(MpegTSSection *s, int tid, int id,
#define DEFAULT_PROVIDER_NAME "Libav" #define DEFAULT_PROVIDER_NAME "Libav"
#define DEFAULT_SERVICE_NAME "Service01" #define DEFAULT_SERVICE_NAME "Service01"
/* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
#define DEFAULT_PES_HEADER_FREQ 16
#define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
/* we retransmit the SI info at this rate */ /* we retransmit the SI info at this rate */
#define SDT_RETRANS_TIME 500 #define SDT_RETRANS_TIME 500
#define PAT_RETRANS_TIME 100 #define PAT_RETRANS_TIME 100
...@@ -206,7 +209,7 @@ typedef struct MpegTSWriteStream { ...@@ -206,7 +209,7 @@ typedef struct MpegTSWriteStream {
int64_t payload_pts; int64_t payload_pts;
int64_t payload_dts; int64_t payload_dts;
int payload_flags; int payload_flags;
uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE]; uint8_t *payload;
ADTSContext *adts; ADTSContext *adts;
} MpegTSWriteStream; } MpegTSWriteStream;
...@@ -453,6 +456,9 @@ static int mpegts_write_header(AVFormatContext *s) ...@@ -453,6 +456,9 @@ static int mpegts_write_header(AVFormatContext *s)
const char *provider_name; const char *provider_name;
int *pids; int *pids;
// round up to a whole number of TS packets
ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
ts->tsid = ts->transport_stream_id; ts->tsid = ts->transport_stream_id;
ts->onid = ts->original_network_id; ts->onid = ts->original_network_id;
/* allocate a single DVB service */ /* allocate a single DVB service */
...@@ -489,6 +495,9 @@ static int mpegts_write_header(AVFormatContext *s) ...@@ -489,6 +495,9 @@ static int mpegts_write_header(AVFormatContext *s)
if (!ts_st) if (!ts_st)
goto fail; goto fail;
st->priv_data = ts_st; st->priv_data = ts_st;
ts_st->payload = av_mallocz(ts->pes_payload_size);
if (!ts_st->payload)
goto fail;
ts_st->service = service; ts_st->service = service;
/* MPEG pid values < 16 are reserved. Applications which set st->id in /* MPEG pid values < 16 are reserved. Applications which set st->id in
* this range are assigned a calculated pid. */ * this range are assigned a calculated pid. */
...@@ -524,10 +533,10 @@ static int mpegts_write_header(AVFormatContext *s) ...@@ -524,10 +533,10 @@ static int mpegts_write_header(AVFormatContext *s)
st->codec->extradata_size > 0) { st->codec->extradata_size > 0) {
ts_st->adts = av_mallocz(sizeof(*ts_st->adts)); ts_st->adts = av_mallocz(sizeof(*ts_st->adts));
if (!ts_st->adts) if (!ts_st->adts)
return AVERROR(ENOMEM); goto fail;
if (ff_adts_decode_extradata(s, ts_st->adts, st->codec->extradata, if (ff_adts_decode_extradata(s, ts_st->adts, st->codec->extradata,
st->codec->extradata_size) < 0) st->codec->extradata_size) < 0)
return -1; goto fail;
} }
} }
...@@ -595,7 +604,13 @@ static int mpegts_write_header(AVFormatContext *s) ...@@ -595,7 +604,13 @@ static int mpegts_write_header(AVFormatContext *s)
fail: fail:
av_free(pids); av_free(pids);
for(i = 0;i < s->nb_streams; i++) { for(i = 0;i < s->nb_streams; i++) {
MpegTSWriteStream *ts_st;
st = s->streams[i]; st = s->streams[i];
ts_st = st->priv_data;
if (ts_st) {
av_freep(&ts_st->payload);
av_freep(&ts_st->adts);
}
av_freep(&st->priv_data); av_freep(&st->priv_data);
} }
return -1; return -1;
...@@ -924,6 +939,7 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -924,6 +939,7 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
int size = pkt->size; int size = pkt->size;
uint8_t *buf= pkt->data; uint8_t *buf= pkt->data;
uint8_t *data= NULL; uint8_t *data= NULL;
MpegTSWrite *ts = s->priv_data;
MpegTSWriteStream *ts_st = st->priv_data; MpegTSWriteStream *ts_st = st->priv_data;
const uint64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE)*2; const uint64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE)*2;
int64_t dts = AV_NOPTS_VALUE, pts = AV_NOPTS_VALUE; int64_t dts = AV_NOPTS_VALUE, pts = AV_NOPTS_VALUE;
...@@ -1006,14 +1022,14 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1006,14 +1022,14 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
return 0; return 0;
} }
if (ts_st->payload_size + size > DEFAULT_PES_PAYLOAD_SIZE) { if (ts_st->payload_size + size > ts->pes_payload_size) {
if (ts_st->payload_size) { if (ts_st->payload_size) {
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size, mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
ts_st->payload_pts, ts_st->payload_dts, ts_st->payload_pts, ts_st->payload_dts,
ts_st->payload_flags & AV_PKT_FLAG_KEY); ts_st->payload_flags & AV_PKT_FLAG_KEY);
ts_st->payload_size = 0; ts_st->payload_size = 0;
} }
if (size > DEFAULT_PES_PAYLOAD_SIZE) { if (size > ts->pes_payload_size) {
mpegts_write_pes(s, st, buf, size, pts, dts, mpegts_write_pes(s, st, buf, size, pts, dts,
pkt->flags & AV_PKT_FLAG_KEY); pkt->flags & AV_PKT_FLAG_KEY);
av_free(data); av_free(data);
...@@ -1052,6 +1068,7 @@ static int mpegts_write_end(AVFormatContext *s) ...@@ -1052,6 +1068,7 @@ static int mpegts_write_end(AVFormatContext *s)
ts_st->payload_pts, ts_st->payload_dts, ts_st->payload_pts, ts_st->payload_dts,
ts_st->payload_flags & AV_PKT_FLAG_KEY); ts_st->payload_flags & AV_PKT_FLAG_KEY);
} }
av_freep(&ts_st->payload);
av_freep(&ts_st->adts); av_freep(&ts_st->adts);
} }
avio_flush(s->pb); avio_flush(s->pb);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment