/* * Prototypes for manipulating NAL 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 _nalunit_fns #define _nalunit_fns #include "nalunit_defns.h" /* * Request details of the NAL unit contents as they are read */ extern void set_show_nal_reading_details(nal_unit_context_p context, int show); /* * Build a new NAL unit context, for reading NAL units from an ES. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int build_nal_unit_context(ES_p es, nal_unit_context_p *context); /* * Free a NAL unit context datastructure. * * Clears the datastructure, frees it, and returns `context` as NULL. * * Does nothing if `context` is already NULL. */ extern void free_nal_unit_context(nal_unit_context_p *context); /* * Rewind a file being read as NAL units. * * A thin jacket for `seek_ES`. * * Doesn't unset the sequence and picture parameter dictionaries * that have been built up when reading the file - this may possibly * not be the desired behaviour, but should be OK for well behaved files. * * Returns 0 if all goes well, 1 if something goes wrong. */ extern int rewind_nal_unit_context(nal_unit_context_p context); /* * Build a new NAL unit datastructure. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int build_nal_unit(nal_unit_p *nal); /* * Tidy up and free a NAL unit datastructure after we've finished with it. * * Empties the NAL unit datastructure, frees it, and sets `nal` to NULL. * * If `nal` is already NULL, does nothing. */ extern void free_nal_unit(nal_unit_p *nal); /* * Find and read in the next NAL unit. * * - `context` is the NAL unit context we're reading from * - `verbose` is true if a brief report on the NAL unit should be given * - `nal` is the datastructure containing the NAL 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 NAL unit), * * 2 if the NAL unit data does not make sense, so it should be ignored * (specifically, if the NAL unit's RBSP data cannot be understood), * * 1 if some other error occurs. */ extern int find_next_NAL_unit(nal_unit_context_p context, int verbose, nal_unit_p *nal); /* * Write (copy) the current NAL unit to the ES output stream. * * - `output` is the output stream (file descriptor) to write to * - `nal` is the NAL unit to write * * Returns 0 if all went well, 1 if something went wrong. */ extern int write_NAL_unit_as_ES(FILE *output, nal_unit_p nal); /* * Write (copy) the current NAL unit to the output stream, wrapped up in a * PES within TS. * * - `output` is the TS writer to write to * - `nal` is the NAL unit to write * - `video_pid` is the video PID to use * * Returns 0 if all went well, 1 if something went wrong. */ extern int write_NAL_unit_as_TS(TS_writer_p tswriter, nal_unit_p nal, uint32_t video_pid); /* * Create a new "dictionary" for remembering picture or sequence * parameter sets. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int build_param_dict(param_dict_p *param_dict); /* * Tidy up and free a parameters "dictionary" datastructure after we've * finished with it. * * Empties the datastructure, frees it, and sets `param_dict` to NULL. * * Does nothing if `param_dict` is already NULL. */ extern void free_param_dict(param_dict_p *param_dict); /* * Remember parameter set data in a "dictionary". * * - `param_dict` should be an appropriate "dictionary" - i.e., one * being used to store picture or sequence parameter set data, as * appropriate. * - `param_id` is the id for this picture or sequence parameter set. * - `nal` is the NAL unit containing the parameter set data. * Note that a copy will be taken of the parameter set data, which * means that the caller may free the NAL unit. * * Any previous data for this picture or sequence parameter set id will be * forgotten (overwritten). * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int remember_param_data(param_dict_p param_dict, uint32_t param_id, nal_unit_p nal); /* * Retrieve the picture parameter set data for the given id. * * - `pic_param_dict` is a parameter "dictionary" of the appropriate type. * - `pic_param_id` is the id to look up. * - `pic_param_data` is the data for that id. Do not free this, it refers * into the "dictionary" datastructure. * * Note that altering the "dictionary" (with `remember_param_data()`) may * cause the underlying datastructures to be realloc'ed, which in turn means * that the address returned as `pic_param_data` may not be valid after such * an action. * * Returns 0 if it succeeds, 1 if the id is not recognised. */ extern int get_pic_param_data(param_dict_p pic_param_dict, uint32_t pic_param_id, nal_pic_param_data_p *pic_param_data); /* * Retrieve the sequence parameter set data for the given id. * * - `seq_param_dict` is a parameter "dictionary" of the appropriate type. * - `seq_param_id` is the id to look up. * - `seq_param_data` is the data for that id. Do not free this, it refers * into the "dictionary" datastructure. * * Note that altering the "dictionary" (with `remember_param_data()`) may * cause the underlying datastructures to be realloc'ed, which in turn means * that the address returned as `seq_param_data` may not be valid after such * an action. * * Returns 0 if it succeeds, 1 if the id is not recognised. */ extern int get_seq_param_data(param_dict_p seq_param_dict, uint32_t seq_param_id, nal_seq_param_data_p *seq_param_data); /* * Is this NAL unit a slice? * * Returns true if its ``nal_unit_type`` is 1 (coded slice of IDR picture) * or 5 (coded slice of IDR picture). */ extern int nal_is_slice(nal_unit_p nal); /* * Is this NAL unit a picture parameter set? * * Returns true if its ``nal_unit_type`` is 8. */ extern int nal_is_pic_param_set(nal_unit_p nal); /* * Is this NAL unit a sequence parameter set? * * Returns true if its ``nal_unit_type`` is 7. */ extern int nal_is_seq_param_set(nal_unit_p nal); /* * Is this NAL unit marked as part of a redundant picture? */ extern int nal_is_redundant(nal_unit_p nal); /* * Is this VCL NAL unit the first of a new primary coded picture? * * - `nal` is the NAL unit we need to decide about. * - `last` is a slice NAL unit from the last primary coded picture * (likely to be the first NAL unit therefrom, in fact) * * Both `nal` and `last` must be VCL NALs representing slices of a reference * picture - i.e., with nal_unit_type 1 or 5 (if we were supporting type A * slice data partitions, we would have to take them into account as well). * * Both `nal` and `last` must have had their innards decoded with * `read_slice_data`, which should have occurred automatically if they are * both appropriate NAL units for this process. * * Acording to H.264 7.4.1.2.4 (from the JVT-J010d7 draft): * * The first NAL unit of a new primary code picture can be detected * because: * * - its frame number differs in value from that of the last slice (NB: * IDR pictures always have frame_num == 0) * * - its field_pic_flag differs in value (i.e., one is a field slice, and * the other a frame slice) * * - the bottom_field_flag is present in both (determined by * frame_mbs_only_flag in the sequence parameter set, and by * field_pic_flag) and differs (i.e., both are field slices, but one * is top and the other bottom) [*]_ * * - nal_ref_idc differs in value, and one of them has nal_ref_idc == 0 * (i.e., one is a reference picture and the other is not) * * - pic_order_cnt_type (found in the sequence parameter set) == 0 for * both and either pic_order_cnt_lsb differs in value or * delta_pic_order_cnt_bottom differs in value [*]_ * * - pic_order_cnt_type == 1 for both and either delta_pic_order_cnt[0] * or delta_pic_order_cnt[1] differs in value [*]_ * * - nal_unit_type == 5 for one and not in the other (i.e., one is IDR * and the other is not) * * - nal_unit_type == 5 for both (i.e., both are IDR), and idr_pic_id * differs (i.e., they're not the same IDR) * * It is possible that later drafts may alter/augment these criteria - * that has already happened between JVT-G050r1 and JVT-J010d7. * * .. [*] For these three items, we need to have decoded the active * sequence parameter set (which, for now, I'll assume to be the last * set we found with the appropriate id). */ extern int nal_is_first_VCL_NAL(nal_unit_p nal, nal_unit_p last); // ------------------------------------------------------------ // Lists of NAL units // // This duplicates the functionality provided by ES unit lists // in es.h, but it works at the higher level of NAL units, // which is useful if one wants to report on the content of the // lists *as* NAL units. // ------------------------------------------------------------ /* * Build a new list-of-nal-units datastructure. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int build_nal_unit_list(nal_unit_list_p *list); /* * Add a NAL unit to the end of the NAL unit list. Does not take a copy. * * Returns 0 if it succeeds, 1 if some error occurs. */ extern int append_to_nal_unit_list(nal_unit_list_p list, nal_unit_p nal); /* * Reset (empty) a NAL unit list. * * If `deep` is true, then any NAL units in the list will be freed * as well (this will be a Bad Thing if anywhere else is using them). */ extern void reset_nal_unit_list(nal_unit_list_p list, int deep); /* * Tidy up and free a NAL unit list datastructure after we've finished with it. * * If `deep` is true, then any NAL units in the list will be freed * as well (this will be a Bad Thing if anywhere else is using them). * * Clears the datastructure, frees it and returns `list` as NULL. * * Does nothing if `list` is already NULL. */ extern void free_nal_unit_list(nal_unit_list_p *list, int deep); /* * Report on a NAL unit list's contents, to the given stream. */ extern void report_nal_unit_list(int is_msg, char *prefix, nal_unit_list_p list); /* * Print out useful information about this NAL unit, on the given stream. * * This is intended as a single line of information. */ extern void report_nal(int is_msg, nal_unit_p nal); #endif // _nalunit_fns // Local Variables: // tab-width: 8 // indent-tabs-mode: nil // c-basic-offset: 2 // End: // vim: set tabstop=8 shiftwidth=2 expandtab: