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

📄 avilib.c

📁 这是将avs视频的ES流转换成avi文件格式的源代码
💻 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 "mpeg4ip.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_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 */

//   printf("entery the aviopenoutputfile!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");   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 | _O_BINARY);   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 */


   printf("open end !!!!!!\n");   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 samplepersec, 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/8;
   AVI->a_samplepersec  = samplepersec;   AVI->a_bits  = bits;   AVI->a_fmt   = format;

   AVI->a_cbsize   = 12; //MPEGLAYER3_WFX_EXTRA_BYTES   12
  
   AVI->a_wID = 1;			//MPEGLAYER3_ID_MPEG  ==1
   ////#define MPEGLAYER3_FLAG_PADDING_OFF      0x00000002
   AVI->a_fdwFlags = 2;		// These values based on an old Usenet post!!
   AVI->a_nBlockSize = 731;	//AVI->a_nBlockSize = 576;	// this value COMPUTE later...
   AVI->a_nFramesPerBlock = 1;	//
   AVI->a_nCodecDelay = 0;	// AVI->a_nCodecDelay = 1393;	// 0x571 for F-IIS MP3 Codec}#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;
   long ntime;

   //return 0;   /* 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 */
   ntime=1000*AVI->video_frames/AVI->fps;
   if(AVI->fps < 0.001)      ms_per_frame = 0;   else
	    ms_per_frame = 1000000./AVI->fps + 0.5;
printf("ms_per_frame==%d\n",ms_per_frame);   /* 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 现在还不知道它的长度,在后面通过   long2str(AVI_header+hdrl_start-4,nhb-hdrl_start);设置长度   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);// OUTLONG(1244160);//OUTLONG(10000000);           /* MaxBytesPerSec, I hope this will never be used */   OUTLONG(0);  //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 *///////




   printf("AVI->video_frames==%d\n",AVI->video_frames);
   OUTLONG(0);                  /* InitialFrames */   if (AVI->audio_bytes)   { 
	   OUTLONG(2); 
   }           /* Streams */   else   { 
	   OUTLONG(1); 
   }           /* Streams */   OUTLONG(0); //OUTLONG(10000); // OUTLONG(0);                  /* SuggestedBufferSize *///!!!!!!   OUTLONG(AVI->width);         /* Width */   OUTLONG(AVI->height);        /* Height */                                /* MS calls the following 'reserved': */   OUTLONG(ms_per_frame); //OUTLONG(ms_per_frame);      /* 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 ,现在还不知道它的长度,在后面通过   long2str(AVI_header+hdrl_start-4,nhb-hdrl_start);设置长度   strl_start = nhb;  /// Store start position    OUT4CC ("strl");   /// The video stream header    OUT4CC ("strh");   OUTLONG(56);                 // # 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(ms_per_frame*AVI->fps);//OUTLONG(AVI->width*AVI->height);// OUTLONG(AVI->width*AVI->height/ms_per_frame);/// Rate: Rate/Scale == samples/second 每秒多少个象素点
  // printf("AVI->width*AVI->height/ms_per_frame==%d\n",AVI->width*AVI->height/ms_per_frame);   OUTLONG(0);                  /// Start 


     OUTLONG(AVI->video_frames);  /// Length 
   OUTLONG(1000000);                  /// SuggestedBufferSize    OUTLONG(-1);                 /// Quality    OUTLONG(0);                  /// SampleSize 
   OUTLONG(0);
   OUTSHRT(0);
   OUTSHRT(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);  //OUTLONG(608256);  ///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");    OUT4CC ("\0\0\0\0");///  OUT4CC ("\0\0\0\0");//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   OUTLONG(0);             /* Flags */   OUTLONG(0);             /* Reserved, MS says: wPriority, wLanguage */   OUTLONG(0);             /* InitialFrames */




   OUTLONG(1); //OUTLONG(ntime); // OUTLONG(1);      /* Scale */
 
   OUTLONG(AVI->a_rate);   //OUTLONG(AVI->a_rate/8); /* Rate: Rate/Scale == samples/second *///!!!!!???????????????

