예제 #1
0
void AviRecorder::Stop()
{
	m_fAudioReady = false;

	if (m_pstmVideo != NULL) {
		AVIStreamClose(m_pstmVideo);
		m_pstmVideo = NULL;
	}

	if (m_pstmAudio != NULL) {
		AVIStreamClose(m_pstmAudio);
		m_pstmAudio = NULL;
	}

	if (m_pavif != NULL) {
		AVIFileClose(m_pavif);
		m_pavif = NULL;
	}

	AVIFileExit();

	m_nSample = 0;
	delete m_pbmFlip;
	m_pbmFlip = NULL;
	delete m_ptbmPointer;
	m_ptbmPointer = NULL;
}
예제 #2
0
void plAVIWriterImp::Close()
{
    plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());

#if HS_BUILD_FOR_WIN32
    hsTimer::SetRealTime(fOldRealTime);

    if (fStreamHandle)
    {
        AVIStreamClose(fStreamHandle);
        fStreamHandle = nil;
    }

    if (fCompressedHandle)
    {
        AVIStreamClose(fCompressedHandle);
        fCompressedHandle = nil;
    }

    if (fFileHandle)
    {
        AVIFileClose(fFileHandle);
        fFileHandle = nil;
    }

    AVIFileExit();
#endif
}
예제 #3
0
static void clean_up(AVIFile* _avi)
{
	AVIFile& avi = *_avi;

	if(avi.sound_added)
	{
		if(avi.compressed_streams[AUDIO_STREAM])
		{
			AVIStreamClose(avi.compressed_streams[AUDIO_STREAM]);
			avi.compressed_streams[AUDIO_STREAM] = NULL;
			avi.streams[AUDIO_STREAM] = NULL;				// compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM]
		}
	}

	if(avi.video_added)
	{
		if(avi.compressed_streams[VIDEO_STREAM])
		{
			AVIStreamClose(avi.compressed_streams[VIDEO_STREAM]);
			avi.compressed_streams[VIDEO_STREAM] = NULL;
		}

		if(avi.streams[VIDEO_STREAM])
		{
			AVIStreamClose(avi.streams[VIDEO_STREAM]);
			avi.streams[VIDEO_STREAM] = NULL;
		}
	}

	if(avi.avi_file)
	{
		AVIFileClose(avi.avi_file);
		avi.avi_file = NULL;
	}
}
예제 #4
0
void MovieMaker::EndCapture()
{
    fprintf( stderr, "\n" );
	if (ps)
        {
		AVIStreamClose(ps);
        ps = NULL;
        }

	if (psCompressed)
        {
		AVIStreamClose(psCompressed);
        psCompressed = NULL;
        }

	if (psText)
        {
		AVIStreamClose(psText);
        psText = NULL;
        }

	if (pfile)
        {
		AVIFileClose(pfile);
        pfile = NULL;
        }

	WORD wVer = HIWORD(VideoForWindowsVersion());
	if (wVer >= 0x010A)
	    {
		AVIFileExit();
	    }

}
예제 #5
0
파일: aviout.cpp 프로젝트: Plombo/fceux
static void avi_destroy(struct AVIFile** avi_out)
{
	if(!(*avi_out))
		return;

	if((*avi_out)->sound_added)
	{
		if((*avi_out)->compressed_streams[AUDIO_STREAM])
		{
			if ((*avi_out)->audio_buffer_pos > 0) {
				if(FAILED(AVIStreamWrite(avi_file->compressed_streams[AUDIO_STREAM],
				                         avi_file->sound_samples, (*avi_out)->audio_buffer_pos / (*avi_out)->wave_format.nBlockAlign,
				                         (*avi_out)->audio_buffer, (*avi_out)->audio_buffer_pos, 0, NULL, &avi_file->ByteBuffer)))
				{
					avi_file->valid = 0;
				}
				(*avi_out)->sound_samples += (*avi_out)->audio_buffer_pos / (*avi_out)->wave_format.nBlockAlign;
				(*avi_out)->tBytes += avi_file->ByteBuffer;
				(*avi_out)->audio_buffer_pos = 0;
			}

			LONG test = AVIStreamClose((*avi_out)->compressed_streams[AUDIO_STREAM]);
			(*avi_out)->compressed_streams[AUDIO_STREAM] = NULL;
			(*avi_out)->streams[AUDIO_STREAM] = NULL;				// compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM]
		}
	}

	if((*avi_out)->video_added)
	{
		if((*avi_out)->compressed_streams[VIDEO_STREAM])
		{
			AVIStreamClose((*avi_out)->compressed_streams[VIDEO_STREAM]);
			(*avi_out)->compressed_streams[VIDEO_STREAM] = NULL;
		}

		if((*avi_out)->streams[VIDEO_STREAM])
		{
			AVIStreamClose((*avi_out)->streams[VIDEO_STREAM]);
			(*avi_out)->streams[VIDEO_STREAM] = NULL;
		}
	}

	if((*avi_out)->avi_file)
	{
		AVIFileClose((*avi_out)->avi_file);
		(*avi_out)->avi_file = NULL;
	}

	free((*avi_out)->convert_buffer);
	free(*avi_out);
	*avi_out = NULL;
}
예제 #6
0
AVIWrite::~AVIWrite()
{
  if(m_streamSound)
    AVIStreamClose(m_streamSound);

  if(m_streamCompressed)
    AVIStreamClose(m_streamCompressed);
  
  if(m_stream)
    AVIStreamClose(m_stream);

  if(m_file)
    AVIFileClose(m_file);

  AVIFileExit();
}
예제 #7
0
void CMainFrame::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	capCaptureAbort(m_hWndCap);
	capDriverDisconnect(m_hWndCap);
	Sleep(100);
	capSetCallbackOnError(m_hWndCap,NULL);
	capSetCallbackOnStatus(m_hWndCap,NULL);
	capSetCallbackOnVideoStream(m_hWndCap,NULL);
	delete lpbiIn;
	delete lpbiTmp;
	delete lpbiOut;
	if (m_vfwState==ENCDEC){
		ICDecompressEnd(hic2);
		ICClose(hic2);
		ICSeqCompressFrameEnd(&pc);
		ICCompressEnd(hic1);
		ICClose(hic1);
		AVIStreamClose(ps);
		if(m_pFile != NULL)
			AVIFileRelease(m_pFile);
	}

	enc_stop();
	dec_stop();

	Sleep(100);
	CFrameWnd::OnClose();
}
예제 #8
0
static void clean_up(AVIFile* _avi)
{
	AVIFile& avi = *_avi;

	if(avi.sound_added)
	{
		if(avi.compressed_streams[AUDIO_STREAM])
		{
			if (avi.audio_buffer_pos > 0) {
				if(FAILED(AVIStreamWrite(avi.compressed_streams[AUDIO_STREAM],
				                         avi.sound_samples, avi.audio_buffer_pos / avi.wave_format.nBlockAlign,
				                         avi.audio_buffer, avi.audio_buffer_pos, 0, NULL, &avi.ByteBuffer)))
				{
					avi.valid = false;
				}
				avi.sound_samples += avi.audio_buffer_pos / avi.wave_format.nBlockAlign;
				avi.tBytes += avi.ByteBuffer;
				avi.audio_buffer_pos = 0;
			}

			AVIStreamClose(avi.compressed_streams[AUDIO_STREAM]);
			avi.compressed_streams[AUDIO_STREAM] = NULL;
			avi.streams[AUDIO_STREAM] = NULL;				// compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM]
		}
	}

	if(avi.video_added)
	{
		if(avi.compressed_streams[VIDEO_STREAM])
		{
			AVIStreamClose(avi.compressed_streams[VIDEO_STREAM]);
			avi.compressed_streams[VIDEO_STREAM] = NULL;
		}

		if(avi.streams[VIDEO_STREAM])
		{
			AVIStreamClose(avi.streams[VIDEO_STREAM]);
			avi.streams[VIDEO_STREAM] = NULL;
		}
	}

	if(avi.avi_file)
	{
		AVIFileClose(avi.avi_file);
		avi.avi_file = NULL;
	}
}
예제 #9
0
CAVIFile::~CAVIFile()
{
  if (ps)
    AVIStreamClose(ps);
  
  if (psCompressed)
    AVIStreamClose(psCompressed);

  if(psound)
    AVIStreamClose(psound);

  if (pfile)
    AVIFileClose(pfile);

  WORD wVer = HIWORD(VideoForWindowsVersion());
  if (wVer >= 0x010A) {
    AVIFileExit();
  }
}
예제 #10
0
// --[  Method  ]---------------------------------------------------------------
//
//  - Class     : CAviRenderer
//  - prototype : bool StopRender()
//
//  - Purpose   : Stops capturing and closes the file.
//
// -----------------------------------------------------------------------------
bool CAviRenderer::StopRender()
{
	// Close/free stuff

	if(m_pAviStream)
	{
		AVIStreamClose(m_pAviStream);
		m_pAviStream = NULL;
	}

	if(m_pAviStreamCompressed)
	{
		AVIStreamClose(m_pAviStreamCompressed);
		m_pAviStreamCompressed = NULL;
	}

	if(m_pAviText)
	{
		AVIStreamClose(m_pAviText);
		m_pAviText = NULL;
	}

	if(m_pAviFile)
	{
		AVIFileClose(m_pAviFile);
		m_pAviFile = NULL;
	}

	WORD wVer = HIWORD(VideoForWindowsVersion());

	if(wVer >= 0x010A)
	{
		AVIFileExit();
	}

	m_bIsWorking = false;
	m_pWindowGL  = NULL;

	return true;
}
예제 #11
0
void AVIDump::Stop()
{
	// store one copy of the last video frame, CFR case
	if (s_stream_compressed)
		AVIStreamWrite(s_stream_compressed, s_frame_count++, 1, GetFrame(), s_bitmap.biSizeImage, AVIIF_KEYFRAME, nullptr, &s_byte_buffer);
	
	//Dragonbane:: Dump 5 seconds of the same frame for readability
	if (Movie::cmp_justFinished || Movie::cmp_rightFinished && Movie::cmp_leftFinished || (Movie::cmp_rightFinished || Movie::cmp_leftFinished) && Movie::cmp_movieFinished && !Movie::GetNextComparisonMovie(false))
	{
		Movie::cmp_justFinished = false;

		if (s_stream && s_stream_compressed)
		{
			int endFrames = s_frame_rate * 5;
			for (int i = 0; i < endFrames - 1; i++)
			{
				AVIStreamWrite(s_stream, s_frame_count++, 1, nullptr, 0, 0, nullptr, nullptr);
			}
			AVIStreamWrite(s_stream_compressed, s_frame_count++, 1, GetFrame(), s_bitmap.biSizeImage, AVIIF_KEYFRAME, nullptr, &s_byte_buffer);
		}
	}
	
	s_start_dumping = false;
	CloseFile();
	s_file_count = 0;

	//Dragonbane
	if (s_getFrame_temp)
	{
		AVIStreamGetFrameClose(s_getFrame_temp);
		s_getFrame_temp = nullptr;
	}

	if (s_stream_temp)
	{
		AVIStreamClose(s_stream_temp);
		s_stream_temp = nullptr;
	}

	if (s_file_temp)
	{
		AVIFileRelease(s_file_temp);
		s_file_temp = nullptr;

		std::string movie_file_name = GetCurrDumpFile(tempFileCount, true);

		if (File::Exists(movie_file_name))
			File::Delete(movie_file_name);
	}

	NOTICE_LOG(VIDEO, "Stop");
}
예제 #12
0
void AVIDump::CloseFile()
{
	if (m_streamCompressed)
	{
		AVIStreamClose(m_streamCompressed);
		m_streamCompressed = nullptr;
	}

	if (m_stream)
	{
		AVIStreamClose(m_stream);
		m_stream = nullptr;
	}

	if (m_file)
	{
		AVIFileRelease(m_file);
		m_file = nullptr;
	}

	AVIFileExit();
}
예제 #13
0
파일: MovieMaker.cpp 프로젝트: jrco/nau
MovieMaker::~MovieMaker()
{
  //Close the file and stream if opened
  if(ps)
  {
    AVIStreamClose(ps);
  }
  if (psCompressed)
  {
    AVIStreamClose(psCompressed);
  }
  if(pfile)
  {
    AVIFileClose(pfile);
  }

  //Close the AVI system if it was opened
  if(aviSysOpen)
  {
    AVIFileExit();
  }
}
예제 #14
0
MovieMaker::~MovieMaker()
{
	if (ps)
		AVIStreamClose(ps);

	if (psCompressed)
		AVIStreamClose(psCompressed);

	if (psText)
		AVIStreamClose(psText);

	if (pfile)
        {
		AVIFileClose(pfile);
        }

	WORD wVer = HIWORD(VideoForWindowsVersion());
	if (wVer >= 0x010A)
	    {
		AVIFileExit();
	    }
}
예제 #15
0
static void avi_destroy(struct AVIFile** avi_out)
{
	if(!(*avi_out))
		return;

	if((*avi_out)->sound_added)
	{
		if((*avi_out)->compressed_streams[AUDIO_STREAM])
		{
			LONG test = AVIStreamClose((*avi_out)->compressed_streams[AUDIO_STREAM]);
			(*avi_out)->compressed_streams[AUDIO_STREAM] = NULL;
			(*avi_out)->streams[AUDIO_STREAM] = NULL;				// compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM]
		}
	}

	if((*avi_out)->video_added)
	{
		if((*avi_out)->compressed_streams[VIDEO_STREAM])
		{
			AVIStreamClose((*avi_out)->compressed_streams[VIDEO_STREAM]);
			(*avi_out)->compressed_streams[VIDEO_STREAM] = NULL;
		}

		if((*avi_out)->streams[VIDEO_STREAM])
		{
			AVIStreamClose((*avi_out)->streams[VIDEO_STREAM]);
			(*avi_out)->streams[VIDEO_STREAM] = NULL;
		}
	}

	if((*avi_out)->avi_file)
	{
		AVIFileClose((*avi_out)->avi_file);
		(*avi_out)->avi_file = NULL;
	}

	free(*avi_out);
	*avi_out = NULL;
}
예제 #16
0
void aviClose()
{
    if (aviSndStream != NULL) {
        AVIStreamClose(aviSndStream);
        aviSndStream = NULL;
    }

    if (aviVidStream != NULL) {
        AVIStreamClose(aviVidStream);
        aviVidStream = NULL;
    }

    if (aviStream != NULL) {
        AVIStreamClose(aviStream);
        aviStream = NULL;
    }

    if (aviFile != NULL) {
        AVIFileClose(aviFile);
        aviFile = NULL;
    }

    AVIFileExit();
}
예제 #17
0
void AVIDump::StoreFrame(const void* data)
{
	if (s_bitmap.biSizeImage > s_stored_frame_size)
	{
		void* temp_stored_frame = realloc(s_stored_frame, s_bitmap.biSizeImage);
		if (temp_stored_frame)
		{
			s_stored_frame = temp_stored_frame;
		}
		else
		{
			free(s_stored_frame);
			PanicAlertT("Something has gone seriously wrong.\n"
			            "Stopping video recording.\n"
			            "Your video will likely be broken.");
			Stop();
		}
		s_stored_frame_size = s_bitmap.biSizeImage;
		memset(s_stored_frame, 0, s_bitmap.biSizeImage);
	}
	if (s_stored_frame)
	{
		//PanicAlertT("Width: %i, Height: %i, Bit Count: %i", s_bitmap.biWidth, s_bitmap.biHeight, s_bitmap.biBitCount);

		if (data && (s_file_count || !Movie::cmp_isRunning || s_frame_count > 0))
		{
			bool lastSide = false, readOnly = false;

			if (Movie::cmp_isRunning && (Movie::cmp_leftFinished || Movie::cmp_rightFinished))
				lastSide = true;

			if (lastSide && Movie::cmp_startTimerFrame > Movie::cmp_curentBranchFrame) //Dragonbane: Combine frames
				readOnly = true;
			else
				readOnly = false;


			if (readOnly && s_getFrame_temp)
			{
				size_t totalBytes = s_bitmap.biSizeImage / 2;
				size_t rowSize = (s_bitmap.biWidth * (s_bitmap.biBitCount / 8)) / 2;
				size_t currentByte = 0;

				if (s_last_key_temp < 2)
				{
					BOOL result = AVIStreamIsKeyFrame(s_stream_temp, s_last_key_temp);

					if (!result)
						s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp);
				}

				u64 samplePos = AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY);

				u64 s_last_key_old = s_last_key_temp;

				s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp);

				void* s_uncompressed_frame = AVIStreamGetFrame(s_getFrame_temp, samplePos);
				std::string movie_file_name;

				if (!s_uncompressed_frame || s_stopTempFile)
				{
					//Close current file
					if (s_getFrame_temp)
					{
						AVIStreamGetFrameClose(s_getFrame_temp);
						s_getFrame_temp = nullptr;
					}

					if (s_stream_temp)
					{
						AVIStreamClose(s_stream_temp);
						s_stream_temp = nullptr;
					}

					if (s_file_temp)
					{
						AVIFileRelease(s_file_temp);
						s_file_temp = nullptr;

						movie_file_name = GetCurrDumpFile(tempFileCount, true);

						if (File::Exists(movie_file_name))
							File::Delete(movie_file_name);
					}

					//Check if we have another temp file
					tempFileCount++;
					s_stopTempFile = false;

					movie_file_name = GetCurrDumpFile(tempFileCount, true);

					if (File::Exists(movie_file_name)) //Dragonbane: Open temp file for reading
					{
						HRESULT h2 = AVIFileOpenA(&s_file_temp, movie_file_name.c_str(), OF_READ, nullptr);
						HRESULT h3 = AVIFileGetStream(s_file_temp, &s_stream_temp, streamtypeVIDEO, 0);

						s_last_key_temp = 0; //Not the first file anymore, so start from keyframe 0

						s_getFrame_temp = AVIStreamGetFrameOpen(s_stream_temp, &s_bitmap);

						if (!s_getFrame_temp)
						{
							PanicAlertT("Your chosen compression codec can not be decompressed again! Can't continue video comparison!");
							Movie::CancelComparison();
							return;
						}

						BOOL result = AVIStreamIsKeyFrame(s_stream_temp, s_last_key_temp);

						if (!result)
							s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp);

						samplePos = AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY);

						s_last_key_old = s_last_key_temp;

						s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp);

						s_uncompressed_frame = AVIStreamGetFrame(s_getFrame_temp, samplePos);

						if (!s_uncompressed_frame)
						{
							//PanicAlertT("Last frame stored. Start timer now!");
							Movie::cmp_startTimerFrame = Movie::cmp_curentBranchFrame;
							memcpy(s_stored_frame, data, s_bitmap.biSizeImage);
							return;
						}
					}
					else
					{
						//PanicAlertT("Last frame stored. Start timer now!");
						Movie::cmp_startTimerFrame = Movie::cmp_curentBranchFrame;
						memcpy(s_stored_frame, data, s_bitmap.biSizeImage);
						return;
					}
				}

				//Stop temp file on next frame if last frame is processed
				if (s_last_key_old == s_last_key_temp || AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY) == samplePos)
					s_stopTempFile = true;


				void* memptr1 = s_uncompressed_frame;
				memptr1 = static_cast<u8*>(memptr1) + sizeof(BITMAPINFOHEADER);

				if (Movie::cmp_leftFinished)
				{
					memcpy(s_stored_frame, memptr1, s_bitmap.biSizeImage);

					for (u64 currentRow = 0; currentRow < s_bitmap.biHeight; currentRow++)
					{
						currentByte += rowSize;

						void* memptr = s_stored_frame;
						const void* memptr2 = data;

						memptr = static_cast<u8*>(memptr) + currentByte;
						memptr2 = static_cast<const u8*>(memptr2) + currentByte;

						memcpy(memptr, memptr2, rowSize);

						currentByte += rowSize;
					}
				}
				else if (Movie::cmp_rightFinished)
				{
					memcpy(s_stored_frame, memptr1, s_bitmap.biSizeImage);

					//BITMAPINFOHEADER test;
					//memset(&test, 0, sizeof(BITMAPINFOHEADER));
					//memcpy(&test, s_uncompressed_frame, sizeof(BITMAPINFOHEADER));

					for (u64 currentRow = 0; currentRow < s_bitmap.biHeight; currentRow++)
					{
						void* memptr = s_stored_frame;
						const void* memptr2 = data;

						memptr = static_cast<u8*>(memptr) + currentByte;
						memptr2 = static_cast<const u8*>(memptr2) + currentByte;

						memcpy(memptr, memptr2, rowSize);

						currentByte += rowSize * 2;
					}
				}
				else
				{
					memcpy(s_stored_frame, data, s_bitmap.biSizeImage);
				}
			}
			else
			{
				memcpy(s_stored_frame, data, s_bitmap.biSizeImage);
			}
		}
		else // pitch black frame
		{
			memset(s_stored_frame, 0, s_bitmap.biSizeImage);
		}
	}
}
예제 #18
0
void CAviHelper::BMPtoAVI(const wstring& szAVIName, const wstring& strBDir)
{
	CFileFind finder;
	CString strBmpDir;
	strBmpDir.Format(_T("%s\\*.*"), strBDir.c_str()); 
	AVIFileInit(); 
	AVISTREAMINFO strhdr;
	PAVIFILE pfile;
	PAVISTREAM ps; 
	int nFrames =0; 
	HRESULT hr; 
	BOOL bFind = finder.FindFile(strBmpDir);
	while(bFind)
	{
		bFind = finder.FindNextFile();
		if(!finder.IsDots() && !finder.IsDirectory())
		{
			CString str = finder.GetFilePath();
			FILE *fp = _tfopen(str, _T("rb"));
			
			BITMAPFILEHEADER bmpFileHdr;
			BITMAPINFOHEADER bmpInfoHdr;
			fseek( fp,0,SEEK_SET);
			fread(&bmpFileHdr,sizeof(BITMAPFILEHEADER),1, fp);
			fread(&bmpInfoHdr,sizeof(BITMAPINFOHEADER),1, fp);
			BYTE *tmp_buf = NULL;
			if(nFrames ==0 )
			{
			
				AVIFileOpen(&pfile, WS2S(szAVIName).c_str(), OF_WRITE | OF_CREATE,NULL);
				memset(&strhdr, 0, sizeof(strhdr));
				strhdr.fccType = streamtypeVIDEO;// stream type
				strhdr.fccHandler = 0;
				strhdr.dwScale = 1;
				strhdr.dwRate = 15; // 15 fps
				strhdr.dwSuggestedBufferSize = bmpInfoHdr.biSizeImage ;
				SetRect(&strhdr.rcFrame, 0, 0, bmpInfoHdr.biWidth, bmpInfoHdr.biHeight);
				
				// And create the stream;
				hr = AVIFileCreateStream(pfile,&ps,&strhdr); 
				// hr = AVIStreamSetFormat(ps,nFrames,&bmpInfoHdr,sizeof(bmpInfoHdr));
			}
			
			tmp_buf = new BYTE[bmpInfoHdr.biWidth * bmpInfoHdr.biHeight * 3];
			fread(tmp_buf, 1, bmpInfoHdr.biWidth * bmpInfoHdr.biHeight * 3, fp);
			hr = AVIStreamSetFormat(ps,nFrames,&bmpInfoHdr,sizeof(bmpInfoHdr));
			hr = AVIStreamWrite(ps, // stream pointer
				nFrames , // time of this frame
				1, // number to write
				(LPBYTE) tmp_buf,
				bmpInfoHdr.biSizeImage , // size of this frame
				AVIIF_KEYFRAME, // flags....
				NULL,
				NULL);
			nFrames ++; 
			fclose(fp);
		}
	}
	
	AVIStreamClose(ps);
	if(pfile != NULL)
		AVIFileRelease(pfile);
	AVIFileExit();
}
예제 #19
0
	bool setupAudio()
	{
		int ret;


		//read audio stream info; specifically, we need the encoded chunksize
		AVISTREAMINFO audioStreamInfo;
		AVIStreamInfo(audioStream,&audioStreamInfo,sizeof(AVISTREAMINFO));
		audioChunkSize = audioStreamInfo.dwSuggestedBufferSize;
		audioSampleCount = audioStreamInfo.dwLength;

		audioEncoded = new char[audioChunkSize];

		//read the audio streamformat info
		LONG formatSize;
		AVIStreamReadFormat(audioStream,AVIStreamStart(audioStream),0,&formatSize);
		char *format = (char *)malloc(formatSize);
		AVIStreamReadFormat(audioStream,AVIStreamStart(audioStream),format,&formatSize);
		WAVEFORMATEX *wfxEncoded = (WAVEFORMATEX *)format;

		//construct a descriptor for the format we desire to get out of the decoder
		//note that we have to use the same samplerate as the encoded format indicates
		//since acm can't change the samplerate in one fell swoop
		wfxDecoded.cbSize = sizeof(WAVEFORMATEX);
		wfxDecoded.nChannels = wfxEncoded->nChannels;
		wfxDecoded.wFormatTag = WAVE_FORMAT_PCM;
		wfxDecoded.nSamplesPerSec = wfxEncoded->nSamplesPerSec;
		wfxDecoded.wBitsPerSample = 16;
		wfxDecoded.nBlockAlign = wfxDecoded.wBitsPerSample/8 * wfxEncoded->nChannels;
		wfxDecoded.nAvgBytesPerSec = wfxDecoded.nBlockAlign * wfxDecoded.nSamplesPerSec;

		sampleSize = wfxDecoded.nBlockAlign;

		//try to get a converter from the encoded data to the decoded data
		ret = acmStreamOpen(&acmStream,0,wfxEncoded,&wfxDecoded,0,0,0,0);

		//now we're done with wfxEncoded
		free(format);

		if(ret)
		{
			delete[] audioEncoded;
			AVIStreamClose(audioStream);
			return false;
		}


		//decide on a playback buffer size
		//make each buffer 1/2sec
		playBufferSamples = wfxDecoded.nSamplesPerSec / 2;
		playBufferSize = playBufferSamples * sampleSize;


		//hurry and try to create the output stream.
		//if we can't do that, then everything that follows is pointless.
		int mode = 0;
		if(wfxDecoded.wBitsPerSample == 8)
			mode |= FSOUND_8BITS;
		else if(wfxDecoded.wBitsPerSample == 16)
			mode |= FSOUND_16BITS;
		if(wfxDecoded.nChannels == 1)
			mode |= FSOUND_MONO;
		else
			mode |= FSOUND_STEREO;

		#ifdef SND_USE_FMOD
		fmod_stream = FSOUND_Stream_Create(win_movie_fmod_streamCallback,playBufferSize,mode,wfxDecoded.nSamplesPerSec,(int)this);
		if(!fmod_stream)
		{
			acmStreamClose(acmStream,0);
			delete[] audioEncoded;
			AVIStreamClose(audioStream);
			err("Error creating fmod stream for movieplayback.  Please report this case so we can improve the robustness of the movie player!");
			return false;
		}
		#endif


		//find out how large a decode buffer we need for the encode buffer chunksize
		acmStreamSize(acmStream,audioChunkSize,&decodeBufferSize,ACM_STREAMSIZEF_SOURCE);
		decodeBufferSamples = decodeBufferSize / sampleSize;


		//allocate the decode buffer
		audioDecoded = new char[decodeBufferSize];

		//prep the decode operation
		audioStreamHeader.cbStruct = sizeof(ACMSTREAMHEADER);
		audioStreamHeader.fdwStatus = 0;
		audioStreamHeader.pbSrc = (LPBYTE)audioEncoded;
		audioStreamHeader.cbSrcLength = audioChunkSize;
		audioStreamHeader.pbDst = (LPBYTE)audioDecoded;
		audioStreamHeader.cbDstLength = decodeBufferSize;
		ret = acmStreamPrepareHeader(acmStream,&audioStreamHeader,0);
		if(ret)
		{
			delete[] audioDecoded;
			acmStreamClose(acmStream,0);
			delete[] audioEncoded;
			AVIStreamClose(audioStream);
			return false;
		}

		#ifdef SND_USE_FMOD
		//finally we're ready to start the audio stream
		FSOUND_Stream_Play(FSOUND_FREE,fmod_stream);
		#endif

		return true;
	}