TASVideos

Tool-assisted game movies
When human skills are just not enough

Encoding Guide / Dedup C

This tool, written by sgrunt for use in 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:

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

#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;
}


Combined RSS Feed
EncodingGuide/DedupC last edited by sgrunt on 2011-07-05 15:37:13
Page info and history | Latest diff | List referrers | View Source