/* * Functions for working with access units in 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 _accessunit_fns #define _accessunit_fns #include "accessunit_defns.h" /* * Build a new access unit context datastructure. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int build_access_unit_context(ES_p es, access_unit_context_p *context); /* * Free a new access unit context datastructure. * * Clears the datastructure, frees it, and returns `context` as NULL. * * Does not free any `reverse_data` datastructure. * * Does nothing if `context` is already NULL. */ extern void free_access_unit_context(access_unit_context_p *context); /* * Reset an acccess unit context, so it "forgets" its current information * about what it is reading, etc. */ extern void reset_access_unit_context(access_unit_context_p context); /* * Rewind a file being read as access units. * * This is a wrapper for `rewind_nal_unit_context` that also knows to * unset things appropriate to the access unit context. * * If a reverse context is attached to this access unit, it also will * be "rewound" appropriately. * * Returns 0 if all goes well, 1 if something goes wrong. */ extern int rewind_access_unit_context(access_unit_context_p context); /* * Tidy up and free an access unit datastructure after we've finished with it. * * Clears the datastructure, frees it, and returns `acc_unit` as NULL. * * Does nothing if `acc_unit` is already NULL. */ extern void free_access_unit(access_unit_p *acc_unit); /* * Report on this access unit */ extern void report_access_unit(access_unit_p access_unit); /* * Retrieve the bounds of this access unit in the file it was read from. * * - `access_unit` is the access unit 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 access unit, including * the 00 00 01 prefix at the start of the first NAL unit therein) * - `length` is the total length of the NAL units within this access unit * * Returns 0 if all goes well, 1 if the access unit has no content. */ extern int get_access_unit_bounds(access_unit_p access_unit, ES_offset *start, uint32_t *length); /* * Are all slices in this access unit I slices? */ extern int all_slices_I(access_unit_p access_unit); /* * Are all slices in this access unit P slices? */ extern int all_slices_P(access_unit_p access_unit); /* * Are all slices in this access unit I or P slices? */ extern int all_slices_I_or_P(access_unit_p access_unit); /* * Are all slices in this access unit B slices? */ extern int all_slices_B(access_unit_p access_unit); /* * Write out an access unit as ES. * * Also writes out any end of sequence or end of stream NAL unit found in the * `context` (since they are assumed to have immediately followed this access * unit). * * - `access_unit` is the access unit to write out * - `context` may contain additional things to write (see above), but may * legitimately be NULL if there is no context. * - `output` is the ES file to write to * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int write_access_unit_as_ES(access_unit_p access_unit, access_unit_context_p context, FILE *output); /* * Write out an access unit as TS. * * Also writes out any end of sequence or end of stream NAL unit found in the * `context` (since they are assumed to have immediately followed this access * unit). * * - `access_unit` is the access unit to write out * - `context` may contain additional things to write (see above), but may * legitimately be NULL if there is no context. * - `tswriter` is the TS context to write with * - `video_pid` is the PID to use to write the data * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int write_access_unit_as_TS(access_unit_p access_unit, access_unit_context_p context, TS_writer_p tswriter, uint32_t video_pid); /* * Write out an access unit as TS, with PTS timing in the first PES packet * (and PCR timing in the first TS of the frame). * * Also writes out any end of sequence or end of stream NAL unit found in the * `context` (since they are assumed to have immediately followed this access * unit). * * - `access_unit` is the access unit to write out * - `context` may contain additional things to write (see above), but may * legitimately be NULL if there is no context. * - `tswriter` is the TS context to write with * - `video_pid` is the PID to use to write the data * - `pts` is the PTS time (which is also used as the PCR base). * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int write_access_unit_as_TS_with_pts_dts(access_unit_p access_unit, access_unit_context_p context, TS_writer_p tswriter, uint32_t video_pid, int got_pts, uint64_t pts, int got_dts, uint64_t dts); /* * Write out an access unit as TS, with PCR timing in the first TS of the * frame. * * Also writes out any end of sequence or end of stream NAL unit found in the * `context` (since they are assumed to have immediately followed this access * unit). * * - `access_unit` is the access unit to write out * - `context` may contain additional things to write (see above), but may * legitimately be NULL if there is no context. * - `tswriter` is the TS context to write with * - `video_pid` is the PID to use to write the data * - `pcr_base` and `pcr_extn` encode the PCR value. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int write_access_unit_as_TS_with_PCR(access_unit_p access_unit, access_unit_context_p context, TS_writer_p tswriter, uint32_t video_pid, uint64_t pcr_base, uint32_t pcr_extn); /* * Retrieve the next access unit from the given elementary stream. * * - `context` is the context information needed to allow us to find * successive access units. * - `quiet` is true if we should try to be silent about it * - `show_details` is true if we should output more info than normal * - `ret_access_unit` is the next access unit. * * If the access unit was ended because an end of sequence or end of * stream NAL unit was encountered, then said end of sequence/stream * NAL unit will be remembered in the `context`. * * Note that it is possible to get back an *empty* access unit in * certain situations - the most obvious of which is if we get two * ``end of sequence`` NAL units with nothing betwen them. * * Because of this possibility, some care should be taken to allow for * access units that do not contain a primary picture (no VCL NAL unit), * and contain zero NAL units. Also, if one is trying for an accurate * count of access units, such instances should probably be ignored. * * Returns 0 if it succeeds, EOF if there is no more data to read, or 1 if * some error occurs. * * EOF can be returned because the end of file has been reached, or because an * end of stream NAL unit has been encountered. The two may be distinguished * by looking at `context->end_of_stream`, which will be NULL if it was a true * EOF. * * Note that `ret_access_unit` will be NULL if EOF is returned. */ extern int get_next_access_unit(access_unit_context_p context, int quiet, int show_details, access_unit_p *ret_access_unit); /* * Retrieve the next H.264 frame from the given elementary stream. * * The next access unit is retrieved from the input stream (using * get_next_access_unit). * * If that access unit represents a frame, it is returned. * * If it represents a field, then the *following* access unit is retrieved, * and if that is the second field of its frame, it is merged into the first, * and the resultant frame is returned. * * If a field with frame number A is followed by a field with frame number B, * it is assumed that synchronisation has been lost. In this case, the first * field (frame A) will be discarded, and an attempt made to read the second * field of frame B. * * Similarly, if a frame is found instead of the second field, the first * field will be discarded and the frame returned. * * Note that if the context is associated with a reverse context, * then appropriate frames will automatically be remembered therein. * * - `context` is the context information needed to allow us to find * successive access units. * - `quiet` is true if we should try to be silent about it * - `show_details` is true if we should output more info than normal * - `frame` is an access unit datastructure representing the next * frame. * * If the access unit was ended because an end of sequence or end of * stream NAL unit was encountered, then said end of sequence/stream * NAL unit will be remembered in the `context`. * * Returns 0 if it succeeds, EOF if there is no more data to read, or 1 if * some error occurs. * * EOF can be returned because the end of file has been reached, or because an * end of stream NAL unit has been encountered. The two may be distinguished * by looking at `context->end_of_stream`, which will be NULL if it was a true * EOF. * * Note that `ret_access_unit` will be NULL if EOF is returned. */ extern int get_next_h264_frame(access_unit_context_p context, int quiet, int show_details, access_unit_p *frame); /* * If this access unit was read from PES, did any of its PES packets contain * a PTS? * * Returns TRUE if so, FALSE if not. */ extern int access_unit_has_PTS(access_unit_p access_unit); #endif // _accessunit_fns // Local Variables: // tab-width: 8 // indent-tabs-mode: nil // c-basic-offset: 2 // End: // vim: set tabstop=8 shiftwidth=2 expandtab: