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