📄 avistream.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 "stdafx.h"
#include "AVIStream.h"
#ifdef SMART
#define INDEX_SIZE 5000
#else
#define INDEX_SIZE 100000
#endif
aviinfo vidinfo;
videoinfo viddata;
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;
int CacheSize;
//#include "inputmedia.h"
/*
* Some useful functions
*/
/*
* copy n into dst as a 4 byte,
* little endian number.
* should also work on
* big endian machines
*
*/
int nMalloc=0;
int abytes_read=0;
static void long2str(char *dst, int n)
{
dst[0] = (n ) & 0xff;
dst[1] = (n >> 8) & 0xff;
dst[2] = (n >> 16) & 0xff;
dst[3] = (n >> 24) & 0xff;
}
/* Convert a string of 4
* or 2 bytes to a number,
* also working on big
* endian machines
*
*/
unsigned long str2ulong(char *str)
{
unsigned long result;
result = ( ((unsigned long) str[0] & 0xFF) | ( ((unsigned long)str[1] &0xFF) << 8) |
(((unsigned long) str[2] & 0xFF) << 16) | ( ((unsigned long) str[3] & 0xFF) << 24) );
return result;
}
static unsigned long str2ushort(char *str)
{
return ( str[0] | (str[1]<<8) );
}
/*
* Reads the first 12 bytes of
* the file, and returns TRUE
* if the file is an AVI.
*
*/
int AVIDecaps_IsAVI()
{
char data[24];
// if(vidinfo.input != NULL) {
if( InputMediaRead(data, 12) != 12 ) {
//MessageBox(NULL, "Error Reading", "Info", MB_OK);
return 0;
}
if( strncmp(data, "RIFF", 4) !=0 ||
strncmp(data + 8, "AVI ", 4) !=0 ) {
return 0;
}
return 1;
return 0;
}
/*
* Fill the class with info from headers
* and reconstruct an index if wanted.
*
*/
int AVIDecaps_FillHeader(int getIndex)
{
unsigned long i, n, rate;
char *hdrl_data;
long hdrl_len = 0;
int scale,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];
long nvi=0, nai=0, ioff, frame=0;
int tot;
/* go through the AVI file and
* extract the header list,
* the start position of the 'movi'
* list and an optionally
* present idx1 tag
*
*/
hdrl_data = 0;
while(1)
{
if( InputMediaRead(data, 8) != 8 )
break;
/*
* we assume it's EOF
*
*/
n = str2ulong(data + 4);
n = PAD_EVEN(n);
if(strncmp(data, "LIST", 4) == 0)
{
if( InputMediaRead(data, 4) != 4 ) {
return 0;
}
n -= 4;
if(strncmp(data, "hdrl", 4) == 0)
{
hdrl_len = n;
if (hdrl_data) free(hdrl_data);
hdrl_data = (char *) malloc(n);
if(hdrl_data == 0) {
return 0;
}
if( InputMediaRead(hdrl_data, n) != n ) {
return 0;
}
}
else if(strncmp(data, "movi", 4) == 0)
{
vidinfo.movi_start = InputMediaSeek(0, INPUT_SEEK_CUR);
//break;
if (vidinfo.m_type!=1) InputMediaSeek(n, INPUT_SEEK_CUR);
else
break;
}
else
{
InputMediaSeek(n, INPUT_SEEK_CUR);
//break;
}
}
else if((strncmp(data,"idx1",4) == 0)&&(vidinfo.m_type!=1))
{
vidinfo.n_idx = vidinfo.max_idx = n/16;
if (vidinfo.idx) free(vidinfo.idx);
vidinfo.video_index = (video_index_entry *) malloc(INDEX_SIZE*sizeof(video_index_entry));
if (!vidinfo.video_index)
{
return 0;
}
vidinfo.audio_index = (audio_index_entry *) malloc(INDEX_SIZE*sizeof(audio_index_entry));
if (!vidinfo.audio_index)
{
free(vidinfo.video_index);
vidinfo.video_index=0;
return 0;
}
tot=0;
unsigned long read;
ioff = vidinfo.movi_start+4;
for (i=0;i<(vidinfo.n_idx/1000)+1;i++)
{
char temp[16000];
int toread=16000;
int i2;
if (i==(vidinfo.n_idx/1000))
toread=(vidinfo.n_idx%1000)*16;
if( (read = InputMediaRead((char *) temp, toread)) != toread) {
break;
}
for (i2=0;i2<read/16;i2++)
{
if(strncmp(temp+(16*i2)+2, "db", 1) == 0)
{
if(nvi%INDEX_SIZE==0)
{
void* ptr = realloc((void *)vidinfo.video_index,
(nvi+INDEX_SIZE)*sizeof(video_index_entry));
if (!ptr)
{
free(vidinfo.video_index);
vidinfo.video_index=0;
free(vidinfo.audio_index);
vidinfo.audio_index=0;
return 0;
}
vidinfo.video_index = (video_index_entry*)ptr;
}
if ((str2ulong(temp+(16*i2) +4) & AVIIF_KEYFRAME)>1)
{
vidinfo.video_index[nvi].flags = frame;//(BYTE) (str2ulong(temp+(16*i2) +4) & AVIIF_KEYFRAME)>1;
vidinfo.video_index[nvi].pos = str2ulong(temp+(16*i2)+ 8)+ioff;
vidinfo.video_index[nvi].len = str2ulong(temp+(16*i2)+12);
nvi++;
}
frame++;
}
else if(strncmp(temp+(16*i2)+2, "wb", 2) == 0)
{
if(nai%INDEX_SIZE==0)
{
void* ptr = realloc((void *)vidinfo.audio_index,
(nai+INDEX_SIZE)*sizeof(audio_index_entry));
if (!ptr)
{
free(vidinfo.video_index);
vidinfo.video_index=0;
free(vidinfo.audio_index);
vidinfo.audio_index=0;
return 0;
}
vidinfo.audio_index = (audio_index_entry*)ptr;
}
vidinfo.audio_index[nai].pos = str2ulong(temp+(16*i2)+ 8)+ioff;
vidinfo.audio_index[nai].len = str2ulong(temp+(16*i2)+12);
vidinfo.audio_index[nai].tot = tot;
tot += vidinfo.audio_index[nai].len;
if ((!nai)||(vidinfo.audio_index[nai].tot>vidinfo.audio_index[nai-1].tot+INDEX_SIZE))
nai++;
}
}
}
void* ptr = realloc((void *)vidinfo.video_index,
(nvi)*sizeof(video_index_entry));
vidinfo.video_index = (video_index_entry*)ptr;
ptr = realloc((void *)vidinfo.audio_index,
(nai)*sizeof(audio_index_entry));
vidinfo.audio_index = (audio_index_entry*)ptr;
}
else {
InputMediaSeek(n, INPUT_SEEK_CUR);
}
}
if(!hdrl_data) {
return 0;
}
if(!vidinfo.movi_start) {
return 0;
}
/*
* interpret the header list
*
*/
for(i=0; i < hdrl_len; )
{
/*
* list tags are completly ignored
*
*/
if(strncmp(hdrl_data + i, "LIST", 4)==0)
{
i+= 12;
continue;
}
n = str2ulong(hdrl_data+i+4);
n = PAD_EVEN(n);
/*
* interpret the tag and its args
*
*/
if(strncmp(hdrl_data + i, "strh", 4)==0)
{
i += 8;
if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
{
memcpy(viddata.compressor,hdrl_data+i+4,4);
viddata.compressor[4] = 0;
scale = str2ulong(hdrl_data+i+20);
rate = str2ulong(hdrl_data+i+24);
if(scale!=0)
viddata.fps = (double)rate/(double)scale;
viddata.video_frames = str2ulong(hdrl_data+i+32);
vidinfo.video_strn = num_stream;
vids_strh_seen = 1;
lasttag = 1;
}
else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
{
viddata.audio_bytes = str2ulong(hdrl_data + i + 32);//AVIDecaps_SampleSize();
vidinfo.audio_strn = num_stream;
auds_strh_seen = 1;
lasttag = 2;
}
else
lasttag = 0;
num_stream++;
}
else if(strncmp(hdrl_data + i, "strf", 4)==0)
{
i += 8;
if(lasttag == 1)
{
/*
* keep a copy of
* the bitmapinfoheader
*
*/
viddata.width = str2ulong(hdrl_data+i+4);
viddata.height = str2ulong(hdrl_data+i+8);
vids_strf_seen = 1;
}
else if(lasttag == 2)
{
viddata.a_fmt = str2ushort(hdrl_data + i );
}
lasttag = 0;
}
else
{
i += 8;
lasttag = 0;
}
i += n;
}
if (hdrl_data) free(hdrl_data);
hdrl_data=0;
if(!vids_strh_seen || !vids_strf_seen || viddata.video_frames==0) {
return 0;
}
viddata.video_tag[0] = vidinfo.video_strn/10 + '0';
viddata.video_tag[1] = vidinfo.video_strn%10 + '0';
viddata.video_tag[2] = 'd';
viddata.video_tag[3] = 'b';
/*
* audio tag is set to "99wb"
* if no audio present
*
*/
viddata.audio_tag[0] = vidinfo.audio_strn/10 + '0';
viddata.audio_tag[1] = vidinfo.audio_strn%10 + '0';
viddata.audio_tag[2] = 'w';
viddata.audio_tag[3] = 'b';
InputMediaSeek(vidinfo.movi_start, INPUT_SEEK_SET);
vidinfo.currentchunk.pos=vidinfo.movi_start;
vidinfo.currentchunk.len=0;
vidinfo.currentframe.pos=vidinfo.movi_start;
vidinfo.currentframe.len=0;
/*
* reposition the file
*
*/
InputMediaClose();
int fsize=InputMediaOpen(vidinfo.m_lpFilename,0,0,4000000,CacheSize);
if (!fsize) return 0;
InputMediaSeek(vidinfo.movi_start,
INPUT_SEEK_SET);
viddata.video_pos = 0;
return 1;
}
/*
* Tries to open an AVI
* with and without an index
*/
AVISTREAM_API int AVIDecaps_Open(LPTSTR lpFilename, int type, int CacheSize,videoinfo** vid)
{
int ret=0;
::CacheSize=CacheSize;
wcscpy(vidinfo.m_lpFilename,lpFilename);
vidinfo.m_type=type;
if (type==0)
hDLL=LoadLibrary(_T("InputMedia.dll"));
else if (type==2)
hDLL=LoadLibrary(_T("InputMediaCache.dll"));
else
{
hDLL=LoadLibrary(_T("InputMediaHTTP.dll"));
}
InputMediaRead=(pInputMediaRead)GetProcAddress(hDLL,_T("InputMediaRead"));
InputMediaSeek=(pInputMediaSeek)GetProcAddress(hDLL,_T("InputMediaSeek"));
InputMediaOpen=(pInputMediaOpen)GetProcAddress(hDLL,_T("InputMediaOpen"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -