xref: /OK3568_Linux_fs/kernel/drivers/media/test-drivers/vidtv/vidtv_ts.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * The Virtual DVB test driver serves as a reference DVB driver and helps
4*4882a593Smuzhiyun  * validate the existing APIs in the media subsystem. It can also aid
5*4882a593Smuzhiyun  * developers working on userspace applications.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2020 Daniel W. S. Almeida
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/math64.h>
13*4882a593Smuzhiyun #include <linux/printk.h>
14*4882a593Smuzhiyun #include <linux/ratelimit.h>
15*4882a593Smuzhiyun #include <linux/types.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "vidtv_common.h"
18*4882a593Smuzhiyun #include "vidtv_ts.h"
19*4882a593Smuzhiyun 
vidtv_ts_write_pcr_bits(u8 * to,u32 to_offset,u64 pcr)20*4882a593Smuzhiyun static u32 vidtv_ts_write_pcr_bits(u8 *to, u32 to_offset, u64 pcr)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	/* Exact same from ffmpeg. PCR is a counter driven by a 27Mhz clock */
23*4882a593Smuzhiyun 	u64 div;
24*4882a593Smuzhiyun 	u64 rem;
25*4882a593Smuzhiyun 	u8 *buf = to + to_offset;
26*4882a593Smuzhiyun 	u64 pcr_low;
27*4882a593Smuzhiyun 	u64 pcr_high;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	div = div64_u64_rem(pcr, 300, &rem);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	pcr_low = rem; /* pcr_low = pcr % 300 */
32*4882a593Smuzhiyun 	pcr_high = div; /* pcr_high = pcr / 300 */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	*buf++ = pcr_high >> 25;
35*4882a593Smuzhiyun 	*buf++ = pcr_high >> 17;
36*4882a593Smuzhiyun 	*buf++ = pcr_high >>  9;
37*4882a593Smuzhiyun 	*buf++ = pcr_high >>  1;
38*4882a593Smuzhiyun 	*buf++ = pcr_high <<  7 | pcr_low >> 8 | 0x7e;
39*4882a593Smuzhiyun 	*buf++ = pcr_low;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	return 6;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun 
vidtv_ts_inc_cc(u8 * continuity_counter)44*4882a593Smuzhiyun void vidtv_ts_inc_cc(u8 *continuity_counter)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	++*continuity_counter;
47*4882a593Smuzhiyun 	if (*continuity_counter > TS_CC_MAX_VAL)
48*4882a593Smuzhiyun 		*continuity_counter = 0;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
vidtv_ts_null_write_into(struct null_packet_write_args args)51*4882a593Smuzhiyun u32 vidtv_ts_null_write_into(struct null_packet_write_args args)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	u32 nbytes = 0;
54*4882a593Smuzhiyun 	struct vidtv_mpeg_ts ts_header = {};
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	ts_header.sync_byte          = TS_SYNC_BYTE;
57*4882a593Smuzhiyun 	ts_header.bitfield           = cpu_to_be16(TS_NULL_PACKET_PID);
58*4882a593Smuzhiyun 	ts_header.payload            = 1;
59*4882a593Smuzhiyun 	ts_header.continuity_counter = *args.continuity_counter;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	/* copy TS header */
62*4882a593Smuzhiyun 	nbytes += vidtv_memcpy(args.dest_buf,
63*4882a593Smuzhiyun 			       args.dest_offset + nbytes,
64*4882a593Smuzhiyun 			       args.buf_sz,
65*4882a593Smuzhiyun 			       &ts_header,
66*4882a593Smuzhiyun 			       sizeof(ts_header));
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	vidtv_ts_inc_cc(args.continuity_counter);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* fill the rest with empty data */
71*4882a593Smuzhiyun 	nbytes += vidtv_memset(args.dest_buf,
72*4882a593Smuzhiyun 			       args.dest_offset + nbytes,
73*4882a593Smuzhiyun 			       args.buf_sz,
74*4882a593Smuzhiyun 			       TS_FILL_BYTE,
75*4882a593Smuzhiyun 			       TS_PACKET_LEN - nbytes);
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	/* we should have written exactly _one_ 188byte packet */
78*4882a593Smuzhiyun 	if (nbytes != TS_PACKET_LEN)
79*4882a593Smuzhiyun 		pr_warn_ratelimited("Expected exactly %d bytes, got %d\n",
80*4882a593Smuzhiyun 				    TS_PACKET_LEN,
81*4882a593Smuzhiyun 				    nbytes);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return nbytes;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
vidtv_ts_pcr_write_into(struct pcr_write_args args)86*4882a593Smuzhiyun u32 vidtv_ts_pcr_write_into(struct pcr_write_args args)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	u32 nbytes = 0;
89*4882a593Smuzhiyun 	struct vidtv_mpeg_ts ts_header = {};
90*4882a593Smuzhiyun 	struct vidtv_mpeg_ts_adaption ts_adap = {};
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	ts_header.sync_byte     = TS_SYNC_BYTE;
93*4882a593Smuzhiyun 	ts_header.bitfield      = cpu_to_be16(args.pid);
94*4882a593Smuzhiyun 	ts_header.scrambling    = 0;
95*4882a593Smuzhiyun 	/* cc is not incremented, but it is needed. see 13818-1 clause 2.4.3.3 */
96*4882a593Smuzhiyun 	ts_header.continuity_counter = *args.continuity_counter;
97*4882a593Smuzhiyun 	ts_header.payload            = 0;
98*4882a593Smuzhiyun 	ts_header.adaptation_field   = 1;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	/* 13818-1 clause 2.4.3.5 */
101*4882a593Smuzhiyun 	ts_adap.length = 183;
102*4882a593Smuzhiyun 	ts_adap.PCR    = 1;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	/* copy TS header */
105*4882a593Smuzhiyun 	nbytes += vidtv_memcpy(args.dest_buf,
106*4882a593Smuzhiyun 			       args.dest_offset + nbytes,
107*4882a593Smuzhiyun 			       args.buf_sz,
108*4882a593Smuzhiyun 			       &ts_header,
109*4882a593Smuzhiyun 			       sizeof(ts_header));
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* write the adap after the TS header */
112*4882a593Smuzhiyun 	nbytes += vidtv_memcpy(args.dest_buf,
113*4882a593Smuzhiyun 			       args.dest_offset + nbytes,
114*4882a593Smuzhiyun 			       args.buf_sz,
115*4882a593Smuzhiyun 			       &ts_adap,
116*4882a593Smuzhiyun 			       sizeof(ts_adap));
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* write the PCR optional */
119*4882a593Smuzhiyun 	nbytes += vidtv_ts_write_pcr_bits(args.dest_buf,
120*4882a593Smuzhiyun 					  args.dest_offset + nbytes,
121*4882a593Smuzhiyun 					  args.pcr);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	nbytes += vidtv_memset(args.dest_buf,
124*4882a593Smuzhiyun 			       args.dest_offset + nbytes,
125*4882a593Smuzhiyun 			       args.buf_sz,
126*4882a593Smuzhiyun 			       TS_FILL_BYTE,
127*4882a593Smuzhiyun 			       TS_PACKET_LEN - nbytes);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	/* we should have written exactly _one_ 188byte packet */
130*4882a593Smuzhiyun 	if (nbytes != TS_PACKET_LEN)
131*4882a593Smuzhiyun 		pr_warn_ratelimited("Expected exactly %d bytes, got %d\n",
132*4882a593Smuzhiyun 				    TS_PACKET_LEN,
133*4882a593Smuzhiyun 				    nbytes);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	return nbytes;
136*4882a593Smuzhiyun }
137