Commit 7a7899f6 authored by Daniel W. S. Almeida's avatar Daniel W. S. Almeida Committed by Mauro Carvalho Chehab
Browse files

media: vidtv: psi: Implement an Event Information Table (EIT)



Implement an Event Information Table (EIT) as per EN 300 468
5.2.4.

The EIT provides information in chronological order regarding
the events contained within each service.

For now only present event information is supported.

[mchehab+huawei@kernel.org: removed an extra blank line]
Signed-off-by: default avatarDaniel W. S. Almeida <dwlsalmeida@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent c2f78f0c
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -149,11 +149,11 @@ vidtv_psi.[ch]
	Because the generator is implemented in a separate file, it can be
	reused elsewhere in the media subsystem.

	Currently vidtv supports working with 4 PSI tables: PAT, PMT,
	SDT and NIT.
	Currently vidtv supports working with 5 PSI tables: PAT, PMT,
	SDT, NIT and EIT.

	The specification for PAT and PMT can be found in *ISO 13818-1:
	Systems*, while the specification for the SDT, NIT can be found in *ETSI
	Systems*, while the specification for the SDT, NIT, EIT can be found in *ETSI
	EN 300 468: Specification for Service Information (SI) in DVB
	systems*.

@@ -197,6 +197,8 @@ vidtv_channel.[ch]

	#. Their programs will be concatenated to populate the PAT

	#. Their events will be concatenated to populate the EIT

	#. For each program in the PAT, a PMT section will be created

	#. The PMT section for a channel will be assigned its streams.
+69 −2
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
 * When vidtv boots, it will create some hardcoded channels.
 * Their services will be concatenated to populate the SDT.
 * Their programs will be concatenated to populate the PAT
 * Their events will be concatenated to populate the EIT
 * For each program in the PAT, a PMT section will be created
 * The PMT section for a channel will be assigned its streams.
 * Every stream will have its corresponding encoder polled to produce TS packets
