F5OEO-tstools/pes_defns.h

236 wiersze
10 KiB
C
Czysty Zwykły widok Historia

/*
* 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_t data_len; // The length of the `data` array [1]
int32_t 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_t 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
{
uint32_t *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.
uint32_t video_pid; // Zero if not yet known
uint32_t audio_pid; // Ditto
uint32_t pcr_pid; // A copy of the value from the PMT
uint16_t program_number; // Which program are we reading? (0=first)
uint32_t 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:
uint32_t output_video_pid;
uint32_t output_audio_pid;
uint32_t output_pcr_pid;
uint16_t output_program_number;
uint32_t 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;
// If the original data is TS, and we want to send *all* of said data
// to the server, it is sensible to write the *TS packets* as a side
// effect of reading, rather than the PES packets. Thus we also have
int write_TS_packets;
// Obviously, one assumes that we are not going to be doing both at
// the same time (since they write through the same tswriter interface)
// In either case, sometimes it is useful to suppress writing packets
// out for a while
int suppress_writing;
// 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: