[FFmpeg-devel] [PATCH v2] avformat/mpegts: reduce buffering during initialization
Marton Balint
cus at passwd.hu
Wed Mar 6 22:45:19 EET 2019
On Wed, 6 Mar 2019, Andriy Gelman wrote:
> From: Andriy Gelman <andriy.gelman at 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
More information about the ffmpeg-devel
mailing list