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

media: vidtv: psi: add a Network Information Table (NIT)



Add a Network Information Table (NIT) as specified in ETSI EN 300 468.

This table conveys information relating to the physical organization of
the multiplexes carried via a given network and the characteristics of
the network itself.

It is conveyed in the output of vidtv as packets with TS PID of 0x0010

[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 dd6dbe8d
Loading
Loading
Loading
Loading
+3 −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 3 PSI tables: PAT, PMT and
	SDT.
	Currently vidtv supports working with 4 PSI tables: PAT, PMT,
	SDT and NIT.

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

+4 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
//#define MUX_BUF_MIN_SZ
#define TUNER_DEFAULT_ADDR 0x68
#define DEMOD_DEFAULT_ADDR 0x60
#define VIDTV_DEFAULT_NETWORK_ID 0x744
#define VIDTV_DEFAULT_NETWORK_NAME "LinuxTV.org"

/* LNBf fake parameters: ranges used by an Universal (extended) European LNBf */
#define LNB_CUT_FREQUENCY	11700000
@@ -177,6 +179,8 @@ static int vidtv_start_streaming(struct vidtv_dvb *dvb)
	mux_args.si_period_usecs             = si_period_msec * 1000;
	mux_args.pcr_pid                     = pcr_pid;
	mux_args.transport_stream_id         = VIDTV_DEFAULT_TS_ID;
	mux_args.network_id                  = VIDTV_DEFAULT_NETWORK_ID,
	mux_args.network_name                = VIDTV_DEFAULT_NETWORK_NAME,
	mux_args.priv                        = dvb;

	dvb->streaming = true;
+59 −0
Original line number Diff line number Diff line
@@ -246,10 +246,57 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
	}
}

static struct vidtv_psi_desc_service_list_entry
*vidtv_channel_build_service_list(struct vidtv_psi_table_sdt_service *s)
{
	struct vidtv_psi_desc_service_list_entry *curr_e = NULL;
	struct vidtv_psi_desc_service_list_entry *head_e = NULL;
	struct vidtv_psi_desc_service_list_entry *prev_e = NULL;
	struct vidtv_psi_desc *desc = s->descriptor;
	struct vidtv_psi_desc_service *s_desc;

	while (s) {
		while (desc) {
			if (s->descriptor->type != SERVICE_DESCRIPTOR)
				goto next_desc;

			s_desc = (struct vidtv_psi_desc_service *)desc;

			curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL);
			curr_e->service_id = s->service_id;
			curr_e->service_type = s_desc->service_type;

			if (!head_e)
				head_e = curr_e;
			if (prev_e)
				prev_e->next = curr_e;

			prev_e = curr_e;

next_desc:
			desc = desc->next;
		}
		s = s->next;
	}
	return head_e;
}

static void vidtv_channel_destroy_service_list(struct vidtv_psi_desc_service_list_entry *e)
{
	struct vidtv_psi_desc_service_list_entry *tmp;

	while (e) {
		tmp = e;
		e = e->next;
		kfree(tmp);
	}
}

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;

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

@@ -258,6 +305,15 @@ 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);

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

	/* use these descriptors to build the NIT */
	m->si.nit = vidtv_psi_nit_table_init(m->network_id,
					     m->transport_stream_id,
					     m->network_name,
					     service_list);

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

@@ -269,6 +325,8 @@ void vidtv_channel_si_init(struct vidtv_mux *m)
	vidtv_channel_pmt_match_sections(m->channels,
					 m->si.pmt_secs,
					 m->si.pat->programs);

	vidtv_channel_destroy_service_list(service_list);
}

void vidtv_channel_si_destroy(struct vidtv_mux *m)
@@ -283,6 +341,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);
}

void vidtv_channels_init(struct vidtv_mux *m)
+16 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m)
	vidtv_mux_create_pid_ctx_once(m, VIDTV_PAT_PID);
	/* push the SDT pid ctx */
	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);

	/* add a ctx for all PMT sections */
	while (p) {
@@ -117,10 +119,12 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m)
	struct vidtv_mux_pid_ctx *pat_ctx;
	struct vidtv_mux_pid_ctx *pmt_ctx;
	struct vidtv_mux_pid_ctx *sdt_ctx;
	struct vidtv_mux_pid_ctx *nit_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 = {};

	u32 nbytes; /* the number of bytes written by this function */
	u16 pmt_pid;
@@ -128,6 +132,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);

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

	m->mux_buf_offset += vidtv_psi_sdt_write_into(sdt_args);

	nit_args.buf                = m->mux_buf;
	nit_args.offset             = m->mux_buf_offset;
	nit_args.nit                = m->si.nit;
	nit_args.buf_sz             = m->mux_buf_sz;
	nit_args.continuity_counter = &nit_ctx->cc;

	m->mux_buf_offset += vidtv_psi_nit_write_into(nit_args);

	nbytes = m->mux_buf_offset - initial_offset;

	m->num_streamed_si++;
@@ -446,6 +459,8 @@ struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe,
	m->pcr_pid = args.pcr_pid;
	m->transport_stream_id = args.transport_stream_id;
	m->priv = args.priv;
	m->network_id = args.network_id;
	m->network_name = kstrdup(args.network_name, GFP_KERNEL);
	m->timing.current_jiffies = get_jiffies_64();

	if (args.channels)
@@ -469,6 +484,7 @@ void vidtv_mux_destroy(struct vidtv_mux *m)
	vidtv_mux_pid_ctx_destroy(m);
	vidtv_channel_si_destroy(m);
	vidtv_channels_destroy(m);
	kfree(m->network_name);
	vfree(m->mux_buf);
	kfree(m);
}
+9 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct vidtv_mux_si {
	struct vidtv_psi_table_pat *pat;
	struct vidtv_psi_table_pmt **pmt_secs; /* the PMT sections */
	struct vidtv_psi_table_sdt *sdt;
	struct vidtv_psi_table_nit *nit;
};

/**
@@ -99,6 +100,8 @@ struct vidtv_mux_pid_ctx {
 * @pcr_pid: The TS PID used for the PSI packets. All channels will share the
 * same PCR.
 * @transport_stream_id: The transport stream ID
 * @network_id: The network ID
 * @network_name: The network name
 * @priv: Private data.
 */
struct vidtv_mux {
@@ -128,6 +131,8 @@ struct vidtv_mux {

	u16 pcr_pid;
	u16 transport_stream_id;
	u16 network_id;
	char *network_name;
	void *priv;
};

@@ -142,6 +147,8 @@ struct vidtv_mux {
 * same PCR.
 * @transport_stream_id: The transport stream ID
 * @channels: an optional list of channels to use
 * @network_id: The network ID
 * @network_name: The network name
 * @priv: Private data.
 */
struct vidtv_mux_init_args {
@@ -153,6 +160,8 @@ struct vidtv_mux_init_args {
	u16 pcr_pid;
	u16 transport_stream_id;
	struct vidtv_channel *channels;
	u16 network_id;
	char *network_name;
	void *priv;
};

Loading