1 /*
2  * Datastructures for handling H.264 elementary streams.
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is the MPEG TS, PS and ES tools.
18  *
19  * The Initial Developer of the Original Code is Amino Communications Ltd.
20  * Portions created by the Initial Developer are Copyright (C) 2008
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  *   Amino Communications Ltd, Swavesey, Cambridge UK
25  *
26  * ***** END LICENSE BLOCK *****
27  */
28 
29 #ifndef _es_defns
30 #define _es_defns
31 
32 #include <stdio.h>
33 #include "compat.h"
34 #include "pes_defns.h"
35 
36 // ------------------------------------------------------------
37 // A "file" offset in an ES stream, suitable for seeking to
38 // For an ES based on a "bare" file, the `infile` value is all that is needed
39 // For an ES based on a PES, the file offset of the PES packet and the byte
40 // offset within that packet's ES data are needed.
41 struct _ES_offset
42 {
43   offset_t  infile;   // as used by lseek
44   int32_t   inpacket;
45 };
46 typedef struct _ES_offset  ES_offset;
47 typedef struct _ES_offset *ES_offset_p;
48 #define SIZEOF_ES_OFFSET sizeof(struct _ES_offset)
49 
50 // The number of bytes to "read ahead" when reading directly from an
51 // elementary stream
52 #define ES_READ_AHEAD_SIZE  1000
53 
54 // ------------------------------------------------------------
55 // A datastructure to represent our input elementary stream (ES)
56 // (*output* elementary streams shouldn't need any particular housekeeping)
57 struct elementary_stream
58 {
59   int       reading_ES;  // TRUE if we're reading ES data direct, FALSE if PES
60 
61   // If we're reading from an elementary data stream directly, then
62   // we use the input directly
63   int       input;
64   // And maintain a buffer of "read ahead" bytes
65   byte      read_ahead[ES_READ_AHEAD_SIZE];
66   offset_t  read_ahead_posn;   // location of this data in the file
67   int32_t   read_ahead_len;    // actual number of bytes in the buffer
68 
69   // And the next byte to be read is specified by its offset in said
70   // data stream. For "bare" ES data, the `infile` value is used to
71   // remember the next bytes actual position in the file, and for PES
72   // based ES data, the `inpacket` value is used to remember the next
73   // bytes offset in the current PES packet. In both cases, the "unused"
74   // quantity in the ES_offset is undefined.
75   // (this is, in fact, more used by tsserve than by anything else)
76   ES_offset  posn_of_next_byte;
77 
78   // If we're reading from PES packets (from either a PS or TS file),
79   // then we need to remember our PES reader
80   PES_reader_p  reader;
81 
82   byte      *data;               // Where we're reading our bytes from
83   byte      *data_end;           // How to tell we've read them all
84   byte      *data_ptr;           // And which byte we're interested in
85 
86   offset_t   last_packet_posn;   // Where the last PES packet was in the file
87   int32_t    last_packet_es_data_len;  // And its number of ES bytes
88 
89   // Regardless, our triple byte memory is the same
90   byte      cur_byte;    // The current (last read) byte
91   byte      prev1_byte;  // The previous byte
92   byte      prev2_byte;  // The byte before *that*
93 };
94 typedef struct elementary_stream *ES_p;
95 #define SIZEOF_ES sizeof(struct elementary_stream)
96 
97 // ------------------------------------------------------------
98 // And a representation of a single unit from the elementary stream
99 // (whether an MPEG-2 (H.262) item, or an MPEG-4/AVC (H.264) NAL unit)
100 // - basically, the thing that starts with a 00 00 01 prefix, and continues
101 // to end of file or before the next 00 00 01 prefix (so note that it
102 // contains any "trailing" 00 bytes).
103 //
104 // The normal way to acquire such a datastructure is via `build_ES_unit()`,
105 // or `find_and_build_next_ES_unit()`. If instead you want to use the
106 // address of a `struct ES_unit`, it is imperative that it be set up
107 // correctly with `setup_ES_unit()` before it is passed to any of the
108 // functions that use it, otherwise the contents will not be valid (and,
109 // particularly, the "data" pointer will reference random memory).
110 struct ES_unit
111 {
112   ES_offset start_posn;   // The start of the current data unit
113   byte     *data;         // Its data, including the leading 00 00 01
114   uint32_t  data_len;     // Its length
115   uint32_t  data_size;    // The total buffer size
116 
117   byte      start_code;   // The byte after the 00 00 01 prefix
118 
119   // Something of a hack - if we were reading PES, did any of the PES packets
120   // we read to make this ES unit contain a PTS?
121   byte      PES_had_PTS;
122 };
123 typedef struct ES_unit *ES_unit_p;
124 #define SIZEOF_ES_UNIT sizeof(struct ES_unit)
125 
126 // Start and increment sizes for the es_unit/data array.
127 #define ES_UNIT_DATA_START_SIZE  1000  // was 500
128 #define ES_UNIT_DATA_INCREMENT    500  // was 100
129 
130 // ------------------------------------------------------------
131 // An expandable list of ES units
132 struct ES_unit_list
133 {
134   struct ES_unit *array;   // The current array of ES units
135   int             length;  // How many there are
136   int             size;    // How big the array is
137 };
138 typedef struct ES_unit_list *ES_unit_list_p;
139 #define SIZEOF_ES_UNIT_LIST sizeof(struct ES_unit_list)
140 
141 #define ES_UNIT_LIST_START_SIZE  20
142 #define ES_UNIT_LIST_INCREMENT   20
143 
144 #endif // _es_defns
145 
146 // Local Variables:
147 // tab-width: 8
148 // indent-tabs-mode: nil
149 // c-basic-offset: 2
150 // End:
151 // vim: set tabstop=8 shiftwidth=2 expandtab:
152