1 /*
2  * Support for writing out TS packets, to file, or over TCP/IP or UDP
3  *
4  * When writing asynchronously, provides automated producer/consumer
5  * behaviour via a circular buffer, optionally taking timing from the
6  * TS PCR entries.
7  *
8  * ***** BEGIN LICENSE BLOCK *****
9  * Version: MPL 1.1
10  *
11  * The contents of this file are subject to the Mozilla Public License Version
12  * 1.1 (the "License"); you may not use this file except in compliance with
13  * the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS" basis,
17  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18  * for the specific language governing rights and limitations under the
19  * License.
20  *
21  * The Original Code is the MPEG TS, PS and ES tools.
22  *
23  * The Initial Developer of the Original Code is Amino Communications Ltd.
24  * Portions created by the Initial Developer are Copyright (C) 2008
25  * the Initial Developer. All Rights Reserved.
26  *
27  * Contributor(s):
28  *   Amino Communications Ltd, Swavesey, Cambridge UK
29  *
30  * ***** END LICENSE BLOCK *****
31  */
32 
33 #ifndef _tswrite_defns
34 #define _tswrite_defns
35 
36 #include "compat.h"
37 #include "ts_defns.h"
38 #include "h222_defns.h"
39 
40 #ifdef _WIN32
41 #include <winsock2.h>  // for definition of SOCKET
42 #else
43 typedef int SOCKET;    // for compatibility with Windows
44 #include <termios.h>   // for struct termios
45 #endif
46 
47 
48 // ============================================================
49 // CIRCULAR BUFFER
50 // ============================================================
51 
52 // We default to using a "packet" of 7 transport stream packets because 7*188 =
53 // 1316, but 8*188 = 1504, and we would like to output as much data as we can
54 // that is guaranteed to fit into a single ethernet packet, size 1500.
55 #define DEFAULT_TS_PACKETS_IN_ITEM      7
56 
57 // For simplicity, we'll have a maximum on that (it allows us to have static
58 // array sizes in some places). This should be a big enough size to more than
59 // fill a jumbo packet on a gigabit network.
60 #define MAX_TS_PACKETS_IN_ITEM          100
61 
62 // ------------------------------------------------------------
63 // A circular buffer, usable as a queue
64 //
65 // We "waste" one buffer item so that we don't have to maintain a count
66 // of items in the buffer
67 //
68 // To get an understanding of how it works, choose a small BUFFER_SIZE
69 // (e.g., 11), enable DISPLAY_BUFFER, and select --visual - this will show the
70 // reading/writing of the circular buffer in action, including the
71 // "unused item".
72 //
73 // The data for the circular buffer
74 // Each circular buffer item "contains" (up to) N TS packets (where N defaults
75 // to 7, and is specified as `item_size` in the circular buffer header), and a
76 // time (in microseconds) when we would like it to be output (relative to the
77 // time for the first packet "sent").
78 //
79 // Said data is stored at the address indicated by the circular buffer
80 // "header", as `item_data`.
81 //
82 struct circular_buffer_item
83 {
84   uint32_t time;              // when we would like this data output
85   int      discontinuity;     // TRUE if our timeline has "broken"
86   int      length;            // number of bytes of data in the array
87 };
88 typedef struct circular_buffer_item *circular_buffer_item_p;
89 
90 #define SIZEOF_CIRCULAR_BUFFER_ITEM sizeof(struct circular_buffer_item)
91 
92 // ------------------------------------------------------------
93 // The header for the circular buffer
94 //
95 // Note that `start` is only ever written to by the child process, and this is
96 // the only thing that the child process ever changes in the circular buffer.
97 //
98 // `maxnowait` is the maximum number of packets to send to the target host
99 // without forcing an intermediate wait - required to stop us "swamping" the
100 // target with too much data, and overrunning its buffers.
101 struct circular_buffer
102 {
103   int      start;      // start of data "pointer"
104   int      end;        // end of data "pointer" (you guessed)
105   int      size;       // the actual length of the `item` array
106 
107   int      TS_in_item; // max number of TS packets in a circular buffer item
108   int      item_size;  // and thus the size of said item's data array
109 
110   int      maxnowait;  // max number consecutive packets to send with no wait
111   int      waitfor;    // the number of microseconds to wait thereafter
112 
113   // The location of the packet data for the circular buffer items
114   byte     *item_data;
115 
116   // The "header" data for each circular buffer item
117   struct circular_buffer_item item[];
118 };
119 typedef struct circular_buffer *circular_buffer_p;
120 
121 // Note that size doesn't include the final `item`
122 #define SIZEOF_CIRCULAR_BUFFER sizeof(struct circular_buffer)
123 
124 #define DEFAULT_CIRCULAR_BUFFER_SIZE  1024              // used to be 100
125 
126 
127 // ============================================================
128 // BUFFERED OUTPUT
129 // ============================================================
130 
131 // Information about each TS packet in our circular buffer item
132 struct TS_packet_info
133 {
134   int                index;
135   uint32_t           pid;       // do we need the PIDs?
136   int                got_pcr;
137   uint64_t           pcr;
138 };
139 typedef struct TS_packet_info *TS_packet_info_p;
140 #define SIZEOF_TS_PACKET_INFO sizeof(struct TS_packet_info);
141 
142 // If we're going to support output via our circular buffer in a manner
143 // similar to that for output to a file or socket, then we need a structure
144 // to maintain the relevant information. It seems a bit wasteful to burden
145 // the circular buffer itself with this, particularly as only the writer
146 // cares about this data, so it needn't be shared.
147 struct buffered_TS_output
148 {
149   circular_buffer_p  buffer;
150   int                which;   // Which buffer index we're writing to
151   int                started; // TRUE if we've started writing therein
152 
153   // For each TS packet in the circular buffer, remember its `count`
154   // within the input stream, whether it had a PCR, and if so what that
155   // PCR was. To make it simpler to access these arrays, also keep a fill
156   // index into them (the alternative would be to always re-zero the
157   // `got_pcr` values whenever we start a new circular buffer entry,
158   // which would be a pain...)
159   int                    num_packets;  // how many TS packets we've got
160   struct TS_packet_info  packet[MAX_TS_PACKETS_IN_ITEM];
161 
162   // `rate` is the rate (in bytes per second) we would like to output data at
163   uint32_t           rate;
164 
165   // `pcr_scale` is a multiplier for PCRs - each PCR found gets its value
166   // multiplied by this
167   double             pcr_scale;
168 
169   // `use_pcrs` indicates if we should use PCRs in the data to drive our
170   // timing, rather than use the specified byte rate directly. The `priming`
171   // values are only relevant if `use_pcrs` is true.
172   int                use_pcrs;
173 
174   // 'prime_size' is the amount of space/time to 'prime' the circular buffer
175   // output timing mechanism with. This is effectively multiples of the
176   // size of a circular buffer item.
177   int                prime_size;
178 
179   // Percentage "too fast" speedup for our priming rate
180   int                prime_speedup;
181 };
182 typedef struct buffered_TS_output *buffered_TS_output_p;
183 #define SIZEOF_BUFFERED_TS_OUTPUT sizeof(struct buffered_TS_output)
184 
185 
186 // ============================================================
187 // EXTERNAL DATASTRUCTURES - these are *intended* for external use
188 // ============================================================
189 
190 // Our supported target types
191 // On Unix-type systems, there is little distinction between file and
192 // socket, but on Windows this becomes more interesting
193 enum TS_writer_type
194 {
195   TS_W_UNDEFINED,
196   TS_W_STDOUT,  // standard output
197   TS_W_FILE,    // a file
198   TS_W_TCP,     // a socket, over TCP/IP
199   TS_W_UDP,     // a socket, over UDP
200 };
201 typedef enum TS_writer_type TS_WRITER_TYPE;
202 
203 // ------------------------------------------------------------
204 // So, *is* it a file or a socket?
205 union TS_writer_output
206 {
207   FILE   *file;
208   SOCKET  socket;
209 };
210 
211 // ------------------------------------------------------------
212 // A datastructure to allow us to write to various different types of target
213 //
214 // When writing to a file, "how" will be TS_W_STDOUT or TS_W_FILE, and
215 // "where" will be the appropriate file interface. "writer" is not necessary
216 // (there's no point in putting a circular buffer and other stuff above
217 // the file writes), and no child process is needed.
218 //
219 // When writing over UDP, "how" will be TS_W_UDP, and "where" will be the
220 // socket that is being written to. For UDP, timing needs to be managed, and
221 // thus the circular buffer support is necessary, so "writer" should be
222 // set to a buffered output context. Since the circular buffer is being
223 // used, there will also be a child process.
224 //
225 // When writing over TCP/IP, "how" will be TS_W_TCP, and "where" will be the
226 // socket that is being written to. Timing is not an issue, so "writer" will
227 // not be needed, and nor will there be a child process.  However, it is
228 // possible that we will want to respond to commands (over the same or another
229 // socket (or, on Linux/BSD, file descriptor)), so "commander" may be set.
230 struct TS_writer
231 {
232   enum  TS_writer_type   how;    // what type of output we want
233   union TS_writer_output where;  // where it's going to
234   buffered_TS_output_p   writer; // our buffered output interface, if needed
235   int                    count;  // a count of how many TS packets written
236 
237   // Support for the child fork/thread, which actually does the writing when
238   // buffered output is enabled.
239 #ifdef _WIN32
240   HANDLE                 child;  // the handle for the child thread (if any)
241 #else  // _WIN32
242   pid_t                  child;  // the PID of the child process (if any)
243 #endif // _WIN32
244   int                    quiet;  // Should the child be as quiet as possible?
245 
246   // Support for "commands" being sent to us via a socket (or, on Linux/BSD,
247   // from any other file descriptor). The "normal" way this is used is for
248   // our application (tsserve) to act as a server, listening on a socket
249   // for an incoming connection, and then both playing data to that
250   // connection, and listening for commands from it.
251   int                    server;         // are we acting as a server?
252   SOCKET                 command_socket; // where to read commands from/through
253 
254   // When the user sends a new command (a different character than is
255   // currently in `command`), the underpinnings of tswrite_write() set
256   // `command` to that command letter, and `command_changed` to TRUE.
257   // Various key functions that write to TS check `command_changed`, and
258   // return COMMAND_RETURN_CODE if it is true.
259   // Note, however, that it is left up to the top level to *unset*
260   // `command_changed` again.
261   byte   command;          // A single character "command" for what to do
262   int    command_changed;  // Has it changed?
263   // Some commands (notably, the "skip" commands) want to be atomic - that
264   // is, they should not be interrupted by the user "typing ahead". Since
265   // the fast forward and reverse mechanisms (used for skipping as well)
266   // call tswrite_command_changed() to tell if there is a new command that
267   // should interrup them, we can provide a flag to say "don't do that"...
268   int    atomic_command;
269 
270   // Should some TS packets be thrown away every <n> packets? This can be
271   // useful for debugging other applications
272   int    drop_packets;  // 0 to keep all packets, otherwise keep <n> packets
273   int    drop_number;   // and then drop this many
274 };
275 typedef struct TS_writer *TS_writer_p;
276 #define SIZEOF_TS_WRITER sizeof(struct TS_writer)
277 
278 // ------------------------------------------------------------
279 // Command letters
280 #define COMMAND_NOT_A_COMMAND '_' // A guaranteed non-command letter
281 
282 #define COMMAND_QUIT          'q' // quit/exit
283 #define COMMAND_NORMAL        'n' // normal playing speed
284 #define COMMAND_PAUSE         'p' // pause until another command
285 #define COMMAND_FAST          'f' // fast forward
286 #define COMMAND_FAST_FAST     'F' // faster forward
287 #define COMMAND_REVERSE       'r' // reverse/rewind
288 #define COMMAND_FAST_REVERSE  'R' // faster reverse/rewind
289 #define COMMAND_SKIP_FORWARD       '>'  // aim at 10s
290 #define COMMAND_SKIP_BACKWARD      '<'  // ditto
291 #define COMMAND_SKIP_FORWARD_LOTS  ']'  // aim at 100s
292 #define COMMAND_SKIP_BACKWARD_LOTS '['  // ditto
293 
294 #define COMMAND_SELECT_FILE_0 '0'
295 #define COMMAND_SELECT_FILE_1 '1'
296 #define COMMAND_SELECT_FILE_2 '2'
297 #define COMMAND_SELECT_FILE_3 '3'
298 #define COMMAND_SELECT_FILE_4 '4'
299 #define COMMAND_SELECT_FILE_5 '5'
300 #define COMMAND_SELECT_FILE_6 '6'
301 #define COMMAND_SELECT_FILE_7 '7'
302 #define COMMAND_SELECT_FILE_8 '8'
303 #define COMMAND_SELECT_FILE_9 '9'
304 
305 // And a "return code" that means "the command character has changed"
306 #define COMMAND_RETURN_CODE  -999
307 
308 // ------------------------------------------------------------
309 // Context for use in decoding command line - see `tswrite_process_args()`
310 struct TS_context
311 {
312   // Values used in setting up buffered output
313   int circ_buf_size; // number of buffer entries (+1) for circular buffer
314   int TS_in_item;    // number of TS packets in each circular buffer item
315   int maxnowait;     // max number of packets to send without waiting
316   int waitfor;       // the number of microseconds to wait thereafter
317   int bitrate;       // suggested bit rate  (byterate*8) - both are given
318   int byterate;      // suggested byte rate (bitrate/8)  - for convenience
319   int use_pcrs;      // use PCRs for timing information?
320   int prime_size;    // initial priming size for buffered output
321   int prime_speedup; // percentage of normal speed to prime with
322   double pcr_scale;       // multiplier for PCRs -- see buffered_TS_output
323 };
324 typedef struct TS_context *TS_context_p;
325 
326 // Arguments processed by tswrite_process_args are set to:
327 #define TSWRITE_PROCESSED "<processed>"
328 
329 #endif // _tswrite_defns
330 
331 // Local Variables:
332 // tab-width: 8
333 // indent-tabs-mode: nil
334 // c-basic-offset: 2
335 // End:
336 // vim: set tabstop=8 shiftwidth=2 expandtab:
337