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

TADANO Tokumei aimingoff at pc.nifty.jp
Sun Apr 10 10:49:53 EEST 2022


On 2022/04/10 3:34, Marton Balint wrote:
> 
> 
> 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.

Thanks for your comments.

I have a plan to add EIT parsing capabilities for Japanese ISDB:

* dual-monoral audio stream: Audio component descriptor (0xC4)
   libavcodec already has capability to handle Japanese dual-mono audio.
   (libavcodec/packet.h, libavcodec/avpacket.c, libavcodec/aacdec_template.c, ...)
   However, the information of dual-mono mode is provided via only the EIT descriptor.
   Thus, most of application treat the dual-mono audio stream as stereo.
   ref: ARIB STD-B10 Part 2, Section 6.2.26
   There is no standard way to pass the dual-mono audio information.
   My idea is to add side data of AV_PKT_DATA_JP_DUALMONO to the audio stream
   (Similar way to DOVI).
   To play the dual-mono audio correctly, application have to set (or pass)
   AV_PKT_DATA_JP_DUALMONO side data into each audio packet if the stream has
   AV_PKT_DATA_JP_DUALMONO side data. (The stream's side data indicates default
   mode, and packet's side data should be set user selected mode)

* Language information of ARIB Caption: Data content(s) descriptor (0xC7)
   On DVB, similar information is provided by Subtitling descriptor (0x59).
   But on ISDB, such information is provided by this EIT descriptor.
   ref: ARIB STD-B10 Part 2, Section 6.2.28 and Annex J
        ARIB STD-B24 Fascicle 1 Part 3 Chapter 9 Table 9-17

On DVB, most important information for A/V stream are provided by PMT.
But on ISDB, some important information are lacked without parsing EIT.

Regards,
TADANO

> 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".
> _______________________________________________
> 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