F5OEO-tstools/pes_fns.h

557 wiersze
21 KiB
C
Czysty Zwykły widok Historia

/*
* Functions for reading PES packets from TS or PS files
*
* ***** 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 _pes_fns
#define _pes_fns
#include "pes_defns.h"
#include "es_defns.h"
2016-09-12 16:12:39 +00:00
extern void setup_PES_as_ES(PES_packet_data_p packet);
/*
* Free a PES packet datastructure
*
* - `data` is the PES packet datastructure, which will be freed,
* and returned as NULL.
*/
extern void free_PES_packet_data(PES_packet_data_p *data);
/*
* Look at the start of a file to determine if it appears to be transport
* stream. Rewinds the file when it is finished.
*
* The file is assumed to be Transport Stream if it starts with 0x47 as
* the first byte, and 0x47 recurs at 188 byte intervals (in other words,
* it appears to start with several TS packets).
*
* - `input` is the file to check
* - `is_TS` is TRUE if it looks like TS, as described above.
*
* Returns 0 if all goes well, 1 if there was an error.
*/
extern int determine_if_TS_file(int input,
int *is_TS);
/*
* Build a PES reader datastructure for PS data
*
* - `ps` is the Program Stream to read the PES data from
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout).
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `reader` is the resulting PES reader
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int build_PS_PES_reader(PS_reader_p ps,
int give_info,
int give_warnings,
PES_reader_p *reader);
/*
* Build a PES reader datastructure for TS data
*
* - `tsreader` is the Transport Stream to read the PES data from
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout).
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `program_number` is only used for TS data, and identifies which program
* to read. If this is 0 then the first program encountered in the first PAT
* will be read.
* - `reader` is the resulting PES reader
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int build_TS_PES_reader(TS_reader_p tsreader,
int give_info,
int give_warnings,
uint16_t program_number,
PES_reader_p *reader);
/*
* Build a PES reader datastructure
*
* - `input` is the file to read the PES data from
* - `is_TS` should be TRUE if the data is TS, FALSE if it is PS
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout).
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `program_number` is only used for TS data, and identifies which program
* to read. If this is 0 then the first program encountered in the first PAT
* will be read.
* - `reader` is the resulting PES reader
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int build_PES_reader(int input,
int is_TS,
int give_info,
int give_warnings,
uint16_t program_number,
PES_reader_p *reader);
/*
* Open a Transport Stream file for PES packet reading
*
* - `filename` is the name of the file to open.
* - `program_number` identifies which program to read. If this is 0
* then the first program encountered in the first PAT will be read.
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout). If information messages are requested, and the
* program number is given as 0, the actual program number chosen will
* be reported as well.
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `reader` is the PES reader context corresponding to the newly
* opened file.
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int open_PES_reader_for_TS(char *filename,
uint16_t program_number,
int give_info,
int give_warnings,
PES_reader_p *reader);
/*
* Open a Program Stream file for PES packet reading
*
* - `filename` is the name of the file to open.
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout).
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `reader` is the PES reader context corresponding to the newly
* opened file.
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int open_PES_reader_for_PS(char *filename,
int give_info,
int give_warnings,
PES_reader_p *reader);
/*
* Open a Program Stream or Transport Stream file for PES packet reading
*
* - `filename` is the name of the file to open.
* - `give_info` is TRUE if information about program data, etc., should be
* output (to stdout).
* - `give_warnings` is TRUE if warnings (starting with "!!!") should be
* output (to stderr), FALSE if they should be suppressed.
* - `reader` is the PES reader context corresponding to the newly
* opened file.
*
* If the file is Transport Stream, then this is equivalent to a call
* of::
*
* err = open_PES_reader_for_TS(filename,0,give_info,give_warnings,&reader);
*
* i.e., the first program found is the program that will be read.
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int open_PES_reader(char *filename,
int give_info,
int give_warnings,
PES_reader_p *reader);
/*
* Tell the PES reader whether we only want video data
*
* - `video_only` should be TRUE if audio is to be ignored, FALSE
* if audio should be retained.
*
* By default, the PES reader returns video data and a single audio
* stream (taken from the first audio stream encountered).
*/
extern void set_PES_reader_video_only(PES_reader_p reader,
int video_only);
/*
* Tell the PES reader which audio stream we want.
*
* By default, the PES reader returns video data and a single audio
* stream (taken from the first audio stream encountered).
*
* - `reader` is the PES reader context
* - `stream_number` is the number of the audio stream to read, from
* 0 to 31 (0x1F).
*
* This call only has effect if the input data is PS.
*
* Returns 0 if all went well, or 1 if there was an error (specifically,
* that `stream_number` was not in the range 0-31).
*/
extern int set_PES_reader_audio_stream(PES_reader_p reader,
int stream_number);
/*
* Tell the PES reader to get its audio stream from private stream 1
* (this is the stream that is conventionally used for Dolby in DVD data).
*
* By default, the PES reader returns video data and a single audio
* stream (taken from the first audio stream encountered).
*
* - `reader` is the PES reader context
*
* This call only has effect if the input data is PS.
*/
extern void set_PES_reader_audio_private1(PES_reader_p reader);
/*
* Tell the PES reader to "pretend" it has read a PAT and PMT with
* the given program information.
*
* This is intended for use in setting up sensible values when reading
* PS data (which does not contain such information). It will silently
* do nothing for TS data.
*
* Note that calling it more than once is allowed - it will happily
* overwrite any previous values.
*
* - `reader` is the PES reader context
* - `program_number` is the program number to assume. If this is 0,
* then 1 will be used.
* - `pmt_pid` is the PID for the PMT we've pretended to read.
* - `video_pid` is the PID to assume for the video data
* - `audio_pid` is the PID to assume for the audio data (if any)
* - `pcr_pid` is the PID to assume for the PCR data - this will often
* be the same as the `video_pid`
*/
extern void set_PES_reader_program_data(PES_reader_p reader,
uint16_t program_number,
uint32_t pmt_pid,
uint32_t video_pid,
uint32_t audio_pid,
uint32_t pcr_pid);
/*
* Tell the PES reader that the PS data it is reading is MPEG-4/AVC,
* as opposed to MPEG-1/MPEG-2.
*/
extern void set_PES_reader_h264(PES_reader_p reader);
/*
* Tell the PES reader that the PS data it is reading is of
* type `video_type` (which is assumed to be a legitimate value
* such as VIDEO_H264, etc.)
*/
extern void set_PES_reader_video_type(PES_reader_p reader,
int video_type);
/*
* Tell the PES reader whether to output any Dolby (AC-3) audio data
* it may read using the DVB stream type (0x06) or the ATSC stream
* type (0x81).
*
* If it is reading TS data, then the default is to use whatever stream type
* the Dolby audio was read with.
*
* If it is reading PS data, then the default is to assume DVB data.
*
* This call only has effect if Dolby audio data is actually selected.
*/
extern void set_PES_reader_dolby_stream_type(PES_reader_p reader,
int is_dvb);
/*
* Reposition the PES reader to an earlier packet
*
* It is the caller's responsibility to choose a sensible `posn` to seek to.
*
* Note that using this to reposition in a PES reader does not affect any
* "higher" reading context using this PES reader - specifically, if data
* is being read via an ES reader, then calling this function directly
* will result in the ES reader losing its positional information.
*
* In this case, `seek_ES` should be called.
*
* - `reader` is the PES reader context
* - `posn` is a packet position obtained from an earlier PES packet
* datastructure (this should *not* be a random offset in the input
* file, as that will not in general work).
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int set_PES_reader_position(PES_reader_p reader,
offset_t posn);
/*
* Free a PES reader, and the relevant datastructures. Does not close
* the underlying file.
*
* - `reader` is the PES reader context. This will be freed, and
* returned as NULL.
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int free_PES_reader(PES_reader_p *reader);
/*
* Close a PES reader, and free the relevant datastructures.
*
* - `reader` is the PES reader context. This will be freed, and
* returned as NULL.
*
* Returns 0 if all goes well, 1 if something goes wrong with closing the
* file (although in that case, the `reader` will still have been freed).
*/
extern int close_PES_reader(PES_reader_p *reader);
/*
* Return the next PES packet from the input file
*
* - `reader` is a PES reader context
*
* Returns 0 if all goes well, EOF if end of file is read, and 1 if
* something goes wrong.
*/
extern int read_next_PES_packet(PES_reader_p reader);
/*
* Given an MPEG-1 PES packet, determine the offset of the ES data.
*
* - `data` is the PES packet data, starting "00 00 01 <stream_id>
* <packet_length>"
* - `data_len` is the actual length of the data therein
*
* Returns the required offset (i.e., packet[offset] is the first byte
* of the ES data within the PES packet).
*/
extern int calc_mpeg1_pes_offset(byte *data, int data_len);
/*
* Read in the next PES packet that contains ES data we are interested in
* Ignores non-video packets.
*
* - `reader` is a PES reader context
*
* Returns 0 if all goes well, EOF if end of file is read, and 1 if
* something goes wrong.
*/
extern int read_next_PES_ES_packet(PES_reader_p reader);
/*
* If the given PES packet data contains a PTS field, return it
*
* - `data` is the data for this PES packet
* - `data_len` is its length
* - `got_pts` is TRUE if a PTS field was found, in which case
* - `pts` is that PTS value
*
* Returns 0 if all went well, 1 if an error occurs.
*/
extern int find_PTS_in_PES(byte data[],
int32_t data_len,
int *got_pts,
uint64_t *pts);
/*
* If the given PES packet data contains a DTS field, return it
*
* - `data` is the data for this PES packet
* - `data_len` is its length
* - `got_dts` is TRUE if a DTS field was found, in which case
* - `dts` is that DTS value
*
* Returns 0 if all went well, 1 if an error occurs.
*/
extern int find_DTS_in_PES(byte data[],
int32_t data_len,
int *got_dts,
uint64_t *dts);
/*
* If the given PES packet data contains a PTS and/or DTS field, return it
*
* - `data` is the data for this PES packet
* - `data_len` is its length
* - `got_pts` is TRUE if a PTS field was found, in which case
* - `pts` is that PTS value
* - `got_dts` is TRUE if a DTS field was found, in which case
* - `dts` is that DTS value
*
* Returns 0 if all went well, 1 if an error occurs.
*/
extern int find_PTS_DTS_in_PES(byte data[],
int32_t data_len,
int *got_pts,
uint64_t *pts,
int *got_dts,
uint64_t *dts);
/*
* If the given PES packet data contains an ESCR field, return it
*
* - `data` is the data for this PES packet
* - `data_len` is its length
* - `got_escr` is TRUE if an ESCR field was found, in which case
* - `escr` is that ESCR value
*
* Returns 0 if all went well, 1 if an error occurs.
*/
extern int find_ESCR_in_PES(byte data[],
int32_t data_len,
int *got_escr,
uint64_t *escr);
/*
* Decode a PTS or DTS value.
*
* - `bytes` is the 5 bytes containing the encoded PTS or DTS value
* - `required_guard` should be 2 for a PTS alone, 3 for a PTS before
* a DTS, or 1 for a DTS after a PTS
* - `value` is the PTS or DTS value as decoded
*
* Returns 0 if the PTS/DTS value is decoded successfully, 1 if an error occurs
*/
extern int decode_pts_dts(byte data[],
int required_guard,
uint64_t *value);
/*
* Encode a PTS or DTS.
*
* - `data` is the array of 5 bytes into which to encode the PTS/DTS
* - `guard_bits` are the required guard bits: 2 for a PTS alone, 3 for
* a PTS before a DTS, or 1 for a DTS after a PTS
* - `value` is the PTS or DTS value to be encoded
*/
extern void encode_pts_dts(byte data[],
int guard_bits,
uint64_t value);
/*
* Does the given PES packet contain a PTS?
*
* - `packet` is the PES packet datastructure
*
* Returns TRUE if it does, FALSE if it does not (or is in error)
*/
extern int PES_packet_has_PTS(PES_packet_data_p packet);
/*
* Report on the content of a PES packet - specifically, its header data.
*
* - `prefix` is a string to put before each line of output
* - `data` is the packet data, and `data_len` its length
* - `show_data` should be TRUE if the start of the data for each packet should
* be shown
*
* Returns 0 if all went well, 1 if an error occurs.
*/
extern int report_PES_data_array(char *prefix,
byte *data,
int data_len,
int show_data);
/*
* Report on the content of a PES packet.
*
* This gives a longer form of report than report_PES_data_array(), and
* can also present substream data for audio stream_types.
*
* - `stream_type` is the stream type of the data, or -1 if it is not
* known (i.e., if this packet is from PS data).
* - `payload` is the packet data.
* - `payload_len` is the actual length of the payload (for a TS packet,
* this will generally be less than the PES packet's length).
* - if `show_data_len` is non-0 then the data for the PES packet will
* also be shown, up to that length
*
* Returns 0 if all went well, 1 if something went wrong.
*/
extern void report_PES_data_array2(int stream_type,
byte *payload,
int payload_len,
int show_data_len);
// ============================================================
// Server support
// ============================================================
/*
* Packets can be written out to a client via a TS writer, as a
* "side effect" of reading them. The original mechanism was to
* write out PES packets (as TS) as they are read. This will work
* for PS or TS data, and writes out only those PES packets that
* have been read for video or audio data.
*
* An alternative, which will only work for TS input data, is
* to write out TS packets as they are read. This will write all
* TS packets to the client.
*
* - `reader` is our PES reader context
* - `tswriter` is the TS writer
* - if `write_PES`, then write PES packets out as they are read from
* the input, otherwise write TS packets.
* - `program_freq` is how often to write out program data (PAT/PMT)
* if we are writing PES data (if we are writing TS data, then the
* program data will be in the original TS packets)
*/
extern void set_server_output(PES_reader_p reader,
TS_writer_p tswriter,
int write_PES,
int program_freq);
/*
* Start packets being written out to a TS writer (again).
*
* If packets were already being written out, this does nothing.
*
* If set_server_output() has not been called to define a TS writer
* context, this will have no effect.
*
* If `reader` is NULL, nothing is done.
*/
extern void start_server_output(PES_reader_p reader);
/*
* Stop packets being written out to a TS writer.
*
* If packets were already not being written out, this does nothing.
*
* If set_server_output() has not been called to define a TS writer
* context, this will have no effect.
*
* If `reader` is NULL, nothing is done.
*/
extern void stop_server_output(PES_reader_p reader);
/*
* When outputting PES packets in "normal play" mode, add ``extra`` PES
* packets (of the same size as each real packet) to the output. This
* makes the amount of data output be about ``extra``+1 times the amount
* read (the discrepancy is due to any program data being written).
*
* This "expansion" or "padding" of the data can be useful for benchmarking
* the recipient, as the extra data (which has an irrelevant stream id)
* will be ignored by the video processor, but not by preceding systems.
*
* This does nothing if TS packets are being output directly.
*
* - `reader` is our PES reader context
* - `extra` is how many extra packets to output per "real" packet.
*/
extern void set_server_padding(PES_reader_p reader,
int extra);
/*
* Write out TS program data based on the information we have within the given
* PES reader context (as amended by any calls of
* `set_PES_reader_program_data`).
*
* Returns 0 if all goes well, 1 if something goes wrong.
*/
extern int write_program_data(PES_reader_p reader,
TS_writer_p output);
#endif // _pes_fns
// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 expandtab: