📄 decapsavi.cpp
字号:
#include "DecapsAVI.h"
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;
}
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) );
}
media_type_t MediaDecapsAVI::GetType()
{
return MEDIA_TYPE_DECAPS;
}
char *MediaDecapsAVI::GetName()
{
return "AVI Demuxer";
}
MP_RESULT MediaDecapsAVI::Connect(MediaItem *item)
{
if(item->GetType() == MEDIA_TYPE_INPUT) {
this->input = (MediaItemInput *) item;
}
this->video_pos = 0;
this->audio_posc = 0;
this->audio_posb = 0;
this->idx = NULL;
this->video_index = NULL;
this->audio_index = NULL;
if(this->IsAVI()) {
if(this->FillHeader(1)) {
return MP_RESULT_OK;
}
else {
this->input->Seek(0, INPUT_SEEK_SET);
this->IsAVI();
if(this->FillHeader(0)) {
return MP_RESULT_OK;
}
}
}
return MP_RESULT_ERROR;
}
MP_RESULT MediaDecapsAVI::ReleaseConnections()
{
this->input = NULL;
if(this->idx != NULL)
free(this->idx);
if(this->video_index != NULL)
free(this->video_index);
if(this->audio_index != NULL)
free(this->audio_index);
this->idx = NULL;
this->video_index = NULL;
this->audio_index = NULL;
this->audio_strn = 0;
this->video_strn = 0;
memset(&this->waveformatex, 0, sizeof(MPEGLAYER3WAVEFORMAT));
memset(&this->bitmapinfoheader, 0, sizeof(BITMAPINFOHEADER));
return MP_RESULT_OK;
}
DWORD MediaDecapsAVI::GetCaps()
{
return 0;
}
MP_RESULT MediaDecapsAVI::Configure(HINSTANCE hInstance, HWND hwnd)
{
return MP_RESULT_ERROR;
}
MediaDecapsAVI::MediaDecapsAVI()
{
this->video_pos = 0;
this->audio_posc = 0;
this->audio_posb = 0;
this->idx = NULL;
this->video_index = NULL;
this->audio_index = NULL;
this->hIOMutex = CreateMutex (NULL, FALSE, NULL);
this->input = NULL;
}
MediaDecapsAVI::~MediaDecapsAVI()
{
CloseHandle(this->hIOMutex);
}
int MediaDecapsAVI::IsAVI()
{
MediaBuffer *mb = new MediaBuffer();
mb->Alloc(12);
if(this->input != NULL) {
if( this->input->Read(mb, 12) != 12 ) {
delete mb;
return 0;
}
if( strncmp((char *) mb->GetData(), "RIFF", 4) !=0 ||
strncmp(((char *) mb->GetData()) + 8, "AVI ", 4) !=0 ) {
return 0;
}
delete mb;
return 1;
}
return 0;
}
int MediaDecapsAVI::SampleSize()
{
int s;
s = ((this->a_bits + 7) / 8) * this->a_chans;
if(s == 0)
s = 1;
return s;
}
int MediaDecapsAVI::FillHeader(int getIndex)
{
unsigned long n, rate;
long scale, idx_type;
char *hdrl_data;
long i, hdrl_len = 0;
long nvi, nai, ioff;
long tot;
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;
MediaBuffer *mb = new MediaBuffer();
if(this->input == NULL)
return MP_RESULT_ERROR;
mb->Alloc(256);
hdrl_data = 0;
while(1)
{
if( this->input->Read(mb, 8) != 8 )
break;
n = str2ulong(((char *) mb->GetData()) + 4);
n = PAD_EVEN(n);
if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
{
if( this->input->Read(mb, 4) != 4 ) {
mb->Free();
return 0;
}
n -= 4;
if(strncmp((char *) mb->GetData(), "hdrl", 4) == 0)
{
MediaBuffer *mbh;
hdrl_len = n;
char buffer[256];
sprintf(buffer, "size = %d", n);
mbh = new MediaBuffer();
mbh->Alloc(n);
hdrl_data = (char *) new char[n];
if(hdrl_data == NULL) {
mb->Free();
return 0;
}
if( this->input->Read(mbh, n) != n ) {
mb->Free();
return 0;
}
memcpy(hdrl_data, mbh->GetData(), n);
mbh->Free();
}
else if(strncmp((char *) mb->GetData(), "movi", 4) == 0)
{
this->movi_start = this->input->Seek(0, INPUT_SEEK_CUR);
this->input->Seek(n, INPUT_SEEK_CUR);
}
else
this->input->Seek(n, INPUT_SEEK_CUR);
}
else if(strncmp((char *) mb->GetData(),"idx1",4) == 0)
{
this->n_idx = this->max_idx = n/16;
this->idx = (char((*)[16]) ) new char[n];
if(this->idx == NULL) {
mb->Free();
return 0;
}
unsigned long read;
MediaBuffer *mbi = new MediaBuffer();
mbi->Alloc(n);
if( (read = this->input->Read(mbi, n)) != n ) {
break;
}
memcpy(this->idx, mbi->GetData(), n);
mbi->Free();
}
else {
this->input->Seek(n, INPUT_SEEK_CUR);
}
}
if(!hdrl_data) {
mb->Free();
return 0;
}
if(!this->movi_start) {
mb->Free();
return 0;
}
for(i=0; i < hdrl_len; )
{
if(strncmp(hdrl_data + i, "LIST", 4)==0)
{
i+= 12;
continue;
}
n = str2ulong(hdrl_data+i+4);
n = PAD_EVEN(n);
if(strncmp(hdrl_data + i, "strh", 4)==0)
{
i += 8;
if(strncmp(hdrl_data + i, "vids", 4) == 0 && !vids_strh_seen)
{
memcpy(this->compressor,hdrl_data+i+4,4);
this->compressor[4] = 0;
scale = str2ulong(hdrl_data+i+20);
rate = str2ulong(hdrl_data+i+24);
if(scale!=0)
this->fps = (double)rate/(double)scale;
this->video_frames = str2ulong(hdrl_data+i+32);
this->video_strn = num_stream;
vids_strh_seen = 1;
lasttag = 1;
}
else if (strncmp (hdrl_data + i, "auds", 4) == 0 && ! auds_strh_seen)
{
this->audio_bytes = str2ulong(hdrl_data + i + 32)*this->SampleSize();
this->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)
{
memcpy(&this->bitmapinfoheader,
hdrl_data + i,
sizeof(BITMAPINFOHEADER));
this->width = str2ulong(hdrl_data+i+4);
this->height = str2ulong(hdrl_data+i+8);
vids_strf_seen = 1;
}
else if(lasttag == 2)
{
memcpy(&this->waveformatex,
hdrl_data + i,
sizeof(MPEGLAYER3WAVEFORMAT));
this->a_fmt = str2ushort(hdrl_data + i );
this->a_chans = str2ushort(hdrl_data + i + 2);
this->a_rate = str2ulong (hdrl_data + i + 4);
this->a_bits = str2ushort(hdrl_data + i + 14) == 0 ? 16 : str2ushort(hdrl_data + i + 14);
auds_strf_seen = 1;
}
lasttag = 0;
}
else
{
i += 8;
lasttag = 0;
}
i += n;
}
free(hdrl_data);
if(!vids_strh_seen || !vids_strf_seen || this->video_frames==0) {
mb->Free();
return 0;
}
this->video_tag[0] = this->video_strn/10 + '0';
this->video_tag[1] = this->video_strn%10 + '0';
this->video_tag[2] = 'd';
this->video_tag[3] = 'b';
if(!this->a_chans)
this->audio_strn = 99;
this->audio_tag[0] = this->audio_strn/10 + '0';
this->audio_tag[1] = this->audio_strn%10 + '0';
this->audio_tag[2] = 'w';
this->audio_tag[3] = 'b';
this->input->Seek(this->movi_start, INPUT_SEEK_SET);
if(!getIndex)
return 1;
idx_type = 0;
if(this->idx)
{
unsigned long pos, len;
for(i = 0; i < this->n_idx; i++) {
if( strncmp(this->idx[i], this->video_tag, 3) == 0 )
break;
}
if(i >= this->n_idx)
return 0;
pos = str2ulong(this->idx[i] + 8);
len = str2ulong(this->idx[i] + 12);
this->input->Seek(pos, INPUT_SEEK_SET);
if(this->input->Read(mb, 8)!=8)
return 0;
if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
{
idx_type = 1;
}
else
{
this->input->Seek(pos + this->movi_start - 4,INPUT_SEEK_SET);
if(this->input->Read(mb, 8) != 8)
return 0;
if( strncmp((char *) mb->GetData(), this->idx[i], 4) == 0 && str2ulong((char *) mb->GetData() + 4) == len )
{
idx_type = 2;
}
}
}
if(idx_type == 0)
{
this->input->Seek(this->movi_start, INPUT_SEEK_SET);
this->max_idx = 4096;
this->n_idx = 0;
this->idx = (char((*)[16]) ) new char[this->max_idx];
while(1)
{
if( this->input->Read(mb, 8) != 8 )
break;
n = str2ulong((char *) mb->GetData() + 4);
if(strncmp((char *) mb->GetData(), "LIST", 4) == 0)
{
this->input->Seek(4, INPUT_SEEK_CUR);
continue;
}
if( ((((char *) mb->GetData())[2]=='d' || ((char *) mb->GetData())[2]=='D') &&
(((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B' ||
((char *) mb->GetData())[3]=='c' || ((char *) mb->GetData())[3]=='C') ) ||
((((char *) mb->GetData())[2]=='w' || ((char *) mb->GetData())[2]=='W') &&
(((char *) mb->GetData())[3]=='b' || ((char *) mb->GetData())[3]=='B') ) )
{
this->AddIndexEntry(((char *) mb->GetData()),
0,
this->input->Seek(0, INPUT_SEEK_CUR) - 8,
n);
}
this->input->Seek(PAD_EVEN(n), INPUT_SEEK_CUR);
}
idx_type = 1;
}
nvi = 0;
nai = 0;
for(i=0; i < this->n_idx; i++)
{
if(strncmp(this->idx[i], this->video_tag, 3) == 0)
nvi++;
if(strncmp(this->idx[i], this->audio_tag, 4) == 0)
nai++;
}
this->video_frames = nvi;
this->audio_chunks = nai;
if(this->video_frames == 0) {
mb->Free();
return 0;
}
this->video_index = (video_index_entry *) new char[(nvi*sizeof(video_index_entry))];
if(this->video_index == 0) {
mb->Free();
return 0;
}
if(this->audio_chunks)
{
this->audio_index = (audio_index_entry *) new char[(nai*sizeof(audio_index_entry))];
if(this->audio_index == 0) {
mb->Free();
return 0;
}
}
nvi = 0;
nai = 0;
tot = 0;
ioff = idx_type == 1 ? 8 : this->movi_start+4;
for(i=0; i < this->n_idx; i++)
{
if(strncmp(this->idx[i], this->video_tag, 3) == 0)
{
this->video_index[nvi].flags = str2ulong(this->idx[i]+ 4);
this->video_index[nvi].pos = str2ulong(this->idx[i]+ 8)+ioff;
this->video_index[nvi].len = str2ulong(this->idx[i]+12);
nvi++;
}
if(strncmp(this->idx[i], this->audio_tag, 4) == 0)
{
this->audio_index[nai].pos = str2ulong(this->idx[i]+ 8)+ioff;
this->audio_index[nai].len = str2ulong(this->idx[i]+12);
this->audio_index[nai].tot = tot;
tot += this->audio_index[nai].len;
nai++;
}
}
this->audio_bytes = tot;
this->input->Seek(this->movi_start, INPUT_SEEK_SET);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -