⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avilib.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  avilib.c * *  Copyright (C) Thomas 謘treich - June 2001 *  multiple audio track support Copyright (C) 2002 Thomas 謘treich  * *  Original code: *  Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>  * *  This file is part of transcode, a linux video stream processing tool *       *  transcode is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser 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 Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/avilib.h>#ifndef GPAC_READ_ONLY#define PACKAGE "GPAC/avilib"#define VERSION GPAC_VERSION#define INFO_LIST// add a new riff chunk after XX MB//#define NEW_RIFF_THRES (1900*1024*1024)#define NEW_RIFF_THRES (1900*1024*1024)//#define NEW_RIFF_THRES (10*1024*1024)// Maximum number of indices per stream#define NR_IXNN_CHUNKS 32#define DEBUG_ODML#undef DEBUG_ODML/* The following variable indicates the kind of error */long AVI_errno = 0;#define MAX_INFO_STRLEN 64static char id_str[MAX_INFO_STRLEN];#define FRAME_RATE_SCALE 1000000/******************************************************************* *                                                                 * *    Utilities for writing an AVI File                            * *                                                                 * *******************************************************************/static u32 avi_read(FILE *fd, char *buf, u32 len){   u32 n = 0;   u32 r = 0;   while (r < len) {      n = fread(buf + r, 1, len - r, fd);      if (n == 0) break;      if (n < 0) return r;      r += n;   }   return r;}static u32 avi_write (FILE *fd, char *buf, u32 len){   u32 n = 0;   u32 r = 0;   while (r < len) {      n = fwrite (buf + r, 1, len - r, fd);      if (n < 0)         return n;            r += n;   }   return r;}/* HEADERBYTES: The number of bytes to reserve for the header */#define HEADERBYTES 2048/* AVI_MAX_LEN: The maximum length of an AVI file, we stay a bit below    the 2GB limit (Remember: 2*10^9 is smaller than 2 GB) */#define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-HEADERBYTES)#define PAD_EVEN(x) ( ((x)+1) & ~1 )/* Copy n into dst as a 4 or 2 byte, little endian number.   Should also work on big endian machines */static void long2str(unsigned char *dst, s32 n){   dst[0] = (n    )&0xff;   dst[1] = (n>> 8)&0xff;   dst[2] = (n>>16)&0xff;   dst[3] = (n>>24)&0xff;}#ifdef WORDS_BIGENDIANstatic void short2str(unsigned char *dst, s32 n){   dst[0] = (n    )&0xff;   dst[1] = (n>> 8)&0xff;}#endif/* Convert a string of 4 or 2 bytes to a number,   also working on big endian machines */static u64 str2ullong(unsigned char *str){   u64 r = (str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24));   u64 s = (str[4] | (str[5]<<8) | (str[6]<<16) | (str[7]<<24));#ifdef __GNUC__   return ((s<<32)&0xffffffff00000000ULL)|(r&0xffffffff);#else   return ((s<<32)&0xffffffff00000000)|(r&0xffffffff);#endif}static u32 str2ulong(unsigned char *str){   return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );}static u32 str2ushort(unsigned char *str){   return ( str[0] | (str[1]<<8) );}// bit 31 denotes a keyframestatic u32 str2ulong_len (unsigned char *str){   return str2ulong(str) & 0x7fffffff;}// if bit 31 is 0, its a keyframestatic u32 str2ulong_key (unsigned char *str){  u32 c = str2ulong(str);  c &= 0x80000000;  if (c == 0) return 0x10;  else return 0;}/* Calculate audio sample size from number of bits and number of channels.   This may have to be adjusted for eg. 12 bits and stereo */static int avi_sampsize(avi_t *AVI, int j){   int s;   s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans;   //   if(s==0) s=1; /* avoid possible zero divisions */   if(s<4) s=4; /* avoid possible zero divisions */    return s;}/* Add a chunk (=tag and data) to the AVI file,   returns -1 on write error, 0 on success */static int avi_add_chunk(avi_t *AVI, unsigned char *tag, unsigned char *data, u32 length){   unsigned char c[8];   char p=0;      /* Copy tag and length int c, so that we need only 1 write system call      for these two values */   memcpy(c,tag,4);   long2str(c+4,length);   /* Output tag, length and data, restore previous position      if the write fails */   if( avi_write(AVI->fdes,(char *)c,8) != 8 ||       avi_write(AVI->fdes,(char *)data,length) != length ||       avi_write(AVI->fdes,&p,length&1) != (length&1)) // if len is uneven, write a pad byte   {      gf_f64_seek(AVI->fdes,AVI->pos,SEEK_SET);      AVI_errno = AVI_ERR_WRITE;      return -1;   }   /* Update file position */   AVI->pos += 8 + PAD_EVEN(length);   //GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] pos=%lu %s\n", AVI->pos, tag));   return 0;}#define OUTD(n) long2str((unsigned char*) (ix00+bl),(s32)n); bl+=4#define OUTW(n) ix00[bl] = (n)&0xff; ix00[bl+1] = (n>>8)&0xff; bl+=2#define OUTC(n) ix00[bl] = (n)&0xff; bl+=1#define OUTS(s) memcpy(ix00+bl,s,4); bl+=4// this does the physical writeout of the ix## structurestatic int avi_ixnn_entry(avi_t *AVI, avistdindex_chunk *ch, avisuperindex_entry *en) {    int bl;	u32 k;    unsigned int max = ch->nEntriesInUse * sizeof (u32) * ch->wLongsPerEntry + 24; // header    char *ix00 = (char *)malloc (max);    char dfcc[5];    memcpy (dfcc, ch->fcc, 4);    dfcc[4] = 0;    bl = 0;    if (en) {	en->qwOffset = AVI->pos;	en->dwSize = max;	//en->dwDuration = ch->nEntriesInUse -1; // NUMBER OF stream ticks == frames for video/samples for audio    }#ifdef DEBUG_ODML    //GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML Write %s: Entries %ld size %d \n", dfcc, ch->nEntriesInUse, max));#endif    //OUTS(ch->fcc);    //OUTD(max);    OUTW(ch->wLongsPerEntry);    OUTC(ch->bIndexSubType);    OUTC(ch->bIndexType);    OUTD(ch->nEntriesInUse);    OUTS(ch->dwChunkId);    OUTD(ch->qwBaseOffset&0xffffffff);    OUTD((ch->qwBaseOffset>>32)&0xffffffff);    OUTD(ch->dwReserved3);    for (k = 0; k < ch->nEntriesInUse; k++) {	OUTD(ch->aIndex[k].dwOffset);	OUTD(ch->aIndex[k].dwSize);    }    avi_add_chunk (AVI, (unsigned char*)ch->fcc, (unsigned char*)ix00, max);    free(ix00);    return 0;}#undef OUTS#undef OUTW#undef OUTD#undef OUTC// inits a super index structure including its enclosed stdindexstatic int avi_init_super_index(avi_t *AVI, unsigned char *idxtag, avisuperindex_chunk **si){    int k;    avisuperindex_chunk *sil = NULL;    if ((sil = (avisuperindex_chunk *) malloc (sizeof (avisuperindex_chunk))) == NULL) {	AVI_errno = AVI_ERR_NO_MEM;	return -1;    }    memcpy (sil->fcc, "indx", 4);    sil->dwSize = 0; // size of this chunk    sil->wLongsPerEntry = 4;    sil->bIndexSubType = 0;    sil->bIndexType = AVI_INDEX_OF_INDEXES;    sil->nEntriesInUse = 0; // none are in use    memcpy (sil->dwChunkId, idxtag, 4);    memset (sil->dwReserved, 0, sizeof (sil->dwReserved));    // NR_IXNN_CHUNKS == allow 32 indices which means 32 GB files -- arbitrary    sil->aIndex = (avisuperindex_entry *) malloc (sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (void*));    if (!sil->aIndex) {	AVI_errno = AVI_ERR_NO_MEM;	return -1;    }    memset (sil->aIndex, 0, sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (u32));    sil->stdindex = (avistdindex_chunk **)malloc (NR_IXNN_CHUNKS * sizeof (avistdindex_chunk *));    if (!sil->stdindex) {	AVI_errno = AVI_ERR_NO_MEM;	return -1;    }    for (k = 0; k < NR_IXNN_CHUNKS; k++) {	sil->stdindex[k] = (avistdindex_chunk *) malloc (sizeof (avistdindex_chunk));	// gets rewritten later	sil->stdindex[k]->qwBaseOffset = (u64)k * NEW_RIFF_THRES;	sil->stdindex[k]->aIndex = NULL;    }    *si = sil;    return 0;}// fills an alloc'ed stdindex structure and mallocs some entries for the actual chunksstatic int avi_add_std_index(avi_t *AVI, unsigned char *idxtag, unsigned char *strtag,	avistdindex_chunk *stdil){    memcpy (stdil->fcc, idxtag, 4);     stdil->dwSize = 4096;    stdil->wLongsPerEntry = 2; //sizeof(avistdindex_entry)/sizeof(u32);    stdil->bIndexSubType = 0;    stdil->bIndexType = AVI_INDEX_OF_CHUNKS;    stdil->nEntriesInUse = 0;    // cp 00db ChunkId    memcpy(stdil->dwChunkId, strtag, 4);    //stdil->qwBaseOffset = AVI->video_superindex->aIndex[ cur_std_idx ]->qwOffset;    stdil->aIndex = (avistdindex_entry *)malloc(stdil->dwSize * sizeof (u32) * stdil->wLongsPerEntry);    if (!stdil->aIndex) {	AVI_errno = AVI_ERR_NO_MEM;	return -1;    }    return 0;}static int avi_add_odml_index_entry_core(avi_t *AVI, long flags, u64 pos, unsigned long len, avistdindex_chunk *si) {    u32 cur_chunk_idx;    // put new chunk into index    si->nEntriesInUse++;    cur_chunk_idx = si->nEntriesInUse-1;    // need to fetch more memory    if (cur_chunk_idx >= si->dwSize) {	si->dwSize += 4096;	si->aIndex = (avistdindex_entry *)realloc ( si->aIndex, si->dwSize * sizeof (u32) * si->wLongsPerEntry);    }    if(len>AVI->max_len) AVI->max_len=len;    // if bit 31 is set, it is NOT a keyframe    if (flags != 0x10) {	len |= 0x80000000;    }    si->aIndex [ cur_chunk_idx ].dwSize = len;    si->aIndex [ cur_chunk_idx ].dwOffset = (u32) (pos - si->qwBaseOffset + 8);    //GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML: POS: 0x%lX\n", si->aIndex [ cur_chunk_idx ].dwOffset));    return 0;}static int avi_add_odml_index_entry(avi_t *AVI, unsigned char *tag, long flags, u64 pos, unsigned long len) {    char fcc[5];    int audio = (strchr ((char*)tag, 'w')?1:0);    int video = !audio;    unsigned int cur_std_idx;    u32 audtr;    s64 towrite = 0;    if (video) {	if (!AVI->video_superindex) {	    if (avi_init_super_index(AVI, (unsigned char *)"ix00", &AVI->video_superindex) < 0) return -1;             AVI->video_superindex->nEntriesInUse++;	    cur_std_idx = AVI->video_superindex->nEntriesInUse-1;	    if (avi_add_std_index (AVI, (unsigned char *)"ix00", (unsigned char *)"00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) 		return -1;	} // init    } // video    if (audio) {	fcc[0] = 'i'; fcc[1] = 'x'; fcc[2] = tag[0]; fcc[3] = tag[1]; fcc[4] = '\0';	if (!AVI->track[AVI->aptr].audio_superindex) {#ifdef DEBUG_ODML	    GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML: fcc = %s\n", fcc));#endif	    if (avi_init_super_index(AVI, (unsigned char *)fcc, &AVI->track[AVI->aptr].audio_superindex) < 0) return -1;	    AVI->track[AVI->aptr].audio_superindex->nEntriesInUse++;	    sprintf(fcc, "ix%02d", AVI->aptr+1);	    if (avi_add_std_index (AVI, (unsigned char *)fcc, tag, AVI->track[AVI->aptr].audio_superindex->stdindex[ 			AVI->track[AVI->aptr].audio_superindex->nEntriesInUse - 1 ]) < 0	       ) return -1;	} // init    }    towrite = 0;    if (AVI->video_superindex) {	cur_std_idx = AVI->video_superindex->nEntriesInUse-1;	towrite += AVI->video_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 	    + 4+4+2+1+1+4+4+8+4;	if (cur_std_idx == 0) {	    towrite += AVI->n_idx*16 + 8;	    towrite += HEADERBYTES;	}    }    for (audtr=0; audtr<AVI->anum; audtr++) {	if (AVI->track[audtr].audio_superindex) {	    cur_std_idx = AVI->track[audtr].audio_superindex->nEntriesInUse-1;	    towrite += AVI->track[audtr].audio_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -