📄 qcdmp4.c
字号:
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); 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -