VDR-1.3.44: speedup patch for cRemux::ScanVideoPacket()
Commit Message
Hi,
the attached patch speeds up ScanVideoPacket() in two ways:
- finding the start code is done by memchr(), which was the major change
for the cVideoRepacker speedup patches some VDR versions ago.
- ScanVideoPacket() may skip scanning the packets most of the time when
cVideoRepacker is enabled (see source comments for details).
As a result, the CPU load of my EPIA system with a 600 MHz CPU drops
from 27 % to 17 % for receiving the 'ASTRA HD' HDTV demo channel.
Besides the mentioned improvements, I've declared ScanVideoPacket() and
GetPacketLength() static and pubic, as I'd like to use their
functionality in future versions of vdr-xine.
Bye.
@@ -46,8 +48,6 @@ private:
cRingBufferLinear *resultBuffer;
int resultSkipped;
int GetPid(const uchar *Data);
- int GetPacketLength(const uchar *Data, int Count, int Offset);
- int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
public:
cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
///< Creates a new remuxer for the given PIDs. VPid is the video PID, while
@@ -79,6 +80,8 @@ public:
///< Clears the remuxer of all data it might still contain, keeping the PID
///< settings as they are.
static void SetBrokenLink(uchar *Data, int Length);
+ static int GetPacketLength(const uchar *Data, int Count, int Offset);
+ static int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
};
#endif // __REMUX_H
@@ -1429,7 +1821,9 @@ int cDolbyRepacker::BreakAt(const uchar
#define IPACKS 2048
// Start codes:
-#define SC_PICTURE 0x00 // "picture header"
+#define SC_SEQUENCE 0xB3 // "sequence header code"
+#define SC_GROUP 0xB8 // "group start code"
+#define SC_PICTURE 0x00 // "picture start code"
#define MAXNONUSEFULDATA (10*1024*1024)
#define MAXNUMUPTERRORS 10
@@ -1925,14 +2327,38 @@ int cRemux::ScanVideoPacket(const uchar
if (Length > 0) {
int PesPayloadOffset = 0;
if (AnalyzePesHeader(Data + Offset, Length, PesPayloadOffset) >= phMPEG1) {
- for (int i = Offset + PesPayloadOffset; i < Offset + Length - 5; 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;
+ 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;