/* * Make a movie out of a pile of jpeg files. If you end up with terribly * long command lines make several shorter movies and join them with mvcat. * Each jpeg file is expected to be the same wid/ht and is expected to * match WID and HT. There is no checking for this here! * * cc -o jmv jmv.c -lmoviefile -ldmedia * * This program is hardwired for _frames_ by way of using * 1) DM_IMAGE_INTERLACING = DM_IMAGE_NONINTERLACED * and 2) mvInsertTrackData * * To change this to use _fields_ change: * 1) DM_IMAGE_INTERLACING = DM_IMAGE_INTERLACED_EVEN (PAL) _ODD (NTSC) * and 2) mvInsertTrackDataFields * * In a moviefile the ht and rate are always for the _frame_. so, if * one has a bunch of jpeg _fields_ then each jpeg file should be 240 * if the moviefile ht is 480, etc. */ #define WID 640 /* square pixel */ #define HT 480 /* frames (non-interlaced) */ #define RATE 29.97 /* NSTC _frame_ rate (hz) */ #include #include #include /* exit() */ #include #include /* select() timeout */ #include #include #include #include #include /* libdm errors */ DMstatus e; const char *e_short; int e_num; char e_long[DM_MAX_ERROR_DETAIL]; #define GE() e_short = dmGetError(&e_num, e_long); #define PR(str) fprintf(stderr, "libdm failed %s %s %d %s\n", str, e_short, e_num, e_long); #define EX(v) exit(v) #define ED(dmfunc, str) if ((e = dmfunc) != DM_SUCCESS) {GE(); PR(str); EX(1);} /* moviefile errors */ #define MVPR(s) fprintf(stderr, "%s: %s\n", s, mvGetErrorStr(mvGetErrno())) #define EMV(func, s) if (func == DM_FAILURE) { MVPR(s); exit(1); } char * readfile(char *filename, size_t *nbytes, int *fd) { char *cp; struct stat sb; *fd = open(filename, 0); if (*fd < 0) { perror(filename); exit(1); } if (stat(filename, &sb) < 0) { perror(filename); exit(1); } *nbytes = sb.st_size; cp = mmap(0, *nbytes, PROT_READ, MAP_PRIVATE, *fd, 0); if ((int)cp == -1) { perror(filename); exit(1); } return cp; } main(int argc, char **argv) { int wid = WID, ht = HT; int npix, fn; DMparams *p; char *mvfile = argv[1]; MVid mid, tid; MVtimescale tscale; MVtime dur; double rate = RATE; if (argc < 3) { fprintf(stderr, "usage: %s file.mv file.jpeg ...\n", argv[0]); exit(1); } npix = argc - 2; printf("wid %d, ht %d, rate %f, npix %d\n", wid, ht, rate, npix); /* * Create the movie file. */ ED(dmParamsCreate(&p), "movie params"); EMV(mvSetMovieDefaults(p, MV_FORMAT_QT), "movie defaults"); EMV(mvCreateFile(mvfile, p, NULL, &mid), "mv create"); dmParamsDestroy(p); /* * Create an image track in the movie. */ ED(dmParamsCreate(&p), "image params"); ED(dmSetImageDefaults(p, wid, ht, DM_PACKING_RGBX), "img def"); ED(dmParamsSetString(p, DM_IMAGE_COMPRESSION, DM_IMAGE_JPEG), "jpeg"); ED(dmParamsSetFloat(p, DM_IMAGE_RATE, rate), "rate"); ED(dmParamsSetEnum(p, DM_IMAGE_ORIENTATION, DM_TOP_TO_BOTTOM), "ttob"); ED(dmParamsSetEnum(p, DM_IMAGE_INTERLACING, DM_IMAGE_NONINTERLACED), "interlacing"); EMV(mvAddTrack(mid, DM_IMAGE, p, NULL, &tid), "add track"); dmParamsDestroy(p); tscale = mvGetTrackTimeScale(tid); dur = (long long)((double)tscale/rate); printf("tscale %d, dur %lld\n", tscale, dur); argv += 2; for (fn = 0; fn < npix; fn++, argv++) { size_t nbytes; int fd; char *buf = readfile(*argv, &nbytes, &fd); MVtime mvtime = (long long)fn * dur; printf("%d %s %d bytes\n", fn, *argv, nbytes); EMV(mvInsertTrackData(tid, 1, mvtime, dur, tscale, nbytes, buf, MV_FRAMETYPE_KEY, 0), "insert"); close(fd); } mvClose(mid); }