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

📄 avilib.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:
   OUTLONG(0);             /* Frame */
   OUTLONG(0);             /* Frame */
   OUTLONG(0);             /* Frame */

   /* The audio stream format */

   OUT4CC ("strf");
   OUTLONG(16);                   /* # of bytes to follow */
   OUTSHRT(AVI->a_fmt);           /* Format */
   OUTSHRT(AVI->a_chans);         /* Number of channels */
   OUTLONG(AVI->a_rate);          /* SamplesPerSec */
   OUTLONG(sampsize*AVI->a_rate); /* AvgBytesPerSec */
   OUTSHRT(sampsize);             /* BlockAlign */
   OUTSHRT(AVI->a_bits);          /* BitsPerSample */

   /* 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);

   /* 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 _WINDOWS
        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)
{
   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,"00db",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,"00db",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;

   return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx));
}

/*******************************************************************
 *                                                                 *
 *    Utilities for reading video and audio from an AVI File       *
 *                                                                 *
 *******************************************************************/

int AVI_close(avi_t *AVI)
{
   int ret;

   /* If the file was open for writing, the header and index still have
      to be written */

   if(AVI->mode == AVI_MODE_WRITE)
      ret = avi_close_output_file(AVI);
   else
      ret = 0;

   /* Even if there happened a error, we first clean up */

   close(AVI->fdes);
   if(AVI->idx) free(AVI->idx);
   if(AVI->video_index) free(AVI->video_index);
   if(AVI->audio_index) free(AVI->audio_index);
   free(AVI);

   return ret;
}


#define ERR_EXIT(x) \
{ \
   AVI_close(AVI); \
   AVI_errno = x; \
   return 0; \
}

avi_t *AVI_open_input_file(const char *filename, int getIndex)
{
   avi_t *AVI;
   long i, n, rate, scale, idx_type;
   unsigned char *hdrl_data;
   long hdrl_len;
   long nvi, nai, ioff;
   long tot;
   int lasttag = 0;
   int vids_strh_seen = 0;
   int vids_strf_seen = 0;
   int auds_strh_seen = 0;
   int auds_strf_seen = 0;
   int num_stream = 0;
   char data[256];

   /* Create avi_t structure */

   AVI = (avi_t *) malloc(sizeof(avi_t));
   if(AVI==NULL)
   {
      AVI_errno = AVI_ERR_NO_MEM;
      return 0;
   }
   memset((void *)AVI,0,sizeof(avi_t));

   AVI->mode = AVI_MODE_READ; /* open for reading */

   /* Open the file */

   AVI->fdes = open(filename,OPEN_RDONLY);
   if(AVI->fdes < 0)
   {
      AVI_errno = AVI_ERR_OPEN;
      free(AVI);
      return 0;
   }

   /* Read first 12 bytes and check that this is an AVI file */

   if( read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ)

   if( strncasecmp(data  ,"RIFF",4) !=0 ||
       strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI)

   /* Go through the AVI file and extract the header list,
      the start position of the 'movi' list and an optionally
      present idx1 tag */

   hdrl_data = 0;

   while(1)
   {
      if( read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */

      n = str2ulong(data+4);
      n = PAD_EVEN(n);

      if(strncasecmp(data,"LIST",4) == 0)
      {
         if( read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ)
         n -= 4;
         if(strncasecmp(data,"hdrl",4) == 0)
         {
            hdrl_len = n;
            hdrl_data = (unsigned char *) malloc(n);
            if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM)
            if( read(AVI->fdes,hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ)
         }
         else if(strncasecmp(data,"movi",4) == 0)
         {
            AVI->movi_start = lseek(AVI->fdes,0,SEEK_CUR);
            lseek(AVI->fdes,n,SEEK_CUR);
         }
         else
            lseek(AVI->fdes,n,SEEK_CUR);
      }
      else if(strncasecmp(data,"idx1",4) == 0)
      {
         /* n must be a multiple of 16, but the reading does not
            break if this is not the case */

         AVI->n_idx = AVI->max_idx = n/16;
         AVI->idx = (unsigned  char((*)[16]) ) malloc(n);
         if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM)
         if( read(AVI->fdes,AVI->idx,n) != n ) ERR_EXIT(AVI_ERR_READ)
      }
      else
         lseek(AVI->fdes,n,SEEK_CUR);
   }

   if(!hdrl_data      ) ERR_EXIT(AVI_ERR_NO_HDRL)
   if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI)

   /* Interpret the header list */

   for(i=0;i<hdrl_len;)
   {
      /* List tags are completly ignored */

      if(strncasecmp(hdrl_data+i,"LIST",4)==0) { i+= 12; continue; }

      n = str2ulong(hdrl_data+i+4);
      n = PAD_EVEN(n);

      /* Interpret the tag and its args */

      if(strncasecmp(hdrl_data+i,"strh",4)==0)
      {
         i += 8;
         if(strncasecmp(hdrl_data+i,"vids",4) == 0 && !vids_strh_seen)
         {
            memcpy(AVI->compressor,hdrl_data+i+4,4);
            AVI->compressor[4] = 0;
            scale = str2ulong(hdrl_data+i+20);
            rate  = str2ulong(hdrl_data+i+24);
            if(scale!=0) AVI->fps = (double)rate/(double)scale;
            AVI->video_frames = str2ulong(hdrl_data+i+32);
            AVI->video_strn = num_stream;
            vids_strh_seen = 1;
            lasttag = 1; /* vids */
         }
         else if (strncasecmp (hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen)
         {
            AVI->audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI);
            AVI->audio_strn = num_stream;
            auds_strh_seen = 1;
            lasttag = 2; /* auds */
         }
         else
            lasttag = 0;
         num_stream++;
      }
      else if(strncasecmp(hdrl_data+i,"strf",4)==0)
      {
         i += 8;
         if(lasttag == 1)
         {
            AVI->width  = str2ulong(hdrl_data+i+4);
            AVI->height = str2ulong(hdrl_data+i+8);
            vids_strf_seen = 1;
         }
         else if(lasttag == 2)
         {
            AVI->a_fmt   = str2ushort(hdrl_data+i  );
            AVI->a_chans = str2ushort(hdrl_data+i+2);
            AVI->a_rate  = str2ulong (hdrl_data+i+4);
            AVI->a_bits  = str2ushort(hdrl_data+i+14);
            auds_strf_seen = 1;
         }
         lasttag = 0;
      }
      else
      {
         i += 8;
         lasttag = 0;
      }

      i += n;
   }

   free(hdrl_data);

   if(!vids_strh_seen || !vids_strf_seen || AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS)

   AVI->video_tag[0] = AVI->video_strn/10 + '0';
   AVI->video_tag[1] = AVI->video_strn%10 + '0';
   AVI->video_tag[2] = 'd';
   AVI->video_tag[3] = 'b';

   /* Audio tag is set to "99wb" if no audio present */
   if(!AVI->a_chans) AVI->audio_strn = 99;

   AVI->audio_tag[0] = AVI->audio_strn/10 + '0';
   AVI->audio_tag[1] = AVI->audio_strn%10 + '0';
   AVI->audio_tag[2] = 'w';
   AVI->audio_tag[3] = 'b';

   lseek(AVI->fdes,AVI->movi_start,SEEK_SET);

   /* get index if wanted */

   if(!getIndex) return AVI;

   /* if the file has an idx1, check if this is relative
      to the start of the file or to the start of the movi list */

   idx_type = 0;

   if(AVI->idx)
   {
      long pos;
		unsigned long len;

      /* Search the first videoframe in the idx1 and look where
         it is in the file */

      for(i=0;i<AVI->n_idx;i++)
         if( strncasecmp(AVI->idx[i],AVI->video_tag,3)==0 ) break;
      if(i>=AVI->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS)

      pos = str2ulong(AVI->idx[i]+ 8);
      len = str2ulong(AVI->idx[i]+12);

      lseek(AVI->fdes,pos,SEEK_SET);
      if(read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ)
      if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len )
      {
         idx_type = 1; /* Index from start of file */
      }
      else
      {
         lseek(AVI->fdes,pos+AVI->movi_start-4,SEEK_SET);
         if(read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ)
         if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len )
         {
            idx_type = 2; /* Index from start of movi list */
         }

⌨️ 快捷键说明

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