📄 qcdmp4.c
字号:
EndDialog(hwndDlg, wParam);
return TRUE;
}
}
return FALSE;
}
void Configure(int flags)
{
DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG),
module.hMainWindow, config_dialog_proc);
}
//-----------------------------------------------------------------------------
void About(int flags)
{
MessageBox(module.hMainWindow,
"AudioCoding.com MPEG-4 General Audio player " FAAD2_VERSION " compiled on " __DATE__ ".\n"
"Visit the website for more info.\n"
"Ported to QCD by Shao Hao.\n"
"Copyright 2002-2003 AudioCoding.com",
"About",
MB_OK);
}
//-----------------------------------------------------------------------------
int fill_buffer(state *st)
{
int bread;
if (st->m_aac_bytes_consumed > 0)
{
if (st->m_aac_bytes_into_buffer)
{
memmove((void*)st->m_aac_buffer, (void*)(st->m_aac_buffer + st->m_aac_bytes_consumed),
st->m_aac_bytes_into_buffer*sizeof(unsigned char));
}
if (!st->m_at_eof)
{
bread = fread((void*)(st->m_aac_buffer + st->m_aac_bytes_into_buffer),
1, st->m_aac_bytes_consumed, st->aacfile);
if (bread != st->m_aac_bytes_consumed)
st->m_at_eof = 1;
st->m_aac_bytes_into_buffer += bread;
}
st->m_aac_bytes_consumed = 0;
if (st->m_aac_bytes_into_buffer > 3)
{
if (memcmp(st->m_aac_buffer, "TAG", 3) == 0)
st->m_aac_bytes_into_buffer = 0;
}
if (st->m_aac_bytes_into_buffer > 11)
{
if (memcmp(st->m_aac_buffer, "LYRICSBEGIN", 11) == 0)
st->m_aac_bytes_into_buffer = 0;
}
if (st->m_aac_bytes_into_buffer > 8)
{
if (memcmp(st->m_aac_buffer, "APETAGEX", 8) == 0)
st->m_aac_bytes_into_buffer = 0;
}
}
return 1;
}
void advance_buffer(state *st, int bytes)
{
st->m_file_offset += bytes;
st->m_aac_bytes_consumed = bytes;
st->m_aac_bytes_into_buffer -= bytes;
}
int adts_parse(state *st, __int64 *bitrate, double *length)
{
static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
int frames, frame_length;
int t_framelength = 0;
int samplerate;
double frames_per_sec, bytes_per_frame;
/* Read all frames to ensure correct time and bitrate */
for (frames = 0; /* */; frames++)
{
fill_buffer(st);
if (st->m_aac_bytes_into_buffer > 7)
{
/* check syncword */
if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
break;
st->m_tail->offset = st->m_file_offset;
st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
st->m_tail = st->m_tail->next;
st->m_tail->next = NULL;
if (frames == 0)
samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];
frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
| (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);
t_framelength += frame_length;
if (frame_length > st->m_aac_bytes_into_buffer)
break;
advance_buffer(st, frame_length);
} else {
break;
}
}
frames_per_sec = (double)samplerate/1024.0;
if (frames != 0)
bytes_per_frame = (double)t_framelength/(double)(frames*1000);
else
bytes_per_frame = 0;
*bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
if (frames_per_sec != 0)
*length = (double)frames/frames_per_sec;
else
*length = 1;
return 1;
}
int skip_id3v2_tag()
{
unsigned char buf[10];
int bread, tagsize = 0;
bread = fread(buf, 1, 10, mp4state.aacfile);
if (bread != 10) return -1;
if (!memcmp(buf, "ID3", 3))
{
/* high bit is not used */
tagsize = (buf[6] << 21) | (buf[7] << 14) | (buf[8] << 7) | (buf[9] << 0);
tagsize += 10;
fseek(mp4state.aacfile, tagsize, SEEK_SET);
} else {
fseek(mp4state.aacfile, 0, SEEK_SET);
}
return tagsize;
}
int GetMediaSupported(const char* medianame, MediaInfo *mediaInfo)
{
int tagsize = 0, init;
if (!medianame || !*medianame)
return 0;
if (!stricmp(medianame + strlen(medianame) - 3,"MP4") || !stricmp(medianame + strlen(medianame) - 3,"M4A"))
{
if (mediaInfo)
{
mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
mediaInfo->op_canSeek = 1;
}
return 1;
}
else if (m_use_for_aac && !stricmp(medianame + strlen(medianame) - 3,"AAC"))
{
if (mediaInfo)
{
mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
mediaInfo->op_canSeek = 1;
memset(&mp4state, 0, sizeof(state));
lstrcpy(mp4state.filename, medianame);
if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
{
// error
return 0;
}
tagsize = skip_id3v2_tag();
if (tagsize<0) return 0;
if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
{
show_error(module.hMainWindow, "Memory allocation error.");
return 0;
}
for (init=0; init<2; init++)
{
memset(mp4state.m_aac_buffer, 0, 768*6);
fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
if (init==0)
fseek(mp4state.aacfile, tagsize, SEEK_SET);
}
if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0)
mediaInfo->op_canSeek = (double)file_length(mp4state.aacfile) == -1 ? 0 : 1;
free(mp4state.m_aac_buffer);
fclose(mp4state.aacfile);
}
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
int Play(const char* medianame, int playfrom, int playto, int flags)
{
WAVEFORMATEX wf;
//int maxlatency;
int thread_id;
int avg_bitrate, br, sr;
unsigned char *buffer;
int buffer_size;
faacDecConfigurationPtr config;
#ifdef DEBUG_OUTPUT
in_mp4_DebugOutput("play");
#endif
if (stricmp(mp4state.filename, medianame) != 0)
Stop(mp4state.filename, STOPFLAG_PLAYDONE);
if (mp4state.paused)
{
// Update the player controls to reflect the new unpaused state
module.QCDCallbacks.toPlayer.OutputPause(0);
Pause(medianame, 0);
if (playfrom >= 0)
mp4state.seek_needed = playfrom;
}
else if (PlayThreadAlive) // is playing
{
mp4state.seek_needed = playfrom;
return 1;
}
else
{
memset(&mp4state, 0, sizeof(state));
lstrcpy(mp4state.filename, medianame);
if (!(mp4state.mp4file = MP4Read(mp4state.filename, 0)))
{
mp4state.filetype = 1;
} else {
MP4Close(mp4state.mp4file);
mp4state.filetype = 0;
}
if (mp4state.filetype)
{
int tagsize = 0, tmp = 0, init;
int bread = 0;
double length = 0.;
__int64 bitrate = 128;
//module.is_seekable = 1;
if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
{
// error
return -1;
}
tagsize = skip_id3v2_tag();
if (tagsize<0) return 0;
if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
{
show_error(module.hMainWindow, "Memory allocation error.");
return -1;
}
for (init=0; init<2; init++)
{
mp4state.hDecoder = faacDecOpen();
if (!mp4state.hDecoder)
{
show_error(module.hMainWindow, "Unable to open decoder library.");
return -1;
}
config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
config->outputFormat = m_resolution + 1;
config->downMatrix = m_downmix;
faacDecSetConfiguration(mp4state.hDecoder, config);
memset(mp4state.m_aac_buffer, 0, 768*6);
bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
mp4state.m_aac_bytes_into_buffer = bread;
mp4state.m_aac_bytes_consumed = 0;
mp4state.m_file_offset = 0;
mp4state.m_at_eof = (bread != 768*6) ? 1 : 0;
if (init==0)
{
faacDecFrameInfo frameInfo;
fill_buffer(&mp4state);
if ((mp4state.m_aac_bytes_consumed = faacDecInit(mp4state.hDecoder,
mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
&mp4state.samplerate, &mp4state.channels)) < 0)
{
show_error(module.hMainWindow, "Can't initialize decoder library.");
return -1;
}
advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
do {
memset(&frameInfo, 0, sizeof(faacDecFrameInfo));
fill_buffer(&mp4state);
faacDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
} while (!frameInfo.samples && !frameInfo.error);
if (frameInfo.error)
{
show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
return -1;
}
mp4state.channels = frameInfo.channels;
mp4state.samplerate = frameInfo.samplerate;
mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
/*
sbr = frameInfo.sbr;
profile = frameInfo.object_type;
header_type = frameInfo.header_type;
*/
faacDecClose(mp4state.hDecoder);
fseek(mp4state.aacfile, tagsize, SEEK_SET);
}
}
mp4state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
mp4state.m_tail = mp4state.m_head;
mp4state.m_tail->next = NULL;
mp4state.m_header_type = 0;
if ((mp4state.m_aac_buffer[0] == 0xFF) && ((mp4state.m_aac_buffer[1] & 0xF6) == 0xF0))
{
if (1) //(can_seek)
{
adts_parse(&mp4state, &bitrate, &length);
fseek(mp4state.aacfile, tagsize, SEEK_SET);
bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
if (bread != 768*6)
mp4state.m_at_eof = 1;
else
mp4state.m_at_eof = 0;
mp4state.m_aac_bytes_into_buffer = bread;
mp4state.m_aac_bytes_consumed = 0;
mp4state.m_header_type = 1;
}
} else if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0) {
int skip_size = (mp4state.m_aac_buffer[4] & 0x80) ? 9 : 0;
bitrate = ((unsigned int)(mp4state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
((unsigned int)mp4state.m_aac_buffer[5 + skip_size]<<11) |
((unsigned int)mp4state.m_aac_buffer[6 + skip_size]<<3) |
((unsigned int)mp4state.m_aac_buffer[7 + skip_size] & 0xE0);
length = (double)file_length(mp4state.aacfile);
if (length == -1)
{
//module.is_seekable = 0;
length = 0;
} else {
length = ((double)length*8.)/((double)bitrate) + 0.5;
}
mp4state.m_header_type = 2;
} else {
length = (double)file_length(mp4state.aacfile);
length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
//module.is_seekable = 1;
}
mp4state.m_length = (int)(length*1000.);
fill_buffer(&mp4state);
if ((mp4state.m_aac_bytes_consumed = faacDecInit(mp4state.hDecoder,
mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
&mp4state.samplerate, &mp4state.channels)) < 0)
{
show_error(module.hMainWindow, "Can't initialize decoder library.");
return -1;
}
advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
if (mp4state.m_header_type == 2)
avg_bitrate = bitrate;
else
avg_bitrate = bitrate*1000;
} else {
mp4state.hDecoder = faacDecOpen();
if (!mp4state.hDecoder)
{
show_error(module.hMainWindow, "Unable to open decoder library.");
return -1;
}
config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
config->outputFormat = m_resolution + 1;
config->downMatrix = m_downmix;
faacDecSetConfiguration(mp4state.hDecoder, config);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -