diff options
Diffstat (limited to 'tools/pes.h')
-rw-r--r-- | tools/pes.h | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/tools/pes.h b/tools/pes.h new file mode 100644 index 00000000..c01b98db --- /dev/null +++ b/tools/pes.h @@ -0,0 +1,258 @@ +/* + * pes.h: PES header definitions + * + * See the main source file 'xineliboutput.c' for copyright information and + * how to reach the author. + * + * $Id: pes.h,v 1.1 2006-06-03 10:04:27 phintuka Exp $ + * + */ + +#ifndef _PES_H_ +#define _PES_H_ + + +#define PES_CHUNK_SIZE 2048 + +#define MAX_SCR ((int64_t)0x1ffffffffLL) + +// PES PIDs +#define PRIVATE_STREAM1 0xBD +#define PADDING_STREAM 0xBE +#define PRIVATE_STREAM2 0xBF +#define AUDIO_STREAM_S 0xC0 /* 1100 0000 */ +#define AUDIO_STREAM_E 0xDF /* 1101 1111 */ +#define VIDEO_STREAM_S 0xE0 /* 1110 0000 */ +#define VIDEO_STREAM_E 0xEF /* 1110 1111 */ + +#define AUDIO_STREAM_MASK 0x1F /* 0001 1111 */ +#define VIDEO_STREAM_MASK 0x0F /* 0000 1111 */ +#define AUDIO_STREAM 0xC0 /* 1100 0000 */ +#define VIDEO_STREAM 0xE0 /* 1110 0000 */ + +#define ECM_STREAM 0xF0 +#define EMM_STREAM 0xF1 +#define DSM_CC_STREAM 0xF2 +#define ISO13522_STREAM 0xF3 +#define PROG_STREAM_DIR 0xFF + +// "picture header" +#define SC_PICTURE 0x00 + +// Picture types +#define NO_PICTURE 0 +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 + +static inline int64_t pes_extract_pts(const uchar *Data, int Length, + bool& Audio, bool& Video) +{ + /* assume mpeg2 pes header ... */ + Audio = Video = false; + + if((VIDEO_STREAM == (Data[3] & ~VIDEO_STREAM_MASK) && (Video=true)) || + (AUDIO_STREAM == (Data[3] & ~AUDIO_STREAM_MASK) && (Audio=true)) || + (PRIVATE_STREAM1 == Data[3] && (Audio=true))) { + + if ((Data[6] & 0xC0) != 0x80) + return -1; + if ((Data[6] & 0x30) != 0) + return -1; + + if((Length > 14) && (Data[7] & 0x80)) { /* pts avail */ + int64_t pts; + pts = ((int64_t)(Data[ 9] & 0x0E)) << 29 ; + pts |= ((int64_t) Data[10]) << 22 ; + pts |= ((int64_t)(Data[11] & 0xFE)) << 14 ; + pts |= ((int64_t) Data[12]) << 7 ; + pts |= ((int64_t)(Data[13] & 0xFE)) >> 1 ; + return pts; + } + } + return -1ULL; +} + +static inline void pes_change_pts(uchar *Data, int Length) +{ + /* assume mpeg2 pes header ... Assume header already HAS pts */ + if((VIDEO_STREAM == (Data[3] & ~VIDEO_STREAM_MASK)) || + (AUDIO_STREAM == (Data[3] & ~AUDIO_STREAM_MASK)) || + (PRIVATE_STREAM1 == Data[3])) { + + if ((Data[6] & 0xC0) != 0x80) + return; + if ((Data[6] & 0x30) != 0) + return; + + if((Length > 14) && (Data[7] & 0x80)) { /* pts avail */ + int64_t pts; + //pts = ((int64_t)(Data[ 9] & 0x0E)) << 29 ; + Data[ 9] |= ((pts >> 29) & 0x0E); + //pts |= ((int64_t) Data[10]) << 22 ; + Data[10] |= ((pts >> 22) & 0xFF); + //pts |= ((int64_t)(Data[11] & 0xFE)) << 14 ; + Data[11] |= ((pts >> 14) & 0xFE); + //pts |= ((int64_t) Data[12]) << 7 ; + Data[12] |= ((pts >> 7 ) & 0xFF); + //pts |= ((int64_t)(Data[13] & 0xFE)) >> 1 ; + Data[13] |= ((pts << 1 ) & 0xFE); + } + } +} + +// Remove pts from PES packet (zero it) +static inline void pes_strip_pts(uchar *Data, int Len) +{ + if(VIDEO_STREAM == (Data[3] & ~VIDEO_STREAM_MASK) || + AUDIO_STREAM == (Data[3] & ~AUDIO_STREAM_MASK) || + PRIVATE_STREAM1 == Data[3]) { + + // MPEG1 PES + if ((Data[6] & 0xC0) != 0x80) { + Data += 6; + Len -= 6; + + // skip stuffing + while ((Data[0] & 0x80) == 0x80) { + Data++; + Len--; + } + if ((Data[0] & 0xc0) == 0x40) { + // STD_buffer_scale, STD_buffer_size + Data += 2; + Len -= 2; + } + + if(Len<5) return; + if ((Data[0] & 0xf0) == 0x20) { + // zero PTS + Data[0] &= ~0x0E; + Data[1] = 0; + Data[2] &= ~0xFE; + Data[3] = 0; + Data[4] &= ~0xFE; + return; + } + if(Len<10) return; + if ((Data[0] & 0xf0) == 0x30) { + // zero PTS & DTS +//((uint32*)Data)[0] &= 0x0E00FE00; + Data[0] &= ~0x0E; + Data[1] = 0; + Data[2] &= ~0xFE; + Data[3] = 0; +//((uint32*)Data)[1] &= 0xFE0E00FE; + Data[4] &= ~0xFE; + Data[5] &= ~0x0E; + Data[6] = 0; + Data[7] &= ~0xFE; +//((uint32*)Data)[2] &= 0x00FEFFFF; + Data[8] = 0; + Data[9] &= ~0xFE; + return; + } + + // MPEG2 PES + } else { + if ((Data[6] & 0xC0) != 0x80) + return; + if ((Data[6] & 0x30) != 0) + return; + + if(Len<14) return; + if (Data[7] & 0x80) { + // PTS + if(Data[8]<5) return; + Data[ 9] &= ~0x0E; + Data[10] = 0; + Data[11] &= ~0xFE; + Data[12] = 0; + Data[13] &= ~0xFE; + } + if(Len<19) return; + if (Data[7] & 0x40) { + // DTS + if(Data[8]<10) return; + Data[14] &= ~0x0E; + Data[15] = 0; + Data[16] &= ~0xFE; + Data[17] = 0; + Data[18] &= ~0xFE; + } + } + } +} + +static inline int pes_packet_len(const uchar *header, const int maxlen, bool &isMpeg1) +{ + if(VIDEO_STREAM == (header[3] & ~VIDEO_STREAM_MASK) || + AUDIO_STREAM == (header[3] & ~AUDIO_STREAM_MASK) || + PRIVATE_STREAM1 == header[3]) { + isMpeg1 = ((header[6] & 0xC0) != 0x80); + return 6 + (header[4] << 8 | header[5]); + } else if (header[3] == PADDING_STREAM) { + isMpeg1 = false; + return (6 + (header[4] << 8 | header[5])); + } else if (header[3] == 0xBA) { + if ((header[4] & 0x40) == 0) { /* mpeg1 */ + isMpeg1 = true; + return 12; + } else { /* mpeg 2 */ + isMpeg1 = false; + return 14 + (header[0xD] & 0x07); + } + } else if (header[3] <= 0xB9) { + int len=3; + return -3; + isMpeg1 = false; + while(len+2<maxlen) { + if(!header[len] && !header[len+1] && header[len+2] == 1) + return len; + len++; + } + return -len; + } + isMpeg1 = false; + return -(6 + (header[4] << 8 | header[5])); +} + +// from vdr/remux.c: +static inline int ScanVideoPacket(const uchar *Data, int Count, /*int Offset,*/ + uchar &PictureType) +{ + // Scans the video packet starting at Offset and returns its length. + // If the return value is -1 the packet was not completely in the buffer. + int Offset = 0; + int Length = Count; + if (Length > 0 && Offset + Length <= Count) { + int i = Offset + 8; // the minimum length of the video packet header + i += Data[i] + 1; // possible additional header bytes + for (; i < Offset + Length; i++) { + if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1) { + switch (Data[i + 3]) { + case SC_PICTURE: + PictureType = (Data[i + 5] >> 3) & 0x07; + return Length; + } + } + } + PictureType = NO_PICTURE; + return Length; + } + return -1; +} + +static inline const char *PictureTypeStr(int Type) +{ + switch(Type) { + case I_FRAME: return "I-Frame"; break; + case B_FRAME: return "B-Frame"; break; + case P_FRAME: return "P-Frame"; break; + case NO_PICTURE: return "(none)"; break; + default: break; + } + return "UNKNOWN"; +} + +#endif |