[FFmpeg-devel] [PATCH] DVB EPG decoder

Marton Balint cus at passwd.hu
Sat Sep 7 21:39:38 EEST 2019



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.2lannoy at 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


More information about the ffmpeg-devel mailing list