raze/polymer/eduke32/source/util/ivfrate.c

132 lines
3.3 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#define Bmemcmp memcmp
#ifndef USE_OPENGL
# define USE_OPENGL
#endif
#define ANIMVPX_STANDALONE
#include "animvpx.h"
static void print_info(const char *prefix, const animvpx_ivf_header_t *hdr)
{
printf("%s%d x %d, %d frames @ %d frames / %d seconds (%.3f fps%s)\n", prefix,
hdr->width, hdr->height, hdr->numframes, hdr->fpsnumer, hdr->fpsdenom,
(hdr->fpsdenom==0 ? 0 : (double)hdr->fpsnumer/hdr->fpsdenom),
hdr->fpsnumer>=1000 ? " --> 30 fps" : "");
}
int main(int argc, char **argv)
{
int fd, dowrite, err;
animvpx_ivf_header_t hdr;
union { uint16_t i; char c[2]; } u;
u.c[0] = 1;
u.c[1] = 0;
if (u.i != 1)
{
fprintf(stderr, "This program is only for little-endian machines.\n");
return 255;
}
if (argc == 2 && argv[1][0]=='-')
goto usage;
if (argc != 2 && argc != 4 && argc != 5)
{
usage:
fprintf(stderr, "Usage: %s <file.ivf> [<fpsnumerator> <fpsdenominator> [-force]]\n"
" Without -force, <fpsnumerator> must be < 1000.\n"
" If <fpsnumerator> is >= 1000, the actual frame rate\n"
" is set to 30 fps on playback.\n",
argv[0]);
return 1;
}
dowrite = (argc >= 4);
fd = open(argv[1], dowrite ? O_RDWR : O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Could't open \"%s\" for %s: %s\n", argv[1],
dowrite ? "reading/writing":"reading", strerror(errno));
return 2;
}
if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
{
fprintf(stderr, "Couldn't read IVF header: %s\n", strerror(errno));
return 3;
}
err = animvpx_check_header(&hdr);
if (err)
{
fprintf(stderr, "Header check failed with code %d (not an IVF file?)\n", err);
return 4;
}
if (!dowrite)
{
print_info("", &hdr);
}
else
{
unsigned long numer = strtoul(argv[2], NULL, 10);
unsigned long denom = strtoul(argv[3], NULL, 10);
uint32_t numer32=numer, denom32=denom;
const int NUMER_OFS = 16; //offsetof(animvpx_ivf_header_t, fpsnumer);
if (denom == 0)
{
fprintf(stderr, "FPS denominator must not be zero!\n");
return 4;
}
if (numer >= 1000 && (argc!=5 || strcmp(argv[4], "-force")))
{
fprintf(stderr, "FPS numerator must be < 1000, or -force must be passed as 5th arg.\n");
return 5;
}
if (numer32 != numer || denom32 != denom)
{
fprintf(stderr, "Out of range number passed.\n");
return 6;
}
print_info("Old: ", &hdr);
hdr.fpsnumer = numer32;
hdr.fpsdenom = denom32;
print_info("New: ", &hdr);
if (lseek(fd, NUMER_OFS, SEEK_SET) != NUMER_OFS)
{
fprintf(stderr, "lseek failed: %s\n", strerror(errno));
return 7;
}
err = 0;
err |= (write(fd, &numer32, 4) != 4);
err |= (write(fd, &denom32, 4) != 4);
if (err)
{
fprintf(stderr, "Warning: data not fully written.\n");
return 8;
}
}
return 0;
}