printf("AVI->a_rate==%d\n",AVI->a_rate);




   OUTLONG(0);             /* Start */   OUTLONG(AVI->audio_bytes/sampsize);   /* Length */   OUTLONG(0);             /* SuggestedBufferSize */   OUTLONG(-1); //   OUTLONG(-1);            /* Quality *///!!!!!!!!!!!!!!!!   OUTLONG(sampsize);      /* SampleSize */   OUTLONG(0);             /* Frame */   OUTLONG(0);             /* Frame */   OUTLONG(0);             /* Frame */   OUTLONG(0);             /* Frame */   /* The audio stream format */   OUT4CC ("strf");   OUTLONG(30);                   /* # of bytes to follow */   OUTSHRT(AVI->a_fmt);           /* Format */   OUTSHRT(AVI->a_chans);         /* Number of channels */

   OUTLONG(AVI->a_samplepersec);          /* SamplesPerSec */   OUTLONG(AVI->a_rate);//   OUTLONG(AVI->a_rate/8); /* AvgBytesPerSec */   OUTSHRT(sampsize);             /* BlockAlign */   OUTSHRT(AVI->a_bits);          /* BitsPerSample */
   OUTSHRT(AVI->a_cbsize);

   OUTSHRT(AVI->a_wID);
   OUTLONG(AVI->a_fdwFlags);
   OUTSHRT(AVI->a_nBlockSize);
   OUTSHRT(AVI->a_nFramesPerBlock);
   OUTSHRT(AVI->a_nCodecDelay);   /* Finish stream list, i.e. put number of bytes in the list to proper pos */   long2str(AVI_header+strl_start-4,nhb-strl_start);   }   /* Finish header list */   long2str(AVI_header+hdrl_start-4,nhb-hdrl_start);///设置hdrl的长度   /* Calculate the needed amount of junk bytes, output junk */   njunk = HEADERBYTES - nhb - 8 - 12;   /* Safety first: if njunk <= 0, somebody has played with      HEADERBYTES without knowing what (s)he did.      This is a fatal error */   if(njunk<=0)   {      fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n");      exit(1);   }   OUT4CC ("JUNK");   OUTLONG(njunk);   memset(AVI_header+nhb,0,njunk);   nhb += njunk;   /* Start the movi list */   OUT4CC ("LIST");   OUTLONG(movi_len); /* Length of list in bytes */   OUT4CC ("movi");   /* Output the header, truncate the file to the number of bytes      actually written, report an error if someting goes wrong */   if ( _lseek(AVI->fdes,0,SEEK_SET)<0 ||        _write(AVI->fdes,AVI_header,HEADERBYTES)!=HEADERBYTES ||#ifndef _WIN32        ftruncate(AVI->fdes,AVI->pos)<0#else		_chsize(AVI->fdes,AVI->pos)<0 #endif		)   {      AVI_errno = AVI_ERR_CLOSE;      return -1;   }   if(idxerror) return -1;   return 0;}/*   AVI_write_data:   Add video or audio data to the file;   Return values:    0    No error;   -1    Error, AVI_errno is set appropriatly;*/static int avi_write_data(avi_t *AVI, char *data, long length, int audio)//audio==1 -->audio , audio==0 -->video{   int n;   /* Check for maximum file length */   if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN )   {      AVI_errno = AVI_ERR_SIZELIM;      return -1;   }   /* Add index entry */   if(audio)      n = avi_add_index_entry(AVI,"01wb",0x00,AVI->pos,length);   else      n = avi_add_index_entry(AVI,"00dc",0x10,AVI->pos,length);   if(n) return -1;   /* Output tag and data */   if(audio)      n = avi_add_chunk(AVI,"01wb",data,length);   else      n = avi_add_chunk(AVI,"00dc",data,length);   if (n) return -1;   return 0;}int AVI_write_frame(avi_t *AVI, char *data, long bytes){   long pos;   if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }   pos = AVI->pos;   if( avi_write_data(AVI,data,bytes,0) ) return -1;   AVI->last_pos = pos;   AVI->last_len = bytes;   AVI->video_frames++;   return 0;}int AVI_dup_frame(avi_t *AVI){   if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }   if(AVI->last_pos==0) return 0; /* No previous real frame */   if(avi_add_index_entry(AVI,"00db",0x10,AVI->last_pos,AVI->last_len)) return -1;   AVI->video_frames++;   AVI->must_use_index = 1;   return 0;}int AVI_write_audio(avi_t *AVI, char *data, long bytes){   if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }   if( avi_write_data(AVI,data,bytes,1) ) return -1;   AVI->audio_bytes += bytes;   return 0;}long AVI_bytes_remain(avi_t *AVI){   if(AVI->mode==AVI_MODE_READ) return 0;

⌨️ 快捷键说明

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