/ source / tools / src / ivfrate.cpp
ivfrate.cpp
  1  
  2  #include "compat.h"
  3  #ifndef USE_OPENGL
  4  # define USE_OPENGL
  5  #endif
  6  #define ANIMVPX_STANDALONE
  7  #include "animvpx.h"
  8  
  9  
 10  static void print_info(const char *prefix, const animvpx_ivf_header_t *hdr)
 11  {
 12      printf("%s%d x %d, %d frames @ %d frames / %d seconds (%.3f fps%s)\n", prefix,
 13             hdr->width, hdr->height, hdr->numframes, hdr->fpsnumer, hdr->fpsdenom,
 14             (hdr->fpsdenom==0 ? 0 : (double)hdr->fpsnumer/hdr->fpsdenom),
 15             hdr->fpsnumer>=1000 ? " --> 30 fps" : "");
 16  }
 17  
 18  
 19  int main(int argc, char **argv)
 20  {
 21      int fd, dowrite, err;
 22      animvpx_ivf_header_t hdr;
 23  
 24      union { uint16_t i; char c[2]; } u;
 25      u.c[0] = 1;
 26      u.c[1] = 0;
 27      if (u.i != 1)
 28      {
 29          fprintf(stderr, "This program is only for little-endian machines.\n");
 30          return 255;
 31      }
 32  
 33      if (argc == 2 && argv[1][0]=='-')
 34          goto usage;
 35  
 36      if (argc != 2 && argc != 4 && argc != 5)
 37      {
 38  usage:
 39          fprintf(stderr, "Usage: %s <file.ivf> [<fpsnumerator> <fpsdenominator> [-force]]\n"
 40                  " Without -force, <fpsnumerator> must be < 1000.\n"
 41                  " If <fpsnumerator> is >= 1000, the actual frame rate\n"
 42                  " is set to 30 fps on playback.\n",
 43                  argv[0]);
 44          return 1;
 45      }
 46  
 47      dowrite = (argc >= 4);
 48  
 49      fd = open(argv[1], dowrite ? O_RDWR : O_RDONLY);
 50      if (fd < 0)
 51      {
 52          fprintf(stderr, "Could't open \"%s\" for %s: %s\n", argv[1],
 53                  dowrite ? "reading/writing":"reading", strerror(errno));
 54          return 2;
 55      }
 56  
 57      if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
 58      {
 59          fprintf(stderr, "Couldn't read IVF header: %s\n", strerror(errno));
 60          return 3;
 61      }
 62  
 63      err = animvpx_check_header(&hdr);
 64      if (err)
 65      {
 66          fprintf(stderr, "Header check failed with code %d (not an IVF file?)\n", err);
 67          return 4;
 68      }
 69  
 70      if (!dowrite)
 71      {
 72          print_info("", &hdr);
 73      }
 74      else
 75      {
 76          unsigned long numer = strtoul(argv[2], NULL, 10);
 77          unsigned long denom = strtoul(argv[3], NULL, 10);
 78          uint32_t numer32=numer, denom32=denom;
 79          const int NUMER_OFS = 16;  //offsetof(animvpx_ivf_header_t, fpsnumer);
 80  
 81          if (denom == 0)
 82          {
 83              fprintf(stderr, "FPS denominator must not be zero!\n");
 84              return 4;
 85          }
 86  
 87          if (numer >= 1000 && (argc!=5 || strcmp(argv[4], "-force")))
 88          {
 89              fprintf(stderr, "FPS numerator must be < 1000, or -force must be passed as 5th arg.\n");
 90              return 5;
 91          }
 92  
 93          if (numer32 != numer || denom32 != denom)
 94          {
 95              fprintf(stderr, "Out of range number passed.\n");
 96              return 6;
 97          }
 98  
 99          print_info("Old: ", &hdr);
100          hdr.fpsnumer = numer32;
101          hdr.fpsdenom = denom32;
102          print_info("New: ", &hdr);
103  
104          if (lseek(fd, NUMER_OFS, SEEK_SET) != NUMER_OFS)
105          {
106              fprintf(stderr, "lseek failed: %s\n", strerror(errno));
107              return 7;
108          }
109  
110          err = 0;
111          err |= (write(fd, &numer32, 4) != 4);
112          err |= (write(fd, &denom32, 4) != 4);
113  
114          if (err)
115          {
116              fprintf(stderr, "Warning: data not fully written.\n");
117              return 8;
118          }
119      }
120  
121      return 0;
122  }