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

📄 decapsavi.cpp

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include "DecapsAVI.h"



static void long2str(char *dst, int n)
{
	dst[0] = (n      ) & 0xff;
	dst[1] = (n >>  8) & 0xff;
	dst[2] = (n >> 16) & 0xff;
	dst[3] = (n >> 24) & 0xff;
}



unsigned long str2ulong(char *str)
{
    unsigned long result;

	result = ( ((unsigned long) str[0] & 0xFF) | ( ((unsigned long)str[1] &0xFF) << 8) |
			  (((unsigned long) str[2] & 0xFF) << 16) | ( ((unsigned long) str[3] & 0xFF) << 24) );

	return result;
}

static unsigned long str2ushort(char *str)
{
	return ( str[0] | (str[1]<<8) );
}



media_type_t MediaDecapsAVI::GetType()
{
	return MEDIA_TYPE_DECAPS;
}



char *MediaDecapsAVI::GetName()
{
	return "AVI Demuxer";
}


MP_RESULT MediaDecapsAVI::Connect(MediaItem *item)
{
	if(item->GetType() == MEDIA_TYPE_INPUT) {

		this->input = (MediaItemInput *) item;
	}

	this->video_pos  = 0;
	this->audio_posc = 0;
	this->audio_posb = 0;

	this->idx         = NULL;
	this->video_index = NULL;
	this->audio_index = NULL;


	if(this->IsAVI()) {
		
		if(this->FillHeader(1)) {
		
			return MP_RESULT_OK;
		}
		else {

			this->input->Seek(0, INPUT_SEEK_SET);

			this->IsAVI();
			
			if(this->FillHeader(0)) {
		
				return MP_RESULT_OK;
			}
		}
	}
	
	return MP_RESULT_ERROR;
}



MP_RESULT MediaDecapsAVI::ReleaseConnections()
{
	this->input = NULL;

	if(this->idx != NULL)
		free(this->idx);

	if(this->video_index != NULL)
		free(this->video_index);
	
	if(this->audio_index != NULL)
		free(this->audio_index);

	this->idx         = NULL;
	this->video_index = NULL;
	this->audio_index = NULL;

	this->audio_strn = 0;
	this->video_strn = 0;

	memset(&this->waveformatex, 0, sizeof(MPEGLAYER3WAVEFORMAT));
	memset(&this->bitmapinfoheader, 0, sizeof(BITMAPINFOHEADER));
	
	return MP_RESULT_OK;
}

DWORD         MediaDecapsAVI::GetCaps()
{
	return 0;
}

MP_RESULT     MediaDecapsAVI::Configure(HINSTANCE hInstance, HWND hwnd)
{
	return MP_RESULT_ERROR;
}




MediaDecapsAVI::MediaDecapsAVI()
{
	this->video_pos  = 0;
	this->audio_posc = 0;
	this->audio_posb = 0;

	this->idx         = NULL;
	this->video_index = NULL;
	this->audio_index = NULL;

	this->hIOMutex = CreateMutex (NULL, FALSE, NULL);

	this->input = NULL;
}

MediaDecapsAVI::~MediaDecapsAVI()
{
	CloseHandle(this->hIOMutex);
}

int MediaDecapsAVI::IsAVI()
{
	MediaBuffer *mb = new MediaBuffer();
	mb->Alloc(12);

	if(this->input != NULL) {
		
		if( this->input->Read(mb, 12) != 12 ) {
			
			delete mb;
			return 0;
		}
		

		if( strncmp((char *) mb->GetData(), "RIFF", 4) !=0 || 
			strncmp(((char *) mb->GetData()) + 8, "AVI ", 4) !=0 ) {
			return 0;
		}
		
		delete mb;
		return 1;
	}
	
	return 0;
}

int MediaDecapsAVI::SampleSize()
{
	int s;
	
	s = ((this->a_bits + 7) / 8) * this->a_chans;
	
	if(s == 0)
		s = 1;
	
	return s;
}

int MediaDecapsAVI::FillHeader(int getIndex)
{
	unsigned long  n, rate; 
	long           scale, idx_type;
	char          *hdrl_data;
	long           i, hdrl_len = 0;
	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;
	MediaBuffer   *mb = new MediaBuffer();
	
	if(this->input == NULL)
		return MP_RESULT_ERROR;

	mb->Alloc(256);


	
	hdrl_data = 0;
	
	while(1)
    {
		if( this->input->Read(mb, 8) != 8 ) 
			break; 

		
		n = str2ulong(((char *) mb->GetData()) + 4);
		n = PAD_EVEN(n);
		
		if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
		{
			
			if( this->input->Read(mb, 4) != 4 ) {

				mb->Free();
				return 0;
			}
			
			n -= 4;
			
			if(strncmp((char *) mb->GetData(), "hdrl", 4) == 0)
			{
			

				MediaBuffer *mbh;
				hdrl_len = n;

				char buffer[256];
				sprintf(buffer, "size = %d", n);

				mbh = new MediaBuffer();
				mbh->Alloc(n);

				hdrl_data = (char *) new char[n];
				
				if(hdrl_data == NULL) { 
					
					mb->Free();
					return 0;
				}
				
				if( this->input->Read(mbh, n) != n ) {
					
					mb->Free();
					return 0;
				}

				memcpy(hdrl_data, mbh->GetData(), n);
				mbh->Free();
			}
			else if(strncmp((char *) mb->GetData(), "movi", 4) == 0)
			{
				this->movi_start = this->input->Seek(0, INPUT_SEEK_CUR);
				
				this->input->Seek(n, INPUT_SEEK_CUR);
			}
			else
				this->input->Seek(n, INPUT_SEEK_CUR);
		}
		else if(strncmp((char *) mb->GetData(),"idx1",4) == 0)
		{


			
			this->n_idx = this->max_idx = n/16;
			this->idx = (char((*)[16]) ) new char[n];
			
			if(this->idx == NULL) { 
				
				mb->Free();
				return 0;
			}
			
			unsigned long read;
			MediaBuffer  *mbi = new MediaBuffer();

			mbi->Alloc(n);

			if( (read = this->input->Read(mbi, n)) != n ) {
				
				break;
			}

			memcpy(this->idx, mbi->GetData(), n);
			mbi->Free();
		}
		else {
		  
			this->input->Seek(n, INPUT_SEEK_CUR);
		}
	}
	
	if(!hdrl_data) {
		
		mb->Free();
		return 0;
	}
	
	if(!this->movi_start) {
		
		mb->Free();
		return 0;
	}
	


	
	for(i=0; i < hdrl_len; )
	{

		
		if(strncmp(hdrl_data + i, "LIST", 4)==0) 
		{ 
			i+= 12; 
			continue; 
		}
		
		n = str2ulong(hdrl_data+i+4);
		n = PAD_EVEN(n);
		

		
		if(strncmp(hdrl_data + i, "strh", 4)==0)
		{
			i += 8;
			if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
			{
				memcpy(this->compressor,hdrl_data+i+4,4);
				
				this->compressor[4] = 0;
				
				scale = str2ulong(hdrl_data+i+20);
				rate  = str2ulong(hdrl_data+i+24);
				
				if(scale!=0) 
					this->fps = (double)rate/(double)scale;
				
				this->video_frames = str2ulong(hdrl_data+i+32);
				this->video_strn = num_stream;
				
				vids_strh_seen = 1;
				lasttag = 1; 
			}
			else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
			{
				this->audio_bytes = str2ulong(hdrl_data + i + 32)*this->SampleSize();
				this->audio_strn = num_stream;
				
				auds_strh_seen = 1;
				lasttag = 2; 
			}
			else
				lasttag = 0;
			num_stream++;
		}
		else if(strncmp(hdrl_data + i, "strf", 4)==0)
		{
			i += 8;
			if(lasttag == 1)
			{

				
			memcpy(&this->bitmapinfoheader, 
					hdrl_data + i,
					sizeof(BITMAPINFOHEADER));  
				
				this->width  = str2ulong(hdrl_data+i+4);
				this->height = str2ulong(hdrl_data+i+8);
				vids_strf_seen = 1;
			}
			else if(lasttag == 2)
			{


				memcpy(&this->waveformatex,
					   hdrl_data + i,
					   sizeof(MPEGLAYER3WAVEFORMAT));

				this->a_fmt   = str2ushort(hdrl_data + i  );
				this->a_chans = str2ushort(hdrl_data + i + 2);
				this->a_rate  = str2ulong (hdrl_data + i + 4);
				this->a_bits  = str2ushort(hdrl_data + i + 14) == 0 ? 16 : 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 || this->video_frames==0) { 
		
		mb->Free();
		return 0;
	}
	
	this->video_tag[0] = this->video_strn/10 + '0';
	this->video_tag[1] = this->video_strn%10 + '0';
	this->video_tag[2] = 'd';
	this->video_tag[3] = 'b';

	
	if(!this->a_chans) 
		this->audio_strn = 99;
	
	this->audio_tag[0] = this->audio_strn/10 + '0';
	this->audio_tag[1] = this->audio_strn%10 + '0';
	this->audio_tag[2] = 'w';
	this->audio_tag[3] = 'b';
	
	this->input->Seek(this->movi_start, INPUT_SEEK_SET);

	
	if(!getIndex) 
		return 1;
	

	
	idx_type = 0;
	
	if(this->idx)
	{
		unsigned long pos, len;
		

		
		for(i = 0; i < this->n_idx; i++) {
			if( strncmp(this->idx[i], this->video_tag, 3) == 0 ) 
				break;
		}
		
		if(i >= this->n_idx) 
			return 0;
		
		pos = str2ulong(this->idx[i] + 8);
		len = str2ulong(this->idx[i] + 12);
		
		this->input->Seek(pos, INPUT_SEEK_SET);
		
		if(this->input->Read(mb, 8)!=8) 
			return 0;
		
		if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
		{

			
			idx_type = 1; 
		}
		else
		{
			this->input->Seek(pos + this->movi_start - 4,INPUT_SEEK_SET);
			
			if(this->input->Read(mb, 8) != 8) 
				return 0;
			
			if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
			{

				
				idx_type = 2; 
			}
		}


	}
	
	if(idx_type == 0)
	{


		
		this->input->Seek(this->movi_start, INPUT_SEEK_SET);
		
		this->max_idx = 4096;
		this->n_idx   = 0;

		this->idx = (char((*)[16]) ) new char[this->max_idx];
		
		while(1)
		{
			
			if( this->input->Read(mb, 8) != 8 ) 
				break;
			
			n = str2ulong((char *) mb->GetData() + 4);
			

			
			if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
			{
				this->input->Seek(4, INPUT_SEEK_CUR);
				continue;
			}
			

			
			if( ((((char *) mb->GetData())[2]=='d' || ((char *) mb->GetData())[2]=='D') &&
				 (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B' || 
				  ((char *) mb->GetData())[3]=='c' || ((char *) mb->GetData())[3]=='C') ) || 
				((((char *) mb->GetData())[2]=='w' || ((char *) mb->GetData())[2]=='W') &&
				 (((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B') ) )
			{
				this->AddIndexEntry(((char *) mb->GetData()),
									0, 
									this->input->Seek(0, INPUT_SEEK_CUR) - 8, 
									n);
			}
			
			this->input->Seek(PAD_EVEN(n), INPUT_SEEK_CUR);
		}

		idx_type = 1;
	}
	

	
	nvi = 0;
	nai = 0;
	
	for(i=0; i < this->n_idx; i++)
	{
		if(strncmp(this->idx[i], this->video_tag, 3) == 0) 
			nvi++;
		
		if(strncmp(this->idx[i], this->audio_tag, 4) == 0) 
			nai++;
	}
	
	this->video_frames = nvi;
	this->audio_chunks = nai;
	
	if(this->video_frames == 0) {
	
		mb->Free();
		return 0;
	}

	this->video_index = (video_index_entry *) new char[(nvi*sizeof(video_index_entry))];
	
	if(this->video_index == 0) { 
	
		mb->Free();
		return 0;
	}

	if(this->audio_chunks)
	{
		this->audio_index = (audio_index_entry *) new char[(nai*sizeof(audio_index_entry))];
		
		if(this->audio_index == 0) {

			mb->Free();
			return 0;
		}
	}
	
	nvi = 0;
	nai = 0;
	tot = 0;
	
	ioff = idx_type == 1 ? 8 : this->movi_start+4;
	
	for(i=0; i < this->n_idx; i++)
	{
		if(strncmp(this->idx[i], this->video_tag, 3) == 0)
		{
			this->video_index[nvi].flags = str2ulong(this->idx[i]+ 4);
			this->video_index[nvi].pos   = str2ulong(this->idx[i]+ 8)+ioff;
			this->video_index[nvi].len   = str2ulong(this->idx[i]+12);
			
			nvi++;
		}
		if(strncmp(this->idx[i], this->audio_tag, 4) == 0)
		{
			this->audio_index[nai].pos = str2ulong(this->idx[i]+ 8)+ioff;
			this->audio_index[nai].len = str2ulong(this->idx[i]+12);
			this->audio_index[nai].tot = tot;
			
			tot += this->audio_index[nai].len;
			
			nai++;
		}
	}
	
	this->audio_bytes = tot;
	

	
	this->input->Seek(this->movi_start, INPUT_SEEK_SET);

⌨️ 快捷键说明

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