F5OEO-tstools/misc_fns.h

512 wiersze
17 KiB
C

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* Miscellaneous useful functions.
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the MPEG TS, PS and ES tools.
*
* The Initial Developer of the Original Code is Amino Communications Ltd.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Amino Communications Ltd, Swavesey, Cambridge UK
*
* ***** END LICENSE BLOCK *****
*/
#ifndef _misc_fns
#define _misc_fns
#include "misc_defns.h"
#include "es_defns.h"
#ifndef _WIN32
#include <stdint.h>
#endif
#ifdef _WIN32
#include "compat.h"
#include <winsock2.h>
#endif // _WIN32
#define CRC32_POLY 0x04c11db7L
/*
* Compute CRC32 over a block of data, by table method.
*
* Returns a working value, suitable for re-input for further blocks
*
* Notes: Input value should be 0xffffffff for the first block,
* else return value from previous call (not sure if that
* needs complementing before being passed back in).
*/
extern uint32_t crc32_block(uint32_t crc, byte *pData, int blk_len);
/*
* Print out the bottom N bits from a byte
*/
extern void print_bits(int num_bits,
byte value);
/*
* Print out (the first `max`) bytes of a byte array.
*
* - if `is_msg` then print as a message, otherwise as an error
* - `name` is identifying text to start the report with.
* - `data` is the byte data to print. This may be NULL.
* - `length` is its length
* - `max` is the maximum number of bytes to print
*
* Prints out::
*
* <name> (<length>): b1 b2 b3 b4 ...
*
* where no more than `max` bytes are to be printed (and "..." is printed
* if not all bytes were shown).
*/
extern void print_data(int is_msg,
const char *name,
const byte data[],
int length,
int max);
/*
* Print out (the last `max`) bytes of a byte array.
*
* - `name` is identifying text to start the report with.
* - `data` is the byte data to print. This may be NULL.
* - `length` is its length
* - `max` is the maximum number of bytes to print
*
* Prints out::
*
* <name> (<length>): ... b1 b2 b3 b4
*
* where no more than `max` bytes are to be printed (and "..." is printed
* if not all bytes were shown).
*/
extern void print_end_of_data(char *name,
byte data[],
int length,
int max);
/*
* Calculate log2 of `x` - for some reason this is missing from <math.h>
*/
extern double log2(double x);
// ============================================================
// Simple file I/O utilities
// ============================================================
/*
* Read a given number of bytes from a file.
*
* This is a jacket for `read`, allowing for the future possibility of
* buffered input, and simplifying error handling.
*
* - `input` is the file descriptor for the file
* - `num_bytes` is how many bytes to read
* - `data` is the buffer to read the bytes into
*
* Returns 0 if all goes well, EOF if end of file was read, or 1 if some
* other error occurred (in which case it will already have output a message
* on stderr about the problem).
*/
extern int read_bytes(int input,
int num_bytes,
byte *data);
/*
* Utility function to seek within a file
*
* - `filedes` is the file to seek within
* - `posn` is the position to which to seek
*
* This is a jacket for::
*
* new_posn = lseek(filedes,posn,SEEK_SET);
*
* Returns 0 if all went well, 1 if the seek failed (either because
* it returned -1, or because the position reached was not the position
* requested). If an error occurs, then an explanatory message will
* already have been written to stderr.
*/
extern int seek_file(int filedes,
offset_t posn);
/*
* Utility function to report the current location within a file
*
* - `filedes` is the file to seek within
*
* This is a jacket for::
*
* posn = lseek(filedes,0,SEEK_CUR);
*
* Returns the current position in the file if all went well, otherwise
* -1 (in which case an error message will already have been written
* on stderr)
*/
extern offset_t tell_file(int filedes);
/*
* Utility function to open a file (descriptor), and report any errors
*
* This is intended only for very simple usage, and is not mean to be
* a general purpose "open" replacement.
*
* - `filename` is the name of the file to open
* - `for_write` should be TRUE if the file is to be written to,
* in which case it will be opened with flags O_WRONLY|O_CREAT|O_TRUNC,
* or FALSE if the file is to be read, in which case it will be
* opened with flag O_RDONLY. In both cases, on Windows the flag
* O_BINARY will also be set.
*
* Returns the file descriptor for the file, or -1 if it failed to open
* the file.
*/
extern int open_binary_file(char *filename,
int for_write);
/*
* Utility function to close a file (descriptor), and report any errors
*
* Returns 0 if all went well, 1 if an error occurred.
*/
extern int close_file(int filedes);
// ============================================================
// More complex file I/O utilities
// ============================================================
/*
* Open an input file appropriately for reading as ES.
*
* - `name` is the name of the file, or NULL if standard input
* is to be read from (which is not allowed if `use_pes` is
* TRUE).
*
* - If `use_pes` is true then the input file is PS or TS and should
* be read via a PES reader.
*
* - If `quiet` is true then information about the file being read will
* not be written out. Otherwise, its name and what is decided about
* its content will be printed.
*
* - If `force_stream_type` is true, then the caller asserts that
* the input shall be read according to `want_data`, and not whatever
* might be deduced from looking at the file itself.
*
* - If `force_stream_type` is true, then `want_data` should be one of
* VIDEO_H262, VIDEO_H264 or VIDEO_AVS. `is_data` will then be
* returned with the same value.
*
* - If `force_stream_type` is false, then the function will attempt
* to determine what type of data it has, and `is_data` will be set
* to whatever is determined (presumably one of VIDEO_H262, VIDEO_H264
* or VIDEO_AVS).
*
* - If input is from standard input, and `force_stream_type` is FALSE,
* `is_data` will always be set to VIDEO_H262, which may be incorrect.
*
* - `es` is the new ES reader context.
*
* Returns 0 if all goes well, 1 if something goes wrong. In the latter case,
* suitable messages will have been written out to standard error.
*/
extern int open_input_as_ES(char *name,
int use_pes,
int quiet,
int force_stream_type,
int want_data,
int *is_data,
ES_p *es);
/*
* Close an input ES stream opened with `open_input_as_ES`.
*
* Specifically, this will close the ES stream and also any underlying PES
* reader and file (unless the input was standard input).
*
* - `name` is the name of the file, used for error reporting.
* - `es` is the ES stream to close. This will be set to NULL.
*
* Returns 0 if all goes well, 1 if something goes wrong. In the latter case,
* suitable messages will have been written out to standard error.
*/
extern int close_input_as_ES(char *name,
ES_p *es);
// ============================================================
// Command line "helpers"
// ============================================================
/*
* Read in an unsigned integer value, checking for extraneous characters.
*
* - `prefix` is an optional prefix for error messages, typically the
* name of the program. It may be NULL.
* - `cmd` is the command switch we're reading for (typically ``argv[ii]``),
* which is used in error messages.
* - `str` is the string to read (typically ``argv[ii+1]``).
* - `base` is the base to read to. If it is 0, then the user can use
* C-style expressions like "0x68" to specify the base on the command line.
* - `value` is the value read.
*
* Returns 0 if all went well, 1 otherwise (in which case a message
* explaining will have been written to stderr).
*/
extern int unsigned_value(char *prefix,
char *cmd,
char *arg,
int base,
uint32_t *value);
/*
* Read in an integer value, checking for extraneous characters.
*
* - `prefix` is an optional prefix for error messages, typically the
* name of the program. It may be NULL.
* - `cmd` is the command switch we're reading for (typically ``argv[ii]``),
* which is used in error messages.
* - `str` is the string to read (typically ``argv[ii+1]``).
* - if `positive` is true, then the number read must be positive (0 or more).
* - `base` is the base to read to. If it is 0, then the user can use
* C-style expressions like "0x68" to specify the base on the command line.
* - `value` is the value read.
*
* Returns 0 if all went well, 1 otherwise (in which case a message
* explaining will have been written to stderr).
*/
extern int int_value(char *prefix,
char *cmd,
char *str,
int positive,
int base,
int *value);
/*
* Read in an integer value, checking for extraneous characters and a range.
*
* - `prefix` is an optional prefix for error messages, typically the
* name of the program. It may be NULL.
* - `cmd` is the command switch we're reading for (typically ``argv[ii]``),
* which is used in error messages.
* - `str` is the string to read (typically ``argv[ii+1]``).
* - `minimum` is the minimum value allowed.
* - `maximum` is the maximum value allowed.
* - `base` is the base to read to. If it is 0, then the user can use
* C-style expressions like "0x68" to specify the base on the command line.
* - `value` is the value read.
*
* Returns 0 if all went well, 1 otherwise (in which case a message
* explaining will have been written to stderr).
*/
extern int int_value_in_range(char *prefix,
char *cmd,
char *arg,
int minimum,
int maximum,
int base,
int *value);
/*
* Read in a double value, checking for extraneous characters.
*
* - `prefix` is an optional prefix for error messages, typically the
* name of the program. It may be NULL.
* - `cmd` is the command switch we're reading for (typically ``argv[ii]``),
* which is used in error messages.
* - `str` is the string to read (typically ``argv[ii+1]``).
* - if `positive` is true, then the number read must be positive (0 or more).
* - `value` is the value read.
*
* Returns 0 if all went well, 1 otherwise (in which case a message
* explaining will have been written to stderr).
*/
extern int double_value(char *prefix,
char *cmd,
char *arg,
int positive,
double *value);
/*
* Read in a hostname and (optional) port
*
* - `prefix` is an optional prefix for error messages, typically the
* name of the program. It may be NULL.
* - `cmd` is the command switch we're reading for (typically ``argv[ii]``),
* which is used in error messages.
* - `arg` is the string to read (typically ``argv[ii+1]``).
* - `hostname` is the host name read
* - `port` is the port read (note that this is not touched if there is
* no port number, so it may be set to a default before calling this
* function)
*
* Note that this works by pointing `hostname` to the start of the `arg`
* string, and then if there is a ':' in `arg`, changing that colon to
* a '\0' delimiter, and interpreting the string thereafter as the port
* number. If *that* fails, it resets the '\0' as a ':'.
*
* Returns 0 if all went well, 1 otherwise (in which case a message
* explaining will have been written to stderr).
*/
extern int host_value(char *prefix,
char *cmd,
char *arg,
char **hostname,
int *port);
// ============================================================
// Sockets
// ============================================================
#ifdef _WIN32
/*
* Start up WINSOCK so we can use sockets.
*
* Note that each successful call of this *must* be matched by a call
* of winsock_cleanup().
*
* Returns 0 if it works, 1 if it fails.
*/
extern int winsock_startup(void);
/*
* Convert a WinSock error number into a string and print it out on stderr
*/
extern void print_winsock_err(int err);
#endif // _WIN32
/*
* Connect to a socket, to allow us to write to it, using TCP/IP.
*
* - `hostname` is the name of the host to connect to
* - `port` is the port to use
* - if `use_tcpip`, then a TCP/IP connection will be made, otherwise UDP.
* For UDP, multicast TTL will be enabled.
* - If the destination address (`hostname`) is multicast and `multicast_ifaddr`
* is supplied, it is used to select (by IP address) the network interface
* on which to send the multicasts. It may be NULL to use the default,
* or for non-multicast cases.
*
* A socket connected to via this function must be disconnected from with
* disconnect_socket().
*
* Returns a positive integer (the file descriptor for the socket) if it
* succeeds, or -1 if it fails, in which case it will have complained on
* stderr.
*/
extern int connect_socket(char *hostname,
int port,
int use_tcpip,
char *multicast_ifaddr);
/*
* Disconnect from a socket (close it).
*
* Returns 0 if all goes well, 1 otherwise.
*/
#ifdef _WIN32
extern int disconnect_socket(SOCKET socket);
#else // _WIN32
extern int disconnect_socket(int socket);
#endif // _WIN32
/*! Decode a host byte order address to a static buffer. */
const char *ipv4_addr_to_string(const uint32_t addr);
/*! Decode a string to a host byte order address */
int ipv4_string_to_addr(uint32_t *dest, const char *addr);
// ============================================================
// Byte order handling
// ============================================================
static inline uint32_t uint_32_be(const uint8_t *const p)
{
return (((int)p[0]&0xff) << 24) |
(((int)p[1]&0xff) << 16) |
(((int)p[2]&0xff) << 8) |
(((int)p[3]&0xff));
}
static inline uint32_t uint_32_le(const uint8_t *const p)
{
return (((int)p[0]&0xff) |
(((int)p[1]&0xff) << 8) |
(((int)p[2]&0xff) << 16) |
(((int)p[3]&0xff) << 24));
}
static inline uint16_t uint_16_be(const uint8_t *const p)
{
return ((((int)p[0])&0xff)<<8) |
((((int)p[1])&0xff));
}
static inline uint16_t uint_16_le(const uint8_t *const p)
{
return (((int)p[0]&0xff) |
((int)p[1]&0xff)<<8);
}
// ============================================================
// Time diffs
// ============================================================
#define PCR_UNSIGNED_WRAP (300ULL * (1ULL << 33))
// (x - y) with allowance for PCR wrap - unsigned version
static inline uint64_t
pcr_unsigned_diff(uint64_t x, uint64_t y)
{
return x > y ? x - y :
300ULL * (1ULL << 33) - (y - x);
}
#define PCR_SIGNED_WRAP (300LL * (1LL << 33))
#define PCR_SIGNED_MAX (PCR_SIGNED_WRAP / 2LL - 1LL)
#define PCR_SIGNED_MIN (-PCR_SIGNED_WRAP / 2LL)
// (x - y) with allowance for PCR wrap - signed version
static inline int64_t
pcr_signed_diff(uint64_t x, uint64_t y)
{
int64_t r = x - y;
return r < PCR_SIGNED_MIN ? r + PCR_SIGNED_WRAP :
r > PCR_SIGNED_MAX ? r - PCR_SIGNED_WRAP :
r;
}
// Deal with simple overflow
static inline uint64_t
pcr_unsigned_wrap(uint64_t x)
{
return x >= PCR_UNSIGNED_WRAP ? x - PCR_UNSIGNED_WRAP : x;
}
static inline int64_t
pts_signed_diff(uint64_t x, uint64_t y)
{
int64_t r = x - y;
return (r << 31) >> 31;
}
#endif // _misc_fns
// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 expandtab: