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

📄 avilib.c

📁 JPEG-MPEG編解碼技術書集的代碼
💻 C
📖 第 1 页 / 共 3 页
字号:
      }
      /* idx_type remains 0 if neither of the two tests above succeeds */
   }

   if(idx_type == 0)
   {
      /* we must search through the file to get the index */

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

      AVI->n_idx = 0;

      while(1)
      {
         if( read(AVI->fdes,data,8) != 8 ) break;
         n = str2ulong(data+4);

         /* The movi list may contain sub-lists, ignore them */

         if(strncasecmp(data,"LIST",4)==0)
         {
            lseek(AVI->fdes,4,SEEK_CUR);
            continue;
         }

         /* Check if we got a tag ##db, ##dc or ##wb */

         if( ( (data[2]=='d' || data[2]=='D') &&
               (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') )
          || ( (data[2]=='w' || data[2]=='W') &&
               (data[3]=='b' || data[3]=='B') ) )
         {
            avi_add_index_entry(AVI,data,0,lseek(AVI->fdes,0,SEEK_CUR)-8,n);
         }

         lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR);
      }
      idx_type = 1;
   }

   /* Now generate the video index and audio index arrays */

   nvi = 0;
   nai = 0;

   for(i=0;i<AVI->n_idx;i++)
   {
      if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) nvi++;
      if(strncasecmp(AVI->idx[i],AVI->audio_tag,4) == 0) nai++;
   }

   AVI->video_frames = nvi;
   AVI->audio_chunks = nai;

   if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS)
   AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry));
   if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM)
   if(AVI->audio_chunks)
   {
      AVI->audio_index = (audio_index_entry *) malloc(nai*sizeof(audio_index_entry));
      if(AVI->audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM)
   }

   nvi = 0;
   nai = 0;
   tot = 0;
   ioff = idx_type == 1 ? 8 : AVI->movi_start+4;

   for(i=0;i<AVI->n_idx;i++)
   {
      if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0)
      {
         AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
         AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12);
         nvi++;
      }
      if(strncasecmp(AVI->idx[i],AVI->audio_tag,4) == 0)
      {
         AVI->audio_index[nai].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
         AVI->audio_index[nai].len = str2ulong(AVI->idx[i]+12);
         AVI->audio_index[nai].tot = tot;
         tot += AVI->audio_index[nai].len;
         nai++;
      }
   }

   AVI->audio_bytes = tot;

   /* Reposition the file */

   lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
   AVI->video_pos = 0;

   return AVI;
}

long AVI_video_frames(avi_t *AVI)
{
   return AVI->video_frames;
}
int  AVI_video_width(avi_t *AVI)
{
   return AVI->width;
}
int  AVI_video_height(avi_t *AVI)
{
   return AVI->height;
}
double AVI_video_frame_rate(avi_t *AVI)
{
   return AVI->fps;
}
char* AVI_video_compressor(avi_t *AVI)
{
   return AVI->compressor;
}

int AVI_audio_channels(avi_t *AVI)
{
   return AVI->a_chans;
}
int AVI_audio_bits(avi_t *AVI)
{
   return AVI->a_bits;
}
int AVI_audio_format(avi_t *AVI)
{
   return AVI->a_fmt;
}
long AVI_audio_rate(avi_t *AVI)
{
   return AVI->a_rate;
}
long AVI_audio_bytes(avi_t *AVI)
{
   return AVI->audio_bytes;
}

long AVI_frame_size(avi_t *AVI, long frame)
{
   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
   if(!AVI->video_index)         { AVI_errno = AVI_ERR_NO_IDX;   return -1; }

   if(frame < 0 || frame >= AVI->video_frames) return 0;
   return(AVI->video_index[frame].len);
}

int AVI_seek_start(avi_t *AVI)
{
   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }

   lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
   AVI->video_pos = 0;
   AVI->audio_posc = 0;
   AVI->audio_posb = 0;
   return 0;
}

int AVI_set_video_position(avi_t *AVI, long frame, long *frame_len)
{
   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
   if(!AVI->video_index)         { AVI_errno = AVI_ERR_NO_IDX;   return -1; }

   if (frame < 0 ) frame = 0;
   AVI->video_pos = frame;
   if (frame_len != NULL)
     *frame_len = AVI->video_index[frame].len;
   return 0;
}
      

long AVI_read_frame(avi_t *AVI, char *vidbuf)
{
   long n;

   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
   if(!AVI->video_index)         { AVI_errno = AVI_ERR_NO_IDX;   return -1; }

   if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return 0;
   n = AVI->video_index[AVI->video_pos].len;

   lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET);
   if (read(AVI->fdes,vidbuf,n) != n)
   {
      AVI_errno = AVI_ERR_READ;
      return -1;
   }

   AVI->video_pos++;

   return n;
}

int AVI_set_audio_position(avi_t *AVI, long byte)
{
   long n0, n1, n;

   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
   if(!AVI->audio_index)         { AVI_errno = AVI_ERR_NO_IDX;   return -1; }

   if(byte < 0) byte = 0;

   /* Binary search in the audio chunks */

   n0 = 0;
   n1 = AVI->audio_chunks;

   while(n0<n1-1)
   {
      n = (n0+n1)/2;
      if(AVI->audio_index[n].tot>byte)
         n1 = n;
      else
         n0 = n;
   }

   AVI->audio_posc = n0;
   AVI->audio_posb = byte - AVI->audio_index[n0].tot;

   return 0;
}

