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

📄 avireader.cpp

📁 播放被H264_AAC所压缩的avi文件的播放器。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// AviReader.cpp: implementation of the CAviReader class.
//
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdlib.h>
#include "common.h"
#include "AviReader.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define PAD_EVEN(x) ( ((x)+1) & ~1 )
#define ERR_EXIT(x) \
{ \
   CloseAviFile(); \
   m_nAviErrNo = x; \
   return 0; \
}

#define	I_FRAME		MAKEFOURCC('0', '0', 'd', 'b')

//##ModelId=4753BE280233
CAviReader::CAviReader()
{
	m_pAviFile = (avi_t *) malloc(sizeof(avi_t));
	memset((void *)m_pAviFile, 0, sizeof(avi_t));

	m_pVideoBuf = (BYTE *)malloc(VIDEO_BUFFER_MAX_SIZE);
	memset(m_pVideoBuf, 0, VIDEO_BUFFER_MAX_SIZE);

	m_pAudioBuf = (BYTE *)malloc(AUDIO_BUFFER_MAX_SIZE);
	memset(m_pAudioBuf, 0, AUDIO_BUFFER_MAX_SIZE);

	m_nCurAudioPos = m_nCurVideoPos = 0;
}

//##ModelId=4753BE280242
CAviReader::~CAviReader()
{
	if( m_pAudioBuf )
		free(m_pAudioBuf);

	if( m_pVideoBuf )
		free(m_pVideoBuf);

	if( m_pAviFile )
		free(m_pAviFile);
}

/*******************************************************************
 *                                                                 *
 *    Utilities for reading video and audio from an m_pAviFile File       *
 *                                                                 *
 *******************************************************************/
/* Copy n into dst as a 4 byte, little endian number.
   Should also work on big endian machines */

//##ModelId=4753BE280295
void CAviReader::Long2Str(BYTE *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 */

//##ModelId=4753BE2802A1
unsigned long CAviReader::Str2ULong(BYTE *str)
{
   return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );
}

//##ModelId=4753BE2802AF
unsigned long CAviReader::Str2UShort(BYTE *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 */

//##ModelId=4753BE2802BF
int CAviReader::Sampsize()
{
   int s;
   s = ((m_pAviFile->a_bits+7)/8)*m_pAviFile->a_chans;
   
   if(s==0) 
	   s=1; /* avoid possible zero divisions */
   return s;
}

//##ModelId=4753BE2802C0
int CAviReader::AddIndexEntry(BYTE *tag, LONG flags, LONG pos, LONG len)
{
   void *ptr;

   if(m_pAviFile->n_idx>=m_pAviFile->max_idx)
   {
      ptr = realloc((void *)m_pAviFile->idx,(m_pAviFile->max_idx+4096)*16);
      if(ptr == 0)
      {
         m_nAviErrNo = AVI_ERR_NO_MEM;
         return -1;
      }
      m_pAviFile->max_idx += 4096;
      m_pAviFile->idx = (BYTE((*)[16]) ) ptr;
   }

   /* Add index entry */

   memcpy(m_pAviFile->idx[m_pAviFile->n_idx],tag,4);
   Long2Str(m_pAviFile->idx[m_pAviFile->n_idx]+ 4,flags);
   Long2Str(m_pAviFile->idx[m_pAviFile->n_idx]+ 8,pos);
   Long2Str(m_pAviFile->idx[m_pAviFile->n_idx]+12,len);

   /* Update counter */

   m_pAviFile->n_idx++;

   return 0;
}

//##ModelId=4753BE280244
int CAviReader::OpenAviFile(const char *filename)
{
   long i, n, rate, scale, idx_type;
   BYTE *hdrl_data;
   long hdrl_len = 0;
   long nvi, nai, ioff;
   long audtot, vidtot;
   DWORD dwRead;
   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 */

   if(m_pAviFile == NULL)
   {
      m_nAviErrNo = AVI_ERR_NO_MEM;
      return -1;
   }
   memset((void *)m_pAviFile,0,sizeof(avi_t));

   /* Open the file */

   m_pAviFile->fDes = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
						 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
   if(m_pAviFile->fDes == INVALID_HANDLE_VALUE)
   {
	  m_nAviErrNo = AVI_ERR_OPEN;
      free(m_pAviFile);
	  m_pAviFile = NULL;
      return -1;
   }

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

   ReadFile(m_pAviFile->fDes, data, 12, &dwRead, NULL);
   if( dwRead != 12 ) 
	   ERR_EXIT(AVI_ERR_READ)

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

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

   hdrl_data = 0;

   while(1)
   {
	  ReadFile(m_pAviFile->fDes, data, 8, &dwRead, NULL);
      if( dwRead != 8 ) break; /* We assume it's EOF */

      n = Str2ULong((BYTE*)data+4);
      n = PAD_EVEN(n);

      if(strncmp(data,"LIST",4) == 0)
      {
		 ReadFile(m_pAviFile->fDes, data, 4, &dwRead, NULL);
         if( dwRead != 4 ) ERR_EXIT(AVI_ERR_READ)
         n -= 4;
         if(strncmp(data,"hdrl",4) == 0)
         {
            hdrl_len = n;
            hdrl_data = (BYTE *) malloc(n);
            if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM)
			ReadFile(m_pAviFile->fDes, hdrl_data, n, &dwRead, NULL);
            if( (long)dwRead != n ) ERR_EXIT(AVI_ERR_READ)
         }
         else if(strncmp(data,"movi",4) == 0)
         {
			m_pAviFile->movi_start = SetFilePointer(m_pAviFile->fDes, 0, NULL, FILE_CURRENT);
			SetFilePointer(m_pAviFile->fDes, n, NULL, FILE_CURRENT);
         }
         else
            SetFilePointer(m_pAviFile->fDes, n, NULL, FILE_CURRENT);
      }
      else if(strncmp(data,"idx1",4) == 0)
      {
         /* n must be a multiple of 16, but the reading does not
            break if this is not the case */
         m_pAviFile->n_idx = m_pAviFile->max_idx = n/16;
         m_pAviFile->idx = (BYTE((*)[16]) ) malloc(n);
         
		 if(m_pAviFile->idx==0) 
			 ERR_EXIT(AVI_ERR_NO_MEM)
         
		 ReadFile(m_pAviFile->fDes, m_pAviFile->idx, n, &dwRead, NULL);
		 if( (long)dwRead != n ) 
			 ERR_EXIT(AVI_ERR_READ)
      }
      else
         SetFilePointer(m_pAviFile->fDes, n, NULL, FILE_CURRENT);
   }

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

   /* Interpret the header list */

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

      if(strncmp((const char*)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(strncmp((const char*)hdrl_data+i,"strh",4)==0)
      {
         i += 8;
         if(strncmp((const char*)hdrl_data+i,"vids",4) == 0 && !vids_strh_seen)
         {
            scale = Str2ULong(hdrl_data+i+20);
            rate  = Str2ULong(hdrl_data+i+24);
            if(scale!=0) m_pAviFile->fps = (double)rate/(double)scale;
            m_pAviFile->video_frames = Str2ULong(hdrl_data+i+32);
            m_pAviFile->video_strn = num_stream;
            vids_strh_seen = 1;
            lasttag = 1; /* vids */
         }
         else if (strncmp ((const char*)hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen)
         {
            m_pAviFile->audio_bytes = Str2ULong(hdrl_data+i+32)*Sampsize();
            m_pAviFile->audio_strn = num_stream;
            auds_strh_seen = 1;
            lasttag = 2; /* auds */
         }
         else
            lasttag = 0;
		 num_stream++;
      }
      else if(strncmp((const char*)hdrl_data+i,"strf",4)==0)
      {
         i += 8;
         if(lasttag == 1)
         {
            m_pAviFile->width  = Str2ULong(hdrl_data+i+4);
            m_pAviFile->height = Str2ULong(hdrl_data+i+8);
            memcpy(m_pAviFile->compressor,hdrl_data+i+16,4);
            m_pAviFile->compressor[4] = 0;
            vids_strf_seen = 1;
         }
         else if(lasttag == 2)
         {
            m_pAviFile->a_fmt   = Str2UShort(hdrl_data+i  );
            m_pAviFile->a_chans = Str2UShort(hdrl_data+i+2);
            m_pAviFile->a_rate  = Str2ULong (hdrl_data+i+4);
            m_pAviFile->a_bits  = Str2UShort(hdrl_data+i+14);
			m_pAviFile->acps = m_pAviFile->a_rate / 1024.0;
			//temp code for aac decode
			if( Str2ULong(hdrl_data+i-4) > 16 )
			{
				m_pAviFile->a_extradata_size = Str2UShort(hdrl_data+i+16);
				memcpy(m_pAviFile->a_extradata, hdrl_data+i+18, 2);
			}
            auds_strf_seen = 1;
         }
         lasttag = 0;
      }
      else
      {
         i += 8;
         lasttag = 0;
      }

      i += n;
   }

   free(hdrl_data);

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

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

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

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

   SetFilePointer(m_pAviFile->fDes, m_pAviFile->movi_start, NULL, FILE_BEGIN);

   /* 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(m_pAviFile->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<m_pAviFile->n_idx;i++)
         if( strncmp((const char*)m_pAviFile->idx[i],m_pAviFile->video_tag,3)==0 ) break;
      if(i>=m_pAviFile->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS)

      pos = Str2ULong(m_pAviFile->idx[i]+ 8);
      len = Str2ULong(m_pAviFile->idx[i]+12);

	  SetFilePointer(m_pAviFile->fDes, pos, NULL, FILE_BEGIN);
	  ReadFile(m_pAviFile->fDes, data, 8, &dwRead, NULL);

⌨️ 快捷键说明

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