[FFmpeg-devel] [PATCH] avformat/mpegts.c: reduce buffering during initialization

andriy.gelman at gmail.com andriy.gelman at gmail.com
Tue Mar 5 05:21:01 EET 2019


From: Andriy Gelman <andriy.gelman at gmail.com>

Reduces buffering during estimation of mpegts raw_packet_size
parameter. Instead of buffering a fixed 8192 bytes, calculate
probe scores on a smaller buffer. Increase buffer size until
probe score is greater than minimum value.
---
 libavformat/mpegts.c | 82 +++++++++++++++++++++++++++++++-------------
 1 file changed, 59 insertions(+), 23 deletions(-)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index b04fd7b4f4..a7b33eae69 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -53,6 +53,10 @@
         (prev_dividend) = (dividend);                                          \
     } while (0)
 
+#define MAX_RAW_PACKET_PROBE 8192
+#define PROBE_PACKET_STEP 512
+#define RAW_PACKET_MIN_SCORE 10
+
 enum MpegTSFilterType {
     MPEGTS_PES,
     MPEGTS_SECTION,
@@ -591,28 +595,64 @@ 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 pd_packet_size = TS_PACKET_SIZE;
+    int best_score = 0;
+    int ret;
 
-    if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
-        return AVERROR_INVALIDDATA;
+    AVProbeData pd = { 0 };
+    while (best_score < RAW_PACKET_MIN_SCORE &&
+            pd.buf_size + PROBE_PACKET_STEP <= MAX_RAW_PACKET_PROBE) {
+
+        /*create extra space for next packet*/
+        uint8_t *new_buf = av_realloc(pd.buf, pd.buf_size + PROBE_PACKET_STEP);
+        if (new_buf) {
+            pd.buf = new_buf;
+            ret = avio_read(pb, pd.buf + pd.buf_size, PROBE_PACKET_STEP);
+            if (ret < 0) {
+                av_log(pb, AV_LOG_ERROR, "Error reading from input: %s.\n",
+                   av_err2str(ret));
+                break;
+            }
+            pd.buf_size += ret;
+        } else
+            goto fail;
+
+        /*check score for each fec packet size*/
+        score      = analyze(pd.buf, pd.buf_size, TS_PACKET_SIZE,      0);
+        if (score > best_score) {
+            best_score = score;
+            pd_packet_size = TS_PACKET_SIZE;
+        }
 
-    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;
+        dvhs_score = analyze(pd.buf, pd.buf_size, TS_DVHS_PACKET_SIZE, 0);
+        if (dvhs_score > best_score) {
+            best_score = dvhs_score;
+            pd_packet_size = TS_DVHS_PACKET_SIZE;
+        }
+
+        fec_score  = analyze(pd.buf, pd.buf_size, TS_FEC_PACKET_SIZE,  0);
+        if (fec_score > best_score) {
+            best_score = fec_score;
+            pd_packet_size = TS_FEC_PACKET_SIZE;
+        }
+
+        av_log(NULL, AV_LOG_TRACE, "Probe size: %d, score: %d, dvhs_score: %d, fec_score: %d \n",
+            pd.buf_size, score, dvhs_score, fec_score);
+    }
+
+    if (pd.buf)
+        av_freep(&pd.buf);
+
+    return pd_packet_size;
+
+fail:
+    if (pd.buf)
+        av_freep(&pd.buf);
+    return AVERROR(ENOMEM);
 }
 
 typedef struct SectionHeader {
@@ -2841,8 +2881,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 +2888,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;
-- 
2.20.1



More information about the ffmpeg-devel mailing list