/* * Input : Filename * Output : 1 if succesful 0 if not */ int openFile(const char * name) { readOff = readBuf; if((fp = fopen(name, "rb"))) { if(strstr(name, ".aac") || strstr(name, ".AAC")) { dec_state = DEC_AAC; if((decoder = AACInitDecoder())) { if(fill_readBuffer(readBuf, &readOff, READ_BUF_SIZE, &dataLeft) == READ_BUF_SIZE) { int ret = 0; int bitOffset = 0, bitsAvail = dataLeft << 3; if(IS_ADIF(readBuf)) ret = UnpackADIFHeader((AACDecInfo*)decoder, &readOff, &bitOffset, &bitsAvail); else ret = UnpackADTSHeader((AACDecInfo*)decoder, &readOff, &bitOffset, &bitsAvail); if(!ret) { AACGetLastFrameInfo(decoder, &inf); readOff = readBuf; dataLeft = READ_BUF_SIZE; return 1; } } } } else { dec_state = DEC_MP4; mp4cb.user_data = fp; if((infile = mp4ff_open_read(&mp4cb))) { if ((track = findAudioTrack(infile)) >= 0) { /* Decoder failed to initialize */ if((decoder = AACInitDecoder())) { /* Decoder should be updated to decode raw blocks in the mp4 * IMPORTANT: * mp4ff_get_channel_count will return the wrong value for mono in this state */ inf.sampRateCore = mp4ff_get_sample_rate(infile, track); samples = mp4ff_num_samples(infile, track); /* DECODER CONFIG: [AAAA ABBB] [BCCC CDEF] A)object type B)frequency index C)channel configuration D)bit: frame length flag E)bit: dependsOnCoreCoder F)bit: extensionFlag */ unsigned char * config_buf; unsigned int config_bufSize; mp4ff_get_decoder_config(infile, track, &config_buf, &config_bufSize); inf.profile = AAC_PROFILE_LC; inf.nChans = (config_buf[1] >> 3) & 0xF; free(config_buf); if(!AACSetRawBlockParams(decoder, 0, &inf)) return 1; } } } } }
ReadStatus MP4Reader::parse() { mp4AudioSpecificConfig cfg; FXuchar* buffer; FXuint size; FXint ntracks; FXASSERT(handle==NULL); FXASSERT(packet); handle = mp4ff_open_read(&callback); if (handle==NULL) goto error; ntracks = mp4ff_total_tracks(handle); if (ntracks<=0) goto error; for (FXint i=0;i<ntracks;i++) { if ((mp4ff_get_decoder_config(handle,i,&buffer,&size)==0) && buffer && size) { if (NeAACDecAudioSpecificConfig(buffer,size,&cfg)==0) { af.set(AP_FORMAT_S16,mp4ff_get_sample_rate(handle,i),mp4ff_get_channel_count(handle,i)); af.debug(); if (size>packet->space()) { GM_DEBUG_PRINT("MP4 config buffer is too big for decoder packet"); free(buffer); goto error; } track=i; frame=0; nframes=mp4ff_num_samples(handle,i); stream_length=mp4ff_get_track_duration(handle,i); packet->append(buffer,size); packet->flags|=AAC_FLAG_CONFIG|AAC_FLAG_FRAME; engine->decoder->post(new ConfigureEvent(af,Codec::AAC)); send_meta(); engine->decoder->post(packet); packet=NULL; flags|=FLAG_PARSED; free(buffer); return ReadOk; } free(buffer); } } error: packet->unref(); return ReadError; }
static int xmms_mp4_get_track (xmms_xform_t *xform, mp4ff_t *infile) { glong chans, rate; int i; int numTracks = mp4ff_total_tracks (infile); /* find first suitable audio track */ for (i = 0; i < numTracks; i++) { gint object_type = mp4ff_get_audio_type (infile, i); /* these identifiers are mostly from VLC code */ switch (object_type) { case 0x40: /* MPEG-4 audio */ case 0x66: /* MPEG-2 AAC */ case 0x67: /* MPEG-2 AAC LC */ case 0x68: /* MPEG-2 AAC SSR */ xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/aac", XMMS_STREAM_TYPE_END); return i; case 0x69: /* MPEG-2 audio */ case 0x6B: /* MPEG-1 audio */ continue; case 0xff: /* ALAC */ chans = mp4ff_get_channel_count (infile, i); rate = mp4ff_get_sample_rate (infile, i); if (chans <= 0 || rate <= 0) { XMMS_DBG ("Bad ALAC audio track %d", i); continue; } xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/x-ffmpeg-alac", XMMS_STREAM_TYPE_FMT_SAMPLERATE, (int)rate, XMMS_STREAM_TYPE_FMT_CHANNELS, (int)chans, XMMS_STREAM_TYPE_END); return i; default: continue; } } /* can't decode this */ return -1; }
static void xmms_mp4_get_mediainfo (xmms_xform_t *xform) { xmms_mp4_data_t *data; const gchar *metakey; glong temp; gint i, num_items; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); if ((temp = mp4ff_get_sample_rate (data->mp4ff, data->track)) > 0) { glong srate = temp; if ((temp = mp4ff_get_track_duration (data->mp4ff, data->track)) >= 0) { glong msec = ((gint64) temp) * 1000 / srate; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, xmms_xform_metadata_set_int (xform, metakey, msec); } } if ((temp = mp4ff_get_avg_bitrate (data->mp4ff, data->track)) >= 0) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, temp); } num_items = mp4ff_meta_get_num_items (data->mp4ff); for (i = 0; i < num_items; i++) { gchar *key, *value; guint length; length = mp4ff_meta_get_by_index (data->mp4ff, i, &key, &value); if (length > 0) { if (!xmms_xform_metadata_mapper_match (xform, key, value, length)) { /* iTunSMPB should be handled in xmms_mp4_gapless_try */ if (0 != g_ascii_strcasecmp (key, "iTunSMPB")) { XMMS_DBG ("Unhandled tag '%s' = '%s'", key, value); } } g_free (key); g_free (value); } } }
/* * Input : Filename * Output : 1 if succesful -1 if not */ int mp4_openFile(char * name) { if((sndFile = fopen(name, "rb"))) { mp4cb.user_data = sndFile; if((infile = mp4ff_open_read(&mp4cb))) { if ((track = findAudioTrack(infile)) >= 0) { /* Decoder failed to initialize */ if((decoder = AACInitDecoder())) { /* Decoder should be updated to decode raw blocks in the mp4 */ inf.sampRateCore = mp4ff_get_sample_rate(infile, track); inf.nChans = mp4ff_get_channel_count(infile,track); /* AACSetRawBlockParams will fail if not set */ inf.profile = AAC_PROFILE_LC; samples = mp4ff_num_samples(infile, track); if(!AACSetRawBlockParams(decoder, 0, &inf)) return 0; } } } } return -1; /* sndFile == NULL */ }
// returns -1 for error, 0 for mp4, 1 for aac int aac_probe (DB_FILE *fp, const char *fname, MP4FILE_CB *cb, float *duration, int *samplerate, int *channels, int *totalsamples, int *mp4track, MP4FILE *pmp4) { // try mp4 if (mp4track) { *mp4track = -1; } if (*pmp4) { *pmp4 = NULL; } *duration = -1; #ifdef USE_MP4FF mp4ff_t *mp4 = mp4ff_open_read (cb); #else MP4FileHandle mp4 = MP4ReadProvider (fname, 0, cb); #endif if (!mp4) { trace ("not an mp4 file\n"); return -1; } if (pmp4) { *pmp4 = mp4; } #ifdef USE_MP4FF int ntracks = mp4ff_total_tracks (mp4); if (ntracks > 0) { trace ("m4a container detected, ntracks=%d\n", ntracks); int i = -1; trace ("looking for mp4 data...\n"); int sr = -1; for (i = 0; i < ntracks; i++) { unsigned char* buff = 0; unsigned int buff_size = 0; mp4AudioSpecificConfig mp4ASC; mp4ff_get_decoder_config(mp4, i, &buff, &buff_size); if(buff){ int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); sr = mp4ASC.samplingFrequency; free(buff); if(rc < 0) continue; break; } } if (i != ntracks) { trace ("mp4 track: %d\n", i); if (sr != -1) { *samplerate = sr; } else { *samplerate = mp4ff_get_sample_rate (mp4, i); } *channels = mp4ff_get_channel_count (mp4, i); int samples = mp4ff_num_samples(mp4, i) * 1024; samples = (int64_t)samples * (*samplerate) / mp4ff_time_scale (mp4, i); trace ("mp4 nsamples=%d, samplerate=%d, timescale=%d, duration=%lld\n", samples, *samplerate, mp4ff_time_scale(mp4, i), mp4ff_get_track_duration(mp4, i)); *duration = (float)samples / (*samplerate); if (totalsamples) { *totalsamples = samples; } if (mp4track) { *mp4track = i; } if (!*pmp4) { mp4ff_close (mp4); } return 0; } } #else MP4FileHandle mp4File = mp4; MP4TrackId trackId = MP4FindTrackId(mp4File, 0, "audio", 0); trace ("trackid: %d\n", trackId); uint32_t timeScale = MP4GetTrackTimeScale(mp4File, trackId); MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId); MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId); u_int8_t* pConfig; uint32_t configSize = 0; bool res = MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize); if (res && pConfig) { mp4AudioSpecificConfig mp4ASC; int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC); free (pConfig); if (rc >= 0) { *samplerate = mp4ASC.samplingFrequency; *channels = MP4GetTrackAudioChannels (mp4File, trackId); // int64_t duration = MP4ConvertFromTrackDuration (mp4File, trackId, trackDuration, timeScale); int samples = MP4GetTrackNumberOfSamples (mp4File, trackId) * 1024 * (*channels); trace ("mp4 nsamples=%d, timescale=%d, samplerate=%d\n", samples, timeScale, *samplerate); *duration = (float)samples / (*samplerate); if (totalsamples) { *totalsamples = samples; } if (mp4track) { *mp4track = trackId; } if (!*pmp4) { MP4Close (mp4); } return 0; } } #endif if (*pmp4) { *pmp4 = NULL; } if (mp4) { #if USE_MP4FF mp4ff_close (mp4); #else MP4Close (mp4); #endif mp4 = NULL; } trace ("mp4 track not found, looking for aac stream...\n"); // not an mp4, try raw aac #if USE_MP4FF deadbeef->rewind (fp); #endif if (parse_aac_stream (fp, samplerate, channels, duration, totalsamples) == -1) { trace ("aac stream not found\n"); return -1; } trace ("found aac stream\n"); return 1; }