summaryrefslogtreecommitdiff
path: root/libavformat/mpegts.c
diff options
context:
space:
mode:
authorAndriy Gelman <andriy.gelman@gmail.com>2019-03-08 22:20:07 -0500
committerMichael Niedermayer <michael@niedermayer.cc>2019-03-09 15:27:07 +0100
commit0a84ba26081c890e0726f0ad5ece2b4517bf4ee1 (patch)
treee9b446c5e49543a46bf0c7095ac87ba28dfbc651 /libavformat/mpegts.c
parent147ef1d9472ea39f837224bc8a2fbe07a9f04ae3 (diff)
avformat/mpegts: reduce buffering during initialization
Reduces buffering latency with low bitrate streams, where 8192 bytes can mean several seconds. Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r--libavformat/mpegts.c59
1 files changed, 36 insertions, 23 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index e7bbf3e488..773b7a0384 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -56,6 +56,9 @@
(prev_dividend) = (dividend); \
} while (0)
+#define PROBE_PACKET_MAX_BUF 8192
+#define PROBE_PACKET_MARGIN 5
+
enum MpegTSFilterType {
MPEGTS_PES,
MPEGTS_SECTION,
@@ -594,28 +597,42 @@ static int analyze(const uint8_t *buf, int size, int packet_size,
return best_score - FFMAX(stat_all - 10*best_score, 0)/10;
}
-/* autodetect fec presence. Must have at least 1024 bytes */
-static int get_packet_size(const uint8_t *buf, int size)
+/* autodetect fec presence */
+static int get_packet_size(AVFormatContext* s)
{
int score, fec_score, dvhs_score;
+ int margin;
+ int ret;
- if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
- return AVERROR_INVALIDDATA;
+ /*init buffer to store stream for probing */
+ uint8_t buf[PROBE_PACKET_MAX_BUF] = {0};
+ int buf_size = 0;
- score = analyze(buf, size, TS_PACKET_SIZE, 0);
- dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, 0);
- fec_score = analyze(buf, size, TS_FEC_PACKET_SIZE, 0);
- av_log(NULL, AV_LOG_TRACE, "score: %d, dvhs_score: %d, fec_score: %d \n",
- score, dvhs_score, fec_score);
-
- if (score > fec_score && score > dvhs_score)
- return TS_PACKET_SIZE;
- else if (dvhs_score > score && dvhs_score > fec_score)
- return TS_DVHS_PACKET_SIZE;
- else if (score < fec_score && dvhs_score < fec_score)
- return TS_FEC_PACKET_SIZE;
- else
- return AVERROR_INVALIDDATA;
+ while (buf_size < PROBE_PACKET_MAX_BUF) {
+ ret = avio_read_partial(s->pb, buf + buf_size, PROBE_PACKET_MAX_BUF - buf_size);
+ if (ret < 0)
+ return AVERROR_INVALIDDATA;
+ buf_size += ret;
+
+ score = analyze(buf, buf_size, TS_PACKET_SIZE, 0);
+ dvhs_score = analyze(buf, buf_size, TS_DVHS_PACKET_SIZE, 0);
+ fec_score = analyze(buf, buf_size, TS_FEC_PACKET_SIZE, 0);
+ av_log(s, AV_LOG_TRACE, "Probe: %d, score: %d, dvhs_score: %d, fec_score: %d \n",
+ buf_size, score, dvhs_score, fec_score);
+
+ if (buf_size < PROBE_PACKET_MAX_BUF)
+ margin = PROBE_PACKET_MARGIN; /*if buffer not filled */
+ else
+ margin = 0;
+
+ if (score > FFMAX(fec_score, dvhs_score) + margin)
+ return TS_PACKET_SIZE;
+ else if (dvhs_score > FFMAX(score, fec_score) + margin)
+ return TS_DVHS_PACKET_SIZE;
+ else if (fec_score > FFMAX(score, dvhs_score) + margin)
+ return TS_FEC_PACKET_SIZE;
+ }
+ return AVERROR_INVALIDDATA;
}
typedef struct SectionHeader {
@@ -2933,8 +2950,6 @@ static int mpegts_read_header(AVFormatContext *s)
{
MpegTSContext *ts = s->priv_data;
AVIOContext *pb = s->pb;
- uint8_t buf[8 * 1024] = {0};
- int len;
int64_t pos, probesize = s->probesize;
s->internal->prefer_codec_framerate = 1;
@@ -2942,10 +2957,8 @@ static int mpegts_read_header(AVFormatContext *s)
if (ffio_ensure_seekback(pb, probesize) < 0)
av_log(s, AV_LOG_WARNING, "Failed to allocate buffers for seekback\n");
- /* read the first 8192 bytes to get packet size */
pos = avio_tell(pb);
- len = avio_read(pb, buf, sizeof(buf));
- ts->raw_packet_size = get_packet_size(buf, len);
+ ts->raw_packet_size = get_packet_size(s);
if (ts->raw_packet_size <= 0) {
av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n");
ts->raw_packet_size = TS_PACKET_SIZE;