TS optimize, specifically MPEG2 speedup

This commit is contained in:
Thulinma 2018-11-01 17:04:05 +01:00
parent df6862fb0a
commit 6e2e7d81b2
2 changed files with 54 additions and 61 deletions

View file

@ -3,17 +3,17 @@
#endif #endif
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <math.h>//for log #include <math.h> //for log
#include "nal.h"
#include "bitstream.h"
#include "bitfields.h" #include "bitfields.h"
#include "bitstream.h"
#include "defines.h" #include "defines.h"
#include "nal.h"
namespace nalu { namespace nalu{
std::deque<int> parseNalSizes(DTSC::Packet & pack){ std::deque<int> parseNalSizes(DTSC::Packet &pack){
std::deque<int> result; std::deque<int> result;
char * data; char *data;
unsigned int dataLen; unsigned int dataLen;
pack.getString("data", data, dataLen); pack.getString("data", data, dataLen);
int offset = 0; int offset = 0;
@ -25,7 +25,7 @@ namespace nalu {
return result; return result;
} }
std::string removeEmulationPrevention(const std::string & data) { std::string removeEmulationPrevention(const std::string &data){
std::string result; std::string result;
result.resize(data.size()); result.resize(data.size());
result[0] = data[0]; result[0] = data[0];
@ -33,76 +33,71 @@ namespace nalu {
unsigned int dataPtr = 2; unsigned int dataPtr = 2;
unsigned int dataLen = data.size(); unsigned int dataLen = data.size();
unsigned int resPtr = 2; unsigned int resPtr = 2;
while (dataPtr + 2 < dataLen) { while (dataPtr + 2 < dataLen){
if (!data[dataPtr] && !data[dataPtr + 1] && data[dataPtr + 2] == 3){ //We have found an emulation prevention if (!data[dataPtr] && !data[dataPtr + 1] &&
data[dataPtr + 2] == 3){// We have found an emulation prevention
result[resPtr++] = data[dataPtr++]; result[resPtr++] = data[dataPtr++];
result[resPtr++] = data[dataPtr++]; result[resPtr++] = data[dataPtr++];
dataPtr++; //Skip the emulation prevention byte dataPtr++; // Skip the emulation prevention byte
} else { }else{
result[resPtr++] = data[dataPtr++]; result[resPtr++] = data[dataPtr++];
} }
} }
while (dataPtr < dataLen){ while (dataPtr < dataLen){result[resPtr++] = data[dataPtr++];}
result[resPtr++] = data[dataPtr++];
}
return result.substr(0, resPtr); return result.substr(0, resPtr);
} }
unsigned long toAnnexB(const char * data, unsigned long dataSize, char *& result){ unsigned long toAnnexB(const char *data, unsigned long dataSize, char *&result){
//toAnnexB keeps the same size. // toAnnexB keeps the same size.
if (!result){ if (!result){result = (char *)malloc(dataSize);}
result = (char *)malloc(dataSize);
}
int offset = 0; int offset = 0;
while (offset < dataSize){ while (offset < dataSize){
//Read unit size // Read unit size
unsigned long unitSize = Bit::btohl(data + offset); unsigned long unitSize = Bit::btohl(data + offset);
//Write annex b header // Write annex b header
memset(result + offset, 0x00, 3); memset(result + offset, 0x00, 3);
result[offset + 3] = 0x01; result[offset + 3] = 0x01;
//Copy the nal unit // Copy the nal unit
memcpy(result + offset + 4, data + offset + 4, unitSize); memcpy(result + offset + 4, data + offset + 4, unitSize);
//Update the offset // Update the offset
offset += 4 + unitSize; offset += 4 + unitSize;
} }
return dataSize; return dataSize;
} }
///Scans data for the last non-zero byte, returning a pointer to it. /// Scans data for the last non-zero byte, returning a pointer to it.
const char* nalEndPosition(const char * data, uint32_t dataSize){ const char *nalEndPosition(const char *data, uint32_t dataSize){
while(dataSize > 0 && memcmp(data+dataSize-1, "\000",1) == 0 ){ while (dataSize && !data[dataSize - 1]){--dataSize;}
dataSize--; return data + dataSize;
}
return data+dataSize;
} }
///Scan data for Annex B start code. Returns pointer to it when found, null otherwise. /// Scan data for Annex B start code. Returns pointer to it when found, null otherwise.
const char * scanAnnexB(const char * data, uint32_t dataSize){ const char *scanAnnexB(const char *data, uint32_t dataSize){
char * offset = (char*)data; char *offset = (char *)data;
const char * maxData = data + dataSize - 2; const char *maxData = data + dataSize - 2;
while(offset < maxData){ while (offset < maxData){
if (offset[2] > 1){ if (offset[2] > 1){
//We have no zero in the third byte, so we need to skip at least 3 bytes forward // We have no zero in the third byte, so we need to skip at least 3 bytes forward
offset += 3; offset += 3;
continue; continue;
} }
if (!offset[2]){ if (!offset[2]){
//We skip forward 1 or 2 bytes depending on contents of the second byte // We COULD skip forward 1 or 2 bytes depending on contents of the second byte
offset += (offset[1]?2:1); // offset += (offset[1]?2:1);
//... but skipping a single byte (removing the 'if') is actually faster (benchmarked).
++offset;
continue; continue;
} }
if (!offset[0] && !offset[1]){ if (!offset[0] && !offset[1]){return offset;}
return offset; // We have no zero in the third byte, so we need to skip at least 3 bytes forward
}
//We have no zero in the third byte, so we need to skip at least 3 bytes forward
offset += 3; offset += 3;
} }
return 0; return 0;
} }
unsigned long fromAnnexB(const char * data, unsigned long dataSize, char *& result){ unsigned long fromAnnexB(const char *data, unsigned long dataSize, char *&result){
const char * lastCheck = data + dataSize - 3; const char *lastCheck = data + dataSize - 3;
if (!result){ if (!result){
FAIL_MSG("No output buffer given to FromAnnexB"); FAIL_MSG("No output buffer given to FromAnnexB");
return 0; return 0;
@ -110,26 +105,20 @@ namespace nalu {
int offset = 0; int offset = 0;
int newOffset = 0; int newOffset = 0;
while (offset < dataSize){ while (offset < dataSize){
const char * begin = data + offset; const char *begin = data + offset;
while ( begin < lastCheck && !(!begin[0] && !begin[1] && begin[2] == 0x01)){ while (begin < lastCheck && !(!begin[0] && !begin[1] && begin[2] == 0x01)){
begin++;
if (begin < lastCheck && begin[0]){
begin++; begin++;
if (begin < lastCheck && begin[0]){begin++;}
} }
} begin += 3; // Initialize begin after the first 0x000001 pattern.
begin += 3;//Initialize begin after the first 0x000001 pattern.
if (begin > data + dataSize){ if (begin > data + dataSize){
offset = dataSize; offset = dataSize;
continue; continue;
} }
const char * end = (const char*)memmem(begin, dataSize - (begin - data), "\000\000\001", 3); const char *end = (const char *)memmem(begin, dataSize - (begin - data), "\000\000\001", 3);
if (!end) { if (!end){end = data + dataSize;}
end = data + dataSize; // Check for 4-byte lead in's. Yes, we access -1 here
} if (end > begin && (end - data) != dataSize && end[-1] == 0x00){end--;}
//Check for 4-byte lead in's. Yes, we access -1 here
if (end > begin && (end - data) != dataSize && end[-1] == 0x00){
end--;
}
unsigned int nalSize = end - begin; unsigned int nalSize = end - begin;
Bit::htobl(result + newOffset, nalSize); Bit::htobl(result + newOffset, nalSize);
memcpy(result + newOffset + 4, begin, nalSize); memcpy(result + newOffset + 4, begin, nalSize);
@ -139,4 +128,5 @@ namespace nalu {
} }
return newOffset; return newOffset;
} }
} }// namespace nalu

View file

@ -132,8 +132,8 @@ namespace TS{
int tid = newPack.getPID(); int tid = newPack.getPID();
bool unitStart = newPack.getUnitStart(); bool unitStart = newPack.getUnitStart();
std::deque<Packet> & PS = pesStreams[tid]; std::deque<Packet> & PS = pesStreams[tid];
if ((pidToCodec.count(tid) || tid == 0 || newPack.isPMT()) && if ((unitStart || PS.size()) &&
(unitStart || PS.size())){ (tid == 0 || newPack.isPMT() || pidToCodec.count(tid))){
PS.push_back(newPack); PS.push_back(newPack);
if (unitStart){ if (unitStart){
pesPositions[tid].push_back(bytePos); pesPositions[tid].push_back(bytePos);
@ -667,13 +667,16 @@ namespace TS{
return; return;
} }
while (nextPtr < pesEnd){ uint32_t nalno = 0;
//We only check the first 8 packets, because keys should always be near the front of a PES.
while (nextPtr < pesEnd && nalno < 8){
if (!nextPtr){nextPtr = pesEnd;} if (!nextPtr){nextPtr = pesEnd;}
//Calculate size of NAL unit, removing null bytes from the end //Calculate size of NAL unit, removing null bytes from the end
nalSize = nalu::nalEndPosition(pesPayload, nextPtr - pesPayload) - pesPayload; nalSize = nalu::nalEndPosition(pesPayload, nextPtr - pesPayload) - pesPayload;
// Check if this is a keyframe // Check if this is a keyframe
parseNal(tid, pesPayload, nextPtr, isKeyFrame); parseNal(tid, pesPayload, nextPtr, isKeyFrame);
++nalno;
if (((nextPtr - pesPayload) + 3) >= realPayloadSize){break;}//end of the loop if (((nextPtr - pesPayload) + 3) >= realPayloadSize){break;}//end of the loop
realPayloadSize -= ((nextPtr - pesPayload) + 3); // decrease the total size realPayloadSize -= ((nextPtr - pesPayload) + 3); // decrease the total size