📄 qcdmp4.c
字号:
mp4state.mp4file = MP4Read(mp4state.filename, 0);
if (!mp4state.mp4file)
{
show_error(module.hMainWindow, "Unable to open file.");
faacDecClose(mp4state.hDecoder);
return -1;
}
if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
{
show_error(module.hMainWindow, "Unsupported Audio track type.");
faacDecClose(mp4state.hDecoder);
MP4Close(mp4state.mp4file);
return -1;
}
buffer = NULL;
buffer_size = 0;
MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
&buffer, &buffer_size);
if (!buffer)
{
faacDecClose(mp4state.hDecoder);
MP4Close(mp4state.mp4file);
return -1;
}
if(faacDecInit2(mp4state.hDecoder, buffer, buffer_size,
&mp4state.samplerate, &mp4state.channels) < 0)
{
/* If some error initializing occured, skip the file */
faacDecClose(mp4state.hDecoder);
MP4Close(mp4state.mp4file);
if (buffer) free (buffer);
return -1;
}
/* for gapless decoding */
{
mp4AudioSpecificConfig mp4ASC;
mp4state.timescale = MP4GetTrackTimeScale(mp4state.mp4file, mp4state.mp4track);
mp4state.framesize = 1024;
mp4state.useAacLength = 0;
if (buffer)
{
if (AudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
{
if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
}
}
}
free(buffer);
avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
mp4state.sampleId = 1;
//module.is_seekable = 1;
}
if (mp4state.channels == 0)
{
show_error(module.hMainWindow, "Number of channels not supported for playback.");
faacDecClose(mp4state.hDecoder);
if (mp4state.filetype)
fclose(mp4state.aacfile);
else
MP4Close(mp4state.mp4file);
return -1;
}
if (m_downmix && (mp4state.channels == 5 || mp4state.channels == 6))
mp4state.channels = 2;
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.cbSize = 0;
wf.nChannels = mp4state.channels;
wf.wBitsPerSample = res_table[m_resolution];
wf.nSamplesPerSec = mp4state.samplerate;
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
if (!module.QCDCallbacks.toPlayer.OutputOpen(mp4state.filename, &wf)) // error opening device
{
faacDecClose(mp4state.hDecoder);
if (mp4state.filetype)
fclose(mp4state.aacfile);
else
MP4Close(mp4state.mp4file);
return -1;
}
mp4state.paused = 0;
mp4state.decode_pos_ms = 0;
mp4state.seek_needed = -1;
//// initialize vis stuff
//module.SAVSAInit(maxlatency, mp4state.samplerate);
//module.VSASetInfo((int)mp4state.channels, mp4state.samplerate);
br = (int)floor(((float)avg_bitrate + 500.0)/1000.0 + 0.5);
sr = (int)floor((float)mp4state.samplerate/1000.0 + 0.5);
ai.struct_size = sizeof(AudioInfo);
ai.frequency = sr*1000;
ai.bitrate = br*1000;
ai.mode = (mp4state.channels == 2) ? 0 : 3;
ai.layer = 0;
ai.level = 0;
strcpy(ai.text, mp4state.filetype ? "AAC" : "MP4");
module.QCDCallbacks.Service(opSetAudioInfo, &ai, sizeof(AudioInfo), 0);
//module.outMod->SetVolume(-666); // set the output plug-ins default volume
killPlayThread = 0;
if (mp4state.filetype)
{
if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AACPlayThread,
(void *)&killPlayThread, 0, &thread_id)) == NULL)
{
show_error(module.hMainWindow, "Cannot create playback thread");
faacDecClose(mp4state.hDecoder);
fclose(mp4state.aacfile);
return -1;
}
} else {
if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MP4PlayThread,
(void *)&killPlayThread, 0, &thread_id)) == NULL)
{
show_error(module.hMainWindow, "Cannot create playback thread");
faacDecClose(mp4state.hDecoder);
MP4Close(mp4state.mp4file);
return -1;
}
}
SetThreadAffinityMask(play_thread_handle, 1);
SetThreadPriority(play_thread_handle, priority_table[m_priority]);
}
return 1;
}
//-----------------------------------------------------------------------------
int Pause(const char* medianame, int flags)
{
#ifdef DEBUG_OUTPUT
in_mp4_DebugOutput("pause");
#endif
mp4state.paused = flags;
if (module.QCDCallbacks.toPlayer.OutputPause(flags))
return 1;
mp4state.paused = !flags;
return 0;
}
//void unpause()
//{
//#ifdef DEBUG_OUTPUT
// in_mp4_DebugOutput("unpause");
//#endif
//
// mp4state.paused = 0;
// module.outMod->Pause(0);
//}
//
//int ispaused()
//{
//#ifdef DEBUG_OUTPUT
// in_mp4_DebugOutput("ispaused");
//#endif
//
// return mp4state.paused;
//}
//-----------------------------------------------------------------------------
void SetVolume(int levelleft, int levelright, int flags)
{
#ifdef DEBUG_OUTPUT
in_mp4_DebugOutput("setvolume");
#endif
module.QCDCallbacks.toPlayer.OutputSetVol(levelleft, levelright, flags);
}
//void setpan(int pan)
//{
//#ifdef DEBUG_OUTPUT
// in_mp4_DebugOutput("setpan");
//#endif
//
// module.outMod->SetPan(pan);
//}
//-----------------------------------------------------------------------------
int Stop(const char* medianame, int flags)
{
struct seek_list *target = mp4state.m_head;
#ifdef DEBUG_OUTPUT
in_mp4_DebugOutput("stop");
#endif
if (medianame && *medianame && stricmp(mp4state.filename, medianame) == 0)
{
module.QCDCallbacks.toPlayer.OutputStop(flags);
killPlayThread = 1;
if (play_thread_handle != INVALID_HANDLE_VALUE)
{
if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
TerminateThread(play_thread_handle,0);
CloseHandle(play_thread_handle);
play_thread_handle = INVALID_HANDLE_VALUE;
}
if (mp4state.m_aac_buffer)
free(mp4state.m_aac_buffer);
while (target)
{
struct seek_list *tmp = target;
target = target->next;
if (tmp) free(tmp);
}
faacDecClose(mp4state.hDecoder);
if (mp4state.filetype)
fclose(mp4state.aacfile);
else
MP4Close(mp4state.mp4file);
//module.outMod->Close();
//module.SAVSADeInit();
mp4state.filename[0] = '\0';
mp4state.paused = 0;
}
return 1;
}
int getsonglength(const char *fn)
{
long msDuration = 0;
if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
{
int track;
MP4Duration length;
MP4FileHandle file;
file = MP4Read(fn, 0);
if (!file)
return 0;
if ((track = GetAACTrack(file)) < 0)
{
MP4Close(file);
return -1;
}
length = MP4GetTrackDuration(file, track);
msDuration = MP4ConvertFromTrackDuration(file, track,
length, MP4_MSECS_TIME_SCALE);
MP4Close(file);
return msDuration;
} else {
int tagsize = 0;
int bread = 0;
double length = 0.;
__int64 bitrate = 128;
struct seek_list *target;
state len_state;
memset(&len_state, 0, sizeof(state));
if (!(len_state.aacfile = fopen(fn, "rb")))
{
// error
return 0;
}
len_state.m_at_eof = 0;
if (!(len_state.m_aac_buffer = (unsigned char*)malloc(768*6)))
{
//console::error("Memory allocation error.", "foo_mp4");
return 0;
}
memset(len_state.m_aac_buffer, 0, 768*6);
bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
len_state.m_aac_bytes_into_buffer = bread;
len_state.m_aac_bytes_consumed = 0;
len_state.m_file_offset = 0;
if (bread != 768*6)
len_state.m_at_eof = 1;
if (!memcmp(len_state.m_aac_buffer, "ID3", 3))
{
/* high bit is not used */
tagsize = (len_state.m_aac_buffer[6] << 21) | (len_state.m_aac_buffer[7] << 14) |
(len_state.m_aac_buffer[8] << 7) | (len_state.m_aac_buffer[9] << 0);
tagsize += 10;
advance_buffer(&len_state, tagsize);
}
len_state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
len_state.m_tail = len_state.m_head;
len_state.m_tail->next = NULL;
len_state.m_header_type = 0;
if ((len_state.m_aac_buffer[0] == 0xFF) && ((len_state.m_aac_buffer[1] & 0xF6) == 0xF0))
{
if (1) //(m_reader->can_seek())
{
adts_parse(&len_state, &bitrate, &length);
fseek(len_state.aacfile, tagsize, SEEK_SET);
bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
if (bread != 768*6)
len_state.m_at_eof = 1;
else
len_state.m_at_eof = 0;
len_state.m_aac_bytes_into_buffer = bread;
len_state.m_aac_bytes_consumed = 0;
len_state.m_header_type = 1;
}
} else if (memcmp(len_state.m_aac_buffer, "ADIF", 4) == 0) {
int skip_size = (len_state.m_aac_buffer[4] & 0x80) ? 9 : 0;
bitrate = ((unsigned int)(len_state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
((unsigned int)len_state.m_aac_buffer[5 + skip_size]<<11) |
((unsigned int)len_state.m_aac_buffer[6 + skip_size]<<3) |
((unsigned int)len_state.m_aac_buffer[7 + skip_size] & 0xE0);
length = (double)file_length(len_state.aacfile);
if (length == -1)
length = 0;
else
length = ((double)length*8.)/((double)bitrate) + 0.5;
len_state.m_header_type = 2;
} else {
length = (double)file_length(len_state.aacfile);
length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
len_state.m_header_type = 0;
}
if (len_state.m_aac_buffer)
free(len_state.m_aac_buffer);
target = len_state.m_head;
while (target)
{
struct seek_list *tmp = target;
target = target->next;
if (tmp) free(tmp);
}
fclose(len_state.aacfile);
return (int)(length*1000.);
}
}
//int getlength()
//{
// if (!mp4state.filetype)
// {
// int track;
// long msDuration;
// MP4Duration length;
//
// if ((track = GetAACTrack(mp4state.mp4file)) < 0)
// {
// return -1;
// }
//
// length = MP4GetTrackDuration(mp4state.mp4file, track);
//
// msDuration = MP4ConvertFromTrackDuration(mp4state.mp4file, track,
// length, MP4_MSECS_TIME_SCALE);
//
// return msDuration;
// } else {
// return mp4state.m_length;
// }
// return 0;
//}
//-----------------------------------------------------------------------------
int GetCurrentPosition(const char* medianame, long *track, long *offset)
{
return module.QCDCallbacks.toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
}
//void setoutputtime(int time_in_ms)
//{
//#ifdef DEBUG_OUTPUT
// in_mp4_DebugOutput("setoutputtime");
//#endif
//
// mp4state.seek_needed = time_in_ms;
//}
//-----------------------------------------------------------------------------
int GetTrackExtents(const char* medianame, Tra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -