/* * 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" 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 * " * - `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: