diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/tools/aviindex.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/tools/aviindex.c | 914 |
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: + */ |
