summaryrefslogtreecommitdiffstats
path: root/drivers/media/test-drivers/vidtv/vidtv_pes.h
blob: 963c59155e725e6b42eea61a4e40c1b2554ff021 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Vidtv serves as a reference DVB driver and helps validate the existing APIs
 * in the media subsystem. It can also aid developers working on userspace
 * applications.
 *
 * This file contains the logic to translate the ES data for one access unit
 * from an encoder into MPEG TS packets. It does so by first encapsulating it
 * with a PES header and then splitting it into TS packets.
 *
 * Copyright (C) 2020 Daniel W. S. Almeida
 */

#ifndef VIDTV_PES_H
#define VIDTV_PES_H

#include <linux/types.h>

#include "vidtv_common.h"

#define PES_MAX_LEN 65536 /* Set 'length' to 0 if greater. Only possible for video. */
#define PES_START_CODE_PREFIX 0x001 /* 00 00 01 */

/* Used when sending PTS, but not DTS */
struct vidtv_pes_optional_pts {
	u8 pts1;
	__be16 pts2;
	__be16 pts3;
} __packed;

/* Used when sending both PTS and DTS */
struct vidtv_pes_optional_pts_dts {
	u8 pts1;
	__be16 pts2;
	__be16 pts3;

	u8 dts1;
	__be16 dts2;
	__be16 dts3;
} __packed;

/* PES optional flags */
struct vidtv_pes_optional {
	/*
	 * These flags show which components are actually
	 * present in the "optional fields" in the optional PES
	 * header and which are not
	 *
	 * u16 two:2;  //0x2
	 * u16 PES_scrambling_control:2;
	 * u16 PES_priority:1;
	 * u16 data_alignment_indicator:1; // unused
	 * u16 copyright:1;
	 * u16 original_or_copy:1;
	 * u16 PTS_DTS:2;
	 * u16 ESCR:1;
	 * u16 ES_rate:1;
	 * u16 DSM_trick_mode:1;
	 * u16 additional_copy_info:1;
	 * u16 PES_CRC:1;
	 * u16 PES_extension:1;
	 */
	__be16 bitfield;
	u8 length;
} __packed;

/* The PES header */
struct vidtv_mpeg_pes {
	__be32 bitfield; /* packet_start_code_prefix:24, stream_id: 8 */
	/* after this field until the end of the PES data payload */
	__be16 length;
	struct vidtv_pes_optional optional[];
} __packed;

/**
 * struct pes_header_write_args - Arguments to write a PES header.
 * @dest_buf: The buffer to write into.
 * @dest_offset: where to start writing in the dest_buffer.
 * @dest_buf_sz: The size of the dest_buffer
 * @encoder_id: Encoder id (see vidtv_encoder.h)
 * @send_pts: Should we send PTS?
 * @pts: PTS value to send.
 * @send_dts: Should we send DTS?
 * @dts: DTS value to send.
 * @stream_id: The stream id to use. Ex: Audio streams (0xc0-0xdf), Video
 * streams (0xe0-0xef).
 * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets
 * discarded by the decoder.
 * @access_unit_len: The size of _one_ access unit (with any headers it might need)
 */
struct pes_header_write_args {
	void *dest_buf;
	u32 dest_offset;
	u32 dest_buf_sz;
	u32 encoder_id;

	bool send_pts;
	u64 pts;

	bool send_dts;
	u64 dts;

	u16 stream_id;
	/* might be used by an encoder if needed, gets discarded by decoder */
	u32 n_pes_h_s_bytes;
	u32 access_unit_len;
};

/**
 * struct pes_ts_header_write_args - Arguments to write a TS header.
 * @dest_buf: The buffer to write into.
 * @dest_offset: where to start writing in the dest_buffer.
 * @dest_buf_sz: The size of the dest_buffer
 * @pid: The PID to use for the TS packets.
 * @continuity_counter: Incremented on every new TS packet.
 * @wrote_pes_header: Flag to indicate that the PES header was written
 * @n_stuffing_bytes: Padding bytes. Might be used by an encoder if needed, gets
 * discarded by the decoder.
 * @pcr: counter driven by a 27Mhz clock.
 */
struct pes_ts_header_write_args {
	void *dest_buf;
	u32 dest_offset;
	u32 dest_buf_sz;
	u16 pid;
	u8 *continuity_counter;
	bool wrote_pes_header;
	u32 n_stuffing_bytes;
	u64 pcr;
};

/**
 * struct pes_write_args - Arguments for the packetizer.
 * @dest_buf: The buffer to write into.
 * @from: A pointer to the encoder buffer containing one access unit.
 * @access_unit_len: The size of _one_ access unit (with any headers it might need)
 * @dest_offset: where to start writing in the dest_buffer.
 * @dest_buf_sz: The size of the dest_buffer
 * @pid: The PID to use for the TS packets.
 * @encoder_id: Encoder id (see vidtv_encoder.h)
 * @continuity_counter: Incremented on every new TS packet.
 * @stream_id: The stream id to use. Ex: Audio streams (0xc0-0xdf), Video
 * streams (0xe0-0xef).
 * @send_pts: Should we send PTS?
 * @pts: PTS value to send.
 * @send_dts: Should we send DTS?
 * @dts: DTS value to send.
 * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets
 * discarded by the decoder.
 * @pcr: counter driven by a 27Mhz clock.
 */
struct pes_write_args {
	void *dest_buf;
	void *from;
	u32 access_unit_len;

	u32 dest_offset;
	u32 dest_buf_sz;
	u16 pid;

	u32 encoder_id;

	u8 *continuity_counter;

	u16 stream_id;

	bool send_pts;
	u64 pts;

	bool send_dts;
	u64 dts;

	u32 n_pes_h_s_bytes;
	u64 pcr;
};

/**
 * vidtv_pes_write_into - Write a PES packet as MPEG-TS packets into a buffer.
 * @args: The args to use when writing
 *
 * This function translate the ES data for one access unit
 * from an encoder into MPEG TS packets. It does so by first encapsulating it
 * with a PES header and then splitting it into TS packets.
 *
 * The data is then written into the buffer pointed to by 'args.buf'
 *
 * Return: The number of bytes written into the buffer. This is usually NOT
 * equal to the size of the access unit, since we need space for PES headers, TS headers
 * and padding bytes, if any.
 */
u32 vidtv_pes_write_into(struct pes_write_args *args);

#endif // VIDTV_PES_H