Back to Page
Revision 8 (current)
Edited by feos on 1/11/2022 11:31 AM
This tool, written by [user:sgrunt] for use in [EncodingGuide/Legacy|encoding] in conjunction with {{mencoder}}, takes a raw RGB24 video stream on {{stdin}}, removes duplicate frames, and writes the resulting stream to {{stdout}} and the associated timecodes to a specified file.
!! Usage
Usage is:
dedup <outfile> <fpsnum> <fpsden> <width> <height> [<max consecutive dup frames>]
where:
* {{<outfile>}} is the time code file to be written;
* {{<fpsnum>}} and {{<fpsden>}} are the numerator and denominator of the frame rate of the input stream;
* {{<width>}} and {{<height>}} are the dimensions of the video stream; and
* {{<max consecutive dup frames>}} is the maximum number of consecutive duplicate frames that will be removed from a stream. If not specified, the default value is 20, which tends to be a good trade off between disk space and usability.
{{mencoder}} can produce a raw RGB24 output with:
mencoder -nosound -of rawvideo -ovc raw -vf format=rgb24,scale <input/output files>
and can read a raw RGB24 input with:
mencoder -demuxer rawvideo -rawvideo format=rgb24:w=<width>:h=<height>:fps=<fps> <input/output/codec settings>
This is best used in conjunction with pipes or FIFOs to avoid having to write large raw files to disk.
!! Example: logo-combining
mkfifo dedupin
mkfifo dedupout
mencoder -nosound -of rawvideo -ovc raw -vf format=rgb24,scale logo.avi raw.avi -sub subtitle.srt -subpos 98 -subalign 2 -o dedupin &
dedup times.txt <fps> <width> <height> 20 <dedupin >dedupout &
mencoder -demuxer rawvideo -rawvideo format=rgb24:w=<width>:h=<height>:fps=<fps> dedupin -ovc x264 -x264encopts crf=0:fullrange=on -sws 9 -o in.avi
(Note that sound will need to be extracted from {{raw.avi}} and delayed by hand, perhaps with {{sox}}, for encoding purposes.)
!! Code
%%SRC_EMBED c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
unsigned char *prevframe, *curframe;
unsigned int width = 0, height = 0, framesize = 0;
unsigned int i = 0, tot = 20;
unsigned long framenum = 0;
unsigned short dup = 255;
unsigned long fpsnum = 0, fpsden = 0;
FILE* outfile = 0;
char outfilename[256];
if (argc < 6)
{
fprintf(stderr, "usage: dedup <outfile> <fpsnum> <fpsden> <width> <height> [<max consecutive dup frames>]\n");
exit(1);
}
strncpy(outfilename, argv[1], 256);
fpsnum = atoi(argv[2]);
fpsden = atoi(argv[3]);
width = atoi(argv[4]);
height = atoi(argv[5]);
if (argc >= 7)
{
tot = atoi(argv[6]);
}
framesize = width*height*3;
prevframe = (unsigned char *)malloc(sizeof(unsigned char)*framesize);
if (!prevframe)
{
perror("Couldn't malloc prevframe");
exit(2);
}
curframe = (unsigned char *)malloc(sizeof(unsigned char)*framesize);
if (!curframe)
{
perror("Couldn't malloc prevframe");
free(curframe);
exit(3);
}
outfile = fopen(outfilename, "w");
if (!outfile)
{
perror("Couldn't open output file");
free(prevframe);
free(curframe);
exit(4);
}
fprintf(outfile, "# timecode format v2\n");
while (!feof(stdin))
{
if (fread(curframe, sizeof(unsigned char), framesize, stdin) < framesize)
break;
if (dup != 255)
{
if (!memcmp(prevframe, curframe, framesize))
{
dup = 1;
i++;
if (tot > 0 && i >= tot)
{
dup = 0;
i = 0;
}
}
}
if (!dup || dup == 255)
{
if (fwrite(curframe, sizeof(unsigned char), framesize, stdout) < framesize)
break;
memcpy(prevframe, curframe, framesize);
fprintf(outfile, "%lu.%06lu\n",
framenum*1000*fpsden/fpsnum,
(framenum*10000000000*fpsden/fpsnum+5)/10%1000000);
}
framenum++;
dup = 0;
}
fclose(outfile);
free(prevframe);
free(curframe);
return 0;
}
%%END_EMBED