On Wed, 4 Sep 2019, Anthony Delannoy wrote:

Hi

I'm still interested to have those three commits merged (update in attachments).

Ok, below are some more comments.


But I'd like to see data decoder in the future to use more easily
EPG/NIT/BAT etc tables.
Will it be possible? With modifications if it needs to be?

I don't see how, as it does not fit into the concept of the libav* libraries. I feel this belongs to a separate library.

From 335b0bf377c1e5cfc5207561adc9621b113759b0 Mon Sep 17 00:00:00 2001
From: Anthony Delannoy <anthony.2lan...@gmail.com>
Date: Wed, 21 Aug 2019 11:46:56 +0200
Subject: [PATCH 3/3] lavf/mpegts: EPG extraction from mpegts

---
 libavformat/mpegts.c | 71 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 69 insertions(+), 2 deletions(-)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 0415ceea02..9bb6b6add8 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -168,6 +168,8 @@ struct MpegTSContext {
     /** filters for various streams specified by PMT + for the PAT and PMT */
     MpegTSFilter *pids[NB_PID_MAX];
     int current_pid;
+
+    AVStream *epg_stream;
 };

 #define MPEGTS_OPTIONS \
@@ -2498,13 +2500,68 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t 
*section, int section_len
     }
 }

+static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int 
section_len)
+{
+    MpegTSContext *ts = filter->u.section_filter.opaque;
+    const uint8_t *p, *p_end;
+    SectionHeader h1, *h = &h1;
+
+    /*
+     * Sometimes we receive EPG packets but SDT table do not have
+     * eit_pres_following or eit_sched turned on, so we open EPG
+     * stream directly here.
+     */
+    if (!ts->epg_stream) {
+        ts->epg_stream = avformat_new_stream(ts->stream, NULL);
+        if (!ts->epg_stream)
+            return;
+        ts->epg_stream->id = EIT_PID;
+        ts->epg_stream->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+        ts->epg_stream->codecpar->codec_id = AV_CODEC_ID_EPG;
+    }
+
+    if (ts->epg_stream->discard == AVDISCARD_ALL)
+        return;
+
+    p_end = section + section_len - 4;
+    p     = section;
+
+    if (parse_section_header(h, &p, p_end) < 0)
+        return;
+    if (h->tid < EIT_TID || h->tid > OEITS_END_TID)
+        return;
+
+    av_log(ts->stream, AV_LOG_TRACE, "EIT: tid received = %.02x\n", h->tid);
+
+    /**
+     * Service_id 0xFFFF is reserved, it indicates that the current EIT table
+     * is scrambled.
+     */
+    if (h->id == 0xFFFF) {
+        av_log(ts->stream, AV_LOG_WARNING, "Scrambled EIT table received.\n");
+        return;
+    }

In case of a scrambled EIT (which I have never seen myself in the wild) you'd
print this at every packet. You should either remove the warning, or check if
this is the first time (e.g. by checking if the EPG stream was just created).

+
+    /**
+     * In case we receive an EPG packet before mpegts context is fully
+     * initialized.
+     */
+    if (!ts->pkt)
+        return;
+
+    new_data_packet(section, section_len, ts->pkt);
+    ts->pkt->stream_index = ts->epg_stream->index;
+    ts->stop_parse = 1;
+}
+
 static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int 
section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
     MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h1, *h = &h1;
     const uint8_t *p, *p_end, *desc_list_end, *desc_end;
-    int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
+    int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type,
+        eit_sched, eit_pres_following;
     char *name, *provider_name;

     av_log(ts->stream, AV_LOG_TRACE, "SDT:\n");
@@ -2534,6 +2591,13 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t 
*section, int section_len
         val = get8(&p, p_end);
         if (val < 0)
             break;
+        eit_sched = (val >> 1) & 0x1;
+        eit_pres_following = val & 0x1;
+
+        if ((eit_sched | eit_pres_following) && !ts->epg_stream)
+            av_log(ts->stream, AV_LOG_WARNING, "SDT table advertise EIT but no"
+                   " packets were received yet.\n");
+

You should remove this, there are tons of captures where EIT PID is
intentionally filtered, we should not spam the user.

         desc_list_len = get16(&p, p_end);
         if (desc_list_len < 0)
             break;
@@ -2984,8 +3048,8 @@ static int mpegts_read_header(AVFormatContext *s)
         seek_back(s, pb, pos);

         mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);
-
         mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);
+        mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1);

         handle_packets(ts, probesize / ts->raw_packet_size);
         /* if could not find service, enable auto_guess */
@@ -3240,8 +3304,11 @@ MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext 
*s)
     ts->raw_packet_size = TS_PACKET_SIZE;
     ts->stream = s;
     ts->auto_guess = 1;
+    ts->epg_stream = NULL;

Not needed, as context is zero initialized.

+
     mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);
     mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);
+    mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1);

     return ts;
 }
--
2.23.0

Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to