[FFmpeg-devel] [PATCH] libavformat/mpegts.c: add: parse EIT descriptors

Marton Balint cus at passwd.hu
Sat Apr 9 21:34:53 EEST 2022



On Sun, 10 Apr 2022, TADANO Tokumei wrote:

> This patch add to parse descriptors on EIT packets.
> The patch is intended to set information to current program and/or
> A/V stream.
> On Japanese ISDB, some important / useful information is provided
> via EIT only.
> ref: ARIB STD B10 Table 6-1, Section 6.1, Part 2.

libavformat is a generic A-V demux library, therefore we probably don't 
want to add full or even partial EIT parsing capabilites to it. EIT is 
exported as a data stream, the API user can use that to get all EIT 
related information.

Regards,
Marton

>
> This patch only parse short event descriptor (0x4d) and set title
> information to the program. It may not be useful, but a good example
> of EIT descriptor common for DVB and ISDB.
>
> Note that it only parse EIT for actual and present TS stream as bllow:
> * Parse EIT table_id 0x4E (actual TS stream) only.
>  ref: DVB Blue Book A038 (EN 300 468) Table 2, Section 5.1.3.
> * Parse section number 0x00 only.
>  Section number 0x00 is present event.
>  Section number 0x01 is following (i.e., not for present stream).
>  Section number 0x02 or later may contain event for present stream,
>  but it is hard to distinguish and rarely sent.
>  ref: DVB-SI Guidelines (TS 101 211) Section 4.1.4.1.
> * Find a program associated to the EIT in already initialized
>  AVProgram and Program structures.
>  If no program found, abort to parse the EIT.
>
> Since EIT packets may be sent several times for the same program,
> add 'eit_version' in Program structure and ignore EITs with the
> same version as previously parsed one.
>
> There is a warning: "variable 'language' set but not used" at
> compilation. It should be resolved by later patches.
>
> An sample DVB TS file is found at:
>  https://streams.videolan.org/streams/ts/Teletext/TELETEXTO.ts
> After aplying this patch, ffprobe TELETEXTO.ts shows tile as:
>  Program 340
>    Metadata:
>      title           : NAVY : INVESTIGACIÓN CRIMINAL
>
> Many sample ISDB TS files are found at:
>  https://streams.videolan.org/streams/ts/ARIB/japan/
> Most of TS files show their title by ffprobe, but unrecognizable.
> It is due to encoding problem of text string.
> It should be also resolved by future patches.
>
> Signed-off-by: TADANO Tokumei <aimingoff at pc.nifty.jp>
> ---
> libavformat/mpegts.c | 129 ++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 127 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
> index 49f7735123..8417d71fb3 100644
> --- a/libavformat/mpegts.c
> +++ b/libavformat/mpegts.c
> @@ -123,6 +123,8 @@ struct Program {
>
>     /** have we found pmt for this program */
>     int pmt_found;
> +
> +    int eit_version;
> };
> 
> struct MpegTSContext {
> @@ -304,6 +306,7 @@ static void clear_program(struct Program *p)
>     p->nb_pids = 0;
>     p->nb_streams = 0;
>     p->pmt_found = 0;
> +    p->eit_version = -1;
> }
> 
> static void clear_programs(MpegTSContext *ts)
> @@ -2616,8 +2619,12 @@ 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;
> +    const uint8_t *p, *p_end, *desc_list_end, *desc_end;
>     SectionHeader h1, *h = &h1;
> +    AVProgram *program;
> +    struct Program *prg;
> +    int desc_len;
> +    char language[252];
>
>     /*
>      * Sometimes we receive EPG packets but SDT table do not have
> @@ -2645,6 +2652,7 @@ static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
>         return;
>
>     av_log(ts->stream, AV_LOG_TRACE, "EIT: tid received = %.02x\n", h->tid);
> +    hex_dump_debug(ts->stream, section, section_len);
>
>     /**
>      * Service_id 0xFFFF is reserved, it indicates that the current EIT table
> @@ -2664,7 +2672,124 @@ static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
>
>     new_data_packet(section, section_len, ts->pkt);
>     ts->pkt->stream_index = ts->epg_stream->index;
> -    ts->stop_parse = 1;
> +
> +    /* parse present event of actual TS stream only */
> +    if (h->tid != EIT_TID)
> +        return;
> +    if (!h->current_next)
> +        return;
> +    if (ts->skip_changes)
> +        return;
> +
> +    av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d\n",
> +           h->id, h->sec_num, h->last_sec_num, h->version);
> +
> +    /* DVB-SI Guidelines (TS 101 211) 4.1.4.1 */
> +    /* 0x00 indicates present event, 0x01 indicates following event */
> +    /* 0x02 and after is optional */
> +    if (h->sec_num > 0)
> +        return;
> +
> +    program = NULL;
> +    for (int i = 0; i < ts->stream->nb_programs; i++)
> +        if (ts->stream->programs[i]->id == h->id)
> +            program = ts->stream->programs[i];
> +    if (!program || program->nb_stream_indexes <= 0)
> +        return;
> +
> +    prg = get_program(ts, h->id);
> +    if (!prg)
> +        return;
> +    if (h->version == prg->eit_version)
> +        return;
> +    prg->eit_version = h->version;
> +
> +    /* skip ts_id, original_network_id, last_section_no, last_table_id */
> +    if (p + 6 > p_end)
> +        return;
> +    p += 6;
> +
> +    for (;;) {
> +        int eid, val;
> +
> +        eid = get16(&p, p_end);
> +        if (eid < 0)
> +            break;
> +        {
> +            int hh, mm, ss, d_hh, d_mm, d_ss, running_status;
> +            val = get16(&p, p_end); /* Date */
> +            if (val < 0)
> +                break;
> +            hh = get8(&p, p_end);
> +            if (hh < 0)
> +                break;
> +            mm = get8(&p, p_end);
> +            if (mm < 0)
> +                break;
> +            ss = get8(&p, p_end);
> +            if (ss < 0)
> +                break;
> +            d_hh = get8(&p, p_end);
> +            if (d_hh < 0)
> +                break;
> +            d_mm = get8(&p, p_end);
> +            if (d_mm < 0)
> +                break;
> +            d_ss = get8(&p, p_end);
> +            if (d_ss < 0)
> +                break;
> +            desc_len = get16(&p, p_end);
> +            if (desc_len < 0)
> +                break;
> +            running_status = (desc_len & 0xe000) >> 5;
> +            av_log(ts->stream, AV_LOG_TRACE,
> +                   "eid=0x%04x start %02x:%02x:%02x duration %02x:%02x:%02x running_status=%d\n",
> +                   eid, hh, mm, ss, d_hh, d_mm, d_ss, running_status);
> +        }
> +        desc_len &= 0x0fff;
> +        desc_list_end = p + desc_len;
> +        if (desc_list_end > p_end)
> +            break;
> +
> +        for (;;) {
> +            int desc_tag;
> +
> +            desc_tag = get8(&p, desc_list_end);
> +            if (desc_tag < 0)
> +                break;
> +            desc_len = get8(&p, desc_list_end);
> +            desc_end = p + desc_len;
> +            if (desc_len < 0 || desc_end > desc_list_end)
> +                break;
> +
> +            av_log(ts->stream, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n",
> +                   desc_tag, desc_len);
> +
> +            switch (desc_tag) {
> +            case 0x4d:  /* short event descriptor */
> +                {
> +                    char *txt;
> +
> +                    if (desc_len < 3)
> +                        break;
> +                    language[0] = get8(&p, desc_end);
> +                    language[1] = get8(&p, desc_end);
> +                    language[2] = get8(&p, desc_end);
> +                    language[3] = '\0';
> +                    txt = getstr8(&p, desc_end);
> +                    if (!txt)
> +                        break;
> +                    av_dict_set(&program->metadata, "title", txt, 0);
> +                    av_free(txt);
> +                }
> +                break;
> +            default:
> +                break;
> +            }
> +            p = desc_end;
> +        }
> +        p = desc_list_end;
> +    }
> }
> 
> static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
> -- 
> 2.30.2
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list