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

📄 avilib.c

📁 Simple SunPlus SP54 codec converter and a more playable mode MJPG. untar the archive go to the r
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Some utilities for writing and reading AVI files. *  These are not intended to serve for a full blown *  AVI handling software (this would be much too complex) *  The only intention is to write out MJPEG encoded *  AVIs with sound and to be able to read them back again. *  These utilities should work with other types of codecs too, however. * *  Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de> * *  This program 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 of the License, or *  (at your option) any later version. * *  This program 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 this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "avilib.h"/* The following variable indicates the kind of error */long AVI_errno = 0;/******************************************************************* *                                                                 * *    Utilities for writing an AVI File                            * *                                                                 * *******************************************************************//* 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 2000000000/* HEADERBYTES: The number of bytes to reserve for the header */#define HEADERBYTES 2048#define PAD_EVEN(x) ( ((x)+1) & ~1 )/* Copy n into dst as a 4 byte, little endian number.   Should also work on big endian machines */static void long2str(unsigned char *dst, int n){   dst[0] = (n    )&0xff;   dst[1] = (n>> 8)&0xff;   dst[2] = (n>>16)&0xff;   dst[3] = (n>>24)&0xff;}/* Convert a string of 4 or 2 bytes to a number,   also working on big endian machines */static unsigned long str2ulong(unsigned char *str){   return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );}static unsigned long str2ushort(unsigned char *str){   return ( str[0] | (str[1]<<8) );}/* 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 s;   s = ((AVI->a_bits+7)/8)*AVI->a_chans;   if(s==0) s=1; /* 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, int length){   unsigned char c[8];   /* 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 */   length = PAD_EVEN(length);   if( write(AVI->fdes,c,8) != 8 ||       write(AVI->fdes,data,length) != length )   {      lseek(AVI->fdes,AVI->pos,SEEK_SET);      AVI_errno = AVI_ERR_WRITE;      return -1;   }   /* Update file position */   AVI->pos += 8 + length;   return 0;}static int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, long pos, long len){   void *ptr;   if(AVI->n_idx>=AVI->max_idx)   {      ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16);      if(ptr == 0)      {         AVI_errno = AVI_ERR_NO_MEM;         return -1;      }      AVI->max_idx += 4096;      AVI->idx = (unsigned char((*)[16]) ) ptr;   }   /* Add index entry */   memcpy(AVI->idx[AVI->n_idx],tag,4);   long2str(AVI->idx[AVI->n_idx]+ 4,flags);   long2str(AVI->idx[AVI->n_idx]+ 8,pos);   long2str(AVI->idx[AVI->n_idx]+12,len);   /* Update counter */   AVI->n_idx++;   return 0;}/*   AVI_open_output_file: Open an AVI File and write a bunch                         of zero bytes as space for the header.   returns a pointer to avi_t on success, a zero pointer on error*/avi_t* AVI_open_output_file(char * filename){   avi_t *AVI;   int i;   unsigned char AVI_header[HEADERBYTES];   /* Allocate the avi_t struct and zero it */   AVI = (avi_t *) malloc(sizeof(avi_t));   if(AVI==0)   {      AVI_errno = AVI_ERR_NO_MEM;      return 0;   }   memset((void *)AVI,0,sizeof(avi_t));   /* Since Linux needs a long time when deleting big files,      we do not truncate the file when we open it.      Instead it is truncated when the AVI file is closed */   AVI->fdes = open(filename,O_RDWR|O_CREAT,0600);   if (AVI->fdes < 0)   {      AVI_errno = AVI_ERR_OPEN;      free(AVI);      return 0;   }   /* Write out HEADERBYTES bytes, the header will go here      when we are finished with writing */   for (i=0;i<HEADERBYTES;i++) AVI_header[i] = 0;   i = write(AVI->fdes,AVI_header,HEADERBYTES);   if (i != HEADERBYTES)   {      close(AVI->fdes);      AVI_errno = AVI_ERR_WRITE;      free(AVI);      return 0;   }   AVI->pos  = HEADERBYTES;   AVI->mode = AVI_MODE_WRITE; /* open for writing */   return AVI;}void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor){   /* may only be called if file is open for writing */   if(AVI->mode==AVI_MODE_READ) return;   AVI->width  = width;   AVI->height = height;   AVI->fps    = fps;   memcpy(AVI->compressor,compressor,4);   AVI->compressor[4] = 0;}void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format){   /* may only be called if file is open for writing */   if(AVI->mode==AVI_MODE_READ) return;   AVI->a_chans = channels;   AVI->a_rate  = rate;   AVI->a_bits  = bits;   AVI->a_fmt   = format;}#define OUT4CC(s) \   if(nhb<=HEADERBYTES-4) memcpy(AVI_header+nhb,s,4); nhb += 4#define OUTLONG(n) \   if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb,n); nhb += 4#define OUTSHRT(n) \   if(nhb<=HEADERBYTES-2) { \      AVI_header[nhb  ] = (n   )&0xff; \      AVI_header[nhb+1] = (n>>8)&0xff; \   } \   nhb += 2/*  Write the header of an AVI file and close it.  returns 0 on success, -1 on write error.*/static int avi_close_output_file(avi_t *AVI){   int ret, njunk, sampsize, hasIndex, ms_per_frame, idxerror, flag;   int movi_len, hdrl_start, strl_start;   unsigned char AVI_header[HEADERBYTES];   long nhb;   /* Calculate length of movi list */   movi_len = AVI->pos - HEADERBYTES + 4;   /* Try to ouput the index entries. This may fail e.g. if no space      is left on device. We will report this as an error, but we still      try to write the header correctly (so that the file still may be      readable in the most cases */   idxerror = 0;   ret = avi_add_chunk(AVI,"idx1",(void*)AVI->idx,AVI->n_idx*16);   hasIndex = (ret==0);   if(ret)   {      idxerror = 1;      AVI_errno = AVI_ERR_WRITE_INDEX;   }   /* Calculate Microseconds per frame */   if(AVI->fps < 0.001)      ms_per_frame = 0;   else      ms_per_frame = 1000000./AVI->fps + 0.5;   /* Prepare the file header */   nhb = 0;   /* The RIFF header */   OUT4CC ("RIFF");   OUTLONG(AVI->pos - 8);    /* # of bytes to follow */   OUT4CC ("AVI ");   /* Start the header list */   OUT4CC ("LIST");   OUTLONG(0);        /* Length of list in bytes, don't know yet */   hdrl_start = nhb;  /* Store start position */   OUT4CC ("hdrl");   /* The main AVI header */   /* The Flags in AVI File header */#define AVIF_HASINDEX           0x00000010      /* Index at end of file */#define AVIF_MUSTUSEINDEX       0x00000020#define AVIF_ISINTERLEAVED      0x00000100#define AVIF_TRUSTCKTYPE        0x00000800      /* Use CKType to find key frames */#define AVIF_WASCAPTUREFILE     0x00010000#define AVIF_COPYRIGHTED        0x00020000   OUT4CC ("avih");   OUTLONG(56);                 /* # of bytes to follow */   OUTLONG(ms_per_frame);       /* Microseconds per frame */   OUTLONG(10000000);           /* MaxBytesPerSec, I hope this will never be used */   OUTLONG(0);                  /* PaddingGranularity (whatever that might be) */                                /* Other sources call it 'reserved' */   flag = AVIF_WASCAPTUREFILE;   if(hasIndex) flag |= AVIF_HASINDEX;   if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX;   OUTLONG(flag);               /* Flags */   OUTLONG(AVI->video_frames);  /* TotalFrames */   OUTLONG(0);                  /* InitialFrames */   if (AVI->audio_bytes)      { OUTLONG(2); }           /* Streams */   else      { OUTLONG(1); }           /* Streams */   OUTLONG(0);                  /* SuggestedBufferSize */   OUTLONG(AVI->width);         /* Width */   OUTLONG(AVI->height);        /* Height */                                /* MS calls the following 'reserved': */   OUTLONG(0);                  /* TimeScale:  Unit used to measure time */   OUTLONG(0);                  /* DataRate:   Data rate of playback     */   OUTLONG(0);                  /* StartTime:  Starting time of AVI data */   OUTLONG(0);                  /* DataLength: Size of AVI data chunk    */   /* Start the video stream list ---------------------------------- */   OUT4CC ("LIST");   OUTLONG(0);        /* Length of list in bytes, don't know yet */   strl_start = nhb;  /* Store start position */   OUT4CC ("strl");   /* The video stream header */   OUT4CC ("strh");   OUTLONG(64);                 /* # of bytes to follow */   OUT4CC ("vids");             /* Type */   OUT4CC (AVI->compressor);    /* Handler */   OUTLONG(0);                  /* Flags */   OUTLONG(0);                  /* Reserved, MS says: wPriority, wLanguage */   OUTLONG(0);                  /* InitialFrames */   OUTLONG(ms_per_frame);       /* Scale */   OUTLONG(1000000);            /* Rate: Rate/Scale == samples/second */   OUTLONG(0);                  /* Start */   OUTLONG(AVI->video_frames);  /* Length */   OUTLONG(0);                  /* SuggestedBufferSize */   OUTLONG(-1);                 /* Quality */   OUTLONG(0);                  /* SampleSize */   OUTLONG(0);                  /* Frame */   OUTLONG(0);                  /* Frame */   OUTLONG(0);                  /* Frame */   OUTLONG(0);                  /* Frame */   /* The video stream format */   OUT4CC ("strf");   OUTLONG(40);                 /* # of bytes to follow */   OUTLONG(40);                 /* Size */   OUTLONG(AVI->width);         /* Width */   OUTLONG(AVI->height);        /* Height */   OUTSHRT(1); OUTSHRT(24);     /* Planes, Count */   OUT4CC (AVI->compressor);    /* Compression */   OUTLONG(AVI->width*AVI->height);  /* SizeImage (in bytes?) */   OUTLONG(0);                  /* XPelsPerMeter */   OUTLONG(0);                  /* YPelsPerMeter */   OUTLONG(0);                  /* ClrUsed: Number of colors used */   OUTLONG(0);                  /* ClrImportant: Number of colors important */   /* Finish stream list, i.e. put number of bytes in the list to proper pos */   long2str(AVI_header+strl_start-4,nhb-strl_start);   if (AVI->a_chans && AVI->audio_bytes)   {   sampsize = avi_sampsize(AVI);   /* Start the audio stream list ---------------------------------- */   OUT4CC ("LIST");   OUTLONG(0);        /* Length of list in bytes, don't know yet */   strl_start = nhb;  /* Store start position */   OUT4CC ("strl");   /* The audio stream header */   OUT4CC ("strh");   OUTLONG(64);            /* # of bytes to follow */   OUT4CC ("auds");

⌨️ 快捷键说明

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