summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/tools/aviindex.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/tools/aviindex.c')
-rw-r--r--debian/transcode/transcode-1.1.7/tools/aviindex.c914
1 files changed, 914 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/tools/aviindex.c b/debian/transcode/transcode-1.1.7/tools/aviindex.c
new file mode 100644
index 00000000..8a34234f
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/tools/aviindex.c
@@ -0,0 +1,914 @@
+/*
+ * aviindex.c
+ *
+ * extracts the index of an AVI file for easy seeking with --nav_seek
+ *
+ * Copyright (C) Tilmann Bitterberg - June 2003
+ *
+ * This file is part of transcode, a video stream processing tool
+ *
+ * transcode is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * transcode is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "transcode.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "libtc/xio.h"
+
+#include "aud_scan.h"
+
+#define EXE "aviindex"
+
+/* AVI_info is no longer in avilib */
+void AVI_info(avi_t *avifile);
+
+void version(void)
+{
+ printf("%s (%s v%s) (C) 2003-2004 Tilmann Bitterberg,"
+ " 2004-2010 Transcode Team\n",
+ EXE, PACKAGE, VERSION);
+}
+
+
+static void usage(int status)
+{
+ version();
+ printf("\nUsage: %s [options]\n", EXE);
+ printf(" -o file output file\n");
+ printf(" -i file input file\n");
+ printf(" -f force the use of the existing index\n");
+ printf(" only to use when avi > 2GB, because\n");
+ printf(" the default is to -n with big files\n");
+ printf(" -n read index in \"smart\" mode: don't use the existing index\n");
+ printf(" -x don't use the existing index to generate the keyframes\n");
+ printf(" this flag forces -n\n");
+ printf(" -v print version\n");
+ exit(status);
+}
+
+#define PAD_EVEN(x) ( ((x)+1) & ~1 )
+static unsigned long str2ulong(unsigned char *str)
+{
+ return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );
+}
+
+#define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-2048)
+
+static inline uint32_t SWAP(uint32_t a) {
+#ifdef WORDS_BIGENDIAN
+ return ( (a<<24&0xff000000) | (a<< 8&0x00ff0000) |
+ (a>> 8&0x0000ff00) | (a>>24&0x000000ff));
+#else
+ return a;
+#endif
+}
+
+static inline int avi_stream_id(unsigned int id){
+ unsigned char *p=(unsigned char *)&id;
+ unsigned char a,b;
+#if WORDS_BIGENDIAN
+ a=p[3]-'0'; b=p[2]-'0';
+#else
+ a=p[0]-'0'; b=p[1]-'0';
+#endif
+ if(a>9 || b>9) return 100; // invalid ID
+ return a*10+b;
+}
+
+// returns 1 for video
+// 2 for 1st audio
+// 3 for 2nd audio
+static int avi_stream_nr(int id)
+{
+ unsigned char *p = (unsigned char *)&id;
+
+#if WORDS_BIGENDIAN
+ if (p[1] == 'd') {
+ return 1;
+ } else {
+ int res = (p[3]-'0')+(p[2]-'0');
+ res = (res==0)?2:res+1;
+ return res;
+ }
+#else
+ if (p[2] == 'd') {
+ return 1;
+ } else {
+ int res = (p[0]-'0')+(p[1]-'0');
+ res = (res==0)?2:res+1;
+ return res;
+ }
+#endif
+ return 0;
+}
+
+const int LEN=10;
+
+typedef enum {
+ UNKNOWN = 0,
+ RIFF,
+ AVIIDX1,
+ MPIDX1,
+} ftype_t;
+
+typedef struct {
+ uint32_t ckid;
+ uint32_t dwFlags;
+ uint32_t dwChunkOffset;
+ uint32_t dwChunkLength;
+} AVIINDEXENTRY;
+
+static int aviidx1_to_mpidx1(char *in_file, FILE *out_fd)
+{
+ char *data;
+ FILE *in;
+ int size=0, i;
+ AVIINDEXENTRY *idx;
+ char line[255], d;
+
+ in = fopen (in_file, "r");
+ if (!in) return 1;
+
+ // skip header
+ fgets (line, 255, in);
+ fgets (line, 255, in);
+ while (fgets(line, 255, in)) {
+ d = line[5] - '1';
+ if (d == 0) {
+ size++;
+ } else if (d == 1 || d == 2 || d == 3 || d == 4 ||
+ d == 5 || d == 6 || d == 7 || d == 8 ) {
+ size++;
+ } else continue;
+ }
+ data = malloc (size * sizeof (AVIINDEXENTRY));
+ fseek(in, 0, SEEK_SET);
+ fgets (line, 255, in); fgets (line, 255, in);
+
+ i = size;
+ idx = &((AVIINDEXENTRY *)data)[0];
+ while (fgets(line, 255, in) && i--) {
+ char *c=line;
+ idx->ckid=*(int *)c;
+ idx->ckid=SWAP(idx->ckid);
+ c = strchr(c, ' ')+1; // type
+ c = strchr(c, ' ')+1; // chunk
+ c = strchr(c, ' ')+1; // chunk/type
+ c = strchr(c, ' ')+1; // pos
+ idx->dwChunkOffset = strtol(c, &c, 10);
+ idx->dwChunkLength = strtol(c+1, &c, 10);
+ idx->dwFlags = strtol(c+1, &c, 10);
+ idx->dwFlags = idx->dwFlags?0x10:0;
+ idx++;
+
+ }
+ fwrite ("MPIDX1", 6, 1, out_fd);
+ fwrite (&size, 4, 1, out_fd);
+ fwrite (data, sizeof(AVIINDEXENTRY), size, out_fd);
+
+ free(data);
+ fclose (in);
+ fclose(out_fd);
+ return 0;
+}
+
+static int mpidx1_to_aviidx1(char *in_file, FILE *out_fd)
+{
+ char head[10];
+ char *data;
+ FILE *in;
+ int size, i;
+ AVIINDEXENTRY *idx;
+ int streams[100];
+
+ in = fopen (in_file, "r");
+ if (!in) return 1;
+ fread (head, 10, 1, in);
+
+ // header. Magic tag is AVIIDX1
+ fprintf(out_fd, "AVIIDX1 # Generated by %s (%s-%s)\n", EXE, PACKAGE, VERSION); // Magic
+ fprintf(out_fd, "TAG TYPE CHUNK CHUNK/TYPE POS LEN KEY MS\n");
+
+ size = *(int *)(head+6);
+ data = malloc (size * sizeof(AVIINDEXENTRY));
+ memset (streams, 0, sizeof(streams));
+ if (size != fread (data, sizeof(AVIINDEXENTRY), size, in)) {
+ perror("fread"); return 1;
+ }
+ for (i = 0; i<size; i++) {
+ uint32_t ckid;
+ idx = &((AVIINDEXENTRY *)data)[i];
+ ckid = SWAP(idx->ckid);
+ fprintf(out_fd,
+ "%.4s %d %d %d %d %d %d 0\n",
+ (char *)&ckid,
+ avi_stream_nr(idx->ckid),
+ i,
+ streams[avi_stream_id(idx->ckid)],
+ idx->dwChunkOffset,
+ idx->dwChunkLength,
+ idx->dwFlags?1:0);
+
+ streams[avi_stream_id(idx->ckid)]++;
+ }
+
+
+ free(data);
+ fclose (in);
+ fclose(out_fd);
+
+ return 0;
+}
+
+// data is only 8 bytes long
+static int AVI_read_data_fast(avi_t *AVI, char *buf, off_t *pos, off_t *len, off_t *key, char *data)
+{
+
+/*
+ * Return codes:
+ *
+ * 0 = reached EOF
+ * 1 = video data read
+ * 2 = audio data read from track 0
+ * 3 = audio data read from track 1
+ * 4 = audio data read from track 2
+ * ....
+ * 10 = traditional idx1 chunk
+ */
+
+ off_t n;
+ int rlen;
+ *key=(off_t)0;
+
+ if(AVI->mode==AVI_MODE_WRITE) return 0;
+
+ while(1)
+ {
+ /* Read tag and length */
+
+ if( xio_read(AVI->fdes,data,8) != 8 ) return 0;
+
+ n = PAD_EVEN(str2ulong(data+4));
+
+ if(strncasecmp(data,"LIST",4) == 0 ||
+ strncasecmp(data,"RIFF",4) == 0) { // prevents skipping extended RIFF chunks
+ if( xio_read(AVI->fdes,data,4) != 4 ) return 0;
+ n -= 4;
+ // put here tags of lists that need to be looked into
+ if(strncasecmp(data,"movi",4) == 0 ||
+ strncasecmp(data,"rec ",4) == 0 ||
+ strncasecmp(data,"AVI ",4) == 0 ||
+ strncasecmp(data,"AVIX",4) == 0) {
+ // xio_lseek(AVI->fdes,-4,SEEK_CUR);
+ continue; // proceed to look into it
+ } // otherwise seek over it later on
+ }
+
+ // the following list of comparisons should not include list tags;
+ // these should all go in the list above
+ if(strncasecmp(data,"IDX1",4) == 0)
+ {
+ // deal with it to extract keyframe info
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ //fprintf (stderr, "Found an index chunk at %lld len %lld\n", *pos, *len);
+ if(xio_lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) return 0;
+ return 10;
+ }
+
+ if(strncasecmp(data,AVI->video_tag,3) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->video_pos++;
+ rlen = n;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 1;
+ }
+ else if(AVI->anum>=1 && strncasecmp(data,AVI->track[0].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[0].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 2;
+ break;
+ }
+ else if(AVI->anum>=2 && strncasecmp(data,AVI->track[1].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[1].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 3;
+ break;
+ }
+ else if(AVI->anum>=3 && strncasecmp(data,AVI->track[2].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[2].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 4;
+ break;
+ }
+ else if(AVI->anum>=4 && strncasecmp(data,AVI->track[3].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[3].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 5;
+ break;
+ }
+ else if(AVI->anum>=5 && strncasecmp(data,AVI->track[4].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[4].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 6;
+ break;
+ }
+ else if(AVI->anum>=6 && strncasecmp(data,AVI->track[5].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[5].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 7;
+ break;
+ }
+ else if(AVI->anum>=7 && strncasecmp(data,AVI->track[6].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[6].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 8;
+ break;
+ }
+ else if(AVI->anum>=8 && strncasecmp(data,AVI->track[7].audio_tag,4) == 0)
+ {
+ *len = str2ulong(data+4);
+ *pos = xio_lseek(AVI->fdes, 0, SEEK_CUR)-(off_t)8;
+ AVI->track[7].audio_posc++;
+ rlen = (n<LEN)?n:LEN;
+ xio_read(AVI->fdes, buf, rlen);
+ if(xio_lseek(AVI->fdes,n-rlen,SEEK_CUR)==(off_t)-1) return 0;
+ return 9;
+ break;
+ } else {
+ if(xio_lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) return 0;
+ }
+ // else if(xio_lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) return 0;
+ }
+}
+
+static int is_key(unsigned char *data, long size, char *codec)
+{
+ if (strncasecmp(codec, "div3", 4) == 0) {
+
+ int32_t c=( (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]&0xff) );
+ if(c&0x40000000) return(0);
+ else return 1;
+
+ } else if (strncasecmp(codec, "xvid", 4) == 0 || strncasecmp(codec, "divx", 4) == 0
+ || strncasecmp(codec, "dx50", 4) == 0 || strncasecmp(codec, "div4", 4) == 0
+ || strncasecmp(codec, "mpg4", 4) == 0) {
+ int result = 0;
+ int i;
+
+ for(i = 0; i < size - 5; i++)
+ {
+ if( data[i] == 0x00 && data[i + 1] == 0x00 &&
+ data[i + 2] == 0x01 && data[i + 3] == 0xb6) {
+
+ if((data[i + 4] & 0xc0) == 0x0) return 1;
+ else return 0;
+ }
+ }
+
+ return result;
+
+ }
+
+ // mjpeg, uncompressed, etc
+ return 1;
+
+}
+
+
+int main(int argc, char *argv[])
+{
+
+ avi_t *avifile1=NULL;
+
+ char *in_file=NULL, *out_file=NULL;
+
+ long frames;
+
+ double fps;
+
+ int track_num=0, aud_tracks;
+
+ int ret;
+ long i=0, chunk=0;
+
+ int ch;
+ int progress=0, old_progress=0;
+
+ long rate;
+ int format, chan, bits;
+ int aud_bitrate = 0;
+
+ FILE *out_fd = NULL;
+ int open_without_index=0,index_keyframes=0;
+ int force_with_index=0;
+
+ double vid_ms = 0.0, print_ms = 0.0;
+ double aud_ms [ AVI_MAX_TRACKS ];
+ char tag[8];
+ char *data;
+ int vid_chunks=0, aud_chunks[AVI_MAX_TRACKS];
+ off_t pos, len, key=0, index_pos=0, index_len=0,size=0;
+ struct stat st;
+ char *codec;
+ int idx_type=0;
+ off_t ioff;
+ char fcclen[8]; // FOURCC + len
+
+ ftype_t ftype;
+ FILE *idxfile;
+
+ ac_init(AC_ALL);
+
+ if(argc==1) usage(EXIT_FAILURE);
+
+ for (i=0; i<AVI_MAX_TRACKS; i++) {
+ aud_chunks[i] = 0;
+ aud_ms[i] = 0;
+ }
+
+ while ((ch = getopt(argc, argv, "a:vi:o:nxf?h")) != -1)
+ {
+
+ switch (ch) {
+
+ case 'i':
+
+ if(optarg[0]=='-') usage(EXIT_FAILURE);
+ in_file=optarg;
+
+ break;
+
+ case 'a':
+
+ if(optarg[0]=='-') usage(EXIT_FAILURE);
+ track_num = atoi(optarg);
+
+ if(track_num<0) usage(EXIT_FAILURE);
+
+ break;
+
+ case 'o':
+
+ if(optarg[0]=='-') usage(EXIT_FAILURE);
+ out_file=optarg;
+
+ break;
+
+ case 'n':
+
+ open_without_index=1;
+
+ break;
+
+ case 'x':
+
+ open_without_index=1;
+ index_keyframes=1;
+
+ break;
+
+ case 'f':
+ force_with_index=1;
+ break;
+
+ case 'v':
+ version();
+ exit(0);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ default:
+ usage(EXIT_FAILURE);
+ }
+ }
+
+ // check
+ if(in_file==NULL) usage(EXIT_FAILURE);
+ if (!out_file) out_fd = stdout;
+ else out_fd = fopen(out_file, "w+r");
+
+ if (!out_fd) {
+ perror("ERROR cannot open outputfile");
+ exit(1);
+ }
+
+ idxfile = fopen(in_file, "r");
+ fread (fcclen, 8, 1, idxfile);
+ if (strncasecmp(fcclen, "RIFF", 4) == 0) ftype = RIFF;
+ else if (strncasecmp(fcclen, "AVIIDX1", 7) == 0) ftype = AVIIDX1;
+ else if (strncasecmp(fcclen, "MPIDX1", 6) == 0) ftype = MPIDX1;
+ else ftype = UNKNOWN;
+
+ fclose (idxfile);
+
+ switch (ftype) {
+ case RIFF: fprintf(stderr, "[%s] Seems to be an AVI file.\n", EXE); break;
+ case AVIIDX1: fprintf(stderr, "[%s] Converting a transcode to an mplayer index file.\n", EXE);
+ return aviidx1_to_mpidx1(in_file, out_fd);
+ case MPIDX1: fprintf(stderr, "[%s] Converting an mplayer to a transcode index file.\n", EXE);
+ return mpidx1_to_aviidx1(in_file, out_fd);
+ default: fprintf(stderr, "[%s] Unrecognized format\n", EXE); return (1);
+ }
+
+
+ // if file is larger than 2GB, regen index
+
+ if (stat(in_file, &st)<0) {
+ perror("Stat input file");
+ return 1;
+ }
+
+ size = st.st_size;
+ if (size > (off_t)AVI_MAX_LEN/2)
+ if (!force_with_index) open_without_index = 1;
+
+ if (open_without_index)
+ if (index_keyframes) fprintf(stderr, "[%s] Open \"%s\" without index and don't use index for keyframes info\n",EXE, in_file);
+ else fprintf(stderr, "[%s] Open \"%s\" without index but use index (if any) for keyframes info\n",EXE, in_file);
+ else
+ fprintf(stderr, "[%s] Open \"%s\" with index (fast)\n", EXE, in_file);
+
+ // header. Magic tag is AVIIDX1
+ fprintf(out_fd, "AVIIDX1 # Generated by %s (%s-%s)\n", EXE, PACKAGE, VERSION); // Magic
+ fprintf(out_fd, "TAG TYPE CHUNK CHUNK/TYPE POS LEN KEY MS\n");
+
+ data = malloc (5*1024*1204);
+
+ if (open_without_index) {
+
+ // open file with index.
+ if(NULL == (avifile1 = AVI_open_input_file(in_file,0))) {
+ AVI_print_error("AVI open input file");
+ exit(1);
+ }
+
+ aud_tracks = frames = 0;
+ frames = AVI_video_frames(avifile1);
+ fps = AVI_frame_rate (avifile1);
+ codec = AVI_video_compressor(avifile1);
+
+ aud_tracks = AVI_audio_tracks(avifile1);
+ //printf("frames (%ld), aud_tracks (%d)\n", frames, aud_tracks);
+
+ pos = key = len = (off_t)0;
+ i = 0;
+
+ while ( (ret = AVI_read_data_fast (avifile1, data, &pos, &len, &key, fcclen)) != 0) {
+ int audtr = ret-2;
+
+ /* don't need this and it saves time
+ * */
+ if (audtr>=0 && audtr<=7) {
+ AVI_set_audio_track(avifile1, audtr);
+ format = AVI_audio_format (avifile1);
+ chan = AVI_audio_channels(avifile1);
+ rate = AVI_audio_rate (avifile1);
+ bits = AVI_audio_bits (avifile1);
+ bits = bits==0?16:bits;
+ if (tc_format_ms_supported(format)) {
+
+ aud_bitrate = format==0x1?1:0;
+
+ if (!aud_bitrate && tc_get_audio_header(data, LEN, format, NULL, NULL, &aud_bitrate)<0) {
+ aud_ms[audtr] = vid_ms;
+ } else
+ aud_ms[audtr] += (len*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0):aud_bitrate);
+ }
+ }
+
+ switch (ret) {
+ case 1: ac_memcpy(tag, fcclen, 4);
+ print_ms = vid_ms = (avifile1->video_pos)*1000.0/fps;
+ chunk = avifile1->video_pos;
+ key = is_key(data, len, codec);
+ break;
+ case 2: case 3:
+ case 4: case 5:
+ case 6: case 7:
+ case 8:
+ case 9: ac_memcpy(tag, fcclen, 4);
+ print_ms = aud_ms[audtr];
+ chunk = avifile1->track[audtr].audio_posc;
+ break;
+ case 10: tc_snprintf(tag, sizeof(tag), "idx1");
+ index_pos = pos;
+ index_len = len;
+ print_ms = 0.0;
+ chunk = 0;
+ break;
+
+ case 0:
+ default:
+ // never get here
+ break;
+ }
+
+
+ //if (index_pos != pos)
+ // tag, chunk_nr
+ fprintf(out_fd, "%.4s %d %ld %ld %lld %lld %lld %.2f\n",
+ tag, ret, i, chunk-1,
+ (long long)pos, (long long)len, (long long)key,
+ print_ms);
+ i++;
+
+ // don't update the counter every chunk
+ progress = (int)(pos*100/size)+1;
+ if (old_progress != progress) {
+ fprintf(stderr, "[%s] Scanning ... %d%%\r", EXE, progress);
+ old_progress = progress;
+ }
+
+ }
+ fprintf(stderr, "\n");
+
+ // check if we have found an index chunk to restore keyframe info
+ if (!index_pos || !index_len || index_keyframes)
+ goto aviout;
+
+ fprintf(stderr, "[%s] Found an index chunk. Using it to regenerate keyframe info.\n", EXE);
+ fseek (out_fd, 0, SEEK_SET);
+
+ fgets(data, 100, out_fd); // magic
+ fgets(data, 100, out_fd); // comment
+
+ len = (off_t)0;
+ vid_chunks = 0;
+
+ xio_lseek(avifile1->fdes, index_pos+8, SEEK_SET);
+ while (len<index_len) {
+ xio_read(avifile1->fdes, tag, 8);
+
+ // if its a keyframe and is a video chunk
+ if (str2ulong(tag+4) && tag[1] == '0') {
+ int typen, keyn;
+ long chunkn, chunkptypen;
+ long long posn, lenn;
+ char tagn[5];
+ double msn=0.0;
+
+ chunk = (long)(len/16);
+ i = 0;
+ //fprintf(stderr, "keyframe in chunk %ld\n", chunk);
+
+ // find line "chunk" in the logfile
+
+ while (i<chunk-vid_chunks) {
+ fgets(data, 100, out_fd);
+ i++;
+ }
+
+ vid_chunks += (chunk-vid_chunks);
+ posn = ftell(out_fd);
+ fgets(data, 100, out_fd);
+ fseek(out_fd, posn, SEEK_SET);
+ sscanf(data, "%s %d %ld %ld %lld %lld %d %lf",
+ tagn, &typen, &chunkn, &chunkptypen, &posn, &lenn, &keyn, &msn);
+ fprintf(out_fd, "%s %d %ld %ld %lld %lld %d %.2f",
+ tagn, typen, chunkn, chunkptypen, posn, lenn, 1, msn);
+ }
+
+ xio_lseek(avifile1->fdes, 8, SEEK_CUR);
+ len += 16;
+ }
+
+
+
+ } else { // with index
+
+ // open file with index.
+ if(NULL == (avifile1 = AVI_open_input_file(in_file,1))) {
+ AVI_print_error("AVI open input file");
+ exit(1);
+ }
+ i=0;
+
+ AVI_info(avifile1);
+
+ // idx1 contains only info for first chunk of opendml AVI
+ if(avifile1->idx && !avifile1->is_opendml)
+ {
+ off_t pos, len;
+
+ /* Search the first videoframe in the idx1 and look where
+ it is in the file */
+
+ for(i=0;i<avifile1->n_idx;i++)
+ if( strncasecmp(avifile1->idx[i],avifile1->video_tag,3)==0 ) break;
+
+ pos = str2ulong(avifile1->idx[i]+ 8);
+ len = str2ulong(avifile1->idx[i]+12);
+
+ xio_lseek(avifile1->fdes,pos,SEEK_SET);
+ if(xio_read(avifile1->fdes,data,8)!=8) return 1;
+ if( strncasecmp(data,avifile1->idx[i],4)==0 && str2ulong(data+4)==len )
+ {
+ idx_type = 1; /* Index from start of file */
+ }
+ else
+ {
+ xio_lseek(avifile1->fdes,pos+avifile1->movi_start-4,SEEK_SET);
+ if(xio_read(avifile1->fdes,data,8)!=8) return 1;
+ if( strncasecmp(data,avifile1->idx[i],4)==0 && str2ulong(data+4)==len )
+ {
+ idx_type = 2; /* Index from start of movi list */
+ }
+ }
+ /* idx_type remains 0 if neither of the two tests above succeeds */
+
+
+ ioff = idx_type == 1 ? 0 : avifile1->movi_start-4;
+ //fprintf(stderr, "index type (%d), ioff (%ld)\n", idx_type, (long)ioff);
+ i=0;
+
+ //printf("nr idx: %d\n", avifile1->n_idx);
+ while (i<avifile1->n_idx) {
+ ac_memcpy(tag, avifile1->idx[i], 4);
+ // tag
+ fprintf(out_fd, "%c%c%c%c",
+ avifile1->idx[i][0], avifile1->idx[i][1],
+ avifile1->idx[i][2], avifile1->idx[i][3]);
+
+ // type, absolute chunk number
+ fprintf(out_fd, " %c %ld", avifile1->idx[i][1]+1, i);
+
+
+ switch (avifile1->idx[i][1]) {
+ case '0':
+ fprintf(out_fd, " %d", vid_chunks);
+ vid_chunks++;
+ break;
+ case '1': case '2':
+ case '3': case '4':
+ case '5': case '6':
+ case '7': case '8':
+ // uhoh
+ ret = avifile1->idx[i][1]-'0';
+ fprintf(out_fd, " %d", aud_chunks[ret]);
+ aud_chunks[ret]++;
+ break;
+ default:
+ fprintf(out_fd, " %d", -1);
+ break;
+ }
+
+ pos = str2ulong(avifile1->idx[i]+ 8);
+ pos += ioff;
+ // pos
+ fprintf(out_fd, " %llu", (unsigned long long)pos);
+ // len
+ fprintf(out_fd, " %lu", str2ulong(avifile1->idx[i]+12));
+ // flags (keyframe?);
+ fprintf(out_fd, " %d", (str2ulong(avifile1->idx[i]+ 4))?1:0);
+
+ // ms (not available here)
+ fprintf(out_fd, " %.2f", 0.0);
+
+ fprintf(out_fd, "\n");
+
+ i++;
+ }
+ }
+
+ else
+ { // try to extract from the index that AVILIB built,
+ // possibly from OpenDML superindex
+
+ long aud_entry [ AVI_MAX_TRACKS ] = { 0 };
+ long vid_entry = 0;
+ char* tagp;
+
+ off_t pos, len = 0;
+ i = chunk = 0;
+
+
+ while (1) {
+ ret = pos = 0;
+ int j = 0;
+
+ if(vid_entry < avifile1->video_frames) {
+ pos = avifile1->video_index[vid_entry].pos;
+ len = avifile1->video_index[vid_entry].len;
+ key = (avifile1->video_index[vid_entry].key) & 16 ? 1 : 0;
+ chunk = vid_entry;
+ ret = 1;
+ }
+ for(j = 0; j < AVI_audio_tracks(avifile1); ++j) {
+ if(aud_entry[j] < avifile1->track[j].audio_chunks) {
+ if(!ret || avifile1->track[j].audio_index[aud_entry[j]].pos < pos) {
+ pos = avifile1->track[j].audio_index[aud_entry[j]].pos;
+ len = avifile1->track[j].audio_index[aud_entry[j]].len;
+ key = 0;
+ chunk = aud_entry[j];
+ ret = j + 2;
+ }
+ }
+ }
+
+ if(!ret) // end of all index streams
+ break;
+
+ if (ret == 1)
+ {
+ ++vid_entry;
+ tagp = avifile1->video_tag;
+ }
+ else
+ {
+ aud_entry[ret-2]++;
+ tagp = avifile1->track[ret-2].audio_tag;
+ }
+
+ // index points to data in chunk, but chunk offset is needed here
+ pos -= 8;
+ fprintf(out_fd, "%.4s %d %ld %ld %lld %lld %lld %.2f\n",
+ tagp, ret, i, chunk,
+ (long long)pos, (long long)len, (long long)key,
+ 0.0);
+ i++;
+
+ }
+
+ }
+
+ }
+
+
+aviout:
+ free(data);
+ if (out_fd!=stdout) fclose (out_fd);
+ AVI_close(avifile1);
+
+ return(0);
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */