/* * Functions for working with H.222 Program Stream packets - in particular, * for reading 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 _ps_fns #define _ps_fns #include "compat.h" #include "h222_defns.h" #include "tswrite_defns.h" #include "ps_defns.h" // ============================================================ // Program stream reading functions // ============================================================ /* * Build a program stream context attached to an input file. This handles * read-ahead buffering for the PS. * * - `input` is the file stream to read from. * - If `quiet`, then don't report on ignored bytes at the start of the file * - `ps` is the new PS context * * Returns 0 if all goes well, 1 otherwise. */ extern int build_PS_reader(int input, int quiet, PS_reader_p *ps); /* * Tidy up the PS read-ahead context after we've finished with it. * * Specifically: * * - free the datastructure * - set `ps` to NULL * * Does not close the associated file. */ extern void free_PS_reader(PS_reader_p *ps); /* * Open a PS file for reading. * * - `name` is the name of the file * - If `quiet`, then don't report on ignored bytes at the start of the file * - `ps` is the new PS context * * Returns 0 if all goes well, 1 otherwise. */ extern int open_PS_file(char *name, int quiet, PS_reader_p *ps); /* * Close a PS file, and free the reader context * * Returns 0 if all goes well, 1 otherwise. */ extern int close_PS_file(PS_reader_p *ps); /* * Given a program stream, attempt to determine if it holds H.262 or H.264 * data. * * Leaves the PS rewound to its "start". * * NOTE: It is probably better to use determine_PS_video_type(). * * - `ps` is the program stream to check (assumed just to have been * opened/built). This cannot be standard input, as it must be * seekable. * - `is_h264` is the result * * Returns 0 if all goes well, 1 if there was an error (including the * stream not appearing to be either). */ extern int determine_if_PS_is_h264(PS_reader_p ps, int *is_h264); /* * Given a program stream, attempt to determine what type of video data it * contains. * * Leaves the PS rewound to its "start". * * - `ps` is the program stream to check (assumed just to have been * opened/built). This cannot be standard input, as it must be * seekable. * - `video_type` is the result. Calls determine_PES_video_type(). * * Returns 0 if all goes well, 1 if there was an error (including the * stream not appearing to be either). */ extern int determine_PS_video_type(PS_reader_p ps, int *video_type); /* * Seek within the PS file. * * Note that if the intent is to *rewind* to the start of the PS data, * then `rewind_program_stream` should be used instead, as offset 0 is * not necessarily the same as the start of the program stream. * * - `ps` is the PS read-ahead context * - `posn` is the file offset to seek to * * Returns 0 if all goes well, 1 if something goes wrong */ extern int seek_using_PS_reader(PS_reader_p ps, offset_t posn); /* * Rewind the PS context to the remembered "start of data" * * Returns 0 if all goes well, 1 if something goes wrong */ extern int rewind_program_stream(PS_reader_p ps); /* * Print out a stream id in a manner consistent with the PS usages * of the stream id values. */ extern void print_stream_id(int is_msg, byte stream_id); /* * Look for the start (the first 4 bytes) of the next program stream packet. * * Assumes that (for some reason) alignment has been lost, and thus it is * necessary to scan forwards to find the next 00 00 01 prefix. * * Otherwise equivalent to a call of `read_PS_packet_start`. * * - `ps` is the PS read-ahead context we're reading from * - if `verbose`, then we want to explain what we're doing * - if `max` is non-zero, then it is the maximum number of bytes * to scan before giving up. * - `posn` is the file offset of the start of the packet * - `stream_id` is the identifying byte, after the 00 00 01 prefix. Note * that this is set correctly if MPEG_program_end_code was read, and is * 0 if an error occurred. * * Returns: * * 0 if it succeeds, * * EOF if EOF is read, or an MPEG_program_end_code is read, or * * 1 if some error (including the first 3 bytes not being 00 00 01) occurs. */ extern int find_PS_packet_start(PS_reader_p ps, int verbose, uint32_t max, offset_t *posn, byte *stream_id); /* * Look for the next PS pack header. * * Equivalent to calling `find_PS_packet_start` until `stream_id` is 0xBA * (in other words, equivalent to having read the pack header start with * `read_PS_packet_start`). * * If you want to call `read_PS_packet_start` to read this pack header start * in again, then call ``seek_using_PS_reader(ps,posn)`` to reposition ready * to read it. * * - `ps` is the PS read-ahead context we're reading from * - if `verbose`, then the 00 00 01 XX sequences found will be logged * to stderr, indicating the progress of our search * - if `max` is non-zero, then it is the maximum number of bytes * to scan before giving up. * - `posn` is the file offset of the start of the packet found * * Returns: * * 0 if it succeeds, * * EOF if EOF is read, or an MPEG_program_end_code is read, or * * 1 if some error (including the first 3 bytes not being 00 00 01) occurs. */ extern int find_PS_pack_header_start(PS_reader_p ps, int verbose, uint32_t max, offset_t *posn); /* * Read in (the rest of) a PS packet according to its length. * * Suitable for use reading PS PES packets and PS system header packets. * * NOTE that the `data` buffer in the `packet` is realloc'ed by this * function. It is thus important to ensure that the `packet` datastructure * contains a NULL pointer for said buffer before the first call of this * function. * * - `ps` is the PS read-ahead context we're reading from * - `stream_id` identifies what sort of packet it is * - `packet` is the packet we're reading the PES packet into. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int read_PS_packet_body(PS_reader_p ps, byte stream_id, PS_packet_p packet); /* * Read in the body of the pack header (but *not* the system header packets * therein). * * - `ps` is the PS read-ahead context we're reading from * - `hdr` is the packet we've read * * Returns 0 if it succeeds, or 1 if some error occurs. */ extern int read_PS_pack_header_body(PS_reader_p ps, PS_pack_header_p hdr); /* * Clear the contents of a PS packet datastructure. Frees the internal * `data` array. */ extern void clear_PS_packet(PS_packet_p packet); /* * Tidy up and free a PS packet datastructure after we've finished with it. * * Empties the PS packet datastructure, frees it, and sets `unit` to NULL. * * If `unit` is already NULL, does nothing. */ extern void free_PS_packet(PS_packet_p *packet); /* * Read in the start (the first 4 bytes) of the next program stream packet. * * If the bytes read don't appear to be valid (i.e., they do not start with * the 00 00 01 prefix), then the next pack header will be sought and read in. * * Note that sequences of 00 bytes before the 00 00 01 will be ignored. * * - `ps` is the PS read-ahead context we're reading from * - if `verbose`, then we want to explain what we're doing * - `posn` is the file offset of the start of the packet * - `stream_id` is the identifying byte, after the 00 00 01 prefix. Note * that this is set correctly if MPEG_program_end_code was read, and is * 0 if an error occurred or reading was ended because `max` packets had * been read. * * Returns: * * 0 if it succeeds, * * EOF if EOF is read, or an MPEG_program_end_code is read, * * 2 if the bytes read are not 00 00 01 `stream_id`, or * * 1 if some other error occurs. */ extern int read_PS_packet_start(PS_reader_p ps, int verbose, offset_t *posn, byte *stream_id); /* * Inspect the given PS packet, and determine if it contains AC3 or DTS audio data. * * - `packet` is the packet's data, already established as private_data_1 * - `is_dvd` is true if the data should be interpreted as DVD data * - if `verbose`, report on the details of what we find out * - `substream_index` returns the substream's index, taken from the low * nibble of the substream id, and adjusted to start at 0. This will be * a value in the range 0-7 for DTS, AC3 and LPCM, and in the range 0-1F * (0-31) for subpictures. * - for AC3, `bsmod` and `acmod` return the appropriate quantities, * otherwise they are 0. * * Returns one of the SUBSTREAM_* values. */ extern int identify_private1_data(struct PS_packet *packet, int is_dvd, int verbose, int *substream_index, byte *bsmod, byte *acmod); // ============================================================ // PS to TS functions // ============================================================ /* * Read program stream and write transport stream * * - `ps` is the program stream * - `output` is the transport stream * - `pad_start` is the number of filler TS packets to start the output * with. * - `program_repeat` is how often (after how many PS packs) to repeat * the program information (PAT/PMT) * - `video_type` indicates what type of video is being transferred. It should * be VIDEO_H264, VIDEO_H262, etc. * - `is_dvd` should be true if this input represents DVD data; i.e., with * private_stream_1 used for AC-3/DTS/etc., and with substream headers * therein. * - `video_stream` indicates which video stream we want - i.e., the stream * with id 0xE0 + . -1 means the first encountered. * - `audio_stream` indicates which audio stream we want. If `want_ac3_audio` * is false, then this will be the stream with id 0xC0 + , * or -1 for the first audio stream encountered. * - if `want_ac3_audio` is true, then if `is_dvd` is true, then we want * audio from private_stream_1 (0xBD) with substream id , * otherwise we ignore `audio_stream` and assume that all data in * private_stream_1 is the audio we want. * - `dolby_is_dvb` should be true if Dolby (AC-3) audio (if selected) should * be output using the DVB stream type 0x06, false if using the ATSC stream * type 0x81. This is ignored if the audio being output is not Dolby. * - `pmt_pid` is the PID of the PMT to write * - `pcr_pid` is the PID of the TS unit containing the PCR * - `video_pid` is the PID for the video we write * - `keep_audio` is true if the audio stream should be output, false if * it should be ignored * - `audio_pid` is the PID for the audio we write * - if `max` is non-zero, then we want to stop reading after we've read * `max` packs * - if `verbose` then we want to output diagnostic information * - if `quiet` then we want to be as quiet as we can * * Returns 0 if all went well, 1 if something went wrong. */ extern int ps_to_ts(PS_reader_p ps, TS_writer_p output, int pad_start, int program_repeat, int video_type, int is_dvd, int video_stream, int audio_stream, int want_ac3_audio, int dolby_is_dvb, uint32_t pmt_pid, uint32_t pcr_pid, uint32_t video_pid, int keep_audio, uint32_t audio_pid, int max, int verbose, int quiet); #endif // _ps_fns // Local Variables: // tab-width: 8 // indent-tabs-mode: nil // c-basic-offset: 2 // End: // vim: set tabstop=8 shiftwidth=2 expandtab: