kopia lustrzana https://github.com/F5OEO/tstools
225 wiersze
9.7 KiB
C
225 wiersze
9.7 KiB
C
/*
|
||
* Datastructures for reading PES packets from TS or PS files
|
||
*
|
||
* ***** 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 _pes_defns
|
||
#define _pes_defns
|
||
|
||
#include "compat.h"
|
||
#include "pidint_defns.h"
|
||
#include "ps_defns.h"
|
||
#include "ts_defns.h"
|
||
#include "tswrite_defns.h"
|
||
|
||
// ------------------------------------------------------------
|
||
// A PES packet comes with some useful associated data
|
||
struct PES_packet_data
|
||
{
|
||
byte *data; // The actual packet data
|
||
int32 data_len; // The length of the `data` array [1]
|
||
int32 length; // Its length
|
||
offset_t posn; // The offset of its start in the file [2]
|
||
int is_video; // Is this video data? (as opposed to audio)
|
||
|
||
// For convenience, it's useful to be able to get at the PES packet's
|
||
// "payload" (i.e., the ES data) as if it were a separate array. This
|
||
// is, of course, just an offset into `data`
|
||
byte *es_data;
|
||
int32 es_data_len;
|
||
// The PES packet *does* tell us if its data starts with an ES packet
|
||
// (i.e., if the 00 00 01 bytes come as the first bytes in the data),
|
||
// so that's worth remembering
|
||
int data_alignment_indicator;
|
||
|
||
// Some applications want to know if a particular packet contains
|
||
// a PTS or not
|
||
int has_PTS;
|
||
};
|
||
// [1] For PS data, data_len and length will always be the same.
|
||
// For TS data, length is set when the first TS packet of the
|
||
// PES packet is read, and data_len gradually increases to length
|
||
// as "chunks" of the PES packet are read in
|
||
// [2] For TS data, this is actually the offset of the first TS packet
|
||
// containing the PES packet
|
||
typedef struct PES_packet_data *PES_packet_data_p;
|
||
#define SIZEOF_PES_PACKET_DATA sizeof(struct PES_packet_data)
|
||
|
||
// ------------------------------------------------------------
|
||
// An expandable list of PID vs. PES packet data
|
||
struct peslist
|
||
{
|
||
u_int32 *pid; // An array of the PIDs
|
||
PES_packet_data_p *data; // An array of the corresponding PES data
|
||
int length; // How many there are
|
||
int size; // How big the arrays are
|
||
};
|
||
typedef struct peslist *peslist_p;
|
||
#define SIZEOF_PESLIST sizeof(struct peslist)
|
||
|
||
#define PESLIST_START_SIZE 2 // Guess at one audio, one video
|
||
#define PESLIST_INCREMENT 1 // And a very conservative extension policy
|
||
|
||
// ------------------------------------------------------------
|
||
// A PES "reader" datastructure is the interface through which one reads
|
||
// PES packets from a TS or PS file
|
||
struct PES_reader
|
||
{
|
||
int is_TS; // Is it is TS (as opposed to PS)?
|
||
|
||
// If it is TS, we read via a TS read-ahead buffer
|
||
TS_reader_p tsreader;
|
||
// If it is PS, we read via a PS read-ahead buffer
|
||
PS_reader_p psreader;
|
||
|
||
int give_info; // Should information messages be output?
|
||
int give_warning; // Should warning messages be output (to stderr)?
|
||
|
||
PES_packet_data_p packet; // The current PES packet
|
||
|
||
// When reading PS packets, `posn` is the position of the current (or last)
|
||
// PS or TS packet.
|
||
offset_t posn;
|
||
|
||
// For PS data, we need to know if it is H.264 (MPEG-4/AVC) or not
|
||
int is_h264; // for backwards compatibility
|
||
int video_type; // the actual (believed) video type
|
||
|
||
// For PS and TS, we can choose to ignore audio entirely
|
||
int video_only;
|
||
// For PS, if we're not ignoring audio, we either look for a specific
|
||
// audio stream id (specified by the user), or we will take the first
|
||
// we find that is not Dolby. This latter is indicated by audio_stream
|
||
// being set to 0
|
||
byte audio_stream_id; // If not, the stream id of the audio we want
|
||
|
||
// When reading TS data, we need the program information to make sense
|
||
// of what is going on
|
||
int got_program_data; // Do we know our program data yet?
|
||
pmt_p program_map; // The content of the (current/last) PMT
|
||
// And from that, we can work out our video and audio (if any) pids, etc.
|
||
u_int32 video_pid; // Zero if not yet known
|
||
u_int32 audio_pid; // Ditto
|
||
u_int32 pcr_pid; // A copy of the value from the PMT
|
||
u_int16 program_number; // Which program are we reading? (0=first)
|
||
u_int32 pmt_pid; // What's the PMT PID?
|
||
|
||
// PMTs may be split over several TS packets, so we need a buffer
|
||
// to build them in
|
||
byte *pmt_data; // The buffer (NULL when not in use)
|
||
int pmt_data_len; // The buffers length = the PMT section length + 3
|
||
int pmt_data_used; // How much of said data we've already got
|
||
|
||
// In order to write out TS data, we also need program information.
|
||
// Obviously, the simplest case is when reading TS and writing it out
|
||
// again, with the same settings. However, we also have to cope with
|
||
// reading in PS data (which has no TS program information), and writing
|
||
// out TS data with *different* program information.
|
||
// If we're reading TS data, the default is to use the program data we
|
||
// find therein. If `override_program_data` is TRUE, then we ignore that,
|
||
// and use the values given by the user instead.
|
||
int override_program_data;
|
||
// Regardless, the following are the values to use when writing TS data out:
|
||
u_int32 output_video_pid;
|
||
u_int32 output_audio_pid;
|
||
u_int32 output_pcr_pid;
|
||
u_int16 output_program_number;
|
||
u_int32 output_pmt_pid;
|
||
|
||
// If we're reading Dolby (AC-3) audio, then there are two choices for the
|
||
// stream type. DVB uses stream type 0x06, and ATSC uses stream type 0x81.
|
||
byte dolby_stream_type; // The Dolby stream type we read (if any)
|
||
byte output_dolby_stream_type;
|
||
int override_dolby_stream_type; // Override whatever we read
|
||
|
||
// Before we can write out TS data, we need some basic program information.
|
||
// This is read in automatically if the input is TS, and must be supplied
|
||
// by the user (via set_PES_reader_program_data) if the input is PS.
|
||
|
||
// When reading a TS file, more than one PES packet may be being built
|
||
// at the same time. At any time, the "next" read PES packet will be the
|
||
// first one to be completely read in
|
||
peslist_p packets; // The packets currently being read
|
||
|
||
// If we are reading TS, and a PES packet has a declared length of 0,
|
||
// then it can only be ended by the *next* PES packet of the same PID
|
||
// (or by EOF, of course). In this case, we want to return the newly
|
||
// ended PES packet, and the *next* read request should continue
|
||
// with the PES packet we hadn't yet finished with. However, it is
|
||
// technically possible (although unlikely) that the new (just started)
|
||
// PES packet will end in its first TS packet. In that case, we want
|
||
// to return *it* next time we try to read a TS packet. To facilitate
|
||
// that, we can remember it here...
|
||
PES_packet_data_p deferred;
|
||
|
||
// If we ended such a packet on EOF, it's moderately convenient to
|
||
// remember that we had found EOF, rather than try to bump into it again
|
||
int had_eof;
|
||
|
||
// When being used by a server, we want PES packets to be written out
|
||
// as a "side effect" of reading them in to analyse their contents.
|
||
// Thus we provide:
|
||
int write_PES_packets; // TRUE if to write them out to:
|
||
TS_writer_p tswriter; // this TS writer context
|
||
int program_freq; // how often to write PAT/PMT out
|
||
int program_index; // how long since we last did so
|
||
// Sometimes, for instance when going from fast forwards to normal playing,
|
||
// we've already output the (end of) the current PES packet by hand, and
|
||
// thus don't want the automated server mechanism to output it for us.
|
||
// It's thus useful to have a flag indicating this (which will be unset
|
||
// as soon as the current PES packet has, indeed, not been written out)
|
||
// Since this is (definitely) an internal detail, it must be set explicitly.
|
||
int dont_write_current_packet;
|
||
// For benchmarking purposes (of the recipient), it can be useful to be able
|
||
// to "pad out" the data we're sending, so that it is <n> times as big. If
|
||
// ``expand`` is greater than 0, then ``expand`` "dummy" PES packets (of the
|
||
// same size as the real one) will be output for each real PES packet (but
|
||
// with an irrelevant stream id).
|
||
int pes_padding;
|
||
|
||
// Debugging: if this is set, and the appropriate code is compiled into
|
||
// pes.c (see DEBUG_READ_PACKETS), then report on each PES packet read
|
||
// and written. Even if DEBUG_READ_PACKETS is not defined, some output
|
||
// will be produced.
|
||
int debug_read_packets;
|
||
};
|
||
typedef struct PES_reader *PES_reader_p;
|
||
#define SIZEOF_PES_READER sizeof(struct PES_reader)
|
||
|
||
// Given the PES packet data (i.e., the data starting 00 00 01 <stream_id>
|
||
// <packet_length>), decide if this PES packet is MPEG-1 (11172-1) or
|
||
// H.222.0 (13818-1)
|
||
#define IS_H222_PES(data) ((data[6] & 0xC0) == 0x80)
|
||
|
||
#endif // _pes_defns
|
||
|
||
// Local Variables:
|
||
// tab-width: 8
|
||
// indent-tabs-mode: nil
|
||
// c-basic-offset: 2
|
||
// End:
|
||
// vim: set tabstop=8 shiftwidth=2 expandtab:
|