int AVI_set_audio_frame (avi_t *AVI, long frame, long *frame_len)
{
  if (AVI->audio_posc >= AVI->audio_chunks - 1) { return -1; }
  AVI->audio_posc = frame;
  AVI->audio_posb = 0;
  if (frame_len != NULL)
    *frame_len = AVI->audio_index[frame].len;
  return 0;
}

long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes)
{
   long nr, pos, left, todo;

   if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
   if(!AVI->audio_index)         { AVI_errno = AVI_ERR_NO_IDX;   return -1; }

   nr = 0; /* total number of bytes read */

   while(bytes>0)
   {
      left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb;
      if(left==0)
      {
         if(AVI->audio_posc>=AVI->audio_chunks-1) return nr;
         AVI->audio_posc++;
         AVI->audio_posb = 0;
         continue;
      }
      if(bytes<left)
         todo = bytes;
      else
         todo = left;
      pos = AVI->audio_index[AVI->audio_posc].pos + AVI->audio_posb;
      lseek(AVI->fdes, pos, SEEK_SET);
      if (read(AVI->fdes,audbuf+nr,todo) != todo)
      {
         AVI_errno = AVI_ERR_READ;
         return -1;
      }
      bytes -= todo;
      nr    += todo;
      AVI->audio_posb += todo;
   }

   return nr;
}

/* AVI_read_data: Special routine for reading the next audio or video chunk
                  without having an index of the file. */

int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf,
                              char *audbuf, long max_audbuf,
                              long *len)
{

/*
 * Return codes:
 *
 *    1 = video data read
 *    2 = audio data read
 *    0 = reached EOF
 *   -1 = video buffer too small
 *   -2 = audio buffer too small
 */

   int n;
   char data[8];

   if(AVI->mode==AVI_MODE_WRITE) return 0;

   while(1)
   {
      /* Read tag and length */

      if( read(AVI->fdes,data,8) != 8 ) return 0;

      /* if we got a list tag, ignore it */

      if(strncasecmp(data,"LIST",4) == 0)
      {
         lseek(AVI->fdes,4,SEEK_CUR);
         continue;
      }

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

      if(strncasecmp(data,AVI->video_tag,3) == 0)
      {
         *len = n;
         AVI->video_pos++;
         if(n>max_vidbuf)
         {
            lseek(AVI->fdes,n,SEEK_CUR);
            return -1;
         }
         if(read(AVI->fdes,vidbuf,n) != n ) return 0;
         return 1;
      }
      else if(strncasecmp(data,AVI->audio_tag,4) == 0)
      {
         *len = n;
         if(n>max_audbuf)
         {
            lseek(AVI->fdes,n,SEEK_CUR);
            return -2;
         }
         if(read(AVI->fdes,audbuf,n) != n ) return 0;
         return 2;
         break;
      }
      else
         if(lseek(AVI->fdes,n,SEEK_CUR)<0)  return 0;
   }
}

/* AVI_print_error: Print most recent error (similar to perror) */

char *(avi_errors[]) =
{
  /*  0 */ "avilib - No Error",
  /*  1 */ "avilib - AVI file size limit reached",
  /*  2 */ "avilib - Error opening AVI file",
  /*  3 */ "avilib - Error reading from AVI file",
  /*  4 */ "avilib - Error writing to AVI file",
  /*  5 */ "avilib - Error writing index (file may still be useable)",
  /*  6 */ "avilib - Error closing AVI file",
  /*  7 */ "avilib - Operation (read/write) not permitted",
  /*  8 */ "avilib - Out of memory (malloc failed)",
  /*  9 */ "avilib - Not an AVI file",
  /* 10 */ "avilib - AVI file has no header list (corrupted?)",
  /* 11 */ "avilib - AVI file has no MOVI list (corrupted?)",
  /* 12 */ "avilib - AVI file has no video data",
  /* 13 */ "avilib - operation needs an index",
  /* 14 */ "avilib - Unkown Error"
};
static int num_avi_errors = sizeof(avi_errors)/sizeof(char*);

static char error_string[4096];

void AVI_print_error(char *str)
{
   int aerrno;

   aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;

   fprintf(stderr,"%s: %s\n",str,avi_errors[aerrno]);

   /* for the following errors, perror should report a more detailed reason: */

   if(AVI_errno == AVI_ERR_OPEN ||
      AVI_errno == AVI_ERR_READ ||
      AVI_errno == AVI_ERR_WRITE ||
      AVI_errno == AVI_ERR_WRITE_INDEX ||
      AVI_errno == AVI_ERR_CLOSE )
   {
      perror("REASON");
   }
}

char *AVI_strerror()
{
   int aerrno;

   aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;

   if(AVI_errno == AVI_ERR_OPEN ||
      AVI_errno == AVI_ERR_READ ||
      AVI_errno == AVI_ERR_WRITE ||
      AVI_errno == AVI_ERR_WRITE_INDEX ||
      AVI_errno == AVI_ERR_CLOSE )
   {
      sprintf(error_string,"%s - %s",avi_errors[aerrno],
#ifndef _WINDOWS
			strerror(errno)
#else
			_strerror(NULL)
#endif
			);
      return error_string;
   }
   else
   {
      return avi_errors[aerrno];
   }
}

⌨️ 快捷键说明

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