[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