📄 avistream.cpp
字号:
InputMediaClose=(pInputMediaClose)GetProcAddress(hDLL,_T("InputMediaClose"));
if (!InputMediaOpen(lpFilename, 0, type,2000000,CacheSize))
{
FreeLibrary(hDLL);
hDLL=NULL;
return 0;
}
vidinfo.hIOMutex = CreateMutex (NULL, FALSE, NULL);
viddata.video_pos = 0;
vidinfo.audio_posc = 0;
vidinfo.audio_posb = 0;
vidinfo.idx = NULL;
vidinfo.video_index = NULL;
vidinfo.audio_index = NULL;
if(AVIDecaps_IsAVI()) {
if(AVIDecaps_FillHeader(1)) {
ret= 1;
}
else {
InputMediaSeek(0, INPUT_SEEK_SET);
AVIDecaps_IsAVI();
if(AVIDecaps_FillHeader(0)) {
ret=1;
}
}
}
*vid=&::viddata;
return ret;
}
void GetNextChunkInfo()
{
unsigned long n;
long hdrl_len = 0;
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];
InputMediaSeek(PAD_EVEN(vidinfo.currentchunk.pos+vidinfo.currentchunk.len),INPUT_SEEK_SET);
while(1)
{
if( InputMediaRead(data, 8) != 8 )
{
vidinfo.currentchunk.pos+=vidinfo.currentchunk.len;
vidinfo.currentchunk.len=0;
break;
}
n = str2ulong(data + 4);
/*
* the movi list may contain sub-lists,
* ignore them
*
*/
if(strncmp(data,"LIST", 4) == 0)
{
InputMediaSeek(4, INPUT_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') ) )
{
if(strncmp(data, viddata.audio_tag, 4) == 0)
{
vidinfo.currentchunk.pos = InputMediaSeek(0, INPUT_SEEK_CUR);
vidinfo.currentchunk.len = n;
return;
}
}
InputMediaSeek(PAD_EVEN(n),
INPUT_SEEK_CUR);
}
}
void GetNextFrameInfo()
{
unsigned long n;
long hdrl_len = 0;
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];
InputMediaSeek(PAD_EVEN(vidinfo.currentframe.pos+vidinfo.currentframe.len),INPUT_SEEK_SET);
while(1)
{
if( InputMediaRead(data, 8) != 8 )
break;
n = str2ulong(data + 4);
/*
* the movi list may contain sub-lists,
* ignore them
*
*/
if(strncmp(data,"LIST", 4) == 0)
{
InputMediaSeek(4, INPUT_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') ) )
{
if(strncmp(data, viddata.video_tag, 3) == 0)
{
vidinfo.currentframe.flags = 0;//(BYTE) (str2ulong(data+4) & AVIIF_KEYFRAME)>1;//str2ulong(vidinfo.idx[i]+ 4);
vidinfo.currentframe.pos = InputMediaSeek(0, INPUT_SEEK_CUR);
vidinfo.currentframe.len = n;
return;
}
}
InputMediaSeek(PAD_EVEN(n),
INPUT_SEEK_CUR);
}
}
/*
* Returns the wavefromatex
* associated with the first audio
* stream.
*/
/*
* Reads the next video Frame into
* buffer, return the actual size of
* the frame.
*
*/
AVISTREAM_API int AVIDecaps_NextVideoFrame(char *buffer, int drop)
{
//unsigned int n;
//if(vidinfo.video_pos >= vidinfo.video_frames) {
//
// return -2;
//}
/*
* Request the mutex
* for reading the file;
*/
WaitForSingleObject(vidinfo.hIOMutex, INFINITE);
GetNextFrameInfo();
//n = vidinfo.video_index[vidinfo.video_pos].len;
InputMediaSeek(vidinfo.currentframe.pos, INPUT_SEEK_SET);
InputMediaRead(buffer, vidinfo.currentframe.len);
viddata.video_pos++;
/*
* Release the Mutex.
*/
ReleaseMutex(vidinfo.hIOMutex);
return vidinfo.currentframe.len;
}
/*
* Reads any amount of audio
* data. FIXME : should return
* the actual number read.
*/
AVISTREAM_API int AVIDecaps_ReadAudio(char *audbuf, int bytes)
{
int nr, left = 0, todo;
nr = 0;
/*
* Request the read Mutex
*/
WaitForSingleObject(vidinfo.hIOMutex, INFINITE);
/*
* We loop until we parsed enough
* chunks for the amount we want
*
*/
while(bytes > 0)
{
left = vidinfo.currentchunk.len - vidinfo.audio_posb;
if(!left)
{
//if(vidinfo.audio_posc>=vidinfo.audio_chunks-1)
//{
// ReleaseMutex(vidinfo.hIOMutex);
// return nr;
// }
vidinfo.audio_posc++;
vidinfo.audio_posb = 0;
GetNextChunkInfo();
if (!vidinfo.currentchunk.len)
{
ReleaseMutex(vidinfo.hIOMutex);
return nr;
}
continue;
}
if(bytes<left)
todo = bytes;
else
todo = left;
InputMediaSeek(vidinfo.currentchunk.pos + vidinfo.audio_posb, INPUT_SEEK_SET);
InputMediaRead(audbuf + nr, todo);
bytes -= todo;
nr += todo;
vidinfo.audio_posb += todo;
}
/*
* And release the Mutex.
*/
ReleaseMutex(vidinfo.hIOMutex);
abytes_read+=nr;
return nr;
}
/*
* Return the actual framerate
* FIXME : should be a double...
*
*/
AVISTREAM_API double AVIDecaps_FrameRate()
{
/*
* Fix for some trailers
*/
if(viddata.fps == 0)
viddata.fps = 25;
if(viddata.fps == 23)
viddata.fps = 25;
return (double) viddata.fps;
}
/*
* Seek to a particular
* video frame.
*/
AVISTREAM_API int AVIDecaps_Seek(int percent, int isFrame)
{
long frame;
double ratio;
long audio_bytes;
int look=0;
// double ratio;
char temp[512];
int nShouldbe;
int apos;
WaitForSingleObject(vidinfo.hIOMutex, INFINITE);
/*
* compute the desired
* frame number
*
*/
if (!isFrame)
frame = (long) (percent * viddata.video_frames / 100);
else
frame=percent;
/*
* and go to the next
* keyframe.
*
*/
while(vidinfo.video_index[look+1].flags<frame)
{
look++;
}
frame=vidinfo.video_index[look].flags;
vidinfo.currentframe.len=0;
vidinfo.currentframe.pos=vidinfo.video_index[look].pos-8;
ratio = (double) ((double) frame / (double) viddata.video_frames);
apos = (long) (ratio * (double)viddata.audio_bytes);
look=0;
while(vidinfo.audio_index[look+1].tot<apos)
{
look++;
}
if (look) abytes_read=vidinfo.audio_index[look].tot;
else abytes_read=0;
vidinfo.currentchunk.len=0;
vidinfo.currentchunk.pos=vidinfo.audio_index[look].pos-8;
vidinfo.audio_posb=0;
viddata.video_pos = frame;
/*
* calculate what ratio
* it corresponds to
*
*/
if(vidinfo.audio_strn > 0) {
nShouldbe=0;
while(nShouldbe<viddata.video_pos)
{
AVIDecaps_ReadAudio(temp,512);
nShouldbe=(abytes_read*(__int64)viddata.video_frames)/viddata.audio_bytes+1;
}
ReleaseMutex(vidinfo.hIOMutex);
return viddata.audio_bytes-abytes_read;
}
return 1;
}
AVISTREAM_API int AVIDecaps_ReSeekAudio()
{
double ratio;
char temp[512];
int nShouldbe;
WaitForSingleObject(vidinfo.hIOMutex, INFINITE);
nShouldbe=0;
while(nShouldbe<viddata.video_pos)
{
AVIDecaps_ReadAudio(temp,512);
nShouldbe=(abytes_read*(__int64)viddata.video_frames)/viddata.audio_bytes+1;
}
ReleaseMutex(vidinfo.hIOMutex);
return viddata.audio_bytes-abytes_read;
}
AVISTREAM_API double AVIDecaps_GetProgress()
{
return (double) ((double)(viddata.video_pos))*100.0/((double)viddata.video_frames);
}
AVISTREAM_API int AVIDecaps_Close()
{
if (hDLL)
{
InputMediaClose();
if (vidinfo.video_index) free(vidinfo.video_index);
if (vidinfo.audio_index) free(vidinfo.audio_index);
if (vidinfo.idx) free(vidinfo.idx);
viddata.video_pos=0;
vidinfo.audio_posb=0;
vidinfo.audio_posc=0;
FreeLibrary(hDLL);
hDLL=NULL;
}
return 1;
}
int AVIDecaps_Stop()
{
if (WaitForSingleObject(vidinfo.hIOMutex, 500)==WAIT_TIMEOUT)
AVIDecaps_Close();
else
ReleaseMutex(vidinfo.hIOMutex);
return 1;
}
AVISTREAM_API void InitializeReader(reader* rd)
{
rd->READER_Open=AVIDecaps_Open;
rd->READER_ReadAudio=AVIDecaps_ReadAudio;
rd->READER_NextVideoFrame=AVIDecaps_NextVideoFrame;
rd->READER_Seek=AVIDecaps_Seek;
rd->READER_ReSeekAudio=AVIDecaps_ReSeekAudio;
rd->READER_GetProgress=AVIDecaps_GetProgress;
rd->READER_Close=AVIDecaps_Close;
rd->READER_Stop=AVIDecaps_Stop;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is the constructor of a class that has been exported.
// see AVIStream.h for the class definition
CAVIStream::CAVIStream()
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -