static gint xmms_mp4_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err) { xmms_mp4_data_t *data; guint size, bytes_read = 0; data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); size = MIN (data->outbuf->len, len); while (size == 0) { guchar *tmpbuf; guint tmpbuflen; gint duration, offset; if (data->sampleid >= data->numsamples) { XMMS_DBG ("MP4 EOF"); return 0; } bytes_read = mp4ff_read_sample (data->mp4ff, data->track, data->sampleid, &tmpbuf, &tmpbuflen); offset = mp4ff_get_sample_offset (data->mp4ff, data->track, data->sampleid); duration = mp4ff_get_sample_duration (data->mp4ff, data->track, data->sampleid); data->sampleid++; xmms_xform_auxdata_set_int (xform, "frame_offset", offset); xmms_xform_auxdata_set_int (xform, "frame_duration", duration); if (bytes_read > 0) { g_string_append_len (data->outbuf, (gchar *) tmpbuf, tmpbuflen); g_free (tmpbuf); } size = MIN (data->outbuf->len, len); } memcpy (buf, data->outbuf->str, size); g_string_erase (data->outbuf, 0, size); return size; }
// Same as Faad.decode (Faad.Mp4.read_sample) but more efficient. Share code? CAMLprim value ocaml_faad_mp4_decode(value m, value track, value sample, value dh) { CAMLparam4(m, track, sample, dh); CAMLlocal1(outbuf); mp4_t *mp = Mp4_val(m); int t = Int_val(track); int s = Int_val(sample); NeAACDecHandle dec = Dec_val(dh); NeAACDecFrameInfo frameInfo; unsigned char *inbuf = NULL; unsigned int inbuflen = 0; float *data; int c, i, ret; caml_enter_blocking_section(); ret = mp4ff_read_sample(mp->ff, t, s, &inbuf, &inbuflen); caml_leave_blocking_section(); check_err(ret); caml_enter_blocking_section(); data = NeAACDecDecode(dec, &frameInfo, inbuf, inbuflen); caml_leave_blocking_section(); free(inbuf); if (!data) caml_raise_constant(*caml_named_value("ocaml_faad_exn_failed")); if (frameInfo.error != 0) caml_raise_with_arg(*caml_named_value("ocaml_faad_exn_error"), Val_int(frameInfo.error)); outbuf = caml_alloc_tuple(frameInfo.channels); for(c = 0; c < frameInfo.channels; c++) Store_field(outbuf, c, caml_alloc(frameInfo.samples / frameInfo.channels * Double_wosize, Double_array_tag)); for(i = 0; i < frameInfo.samples; i++) Store_double_field(Field(outbuf, i % frameInfo.channels), i / frameInfo.channels, data[i]); CAMLreturn(outbuf); }
CAMLprim value ocaml_faad_mp4_read_sample(value m, value track, value sample) { CAMLparam3(m, track, sample); CAMLlocal1(ans); mp4_t *mp = Mp4_val(m); int t = Int_val(track); int s = Int_val(sample); unsigned char *buf = NULL; unsigned int buflen = 0; int ret; caml_enter_blocking_section(); ret = mp4ff_read_sample(mp->ff, t, s, &buf, &buflen); caml_leave_blocking_section(); check_err(ret); ans = caml_alloc_string(buflen); memcpy(String_val(ans), buf, buflen); free(buf); CAMLreturn(ans); }
int decodeMP4file(char *sndfile, aac_dec_opt *opt) { int track; unsigned long samplerate; unsigned char channels; void *sample_buffer; mp4ff_t *infile; FILE *mp4File; int sampleId, numSamples; audio_file *aufile; NeAACDecHandle hDecoder; NeAACDecFrameInfo frameInfo; unsigned char *buffer; int buffer_size; int first_time = 1; /* initialise the callback structure */ mp4ff_callback_t *mp4cb = malloc(sizeof(mp4ff_callback_t)); mp4File = fopen(opt->filename, "rb"); mp4cb->read = read_callback; mp4cb->seek = seek_callback; mp4cb->user_data = mp4File; infile = mp4ff_open_read(mp4cb); if (!infile) { /* unable to open file */ error_handler("Error opening file: %s\n", opt->filename); return 1; } if ((track = GetAACTrack(infile)) < 0) { error_handler("Unable to find correct AAC sound track in the MP4 file.\n"); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } buffer = NULL; buffer_size = 0; mp4ff_get_decoder_config(infile, track, &buffer, &buffer_size); hDecoder = NeAACDecOpen(); if(NeAACDecInit2(hDecoder, buffer, buffer_size, &samplerate, &channels) < 0) { /* If some error initializing occured, skip the file */ error_handler("Error initializing decoder library.\n"); NeAACDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } if (buffer) free(buffer); numSamples = mp4ff_num_samples(infile, track); for (sampleId = 0; sampleId < numSamples; sampleId++) { int rc; /* get access unit from MP4 file */ buffer = NULL; buffer_size = 0; rc = mp4ff_read_sample(infile, track, sampleId, &buffer, &buffer_size); if (rc == 0) { error_handler("Reading from MP4 file failed.\n"); NeAACDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, buffer_size); if (buffer) free(buffer); opt->progress_update((long)numSamples, sampleId); /* open the sound file now that the number of channels are known */ if (first_time && !frameInfo.error) { if(opt->decode_mode == 0) { if (Set_WIN_Params (INVALID_FILEDESC, samplerate, SAMPLE_SIZE, frameInfo.channels) < 0) { error_handler("\nCan't access %s\n", "WAVE OUT"); NeAACDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return (0); } } else { aufile = open_audio_file(sndfile, samplerate, frameInfo.channels, opt->output_format, opt->file_type, aacChannelConfig2wavexChannelMask(&frameInfo)); if (aufile == NULL) { NeAACDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 0; } } first_time = 0; } if ((frameInfo.error == 0) && (frameInfo.samples > 0)) { if(opt->decode_mode == 0) WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples); else write_audio_file(aufile, sample_buffer, frameInfo.samples, 0); } if (frameInfo.error > 0) { error_handler("Error: %s\n", NeAACDecGetErrorMessage(frameInfo.error)); break; } if(stop_decoding) break; } NeAACDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); if(opt->decode_mode == 0) WIN_Audio_close(); else { if (!first_time) close_audio_file(aufile); } return frameInfo.error; }
static int aac_read (DB_fileinfo_t *_info, char *bytes, int size) { aac_info_t *info = (aac_info_t *)_info; if (info->eof) { trace ("aac_read: received call after eof\n"); return 0; } int samplesize = _info->fmt.channels * _info->fmt.bps / 8; if (!info->file->vfs->is_streaming ()) { if (info->currentsample + size / samplesize > info->endsample) { size = (info->endsample - info->currentsample + 1) * samplesize; if (size <= 0) { trace ("aac_read: eof (current=%d, total=%d)\n", info->currentsample, info->endsample); return 0; } } } int initsize = size; while (size > 0) { if (info->skipsamples > 0 && info->out_remaining > 0) { int skip = min (info->out_remaining, info->skipsamples); if (skip < info->out_remaining) { memmove (info->out_buffer, info->out_buffer + skip * samplesize, (info->out_remaining - skip) * samplesize); } info->out_remaining -= skip; info->skipsamples -= skip; } if (info->out_remaining > 0) { int n = size / samplesize; n = min (info->out_remaining, n); char *src = info->out_buffer; if (info->noremap) { memcpy (bytes, src, n * samplesize); bytes += n * samplesize; src += n * samplesize; } else { int i, j; if (info->remap[0] == -1) { // build remap mtx // FIXME: should build channelmask 1st; then remap based on channelmask for (i = 0; i < _info->fmt.channels; i++) { switch (info->frame_info.channel_position[i]) { case FRONT_CHANNEL_CENTER: trace ("FC->%d\n", i); info->remap[2] = i; break; case FRONT_CHANNEL_LEFT: trace ("FL->%d\n", i); info->remap[0] = i; break; case FRONT_CHANNEL_RIGHT: trace ("FR->%d\n", i); info->remap[1] = i; break; case SIDE_CHANNEL_LEFT: trace ("SL->%d\n", i); info->remap[6] = i; break; case SIDE_CHANNEL_RIGHT: trace ("SR->%d\n", i); info->remap[7] = i; break; case BACK_CHANNEL_LEFT: trace ("RL->%d\n", i); info->remap[4] = i; break; case BACK_CHANNEL_RIGHT: trace ("RR->%d\n", i); info->remap[5] = i; break; case BACK_CHANNEL_CENTER: trace ("BC->%d\n", i); info->remap[8] = i; break; case LFE_CHANNEL: trace ("LFE->%d\n", i); info->remap[3] = i; break; default: trace ("aac: unknown ch(%d)->%d\n", info->frame_info.channel_position[i], i); break; } } for (i = 0; i < _info->fmt.channels; i++) { trace ("%d ", info->remap[i]); } trace ("\n"); if (info->remap[0] == -1) { info->remap[0] = 0; } if ((_info->fmt.channels == 1 && info->remap[0] == FRONT_CHANNEL_CENTER) || (_info->fmt.channels == 2 && info->remap[0] == FRONT_CHANNEL_LEFT && info->remap[1] == FRONT_CHANNEL_RIGHT)) { info->noremap = 1; } } for (i = 0; i < n; i++) { for (j = 0; j < _info->fmt.channels; j++) { ((int16_t *)bytes)[j] = ((int16_t *)src)[info->remap[j]]; } src += samplesize; bytes += samplesize; } } size -= n * samplesize; if (n == info->out_remaining) { info->out_remaining = 0; } else { memmove (info->out_buffer, src, (info->out_remaining - n) * samplesize); info->out_remaining -= n; } continue; } char *samples = NULL; if (info->mp4file) { if (info->mp4sample >= info->mp4samples) { break; } unsigned char *buffer = NULL; int buffer_size = 0; #ifdef USE_MP4FF int rc = mp4ff_read_sample (info->mp4file, info->mp4track, info->mp4sample, &buffer, &buffer_size); if (rc == 0) { trace ("mp4ff_read_sample failed\n"); info->eof = 1; break; } #else buffer = info->samplebuffer; buffer_size = info->maxSampleSize; MP4Timestamp sampleTime; MP4Duration sampleDuration; MP4Duration sampleRenderingOffset; bool isSyncSample; MP4ReadSample (info->mp4file, info->mp4track, info->mp4sample, &buffer, &buffer_size, &sampleTime, &sampleDuration, &sampleRenderingOffset, &isSyncSample); // convert timestamp and duration from track time to milliseconds u_int64_t myTime = MP4ConvertFromTrackTimestamp (info->mp4file, info->mp4track, sampleTime, MP4_MSECS_TIME_SCALE); u_int64_t myDuration = MP4ConvertFromTrackDuration (info->mp4file, info->mp4track, sampleDuration, MP4_MSECS_TIME_SCALE); #endif info->mp4sample++; samples = NeAACDecDecode(info->dec, &info->frame_info, buffer, buffer_size); if (buffer) { free (buffer); } if (!samples) { break; } } else { if (info->remaining < AAC_BUFFER_SIZE) { trace ("fread from offs %lld\n", deadbeef->ftell (info->file)); size_t res = deadbeef->fread (info->buffer + info->remaining, 1, AAC_BUFFER_SIZE-info->remaining, info->file); info->remaining += res; trace ("remain: %d\n", info->remaining); if (!info->remaining) { break; } } trace ("NeAACDecDecode %d bytes\n", info->remaining) samples = NeAACDecDecode (info->dec, &info->frame_info, info->buffer, info->remaining); trace ("samples =%p\n", samples); if (!samples) { trace ("NeAACDecDecode failed with error %s (%d), consumed=%d\n", NeAACDecGetErrorMessage(info->frame_info.error), (int)info->frame_info.error, info->frame_info.bytesconsumed); if (info->num_errors > 10) { trace ("NeAACDecDecode failed %d times, interrupting\n", info->num_errors); break; } info->num_errors++; info->remaining = 0; continue; } info->num_errors=0; int consumed = info->frame_info.bytesconsumed; if (consumed > info->remaining) { trace ("NeAACDecDecode consumed more than available! wtf?\n"); break; } if (consumed == info->remaining) { info->remaining = 0; } else if (consumed > 0) { memmove (info->buffer, info->buffer + consumed, info->remaining - consumed); info->remaining -= consumed; } } if (info->frame_info.samples > 0) { memcpy (info->out_buffer, samples, info->frame_info.samples * 2); info->out_remaining = info->frame_info.samples / info->frame_info.channels; } } info->currentsample += (initsize-size) / samplesize; return initsize-size; }
static void *mp4Decode(void *args) { FILE* mp4file; pthread_mutex_lock(&mutex); seekPosition = -1; bPlaying = TRUE; if(!(mp4file = fopen(args, "rb"))){ g_print("MP4!AAC - Can't open file\n"); g_free(args); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } mp4_get_file_type(mp4file); fseek(mp4file, 0, SEEK_SET); if(mp4cfg.file_type == FILE_MP4){// We are reading a MP4 file mp4ff_callback_t* mp4cb; mp4ff_t* infile; gint mp4track; mp4cb = getMP4FF_cb(mp4file); if(!(infile = mp4ff_open_read(mp4cb))){ g_print("MP4 - Can't open file\n"); goto end; } if((mp4track = getAACTrack(infile)) < 0){ /* * TODO: check here for others Audio format..... * */ g_print("Unsupported Audio track type\n"); g_free(args); fclose(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); }else{ NeAACDecHandle decoder; unsigned char *buffer = NULL; guint bufferSize = 0; gulong samplerate; guchar channels; //guint avgBitrate; //MP4Duration duration; int msDuration; int numSamples; int sampleID = 0; unsigned int framesize; mp4AudioSpecificConfig mp4ASC; gchar *xmmstitle; decoder = NeAACDecOpen(); mp4ff_get_decoder_config(infile, mp4track, &buffer, &bufferSize); if(NeAACDecInit2(decoder, buffer, bufferSize, &samplerate, &channels)<0){ goto end; } if(buffer){ framesize = 1024; if(NeAACDecAudioSpecificConfig(buffer, bufferSize, &mp4ASC) >= 0){ if(mp4ASC.frameLengthFlag == 1) framesize = 960; if(mp4ASC.sbr_present_flag == 1) framesize *= 2; } g_free(buffer); } if(channels == 0){ g_print("Number of Channels not supported\n"); goto end; } //duration = MP4GetTrackDuration(mp4file, mp4track); //msDuration = MP4ConvertFromTrackDuration(mp4file, mp4track, // duration,MP4_MSECS_TIME_SCALE); //msDuration = mp4ff_get_track_duration(infile, mp4track); //printf("%d\n", msDuration); //numSamples = MP4GetTrackNumberOfSamples(mp4file, mp4track); numSamples = mp4ff_num_samples(infile, mp4track); { float f = 1024.0; if(mp4ASC.sbr_present_flag == 1) f = f * 2.0; msDuration = ((float)numSamples*(float)(f-1.0)/ (float)samplerate)*1000; } xmmstitle = getMP4title(infile, args); mp4_ip.output->open_audio(FMT_S16_NE, samplerate, channels); mp4_ip.output->flush(0); mp4_ip.set_info(xmmstitle, msDuration, -1, samplerate/1000, channels); g_print("MP4 - %d channels @ %ld Hz\n", channels, samplerate); while(bPlaying){ void* sampleBuffer; faacDecFrameInfo frameInfo; gint rc; if(seekPosition!=-1){ /* duration = MP4ConvertToTrackDuration(mp4file, mp4track, seekPosition*1000, MP4_MSECS_TIME_SCALE); sampleID = MP4GetSampleIdFromTime(mp4file, mp4track, duration, 0); */ float f = 1024.0; if(mp4ASC.sbr_present_flag == 1) f = f * 2.0; sampleID = (float)seekPosition*(float)samplerate/(float)(f-1.0); mp4_ip.output->flush(seekPosition*1000); seekPosition = -1; } buffer=NULL; bufferSize=0; rc = mp4ff_read_sample(infile, mp4track, sampleID++, &buffer, &bufferSize); //g_print("%d/%d\n", sampleID-1, numSamples); if((rc==0) || (buffer== NULL)){ g_print("MP4: read error\n"); sampleBuffer = NULL; sampleID=0; mp4_ip.output->buffer_free(); goto end; }else{ sampleBuffer = NeAACDecDecode(decoder, &frameInfo, buffer, bufferSize); if(frameInfo.error > 0){ g_print("MP4: %s\n", faacDecGetErrorMessage(frameInfo.error)); goto end; } if(buffer){ g_free(buffer); buffer=NULL; bufferSize=0; } while(bPlaying && mp4_ip.output->buffer_free()<frameInfo.samples<<1) xmms_usleep(30000); } mp4_ip.add_vis_pcm(mp4_ip.output->written_time(), FMT_S16_NE, channels, frameInfo.samples<<1, sampleBuffer); mp4_ip.output->write_audio(sampleBuffer, frameInfo.samples<<1); if(sampleID >= numSamples){ break; } } while(bPlaying && mp4_ip.output->buffer_playing() && mp4_ip.output->buffer_free()){ xmms_usleep(10000); } end: mp4_ip.output->close_audio(); g_free(args); NeAACDecClose(decoder); if(infile) mp4ff_close(infile); if(mp4cb) g_free(mp4cb); bPlaying = FALSE; fclose(mp4file); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } }else{ // WE ARE READING AN AAC FILE FILE *file = NULL; NeAACDecHandle decoder = 0; guchar *buffer = 0; gulong bufferconsumed = 0; gulong samplerate = 0; guchar channels; gulong buffervalid = 0; TitleInput* input; gchar *temp = g_strdup(args); gchar *ext = strrchr(temp, '.'); gchar *xmmstitle = NULL; NeAACDecConfigurationPtr config; if((file = fopen(args, "rb")) == 0){ g_print("AAC: can't find file %s\n", args); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } if((decoder = NeAACDecOpen()) == NULL){ g_print("AAC: Open Decoder Error\n"); fclose(file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } config = NeAACDecGetCurrentConfiguration(decoder); config->useOldADTSFormat = 0; NeAACDecSetConfiguration(decoder, config); if((buffer = g_malloc(BUFFER_SIZE)) == NULL){ g_print("AAC: error g_malloc\n"); fclose(file); bPlaying = FALSE; NeAACDecClose(decoder); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } if((buffervalid = fread(buffer, 1, BUFFER_SIZE, file))==0){ g_print("AAC: Error reading file\n"); g_free(buffer); fclose(file); bPlaying = FALSE; NeAACDecClose(decoder); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } XMMS_NEW_TITLEINPUT(input); input->file_name = g_basename(temp); input->file_ext = ext ? ext+1 : NULL; input->file_path = temp; if(!strncmp(buffer, "ID3", 3)){ gint size = 0; fseek(file, 0, SEEK_SET); size = (buffer[6]<<21) | (buffer[7]<<14) | (buffer[8]<<7) | buffer[9]; size+=10; fread(buffer, 1, size, file); buffervalid = fread(buffer, 1, BUFFER_SIZE, file); } xmmstitle = xmms_get_titlestring(xmms_get_gentitle_format(), input); if(xmmstitle == NULL) xmmstitle = g_strdup(input->file_name); if(temp) g_free(temp); if(input->performer) g_free(input->performer); if(input->album_name) g_free(input->album_name); if(input->track_name) g_free(input->track_name); if(input->genre) g_free(input->genre); g_free(input); bufferconsumed = NeAACDecInit(decoder, buffer, buffervalid, &samplerate, &channels); if(mp4_ip.output->open_audio(FMT_S16_NE,samplerate,channels) == FALSE){ g_print("AAC: Output Error\n"); g_free(buffer); buffer=0; faacDecClose(decoder); fclose(file); mp4_ip.output->close_audio(); /* if(positionTable){ g_free(positionTable); positionTable=0; } */ g_free(xmmstitle); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } //if(bSeek){ //mp4_ip.set_info(xmmstitle, lenght*1000, -1, samplerate, channels); //}else{ mp4_ip.set_info(xmmstitle, -1, -1, samplerate, channels); //} mp4_ip.output->flush(0); while(bPlaying && buffervalid > 0){ NeAACDecFrameInfo finfo; unsigned long samplesdecoded; char* sample_buffer = NULL; /* if(bSeek && seekPosition!=-1){ fseek(file, positionTable[seekPosition], SEEK_SET); bufferconsumed=0; buffervalid = fread(buffer, 1, BUFFER_SIZE, file); aac_ip.output->flush(seekPosition*1000); seekPosition=-1; } */ if(bufferconsumed > 0){ memmove(buffer, &buffer[bufferconsumed], buffervalid-bufferconsumed); buffervalid -= bufferconsumed; buffervalid += fread(&buffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file); bufferconsumed = 0; } sample_buffer = NeAACDecDecode(decoder, &finfo, buffer, buffervalid); if(finfo.error){ config = NeAACDecGetCurrentConfiguration(decoder); if(config->useOldADTSFormat != 1){ NeAACDecClose(decoder); decoder = NeAACDecOpen(); config = NeAACDecGetCurrentConfiguration(decoder); config->useOldADTSFormat = 1; NeAACDecSetConfiguration(decoder, config); finfo.bytesconsumed=0; finfo.samples = 0; NeAACDecInit(decoder, buffer, buffervalid, &samplerate, &channels); }else{ g_print("FAAD2 Warning %s\n", NeAACDecGetErrorMessage(finfo.error)); buffervalid = 0; } } bufferconsumed += finfo.bytesconsumed; samplesdecoded = finfo.samples; if((samplesdecoded<=0) && !sample_buffer){ g_print("AAC: error sample decoding\n"); continue; } while(bPlaying && mp4_ip.output->buffer_free() < (samplesdecoded<<1)){ xmms_usleep(10000); } mp4_ip.add_vis_pcm(mp4_ip.output->written_time(), FMT_S16_LE, channels, samplesdecoded<<1, sample_buffer); mp4_ip.output->write_audio(sample_buffer, samplesdecoded<<1); } while(bPlaying && mp4_ip.output->buffer_playing()){ xmms_usleep(10000); } mp4_ip.output->buffer_free(); mp4_ip.output->close_audio(); bPlaying = FALSE; g_free(buffer); NeAACDecClose(decoder); g_free(xmmstitle); fclose(file); seekPosition = -1; /* if(positionTable){ g_free(positionTable); positionTable=0; } */ bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } }
static aac_chapter_t * aac_load_itunes_chapters (mp4ff_t *mp4, /* out */ int *num_chapters, int samplerate) { *num_chapters = 0; int i_entry_count = mp4ff_chap_get_num_tracks (mp4); int i_tracks = mp4ff_total_tracks (mp4); int i, j; for( i = 0; i < i_entry_count; i++ ) { for( j = 0; j < i_tracks; j++ ) { int32_t tt = mp4ff_get_track_type (mp4, j); trace ("aac: i_tracks=%d found track id=%d type=%d (expected %d %d)\n", i_tracks, mp4ff_get_track_id (mp4, j), mp4ff_get_track_type (mp4, j), mp4ff_chap_get_track_id (mp4, i), TRACK_TEXT); if(mp4ff_chap_get_track_id (mp4, i) == mp4ff_get_track_id (mp4, j) && mp4ff_get_track_type (mp4, j) == TRACK_TEXT) { trace ("aac: found subt track\n"); break; } } if( j < i_tracks ) { int i_sample_count = mp4ff_num_samples (mp4, j); int i_sample; aac_chapter_t *chapters = malloc (sizeof (aac_chapter_t) * i_sample_count); memset (chapters, 0, sizeof (aac_chapter_t) * i_sample_count); *num_chapters = 0; int64_t total_dur = 0; int64_t curr_sample = 0; for( i_sample = 0; i_sample < i_sample_count; i_sample++ ) { #if 0 const int64_t i_dts = mp4ff_get_track_dts (mp4, j, i_sample); const int64_t i_pts_delta = mp4ff_get_track_pts_delta(mp4, j, i_sample); trace ("i_dts = %lld, i_pts_delta = %lld\n", i_dts, i_pts_delta); const unsigned int i_size = mp4ff_get_track_sample_size(mp4, j, i_sample); if (i_size <= 0) { continue; } int64_t i_time_offset = i_dts + max (i_pts_delta, 0); #endif int32_t dur = (int64_t)1000 * mp4ff_get_sample_duration (mp4, j, i_sample) / mp4ff_time_scale (mp4, j); // milliseconds total_dur += dur; #if 0 trace ("dur: %d %f min // offs: %lld %f (from currsample: %f)\n", dur, dur / 1000.f / 60.f, i_time_offset, i_time_offset / 1000000.f / 60.f, curr_sample * 1000.f/ samplerate); #else trace ("dur: %d %f min\n", dur, dur / 1000.f / 60.f); #endif unsigned char *buffer = NULL; int buffer_size = 0; int rc = mp4ff_read_sample (mp4, j, i_sample, &buffer, &buffer_size); if (rc == 0 || !buffer) { continue; } int len = (buffer[0] << 8) | buffer[1]; len = min (len, buffer_size - 2); if (len > 0) { chapters[*num_chapters].title = strndup (&buffer[2], len); } chapters[*num_chapters].startsample = curr_sample; curr_sample += (int64_t)dur * samplerate / 1000.f; chapters[*num_chapters].endsample = curr_sample - 1; trace ("aac: chapter %d: %s, s=%d e=%d\n", *num_chapters, chapters[*num_chapters].title, chapters[*num_chapters].startsample, chapters[*num_chapters].endsample); if (buffer) { free (buffer); } (*num_chapters)++; } trace ("aac: total dur: %lld (%f min)\n", total_dur, total_dur / 1000.f / 60.f); return chapters; } } return NULL; }
int fdpl_decode_MP4(const char *file_path, size_t &ch, size_t &sr, size_t &samples, std::vector<float> *ch1, std::vector<float> *ch2) { unsigned int track; uint32_t samplerate;//these for init, we prefer to take the ones at frameInfo unsigned char channels; void *sample_buffer; mp4ff_t *infile; FILE *mp4File; int sampleId, numSamples; faacDecHandle hDecoder; faacDecFrameInfo frameInfo; unsigned char *buffer; unsigned int buffer_size; /* initialise the callback structure */ mp4ff_callback_t *mp4cb; mp4cb = (mp4ff_callback_t *)malloc(sizeof(mp4ff_callback_t)); mp4File = fopen(file_path, "rb"); mp4cb->read = read_callback; mp4cb->seek = seek_callback; mp4cb->user_data = mp4File; infile = mp4ff_open_read(mp4cb); if (!infile) { /* unable to open file */ std::cerr<<"Error opening file "<< file_path <<std::endl; return 1; } if ((track = GetAACTrack(infile)) < 0) { std::cerr<<"Unable to find correct AAC sound track in the MP4 file"<<std::endl; mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } buffer = NULL; buffer_size = 0; mp4ff_get_decoder_config(infile, track, &buffer, &buffer_size); hDecoder = faacDecOpen(); if(faacDecInit2(hDecoder, buffer, buffer_size, &samplerate, &channels) < 0) { /* If some error initializing occured, skip the file */ std::cerr<<"Error initializing decoder library"<<std::endl; faacDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } if (buffer) free(buffer); numSamples = mp4ff_num_samples(infile, track); samples = 0; //firstTime = 1; for (sampleId = 0; sampleId < numSamples; sampleId++) { int rc; /* get access unit from MP4 file */ buffer = NULL; buffer_size = 0; rc = mp4ff_read_sample(infile, track, sampleId, &buffer, &buffer_size); if (rc == 0) { std::cerr<<"error while decoding"<<std::endl; faacDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return 1; } sample_buffer = faacDecDecode(hDecoder, &frameInfo, buffer, buffer_size); if (buffer) free(buffer); if ((frameInfo.error == 0) && (frameInfo.samples > 0) && (frameInfo.channels < 3)) { size_t samples_channel = (size_t)frameInfo.samples/(size_t)frameInfo.channels; samples += samples_channel; float *pcm; pcm = (float *)sample_buffer; for(size_t i=0; i<samples_channel; i++){ //writing the samples of each channel in separate float vectors for(size_t j=0; j<frameInfo.channels; j++){ if(j==0){ ch1 -> push_back(pcm[i*frameInfo.channels+j]); }else if(j==1){ ch2 -> push_back(pcm[i*frameInfo.channels+j]); }else{ std::cerr<<"Unexpected number of channels: "<<j<<std::endl; return -1; } } } } if (frameInfo.error > 0) { std::cerr<<"error: "<<faacDecGetErrorMessage(frameInfo.error)<<std::endl; break; } } ch = frameInfo.channels; sr = frameInfo.samplerate; faacDecClose(hDecoder); mp4ff_close(infile); free(mp4cb); fclose(mp4File); return frameInfo.error; }