📄 ogmreader.cpp
字号:
/***************************************************************************************
*This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
****************************************************************************************
* Authors: *
* Marc Dukette *
**************************************************************************************/
#include "OGMReader.h"
#include "OGGStream.h"
//#include "../ogglib/lib/vorbis_codec.h"
#include "../ogglib/lib/ogg.h"
#include "../ogglib/lib/ivorbiscodec.h"
#include "../ogglib/lib/misc.h"
int CacheSize;
videoinfo viddata;
ogminfo thisvid;
typedef int (CALLBACK* pInputMediaRead)(char *data, unsigned int size);
typedef int (CALLBACK* pInputMediaSeek)(int size, unsigned int method);
typedef int (CALLBACK* pInputMediaOpen)(LPTSTR lpFilename, int mode, int type, int reserve, int maxsize);
typedef void (CALLBACK* pInputMediaClose)();
pInputMediaRead InputMediaRead;
pInputMediaSeek InputMediaSeek;
pInputMediaOpen InputMediaOpen;
pInputMediaClose InputMediaClose;
HMODULE hDLL;
ogg_sync_state oy; /* sync and verify incoming physical bitstream */
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
stream_state os[2];
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user comments */
stream_header* sh[2];
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
// int bytes;
int gotaudio;
int gotvideo;
//int i;
int stream_init=0;
ogg_int32_t **pcm;
int samples;
int readpage=1;
int readpagea=1;
int fsize;
__int64 lastpos;
int leftover=0;
//char* convbuffer[8000];
// stream_header* hi;
//unsigned char temp[32000];
//ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
int convsize=4096;
vorbis_info viv;
vorbis_comment vcv;
/*
* Reading Functions
*
*/
/*
* Tries to open an AVI
* with and without an index
*/
int FillHeader(LPTSTR lpFilename,int CacheSize)
{
int i=0;
int stream=0;
int bytes;
char inbuff[4096];
char *buffer;
lastpos=0;
gotvideo=0;
ogg_sync_init(&oy); /* Now we can read pages */
if (!wcsstr(lpFilename,_T("://")))
{
InputMediaSeek(fsize-100000,SEEK_SET);
bytes=4096;
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
stream_state_init(&os[0],0);
while(1)
{
int result=ogg_sync_pageout(&oy,&og);
if(result<=0)
{
int bytes=InputMediaRead(inbuff, 4096);
if (!bytes) break;
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
continue;
}
/* Don't complain about missing or corrupt data yet. We'll
catch it at the packet output phase */
if(result==1)
{
stream=ogg_page_serialno(&og);
if (stream==0) ogg_stream_pagein(&os[stream].os,&og);
else continue;
}
while(1)
{
result=ogg_stream_packetout(&os[0].os,&op);
if (result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
break;
}
if (result<0)
{
/* no page? must not be vorbis */
break;
}
if (op.granulepos!=-1)
{
viddata.video_frames=op.granulepos+1;
}
}
}
InputMediaClose();
fsize=InputMediaOpen(lpFilename,0,0,4000000,CacheSize);
// InputMediaSeek(0,SEEK_SET);
stream=0;
ogg_stream_clear(&os[0].os);
}
else
{
viddata.video_frames=250000;
}
if (viddata.video_frames==0)
viddata.video_frames=250000;
ogg_sync_init(&oy); /* Now we can read pages */
gotaudio=false;
gotvideo=false;
// if(vidinfo.input != NULL) {
bytes=4096;
i=0;
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
// i=1;
while(!gotaudio||(!gotvideo))
{
//convbuffer=(ogg_int16_t*) outmemory;
/* submit a 4k block to libvorbis' Ogg layer */
/* Get the first page. */
int result=ogg_sync_pageout(&oy,&og);
if (result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
continue;
}
if (result<0)
{
return -1;
}
//ogg_stream_init(&os.os,ogg_page_serialno(&og));
stream_state_init(&os[i],ogg_page_serialno(&og));
stream=ogg_page_serialno(&og);
if(ogg_stream_pagein(&os[stream].os,&og)<0)
{
/* error; stream version mismatch perhaps */
return -1;
}
result=ogg_stream_packetout(&os[i].os,&op);
if (result==0)
{
if (i==0)
gotvideo=-1;
if (i==1)
gotaudio=-1;
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
continue;
}
if (result<0)
{
/* no page? must not be vorbis */
return -1;
}
/* extract the initial header from the first page and verify that the
Ogg bitstream is in fact Vorbis data */
/* I handle the initial header first instead of just having the code
read all three Vorbis headers at once because reading the initial
header is an easy way to identify a Vorbis bitstream and it's
useful to see that functionality seperated out. */
if (stream_header_in(&sh[i],&op)!=0)
{
vorbis_info_init(&vi);
vorbis_comment_init(&vc);
if(vorbis_synthesis_headerin(&vi,&vc,&op)<0)
{
/* error case; not a vorbis header */
return -1;
}
gotaudio=1;
// stream_state_init(&os[i],ogg_page_serialno(&og));
//if(ogg_stream_pagein(&os[i].os,&og)<0)
//{
// /* error; stream version mismatch perhaps */
// return -1;
//}
}
else
{
if (strcmp(sh[i]->streamtype,MT_Video)) gotaudio=1;
else gotvideo=1;
}
// else
/* Get the serial number and set up the rest of decode. */
/* serialno first; use it to set up a logical stream */
// stream_init=1;
i++;
}
if (gotvideo>0)
{
int i=0;
while(!i)
{
while(!i)
{
int result=ogg_sync_pageout(&oy,&og);
if(result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
continue;
}
if(result==1)
{
stream=ogg_page_serialno(&og);
ogg_stream_pagein(&os[stream].os,&og);
while(!i)
{
result=ogg_stream_packetout(&os[0].os,&op);
if(result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
break;
}
if(result<0)
{
return -1;
}
vorbis_info_init(&viv);
vorbis_comment_init(&vcv);
viv.rate=1;
if(vorbis_synthesis_headerin(&viv,&vcv,&op)<0)
{
return -1;
}
int c=0;
int j=0;
#if (_WIN32_WCE >= 300)
while ((c<vcv.comments)&&(_strnicmp(vcv.user_comments[c],"CHAPTER",7))) c++;
#else
while ((c<vcv.comments)&&(strncmp(vcv.user_comments[c],"CHAPTER",7))) c++;
#endif
c++;
#if (_WIN32_WCE >= 300)
for (;c<vcv.comments&&(!_strnicmp(vcv.user_comments[c],"CHAPTER",7));c+=2)
#else
for (;c<vcv.comments&&(!strncmp(vcv.user_comments[c],"CHAPTER",7));c+=2)
#endif
{
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,vcv.user_comments[c]+14,-1,viddata.ChapterDisplay[j],vcv.comment_lengths[c]-14);
//MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,vcv.user_comments[(c-1)]+10,-1,thisvid.ChapterDisplay[(c-1)/2]+vcv.comment_lengths[c]-14,8);
j++;
}
viddata.ChapterCount=j;
i++;
}
}
}
}
}
if (gotaudio>0)
{
int i=0;
while(i<2)
{
while(i<2)
{
int result=ogg_sync_pageout(&oy,&og);
if(result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
continue;
}
if(result==1)
{
stream=ogg_page_serialno(&og);
ogg_stream_pagein(&os[stream].os,&og);
while(i<2)
{
result=ogg_stream_packetout(&os[1].os,&op);
if(result==0)
{
InputMediaRead(inbuff, 4096);
buffer=ogg_sync_buffer(&oy,bytes);
memcpy(buffer,inbuff,bytes);
ogg_sync_wrote(&oy,bytes);
break;
}
if(result<0)
{
return -1;
}
if (!sh[1])
{
if(vorbis_synthesis_headerin(&vi,&vc,&op)<0)
{
return -1;
}
}
else
{
i++;
}
i++;
}
}
}
}
}
stream_init=0;
if (!sh[1]&&(gotaudio>0))
{
vorbis_synthesis_init(&vd,&vi);
vorbis_block_init(&vd,&vb);
convsize=4096/vi.channels;
}
return 1;
}
int AVIDecaps_Open(LPTSTR lpFilename, int Cache, int CacheSize,videoinfo** vidinfo)
{
int ret=0;
::CacheSize=CacheSize;
if (wcsstr(lpFilename,_T("://")))
hDLL=LoadLibrary(_T("InputMediaHTTP.dll"));
else if (Cache)
hDLL=LoadLibrary(_T("InputMediaCache.dll"));
else
hDLL=LoadLibrary(_T("InputMedia.dll"));
if (!hDLL) return 0;
leftover=0;
InputMediaRead=(pInputMediaRead)GetProcAddress(hDLL,_T("InputMediaRead"));
InputMediaSeek=(pInputMediaSeek)GetProcAddress(hDLL,_T("InputMediaSeek"));
InputMediaOpen=(pInputMediaOpen)GetProcAddress(hDLL,_T("InputMediaOpen"));
InputMediaClose=(pInputMediaClose)GetProcAddress(hDLL,_T("InputMediaClose"));
if ((fsize=InputMediaOpen(lpFilename, 0, 0,-1,1000000))==0)
{
FreeLibrary(hDLL);
hDLL=NULL;
return 0;
}
thisvid.hIOMutex = CreateMutex (NULL, FALSE, NULL);
viddata.video_pos = 0;
FillHeader(lpFilename,CacheSize);
viddata.audio_bytes=0;
//thisvid.video_frames=100000;
//thisvid.audio_bytes=10584000;
strncpy(viddata.compressor,sh[0]->subtype,4);
viddata.width=sh[0]->video.width;
viddata.height=sh[0]->video.height;
viddata.fps=((double)10000000)/((double)sh[0]->time_unit);
if (gotaudio>0)
{
if (!sh[1])
{
viddata.a_fmt=0;
viddata.a_chans=vi.channels;
viddata.a_rate=vi.rate;
viddata.a_bits=vi.bitrate_nominal;
viddata.audio_bytes=((double)((double)viddata.video_frames)/viddata.fps)*(double)viddata.a_rate*viddata.a_chans*2;
}
else
{
viddata.a_fmt=atoi(sh[1]->subtype);
viddata.a_chans=sh[1]->samples_per_unit;
viddata.a_rate=sh[1]->audio.channels;
viddata.audio_bytes=((double)((double)viddata.video_frames)/viddata.fps)*(double)sh[1]->audio.avgbytespersec;
}
}
*vidinfo=&::viddata;
return 1;
}
bool didseek=false;
char oneframe[48000];
int oneframelen;
__int64 video_reftime;
__int64 audio_reftime;
/*
* Reads the next video Frame into
* buffer, return the actual size of
* the frame.
*
*/
#define VIDEO_STREAM 0
int AVIDecaps_NextVideoFrame(char *buffer, int drop)
{
int stream=0;
int eos=0;
int bytes;
if (!didseek&&(oneframelen))
{
memcpy(buffer,oneframe,oneframelen);
bytes=oneframelen;
oneframelen=0;
return bytes;
}
WaitForSingleObject(thisvid.hIOMutex, INFINITE);
while(!eos)
{
if (readpage)
{
int result=ogg_sync_pageout(&oy,&og);
readpage=0;
if(result==0) /* missing or corrupt data at this page position */
{
bytes=4096;
char* buff=ogg_sync_buffer(&oy,bytes);
bytes=InputMediaRead(buff, 4096);
if (bytes==0)
{
ReleaseMutex(thisvid.hIOMutex);
return -1;
}
if (ogg_sync_wrote(&oy,bytes)==-1)
{
int error=1;
}
readpage=1;
continue;
}
else if (result<0)
{
readpage=1;
continue;
}
stream=ogg_page_serialno(&og);
ogg_stream_pagein(&os[stream].os,&og);
}
if (stream==VIDEO_STREAM)
{
int result;
unsigned char* temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -