F5OEO-tstools/es_fns.h

433 wiersze
14 KiB
C
Czysty Zwykły widok Historia

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