forked from kynesim/tstools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
es_fns.h
432 lines (399 loc) · 14.5 KB
/
es_fns.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
/*
* 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: