/* * Functions for working with H.222 Transport Stream packets - in particular, * for writing PES packets. * * ***** 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 _ts_fns #define _ts_fns #include "compat.h" #include "h222_defns.h" #include "tswrite_defns.h" #include "pidint_defns.h" #include "ts_defns.h" // ============================================================ // Writing a Transport Stream // ============================================================ /* * Write out a Transport Stream PAT and PMT. * * - `output` is the TS output context returned by `tswrite_open` * - `transport_stream_id` is the id for this particular transport stream. * - `program_number` is the program number to use for the PID. * - `pmt_pid` is the PID for the PMT. * - `pid` is the PID of the stream to enter in the tables. This is also * used as the PCR PID. * - `stream_type` is the type of stream. MPEG-2 video is 0x01, * MPEG-4/AVC (H.264) is 0x1b. * * Since we're outputting a TS representing a single ES, we only need to * support a single program stream, containing a single PID. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_TS_program_data(TS_writer_p output, uint32_t transport_stream_id, uint32_t program_number, uint32_t pmt_pid, uint32_t pid, byte stream_type); /* * Write out a Transport Stream PAT and PMT, for multiple streams. * * - `output` is the TS output context returned by `tswrite_open` * - `transport_stream_id` is the id for this particular transport stream. * - `program_number` is the program number to use for the PMT PID. * - `pmt_pid` is the PID for the PMT. * - `pcr_pid` is the PID that contains the PCR. * - `num_progs` is how many program streams are to be defined. * - `prog_pid` is an array of audio/video PIDs * - `prog_type` is an array of the corresponding stream types * * Note that if `num_progs` is 0, `pcr_pid` is ignored. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_TS_program_data2(TS_writer_p output, uint32_t transport_stream_id, uint32_t program_number, uint32_t pmt_pid, uint32_t pcr_pid, int num_progs, uint32_t prog_pid[], byte prog_type[]); /* * Write out a Transport Stream PAT. * * - `output` is the TS output context returned by `tswrite_open` * - `transport_stream_id` is the id for this particular transport stream. * - `prog_list` is a PIDINT list of program number / PID pairs. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_pat(TS_writer_p output, uint32_t transport_stream_id, pidint_list_p prog_list); /* * Write out a Transport Stream PMT, given a PMT datastructure * * - `output` is the TS output context returned by `tswrite_open` * - `pmt_pid` is the PID for the PMT. * - 'pmt' is the datastructure containing the PMT information * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_pmt(TS_writer_p output, uint32_t pmt_pid, pmt_p pmt); /* * Write out a Transport Stream PAT and PMT, given the appropriate * datastructures * * - `output` is the TS output context returned by `tswrite_open` * - `transport_stream_id` is the id for this particular transport stream. * - `prog_list` is a PIDINT list of program number / PID pairs. * - `pmt_pid` is the PID for the PMT. * - 'pmt' is the datastructure containing the PMT information * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_pat_and_pmt(TS_writer_p output, uint32_t transport_stream_id, pidint_list_p prog_list, uint32_t pmt_pid, pmt_p pmt); /* * Write out a Transport Stream PAT, for a single program. * * - `output` is the TS output context returned by `tswrite_open` * - `transport_stream_id` is the id for this particular transport stream. * - `program_number` is the program number to use for the PID. * - `pmt_pid` is the PID for the PMT. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_single_program_pat(TS_writer_p output, uint32_t transport_stream_id, uint32_t program_number, uint32_t pmt_pid); /* * Write out our ES data as a Transport Stream PES packet. * * - `output` is the TS output context returned by `tswrite_open` * - `data` is our ES data (e.g., a NAL unit) * - `data_len` is its length * - `pid` is the PID to use for this TS packet * - `stream_id` is the PES packet stream id to use (e.g., * DEFAULT_VIDEO_STREAM_ID) * * If the data to be written is more than 65535 bytes long (i.e., the * length will not fit into 2 bytes), then the PES packet written will * have PES_packet_length set to zero (see ISO/IEC 13818-1 (H.222.0) * 2.4.3.7, Semantic definitions of fields in PES packet). This is only * allowed for video streams. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_ES_as_TS_PES_packet(TS_writer_p output, byte data[], uint32_t data_len, uint32_t pid, byte stream_id); /* * Write out our ES data as a Transport Stream PES packet, with PTS and/or DTS * if we've got them, and some attempt to write out a sensible PCR. * * - `output` is the TS output context returned by `tswrite_open` * - `data` is our ES data (e.g., a NAL unit) * - `data_len` is its length * - `pid` is the PID to use for this TS packet * - `stream_id` is the PES packet stream id to use (e.g., * DEFAULT_VIDEO_STREAM_ID) * - `got_pts` is TRUE if we have a PTS value, in which case * - `pts` is said PTS value * - `got_dts` is TRUE if we also have DTS, in which case * - `dts` is said DTS value. * * We also want to try to write out a sensible PCR value. * * PTS can go up as well as down (it is the time at which the next frame * should be presented to the user, but frames do not necessarily occur * in presentation order). * * DTS only goes up, since it is the time that the frame should be decoded. * * Thus, if we have it, the DTS is sensible to use for the PCR... * * If the data to be written is more than 65535 bytes long (i.e., the * length will not fit into 2 bytes), then the PES packet written will * have PES_packet_length set to zero (see ISO/IEC 13818-1 (H.222.0) * 2.4.3.7, Semantic definitions of fields in PES packet). This is only * allowed for video streams. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_ES_as_TS_PES_packet_with_pts_dts(TS_writer_p output, byte data[], uint32_t data_len, uint32_t pid, byte stream_id, int got_pts, uint64_t pts, int got_dts, uint64_t dts); /* * Write out our ES data as a Transport Stream PES packet, with PCR. * * - `output` is the TS output context returned by `tswrite_open` * - `data` is our ES data (e.g., a NAL unit) * - `data_len` is its length * - `pid` is the PID to use for this TS packet * - `stream_id` is the PES packet stream id to use (e.g., * DEFAULT_VIDEO_STREAM_ID) * - `pcr_base` and `pcr_extn` encode the PCR value. * * If the data to be written is more than 65535 bytes long (i.e., the * length will not fit into 2 bytes), then the PES packet written will * have PES_packet_length set to zero (see ISO/IEC 13818-1 (H.222.0) * 2.4.3.7, Semantic definitions of fields in PES packet). This is only * allowed for video streams. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_ES_as_TS_PES_packet_with_pcr(TS_writer_p output, byte data[], uint32_t data_len, uint32_t pid, byte stream_id, uint64_t pcr_base, uint32_t pcr_extn); /* * Write out a PES packet's data as a Transport Stream PES packet. * * - `output` is the TS output context returned by `tswrite_open` * - `data` is our PES data (e.g., a program stream video data packet) * - `data_len` is its length * - `pid` is the PID to use for this TS packet * - `stream_id` is the PES packet stream id to use (e.g., * DEFAULT_VIDEO_STREAM_ID) * - `got_pcr` is TRUE if we have values for the PCR in this packet, * in which case `pcr_base` and `pcr_extn` are the parts of the PCR. * * If the data to be written is more than 65535 bytes long (i.e., the * length will not fit into 2 bytes), then the PES packet written will * have PES_packet_length set to zero (see ISO/IEC 13818-1 (H.222.0) * 2.4.3.7, Semantic definitions of fields in PES packet). This is only * allowed for video streams. * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_PES_as_TS_PES_packet(TS_writer_p output, byte data[], uint32_t data_len, uint32_t pid, byte stream_id, int got_pcr, uint64_t pcr_base, uint32_t pcr_extn); /* * Write out a Transport Stream Null packet. * * - `output` is the TS output context returned by `tswrite_open` * * Returns 0 if it worked, 1 if something went wrong. */ extern int write_TS_null_packet(TS_writer_p output); // ============================================================ // Reading a Transport Stream // ============================================================ // ------------------------------------------------------------ // File handling // ------------------------------------------------------------ /* * Build a TS packet reader, including its read-ahead buffer * * - `file` is the file that the TS packets will be read from * * Returns 0 if all goes well, 1 if something goes wrong. */ extern int build_TS_reader(int file, TS_reader_p *tsreader); /* * Build a TS packet reader using the given functions as read() and seek(). * * Returns 0 on success, 1 on failure. */ extern int build_TS_reader_with_fns(void *handle, int (*read_fn)(void *, byte *, size_t), int (*seek_fn)(void *, offset_t), TS_reader_p *tsreader); /* * Open a file to read TS packets from. * * If `filename` is NULL, then the input will be taken from standard input. * * Returns 0 if all goes well, 1 if something goes wrong. */ extern int open_file_for_TS_read(char *filename, TS_reader_p *tsreader); /* * Free a TS packet read-ahead buffer * * Sets `buffer` to NULL. */ extern void free_TS_reader(TS_reader_p *tsreader); /* * Free a TS packet read-ahead buffer and close the referenced file * (if it is not standard input). * * Sets `buffer` to NULL, whether the file close succeeds or not. * * Returns 0 if all goes well, 1 if something goes wrong. */ extern int close_TS_reader(TS_reader_p *tsreader); /* * Seek to a given offset in the TS reader's file * * (This should be used in preference to just seeking on the "bare" file * since it also unsets the read-ahead buffer. However, it is still just * a wrapper around `seek_file`.) * * It is assumed (but not checked) that the seek will end up at an appropriate * offset for reading a TS packet - i.e., presumably some multiple of * TS_PACKET_SIZE. * * Returns 0 if all goes well, 1 if something goes wrong */ extern int seek_using_TS_reader(TS_reader_p tsreader, offset_t posn); /* * Read the (rest of the) first TS packet, given its first four bytes * * This is intended for use after inspecting the first four bytes of the * input file, to determine if the file is TS or PS. * * - `tsreader` is the TS packet reading context * - `start` is the first four bytes of the file * - `packet` is (a pointer to) the resultant TS packet. * * This is a pointer into the reader's read-ahead buffer, and so should not * be freed. Note that this means that it may not persist after another call * of this function (and will not persist after a call of * `free_TS_reader`). * * Note that the caller is trusted to call this only when appropriate. * * 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_rest_of_first_TS_packet(TS_reader_p tsreader, byte start[4], byte **packet); /* * Read the next TS packet. * * - `tsreader` is the TS packet reading context * - `packet` is (a pointer to) the resultant TS packet. * * This is a pointer into the reader's read-ahead buffer, and so should not * be freed. Note that this means that it may not persist after another call * of this function (and will not persist after a call of * `free_TS_reader`). * * 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_next_TS_packet(TS_reader_p tsreader, byte **packet); // ------------------------------------------------------------ // Reading a transport stream with buffered timing // Keeps a PCR in hand, so that it has accurate timing information // for each TS packet // ------------------------------------------------------------ /* Set up the the "looping" buffered TS packet reader and let it know what its * PCR PID is. * * This must be called before any other _buffered_TS_packet function. * * - `pcr_pid` is the PID within which we should look for PCR entries * * Returns 0 if all went well, 1 if something went wrong (allocating space * for the TS PCR buffer). */ extern int prime_read_buffered_TS_packet(TS_reader_p tsreader, uint32_t pcr_pid); /* Retrieve the first TS packet from the PCR read-ahead buffer, * complete with its calculated PCR time. * * prime_read_buffered_TS_packet() must have been called before this. * * This should be called the first time a TS packet is to be read * using the PCR read-ahead buffer. It "primes" the read-ahead mechanism * by performing the first actual read-ahead. * * - `pcr_pid` is the PID within which we should look for PCR entries * - `start_count` is the index of the current (last read) TS entry (which will * generally be the PMT). * - `data` returns a pointer to the TS packet data * - `pid` is its PID * - `pcr` is its PCR, calculated using the previous known PCR and * the following known PCR. * - `count` is the index of the returned TS packet in the file * * Note that, like read_next_TS_packet, we return a pointer to our data, * and, similarly, warn that it will go away next time this function * is called. * * Returns 0 if all went well, 1 if something went wrong, EOF if EOF was read. */ extern int read_first_TS_packet_from_buffer(TS_reader_p tsreader, uint32_t pcr_pid, uint32_t start_count, byte *data[TS_PACKET_SIZE], uint32_t *pid, uint64_t *pcr, uint32_t *count); /* Retrieve the next TS packet from the PCR read-ahead buffer, * complete with its calculated PCR time. * * - `data` returns a pointer to the TS packet data * - `pid` is its PID * - `pcr` is its PCR, calculated using the previous known PCR and * the following known PCR. * * Note that, like read_next_TS_packet, we return a pointer to our data, * and, similarly, warn that it might go away next time this function * is called. * * Returns 0 if all went well, 1 if something went wrong, EOF if EOF was read. */ extern int read_next_TS_packet_from_buffer(TS_reader_p tsreader, byte *data[TS_PACKET_SIZE], uint32_t *pid, uint64_t *pcr); /* * Read the next TS packet, coping with looping, etc. * * prime_read_buffered_TS_packet() should have been called first. * * This is a convenience wrapper around read_first_TS_packet_from_buffer() * and read_next_TS_packet_from_buffer(). * * This differs from ``read_TS_packet`` in that it assumes that the * underlying code will already have read to the next PCR, so that * it can know the *actual* (PCR-based) time for each TS packet. * * - `tsreader` is the TS reader context * - `count` is a running count of TS packets read from this input * - `data` is a pointer to the data for the packet * - `pid` is the PID of the TS packet * - `pcr` is the PCR value (possibly calculated) for this TS packet * - if `max` is greater than zero, then at most `max` TS packets should * be read from the input * - if `loop`, play the input file repeatedly (up to `max` TS packets * if applicable) - i.e., rewind to `start_posn` and start again if * `count` reaches `max` (obviously only if `max` is greater than zero). * - `start_count` is the value `count` should have after we've looped back * to `start_posn` * - if `quiet` is true, then only error messages should be written out * * Returns 0 if all went well, 1 if something went wrong, EOF if `loop` is * false and either EOF was read, or `max` TS packets were read. */ extern int read_buffered_TS_packet(TS_reader_p tsreader, uint32_t *count, byte *data[TS_PACKET_SIZE], uint32_t *pid, uint64_t *pcr, int max, int loop, offset_t start_posn, uint32_t start_count, int quiet); // ------------------------------------------------------------ // Packet interpretation // ------------------------------------------------------------ /* * Retrieve the PCR (if any) from a TS packet's adaptation field * * - `adapt` is the adaptation field content * - `adapt_len` is its length * - `got_PCR` is TRUE if the adaptation field contains a PCR * - `pcr` is then the PCR value itself */ extern void get_PCR_from_adaptation_field(byte adapt[], int adapt_len, int *got_pcr, uint64_t *pcr); /* * Report on the contents of this TS packet's adaptation field * * - `adapt` is the adaptation field content * - `adapt_len` is its length * * Returns 0 if all went well, 1 if something went wrong. */ extern void report_adaptation_field(byte adapt[], int adapt_len); /* * Report on the timing information from this TS packet's adaptation field * * - if `times` is non-NULL, then timing information (derived from the PCR) * will be calculated and reported * - `adapt` is the adaptation field content * - `adapt_len` is its length * - `packet_count` is a count of how many TS packets up to now * * Returns 0 if all went well, 1 if something went wrong. */ extern void report_adaptation_timing(timing_p times, byte adapt[], int adapt_len, int packet_count); /* * Report on the contents of this TS packet's payload. The packet is assumed * to have a payload that is (part of) a PES packet. * * - if `show_data` then the data for the PES packet will also be shown * - `stream_type` is the stream type of the data, or -1 if it is not * known * - `payload` is the payload of the TS packet. We know it can't be more * than 184 bytes long, because of the packet header bytes. * - regardless, `payload_len` is the actual length of the payload. * * Returns 0 if all went well, 1 if something went wrong. */ extern void report_payload(int show_data, int stream_type, byte payload[MAX_TS_PAYLOAD_SIZE], int payload_len, int payload_unit_start_indicator); /* * Print out information about program descriptors * (either from the PMT program info, or the PMT/stream ES info) * * - if `is_msg` then print as a message, otherwise as an error * - `leader1` and `leader2` are the text to write at the start of each line * (either or both may be NULL) * - `desc_data` is the data containing the descriptors * - `desc_data_len` is its length * * Returns 0 if all went well, 1 if something went wrong */ extern int print_descriptors(int is_msg, char *leader1, char *leader2, byte *desc_data, int desc_data_len); /* * Extract the program list from a PAT packet (PID 0x0000). * * Handles the result of calling build_psi_data() for this PAT. * * - if `verbose`, then report on what we're doing * - `payload` is the payload of the TS packet. We know it can't be more * than 184 bytes long, because of the packet header bytes. * - regardless, `payload_len` is the actual length of the payload. * - `prog_list` is the list of program numbers versus PIDs. * * Returns 0 if all went well, 1 if something went wrong. */ extern int extract_prog_list_from_pat(int verbose, byte payload[MAX_TS_PAYLOAD_SIZE], int payload_len, pidint_list_p *prog_list); /* * Extract the stream list (and PCR PID) from a PMT packet. * * Handles the result of calling build_psi_data() for this PMT. * * - if `verbose`, then report on what we're doing * - `payload` is the payload of the TS packet. We know it can't be more * than 184 bytes long, because of the packet header bytes. * - regardless, `payload_len` is the actual length of the payload. * - `pid` is the PID of this TS packet. * - `program_number` is the program number. * - `pcr_pid` is the PID of packets containing the PCR, or 0. * - `stream_list` is a list of stream versus PID. * * Returns 0 if all went well, 1 if something went wrong. */ extern int extract_stream_list_from_pmt(int verbose, byte payload[MAX_TS_PAYLOAD_SIZE], int payload_len, uint32_t pid, int *program_number, uint32_t *pcr_pid, pidint_list_p *stream_list); /* * Given a TS packet, extract the (next bit of) a PAT/PMT's data. * * - if `verbose`, then report on what we're doing * - `payload` is the payload of the current TS packet. We know it can't be * more than 184 bytes long, because of the packet header bytes. * - regardless, `payload_len` is the actual length of the payload. * - `pid` is the PID of this TS packet. * - `data` is the data array for the whole of the data of this PSI. * If it is passed as NULL, then the TS packet must be the first for * this PSI, and this function will malloc an array of the appropriate * length (and return it here). If it is non-NULL, then it is partially * full. * - `data_len` is the actual length of the `data` array -- if `data` is NULL * then this will be set by the function. * - `data_used` is how many bytes of data are already in the `data` array. * This will be updated by this function - if it is returned as equal to * `data_len`, then the PMT packet data is complete. * * Usage: * * If a PSI packet has PUSI set, then it is the first packet of said PSI * (which, for our purposes, means PAT or PMT). If it does not, then it * is a continuation. If PUSI was set, call this with ``data`` NULL, otherwise * pass it some previous data to continue. * * Returns 0 if all went well, 1 if something went wrong. */ extern int build_psi_data(int verbose, byte payload[MAX_TS_PAYLOAD_SIZE], int payload_len, uint32_t pid, byte **data, int *data_len, int *data_used); /* * Extract the program map table from a PMT packet. * * Assumes that the whole content of the PMT is in this single packet. * * - `data` is the data for the PMT packet. * - `data_len` is the length of said data. * - `pid` is the PID of this PMT * - `pmt` is the new PMT datastructure * * Returns 0 if all went well, 1 if something went wrong. */ extern int extract_pmt(int verbose, byte data[], int data_len, uint32_t pid, pmt_p *pmt); /* * Split a TS packet into its main parts * * - `buf` is the data for the packet * - `pid` is the PID of said data * - `payload_unit_start_indicator` is TRUE if any payload in this * packet forms the start of a PES packet. Its meaning is not significant * if there is no payload, or if the payload is not (part of) a PES packet. * - `adapt` is an offset into `buf`, acting as an array of the actual * adaptation control bytes. It will be NULL if there are no adaptation * controls. * - `adapt_len` is the length of the adaptation controls (i.e., the * number of bytes). It will be 0 if there are no adaptation controls. * - `payload` is an offset into `buf`, acting as an array of the actual * payload bytes. It will be NULL if there is no payload. * - `payload_len` is the length of the payload *in this packet* (i.e., the * number of bytes. It will be 0 if there is no payload. * * Returns 0 if all went well, 1 if something went wrong. */ extern int split_TS_packet(byte buf[TS_PACKET_SIZE], uint32_t *pid, int *payload_unit_start_indicator, byte *adapt[], int *adapt_len, byte *payload[], int *payload_len); /* * Return the next TS packet, as payload and adaptation controls. * * This is a convenience wrapping of `read_next_TS_packet` and * `split_TS_packet`. Because of this, the data referenced by `adapt` and * `payload` will generally not persist over further calls of this function * and `read_next_TS_packet`, as it is held within the TS reader's read-ahead * buffer. * * - `tsreader` is the TS packet reading context * - `pid` is the PID of said data * - `payload_unit_start_indicator` is TRUE if any payload in this * packet forms the start of a PES packet. Its meaning is not significant * if there is no payload, or if the payload is not (part of) a PES packet. * - `adapt` is an offset into `buf`, acting as an array of the actual * adaptation control bytes. It will be NULL if there are no adaptation * controls. * - `adapt_len` is the length of the adaptation controls (i.e., the * number of bytes). It will be 0 if there are no adaptation controls. * - `payload` is an offset into `buf`, acting as an array of the actual * payload bytes. It will be NULL if there is no payload. * - `payload_len` is the length of the payload *in this packet* (i.e., the * number of bytes. It will be 0 if there is no payload. * * Returns 0 if all went well, EOF if there is no more data, 1 if something * went wrong. */ extern int get_next_TS_packet(TS_reader_p tsreader, uint32_t *pid, int *payload_unit_start_indicator, byte *adapt[], int *adapt_len, byte *payload[], int *payload_len); /* * Find the first (next) PAT. * * - `tsreader` is the TS packet reading context * - if `max` is non-zero, then it is the maximum number of TS packets to read * - if `verbose` is true, then output extra information * - if `quiet` is true, then don't output normal informational messages * - `num_read` is the number of packets read to find the PAT (or before * giving up) * - `prog_list` is the program list from the PAT, or NULL if none was found * * Returns 0 if all went well, EOF if no PAT was found, * 1 if something else went wrong. */ extern int find_pat(TS_reader_p tsreader, int max, int verbose, int quiet, int *num_read, pidint_list_p *prog_list); /* * Find the next PMT, and report on it. * * - `tsreader` is the TS packet reading context * - `pmt_pid` is the PID of the PMT we are looking for * - if `program_number` is -1, then any PMT with that PID is acceptable, * otherwise we're only interested in a PMT with that PID and the given * program number. * - if `max` is non-zero, then it is the maximum number of TS packets to read * - if `verbose` is true, then output extra information * - if `quiet` is true, then don't output normal informational messages * - `num_read` is the number of packets read to find the PMT (or before * giving up) * - `pmt` is a new datastructure representing the PMT found * * Returns 0 if all went well, EOF if no PMT was found, * 1 if something else went wrong. */ extern int find_next_pmt(TS_reader_p tsreader, uint32_t pmt_pid, int program_number, int max, int verbose,int quiet, int *num_read, pmt_p *pmt); /* * Find the next PAT, and from that the next PMT. * * Looks for the next PAT in the input stream, and then for the first * PMT thereafter. If there is more than one program stream in the PAT, * it looks for the PMT for the first. * * - `tsreader` is the TS packet reading context * - if `max` is non-zero, then it is the maximum number of TS packets to read * - if `verbose` is true, then output extra information * - if `quiet` is true, then don't output normal informational messages * - `num_read` is the number of packets read to find the PMT (or before * giving up) * - `pmt` is a new datastructure containing the information from the PMT. * * Returns 0 if all went well, EOF if no PAT or PMT was found (and thus * no program stream), -2 if a PAT was found but it did not contain any * programs, 1 if something else went wrong. */ extern int find_pmt(TS_reader_p tsreader, const int req_prog_no, int max, int verbose, int quiet, int *num_read, pmt_p *pmt); #endif // _ts_fns // Local Variables: // tab-width: 8 // indent-tabs-mode: nil // c-basic-offset: 2 // End: // vim: set tabstop=8 shiftwidth=2 expandtab: