#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "sysdep.h"
#include <assert.h>

int fixed=0;

void gop2time(unsigned char* gop, unsigned char* time) {

  time[0]=(gop[0]&(64+32+16+8+4))>>2;
  time[1]=((gop[0]&(2+1))<<4)
    +((gop[1]&(128+64+32+16))>>4);
  time[2]=((gop[1]&(4+2+1))<<3)
    +((gop[2]&(128+64+32))>>5);
  time[3]=((gop[2]&(16+8+4+2+1))<<1)
    +((gop[3]&(128))>>7);
}

void printtime(unsigned char* time) {
  printf("%2.2d:%2.2d:%2.2d.%2.2d                 \r",time[0],time[1],time[2],time[3]);
}

void time2gop(unsigned char* gop, unsigned char* time) {

  gop[0] = (gop[0]&128)+             // 7
    (time[0]<<2)+                    // 6-2
    ((time[1]&(32+16))>>4);          // 1-0
  gop[1] = ((time[1]&(8+4+2+1))<<4)+ // 7-4
    (gop[1]&8)+                      // 3
    ((time[2]&(32+16+8))>>3);        // 2-0
  gop[2] = ((time[2]&(4+2+1))<<5)+
    ((time[3]&(32+16+8+4+2))>>1);
  gop[3] = ((time[3]&1)<<7)+
    (gop[3]&(64+32+16+8+4+2+1));
}

void frame2time(int frame, unsigned char* time) {
  time[3] = frame%30;
  time[2] = (frame/30)%60;
  time[1] = ((frame/30)/60)%60;
  time[0] = ((frame/30)/60)/60;
}

int goptime(unsigned char* mem, int i){

  unsigned char oldtime[4]; // h,m,s,f
  unsigned char newtime[4]; // h,m,s,f

  gop2time(mem,oldtime);
  frame2time(i,newtime);

  if (memcmp(oldtime,newtime,4) != 0) {
    fixed++;
    printf(" Fixing ");
    time2gop(mem,newtime);
  }
  printtime(newtime);
  fflush(stdout);
}

int main(int argc, char ** argv) {
  int fd;
  unsigned char a,b,c,d,e;
  int x;
  int fi;
  unsigned char *mem;
  unsigned char zero=0;
  unsigned char one=0x01;
  unsigned char b7=0xb7;
  unsigned char end[]={0x00,0x00,0x01,0xb7};
  //unsigned char end[]="abcd";
  OFF_T eofpos, len, fpos;

  for (fi=1; fi<argc; fi++) {
    fd = open_rw(argv[fi]);
    if (!fd) {
      printf("Couldn't open file %s\n",argv[fi]);
      return(-1);
    }
    
    len = lseek(fd,0,SEEK_END);
    lseek(fd,0,SEEK_SET);
    mem = mmap(0,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    x = 0;
    eofpos=-1;

    for (fpos=0; fpos<len; fpos++) {

      if ((mem[fpos]==0) &&
	  (mem[fpos+1]==0) &&
	  (mem[fpos+2]==1))
	{
	  if (mem[fpos+3]==0) { // Picture
	    x++;
	  }
	  if (mem[fpos+3]==0xb7) { // End of sequence. Replace by zero-padding.
#ifdef DEBUG
	    printf("End of sequence\n");
#endif
	    eofpos=fpos+2;
	    mem[fpos+2]=0;
	    mem[fpos+3]=0;
	  }
	  if (mem[fpos+3]==0xb8) { // GOP
	    printf("%s ",argv[fi]);
	    goptime(mem+fpos+4,x);
	  }
	}
    }
    if (eofpos>0) {
      mem[eofpos] = 1;
      mem[eofpos+1] = 0xb7;
    }
    printf("\nfinished %s \n",argv[fi]);
    printf("fixed %d GOP timestamps\n",fixed);
    fixed=0;
    munmap(mem,len);
    close(fd);
    if (eofpos==-1) {
      printf("Found no end-stamp. Adding...%s\n",end);
      fd = open_wr_app(argv[fi]);
      write(fd,end,4);
      close(fd);
    }
  }
  return 0;
}
