1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Vidtv serves as a reference DVB driver and helps validate the existing APIs |
4 | * in the media subsystem. It can also aid developers working on userspace |
5 | * applications. |
6 | * |
7 | * This file contains the muxer logic for TS packets from different |
8 | * elementary streams. |
9 | * |
10 | * Loosely based on libavcodec/mpegtsenc.c |
11 | * |
12 | * Copyright (C) 2020 Daniel W. S. Almeida |
13 | */ |
14 | |
15 | #ifndef VIDTV_MUX_H |
16 | #define VIDTV_MUX_H |
17 | |
18 | #include <linux/hashtable.h> |
19 | #include <linux/types.h> |
20 | #include <linux/workqueue.h> |
21 | |
22 | #include <media/dvb_frontend.h> |
23 | |
24 | #include "vidtv_psi.h" |
25 | |
26 | /** |
27 | * struct vidtv_mux_timing - Timing related information |
28 | * |
29 | * This is used to decide when PCR or PSI packets should be sent. This will also |
30 | * provide storage for the clock, which is used to compute the value for the PCR. |
31 | * |
32 | * @start_jiffies: The value of 'jiffies' when we started the mux thread. |
33 | * @current_jiffies: The value of 'jiffies' for the current iteration. |
34 | * @past_jiffies: The value of 'jiffies' for the past iteration. |
35 | * @clk: A 27Mhz clock from which we will drive the PCR. Updated proportionally |
36 | * on every iteration. |
37 | * @pcr_period_usecs: How often we should send PCR packets. |
38 | * @si_period_usecs: How often we should send PSI packets. |
39 | */ |
40 | struct vidtv_mux_timing { |
41 | u64 start_jiffies; |
42 | u64 current_jiffies; |
43 | u64 past_jiffies; |
44 | |
45 | u64 clk; |
46 | |
47 | u64 pcr_period_usecs; |
48 | u64 si_period_usecs; |
49 | }; |
50 | |
51 | /** |
52 | * struct vidtv_mux_si - Store the PSI context. |
53 | * |
54 | * This is used to store the PAT, PMT sections and SDT in use by the muxer. |
55 | * |
56 | * The muxer acquire these by looking into the hardcoded channels in |
57 | * vidtv_channel and then periodically sends the TS packets for them> |
58 | * |
59 | * @pat: The PAT in use by the muxer. |
60 | * @pmt_secs: The PMT sections in use by the muxer. One for each program in the PAT. |
61 | * @sdt: The SDT in use by the muxer. |
62 | * @nit: The NIT in use by the muxer. |
63 | * @eit: the EIT in use by the muxer. |
64 | */ |
65 | struct vidtv_mux_si { |
66 | /* the SI tables */ |
67 | struct vidtv_psi_table_pat *pat; |
68 | struct vidtv_psi_table_pmt **pmt_secs; /* the PMT sections */ |
69 | struct vidtv_psi_table_sdt *sdt; |
70 | struct vidtv_psi_table_nit *nit; |
71 | struct vidtv_psi_table_eit *eit; |
72 | }; |
73 | |
74 | /** |
75 | * struct vidtv_mux_pid_ctx - Store the context for a given TS PID. |
76 | * @pid: The TS PID. |
77 | * @cc: The continuity counter for this PID. It is incremented on every TS |
78 | * pack and it will wrap around at 0xf0. If the decoder notices a sudden jump in |
79 | * this counter this will trigger a discontinuity state. |
80 | * @h: This is embedded in a hash table, mapping pid -> vidtv_mux_pid_ctx |
81 | */ |
82 | struct vidtv_mux_pid_ctx { |
83 | u16 pid; |
84 | u8 cc; /* continuity counter */ |
85 | struct hlist_node h; |
86 | }; |
87 | |
88 | /** |
89 | * struct vidtv_mux - A muxer abstraction loosely based in libavcodec/mpegtsenc.c |
90 | * @fe: The frontend structure allocated by the muxer. |
91 | * @dev: pointer to struct device. |
92 | * @timing: Keeps track of timing related information. |
93 | * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes. |
94 | * @pid_ctx: A hash table to keep track of per-PID metadata. |
95 | * @on_new_packets_available_cb: A callback to inform of new TS packets ready. |
96 | * @mux_buf: A pointer to a buffer for this muxer. TS packets are stored there |
97 | * and then passed on to the bridge driver. |
98 | * @mux_buf_sz: The size for 'mux_buf'. |
99 | * @mux_buf_offset: The current offset into 'mux_buf'. |
100 | * @channels: The channels associated with this muxer. |
101 | * @si: Keeps track of the PSI context. |
102 | * @num_streamed_pcr: Number of PCR packets streamed. |
103 | * @num_streamed_si: The number of PSI packets streamed. |
104 | * @mpeg_thread: Thread responsible for the muxer loop. |
105 | * @streaming: whether 'mpeg_thread' is running. |
106 | * @pcr_pid: The TS PID used for the PSI packets. All channels will share the |
107 | * same PCR. |
108 | * @transport_stream_id: The transport stream ID |
109 | * @network_id: The network ID |
110 | * @network_name: The network name |
111 | * @priv: Private data. |
112 | */ |
113 | struct vidtv_mux { |
114 | struct dvb_frontend *fe; |
115 | struct device *dev; |
116 | |
117 | struct vidtv_mux_timing timing; |
118 | |
119 | u32 mux_rate_kbytes_sec; |
120 | |
121 | DECLARE_HASHTABLE(pid_ctx, 3); |
122 | |
123 | void (*on_new_packets_available_cb)(void *priv, u8 *buf, u32 npackets); |
124 | |
125 | u8 *mux_buf; |
126 | u32 mux_buf_sz; |
127 | u32 mux_buf_offset; |
128 | |
129 | struct vidtv_channel *channels; |
130 | |
131 | struct vidtv_mux_si si; |
132 | u64 num_streamed_pcr; |
133 | u64 num_streamed_si; |
134 | |
135 | struct work_struct mpeg_thread; |
136 | bool streaming; |
137 | |
138 | u16 pcr_pid; |
139 | u16 transport_stream_id; |
140 | u16 network_id; |
141 | char *network_name; |
142 | void *priv; |
143 | }; |
144 | |
145 | /** |
146 | * struct vidtv_mux_init_args - Arguments used to inix the muxer. |
147 | * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes. |
148 | * @on_new_packets_available_cb: A callback to inform of new TS packets ready. |
149 | * @mux_buf_sz: The size for 'mux_buf'. |
150 | * @pcr_period_usecs: How often we should send PCR packets. |
151 | * @si_period_usecs: How often we should send PSI packets. |
152 | * @pcr_pid: The TS PID used for the PSI packets. All channels will share the |
153 | * same PCR. |
154 | * @transport_stream_id: The transport stream ID |
155 | * @channels: an optional list of channels to use |
156 | * @network_id: The network ID |
157 | * @network_name: The network name |
158 | * @priv: Private data. |
159 | */ |
160 | struct vidtv_mux_init_args { |
161 | u32 mux_rate_kbytes_sec; |
162 | void (*on_new_packets_available_cb)(void *priv, u8 *buf, u32 npackets); |
163 | u32 mux_buf_sz; |
164 | u64 pcr_period_usecs; |
165 | u64 si_period_usecs; |
166 | u16 pcr_pid; |
167 | u16 transport_stream_id; |
168 | struct vidtv_channel *channels; |
169 | u16 network_id; |
170 | char *network_name; |
171 | void *priv; |
172 | }; |
173 | |
174 | struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe, |
175 | struct device *dev, |
176 | struct vidtv_mux_init_args *args); |
177 | void vidtv_mux_destroy(struct vidtv_mux *m); |
178 | |
179 | void vidtv_mux_start_thread(struct vidtv_mux *m); |
180 | void vidtv_mux_stop_thread(struct vidtv_mux *m); |
181 | |
182 | #endif //VIDTV_MUX_H |
183 | |