F5OEO-tstools/es_fns.h

433 wiersze
14 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.

/*
* Prototypes for handling H.264 elementary streams.
*
* ***** 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 _es_fns
#define _es_fns
#include "es_defns.h"
// ============================================================
// Elementary stream functions - basic
// ============================================================
/*
* Open an ES file and build an elementary stream datastructure to read
* it with.
*
* - `filename` is the ES files name
*
* Opens the file for read, builds the datastructure, and reads the first 3
* bytes of the input file (this is done to prime the triple-byte search
* mechanism).
*
* Use `close_elementary_stream` to close the stream and the file.
*
* Returns 0 if all goes well, 1 otherwise.
*/
extern int open_elementary_stream(char *filename,
ES_p *es);
/*
* Build an elementary stream datastructure attached to an input file.
* This is intended for reading ES data files.
*
* - `input` is the file stream to read from.
*
* Builds the datastructure, and reads the first 3 bytes of the input
* file (this is done to prime the triple-byte search mechanism).
*
* Use `free_elementary_stream` to release the ES context without closing
* the associated file.
*
* Returns 0 if all goes well, 1 otherwise.
*/
extern int build_elementary_stream_file(int input,
ES_p *es);
/*
* Build an elementary stream datastructure for use with a PES reader.
* Reads the first (or next) three bytes of the ES.
*
* This reads data from the PES video data, ignoring any audio data.
*
* - `reader` is the PES reader we want to use to read our TS or PS data.
*
* The caller must explicitly close the PES reader as well as closing the
* elementary stream (closing the ES does not affect the PES reader).
*
* Returns 0 if all goes well, 1 otherwise.
*/
extern int build_elementary_stream_PES(PES_reader_p reader,
ES_p *es);
/*
* Tidy up the elementary stream datastructure after we've finished with it.
*
* Specifically:
*
* - free the datastructure
* - set `es` to NULL
*
* No return status is given, since there's not much one can do if anything
* *did* go wrong, and if something went wrong and the program is continuing,
* it's bound to show up pretty soon.
*/
extern void free_elementary_stream(ES_p *es);
/*
* Tidy up the elementary stream datastructure after we've finished with it.
*
* Specifically:
*
* - close the input file (if its stream is set, and if it's not STDIN)
* - call `free_elementary_stream()`
*
* No return status is given, since there's not much one can do if anything
* *did* go wrong, and if something went wrong and the program is continuing,
* it's bound to show up pretty soon.
*/
extern void close_elementary_stream(ES_p *es);
/*
* Ask an ES context if changed input is available.
*
* This is a convenience wrapper to save querying the ES context to see
* if it is (a) reading from PES, (b) automatically writing the PES packets
* out via a TS writer, and (c) if said TS writer has a changed command.
*
* Calls `tswrite_command_changed()` on the TS writer associated with this ES.
*
* Returns TRUE if there is a changed command.
*/
extern int es_command_changed(ES_p es);
// ============================================================
// Elementary stream functions - item/unit reading
// ============================================================
/*
* Prepare the contents of a (new) ES unit datastructure.
*
* Allocates a new data array, and unsets the counts.
*
* Returns 0 if it succeeds, 1 if some error occurs.
*/
extern int setup_ES_unit(ES_unit_p unit);
/*
* Tidy up an ES unit datastructure after we've finished with it.
*
* (Frees the internal data array, and unsets the counts)
*/
extern void clear_ES_unit(ES_unit_p unit);
/*
* Build a new ES unit datastructure.
*
* Returns 0 if it succeeds, 1 if some error occurs.
*/
extern int build_ES_unit(ES_unit_p *unit);
/*
* Build a new ES unit datastructure, from a given data array.
*
* Takes a copy of 'data'. Sets 'start_code' appropriately,
* sets 'start_posn' to (0,0), and 'PES_had_PTS' to FALSE.
*
* Returns 0 if it succeeds, 1 if some error occurs.
*/
extern int build_ES_unit_from_data(ES_unit_p *unit,
byte *data,
uint32_t data_len);
/*
* Tidy up and free an ES unit datastructure after we've finished with it.
*
* Empties the ES unit datastructure, frees it, and sets `unit` to NULL.
*
* If `unit` is already NULL, does nothing.
*/
extern void free_ES_unit(ES_unit_p *unit);
/*
* Print out some information this ES unit, on normal or error output
*/
extern void report_ES_unit(int is_msg,
ES_unit_p unit);
/*
* Retrieve ES data from the end of a PES packet. It is assumed (i.e, things
* will go wrong if it is not true) that at least one ES unit has been read
* from the PES data stream via the ES reader.
*
* - `es` is our ES reader. It must be reading ES from PES packets.
* - `data` is the ES data remaining (to be read) in the current PES packet.
* It is up to the caller to free this data.
* - `data_len` is the length of said data. If this is 0, then `data`
* will be NULL.
*
* Returns 0 if all goes well, 1 if an error occurs.
*/
extern int get_end_of_underlying_PES_packet(ES_p es,
byte **data,
int *data_len);
/*
* Find and read in the next ES unit.
*
* In general, unless there are compelling reasons, use
* `find_and_build_next_ES_unit()` instead.
*
* - `es` is the elementary stream we're reading from.
* - `unit` is the datastructure into which to read the ES unit
* - any previous content will be lost.
*
* Returns 0 if it succeeds, EOF if the end-of-file is read (i.e., there
* is no next ES unit), otherwise 1 if some error occurs.
*/
extern int find_next_ES_unit(ES_p es,
ES_unit_p unit);
/*
* Find and read the next ES unit into a new datastructure.
*
* - `es` is the elementary stream we're reading from.
* - `count` is an integer to use as an id for this ES unit - typically
* its index in the input stream
* - `unit` is the datastructure containing the ES unit found, or NULL
* if there was none.
*
* Returns 0 if it succeeds, EOF if the end-of-file is read (i.e., there
* is no next ES unit), otherwise 1 if some error occurs.
*/
extern int find_and_build_next_ES_unit(ES_p es,
ES_unit_p *unit);
/*
* Write (copy) the current ES unit to the output stream.
*
* Note that it writes out all of the data for this ES unit,
* including its 00 00 01 start code prefix.
*
* - `output` is the output stream (file descriptor) to write to
* - `unit` is the ES unit to write
*
* Returns 0 if all went well, 1 if something went wrong.
*/
extern int write_ES_unit(FILE *output,
ES_unit_p unit);
// ------------------------------------------------------------
// Arbitrary reading from ES data
// ------------------------------------------------------------
/*
* "Seek" to the given position in the ES data, which is assumed to
* be an offset ready to read a 00 00 01 sequence.
*
* If the ES reader is using PES to read its data, then both fields
* of `where` are significant, but if the underlying file *is* just a file,
* only `where.infile` is used.
*
* Returns 0 if all went well, 1 is something went wrong
*/
extern int seek_ES(ES_p es,
ES_offset where);
/*
* Read in some ES data from disk.
*
* Suitable for use when reading in a set of ES units whose bounds
* (start offset and total number of bytes) have been remembered.
*
* "Seeks" to the given position in the ES data, which is assumed to
* be an offset ready to read a 00 00 01 sequence, and reads data thereafter.
*
* After this function, the triple byte context is set to FF FF FF, and the
* position of said bytes are undefined, but the next position to read a byte
* from *is* defined.
*
* The intent is to allow the caller to have a data array (`data`) that
* always contains the last data read, and is of the required size, and
* need only be freed when no more data is needed.
*
* - `es` is where to read our data from
* - `start_posn` is the file offset to start reading at
* - `num_bytes` is how many bytes we want to read
* - `data_len` may be NULL or a pointer to a value.
* If it is NULL, then the data array will be reallocated to size
* `num_bytes` regardless. If it is non-NULL, it should be passed *in*
* as the size that `data` *was*, and will be returned as the size
* that `data` is when the function returns.
* - `data` is the data array to read into. If this is NULL, or if `num_bytes`
* is NULL, or if `num_bytes` is greater than `data_len`, then it will be
* reallocated to size `num_bytes`.
*
* Returns 0 if all went well, 1 if something went wrong.
*/
extern int read_ES_data(ES_p es,
ES_offset start_posn,
uint32_t num_bytes,
uint32_t *data_len,
byte **data);
// ============================================================
// Lists of ES units
// ============================================================
/*
* Build a new list-of-ES-units datastructure.
*
* Returns 0 if it succeeds, 1 if some error occurs.
*/
extern int build_ES_unit_list(ES_unit_list_p *list);
/*
* Add a copy of an ES unit to the end of the ES unit list
*
* Note that since this takes a copy of the ES unit's data, it is safe
* to free the original ES unit.
*
* Returns 0 if it succeeds, 1 if some error occurs.
*/
extern int append_to_ES_unit_list(ES_unit_list_p list,
ES_unit_p unit);
/*
* Reset (empty) an ES unit list.
*/
extern void reset_ES_unit_list(ES_unit_list_p list);
/*
* Tidy up and free an ES unit list datastructure after we've finished with it.
*
* Clears the datastructure, frees it and returns `list` as NULL.
*
* Does nothing if `list` is already NULL.
*/
extern void free_ES_unit_list(ES_unit_list_p *list);
/*
* Report on an ES unit list's contents.
*
* - `name` is the name of the list (used in the header)
* - `list` is the list to report on
*/
extern void report_ES_unit_list(char *name,
ES_unit_list_p list);
/*
* Retrieve the bounds of this ES unit list in the file it was read from.
*
* - `list` is the ES unit list we're interested in
* - `start` is its start position (i.e., the location at which to start
* reading to retrieve all of the data for the list)
* - `length` is the total length of the ES units within this list
*
* Returns 0 if all goes well, 1 if the ES unit list has no content.
*/
extern int get_ES_unit_list_bounds(ES_unit_list_p list,
ES_offset *start,
uint32_t *length);
/*
* Compare two ES unit lists. The comparison does not include the start
* position of the unit data, but just the actual data - i.e., two unit lists
* read from different locations in the input stream may be considered the
* same if their data content is identical.
*
* - `list1` and `list2` are the two ES unit lists to compare.
*
* Returns TRUE if the lists contain identical content, FALSE otherwise.
*/
extern int same_ES_unit_list(ES_unit_list_p list1,
ES_unit_list_p list2);
/*
* Compare two ES offsets
*
* Returns -1 if offset1 < offset2, 0 if they are the same, and 1 if
* offset1 > offset2.
*/
extern int compare_ES_offsets(ES_offset offset1,
ES_offset offset2);
// ============================================================
// Simple file type guessing
// ============================================================
/*
* Look at the start of an elementary stream to try to determine its
* video type.
*
* "Eats" the ES units that it looks at, and doesn't rewind the stream
* afterwards.
*
* - `es` is the ES file
* - if `print_dots` is true, print a dot for each ES unit that is inspected
* - if `show_reasoning` is true, then output messages explaining how the
* decision is being made
* - `video_type` is the final decision -- one of VIDEO_H264, VIDEO_H262,
* VIDEO_AVS, or VIDEO_UNKNOWN.
*
* Returns 0 if all goes well, 1 if something goes wrong
*/
extern int decide_ES_video_type(ES_p es,
int print_dots,
int show_reasoning,
int *video_type);
/*
* Look at the start of an elementary stream to try to determine it's
* video type.
*
* Note that it is easier to prove something is H.262 (or AVS) than to prove
* that it is H.264, and that the result of this routine is a best-guess, not a
* guarantee.
*
* Rewinds back to the original position in the file after it has finished.
*
* - `input` is the file to look at
* - if `print_dots` is true, print a dot for each ES unit that is inspected
* - if `show_reasoning` is true, then output messages explaining how the
* decision is being made
* - `video_type` is the final decision -- one of VIDEO_H264, VIDEO_H262,
* VIDEO_AVS, or VIDEO_UNKNOWN.
*
* Returns 0 if all goes well, 1 if something goes wrong
*/
extern int decide_ES_file_video_type(int input,
int print_dots,
int show_reasoning,
int *video_type);
#endif // _es_fns
// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 expandtab: