/***************************************************************************** * aout_FifoInit : initialize the members of a FIFO *****************************************************************************/ void aout_FifoInit( aout_instance_t * p_aout, aout_fifo_t * p_fifo, uint32_t i_rate ) { if( i_rate == 0 ) { msg_Err( p_aout, "initialising fifo with zero divider" ); } p_fifo->p_first = NULL; p_fifo->pp_last = &p_fifo->p_first; aout_DateInit( &p_fifo->end_date, i_rate ); }
static int Open (vlc_object_t *p_this) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys; if (p_dec->fmt_in.i_codec != VLC_CODEC_MIDI) return VLC_EGENERIC; char *font_path = var_CreateGetNonEmptyString (p_this, "soundfont"); if (font_path == NULL) { msg_Err (p_this, "sound fonts file required for synthesis"); return VLC_EGENERIC; } p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.audio.i_rate = 44100; p_dec->fmt_out.audio.i_channels = 2; p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; p_dec->fmt_out.i_codec = VLC_CODEC_FL32; p_dec->fmt_out.audio.i_bitspersample = 32; p_dec->pf_decode_audio = DecodeBlock; p_sys = p_dec->p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) { free (font_path); return VLC_ENOMEM; } p_sys->settings = new_fluid_settings (); p_sys->synth = new_fluid_synth (p_sys->settings); /* FIXME: I bet this is not thread-safe */ p_sys->soundfont = fluid_synth_sfload (p_sys->synth, font_path, 1); free (font_path); if (p_sys->soundfont == -1) { msg_Err (p_this, "cannot load sound fonts file"); Close (p_this); return VLC_EGENERIC; } aout_DateInit (&p_sys->end_date, p_dec->fmt_out.audio.i_rate); aout_DateSet (&p_sys->end_date, 0); return VLC_SUCCESS; }
/***************************************************************************** * OpenAudio: *****************************************************************************/ static int OpenAudio( decoder_t *p_dec ) { decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) ); vlc_value_t lockval; int i_error; char fcc[4]; unsigned long WantedBufferSize; unsigned long InputBufferSize = 0; unsigned long OutputBufferSize = 0; memset( p_sys, 0, sizeof( decoder_sys_t ) ); p_dec->p_sys = p_sys; p_dec->pf_decode_audio = DecodeAudio; memcpy( fcc, &p_dec->fmt_in.i_codec, 4 ); /* get lock, avoid segfault */ var_Get( p_dec->p_libvlc, "qt_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); #ifdef __APPLE__ EnterMovies(); #endif if( QTAudioInit( p_dec ) ) { msg_Err( p_dec, "cannot initialize QT"); goto exit_error; } #ifndef __APPLE__ if( ( i_error = p_sys->InitializeQTML( 6 + 16 ) ) ) { msg_Dbg( p_dec, "error on InitializeQTML = %d", i_error ); goto exit_error; } #endif /* input format settings */ p_sys->InputFormatInfo.flags = 0; p_sys->InputFormatInfo.sampleCount = 0; p_sys->InputFormatInfo.buffer = NULL; p_sys->InputFormatInfo.reserved = 0; p_sys->InputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels; p_sys->InputFormatInfo.sampleSize = p_dec->fmt_in.audio.i_bitspersample; p_sys->InputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate; p_sys->InputFormatInfo.format = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); /* output format settings */ p_sys->OutputFormatInfo.flags = 0; p_sys->OutputFormatInfo.sampleCount = 0; p_sys->OutputFormatInfo.buffer = NULL; p_sys->OutputFormatInfo.reserved = 0; p_sys->OutputFormatInfo.numChannels = p_dec->fmt_in.audio.i_channels; p_sys->OutputFormatInfo.sampleSize = 16; p_sys->OutputFormatInfo.sampleRate = p_dec->fmt_in.audio.i_rate; p_sys->OutputFormatInfo.format = FCC( 'N', 'O', 'N', 'E' ); i_error = p_sys->SoundConverterOpen( &p_sys->InputFormatInfo, &p_sys->OutputFormatInfo, &p_sys->myConverter ); if( i_error ) { msg_Err( p_dec, "error on SoundConverterOpen = %d", i_error ); goto exit_error; } #if 0 /* tell the sound converter we accept VBR formats */ i_error = SoundConverterSetInfo( p_dec->myConverter, siClientAcceptsVBR, (void *)true ); #endif if( p_dec->fmt_in.i_extra > 36 + 8 ) { i_error = p_sys->SoundConverterSetInfo( p_sys->myConverter, FCC( 'w', 'a', 'v', 'e' ), ((uint8_t*)p_dec->fmt_in.p_extra) + 36 + 8 ); msg_Dbg( p_dec, "error on SoundConverterSetInfo = %d", i_error ); } WantedBufferSize = p_sys->OutputFormatInfo.numChannels * p_sys->OutputFormatInfo.sampleRate * 2; p_sys->FramesToGet = 0; i_error = p_sys->SoundConverterGetBufferSizes( p_sys->myConverter, WantedBufferSize, &p_sys->FramesToGet, &InputBufferSize, &OutputBufferSize ); msg_Dbg( p_dec, "WantedBufferSize=%li InputBufferSize=%li " "OutputBufferSize=%li FramesToGet=%li", WantedBufferSize, InputBufferSize, OutputBufferSize, p_sys->FramesToGet ); p_sys->InFrameSize = (InputBufferSize + p_sys->FramesToGet - 1 ) / p_sys->FramesToGet; p_sys->OutFrameSize = OutputBufferSize / p_sys->FramesToGet; msg_Dbg( p_dec, "frame size %d -> %d", p_sys->InFrameSize, p_sys->OutFrameSize ); if( (i_error = p_sys->SoundConverterBeginConversion(p_sys->myConverter)) ) { msg_Err( p_dec, "error on SoundConverterBeginConversion = %d", i_error ); goto exit_error; } es_format_Init( &p_dec->fmt_out, AUDIO_ES, AOUT_FMT_S16_NE ); p_dec->fmt_out.audio.i_rate = p_sys->OutputFormatInfo.sampleRate; p_dec->fmt_out.audio.i_channels = p_sys->OutputFormatInfo.numChannels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_sys->OutputFormatInfo.numChannels]; aout_DateInit( &p_sys->date, p_dec->fmt_out.audio.i_rate ); p_sys->i_buffer = 0; p_sys->i_buffer_size = 100*1000; p_sys->p_buffer = malloc( p_sys->i_buffer_size ); p_sys->i_out = 0; p_sys->i_out_frames = 0; vlc_mutex_unlock( lockval.p_address ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( lockval.p_address ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * OpenEncoder: probe the encoder and return score *****************************************************************************/ static int OpenEncoder( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; vlc_value_t val; if( p_enc->fmt_out.i_codec != VLC_FOURCC('m','p','g','a') && p_enc->fmt_out.i_codec != VLC_FOURCC('m','p','2','a') && p_enc->fmt_out.i_codec != VLC_FOURCC('m','p','2',' ') && !p_enc->b_force ) { return VLC_EGENERIC; } if( p_enc->fmt_in.audio.i_channels > 2 ) { msg_Err( p_enc, "doesn't support > 2 channels" ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) { msg_Err( p_enc, "out of memory" ); return VLC_EGENERIC; } p_enc->p_sys = p_sys; p_enc->pf_encode_audio = Encode; p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE; p_enc->fmt_out.i_codec = VLC_FOURCC('m','p','g','a'); sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); p_sys->p_toolame = toolame_init(); /* Set options */ toolame_setSampleFreq( p_sys->p_toolame, p_enc->fmt_out.audio.i_rate ); var_Get( p_enc, ENC_CFG_PREFIX "vbr", &val ); if ( val.b_bool ) { FLOAT i_quality; var_Get( p_enc, ENC_CFG_PREFIX "quality", &val ); i_quality = val.i_int; if ( i_quality > 50.0 ) i_quality = 50.0; if ( i_quality < 0.0 ) i_quality = 0.0; toolame_setVBR( p_sys->p_toolame, 1 ); toolame_setVBRLevel( p_sys->p_toolame, i_quality ); } else { toolame_setBitrate( p_sys->p_toolame, p_enc->fmt_out.i_bitrate / 1000 ); } if ( p_enc->fmt_in.audio.i_channels == 1 ) { toolame_setMode( p_sys->p_toolame, MPG_MD_MONO ); } else { var_Get( p_enc, ENC_CFG_PREFIX "mode", &val ); switch ( val.i_int ) { case 1: toolame_setMode( p_sys->p_toolame, MPG_MD_DUAL_CHANNEL ); break; case 2: toolame_setMode( p_sys->p_toolame, MPG_MD_JOINT_STEREO ); break; case 0: default: toolame_setMode( p_sys->p_toolame, MPG_MD_STEREO ); break; } } if ( toolame_init_params( p_sys->p_toolame ) ) { msg_Err( p_enc, "toolame initialization failed" ); return -VLC_EGENERIC; } p_sys->i_nb_samples = 0; aout_DateInit( &p_sys->pts, p_enc->fmt_out.audio.i_rate ); return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */ break; default: return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_channels <= 0 || p_dec->fmt_in.audio.i_channels > 5 ) { msg_Err( p_dec, "invalid number of channel (not between 1 and 5): %i", p_dec->fmt_in.audio.i_channels ); return VLC_EGENERIC; } if( p_dec->fmt_in.audio.i_rate <= 0 ) { msg_Err( p_dec, "bad samplerate" ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_ENOMEM; } switch( p_dec->fmt_in.i_codec ) { case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_QT; break; case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_WAV; break; case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */ p_sys->codec = ADPCM_MS; break; case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ p_sys->codec = ADPCM_DK4; break; case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ p_sys->codec = ADPCM_DK3; break; case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */ p_sys->codec = ADPCM_EA; p_dec->fmt_in.p_extra = calloc( 2 * p_dec->fmt_in.audio.i_channels, sizeof( int16_t ) ); if( p_dec->fmt_in.p_extra == NULL ) { free( p_sys ); return VLC_ENOMEM; } break; } if( p_dec->fmt_in.audio.i_blockalign <= 0 ) { p_sys->i_block = (p_sys->codec == ADPCM_IMA_QT) ? 34 * p_dec->fmt_in.audio.i_channels : 1024; msg_Warn( p_dec, "block size undefined, using %d", p_sys->i_block ); } else { p_sys->i_block = p_dec->fmt_in.audio.i_blockalign; } /* calculate samples per block */ switch( p_sys->codec ) { case ADPCM_IMA_QT: p_sys->i_samplesperblock = 64; break; case ADPCM_IMA_WAV: p_sys->i_samplesperblock = 2 * ( p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels ) / p_dec->fmt_in.audio.i_channels; break; case ADPCM_MS: p_sys->i_samplesperblock = 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels + 2; break; case ADPCM_DK4: p_sys->i_samplesperblock = 2 * (p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels + 1; break; case ADPCM_DK3: p_dec->fmt_in.audio.i_channels = 2; p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3; break; case ADPCM_EA: p_sys->i_samplesperblock = 2 * (p_sys->i_block - p_dec->fmt_in.audio.i_channels) / p_dec->fmt_in.audio.i_channels; } msg_Dbg( p_dec, "format: samplerate:%d Hz channels:%d bits/sample:%d " "blockalign:%d samplesperblock:%d", p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels, p_dec->fmt_in.audio.i_bitspersample, p_sys->i_block, p_sys->i_samplesperblock ); p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_dec->fmt_in.audio.i_channels]; aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate ); aout_DateSet( &p_sys->end_date, 0 ); p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; }
/***************************************************************************** * DecodeBlock: *****************************************************************************/ static aout_buffer_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 ) { vlc_memcpy( p_block->p_buffer, p_block->p_buffer + i_header_size, p_block->i_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 ) { p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer; p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size ); } if( p_block->i_buffer > 0 ) { vlc_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]; aout_DateInit( &p_sys->date, i_rate ); } } 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]; aout_DateInit( &p_sys->date, i_rate ); } if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) ) { aout_DateSet( &p_sys->date, p_block->i_pts ); } else if( !aout_DateGet( &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; aout_buffer_t *p_out; int i, j; 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 ) ); /* 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 ) { aout_DateInit( &p_sys->date, frame.samplerate ); aout_DateSet( &p_sys->date, p_block->i_pts ); } p_block->i_pts = 0; /* PTS is valid only once */ p_dec->fmt_out.audio.i_rate = frame.samplerate; p_dec->fmt_out.audio.i_channels = frame.channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_guessed[frame.channels]; /* Adjust stream info when dealing with SBR/PS */ if( p_sys->b_sbr != frame.sbr || p_sys->b_ps != frame.ps ) { const char *psz_ext = (frame.sbr && frame.ps) ? "SBR+PS" : frame.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 = frame.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; for( i = 0; i < frame.channels; 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]; } p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels; p_out = decoder_NewAudioBuffer(p_dec, frame.samples/frame.channels); if( p_out == NULL ) { p_sys->i_buffer = 0; block_Release( p_block ); return NULL; } p_out->start_date = aout_DateGet( &p_sys->date ); p_out->end_date = aout_DateIncrement( &p_sys->date, frame.samples / frame.channels ); DoReordering( (uint32_t *)p_out->p_buffer, samples, frame.samples / frame.channels, frame.channels, 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; }
/***************************************************************************** * 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 = p_dec->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" ); return VLC_EGENERIC; } /* Misc init */ aout_DateSet( &p_sys->date, 0 ); p_dec->fmt_out.i_cat = AUDIO_ES; if (vlc_CPU() & CPU_CAPABILITY_FPU) p_dec->fmt_out.i_codec = VLC_CODEC_FL32; else p_dec->fmt_out.i_codec = 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" ); 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]; aout_DateInit( &p_sys->date, i_rate ); } 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 ); if (vlc_CPU() & CPU_CAPABILITY_FPU) cfg->outputFormat = FAAD_FMT_FLOAT; else cfg->outputFormat = 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; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_WMA1 && p_dec->fmt_in.i_codec != VLC_CODEC_WMA2 ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)); if( !p_sys ) return VLC_ENOMEM; memset( p_sys, 0, sizeof( decoder_sys_t ) ); /* Date */ aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate ); /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = VLC_CODEC_FI32; p_dec->fmt_out.audio.i_bitspersample = p_dec->fmt_in.audio.i_bitspersample; p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate; p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels; assert( p_dec->fmt_out.audio.i_channels < ( sizeof( pi_channels_maps ) / sizeof( pi_channels_maps[0] ) ) ); p_dec->fmt_out.audio.i_original_channels = p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_dec->fmt_out.audio.i_channels]; /* aout core assumes this number is not 0 and uses it in divisions */ assert( p_dec->fmt_out.audio.i_physical_channels != 0 ); asf_waveformatex_t wfx; wfx.rate = p_dec->fmt_in.audio.i_rate; wfx.bitrate = p_dec->fmt_in.i_bitrate; wfx.channels = p_dec->fmt_in.audio.i_channels; wfx.blockalign = p_dec->fmt_in.audio.i_blockalign; wfx.bitspersample = p_dec->fmt_in.audio.i_bitspersample; msg_Dbg( p_dec, "samplerate %d bitrate %d channels %d align %d bps %d", wfx.rate, wfx.bitrate, wfx.channels, wfx.blockalign, wfx.bitspersample ); if( p_dec->fmt_in.i_codec == VLC_CODEC_WMA1 ) wfx.codec_id = ASF_CODEC_ID_WMAV1; else if( p_dec->fmt_in.i_codec == VLC_CODEC_WMA2 ) wfx.codec_id = ASF_CODEC_ID_WMAV2; wfx.datalen = p_dec->fmt_in.i_extra; if( wfx.datalen > 6 ) wfx.datalen = 6; if( wfx.datalen > 0 ) memcpy( wfx.data, p_dec->fmt_in.p_extra, wfx.datalen ); /* Init codec */ if( wma_decode_init(&p_sys->wmadec, &wfx ) < 0 ) { msg_Err( p_dec, "codec init failed" ); free( p_sys ); return VLC_EGENERIC; } /* Set callback */ p_dec->pf_decode_audio = DecodeFrame; return VLC_SUCCESS; }
/***************************************************************************** * Open: open a scope effect plugin *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; goom_thread_t *p_thread; vlc_value_t width, height; if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { msg_Warn( p_filter, "Bad input or output format" ); return VLC_EGENERIC; } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { msg_Warn( p_filter, "input and output formats are not similar" ); return VLC_EGENERIC; } p_filter->pf_do_work = DoWork; p_filter->b_in_place = 1; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); /* Create goom thread */ p_sys->p_thread = p_thread = vlc_object_create( p_filter, sizeof( goom_thread_t ) ); vlc_object_attach( p_thread, p_this ); var_Create( p_thread, "goom-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "goom-width", &width ); var_Create( p_thread, "goom-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "goom-height", &height ); p_thread->p_vout = vout_Request( p_filter, NULL, width.i_int, height.i_int, VLC_FOURCC('R','V','3','2'), VOUT_ASPECT_FACTOR * width.i_int/height.i_int ); if( p_thread->p_vout == NULL ) { msg_Err( p_filter, "no suitable vout module" ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } vlc_mutex_init( p_filter, &p_thread->lock ); vlc_cond_init( p_filter, &p_thread->wait ); p_thread->i_blocks = 0; aout_DateInit( &p_thread->date, p_filter->output.i_rate ); aout_DateSet( &p_thread->date, 0 ); p_thread->i_channels = aout_FormatNbChannels( &p_filter->input ); p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) ); if( vlc_thread_create( p_thread, "Goom Update Thread", Thread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { msg_Err( p_filter, "cannot lauch goom thread" ); vout_Destroy( p_thread->p_vout ); vlc_mutex_destroy( &p_thread->lock ); vlc_cond_destroy( &p_thread->wait ); if( p_thread->psz_title ) free( p_thread->psz_title ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }