winamp/Src/Plugins/Input/in_dshow/header_mpg.cpp
2024-09-24 14:54:57 +02:00

235 lines
6.2 KiB
C++

#include <windows.h>
#include "header_mpg.h"
#include <bfc/platform/types.h>
static int frameratecode2framerate[16] = {
0,
// Official mpeg1/2 framerates:
24000*10000/1001, 24*10000,25*10000, 30000*10000/1001, 30*10000,50*10000,60000*10000/1001, 60*10000,
// libmpeg3's "Unofficial economy rates":
1*10000,5*10000,10*10000,12*10000,15*10000,0,0
};
static const int gaSampleRate[3][4] =
{
{44100, 48000, 32000, 0}, // MPEG-1
{22050, 24000, 16000, 0}, // MPEG-2
{11025, 12000, 8000, 0}, // MPEG-2.5
};
static const int gaBitrate[2][3][15] =
{
{
// MPEG-1
{ 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448}, // Layer 1
{ 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384}, // Layer 2
{ 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}, // Layer 3
},
{
// MPEG-2, MPEG-2.5
{ 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, // Layer 1
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, // Layer 2
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, // Layer 3
},
};
#define MPEG_SYNCWORD 0x7ff
#define MPEG1 0
#define MPEG2 1
#define MPEG25 2
#define MODE_MONO 3
HeaderMpg::HeaderMpg() : fh(INVALID_HANDLE_VALUE)
{
memset(buf, 0, sizeof(buf));
pbuf = end = 0;
m_BitrateNdx = m_SampleRateNdx = m_Layer = m_Id = m_Mode =
m_Idex = video_bitrate = audio_bitrate = 0;
}
int HeaderMpg::mp3headerFromInt(unsigned long dwHdrBits)
{
// header fields
int m_Syncword;
/*int m_CrcCheck;
int m_Padding;
int m_Private;
int m_ModeExt;
int m_Copyright;
int m_Original;
int m_Emphasis;*/
// calculated data
int m_HeaderValid;
// read header fields
m_Syncword = (dwHdrBits >> 21) & 0x000007ff;
m_Idex = (dwHdrBits >> 20) & 0x00000001;
m_Id = (dwHdrBits >> 19) & 0x00000001;
m_Layer = 4 -((dwHdrBits >> 17) & 0x00000003);
//m_CrcCheck = !((dwHdrBits >> 16) & 0x00000001);
m_BitrateNdx = (dwHdrBits >> 12) & 0x0000000f;
m_SampleRateNdx = (dwHdrBits >> 10) & 0x00000003;
/*m_Padding = (dwHdrBits >> 9) & 0x00000001;
m_Private = (dwHdrBits >> 8) & 0x00000001;*/
m_Mode = (dwHdrBits >> 6) & 0x00000003;
/*m_ModeExt = (dwHdrBits >> 4) & 0x00000003;
m_Copyright = (dwHdrBits >> 3) & 0x00000001;
m_Original = (dwHdrBits >> 2) & 0x00000001;
m_Emphasis = (dwHdrBits ) & 0x00000003;*/
// check if header is valid
/* if (
(m_Syncword != MPEG_SYNCWORD) ||
#ifndef SYNC_ALL_LAYERS
(m_Layer != 3 ) ||
#else
(m_Layer == 4 ) ||
#endif
(m_BitrateNdx == 15 ) ||
(m_BitrateNdx == 0 ) ||
(m_SampleRateNdx == 3 ) ||
(m_Idex == 0 && m_Layer != 3 ) ||
(m_Idex == 0 && m_Id == 1 && m_Layer == 3)
)*/
if (
(m_Syncword != MPEG_SYNCWORD) ||
(m_Layer == 4 ) ||
(m_BitrateNdx == 15 ) ||
(m_BitrateNdx == 0 ) ||
(m_SampleRateNdx == 3 ) ||
(m_Idex == 0 && m_Layer != 3 ) ||
(m_Idex == 0 && m_Id == 1 ) ||
(m_Idex == 0 && m_BitrateNdx>8 )
)
{
m_HeaderValid = 0;
// ResetMembers();
}
else
{
m_HeaderValid = 1;
// SetMembers();
}
return m_HeaderValid;
}
static __int64 FileSize64(HANDLE file)
{
LARGE_INTEGER position;
position.QuadPart=0;
position.LowPart = GetFileSize(file, (LPDWORD)&position.HighPart);
if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
return INVALID_FILE_SIZE;
else
return position.QuadPart;
}
int HeaderMpg::getInfos(const wchar_t *filename, bool metadata)
{
fh = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(fh==INVALID_HANDLE_VALUE) return 0;
int ret=decodeHeader();
if(ret) {
int l=MulDiv(video_bitrate+audio_bitrate,2048,2018);
l/=8;
int64_t flen = FileSize64(fh);
if(l)
length=(int)((flen*1000ull) / (int64_t)l);
}
CloseHandle(fh);
return ret;
}
int HeaderMpg::decodeHeader()
{
DWORD bytesRead = 0;
memset(buf,0,sizeof(buf));
end=buf+sizeof(buf);
ReadFile(fh, &buf, sizeof(buf), &bytesRead, NULL);
pbuf=buf;
while(1) {
int code;
code=sync_packet();
if(!code) return 1;
switch(code) {
case 0x1b3: {
if(has_video) break;
pbuf+=4;
if ((pbuf[6] & 0x20) != 0x20){
//printf("missing marker bit!\n");
//return 1; /* missing marker_bit */
break;
}
int height = (pbuf[0] << 16) | (pbuf[1] << 8) | pbuf[2];
video_w = (height >> 12);
video_h = (height & 0xfff);
int width = ((height >> 12) + 15) & ~15;
height = ((height & 0xfff) + 15) & ~15;
if ((width > 768) || (height > 576)){
//printf("size restrictions for MP@ML or MPEG1 exceeded! (%dx%d)\n",width,height);
// return 1; /* size restrictions for MP@ML or MPEG1 */
break;
}
has_video=true;
int bitrate=(pbuf[4]<<10)|(pbuf[5]<<2)|(pbuf[6]>>6);
if(bitrate==262143) {
//variable bitrate
//has_video=false;
break;
}
bitrate=bitrate*2/5;
video_bitrate=bitrate*1000;
break;
}
case 0x1be: {
// padding stream
pbuf+=4;
int s=pbuf[0]<<8|pbuf[1];
pbuf+=2+s;
break;
}
}
if(code>=0x1c0 && code<=0x1df) {
pbuf+=4;
int len=pbuf[0]<<8|pbuf[1];
pbuf+=2;
pbuf+=5;
if (len > (end-pbuf))
return 0;
// decode mpeg audio header
while(--len) {
if(mp3headerFromInt((pbuf[0]<<24)|(pbuf[1]<<16)|(pbuf[2]<<8)|pbuf[3])) {
has_audio=true;
audio_bps=16;
int m_MpegVersion = m_Id==1 ? MPEG1 : (m_Idex==1?MPEG2 : MPEG25);
audio_nch = m_Mode == MODE_MONO ? 1:2;
audio_srate = gaSampleRate[m_MpegVersion][m_SampleRateNdx];
audio_bitrate = gaBitrate[m_MpegVersion==MPEG1?0:1][m_Layer-1][m_BitrateNdx] * 1000;
break;
}
pbuf++;
}
}
if(has_audio && has_video) return 1;
pbuf++;
}
return 1;
}