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

📄 decapsavi.cpp

📁 <VC++视频音频开发>一书的光盘资料。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	
	this->video_pos = 0;
	mb->Free();
	
	return 1;
}

int MediaDecapsAVI::AddIndexEntry(char *tag, 
								  long flags, 
								  long pos, 
								  long len)
{
	void *ptr;
	
	if(this->n_idx*16 >= this->max_idx)
	{
		ptr = realloc((void *)this->idx,
			(this->max_idx + 4096) * 16);
		
		if(ptr == 0) {
			return -1;
		}
		
		this->max_idx += 4096;
		this->idx = (char((*)[16]) ) ptr;
	}
	

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

	
	this->n_idx++;
	
	return 0;
}

int  MediaDecapsAVI::ReFillIndex()
{
	unsigned long  n; 
	long           idx_type;
	long           i;
	long           nvi, nai, ioff;
	long           tot;
	MediaBuffer   *mb = new MediaBuffer();
	
	if(this->input == NULL)
		return MP_RESULT_ERROR;

	mb->Alloc(256);



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

	this->idx = (char((*)[16]) ) realloc(this->idx, this->max_idx*16);
		
	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) 
		return 0;
	
	this->video_index = (video_index_entry *) realloc(this->video_index, nvi*sizeof(video_index_entry));
	
	if(this->video_index == 0) 
		return 0;
	
	if(this->audio_chunks)
	{
		this->audio_index = (audio_index_entry *) realloc(this->audio_index, 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;
	mb->Free();

	return 1;
}



BOOL MediaDecapsAVI::isKeyframe(long frame)
{
  if(frame < 0 || frame > this->video_frames)
    frame = 0;

  if(!this->video_index)         
    { 
 

      return 1; 
    }

  return this->video_index[frame].flags & AVIIF_KEYFRAME;
}

unsigned int  MediaDecapsAVI::GetNumberOfVideoStreams()
{


	return 1;
}

unsigned int  MediaDecapsAVI::GetNumberOfAudioStreams()
{
	if(this->audio_strn == 99)
		return 0;
	
	return this->audio_strn;
}

unsigned int  MediaDecapsAVI::GetVideoWidth(unsigned int StreamId)
{
	return this->width;
}

unsigned int  MediaDecapsAVI::GetVideoHeight(unsigned int StreamId)
{
	return this->height;
}

double        MediaDecapsAVI::GetVideoFrameRate(unsigned int StreamId)
{
	if(this->fps == 0)
		this->fps = 25;

	if(this->fps == 23)
		this->fps = 25;

	return this->fps;
}

char		 *MediaDecapsAVI::GetVideoCompression(unsigned int StreamId)
{
	return this->compressor;
}

BITMAPINFOHEADER *MediaDecapsAVI::GetVideoHeader(unsigned int StreamId)
{
	return &this->bitmapinfoheader;
}

unsigned long MediaDecapsAVI::GetCurrentVideoFrame(unsigned int StreamId)
{
	return this->video_pos;
}


unsigned long MediaDecapsAVI::GetTotalVideoFrames(unsigned int StreamId)
{
	return this->video_frames;
}

unsigned long MediaDecapsAVI::GetTotalVideoTime(unsigned int StreamId)
{
	if(this->fps == 0) {
		
		return 0;
	}
	else {
		
		return (unsigned long) (this->video_frames * 1000 / (double) this->fps);
	}
}
	
unsigned int  MediaDecapsAVI::GetAudioBits(unsigned int StreamId)
{
	return this->a_bits;
}

unsigned int  MediaDecapsAVI::GetAudioChannels(unsigned int StreamId)
{
	return this->a_chans;
}

unsigned int  MediaDecapsAVI::GetAudioFrequency(unsigned int StreamId)
{
	return this->a_rate;
}

WAVEFORMATEX *MediaDecapsAVI::GetAudioFormat(unsigned int StreamId)
{
	return (WAVEFORMATEX *) &this->waveformatex;
}


unsigned int  MediaDecapsAVI::GetNextVideoFrameSize(unsigned int StreamId)
{
	if(!this->video_index) { 
		return 0; 
	}

	return(this->video_index[this->video_pos].len);
}

unsigned int MediaDecapsAVI::ReadVideoFrame(unsigned int StreamId, MediaBuffer *mb)
{
	unsigned int m;
	unsigned int n;




	if(!this->video_index || !mb) {
		
		return MP_RESULT_ERROR; 
    }

	if(this->video_pos < 0 || this->video_pos >= this->video_frames - 1) {

		return MP_RESULT_ERROR;
    }



	WaitForSingleObject(this->hIOMutex, INFINITE);

	n = this->video_index[this->video_pos].len;

	this->input->Seek(this->video_index[this->video_pos].pos, INPUT_SEEK_SET);

	if(mb->GetSize() < n) {
		
		mb->ReAlloc(n);
	}

	if ((m = this->input->Read(mb, n)) != n) {

		this->video_pos++;

	    ReleaseMutex(this->hIOMutex);

	char msg[256];
	sprintf(msg, "index %u and %u at %u", this->video_index[this->video_pos].len, this->video_index[this->video_pos].pos, this->video_pos);
	MessageBox(NULL, msg, "", MB_OK);	

	sprintf(msg, "read %d on %u at %d on %d", m, n, this->video_pos, this->video_frames);
	MessageBox(NULL, msg, "", MB_OK);	
		
		return n;
    }

    this->video_pos++;

 

    ReleaseMutex(this->hIOMutex);

    return MP_RESULT_OK;	
}

unsigned int MediaDecapsAVI::ReadAudioData(unsigned int StreamId, char *buffer, unsigned int bytes)
{
	unsigned int nr, pos, left = 0, todo, posc, posb, asked_bytes;
	MediaBuffer *mbi = new MediaBuffer();

	if(!this->audio_index || !buffer) {
		
		return MP_RESULT_ERROR; 
    }

	asked_bytes = bytes;

	posc = this->audio_posc;
	posb = this->audio_posb;

   nr = 0; 
   mbi->Alloc(bytes);



   WaitForSingleObject(this->hIOMutex, INFINITE);



	while(bytes > 0) {

		left = this->audio_index[this->audio_posc].len - this->audio_posb;

		if(left == 0) {

			if(this->audio_posc >= this->audio_chunks - 1) {
				
				ReleaseMutex(this->hIOMutex);

				this->audio_posb = posb;
				this->audio_posc = posc;

				return 0;
			}

			this->audio_posc++;
			this->audio_posb = 0;
			continue;
		}

		if(bytes < left)
			todo = bytes;
		else
			todo = left;

		pos = this->audio_index[this->audio_posc].pos + this->audio_posb;
      
		this->input->Seek(pos, INPUT_SEEK_SET);

	    if (this->input->Read(mbi, todo) != todo) {

			ReleaseMutex(this->hIOMutex);



			this->audio_posb = posb;
			this->audio_posc = posc;
			
			return 0;
		}

		memcpy(buffer + nr, mbi->GetData(), todo);

		bytes -= todo;
		nr    += todo;

		this->audio_posb += todo;
	}

	mbi->Free();
	delete mbi;



    ReleaseMutex(this->hIOMutex);

    return asked_bytes;
}

MP_RESULT     MediaDecapsAVI::UpdateForSize()
{
	this->ReFillIndex();
	
	return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::SeekAudio(unsigned int StreamId, long bytes)
{
   long n0, n1, n;

   if(!this->audio_index) { 
       return MP_RESULT_ERROR; 
   }

   if(bytes < 0) 
	   bytes = 0;

   n0 = 0;
   n1 = this->audio_chunks;

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

   this->audio_posc = n0;

   if(this->audio_index[n0].len > 1000) {
	 this->audio_posb = bytes - this->audio_index[n0].tot;
   }
   else {
     this->audio_posb = 0;
   }

   return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::SeekVideo(unsigned int StreamId, long frame)
{
	if(!this->video_index) {
		
		return MP_RESULT_ERROR; 
    }

	if (frame < 0 ) {
		
		frame = 0;
	}
	
   this->video_pos = frame;

   return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::ReSeekAudio(unsigned int StreamId)
{
	double ratio;
	long audio_bytes;

    if(this->GetNumberOfAudioStreams() > 0) {

	  WaitForSingleObject(this->hIOMutex, INFINITE);

      ratio = (double) ((double) this->video_pos / (double) this->video_frames);
      


      audio_bytes  = (long) (ratio * this->audio_bytes);
      audio_bytes  -= (audio_bytes % this->waveformatex.nBlockSize);

      this->SeekAudio(StreamId, audio_bytes);

      ReleaseMutex(this->hIOMutex);
	}

    return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::Seek(unsigned int videoStreamId, unsigned int audioStreamId, int percent)
{
	long frame;
	double ratio;
	long audio_bytes;
  
	WaitForSingleObject(this->hIOMutex, INFINITE);



    frame = (long) (percent * this->video_frames / 100);

 
  
    while(!this->isKeyframe(frame) && frame < this->video_frames) {
      frame++;
    }


	if(frame >= this->video_frames)
		frame = 0;


    
	this->SeekVideo(videoStreamId, frame);


    if(this->GetNumberOfAudioStreams() > 0) {
      
      ratio = (double) ((double) frame / (double) this->video_frames);
      
 

      audio_bytes  = (long) (ratio * this->audio_bytes);
      audio_bytes  -= (audio_bytes % this->waveformatex.nBlockSize);

      this->SeekAudio(audioStreamId, audio_bytes);

      ReleaseMutex(this->hIOMutex);

      return MP_RESULT_OK;
	}

    ReleaseMutex(this->hIOMutex);

	return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::Rewind(unsigned int videoStreamId, unsigned int audioStreamId)
{
	this->video_pos  = 0;
	this->audio_posc = 0;
	this->audio_posb = 0;

	return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::SeekNextKeyFrame(unsigned int StreamId)
{
	WaitForSingleObject(this->hIOMutex, INFINITE);



	this->video_pos++;

	while(!isKeyframe(this->video_pos) && this->video_pos < this->video_frames)
		this->video_pos++;

    ReleaseMutex(this->hIOMutex);

	return MP_RESULT_OK;
}

MP_RESULT     MediaDecapsAVI::SeekPreviousKeyFrame(unsigned int StreamId)
{
	WaitForSingleObject(this->hIOMutex, INFINITE);
	


	if(this->video_pos > 1) {

		this->video_pos--;
		this->video_pos--;
	}

	while(!isKeyframe(this->video_pos) && this->video_pos > 0)
		this->video_pos--;

    ReleaseMutex(this->hIOMutex);

	return MP_RESULT_OK;
}

⌨️ 快捷键说明

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