1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Vidtv serves as a reference DVB driver and helps validate the existing APIs
4*4882a593Smuzhiyun * in the media subsystem. It can also aid developers working on userspace
5*4882a593Smuzhiyun * applications.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This file contains the logic to translate the ES data for one access unit
8*4882a593Smuzhiyun * from an encoder into MPEG TS packets. It does so by first encapsulating it
9*4882a593Smuzhiyun * with a PES header and then splitting it into TS packets.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Copyright (C) 2020 Daniel W. S. Almeida
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <linux/types.h>
17*4882a593Smuzhiyun #include <linux/printk.h>
18*4882a593Smuzhiyun #include <linux/ratelimit.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "vidtv_pes.h"
21*4882a593Smuzhiyun #include "vidtv_common.h"
22*4882a593Smuzhiyun #include "vidtv_encoder.h"
23*4882a593Smuzhiyun #include "vidtv_ts.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define PRIVATE_STREAM_1_ID 0xbd /* private_stream_1. See SMPTE 302M-2007 p.6 */
26*4882a593Smuzhiyun #define PES_HEADER_MAX_STUFFING_BYTES 32
27*4882a593Smuzhiyun #define PES_TS_HEADER_MAX_STUFFING_BYTES 182
28*4882a593Smuzhiyun
vidtv_pes_op_get_len(bool send_pts,bool send_dts)29*4882a593Smuzhiyun static u32 vidtv_pes_op_get_len(bool send_pts, bool send_dts)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun u32 len = 0;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* the flags must always be sent */
34*4882a593Smuzhiyun len += sizeof(struct vidtv_pes_optional);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* From all optionals, we might send these for now */
37*4882a593Smuzhiyun if (send_pts && send_dts)
38*4882a593Smuzhiyun len += sizeof(struct vidtv_pes_optional_pts_dts);
39*4882a593Smuzhiyun else if (send_pts)
40*4882a593Smuzhiyun len += sizeof(struct vidtv_pes_optional_pts);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return len;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define SIZE_PCR (6 + sizeof(struct vidtv_mpeg_ts_adaption))
46*4882a593Smuzhiyun
vidtv_pes_h_get_len(bool send_pts,bool send_dts)47*4882a593Smuzhiyun static u32 vidtv_pes_h_get_len(bool send_pts, bool send_dts)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun u32 len = 0;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /* PES header length notwithstanding stuffing bytes */
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun len += sizeof(struct vidtv_mpeg_pes);
54*4882a593Smuzhiyun len += vidtv_pes_op_get_len(send_pts, send_dts);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun return len;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
vidtv_pes_write_header_stuffing(struct pes_header_write_args * args)59*4882a593Smuzhiyun static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args *args)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * This is a fixed 8-bit value equal to '0xFF' that can be inserted
63*4882a593Smuzhiyun * by the encoder, for example to meet the requirements of the channel.
64*4882a593Smuzhiyun * It is discarded by the decoder. No more than 32 stuffing bytes shall
65*4882a593Smuzhiyun * be present in one PES packet header.
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun if (args->n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) {
68*4882a593Smuzhiyun pr_warn_ratelimited("More than %d stuffing bytes in PES packet header\n",
69*4882a593Smuzhiyun PES_HEADER_MAX_STUFFING_BYTES);
70*4882a593Smuzhiyun args->n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun return vidtv_memset(args->dest_buf,
74*4882a593Smuzhiyun args->dest_offset,
75*4882a593Smuzhiyun args->dest_buf_sz,
76*4882a593Smuzhiyun TS_FILL_BYTE,
77*4882a593Smuzhiyun args->n_pes_h_s_bytes);
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
vidtv_pes_write_pts_dts(struct pes_header_write_args * args)80*4882a593Smuzhiyun static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args *args)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun u32 nbytes = 0; /* the number of bytes written by this function */
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun struct vidtv_pes_optional_pts pts = {};
85*4882a593Smuzhiyun struct vidtv_pes_optional_pts_dts pts_dts = {};
86*4882a593Smuzhiyun void *op = NULL;
87*4882a593Smuzhiyun size_t op_sz = 0;
88*4882a593Smuzhiyun u64 mask1;
89*4882a593Smuzhiyun u64 mask2;
90*4882a593Smuzhiyun u64 mask3;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (!args->send_pts && args->send_dts)
93*4882a593Smuzhiyun return 0;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun mask1 = GENMASK_ULL(32, 30);
96*4882a593Smuzhiyun mask2 = GENMASK_ULL(29, 15);
97*4882a593Smuzhiyun mask3 = GENMASK_ULL(14, 0);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* see ISO/IEC 13818-1 : 2000 p. 32 */
100*4882a593Smuzhiyun if (args->send_pts && args->send_dts) {
101*4882a593Smuzhiyun pts_dts.pts1 = (0x3 << 4) | ((args->pts & mask1) >> 29) | 0x1;
102*4882a593Smuzhiyun pts_dts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1);
103*4882a593Smuzhiyun pts_dts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun pts_dts.dts1 = (0x1 << 4) | ((args->dts & mask1) >> 29) | 0x1;
106*4882a593Smuzhiyun pts_dts.dts2 = cpu_to_be16(((args->dts & mask2) >> 14) | 0x1);
107*4882a593Smuzhiyun pts_dts.dts3 = cpu_to_be16(((args->dts & mask3) << 1) | 0x1);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun op = &pts_dts;
110*4882a593Smuzhiyun op_sz = sizeof(pts_dts);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun } else if (args->send_pts) {
113*4882a593Smuzhiyun pts.pts1 = (0x1 << 5) | ((args->pts & mask1) >> 29) | 0x1;
114*4882a593Smuzhiyun pts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1);
115*4882a593Smuzhiyun pts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun op = &pts;
118*4882a593Smuzhiyun op_sz = sizeof(pts);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* copy PTS/DTS optional */
122*4882a593Smuzhiyun nbytes += vidtv_memcpy(args->dest_buf,
123*4882a593Smuzhiyun args->dest_offset + nbytes,
124*4882a593Smuzhiyun args->dest_buf_sz,
125*4882a593Smuzhiyun op,
126*4882a593Smuzhiyun op_sz);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun return nbytes;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
vidtv_pes_write_h(struct pes_header_write_args * args)131*4882a593Smuzhiyun static u32 vidtv_pes_write_h(struct pes_header_write_args *args)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun u32 nbytes = 0; /* the number of bytes written by this function */
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun struct vidtv_mpeg_pes pes_header = {};
136*4882a593Smuzhiyun struct vidtv_pes_optional pes_optional = {};
137*4882a593Smuzhiyun struct pes_header_write_args pts_dts_args;
138*4882a593Smuzhiyun u32 stream_id = (args->encoder_id == S302M) ? PRIVATE_STREAM_1_ID : args->stream_id;
139*4882a593Smuzhiyun u16 pes_opt_bitfield = 0x01 << 15;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun pes_header.bitfield = cpu_to_be32((PES_START_CODE_PREFIX << 8) | stream_id);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun pes_header.length = cpu_to_be16(vidtv_pes_op_get_len(args->send_pts,
144*4882a593Smuzhiyun args->send_dts) +
145*4882a593Smuzhiyun args->access_unit_len);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (args->send_pts && args->send_dts)
148*4882a593Smuzhiyun pes_opt_bitfield |= (0x3 << 6);
149*4882a593Smuzhiyun else if (args->send_pts)
150*4882a593Smuzhiyun pes_opt_bitfield |= (0x1 << 7);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun pes_optional.bitfield = cpu_to_be16(pes_opt_bitfield);
153*4882a593Smuzhiyun pes_optional.length = vidtv_pes_op_get_len(args->send_pts, args->send_dts) +
154*4882a593Smuzhiyun args->n_pes_h_s_bytes -
155*4882a593Smuzhiyun sizeof(struct vidtv_pes_optional);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* copy header */
158*4882a593Smuzhiyun nbytes += vidtv_memcpy(args->dest_buf,
159*4882a593Smuzhiyun args->dest_offset + nbytes,
160*4882a593Smuzhiyun args->dest_buf_sz,
161*4882a593Smuzhiyun &pes_header,
162*4882a593Smuzhiyun sizeof(pes_header));
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* copy optional header bits */
165*4882a593Smuzhiyun nbytes += vidtv_memcpy(args->dest_buf,
166*4882a593Smuzhiyun args->dest_offset + nbytes,
167*4882a593Smuzhiyun args->dest_buf_sz,
168*4882a593Smuzhiyun &pes_optional,
169*4882a593Smuzhiyun sizeof(pes_optional));
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /* copy the timing information */
172*4882a593Smuzhiyun pts_dts_args = *args;
173*4882a593Smuzhiyun pts_dts_args.dest_offset = args->dest_offset + nbytes;
174*4882a593Smuzhiyun nbytes += vidtv_pes_write_pts_dts(&pts_dts_args);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* write any PES header stuffing */
177*4882a593Smuzhiyun nbytes += vidtv_pes_write_header_stuffing(args);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun return nbytes;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
vidtv_pes_write_pcr_bits(u8 * to,u32 to_offset,u64 pcr)182*4882a593Smuzhiyun static u32 vidtv_pes_write_pcr_bits(u8 *to, u32 to_offset, u64 pcr)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun /* Exact same from ffmpeg. PCR is a counter driven by a 27Mhz clock */
185*4882a593Smuzhiyun u64 div;
186*4882a593Smuzhiyun u64 rem;
187*4882a593Smuzhiyun u8 *buf = to + to_offset;
188*4882a593Smuzhiyun u64 pcr_low;
189*4882a593Smuzhiyun u64 pcr_high;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun div = div64_u64_rem(pcr, 300, &rem);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun pcr_low = rem; /* pcr_low = pcr % 300 */
194*4882a593Smuzhiyun pcr_high = div; /* pcr_high = pcr / 300 */
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun *buf++ = pcr_high >> 25;
197*4882a593Smuzhiyun *buf++ = pcr_high >> 17;
198*4882a593Smuzhiyun *buf++ = pcr_high >> 9;
199*4882a593Smuzhiyun *buf++ = pcr_high >> 1;
200*4882a593Smuzhiyun *buf++ = pcr_high << 7 | pcr_low >> 8 | 0x7e;
201*4882a593Smuzhiyun *buf++ = pcr_low;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return 6;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
vidtv_pes_write_stuffing(struct pes_ts_header_write_args * args,u32 dest_offset,bool need_pcr,u64 * last_pcr)206*4882a593Smuzhiyun static u32 vidtv_pes_write_stuffing(struct pes_ts_header_write_args *args,
207*4882a593Smuzhiyun u32 dest_offset, bool need_pcr,
208*4882a593Smuzhiyun u64 *last_pcr)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun struct vidtv_mpeg_ts_adaption ts_adap = {};
211*4882a593Smuzhiyun int stuff_nbytes;
212*4882a593Smuzhiyun u32 nbytes = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun if (!args->n_stuffing_bytes)
215*4882a593Smuzhiyun return 0;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun ts_adap.random_access = 1;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* length _immediately_ following 'adaptation_field_length' */
220*4882a593Smuzhiyun if (need_pcr) {
221*4882a593Smuzhiyun ts_adap.PCR = 1;
222*4882a593Smuzhiyun ts_adap.length = SIZE_PCR;
223*4882a593Smuzhiyun } else {
224*4882a593Smuzhiyun ts_adap.length = sizeof(ts_adap);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun stuff_nbytes = args->n_stuffing_bytes - ts_adap.length;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun ts_adap.length -= sizeof(ts_adap.length);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (unlikely(stuff_nbytes < 0))
231*4882a593Smuzhiyun stuff_nbytes = 0;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun ts_adap.length += stuff_nbytes;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /* write the adap after the TS header */
236*4882a593Smuzhiyun nbytes += vidtv_memcpy(args->dest_buf,
237*4882a593Smuzhiyun dest_offset + nbytes,
238*4882a593Smuzhiyun args->dest_buf_sz,
239*4882a593Smuzhiyun &ts_adap,
240*4882a593Smuzhiyun sizeof(ts_adap));
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* write the optional PCR */
243*4882a593Smuzhiyun if (need_pcr) {
244*4882a593Smuzhiyun nbytes += vidtv_pes_write_pcr_bits(args->dest_buf,
245*4882a593Smuzhiyun dest_offset + nbytes,
246*4882a593Smuzhiyun args->pcr);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun *last_pcr = args->pcr;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /* write the stuffing bytes, if are there anything left */
252*4882a593Smuzhiyun if (stuff_nbytes)
253*4882a593Smuzhiyun nbytes += vidtv_memset(args->dest_buf,
254*4882a593Smuzhiyun dest_offset + nbytes,
255*4882a593Smuzhiyun args->dest_buf_sz,
256*4882a593Smuzhiyun TS_FILL_BYTE,
257*4882a593Smuzhiyun stuff_nbytes);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun /*
260*4882a593Smuzhiyun * The n_stuffing_bytes contain a pre-calculated value of
261*4882a593Smuzhiyun * the amount of data that this function would read, made from
262*4882a593Smuzhiyun * vidtv_pes_h_get_len(). If something went wrong, print a warning
263*4882a593Smuzhiyun */
264*4882a593Smuzhiyun if (nbytes != args->n_stuffing_bytes)
265*4882a593Smuzhiyun pr_warn_ratelimited("write size was %d, expected %d\n",
266*4882a593Smuzhiyun nbytes, args->n_stuffing_bytes);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun return nbytes;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
vidtv_pes_write_ts_h(struct pes_ts_header_write_args args,bool need_pcr,u64 * last_pcr)271*4882a593Smuzhiyun static u32 vidtv_pes_write_ts_h(struct pes_ts_header_write_args args,
272*4882a593Smuzhiyun bool need_pcr, u64 *last_pcr)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun /* number of bytes written by this function */
275*4882a593Smuzhiyun u32 nbytes = 0;
276*4882a593Smuzhiyun struct vidtv_mpeg_ts ts_header = {};
277*4882a593Smuzhiyun u16 payload_start = !args.wrote_pes_header;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun ts_header.sync_byte = TS_SYNC_BYTE;
280*4882a593Smuzhiyun ts_header.bitfield = cpu_to_be16((payload_start << 14) | args.pid);
281*4882a593Smuzhiyun ts_header.scrambling = 0;
282*4882a593Smuzhiyun ts_header.adaptation_field = (args.n_stuffing_bytes) > 0;
283*4882a593Smuzhiyun ts_header.payload = (args.n_stuffing_bytes) < PES_TS_HEADER_MAX_STUFFING_BYTES;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun ts_header.continuity_counter = *args.continuity_counter;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun vidtv_ts_inc_cc(args.continuity_counter);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* write the TS header */
290*4882a593Smuzhiyun nbytes += vidtv_memcpy(args.dest_buf,
291*4882a593Smuzhiyun args.dest_offset + nbytes,
292*4882a593Smuzhiyun args.dest_buf_sz,
293*4882a593Smuzhiyun &ts_header,
294*4882a593Smuzhiyun sizeof(ts_header));
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /* write stuffing, if any */
297*4882a593Smuzhiyun nbytes += vidtv_pes_write_stuffing(&args, args.dest_offset + nbytes,
298*4882a593Smuzhiyun need_pcr, last_pcr);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun return nbytes;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
vidtv_pes_write_into(struct pes_write_args * args)303*4882a593Smuzhiyun u32 vidtv_pes_write_into(struct pes_write_args *args)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun u32 unaligned_bytes = (args->dest_offset % TS_PACKET_LEN);
306*4882a593Smuzhiyun struct pes_ts_header_write_args ts_header_args = {
307*4882a593Smuzhiyun .dest_buf = args->dest_buf,
308*4882a593Smuzhiyun .dest_buf_sz = args->dest_buf_sz,
309*4882a593Smuzhiyun .pid = args->pid,
310*4882a593Smuzhiyun .pcr = args->pcr,
311*4882a593Smuzhiyun .continuity_counter = args->continuity_counter,
312*4882a593Smuzhiyun };
313*4882a593Smuzhiyun struct pes_header_write_args pes_header_args = {
314*4882a593Smuzhiyun .dest_buf = args->dest_buf,
315*4882a593Smuzhiyun .dest_buf_sz = args->dest_buf_sz,
316*4882a593Smuzhiyun .encoder_id = args->encoder_id,
317*4882a593Smuzhiyun .send_pts = args->send_pts,
318*4882a593Smuzhiyun .pts = args->pts,
319*4882a593Smuzhiyun .send_dts = args->send_dts,
320*4882a593Smuzhiyun .dts = args->dts,
321*4882a593Smuzhiyun .stream_id = args->stream_id,
322*4882a593Smuzhiyun .n_pes_h_s_bytes = args->n_pes_h_s_bytes,
323*4882a593Smuzhiyun .access_unit_len = args->access_unit_len,
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun u32 remaining_len = args->access_unit_len;
326*4882a593Smuzhiyun bool wrote_pes_header = false;
327*4882a593Smuzhiyun u64 last_pcr = args->pcr;
328*4882a593Smuzhiyun bool need_pcr = true;
329*4882a593Smuzhiyun u32 available_space;
330*4882a593Smuzhiyun u32 payload_size;
331*4882a593Smuzhiyun u32 stuff_bytes;
332*4882a593Smuzhiyun u32 nbytes = 0;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (unaligned_bytes) {
335*4882a593Smuzhiyun pr_warn_ratelimited("buffer is misaligned, while starting PES\n");
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun /* forcibly align and hope for the best */
338*4882a593Smuzhiyun nbytes += vidtv_memset(args->dest_buf,
339*4882a593Smuzhiyun args->dest_offset + nbytes,
340*4882a593Smuzhiyun args->dest_buf_sz,
341*4882a593Smuzhiyun TS_FILL_BYTE,
342*4882a593Smuzhiyun TS_PACKET_LEN - unaligned_bytes);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun while (remaining_len) {
346*4882a593Smuzhiyun available_space = TS_PAYLOAD_LEN;
347*4882a593Smuzhiyun /*
348*4882a593Smuzhiyun * The amount of space initially available in the TS packet.
349*4882a593Smuzhiyun * if this is the beginning of the PES packet, take into account
350*4882a593Smuzhiyun * the space needed for the TS header _and_ for the PES header
351*4882a593Smuzhiyun */
352*4882a593Smuzhiyun if (!wrote_pes_header)
353*4882a593Smuzhiyun available_space -= vidtv_pes_h_get_len(args->send_pts,
354*4882a593Smuzhiyun args->send_dts);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * if the encoder has inserted stuffing bytes in the PES
358*4882a593Smuzhiyun * header, account for them.
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun available_space -= args->n_pes_h_s_bytes;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun /* Take the extra adaptation into account if need to send PCR */
363*4882a593Smuzhiyun if (need_pcr) {
364*4882a593Smuzhiyun available_space -= SIZE_PCR;
365*4882a593Smuzhiyun stuff_bytes = SIZE_PCR;
366*4882a593Smuzhiyun } else {
367*4882a593Smuzhiyun stuff_bytes = 0;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun /*
371*4882a593Smuzhiyun * how much of the _actual_ payload should be written in this
372*4882a593Smuzhiyun * packet.
373*4882a593Smuzhiyun */
374*4882a593Smuzhiyun if (remaining_len >= available_space) {
375*4882a593Smuzhiyun payload_size = available_space;
376*4882a593Smuzhiyun } else {
377*4882a593Smuzhiyun /* Last frame should ensure 188-bytes PS alignment */
378*4882a593Smuzhiyun payload_size = remaining_len;
379*4882a593Smuzhiyun stuff_bytes += available_space - payload_size;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /*
382*4882a593Smuzhiyun * Ensure that the stuff bytes will be within the
383*4882a593Smuzhiyun * allowed range, decrementing the number of payload
384*4882a593Smuzhiyun * bytes to write if needed.
385*4882a593Smuzhiyun */
386*4882a593Smuzhiyun if (stuff_bytes > PES_TS_HEADER_MAX_STUFFING_BYTES) {
387*4882a593Smuzhiyun u32 tmp = stuff_bytes - PES_TS_HEADER_MAX_STUFFING_BYTES;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun stuff_bytes = PES_TS_HEADER_MAX_STUFFING_BYTES;
390*4882a593Smuzhiyun payload_size -= tmp;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /* write ts header */
395*4882a593Smuzhiyun ts_header_args.dest_offset = args->dest_offset + nbytes;
396*4882a593Smuzhiyun ts_header_args.wrote_pes_header = wrote_pes_header;
397*4882a593Smuzhiyun ts_header_args.n_stuffing_bytes = stuff_bytes;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun nbytes += vidtv_pes_write_ts_h(ts_header_args, need_pcr,
400*4882a593Smuzhiyun &last_pcr);
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun need_pcr = false;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (!wrote_pes_header) {
405*4882a593Smuzhiyun /* write the PES header only once */
406*4882a593Smuzhiyun pes_header_args.dest_offset = args->dest_offset +
407*4882a593Smuzhiyun nbytes;
408*4882a593Smuzhiyun nbytes += vidtv_pes_write_h(&pes_header_args);
409*4882a593Smuzhiyun wrote_pes_header = true;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* write as much of the payload as we possibly can */
413*4882a593Smuzhiyun nbytes += vidtv_memcpy(args->dest_buf,
414*4882a593Smuzhiyun args->dest_offset + nbytes,
415*4882a593Smuzhiyun args->dest_buf_sz,
416*4882a593Smuzhiyun args->from,
417*4882a593Smuzhiyun payload_size);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun args->from += payload_size;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun remaining_len -= payload_size;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return nbytes;
425*4882a593Smuzhiyun }
426