📄 ogmreader.cpp
字号:
int bufferlen;
bool isKey;
result= stream_sampleout(&os[VIDEO_STREAM], sh[VIDEO_STREAM],
(bool*)&eos, &isKey,
&video_reftime,
&temp, &bufferlen);
if(result==0||(result<0&&(result!=-2052)))
{
readpage=1;
}
else if (isKey||(!didseek))
{
ReleaseMutex(thisvid.hIOMutex);
memcpy(buffer,temp,bufferlen);
if (os[VIDEO_STREAM].lastpos>=0) viddata.video_pos=os[VIDEO_STREAM].lastpos;
else
viddata.video_pos++;
return bufferlen;
}
else
{
if (os[VIDEO_STREAM].lastpos>0)
viddata.video_pos=os[VIDEO_STREAM].lastpos;
else
viddata.video_pos++;
}
}
else
readpage=1;
}
ReleaseMutex(thisvid.hIOMutex);
return 0;
}
/*
* Reads any amount of audio
* data. FIXME : should return
* the actual number read.
*/
#define AUDIO_STREAM 1
int AVIDecaps_ReadAudio(char *audbuf, int bytes)
{
static char left[4096];
int eos=0;
int stream=AUDIO_STREAM;
int todo=bytes;
int got=0;
//ogg_int16_t* convbuffer=(ogg_int16_t*) audbuf;
while(!eos)
{
WaitForSingleObject(thisvid.hIOMutex, INFINITE);
if (readpagea)
{
do
{
int result=ogg_sync_pageout(&oy,&og);
readpagea=0;
if(result==0) /* missing or corrupt data at this page position */
{
int readbytes=4096;
char* buff=ogg_sync_buffer(&oy,4096);
readbytes=InputMediaRead(buff, 4096);
if (readbytes==0)
{
ReleaseMutex(thisvid.hIOMutex);
return 0;
}
if (ogg_sync_wrote(&oy,readbytes)==-1)
{
int error=1;
}
readpagea=1;
break;
}
else if (result<0)
{
readpagea=1;
break;
}
stream=ogg_page_serialno(&og);
ogg_stream_pagein(&os[stream].os,&og);
}while(stream!=AUDIO_STREAM);
}
ReleaseMutex(thisvid.hIOMutex);
if (readpagea) continue;
int result=1;
unsigned char* temp;
int bufferlen;
bool key;
if (!sh[1])
{
result=ogg_stream_packetout(&os[AUDIO_STREAM].os,&op);
if(result==0)
{
readpagea=1;
continue; //return NEED_MORE; /* need more data */
}
if(result>=0)
{
/* we have a packet. Decode it */
if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
vorbis_synthesis_blockin(&vd,&vb);
/*
**pcm is a multichannel float vector. In stereo, for
example, pcm[0] is left, and pcm[1] is right. samples is
the size of each channel. Convert the float values
(-1.<=range<=1.) to whatever PCM format and write it out */
while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0)
{
int j;
int i;
for(i=0;i<vi.channels;i++)
{
ogg_int32_t *src=pcm[i];
short *dest=((short *)audbuf)+i;
for(j=0;j<samples;j++)
{
*dest=CLIP_TO_15(src[j]>>9);
dest+=vi.channels;
}
}
vorbis_synthesis_read(&vd,samples);
got+=2*vi.channels*samples;
audbuf+=2*vi.channels*samples;
if (got>=2000)
{
if (op.granulepos!=-1)
{
audio_reftime=mediatime_to_reference_time(SEC_IN_REFTIME, vi.rate, op.granulepos);
lastpos=op.granulepos;
if (lastpos==0) lastpos=1;
}
else if (lastpos)
{
lastpos+=samples;
audio_reftime=mediatime_to_reference_time(SEC_IN_REFTIME, vi.rate, lastpos);
}
return got;
}
}
}
if(result==0)
{
readpagea=1;
}
}
else
{
while(todo)
{
if (leftover)
{
if (leftover<=todo)
{
memcpy(audbuf,left,leftover);
audbuf+=leftover;
todo-=leftover;
leftover=0;
}
else
{
memcpy(audbuf,left,todo);
leftover-=todo;
memmove(left,left+todo,leftover);
return bytes;
}
}
result= stream_sampleout(&os[AUDIO_STREAM], sh[AUDIO_STREAM],
(bool*)&eos, &key,
&audio_reftime,
&temp, &bufferlen);
if(result==0)
{
readpagea=1;
break;
}
else
{
if (bufferlen<todo)
{
memcpy(audbuf,temp,bufferlen);
audbuf+=bufferlen;
todo-=bufferlen;
}
else
{
memcpy(left,temp+todo,bufferlen-todo);
leftover=bufferlen-todo;
memcpy(audbuf,temp,todo);
todo=0;
return bytes;
}
}
}
}
}
ReleaseMutex(thisvid.hIOMutex);
return 0;
}
double AVIDecaps_FrameRate()
{
return (double) viddata.fps;
}
int AVIDecaps_AudioSeek(long bytes)
{
return 0;
}
BOOL AVIDecaps_isKeyframe(long frame)
{
return true;
}
char onebuff[8192];
int AVIDecaps_Seek(int percent, int isFrame)
{
__int64 audio_bytes,bytes;
WaitForSingleObject(thisvid.hIOMutex, INFINITE);
begin:
if (!isFrame)
{
bytes = (__int64) (((__int64)percent) * fsize)/100;
}
else
{
double fperc=((double)percent)/((double)viddata.video_frames);
bytes = (__int64) (fperc * ((double)fsize));
}
InputMediaSeek(bytes,SEEK_SET);
ogg_sync_clear(&oy);
stream_state_reset(&os[0]);
stream_state_reset(&os[1]);
readpage=readpagea=1;
lastpos=0;
if (percent==0)
{
video_reftime=0;
audio_reftime=0;
ReleaseMutex(thisvid.hIOMutex);
viddata.video_pos=0;
didseek=0;
oneframelen=0;
return viddata.audio_bytes;
}
video_reftime=-1;
audio_reftime=-1;
didseek=1;
oneframelen=0;
while(video_reftime<0)
{
oneframelen=AVIDecaps_NextVideoFrame(oneframe,0);
if (oneframelen<0)
{
percent=0;
goto begin;
}
}
if (gotaudio>0)
{
while(audio_reftime<0)
{
if (!AVIDecaps_ReadAudio(onebuff,4096))
{
percent=0;
goto begin;
}
}
while (audio_reftime> video_reftime)
{
oneframelen=AVIDecaps_NextVideoFrame(oneframe,0);
if (oneframelen<0)
{
percent=0;
goto begin;
}
}
while (audio_reftime< video_reftime)
{
if (!AVIDecaps_ReadAudio(onebuff,1024))
{
percent=0;
goto begin;
}
}
}
didseek=0;
ReleaseMutex(thisvid.hIOMutex);
if (!sh[1])
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)viddata.a_rate*viddata.a_chans*2;
}
else
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)sh[1]->audio.avgbytespersec;
}
return audio_bytes;
}
int AVIDecaps_SeekChapter(int Chapter)
{
double h,m,s;
int shouldbeframe;
char t[4];
__int64 audio_bytes,bytes;
double percent;
WaitForSingleObject(thisvid.hIOMutex, INFINITE);
begin:
int start=0;
#if (_WIN32_WCE >= 300)
while (_strnicmp(vcv.user_comments[start],"CHAPTER",7)) start++;
#else
while (strncmp(vcv.user_comments[start],"CHAPTER",7)) start++;
#endif
strncpy(t,vcv.user_comments[Chapter*2+start]+10,2);
t[2]=0;
h=atoi(t);
strncpy(t,vcv.user_comments[Chapter*2+start]+13,2);
t[2]=0;
m=atoi(t);
strncpy(t,vcv.user_comments[Chapter*2+start]+16,2);
t[2]=0;
s=atoi(t);
s=(h*3600)+(m*60)+s;
percent=(double)(s*viddata.fps)/(double)(viddata.video_frames);
shouldbeframe=(s*viddata.fps);
repeat:
bytes = (__int64) (percent * (double)fsize);
InputMediaSeek(bytes,SEEK_SET);
ogg_sync_clear(&oy);
stream_state_reset(&os[0]);
stream_state_reset(&os[1]);
readpage=readpagea=1;
lastpos=0;
if (percent==0)
{
video_reftime=0;
audio_reftime=0;
ReleaseMutex(thisvid.hIOMutex);
viddata.video_pos=0;
didseek=0;
oneframelen=0;
return viddata.audio_bytes;
}
video_reftime=-1;
audio_reftime=-1;
didseek=1;
oneframelen=0;
do
{
oneframelen=AVIDecaps_NextVideoFrame(oneframe,0);
if (oneframelen<0)
{
percent=0;
goto begin;
}
}while(video_reftime<0||(viddata.video_pos<shouldbeframe));
if (viddata.video_pos>(shouldbeframe+viddata.fps))
{
percent-=.01;
goto repeat;
}
if (gotaudio>0)
{
while(audio_reftime<0)
{
if (!AVIDecaps_ReadAudio(onebuff,4096))
{
percent=0;
goto begin;
}
}
while (audio_reftime> video_reftime)
{
oneframelen=AVIDecaps_NextVideoFrame(oneframe,0);
if (oneframelen<0)
{
percent=0;
goto begin;
}
}
while (audio_reftime< video_reftime)
{
if (!AVIDecaps_ReadAudio(onebuff,1024))
{
percent=0;
goto begin;
}
}
}
didseek=0;
ReleaseMutex(thisvid.hIOMutex);
if (!sh[1])
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)viddata.a_rate*viddata.a_chans*2;
}
else
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)sh[1]->audio.avgbytespersec;
}
return audio_bytes;
}
int AVIDecaps_ReSeekAudio()
{
__int64 audio_bytes;
WaitForSingleObject(thisvid.hIOMutex, INFINITE);
while(audio_reftime<0)
{
if (!AVIDecaps_ReadAudio(onebuff,4096))
{
ReleaseMutex(thisvid.hIOMutex);
return 0;
}
}
while (audio_reftime< video_reftime)
{
if (!AVIDecaps_ReadAudio(onebuff,1024))
{
ReleaseMutex(thisvid.hIOMutex);
return 0;
}
}
ReleaseMutex(thisvid.hIOMutex);
if (!sh[1])
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)viddata.a_rate*viddata.a_chans*2;
}
else
{
audio_bytes=((double)((double)(viddata.video_frames-viddata.video_pos))/viddata.fps)*(double)sh[1]->audio.avgbytespersec;
}
return audio_bytes;
}
double AVIDecaps_GetProgress()
{
return (double) ((double)(viddata.video_pos))*100.0/((double)viddata.video_frames);
}
int AVIDecaps_Close()
{
ogg_stream_clear(&os[0].os);
ogg_stream_clear(&os[1].os);
/* ogg_page and ogg_packet structs always point to storage in
libvorbis. They're never freed or manipulated directly */
vorbis_block_clear(&vb);
vorbis_dsp_clear(&vd);
vorbis_comment_clear(&vc);
vorbis_info_clear(&vi); /* must be called last */
ogg_sync_clear(&oy);
if (hDLL)
{
InputMediaClose();
FreeLibrary(hDLL);
hDLL=NULL;
}
return 1;
}
int AVIDecaps_Stop()
{
if (WaitForSingleObject(thisvid.hIOMutex, 500)==WAIT_TIMEOUT)
AVIDecaps_Close();
else
ReleaseMutex(thisvid.hIOMutex);
return 1;
}
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_isKeyFrame=AVIDecaps_isKeyframe;
rd->READER_SeekChapter=AVIDecaps_SeekChapter;
rd->READER_Stop=AVIDecaps_Stop;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -