Message ID | 20190306060158.17003-1-andriy.gelman@gmail.com |
---|---|
State | Superseded |
Headers | show |
2019-03-06 7:01 GMT+01:00, Andriy Gelman <andriy.gelman@gmail.com>: > From: Andriy Gelman <andriy.gelman@gmail.com> > > Reduces buffering latency with low bitrate streams, where > 8192 bytes can mean several seconds. Would it be an alternative to add an option that allows to force the packet size? Carl Eugen
> Would it be an alternative to add an option that allows to force > the packet size? I like the idea. I guess the options are: 1. Set packet size + Use old version (fixed 8192 buffer) to estimate parameter if not set by user. 2. Set packet size + Use new version (adaptive buffer) to estimate parameter if not set by user. Regards, Andriy On Wed, 6 Mar 2019 at 02:51, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote: > 2019-03-06 7:01 GMT+01:00, Andriy Gelman <andriy.gelman@gmail.com>: > > From: Andriy Gelman <andriy.gelman@gmail.com> > > > > Reduces buffering latency with low bitrate streams, where > > 8192 bytes can mean several seconds. > > Would it be an alternative to add an option that allows to force > the packet size? > > Carl Eugen > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel >
On Wed, 6 Mar 2019, Andriy Gelman wrote: > From: Andriy Gelman <andriy.gelman@gmail.com> > > Reduces buffering latency with low bitrate streams, where > 8192 bytes can mean several seconds. > --- > libavformat/mpegts.c | 60 +++++++++++++++++++++++++++----------------- > 1 file changed, 37 insertions(+), 23 deletions(-) > > diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c > index b04fd7b4f4..fcb5b488d8 100644 > --- a/libavformat/mpegts.c > +++ b/libavformat/mpegts.c > @@ -53,6 +53,10 @@ > (prev_dividend) = (dividend); \ > } while (0) > > +#define PROBE_PACKET_MAX_BUF 8192 > +#define PROBE_PACKET_STEP 512 > +#define PROBE_PACKET_MARGIN 5 > + > enum MpegTSFilterType { > MPEGTS_PES, > MPEGTS_SECTION, > @@ -591,28 +595,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(AVIOContext* pb) > { > 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_STEP <= PROBE_PACKET_MAX_BUF) { > + ret = avio_read(pb, buf + buf_size, PROBE_PACKET_STEP); > + if (ret < 0) > + break; If EOF happens on STEP boundary then you return INVALIDDATA instead of comparing last scores with 0 margin... > + 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(NULL, 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 && ret == PROBE_PACKET_STEP) > + margin = PROBE_PACKET_MARGIN; /*if buffer not filled and no eof */ > + 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 { > @@ -2841,8 +2859,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; > @@ -2850,10 +2866,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(pb); > 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; > -- Regards, Marton
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index b04fd7b4f4..fcb5b488d8 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -53,6 +53,10 @@ (prev_dividend) = (dividend); \ } while (0) +#define PROBE_PACKET_MAX_BUF 8192 +#define PROBE_PACKET_STEP 512 +#define PROBE_PACKET_MARGIN 5 + enum MpegTSFilterType { MPEGTS_PES, MPEGTS_SECTION, @@ -591,28 +595,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(AVIOContext* pb) { 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_STEP <= PROBE_PACKET_MAX_BUF) { + ret = avio_read(pb, buf + buf_size, PROBE_PACKET_STEP); + if (ret < 0) + break; + 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(NULL, 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 && ret == PROBE_PACKET_STEP) + margin = PROBE_PACKET_MARGIN; /*if buffer not filled and no eof */ + 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 { @@ -2841,8 +2859,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; @@ -2850,10 +2866,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(pb); 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;
From: Andriy Gelman <andriy.gelman@gmail.com> Reduces buffering latency with low bitrate streams, where 8192 bytes can mean several seconds. --- libavformat/mpegts.c | 60 +++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 23 deletions(-)