@@ -59,13 +60,17 @@ struct vidtv_channel

	char *name = ENCODING_ISO8859_15 "Beethoven";
	char *provider = ENCODING_ISO8859_15 "LinuxTV.org";
	char *iso_language_code = ENCODING_ISO8859_15 "eng";
	char *event_name = ENCODING_ISO8859_15 "Beethoven Music";
	char *event_text = ENCODING_ISO8859_15 "Beethoven's 5th Symphony";
	const u16 s302m_beethoven_event_id  = 1;

	struct vidtv_channel *s302m = kzalloc(sizeof(*s302m), GFP_KERNEL);
	struct vidtv_s302m_encoder_init_args encoder_args = {};

	s302m->name = kstrdup(name, GFP_KERNEL);

	s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id);
	s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id, false, true);

	s302m->service->descriptor = (struct vidtv_psi_desc *)
				     vidtv_psi_service_desc_init(NULL,
@@ -94,6 +99,13 @@ struct vidtv_channel

	s302m->encoders = vidtv_s302m_encoder_init(encoder_args);

	s302m->events = vidtv_psi_eit_event_init(NULL, s302m_beethoven_event_id);
	s302m->events->descriptor = (struct vidtv_psi_desc *)
				    vidtv_psi_short_event_desc_init(NULL,
								    iso_language_code,
								    event_name,
								    event_text);

	if (head) {
		while (head->next)
			head = head->next;
@@ -104,6 +116,48 @@ struct vidtv_channel
	return s302m;
}

static struct vidtv_psi_table_eit_event
*vidtv_channel_eit_event_cat_into_new(struct vidtv_mux *m)
{
	/* Concatenate the events */
	const struct vidtv_channel *cur_chnl = m->channels;

	struct vidtv_psi_table_eit_event *curr = NULL;
	struct vidtv_psi_table_eit_event *head = NULL;
	struct vidtv_psi_table_eit_event *tail = NULL;

	struct vidtv_psi_desc *desc = NULL;
	u16 event_id;

	if (!cur_chnl)
		return NULL;

	while (cur_chnl) {
		curr = cur_chnl->events;

		if (!curr)
			dev_warn_ratelimited(m->dev,
					     "No events found for channel %s\n", cur_chnl->name);

		while (curr) {
			event_id = be16_to_cpu(curr->event_id);
			tail = vidtv_psi_eit_event_init(tail, event_id);

			desc = vidtv_psi_desc_clone(curr->descriptor);
			vidtv_psi_desc_assign(&tail->descriptor, desc);

			if (!head)
				head = tail;

			curr = curr->next;
		}

		cur_chnl = cur_chnl->next;
	}

	return head;
}

static struct vidtv_psi_table_sdt_service
*vidtv_channel_sdt_serv_cat_into_new(struct vidtv_mux *m)
{
@@ -129,7 +183,10 @@ static struct vidtv_psi_table_sdt_service

		while (curr) {
			service_id = be16_to_cpu(curr->service_id);
			tail = vidtv_psi_sdt_service_init(tail, service_id);
			tail = vidtv_psi_sdt_service_init(tail,
							  service_id,
							  curr->EIT_schedule,
							  curr->EIT_present_following);

			desc = vidtv_psi_desc_clone(curr->descriptor);
			vidtv_psi_desc_assign(&tail->descriptor, desc);
@@ -297,6 +354,7 @@ void vidtv_channel_si_init(struct vidtv_mux *m)
	struct vidtv_psi_table_pat_program *programs = NULL;
	struct vidtv_psi_table_sdt_service *services = NULL;
	struct vidtv_psi_desc_service_list_entry *service_list = NULL;
	struct vidtv_psi_table_eit_event *events = NULL;

	m->si.pat = vidtv_psi_pat_table_init(m->transport_stream_id);

@@ -305,6 +363,8 @@ void vidtv_channel_si_init(struct vidtv_mux *m)
	programs = vidtv_channel_pat_prog_cat_into_new(m);
	services = vidtv_channel_sdt_serv_cat_into_new(m);

	events = vidtv_channel_eit_event_cat_into_new(m);

	/* look for a service descriptor for every service */
	service_list = vidtv_channel_build_service_list(services);

@@ -314,12 +374,17 @@ void vidtv_channel_si_init(struct vidtv_mux *m)
					     m->network_name,
					     service_list);

	m->si.eit = vidtv_psi_eit_table_init(m->network_id, m->transport_stream_id);

	/* assemble all programs and assign to PAT */
	vidtv_psi_pat_program_assign(m->si.pat, programs);

	/* assemble all services and assign to SDT */
	vidtv_psi_sdt_service_assign(m->si.sdt, services);

	/* assemble all events and assign to EIT */
	vidtv_psi_eit_event_assign(m->si.eit, events);

	m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat, m->pcr_pid);

	vidtv_channel_pmt_match_sections(m->channels,
@@ -342,6 +407,7 @@ void vidtv_channel_si_destroy(struct vidtv_mux *m)
	kfree(m->si.pmt_secs);
	vidtv_psi_sdt_table_destroy(m->si.sdt);
	vidtv_psi_nit_table_destroy(m->si.nit);
	vidtv_psi_eit_table_destroy(m->si.eit);
}

void vidtv_channels_init(struct vidtv_mux *m)
@@ -361,6 +427,7 @@ void vidtv_channels_destroy(struct vidtv_mux *m)
		vidtv_psi_pat_program_destroy(curr->program);
		vidtv_psi_pmt_stream_destroy(curr->streams);
		vidtv_channel_encoder_destroy(curr->encoders);
		vidtv_psi_eit_event_destroy(curr->events);

		tmp = curr;
		curr = curr->next;
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
 * When vidtv boots, it will create some hardcoded channels.
 * Their services will be concatenated to populate the SDT.
 * Their programs will be concatenated to populate the PAT
 * Their events will be concatenated to populate the EIT
 * For each program in the PAT, a PMT section will be created
 * The PMT section for a channel will be assigned its streams.
 * Every stream will have its corresponding encoder polled to produce TS packets
@@ -44,6 +45,7 @@
 * Will be concatenated into the PAT.
 * @streams: A stream loop used to populate the PMT section for 'program'
 * @encoders: A encoder loop. There must be one encoder for each stream.
 * @events: Optional event information. This will feed into the EIT.
 * @next: Optionally chain this channel.
 */
struct vidtv_channel {
@@ -54,6 +56,7 @@ struct vidtv_channel {
	struct vidtv_psi_table_pat_program *program;
	struct vidtv_psi_table_pmt_stream *streams;
	struct vidtv_encoder *encoders;
	struct vidtv_psi_table_eit_event *events;
	struct vidtv_channel *next;
};

+13 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m)
	vidtv_mux_create_pid_ctx_once(m, VIDTV_SDT_PID);
	/* push the NIT pid ctx */
	vidtv_mux_create_pid_ctx_once(m, VIDTV_NIT_PID);
	/* push the EIT pid ctx */
	vidtv_mux_create_pid_ctx_once(m, VIDTV_EIT_PID);

	/* add a ctx for all PMT sections */
	while (p) {
@@ -120,11 +122,13 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m)
	struct vidtv_mux_pid_ctx *pmt_ctx;
	struct vidtv_mux_pid_ctx *sdt_ctx;
	struct vidtv_mux_pid_ctx *nit_ctx;
	struct vidtv_mux_pid_ctx *eit_ctx;

	struct vidtv_psi_pat_write_args pat_args = {};
	struct vidtv_psi_pmt_write_args pmt_args = {};
	struct vidtv_psi_sdt_write_args sdt_args = {};
	struct vidtv_psi_nit_write_args nit_args = {};
	struct vidtv_psi_eit_write_args eit_args = {};

	u32 nbytes; /* the number of bytes written by this function */
	u16 pmt_pid;
@@ -133,6 +137,7 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m)
	pat_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_PAT_PID);
	sdt_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_SDT_PID);
	nit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_NIT_PID);
	eit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_EIT_PID);

	pat_args.buf                = m->mux_buf;
	pat_args.offset             = m->mux_buf_offset;
@@ -182,6 +187,14 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m)

	m->mux_buf_offset += vidtv_psi_nit_write_into(nit_args);

	eit_args.buf                = m->mux_buf;
	eit_args.offset             = m->mux_buf_offset;
	eit_args.eit                = m->si.eit;
	eit_args.buf_sz             = m->mux_buf_sz;
	eit_args.continuity_counter = &eit_ctx->cc;

	m->mux_buf_offset += vidtv_psi_eit_write_into(eit_args);

	nbytes = m->mux_buf_offset - initial_offset;

	m->num_streamed_si++;
+2 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ struct vidtv_mux_timing {
 * @pat: The PAT in use by the muxer.
 * @pmt_secs: The PMT sections in use by the muxer. One for each program in the PAT.
 * @sdt: The SDT in use by the muxer.
 * @eit: the EIT in use by the muxer.
 */
struct vidtv_mux_si {
	/* the SI tables */
@@ -65,6 +66,7 @@ struct vidtv_mux_si {
	struct vidtv_psi_table_pmt **pmt_secs; /* the PMT sections */
	struct vidtv_psi_table_sdt *sdt;
	struct vidtv_psi_table_nit *nit;
	struct vidtv_psi_table_eit *eit;
};

/**
Loading