kopia lustrzana https://github.com/F5OEO/tstools
354 wiersze
12 KiB
C
354 wiersze
12 KiB
C
/*
|
||
* 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,
|
||
u_int32 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,
|
||
u_int32 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,
|
||
u_int32 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,
|
||
u_int32 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(FILE *stream,
|
||
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(FILE *stream,
|
||
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:
|