1 /*
2  * Datastructures for reading PES packets from TS or PS files
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 _pes_defns
30 #define _pes_defns
31 
32 #include "compat.h"
33 #include "pidint_defns.h"
34 #include "ps_defns.h"
35 #include "ts_defns.h"
36 #include "tswrite_defns.h"
37 
38 // ------------------------------------------------------------
39 // A PES packet comes with some useful associated data
40 struct PES_packet_data
41 {
42   byte    *data;      // The actual packet data
43   int32_t  data_len;  // The length of the `data` array [1]
44   int32_t  length;    // Its length
45   offset_t posn;      // The offset of its start in the file [2]
46   int      is_video;  // Is this video data? (as opposed to audio)
47 
48   // For convenience, it's useful to be able to get at the PES packet's
49   // "payload" (i.e., the ES data) as if it were a separate array. This
50   // is, of course, just an offset into `data`
51   byte    *es_data;
52   int32_t  es_data_len;
53   // The PES packet *does* tell us if its data starts with an ES packet
54   // (i.e., if the 00 00 01 bytes come as the first bytes in the data),
55   // so that's worth remembering
56   int      data_alignment_indicator;
57 
58   // Some applications want to know if a particular packet contains
59   // a PTS or not
60   int      has_PTS;
61 };
62 // [1] For PS data, data_len and length will always be the same.
63 //     For TS data, length is set when the first TS packet of the
64 //     PES packet is read, and data_len gradually increases to length
65 //     as "chunks" of the PES packet are read in
66 // [2] For TS data, this is actually the offset of the first TS packet
67 //     containing the PES packet
68 typedef struct PES_packet_data *PES_packet_data_p;
69 #define SIZEOF_PES_PACKET_DATA sizeof(struct PES_packet_data)
70 
71 // ------------------------------------------------------------
72 // An expandable list of PID vs. PES packet data
73 struct peslist
74 {
75   uint32_t          *pid;     // An array of the PIDs
76   PES_packet_data_p *data;    // An array of the corresponding PES data
77   int                length;  // How many there are
78   int                size;    // How big the arrays are
79 };
80 typedef struct peslist *peslist_p;
81 #define SIZEOF_PESLIST sizeof(struct peslist)
82 
83 #define PESLIST_START_SIZE  2  // Guess at one audio, one video
84 #define PESLIST_INCREMENT   1  // And a very conservative extension policy
85 
86 // ------------------------------------------------------------
87 // A PES "reader" datastructure is the interface through which one reads
88 // PES packets from a TS or PS file
89 struct PES_reader
90 {
91   int      is_TS;    // Is it is TS (as opposed to PS)?
92 
93   // If it is TS, we read via a TS read-ahead buffer
94   TS_reader_p  tsreader;
95   // If it is PS, we read via a PS read-ahead buffer
96   PS_reader_p  psreader;
97 
98   int      give_info;     // Should information messages be output?
99   int      give_warning;  // Should warning messages be output (to stderr)?
100 
101   PES_packet_data_p packet;  // The current PES packet
102 
103   // When reading PS packets, `posn` is the position of the current (or last)
104   // PS or TS packet.
105   offset_t posn;
106 
107   // For PS data, we need to know if it is H.264 (MPEG-4/AVC) or not
108   int      is_h264;             // for backwards compatibility
109   int      video_type;          // the actual (believed) video type
110 
111   // For PS and TS, we can choose to ignore audio entirely
112   int      video_only;
113   // For PS, if we're not ignoring audio, we either look for a specific
114   // audio stream id (specified by the user), or we will take the first
115   // we find that is not Dolby. This latter is indicated by audio_stream
116   // being set to 0
117   byte     audio_stream_id;  // If not, the stream id of the audio we want
118 
119   // When reading TS data, we need the program information to make sense
120   // of what is going on
121   int      got_program_data;   // Do we know our program data yet?
122   pmt_p    program_map;        // The content of the (current/last) PMT
123   // And from that, we can work out our video and audio (if any) pids, etc.
124   uint32_t video_pid;          // Zero if not yet known
125   uint32_t audio_pid;          // Ditto
126   uint32_t pcr_pid;            // A copy of the value from the PMT
127   uint16_t program_number;     // Which program are we reading? (0=first)
128   uint32_t pmt_pid;            // What's the PMT PID?
129 
130   // PMTs may be split over several TS packets, so we need a buffer
131   // to build them in
132   byte  *pmt_data;             // The buffer (NULL when not in use)
133   int    pmt_data_len;         // The buffers length = the PMT section length + 3
134   int    pmt_data_used;        // How much of said data we've already got
135 
136   // In order to write out TS data, we also need program information.
137   // Obviously, the simplest case is when reading TS and writing it out
138   // again, with the same settings. However, we also have to cope with
139   // reading in PS data (which has no TS program information), and writing
140   // out TS data with *different* program information.
141   // If we're reading TS data, the default is to use the program data we
142   // find therein. If `override_program_data` is TRUE, then we ignore that,
143   // and use the values given by the user instead.
144   int      override_program_data;
145   // Regardless, the following are the values to use when writing TS data out:
146   uint32_t output_video_pid;
147   uint32_t output_audio_pid;
148   uint32_t output_pcr_pid;
149   uint16_t output_program_number;
150   uint32_t output_pmt_pid;
151 
152   // If we're reading Dolby (AC-3) audio, then there are two choices for the
153   // stream type. DVB uses stream type 0x06, and ATSC uses stream type 0x81.
154   byte     dolby_stream_type;  // The Dolby stream type we read (if any)
155   byte     output_dolby_stream_type;
156   int      override_dolby_stream_type;  // Override whatever we read
157 
158   // Before we can write out TS data, we need some basic program information.
159   // This is read in automatically if the input is TS, and must be supplied
160   // by the user (via set_PES_reader_program_data) if the input is PS.
161 
162   // When reading a TS file, more than one PES packet may be being built
163   // at the same time. At any time, the "next" read PES packet will be the
164   // first one to be completely read in
165   peslist_p      packets;     // The packets currently being read
166 
167   // If we are reading TS, and a PES packet has a declared length of 0,
168   // then it can only be ended by the *next* PES packet of the same PID
169   // (or by EOF, of course). In this case, we want to return the newly
170   // ended PES packet, and the *next* read request should continue
171   // with the PES packet we hadn't yet finished with. However, it is
172   // technically possible (although unlikely) that the new (just started)
173   // PES packet will end in its first TS packet. In that case, we want
174   // to return *it* next time we try to read a TS packet. To facilitate
175   // that, we can remember it here...
176   PES_packet_data_p deferred;
177 
178   // If we ended such a packet on EOF, it's moderately convenient to
179   // remember that we had found EOF, rather than try to bump into it again
180   int               had_eof;
181 
182   // When being used by a server, we want PES packets to be written out
183   // as a "side effect" of reading them in to analyse their contents.
184   // Thus we provide:
185   int               write_PES_packets; // TRUE if to write them out to:
186   TS_writer_p       tswriter;          // this TS writer context
187   int               program_freq;  // how often to write PAT/PMT out
188   int               program_index; // how long since we last did so
189   // Sometimes, for instance when going from fast forwards to normal playing,
190   // we've already output the (end of) the current PES packet by hand, and
191   // thus don't want the automated server mechanism to output it for us.
192   // It's thus useful to have a flag indicating this (which will be unset
193   // as soon as the current PES packet has, indeed, not been written out)
194   // Since this is (definitely) an internal detail, it must be set explicitly.
195   int               dont_write_current_packet;
196   // For benchmarking purposes (of the recipient), it can be useful to be able
197   // to "pad out" the data we're sending, so that it is <n> times as big. If
198   // ``expand`` is greater than 0, then ``expand`` "dummy" PES packets (of the
199   // same size as the real one) will be output for each real PES packet (but
200   // with an irrelevant stream id).
201   int		    pes_padding;
202 
203   // If the original data is TS, and we want to send *all* of said data
204   // to the server, it is sensible to write the *TS packets* as a side
205   // effect of reading, rather than the PES packets. Thus we also have
206   int               write_TS_packets;
207   // Obviously, one assumes that we are not going to be doing both at
208   // the same time (since they write through the same tswriter interface)
209 
210   // In either case, sometimes it is useful to suppress writing packets
211   // out for a while
212   int               suppress_writing;
213 
214   // Debugging: if this is set, and the appropriate code is compiled into
215   // pes.c (see DEBUG_READ_PACKETS), then report on each PES packet read
216   // and written. Even if DEBUG_READ_PACKETS is not defined, some output
217   // will be produced.
218   int               debug_read_packets;
219 };
220 typedef struct PES_reader *PES_reader_p;
221 #define SIZEOF_PES_READER sizeof(struct PES_reader)
222 
223 // Given the PES packet data (i.e., the data starting 00 00 01 <stream_id>
224 // <packet_length>), decide if this PES packet is MPEG-1 (11172-1) or
225 // H.222.0 (13818-1)
226 #define IS_H222_PES(data)  ((data[6] & 0xC0) == 0x80)
227 
228 #endif // _pes_defns
229 
230 // Local Variables:
231 // tab-width: 8
232 // indent-tabs-mode: nil
233 // c-basic-offset: 2
234 // End:
235 // vim: set tabstop=8 shiftwidth=2 expandtab:
236