Skip to content

Commit

Permalink
Merge pull request #5 from mblythe86/master
Browse files Browse the repository at this point in the history
New add_zero feature
  • Loading branch information
MonoS authored Jul 21, 2023
2 parents 0d55c2b + 66af107 commit 870916d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 10 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
SupMover - Shift timings and Screen Area of PGS/Sup subtitle

# Usage
`SupMover (<input.sup> <output.sup>) [delay (ms)] [crop (<left> <top> <right> <bottom>)] [resync (<num>/<den> | multFactor)]`
`SupMover (<input.sup> <output.sup>) [delay (ms)] [crop (<left> <top> <right> <bottom>)] [resync (<num>/<den> | multFactor)] [add_zero]`

`SupMover (<input.sup> <output.sup> <ms>)` old syntax, kept for backward compatibility

Expand All @@ -17,6 +17,8 @@ SupMover - Shift timings and Screen Area of PGS/Sup subtitle
* Crop functionality is not exstensivelly tested when multiple Composition Object or Windows are present or when the windows are is outside the new screen area, a warning is issued if that's the case and i strongly advise to check the resulting subtitle with a video player, also handling of the Object Cropped flag and windows area bigger than the new screen area is not implemented, a warning is issued if needed
* delay + resync
* If both modes are selected the delay will be adjusted if it comes before the resync parameter, for example if the program is launched with `delay 1000 resync 1.001` it will be internally adjusted to 1001ms, instead if it's launched with `resync 1.001 delay 1000` it will not
* add_zero
* Some media players (especially Plex) don't correctly sync `*.sup` subtitles. They seem to ignore any delay before the first 'display set'. This option adds a dummy 'display set' at time 0 so subsequent timestamps are correctly interpreted.

# Build instruction
```
Expand Down
75 changes: 66 additions & 9 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ struct t_crop {
};

struct t_header{
uint16_t header;
uint32_t pts1;
uint16_t dataLength;
uint16_t header;
uint32_t pts1;
uint32_t dts;
uint16_t dataLength;
uint8_t segmentType;
};

Expand Down Expand Up @@ -98,14 +99,19 @@ t_header ReadHeader(uint8_t* buffer) {

header.header = swapEndianness(*(uint16_t*)&buffer[0]);
header.pts1 = swapEndianness(*(uint32_t*)&buffer[2]);
header.dts = swapEndianness(*(uint32_t*)&buffer[6]);
header.segmentType = *(uint8_t*)&buffer[10];
header.dataLength = swapEndianness(*(uint16_t*)&buffer[11]);

return header;
}

void WriteHeader(t_header header, uint8_t* buffer) {
*((uint16_t*)(&buffer[0])) = swapEndianness(header.header);
*((uint32_t*)(&buffer[2])) = swapEndianness(header.pts1);
*((uint32_t*)(&buffer[6])) = swapEndianness(header.dts);
*((uint8_t*)(&buffer[10])) = header.segmentType;
*((uint16_t*)(&buffer[11])) = swapEndianness(header.dataLength);
}

t_WDS ReadWDS(uint8_t* buffer) {
Expand Down Expand Up @@ -225,15 +231,19 @@ t_timestamp PTStoTimestamp(uint32_t pts){
return res;
}

bool ParseCMD(int32_t argc, char** argv, int32_t& delay, t_crop& crop, double& resync) {
bool ParseCMD(int32_t argc, char** argv, int32_t& delay, t_crop& crop, double& resync, bool& addZero) {
delay = 0;
crop = {};
resync = 1;
addZero = false;
int i = 3;
if (argc == 4) {
//backward compatibility
delay = (int32_t)round(atof(argv[3]) * PTS_MULT);
return true;
if(delay != 0){
printf("Running in backwards-compatibility mode\n");
return true;
}
}

while(i < argc) {
Expand Down Expand Up @@ -268,6 +278,10 @@ bool ParseCMD(int32_t argc, char** argv, int32_t& delay, t_crop& crop, double& r

i += 2;
}
else if (command == "add_zero") {
addZero = true;
i += 1;
}
else {
return false;
}
Expand All @@ -283,15 +297,16 @@ int main(int32_t argc, char** argv)


if(argc < 4){
printf("Usage: SupMover (<input.sup> <output.sup>) [delay (ms)] [crop (<left> <top> <right> <bottom>)] [resync (<num>/<den> | multFactor)]\r\n");
printf("Usage: SupMover (<input.sup> <output.sup>) [delay (ms)] [crop (<left> <top> <right> <bottom>)] [resync (<num>/<den> | multFactor)] [add_zero]\r\n");
printf("delay and resync command are executed in the order supplied\r\n");
return 0;
}
int32_t delay = {};
t_crop crop = {};
double resync = 1;
bool addZero = false;

if (!ParseCMD(argc, argv, delay, crop, resync)) {
if (!ParseCMD(argc, argv, delay, crop, resync, addZero)) {
printf("Error parsing input\r\n");
return -1;
}
Expand Down Expand Up @@ -323,7 +338,7 @@ int main(int32_t argc, char** argv)
}

fread(buffer, size, 1, input);
if(doDelay || doCrop || doResync){
if(doDelay || doCrop || doResync || addZero){
size_t start = 0;

t_rect screenRect = {};
Expand Down Expand Up @@ -363,7 +378,7 @@ int main(int32_t argc, char** argv)
break;
case 0x16:
//printf("PCS\r\n");
if (doCrop) {
if (doCrop || addZero) {
pcs = ReadPCS(&buffer[start + HEADER_SIZE]);
offesetCurrPCS = start;

Expand Down Expand Up @@ -401,6 +416,48 @@ int main(int32_t argc, char** argv)
}
}

if (addZero) {
if (pcs.compositionNumber == 0){
uint8_t zeroBuffer[60];
uint8_t pos = 0;
t_header zeroHeader(header);
zeroHeader.pts1 = 0;
zeroHeader.dataLength = 11; //Length of upcoming PCS
WriteHeader(zeroHeader, &zeroBuffer[pos]);
pos += 13;
t_PCS zeroPcs(pcs);
zeroPcs.compositionState = 0;
zeroPcs.paletteUpdFlag = 0;
zeroPcs.paletteID = 0;
zeroPcs.numCompositionObject = 0;
WritePCS(zeroPcs, &zeroBuffer[pos]);
pos += zeroHeader.dataLength;

zeroHeader.segmentType = 0x17; // WDS
zeroHeader.dataLength = 10; //Length of upcoming WDS
WriteHeader(zeroHeader, &zeroBuffer[pos]);
pos += 13;
t_WDS zeroWds;
zeroWds.numberOfWindows = 1;
zeroWds.windows[0].windowID = 0;
zeroWds.windows[0].WindowsHorPos = 0;
zeroWds.windows[0].WindowsVerPos = 0;
zeroWds.windows[0].WindowsWidth = 0;
zeroWds.windows[0].WindowsHeight = 0;
WriteWDS(zeroWds,&zeroBuffer[pos]);
pos += zeroHeader.dataLength;

zeroHeader.segmentType = 0x80; // END
zeroHeader.dataLength = 0; //Length of upcoming END
WriteHeader(zeroHeader, &zeroBuffer[pos]);
pos += 13;

printf("Writing %d bytes as first display set\n", pos);
fwrite(zeroBuffer, pos, 1, output);
}
pcs.compositionNumber += 1;
}

WritePCS(pcs, &buffer[start + HEADER_SIZE]);
}
break;
Expand Down

0 comments on commit 870916d

Please sign in to comment.