diff options
Diffstat (limited to 'plugins/streamdev/streamdev-cvs/remux/tsremux.c')
| -rw-r--r-- | plugins/streamdev/streamdev-cvs/remux/tsremux.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/plugins/streamdev/streamdev-cvs/remux/tsremux.c b/plugins/streamdev/streamdev-cvs/remux/tsremux.c new file mode 100644 index 0000000..a503ed0 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/remux/tsremux.c @@ -0,0 +1,87 @@ +#include "remux/tsremux.h" + +#define SC_PICTURE 0x00 // "picture header" +#define PID_MASK_HI 0x1F +#define VIDEO_STREAM_S 0xE0 + +using namespace Streamdev; + +void cTSRemux::SetBrokenLink(uchar *Data, int Length) +{ + int PesPayloadOffset = 0; + if (AnalyzePesHeader(Data, Length, PesPayloadOffset) >= phMPEG1 && (Data[3] & 0xF0) == VIDEO_STREAM_S) { + for (int i = PesPayloadOffset; i < Length - 7; i++) { + if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1 && Data[i + 3] == 0xB8) { + if (!(Data[i + 7] & 0x40)) // set flag only if GOP is not closed + Data[i + 7] |= 0x20; + return; + } + } + dsyslog("SetBrokenLink: no GOP header found in video packet"); + } + else + dsyslog("SetBrokenLink: no video packet in frame"); +} + +int cTSRemux::GetPid(const uchar *Data) +{ + return (((uint16_t)Data[0] & PID_MASK_HI) << 8) | (Data[1] & 0xFF); +} + +int cTSRemux::GetPacketLength(const uchar *Data, int Count, int Offset) +{ + // Returns the length of the packet starting at Offset, or -1 if Count is + // too small to contain the entire packet. + int Length = (Offset + 5 < Count) ? (Data[Offset + 4] << 8) + Data[Offset + 5] + 6 : -1; + if (Length > 0 && Offset + Length <= Count) + return Length; + return -1; +} + +int cTSRemux::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 Length = GetPacketLength(Data, Count, Offset); + if (Length > 0) { + int PesPayloadOffset = 0; + if (AnalyzePesHeader(Data + Offset, Length, PesPayloadOffset) >= phMPEG1) { + const uchar *p = Data + Offset + PesPayloadOffset + 2; + const uchar *pLimit = Data + Offset + Length - 3; +#ifdef TEST_cVideoRepacker + // cVideoRepacker ensures that a new PES packet is started for a new sequence, + // group or picture which allows us to easily skip scanning through a huge + // amount of video data. + if (p < pLimit) { + if (p[-2] || p[-1] || p[0] != 0x01) + pLimit = 0; // skip scanning: packet doesn't start with 0x000001 + else { + switch (p[1]) { + case SC_SEQUENCE: + case SC_GROUP: + case SC_PICTURE: + break; + default: // skip scanning: packet doesn't start a new sequence, group or picture + pLimit = 0; + } + } + } +#endif + while (p < pLimit && (p = (const uchar *)memchr(p, 0x01, pLimit - p))) { + if (!p[-2] && !p[-1]) { // found 0x000001 + switch (p[1]) { + case SC_PICTURE: PictureType = (p[3] >> 3) & 0x07; + return Length; + } + p += 4; // continue scanning after 0x01ssxxyy + } + else + p += 3; // continue scanning after 0x01xxyy + } + } + PictureType = NO_PICTURE; + return Length; + } + return -1; +} + |
