📄 qcdmp4.c
字号:
{ 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, TrackExtents *ext, int flags){ int len; FILE *fh; len = getsonglength((char *)medianame); fh = fopen(medianame, "rb"); if (len <= 0 || !fh) return 0; ext->track = 1; ext->start = 0; ext->end = len; ext->bytesize = file_length(fh); fclose(fh); ext->unitpersec = 1000; return 1;}//void eq_set(int on, char data[10], int preamp)//{//}static void remap_channels(unsigned char *data, unsigned int samples, unsigned int bps){ unsigned int i; switch (bps) { case 8: { unsigned char r1, r2, r3, r4, r5, r6; for (i = 0; i < samples; i += 6) { r1 = data[i]; r2 = data[i+1]; r3 = data[i+2]; r4 = data[i+3]; r5 = data[i+4]; r6 = data[i+5]; data[i] = r2; data[i+1] = r3; data[i+2] = r1; data[i+3] = r6; data[i+4] = r4; data[i+5] = r5; } } break; case 16: default: { unsigned short r1, r2, r3, r4, r5, r6; unsigned short *sample_buffer = (unsigned short *)data; for (i = 0; i < samples; i += 6) { r1 = sample_buffer[i]; r2 = sample_buffer[i+1]; r3 = sample_buffer[i+2]; r4 = sample_buffer[i+3]; r5 = sample_buffer[i+4]; r6 = sample_buffer[i+5]; sample_buffer[i] = r2; sample_buffer[i+1] = r3; sample_buffer[i+2] = r1; sample_buffer[i+3] = r6; sample_buffer[i+4] = r4; sample_buffer[i+5] = r5; } } break; case 24: case 32: { unsigned int r1, r2, r3, r4, r5, r6; unsigned int *sample_buffer = (unsigned int *)data; for (i = 0; i < samples; i += 6) { r1 = sample_buffer[i]; r2 = sample_buffer[i+1]; r3 = sample_buffer[i+2]; r4 = sample_buffer[
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -