/***************************************************************************** * DecodeBlock: *****************************************************************************/ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { block_Release( p_block ); return NULL; } /* Remove ADTS header if we have decoder specific config */ if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 ) { if( p_block->p_buffer[0] == 0xff && ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */ { /* ADTS header present */ size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */ i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 ); /* FIXME: multiple blocks per frame */ if( p_block->i_buffer > i_header_size ) { p_block->p_buffer += i_header_size; p_block->i_buffer -= i_header_size; } } } /* Append the block to the temporary buffer */ if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer ) { size_t i_buffer_size = p_sys->i_buffer + p_block->i_buffer; uint8_t *p_buffer = realloc( p_sys->p_buffer, i_buffer_size ); if( p_buffer ) { p_sys->i_buffer_size = i_buffer_size; p_sys->p_buffer = p_buffer; } else { p_block->i_buffer = 0; } } if( p_block->i_buffer > 0 ) { memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer ); p_sys->i_buffer += p_block->i_buffer; p_block->i_buffer = 0; } if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 ) { /* We have a decoder config so init the handle */ unsigned long i_rate; unsigned char i_channels; if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_rate, &i_channels ) >= 0 ) { p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } } if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer ) { unsigned long i_rate; unsigned char i_channels; /* Init faad with the first frame */ if( faacDecInit( p_sys->hfaad, p_sys->p_buffer, p_sys->i_buffer, &i_rate, &i_channels ) < 0 ) { block_Release( p_block ); return NULL; } p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->date ) ) { date_Set( &p_sys->date, p_block->i_pts ); } else if( !date_Get( &p_sys->date ) ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); p_sys->i_buffer = 0; return NULL; } /* Decode all data */ if( p_sys->i_buffer ) { void *samples; faacDecFrameInfo frame; block_t *p_out; samples = faacDecDecode( p_sys->hfaad, &frame, p_sys->p_buffer, p_sys->i_buffer ); if( frame.error > 0 ) { msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) ); if( frame.error == 21 || frame.error == 12 ) { /* * Once an "Unexpected channel configuration change" * or a "Invalid number of channels" error * occurs, it will occurs afterwards, and we got no sound. * Reinitialization of the decoder is required. */ unsigned long i_rate; unsigned char i_channels; faacDecHandle *hfaad; faacDecConfiguration *cfg,*oldcfg; oldcfg = faacDecGetCurrentConfiguration( p_sys->hfaad ); hfaad = faacDecOpen(); cfg = faacDecGetCurrentConfiguration( hfaad ); if( oldcfg->defSampleRate ) cfg->defSampleRate = oldcfg->defSampleRate; cfg->defObjectType = oldcfg->defObjectType; cfg->outputFormat = oldcfg->outputFormat; faacDecSetConfiguration( hfaad, cfg ); if( faacDecInit( hfaad, p_sys->p_buffer, p_sys->i_buffer, &i_rate,&i_channels ) < 0 ) { /* reinitialization failed */ faacDecClose( hfaad ); faacDecSetConfiguration( p_sys->hfaad, oldcfg ); } else { faacDecClose( p_sys->hfaad ); p_sys->hfaad = hfaad; p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } } /* Flush the buffer */ p_sys->i_buffer = 0; block_Release( p_block ); return NULL; } if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 ) { msg_Warn( p_dec, "invalid channels count: %i", frame.channels ); /* Flush the buffer */ p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } block_Release( p_block ); return NULL; } if( frame.samples <= 0 ) { msg_Warn( p_dec, "decoded zero sample" ); /* Flush the buffer */ p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } block_Release( p_block ); return NULL; } /* We decoded a valid frame */ if( p_dec->fmt_out.audio.i_rate != frame.samplerate ) { date_Init( &p_sys->date, frame.samplerate, 1 ); date_Set( &p_sys->date, p_block->i_pts ); } p_block->i_pts = VLC_TS_INVALID; /* PTS is valid only once */ p_dec->fmt_out.audio.i_rate = frame.samplerate; p_dec->fmt_out.audio.i_channels = frame.channels; /* Adjust stream info when dealing with SBR/PS */ bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2); if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps ) { const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" : b_sbr ? "SBR" : "PS"; msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)", psz_ext, frame.channels, frame.samplerate ); if( !p_dec->p_description ) p_dec->p_description = vlc_meta_New(); if( p_dec->p_description ) vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext ); p_sys->b_sbr = b_sbr; p_sys->b_ps = frame.ps; } /* Convert frame.channel_position to our own channel values */ p_dec->fmt_out.audio.i_physical_channels = 0; const uint32_t nbChannels = frame.channels; unsigned j; for( unsigned i = 0; i < nbChannels; i++ ) { /* Find the channel code */ for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ ) { if( frame.channel_position[i] == pi_channels_in[j] ) break; } if( j >= MAX_CHANNEL_POSITIONS ) { msg_Warn( p_dec, "unknown channel ordering" ); /* Invent something */ j = i; } /* */ p_sys->pi_channel_positions[i] = pi_channels_out[j]; if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] ) frame.channels--; /* We loose a duplicated channel */ else p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j]; } if ( nbChannels != frame.channels ) { p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[nbChannels]; } else { p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels; } p_dec->fmt_out.audio.i_channels = nbChannels; p_out = decoder_NewAudioBuffer( p_dec, frame.samples / nbChannels ); if( p_out == NULL ) { p_sys->i_buffer = 0; block_Release( p_block ); return NULL; } p_out->i_pts = date_Get( &p_sys->date ); p_out->i_length = date_Increment( &p_sys->date, frame.samples / nbChannels ) - p_out->i_pts; DoReordering( (uint32_t *)p_out->p_buffer, samples, frame.samples / nbChannels, nbChannels, p_sys->pi_channel_positions ); p_sys->i_buffer -= frame.bytesconsumed; if( p_sys->i_buffer > 0 ) { memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed], p_sys->i_buffer ); } return p_out; } block_Release( p_block ); return NULL; }
static int init(sh_audio_t *sh) { unsigned long faac_samplerate; unsigned char faac_channels; int faac_init, pos = 0; faac_hdec = faacDecOpen(); // If we don't get the ES descriptor, try manual config if(!sh->codecdata_len && sh->wf) { sh->codecdata_len = sh->wf->cbSize; sh->codecdata = (char*)(sh->wf+1); mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: codecdata extracted from WAVEFORMATEX\n"); } if(!sh->codecdata_len) { #if 1 faacDecConfigurationPtr faac_conf; /* Set the default object type and samplerate */ /* This is useful for RAW AAC files */ faac_conf = faacDecGetCurrentConfiguration(faac_hdec); if(sh->samplerate) faac_conf->defSampleRate = sh->samplerate; /* XXX: FAAD support FLOAT output, how do we handle * that (FAAD_FMT_FLOAT)? ::atmos */ if (audio_output_channels <= 2) faac_conf->downMatrix = 1; switch(sh->samplesize){ case 1: // 8Bit mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: 8Bit samplesize not supported by FAAD, assuming 16Bit!\n"); default: sh->samplesize=2; case 2: // 16Bit faac_conf->outputFormat = FAAD_FMT_16BIT; break; case 3: // 24Bit faac_conf->outputFormat = FAAD_FMT_24BIT; break; case 4: // 32Bit faac_conf->outputFormat = FAAD_FMT_32BIT; break; } //faac_conf->defObjectType = LTP; // => MAIN, LC, SSR, LTP available. faacDecSetConfiguration(faac_hdec, faac_conf); #endif sh->a_in_buffer_len = demux_read_data(sh->ds, sh->a_in_buffer, sh->a_in_buffer_size); pos = aac_probe(sh->a_in_buffer, sh->a_in_buffer_len); if(pos) { sh->a_in_buffer_len -= pos; memmove(sh->a_in_buffer, &(sh->a_in_buffer[pos]), sh->a_in_buffer_len); sh->a_in_buffer_len += demux_read_data(sh->ds,&(sh->a_in_buffer[sh->a_in_buffer_len]), sh->a_in_buffer_size - sh->a_in_buffer_len); pos = 0; } /* init the codec */ faac_init = faacDecInit(faac_hdec, sh->a_in_buffer, sh->a_in_buffer_len, &faac_samplerate, &faac_channels); sh->a_in_buffer_len -= (faac_init > 0)?faac_init:0; // how many bytes init consumed // XXX FIXME: shouldn't we memcpy() here in a_in_buffer ?? --A'rpi } else { // We have ES DS in codecdata faacDecConfigurationPtr faac_conf = faacDecGetCurrentConfiguration(faac_hdec); if (audio_output_channels <= 2) { faac_conf->downMatrix = 1; faacDecSetConfiguration(faac_hdec, faac_conf); } /*int i; for(i = 0; i < sh_audio->codecdata_len; i++) printf("codecdata_dump %d: 0x%02X\n", i, sh_audio->codecdata[i]);*/ faac_init = faacDecInit2(faac_hdec, sh->codecdata, sh->codecdata_len, &faac_samplerate, &faac_channels); } if(faac_init < 0) { mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: Failed to initialize the decoder!\n"); // XXX: deal with cleanup! faacDecClose(faac_hdec); // XXX: free a_in_buffer here or in uninit? return 0; } else { mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Decoder init done (%dBytes)!\n", sh->a_in_buffer_len); // XXX: remove or move to debug! mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate, faac_channels); sh->channels = faac_channels; if (audio_output_channels <= 2) sh->channels = faac_channels > 1 ? 2 : 1; sh->samplerate = faac_samplerate; sh->samplesize=2; //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate; if(!sh->i_bps) { mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: compressed input bitrate missing, assuming 128kbit/s!\n"); sh->i_bps = 128*1000/8; // XXX: HACK!!! ::atmos } else mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: got %dkbit/s bitrate from MP4 header!\n",sh->i_bps*8/1000); } return 1; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; faacDecConfiguration *cfg; if( p_dec->fmt_in.i_codec != VLC_CODEC_MP4A ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ) ) == NULL ) return VLC_ENOMEM; /* Open a faad context */ if( ( p_sys->hfaad = faacDecOpen() ) == NULL ) { msg_Err( p_dec, "cannot initialize faad" ); free( p_sys ); return VLC_EGENERIC; } /* Misc init */ date_Set( &p_sys->date, 0 ); p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N; p_dec->pf_decode_audio = DecodeBlock; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = 0; if( p_dec->fmt_in.i_extra > 0 ) { /* We have a decoder config so init the handle */ unsigned long i_rate; unsigned char i_channels; if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_rate, &i_channels ) < 0 ) { msg_Err( p_dec, "Failed to initialize faad using extra data" ); faacDecClose( p_sys->hfaad ); free( p_sys ); return VLC_EGENERIC; } p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[i_channels]; date_Init( &p_sys->date, i_rate, 1 ); } else { /* Will be initalised from first frame */ p_dec->fmt_out.audio.i_rate = 0; p_dec->fmt_out.audio.i_channels = 0; } /* Set the faad config */ cfg = faacDecGetCurrentConfiguration( p_sys->hfaad ); cfg->outputFormat = HAVE_FPU ? FAAD_FMT_FLOAT : FAAD_FMT_16BIT; faacDecSetConfiguration( p_sys->hfaad, cfg ); /* buffer */ p_sys->i_buffer = p_sys->i_buffer_size = 0; p_sys->p_buffer = NULL; /* Faad2 can't deal with truncated data (eg. from MPEG TS) */ p_dec->b_need_packetized = true; p_sys->b_sbr = p_sys->b_ps = false; return VLC_SUCCESS; }
int decodeAACfile(char *sndfile, int def_srate, aac_dec_opt *opt) { int tagsize; unsigned long samplerate; unsigned char channels; void *sample_buffer; FILE *infile; audio_file *aufile; faacDecHandle hDecoder; faacDecFrameInfo frameInfo; faacDecConfigurationPtr config; int first_time = 1; /* declare variables for buffering */ DEC_BUFF_VARS infile = fopen(opt->filename, "rb"); if (infile == NULL) { /* unable to open file */ error_handler("Error opening file: %s\n", opt->filename); return 1; } INIT_BUFF(infile) tagsize = id3v2_tag(buffer); if (tagsize) { UPDATE_BUFF_SKIP(tagsize) } hDecoder = faacDecOpen(); /* Set the default object type and samplerate */ /* This is useful for RAW AAC files */ config = faacDecGetCurrentConfiguration(hDecoder); if (def_srate) config->defSampleRate = def_srate; config->defObjectType = opt->object_type; config->outputFormat = opt->output_format; faacDecSetConfiguration(hDecoder, config); if ((bytesconsumed = faacDecInit(hDecoder, buffer, bytes_in_buffer, &samplerate, &channels)) < 0) { /* If some error initializing occured, skip the file */ error_handler("Error initializing decoder library.\n"); END_BUFF faacDecClose(hDecoder); fclose(infile); return 1; } buffer_index += bytesconsumed; do { /* update buffer */ UPDATE_BUFF_READ sample_buffer = faacDecDecode(hDecoder, &frameInfo, buffer, bytes_in_buffer); /* update buffer indices */ UPDATE_BUFF_IDX(frameInfo) if (frameInfo.error > 0) { error_handler("Error: %s\n", faacDecGetErrorMessage(frameInfo.error)); } opt->progress_update((long)fileread, buffer_index); /* 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"); END_BUFF faacDecClose(hDecoder); fclose(infile); return (0); } } else { aufile = open_audio_file(sndfile, samplerate, frameInfo.channels, opt->output_format, opt->file_type, aacChannelConfig2wavexChannelMask(&frameInfo)); if (aufile == NULL) { END_BUFF faacDecClose(hDecoder); fclose(infile); 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 (buffer_index >= fileread) sample_buffer = NULL; /* to make sure it stops now */ if(stop_decoding) break; } while (sample_buffer != NULL); faacDecClose(hDecoder); fclose(infile); if(opt->decode_mode == 0) WIN_Audio_close(); else { if (!first_time) close_audio_file(aufile); } END_BUFF return frameInfo.error; }
static void *mp4Decode(void *args) { MP4FileHandle mp4file; pthread_mutex_lock(&mutex); seekPosition = -1; bPlaying = TRUE; if(!(mp4file = MP4Read(args, 0))){ mp4cfg.file_type = FILE_AAC; MP4Close(mp4file); }else{ mp4cfg.file_type = FILE_MP4; } if(mp4cfg.file_type == FILE_MP4){ // We are reading a MP4 file gint mp4track; if((mp4track = getAACTrack(mp4file)) < 0){ //TODO: check here for others Audio format..... g_print("Unsupported Audio track type\n"); g_free(args); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); }else{ faacDecHandle decoder; unsigned char *buffer = NULL; guint bufferSize = 0; gulong samplerate; guchar channels; guint avgBitrate; MP4Duration duration; gulong msDuration; MP4SampleId numSamples; MP4SampleId sampleID = 1; decoder = faacDecOpen(); MP4GetTrackESConfiguration(mp4file, mp4track, &buffer, &bufferSize); if(!buffer){ g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } if(faacDecInit2(decoder, buffer, bufferSize, &samplerate, &channels)<0){ g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } g_free(buffer); if(channels == 0){ g_print("Number of Channels not supported\n"); g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } duration = MP4GetTrackDuration(mp4file, mp4track); msDuration = MP4ConvertFromTrackDuration(mp4file, mp4track, duration, MP4_MSECS_TIME_SCALE); numSamples = MP4GetTrackNumberOfSamples(mp4file, mp4track); mp4_ip.output->open_audio(FMT_S16_NE, samplerate, channels); mp4_ip.output->flush(0); mp4_ip.set_info(args, msDuration, -1, samplerate/1000, channels); g_print("MP4 - %d channels @ %d 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); mp4_ip.output->flush(seekPosition*1000); seekPosition = -1; } buffer=NULL; bufferSize=0; if(sampleID > numSamples){ mp4_ip.output->close_audio(); g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } rc = MP4ReadSample(mp4file, mp4track, sampleID++, &buffer, &bufferSize, NULL, NULL, NULL, NULL); //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(); mp4_ip.output->close_audio(); g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); }else{ sampleBuffer = faacDecDecode(decoder, &frameInfo, buffer, bufferSize); if(frameInfo.error > 0){ g_print("MP4: %s\n", faacDecGetErrorMessage(frameInfo.error)); mp4_ip.output->close_audio(); g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } 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); } while(bPlaying && mp4_ip.output->buffer_free()){ xmms_usleep(10000); } mp4_ip.output->close_audio(); g_free(args); faacDecClose(decoder); MP4Close(mp4file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } } else{ // WE ARE READING AN AAC FILE FILE *file = NULL; faacDecHandle 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; faacDecConfigurationPtr 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 = faacDecOpen()) == NULL){ g_print("AAC: Open Decoder Error\n"); fclose(file); bPlaying = FALSE; pthread_mutex_unlock(&mutex); pthread_exit(NULL); } config = faacDecGetCurrentConfiguration(decoder); config->useOldADTSFormat = 0; faacDecSetConfiguration(decoder, config); if((buffer = g_malloc(BUFFER_SIZE)) == NULL){ g_print("AAC: error g_malloc\n"); fclose(file); bPlaying = FALSE; faacDecClose(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; faacDecClose(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 = faacDecInit(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){ faacDecFrameInfo 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 = faacDecDecode(decoder, &finfo, buffer, buffervalid); if(finfo.error){ config = faacDecGetCurrentConfiguration(decoder); if(config->useOldADTSFormat != 1){ faacDecClose(decoder); decoder = faacDecOpen(); config = faacDecGetCurrentConfiguration(decoder); config->useOldADTSFormat = 1; faacDecSetConfiguration(decoder, config); finfo.bytesconsumed=0; finfo.samples = 0; faacDecInit(decoder, buffer, buffervalid, &samplerate, &channels); }else{ g_print("FAAD2 Warning %s\n", faacDecGetErrorMessage(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); faacDecClose(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 gboolean xmms_faad_init (xmms_xform_t *xform) { xmms_faad_data_t *data; xmms_error_t error; faacDecConfigurationPtr config; gint bytes_read; guint32 samplerate; guchar channels; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_faad_data_t, 1); data->outbuf = g_string_new (NULL); data->buffer_size = FAAD_BUFFER_SIZE; xmms_xform_private_data_set (xform, data); data->decoder = faacDecOpen (); config = faacDecGetCurrentConfiguration (data->decoder); config->defObjectType = LC; config->defSampleRate = 44100; config->outputFormat = FAAD_FMT_16BIT; config->downMatrix = 0; config->dontUpSampleImplicitSBR = 0; faacDecSetConfiguration (data->decoder, config); switch (config->outputFormat) { case FAAD_FMT_16BIT: data->sampleformat = XMMS_SAMPLE_FORMAT_S16; break; case FAAD_FMT_24BIT: /* we don't have 24-bit format to use in xmms2 */ data->sampleformat = XMMS_SAMPLE_FORMAT_S32; break; case FAAD_FMT_32BIT: data->sampleformat = XMMS_SAMPLE_FORMAT_S32; break; case FAAD_FMT_FLOAT: data->sampleformat = XMMS_SAMPLE_FORMAT_FLOAT; break; case FAAD_FMT_DOUBLE: data->sampleformat = XMMS_SAMPLE_FORMAT_DOUBLE; break; } while (data->buffer_length < 8) { xmms_error_reset (&error); bytes_read = xmms_xform_read (xform, (gchar *) data->buffer + data->buffer_length, data->buffer_size - data->buffer_length, &error); data->buffer_length += bytes_read; if (bytes_read < 0) { xmms_log_error ("Error while trying to read data on init"); goto err; } else if (bytes_read == 0) { XMMS_DBG ("Not enough bytes to check the AAC header"); goto err; } } /* which type of file are we dealing with? */ data->filetype = FAAD_TYPE_UNKNOWN; if (xmms_xform_auxdata_has_val (xform, "decoder_config")) { data->filetype = FAAD_TYPE_MP4; } else if (!strncmp ((char *) data->buffer, "ADIF", 4)) { data->filetype = FAAD_TYPE_ADIF; } else { int i; /* ADTS mpeg file can be a stream and start in the middle of a * frame so we need to have extra loop check here */ for (i=0; i<data->buffer_length-1; i++) { if (data->buffer[i] == 0xff && (data->buffer[i+1]&0xf6) == 0xf0) { data->filetype = FAAD_TYPE_ADTS; g_memmove (data->buffer, data->buffer+i, data->buffer_length-i); data->buffer_length -= i; break; } } } if (data->filetype == FAAD_TYPE_ADTS || data->filetype == FAAD_TYPE_ADIF) { bytes_read = faacDecInit (data->decoder, data->buffer, data->buffer_length, &samplerate, &channels); } else if (data->filetype == FAAD_TYPE_MP4) { const guchar *tmpbuf; gssize tmpbuflen; guchar *copy; if (!xmms_xform_auxdata_get_bin (xform, "decoder_config", &tmpbuf, &tmpbuflen)) { XMMS_DBG ("AAC decoder config data found but it's wrong type! (something broken?)"); goto err; } copy = g_memdup (tmpbuf, tmpbuflen); bytes_read = faacDecInit2 (data->decoder, copy, tmpbuflen, &samplerate, &channels); g_free (copy); } if (bytes_read < 0) { XMMS_DBG ("Error initializing decoder library."); goto err; } /* Get mediainfo and skip the possible header */ xmms_faad_get_mediainfo (xform); g_memmove (data->buffer, data->buffer + bytes_read, data->buffer_length - bytes_read); data->buffer_length -= bytes_read; data->samplerate = samplerate; data->channels = channels; /* Because for HE AAC files some versions of libfaad return the wrong * samplerate in init, we have to do one read and let it decide the * real parameters. After changing sample parameters and format is * supported, this hack should be removed and handled in read instead. */ { gchar tmpbuf[1024]; xmms_error_reset (&error); bytes_read = xmms_faad_read (xform, tmpbuf, 1024, &error); if (bytes_read <= 0) { XMMS_DBG ("First read from faad decoder failed!"); return FALSE; } g_string_prepend_len (data->outbuf, tmpbuf, bytes_read); } xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, data->sampleformat, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, data->samplerate, XMMS_STREAM_TYPE_END); XMMS_DBG ("AAC decoder inited successfully!"); return TRUE; err: g_string_free (data->outbuf, TRUE); g_free (data); return FALSE; }
int fdpl_decode_AAC(int def_srate, const char *file_path, size_t &c, size_t &sr, size_t &samples, std::vector<float> * ch1, std::vector<float> *ch2) { int tagsize; uint32_t samplerate; unsigned char channels; void *sample_buffer; FILE *infile; faacDecHandle hDecoder; faacDecFrameInfo frameInfo; faacDecConfigurationPtr config; /* declare variables for buffering */ DEC_BUFF_VARS infile = fopen(file_path, "rb"); if (infile == NULL) { /* unable to open file */ std::cerr<<"Error opening file"<<std::endl; return 1; } INIT_BUFF(infile) tagsize = id3v2_tag(buffer);//avoids ID3 tag (useful for mp3 as well) if (tagsize) { UPDATE_BUFF_SKIP(tagsize) } hDecoder = faacDecOpen(); /* Set the default object type and samplerate */ /* This is useful for RAW AAC files */ config = faacDecGetCurrentConfiguration(hDecoder); if (def_srate) config->defSampleRate = def_srate; config->defObjectType = LC;//default config->outputFormat = FAAD_FMT_FLOAT; config -> downMatrix = 0; //set to 1 faacDecSetConfiguration(hDecoder, config); if ((bytesconsumed = faacDecInit(hDecoder, buffer, bytes_in_buffer, &samplerate, &channels)) < 0) { /* If some error initializing occured, skip the file */ std::cerr<<"Error initializing decoder library."<<std::endl; END_BUFF faacDecClose(hDecoder); fclose(infile); return 1; } buffer_index += bytesconsumed; do { /* update buffer */ UPDATE_BUFF_READ sample_buffer = faacDecDecode(hDecoder, &frameInfo, buffer, bytes_in_buffer); /* update buffer indices */ UPDATE_BUFF_IDX(frameInfo) if (frameInfo.error > 0) { std::cerr<<"Error: %s\n"<<faacDecGetErrorMessage(frameInfo.error)<<std::endl; } 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 (buffer_index >= fileread) sample_buffer = NULL; /* to make sure it stops now */ } while (sample_buffer != NULL); c = frameInfo.channels; sr = frameInfo.samplerate; faacDecClose(hDecoder); fclose(infile); END_BUFF return frameInfo.error; }