/** * Common initialization for decoder and packetizer */ static int OpenCommon( decoder_t *p_dec, bool b_packetizer ) { const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( p_dec->fmt_in.i_codec ); if( dsc == NULL || dsc->plane_count == 0 ) return VLC_EGENERIC; if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height == 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ decoder_sys_t *p_sys = calloc(1, sizeof(*p_sys)); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; if ( !b_packetizer ) es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } for( unsigned i = 0; i < dsc->plane_count; i++ ) { unsigned pitch = p_dec->fmt_in.video.i_width * dsc->pixel_size * dsc->p[i].w.num / dsc->p[i].w.den; unsigned lines = p_dec->fmt_in.video.i_height * dsc->p[i].h.num / dsc->p[i].h.den; p_sys->pitches[i] = pitch; p_sys->lines[i] = lines; p_sys->size += pitch * lines; } p_dec->p_sys = p_sys; return VLC_SUCCESS; }
/***************************************************************************** * InitAudioDec: initialize audio decoder ***************************************************************************** * The avcodec codec will be opened, some memory allocated. *****************************************************************************/ int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, const char *psz_namecodec ) { decoder_sys_t *p_sys; /* 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; } p_codec->type = AVMEDIA_TYPE_AUDIO; p_context->codec_type = AVMEDIA_TYPE_AUDIO; p_context->codec_id = i_codec_id; p_context->get_buffer = GetAudioBuf; p_sys->p_context = p_context; p_sys->p_codec = p_codec; p_sys->i_codec_id = i_codec_id; p_sys->psz_namecodec = psz_namecodec; p_sys->b_delayed_open = true; // Initialize decoder extradata InitDecoderConfig( p_dec, p_context); /* ***** Open the codec ***** */ if( ffmpeg_OpenCodec( p_dec ) < 0 ) { msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); free( p_sys->p_context->extradata ); free( p_sys ); return VLC_EGENERIC; } p_sys->i_reject_count = 0; p_sys->b_extract = false; p_sys->i_previous_channels = 0; p_sys->i_previous_layout = 0; /* */ p_dec->fmt_out.i_cat = AUDIO_ES; /* Try to set as much information as possible but do not trust it */ SetupOutputFormat( p_dec, false ); date_Set( &p_sys->end_date, 0 ); if( p_dec->fmt_out.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); else if( p_dec->fmt_in.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 ); return VLC_SUCCESS; }
static int SeekSet0 (demux_t *demux) { stream_t *stream = demux->s; demux_sys_t *sys = demux->p_sys; /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */ date_Init (&sys->pts, sys->ppqn * 2, 1); date_Set (&sys->pts, VLC_TS_0); sys->pulse = 0; sys->tick = VLC_TS_0; for (unsigned i = 0; i < sys->trackc; i++) { mtrk_t *tr = sys->trackv + i; tr->offset = 0; tr->next = 0; /* Why 0xF6 (Tuning Calibration)? * Because it has zero bytes of data, so the parser will detect the * error if the first event uses running status. */ tr->running_event = 0xF6; if (stream_Seek (stream, tr->start) || ReadDeltaTime (stream, tr)) { msg_Err (demux, "fatal parsing error"); return -1; } } return 0; }
/***************************************************************************** * Open: check file and initializes structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; /* Identify cdg file by extension, as there is no simple way to * detect it */ if( !demux_IsPathExtension( p_demux, ".cdg" ) && !demux_IsForced( p_demux, "cdg" ) ) return VLC_EGENERIC; /* CDG file size has to be multiple of CDG_FRAME_SIZE (it works even * if size is unknown ie 0) */ // if( (stream_Size( p_demux->s ) % CDG_FRAME_SIZE) != 0 ) // { // msg_Err( p_demux, "Reject CDG file based on its size" ); // return VLC_EGENERIC; // } p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); /* */ es_format_Init( &p_sys->fmt, VIDEO_ES, VLC_CODEC_CDG ); p_sys->fmt.video.i_width = 300-2*6; p_sys->fmt.video.i_height = 216-2*12 ; p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt ); /* There is CDG_FRAME_RATE frames per second */ date_Init( &p_sys->pts, CDG_FRAME_RATE, 1 ); date_Set( &p_sys->pts, 1 ); return VLC_SUCCESS; }
static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *sys = vlc_malloc(obj, sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; es_format_t fmt; es_format_Init (&fmt, SPU_ES, VLC_CODEC_ITU_T140); sys->es = es_out_Add (demux->out, &fmt); unsigned num, den; if (var_InheritURational (demux, &num, &den, "timecode-fps") || !num || !den) { msg_Err (demux, "invalid frame rate"); return VLC_EGENERIC; } date_Init (&sys->date, num, den); date_Set (&sys->date, VLC_TS_0); sys->next_time = VLC_TS_INVALID; demux->p_sys = sys; demux->pf_demux = Demux; demux->pf_control = Control; return VLC_SUCCESS; }
/** * Initializes the members of a FIFO. */ static void aout_FifoInit( aout_fifo_t *p_fifo, uint32_t i_rate ) { assert( i_rate != 0); p_fifo->p_first = NULL; p_fifo->pp_last = &p_fifo->p_first; date_Init( &p_fifo->end_date, i_rate, 1 ); date_Set( &p_fifo->end_date, VLC_TS_INVALID ); }
/***************************************************************************** * InitAudioDec: initialize audio decoder ***************************************************************************** * The avcodec codec will be opened, some memory allocated. *****************************************************************************/ int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context, const AVCodec *p_codec ) { decoder_sys_t *p_sys; /* 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; } p_context->refcounted_frames = true; p_sys->p_context = p_context; p_sys->p_codec = p_codec; p_sys->b_delayed_open = true; // Initialize decoder extradata InitDecoderConfig( p_dec, p_context); /* ***** Open the codec ***** */ if( OpenAudioCodec( p_dec ) < 0 ) { free( p_sys ); return VLC_EGENERIC; } p_sys->i_reject_count = 0; p_sys->b_extract = false; p_sys->i_previous_channels = 0; p_sys->i_previous_layout = 0; /* */ p_dec->fmt_out.i_cat = AUDIO_ES; /* Try to set as much information as possible but do not trust it */ SetupOutputFormat( p_dec, false ); date_Set( &p_sys->end_date, VLC_TS_INVALID ); if( p_dec->fmt_out.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); else if( p_dec->fmt_in.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 ); p_dec->pf_decode_audio = DecodeAudio; p_dec->pf_flush = Flush; return VLC_SUCCESS; }
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->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; } 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; if (HAVE_FPU) { p_dec->fmt_out.i_codec = VLC_CODEC_FL32; p_dec->fmt_out.audio.i_bitspersample = 32; p_sys->fixed = false; } else { p_dec->fmt_out.i_codec = VLC_CODEC_S16N; p_dec->fmt_out.audio.i_bitspersample = 16; p_sys->fixed = true; } date_Init (&p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1); date_Set (&p_sys->end_date, 0); return VLC_SUCCESS; }
bool transcode_audio_add( sout_stream_t *p_stream, es_format_t *p_fmt, sout_stream_id_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; msg_Dbg( p_stream, "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'", (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec ); /* Complete destination format */ id->p_encoder->fmt_out.i_codec = p_sys->i_acodec; id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ? p_sys->i_sample_rate : p_fmt->audio.i_rate; id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate; id->p_encoder->fmt_out.audio.i_bitspersample = p_fmt->audio.i_bitspersample; id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ? p_sys->i_channels : p_fmt->audio.i_channels; /* Sanity check for audio channels */ id->p_encoder->fmt_out.audio.i_channels = __MIN( id->p_encoder->fmt_out.audio.i_channels, id->p_decoder->fmt_in.audio.i_channels ); id->p_encoder->fmt_out.audio.i_original_channels = id->p_decoder->fmt_in.audio.i_physical_channels; if( id->p_decoder->fmt_in.audio.i_channels == id->p_encoder->fmt_out.audio.i_channels ) { id->p_encoder->fmt_out.audio.i_physical_channels = id->p_decoder->fmt_in.audio.i_physical_channels; } else { id->p_encoder->fmt_out.audio.i_physical_channels = pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels]; } /* Build decoder -> filter -> encoder chain */ if( transcode_audio_new( p_stream, id ) ) { msg_Err( p_stream, "cannot create audio chain" ); return false; } /* Open output stream */ id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out ); id->b_transcode = true; if( !id->id ) { transcode_audio_close( id ); return false; } date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 ); return true; }
/***************************************************************************** * aout_FifoInit : initialize the members of a FIFO *****************************************************************************/ void aout_FifoInit( vlc_object_t *obj, aout_fifo_t * p_fifo, uint32_t i_rate ) { if( unlikely(i_rate == 0) ) msg_Err( obj, "initialising fifo with zero divider" ); p_fifo->p_first = NULL; p_fifo->pp_last = &p_fifo->p_first; date_Init( &p_fifo->end_date, i_rate, 1 ); }
/***************************************************************************** * 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 ) { AOUT_ASSERT_FIFO_LOCKED; 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; date_Init( &p_fifo->end_date, i_rate, 1 ); }
/***************************************************************************** * Open: *****************************************************************************/ 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_MJPG ) return VLC_EGENERIC; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_dec->p_sys ) return VLC_ENOMEM; p_sys->i_next_block_flags = 0; if( p_dec->fmt_in.video.i_frame_rate && p_dec->fmt_in.video.i_frame_rate_base ) { date_Init( &p_sys->date, p_dec->fmt_in.video.i_frame_rate, p_dec->fmt_in.video.i_frame_rate_base ); } else date_Init( &p_sys->date, 30000, 1001 ); es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); /* Misc init */ packetizer_Init( &p_sys->packetizer, p_mjpg_startcode, sizeof(p_mjpg_startcode), startcode_Find, NULL, 0, 295, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_dec->pf_packetize = Packetize; p_dec->pf_flush = PacketizeFlush; p_dec->pf_get_cc = NULL; return VLC_SUCCESS; }
static int UpdateAudioFormat( decoder_t *p_dec ) { int i_err; decoder_sys_t *p_sys = p_dec->p_sys; struct mpg123_frameinfo frame_info; /* Get details about the stream */ i_err = mpg123_info( p_sys->p_handle, &frame_info ); if( i_err != MPG123_OK ) { msg_Err( p_dec, "mpg123_info failed: %s", mpg123_plain_strerror( i_err ) ); return VLC_EGENERIC; } p_dec->fmt_out.i_bitrate = frame_info.bitrate * 1000; switch( frame_info.mode ) { case MPG123_M_DUAL: p_dec->fmt_out.audio.i_chan_mode = AOUT_CHANMODE_DUALMONO; /* fall through */ case MPG123_M_STEREO: case MPG123_M_JOINT: p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case MPG123_M_MONO: p_dec->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER; break; default: return VLC_EGENERIC; } aout_FormatPrepare( &p_dec->fmt_out.audio ); /* Date management */ if( p_dec->fmt_out.audio.i_rate != frame_info.rate ) { p_dec->fmt_out.audio.i_rate = frame_info.rate; date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); date_Set( &p_sys->end_date, 0 ); } return decoder_UpdateAudioFormat( p_dec ); }
/***************************************************************************** * GetOutBuffer: *****************************************************************************/ static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *p_buf; if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ) { msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d", p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate ); date_Init( &p_sys->end_date, p_sys->i_rate, 1 ); date_Set( &p_sys->end_date, p_sys->i_pts ); } p_dec->fmt_out.audio.i_rate = p_sys->i_rate; p_dec->fmt_out.audio.i_channels = p_sys->i_channels; /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */ p_dec->fmt_out.audio.i_bytes_per_frame = __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 ); p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length; p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; p_dec->fmt_out.audio.i_physical_channels = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK; p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate; if( p_sys->b_packetizer ) { block_t *p_sout_buffer = GetSoutBuffer( p_dec ); p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL; *pp_out_buffer = p_sout_buffer; } else { block_t *p_aout_buffer = GetAoutBuffer( p_dec ); p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL; *pp_out_buffer = p_aout_buffer; } return p_buf; }
/***************************************************************************** * GetOutBuffer: *****************************************************************************/ static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *p_buf; if( p_dec->fmt_out.audio.i_rate != p_sys->frame.i_rate ) { msg_Dbg( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d", p_sys->frame.i_channels, p_sys->frame.i_rate, p_sys->frame.i_bitrate ); date_Init( &p_sys->end_date, p_sys->frame.i_rate, 1 ); date_Set( &p_sys->end_date, p_sys->i_pts ); } p_dec->fmt_out.audio.i_rate = p_sys->frame.i_rate; p_dec->fmt_out.audio.i_channels = p_sys->frame.i_channels; if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->frame.i_size ) p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->frame.i_size; p_dec->fmt_out.audio.i_frame_length = p_sys->frame.i_samples; p_dec->fmt_out.audio.i_original_channels = p_sys->frame.i_channels_conf; p_dec->fmt_out.audio.i_physical_channels = p_sys->frame.i_channels_conf & AOUT_CHAN_PHYSMASK; p_dec->fmt_out.i_bitrate = p_sys->frame.i_bitrate; if( p_sys->b_packetizer ) { block_t *p_sout_buffer = GetSoutBuffer( p_dec ); p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL; *pp_out_buffer = p_sout_buffer; } else { aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec ); p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL; *pp_out_buffer = p_aout_buffer; } return p_buf; }
static block_t *GetOutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; if( !p_sys->b_date_set || p_dec->fmt_out.audio.i_rate != p_sys->dts.i_rate ) { msg_Dbg( p_dec, "DTS samplerate:%d bitrate:%d", p_sys->dts.i_rate, p_sys->dts.i_bitrate ); date_Init( &p_sys->end_date, p_sys->dts.i_rate, 1 ); date_Set( &p_sys->end_date, p_sys->i_pts ); p_sys->b_date_set = true; } p_dec->fmt_out.audio.i_rate = p_sys->dts.i_rate; if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->dts.i_frame_size ) p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->dts.i_frame_size; p_dec->fmt_out.audio.i_frame_length = p_sys->dts.i_frame_length; p_dec->fmt_out.audio.i_original_channels = p_sys->dts.i_original_channels; p_dec->fmt_out.audio.i_physical_channels = p_sys->dts.i_original_channels & AOUT_CHAN_PHYSMASK; p_dec->fmt_out.audio.i_channels = popcount( p_dec->fmt_out.audio.i_physical_channels ); p_dec->fmt_out.i_bitrate = p_sys->dts.i_bitrate; block_t *p_block = block_Alloc( p_sys->i_input_size ); if( p_block == NULL ) return NULL; p_block->i_nb_samples = p_sys->dts.i_frame_length; p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples ) - p_block->i_pts; return p_block; }
static block_t *GetOutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; if( !p_sys->b_date_set || p_dec->fmt_out.audio.i_rate != p_sys->frame.i_rate ) { msg_Dbg( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d", p_sys->frame.i_channels, p_sys->frame.i_rate, p_sys->frame.i_bitrate ); date_Init( &p_sys->end_date, p_sys->frame.i_rate, 1 ); date_Set( &p_sys->end_date, p_sys->i_pts ); p_sys->b_date_set = true; } p_dec->fmt_out.audio.i_rate = p_sys->frame.i_rate; p_dec->fmt_out.audio.i_channels = p_sys->frame.i_channels; if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->frame.i_size ) p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->frame.i_size; p_dec->fmt_out.audio.i_frame_length = p_sys->frame.i_samples; p_dec->fmt_out.audio.i_chan_mode = p_sys->frame.i_chan_mode; p_dec->fmt_out.audio.i_physical_channels = p_sys->frame.i_channels_conf; p_dec->fmt_out.i_bitrate = p_sys->frame.i_bitrate; block_t *p_block = block_Alloc( p_sys->frame.i_size ); if( p_block == NULL ) return NULL; p_block->i_nb_samples = p_sys->frame.i_samples; p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples ) - p_block->i_pts; return p_block; }
static int Open(vlc_object_t *object) { demux_t *demux = (demux_t*)object; /* Detect the image type */ const image_format_t *img; const uint8_t *peek; int peek_size = 0; for (int i = 0; ; i++) { img = &formats[i]; if (!img->codec) return VLC_EGENERIC; if (img->detect) { if (img->detect(demux->s)) break; } else { if (peek_size < img->marker_size) peek_size = stream_Peek(demux->s, &peek, img->marker_size); if (peek_size >= img->marker_size && !memcmp(peek, img->marker, img->marker_size)) break; } } msg_Dbg(demux, "Detected image: %s", vlc_fourcc_GetDescription(VIDEO_ES, img->codec)); if( img->codec == VLC_CODEC_MXPEG ) { return VLC_EGENERIC; //let avformat demux this file } /* Load and if selected decode */ es_format_t fmt; es_format_Init(&fmt, VIDEO_ES, img->codec); fmt.video.i_chroma = fmt.i_codec; block_t *data = Load(demux); if (data && var_InheritBool(demux, "image-decode")) { char *string = var_InheritString(demux, "image-chroma"); vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, string); free(string); data = Decode(demux, &fmt.video, chroma, data); fmt.i_codec = fmt.video.i_chroma; } fmt.i_id = var_InheritInteger(demux, "image-id"); fmt.i_group = var_InheritInteger(demux, "image-group"); if (var_InheritURational(demux, &fmt.video.i_frame_rate, &fmt.video.i_frame_rate_base, "image-fps") || fmt.video.i_frame_rate <= 0 || fmt.video.i_frame_rate_base <= 0) { msg_Err(demux, "Invalid frame rate, using 10/1 instead"); fmt.video.i_frame_rate = 10; fmt.video.i_frame_rate_base = 1; } /* If loadind failed, we still continue to avoid mis-detection * by other demuxers. */ if (!data) msg_Err(demux, "Failed to load the image"); /* */ demux_sys_t *sys = malloc(sizeof(*sys)); if (!sys) { if (data) block_Release(data); es_format_Clean(&fmt); return VLC_ENOMEM; } sys->data = data; sys->es = es_out_Add(demux->out, &fmt); sys->duration = CLOCK_FREQ * var_InheritFloat(demux, "image-duration"); sys->is_realtime = var_InheritBool(demux, "image-realtime"); sys->pts_origin = sys->is_realtime ? mdate() : 0; sys->pts_next = VLC_TS_INVALID; date_Init(&sys->pts, fmt.video.i_frame_rate, fmt.video.i_frame_rate_base); date_Set(&sys->pts, 0); es_format_Clean(&fmt); demux->pf_demux = Demux; demux->pf_control = Control; demux->p_sys = sys; return VLC_SUCCESS; }
/***************************************************************************** * ProcessInitialHeader: processes the inital Opus header packet. *****************************************************************************/ static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket ) { int err; unsigned char new_stream_map[8]; decoder_sys_t *p_sys = p_dec->p_sys; OpusHeader *p_header = &p_sys->header; if( !opus_header_parse((unsigned char *)p_oggpacket->packet,p_oggpacket->bytes,p_header) ) { msg_Err( p_dec, "cannot read Opus header" ); return VLC_EGENERIC; } msg_Dbg( p_dec, "Opus audio with %d channels", p_header->channels); if((p_header->channels>2 && p_header->channel_mapping==0) || (p_header->channels>8 && p_header->channel_mapping==1) || p_header->channel_mapping>1) { msg_Err( p_dec, "Unsupported channel mapping" ); return VLC_EGENERIC; } /* Setup the format */ p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_header->channels]; p_dec->fmt_out.audio.i_channels = p_header->channels; p_dec->fmt_out.audio.i_rate = 48000; if( p_header->channels>2 && p_header->channels<9 ) { static const uint32_t *pi_ch[6] = { pi_3channels_in, pi_4channels_in, pi_5channels_in, pi_6channels_in, pi_7channels_in, pi_8channels_in }; uint8_t pi_chan_table[AOUT_CHAN_MAX]; aout_CheckChannelReorder( pi_ch[p_header->channels-3], NULL, p_dec->fmt_out.audio.i_physical_channels, pi_chan_table ); for(int i=0;i<p_header->channels;i++) new_stream_map[pi_chan_table[i]]=p_header->stream_map[i]; } /* Opus decoder init */ p_sys->p_st = opus_multistream_decoder_create( 48000, p_header->channels, p_header->nb_streams, p_header->nb_coupled, p_header->channels>2?new_stream_map:p_header->stream_map, &err ); if( !p_sys->p_st || err!=OPUS_OK ) { msg_Err( p_dec, "decoder initialization failed" ); return VLC_EGENERIC; } #ifdef OPUS_SET_GAIN if( opus_multistream_decoder_ctl( p_sys->p_st,OPUS_SET_GAIN(p_header->gain) ) != OPUS_OK ) { msg_Err( p_dec, "OPUS_SET_GAIN failed" ); opus_multistream_decoder_destroy( p_sys->p_st ); return VLC_EGENERIC; } #endif date_Init( &p_sys->end_date, 48000, 1 ); return VLC_SUCCESS; }
/***************************************************************************** * DecodeFrame: decodes an lpcm frame. **************************************************************************** * Beware, this function must be fed with complete frames (PES packet). *****************************************************************************/ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; unsigned int i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0; int i_frame_length; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; *pp_block = NULL; /* So the packet doesn't get re-sent */ /* Date management */ if( p_block->i_pts > 0 && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); return NULL; } if( p_block->i_buffer <= p_sys->i_header_size ) { msg_Err(p_dec, "frame is too short"); block_Release( p_block ); return NULL; } int i_ret; unsigned i_padding = 0; aob_group_t p_aob_group[2]; switch( p_sys->i_type ) { case LPCM_VOB: i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, p_block->p_buffer ); break; case LPCM_AOB: i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding, p_aob_group, p_block->p_buffer ); break; case LPCM_BD: i_ret = BdHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, p_block->p_buffer ); break; default: assert(0); } if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding ) { msg_Warn( p_dec, "no frame sync or too small frame" ); block_Release( p_block ); return NULL; } /* Set output properties */ if( p_dec->fmt_out.audio.i_rate != i_rate ) { date_Init( &p_sys->end_date, i_rate, 1 ); date_Set( &p_sys->end_date, p_block->i_pts ); } p_dec->fmt_out.audio.i_rate = i_rate; p_dec->fmt_out.audio.i_channels = i_channels; p_dec->fmt_out.audio.i_original_channels = i_original_channels; p_dec->fmt_out.audio.i_physical_channels = i_original_channels & AOUT_CHAN_PHYSMASK; i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) / i_channels * 8 / i_bits; if( p_sys->b_packetizer ) { p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, i_frame_length ) - p_block->i_pts; /* Just pass on the incoming frame */ return p_block; } else { /* */ if( i_bits == 16 ) { p_dec->fmt_out.i_codec = VLC_CODEC_S16B; p_dec->fmt_out.audio.i_bitspersample = 16; } else { p_dec->fmt_out.i_codec = VLC_CODEC_S24B; p_dec->fmt_out.audio.i_bitspersample = 24; } /* */ aout_buffer_t *p_aout_buffer; p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length ); if( !p_aout_buffer ) return NULL; p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, i_frame_length ) - p_aout_buffer->i_pts; p_block->p_buffer += p_sys->i_header_size + i_padding; p_block->i_buffer -= p_sys->i_header_size + i_padding; switch( p_sys->i_type ) { case LPCM_VOB: VobExtract( p_aout_buffer, p_block, i_bits ); break; case LPCM_AOB: AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group ); break; default: assert(0); case LPCM_BD: BdExtract( p_aout_buffer, p_block ); break; } block_Release( p_block ); return p_aout_buffer; } }
/***************************************************************************** * 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_CODEC_ADPCM_DK3: case VLC_CODEC_ADPCM_DK4: 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 */ p_sys = malloc(sizeof(*p_sys)); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; p_sys->prev = NULL; 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_CODEC_ADPCM_IMA_WAV: /* IMA ADPCM */ p_sys->codec = ADPCM_IMA_WAV; break; case VLC_CODEC_ADPCM_MS: /* MS ADPCM */ p_sys->codec = ADPCM_MS; break; case VLC_CODEC_ADPCM_DK4: /* Duck DK4 ADPCM */ p_sys->codec = ADPCM_DK4; break; case VLC_CODEC_ADPCM_DK3: /* Duck DK3 ADPCM */ p_sys->codec = ADPCM_DK3; break; case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */ p_sys->codec = ADPCM_EA; p_sys->prev = calloc( 2 * p_dec->fmt_in.audio.i_channels, sizeof( int16_t ) ); if( unlikely(p_sys->prev == 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 %zu", 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:%zu samplesperblock:%zu", 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->p_sys = p_sys; p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = VLC_CODEC_S16N; 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]; date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); date_Set( &p_sys->end_date, 0 ); p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; }
/**************************************************************************** * Encode: the whole thing **************************************************************************** * This function spits out encapsulation units. ****************************************************************************/ static block_t *Encode( encoder_t *p_enc, picture_t *p_pic ) { encoder_sys_t *p_sys = p_enc->p_sys; block_t *p_block, *p_output_chain = NULL; int i_plane, i_line, i_width, i_src_stride; uint8_t *p_dst; if( !p_pic ) return NULL; /* we only know if the sequence is interlaced when the first * picture arrives, so final setup is done here */ /* XXX todo, detect change of interlace */ p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first; p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive; if( p_sys->b_auto_field_coding ) p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive; if( !p_sys->p_dirac ) { date_t date; /* Initialise the encoder with the encoder context */ p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 ); if( !p_sys->p_dirac ) { msg_Err( p_enc, "Failed to initialize dirac encoder" ); return NULL; } date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base ); #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2) int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac ); i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1; date_Increment( &date, i_delayinpics ); #else date_Increment( &date, 1 ); #endif p_sys->i_pts_offset = date_Get( &date ); /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced * for each frame input. Calculate time between fields for offsetting * the second field later. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { date_Set( &date, 0 ); date_Increment( &date, 1 ); p_sys->i_field_time = date_Get( &date ) / 2; } } /* Copy input picture into encoder input buffer (stride by stride) */ /* Would be lovely to just pass the picture in, but there is noway for the * library to free it */ p_dst = p_sys->p_buffer_in; for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { uint8_t *p_src = p_pic->p[i_plane].p_pixels; i_width = p_pic->p[i_plane].i_visible_pitch; i_src_stride = p_pic->p[i_plane].i_pitch; for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ ) { vlc_memcpy( p_dst, p_src, i_width ); p_dst += i_width; p_src += i_src_stride; } } /* Load one frame of data into encoder */ if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in, p_sys->i_buffer_in ) < 0 ) { msg_Dbg( p_enc, "dirac_encoder_load() error" ); return NULL; } /* store pts in a lookaside buffer, so that the same pts may * be used for the picture in coded order */ StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date ); p_sys->i_input_picnum++; /* store dts in a queue, so that they appear in order in * coded order */ p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; /* for field coding mode, insert an extra value into both the * pts lookaside buffer and dts queue, offset to correspond * to a one field delay. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time ); p_sys->i_input_picnum++; p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; } dirac_encoder_state_t state; /* Retrieve encoded frames from encoder */ do { p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out; p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out; state = dirac_encoder_output( p_sys->p_dirac ); switch( state ) { case ENC_STATE_AVAIL: { uint32_t pic_num; /* extract data from encoder temporary buffer. */ p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size ); if( !p_block ) return NULL; memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer, p_sys->p_dirac->enc_buf.size ); /* if some flags were set for a previous block, prevent * them from getting lost */ if( p_sys->p_chain ) p_block->i_flags |= p_sys->p_chain->i_flags; /* store all extracted blocks in a chain and gather up when an * entire encapsulation unit is avaliable (ends with a picture) */ block_ChainAppend( &p_sys->p_chain, p_block ); /* Presence of a Sequence header indicates a seek point */ if( 0 == p_block->p_buffer[4] ) { p_block->i_flags |= BLOCK_FLAG_TYPE_I; if( !p_enc->fmt_out.p_extra ) { const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 }; uint32_t len = GetDWBE( p_block->p_buffer + 5 ); /* if it hasn't been done so far, stash a copy of the * sequence header for muxers such as ogg */ /* The OggDirac spec advises that a Dirac EOS DataUnit * is appended to the sequence header to allow guard * against poor streaming servers */ /* XXX, should this be done using the packetizer ? */ p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) ); if( !p_enc->fmt_out.p_extra ) return NULL; memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len); memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) ); SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len ); p_enc->fmt_out.i_extra = len + sizeof(eos); } } if( ReadDiracPictureNumber( &pic_num, p_block ) ) { /* Finding a picture terminates an ecapsulation unit, gather * all data and output; use the next dts value queued up * and find correct pts in the tlb */ p_block = block_FifoGet( p_sys->p_dts_fifo ); p_sys->p_chain->i_dts = p_block->i_dts; p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num ); block_Release( p_block ); block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) ); p_sys->p_chain = NULL; } else { p_block = NULL; } break; } case ENC_STATE_BUFFER: break; case ENC_STATE_INVALID: default: break; } } while( state == ENC_STATE_AVAIL ); return p_output_chain; }
/***************************************************************************** * 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 ) { /* Planar YUV */ case VLC_CODEC_I444: case VLC_CODEC_J444: case VLC_CODEC_I440: case VLC_CODEC_J440: case VLC_CODEC_I422: case VLC_CODEC_J422: case VLC_CODEC_I420: case VLC_CODEC_J420: case VLC_CODEC_YV12: case VLC_CODEC_YV9: case VLC_CODEC_I411: case VLC_CODEC_I410: case VLC_CODEC_GREY: case VLC_CODEC_YUVP: case VLC_CODEC_NV12: case VLC_CODEC_NV21: case VLC_CODEC_I422_10L: case VLC_CODEC_I422_10B: /* Packed YUV */ case VLC_CODEC_YUYV: case VLC_CODEC_YVYU: case VLC_CODEC_UYVY: case VLC_CODEC_VYUY: /* RGB */ case VLC_CODEC_RGB32: case VLC_CODEC_RGB24: case VLC_CODEC_RGB16: case VLC_CODEC_RGB15: case VLC_CODEC_RGB8: case VLC_CODEC_RGBP: case VLC_CODEC_RGBA: break; default: 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 ) return VLC_ENOMEM; /* Misc init */ p_dec->p_sys->b_packetizer = false; p_sys->b_invert = false; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = true; } if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; if( p_dec->fmt_in.video.i_visible_width <= 0 || p_dec->fmt_in.video.i_visible_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } /* Find out p_vdec->i_raw_size */ video_format_Setup( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, p_dec->fmt_in.video.i_visible_width, p_dec->fmt_in.video.i_visible_height, p_dec->fmt_in.video.i_sar_num, p_dec->fmt_in.video.i_sar_den ); picture_t picture; picture_Setup( &picture, p_dec->fmt_out.i_codec, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height, 0, 1 ); p_sys->i_raw_size = 0; for( int i = 0; i < picture.i_planes; i++ ) { p_sys->i_raw_size += picture.p[i].i_visible_pitch * picture.p[i].i_visible_lines; p_sys->planes[i] = picture.p[i]; } if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den ) { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; return VLC_SUCCESS; }
/***************************************************************************** * OpenAudio: *****************************************************************************/ static int OpenAudio( decoder_t *p_dec ) { decoder_sys_t *p_sys; int i_error; char fcc[4]; unsigned long WantedBufferSize; unsigned long InputBufferSize = 0; unsigned long OutputBufferSize = 0; /* get lock, avoid segfault */ vlc_mutex_lock( &qt_mutex ); p_sys = calloc( 1, sizeof( decoder_sys_t ) ); p_dec->p_sys = p_sys; p_dec->pf_decode_audio = DecodeAudio; if( p_dec->fmt_in.i_original_fourcc ) memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 ); else memcpy( fcc, &p_dec->fmt_in.i_codec, 4 ); #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, VLC_CODEC_S16N ); 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]; date_Init( &p_sys->date, p_dec->fmt_out.audio.i_rate, 1 ); p_sys->i_buffer = 0; p_sys->i_buffer_size = 100*1000; p_sys->p_buffer = malloc( p_sys->i_buffer_size ); if( !p_sys->p_buffer ) goto exit_error; p_sys->i_out = 0; p_sys->i_out_frames = 0; vlc_mutex_unlock( &qt_mutex ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( &qt_mutex ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * DecodeAudio: Called to decode one frame *****************************************************************************/ aout_buffer_t * DecodeAudio ( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_used, i_output; aout_buffer_t *p_buffer; block_t *p_block; AVPacket pkt; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; if( !p_sys->p_context->extradata_size && p_dec->fmt_in.i_extra && p_sys->b_delayed_open) { InitDecoderConfig( p_dec, p_sys->p_context); if( ffmpeg_OpenCodec( p_dec ) ) msg_Err( p_dec, "Cannot open decoder %s", p_sys->psz_namecodec ); } if( p_sys->b_delayed_open ) { block_Release( p_block ); return NULL; } if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { block_Release( p_block ); avcodec_flush_buffers( p_sys->p_context ); p_sys->i_samples = 0; date_Set( &p_sys->end_date, 0 ); if( p_sys->i_codec_id == CODEC_ID_MP2 || p_sys->i_codec_id == CODEC_ID_MP3 ) p_sys->i_reject_count = 3; return NULL; } if( p_sys->i_samples > 0 ) { /* More data */ p_buffer = SplitBuffer( p_dec ); if( !p_buffer ) block_Release( p_block ); return p_buffer; } if( !date_Get( &p_sys->end_date ) && !p_block->i_pts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); return NULL; } if( p_block->i_buffer <= 0 ) { block_Release( p_block ); return NULL; } if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 ) { *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE ); if( !p_block ) return NULL; p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE; memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE ); p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED; } do { i_output = __MAX( p_block->i_buffer, p_sys->i_output_max ); if( i_output > p_sys->i_output_max ) { /* Grow output buffer if necessary (eg. for PCM data) */ p_sys->p_output = av_realloc( p_sys->p_output, i_output ); } av_init_packet( &pkt ); pkt.data = p_block->p_buffer; pkt.size = p_block->i_buffer; i_used = avcodec_decode_audio3( p_sys->p_context, (int16_t*)p_sys->p_output, &i_output, &pkt ); if( i_used < 0 || i_output < 0 ) { if( i_used < 0 ) msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); block_Release( p_block ); return NULL; } else if( (size_t)i_used > p_block->i_buffer ) { i_used = p_block->i_buffer; } p_block->i_buffer -= i_used; p_block->p_buffer += i_used; } while( p_block->i_buffer > 0 && i_output <= 0 ); if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 8 || p_sys->p_context->sample_rate <= 0 ) { msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d", p_sys->p_context->channels, p_sys->p_context->sample_rate ); block_Release( p_block ); return NULL; } if( p_dec->fmt_out.audio.i_rate != (unsigned int)p_sys->p_context->sample_rate ) { date_Init( &p_sys->end_date, p_sys->p_context->sample_rate, 1 ); date_Set( &p_sys->end_date, p_block->i_pts ); } /* **** Set audio output parameters **** */ SetupOutputFormat( p_dec, true ); if( p_block->i_pts != 0 && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } p_block->i_pts = 0; /* **** Now we can output these samples **** */ p_sys->i_samples = i_output / (p_dec->fmt_out.audio.i_bitspersample / 8) / p_sys->p_context->channels; p_sys->p_samples = p_sys->p_output; /* Silent unwanted samples */ if( p_sys->i_reject_count > 0 ) { memset( p_sys->p_output, 0, i_output ); p_sys->i_reject_count--; } p_buffer = SplitBuffer( p_dec ); if( !p_buffer ) block_Release( p_block ); return p_buffer; }
/***************************************************************************** * InitAudioDec: initialize audio decoder ***************************************************************************** * The ffmpeg codec will be opened, some memory allocated. *****************************************************************************/ int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, const char *psz_namecodec ) { decoder_sys_t *p_sys; /* 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; } p_codec->type = AVMEDIA_TYPE_AUDIO; p_context->codec_type = AVMEDIA_TYPE_AUDIO; p_context->codec_id = i_codec_id; p_sys->p_context = p_context; p_sys->p_codec = p_codec; p_sys->i_codec_id = i_codec_id; p_sys->psz_namecodec = psz_namecodec; p_sys->b_delayed_open = true; // Initialize decoder extradata InitDecoderConfig( p_dec, p_context); /* ***** Open the codec ***** */ if( ffmpeg_OpenCodec( p_dec ) < 0 ) { msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); free( p_sys->p_context->extradata ); free( p_sys ); return VLC_EGENERIC; } switch( i_codec_id ) { case CODEC_ID_WAVPACK: p_sys->i_output_max = 8 * sizeof(int32_t) * 131072; break; case CODEC_ID_TTA: p_sys->i_output_max = p_sys->p_context->channels * sizeof(int32_t) * p_sys->p_context->sample_rate * 2; break; case CODEC_ID_FLAC: p_sys->i_output_max = 8 * sizeof(int32_t) * 65535; break; #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 35, 0 ) case CODEC_ID_WMAPRO: p_sys->i_output_max = 8 * sizeof(float) * 6144; /* (1 << 12) * 3/2 */ break; #endif default: p_sys->i_output_max = 0; break; } if( p_sys->i_output_max < AVCODEC_MAX_AUDIO_FRAME_SIZE ) p_sys->i_output_max = AVCODEC_MAX_AUDIO_FRAME_SIZE; msg_Dbg( p_dec, "Using %d bytes output buffer", p_sys->i_output_max ); p_sys->p_output = av_malloc( p_sys->i_output_max ); p_sys->p_samples = NULL; p_sys->i_samples = 0; p_sys->i_reject_count = 0; p_sys->b_extract = false; p_sys->i_previous_channels = 0; p_sys->i_previous_layout = 0; /* */ p_dec->fmt_out.i_cat = AUDIO_ES; /* Try to set as much information as possible but do not trust it */ SetupOutputFormat( p_dec, false ); date_Set( &p_sys->end_date, 0 ); if( p_dec->fmt_out.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 ); else if( p_dec->fmt_in.audio.i_rate ) date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 ); return VLC_SUCCESS; }
static block_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block ) { block_t *p_speex_bit_block = *pp_block; decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_aout_buffer; int i_decode_ret; unsigned int i_speex_frame_size; if ( !p_speex_bit_block || p_speex_bit_block->i_pts <= VLC_TS_INVALID ) return NULL; /* If the SpeexBits buffer size is 0 (a default value), we know that a proper initialization has not yet been done. */ if ( p_sys->bits.buf_size==0 ) { p_sys->p_header = malloc(sizeof(SpeexHeader)); if ( !p_sys->p_header ) { msg_Err( p_dec, "Could not allocate a Speex header."); return NULL; } const SpeexMode *mode = speex_lib_get_mode((p_sys->rtp_rate / 8000) >> 1); speex_init_header( p_sys->p_header,p_sys->rtp_rate, 1, mode ); speex_bits_init( &p_sys->bits ); p_sys->p_state = speex_decoder_init( mode ); if ( !p_sys->p_state ) { msg_Err( p_dec, "Could not allocate a Speex decoder." ); free( p_sys->p_header ); return NULL; } /* Assume that variable bit rate is enabled. Also assume that there is only one frame per packet. */ p_sys->p_header->vbr = 1; p_sys->p_header->frames_per_packet = 1; p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels; p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_sys->p_header->nb_channels]; p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate; if ( speex_mode_query( &speex_nb_mode, SPEEX_MODE_FRAME_SIZE, &i_speex_frame_size ) ) { msg_Err( p_dec, "Could not determine the frame size." ); speex_decoder_destroy( p_sys->p_state ); free( p_sys->p_header ); return NULL; } p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size; date_Init(&p_sys->end_date, p_sys->p_header->rate, 1); }
/***************************************************************************** * ProcessInitialHeader: processes the inital Speex header packet. *****************************************************************************/ static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; void *p_state; SpeexHeader *p_header; const SpeexMode *p_mode; SpeexCallback callback; p_sys->p_header = p_header = speex_packet_to_header( (char *)p_oggpacket->packet, p_oggpacket->bytes ); if( !p_header ) { msg_Err( p_dec, "cannot read Speex header" ); return VLC_EGENERIC; } if( p_header->mode >= SPEEX_NB_MODES || p_header->mode < 0 ) { msg_Err( p_dec, "mode number %d does not (yet/any longer) exist in " "this version of libspeex.", p_header->mode ); return VLC_EGENERIC; } p_mode = speex_mode_list[p_header->mode]; if( p_mode == NULL ) return VLC_EGENERIC; if( p_header->speex_version_id > 1 ) { msg_Err( p_dec, "this file was encoded with Speex bit-stream " "version %d which is not supported by this decoder.", p_header->speex_version_id ); return VLC_EGENERIC; } if( p_mode->bitstream_version < p_header->mode_bitstream_version ) { msg_Err( p_dec, "file encoded with a newer version of Speex." ); return VLC_EGENERIC; } if( p_mode->bitstream_version > p_header->mode_bitstream_version ) { msg_Err( p_dec, "file encoded with an older version of Speex." ); return VLC_EGENERIC; } msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s", p_header->rate, p_mode->modeName, ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo", p_header->vbr ? ", VBR)" : ")" ); /* Take care of speex decoder init */ speex_bits_init( &p_sys->bits ); p_sys->p_state = p_state = speex_decoder_init( p_mode ); if( !p_state ) { msg_Err( p_dec, "decoder initialization failed" ); return VLC_EGENERIC; } if( p_header->nb_channels == 2 ) { SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; p_sys->stereo = stereo; callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = &p_sys->stereo; speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback ); } if( p_header->nb_channels <= 0 || p_header->nb_channels > 5 ) { msg_Err( p_dec, "invalid number of channels (not between 1 and 5): %i", p_header->nb_channels ); return VLC_EGENERIC; } /* Setup the format */ p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_header->nb_channels]; p_dec->fmt_out.audio.i_channels = p_header->nb_channels; p_dec->fmt_out.audio.i_rate = p_header->rate; date_Init( &p_sys->end_date, p_header->rate, 1 ); return VLC_SUCCESS; }
static int Open (vlc_object_t *p_this) { decoder_t *p_dec = (decoder_t *)p_this; if (p_dec->fmt_in.i_codec != VLC_CODEC_MIDI) return VLC_EGENERIC; decoder_sys_t *p_sys = (decoder_sys_t *)malloc (sizeof (*p_sys)); // sunqueen modify if (unlikely(p_sys == NULL)) return VLC_ENOMEM; p_sys->settings = new_fluid_settings (); p_sys->synth = new_fluid_synth (p_sys->settings); p_sys->soundfont = -1; char *font_path = var_InheritString (p_this, "soundfont"); if (font_path != NULL) { msg_Dbg (p_this, "loading sound fonts file %s", font_path); p_sys->soundfont = fluid_synth_sfload (p_sys->synth, font_path, 1); if (p_sys->soundfont == -1) msg_Err (p_this, "cannot load sound fonts file %s", font_path); free (font_path); } #ifdef _POSIX_VERSION else { glob_t gl; glob ("/usr/share/sounds/sf2/*.sf2", GLOB_NOESCAPE, NULL, &gl); for (size_t i = 0; i < gl.gl_pathc; i++) { const char *path = gl.gl_pathv[i]; msg_Dbg (p_this, "loading sound fonts file %s", path); p_sys->soundfont = fluid_synth_sfload (p_sys->synth, path, 1); if (p_sys->soundfont != -1) break; /* it worked! */ msg_Err (p_this, "cannot load sound fonts file %s", path); } globfree (&gl); } #endif if (p_sys->soundfont == -1) { msg_Err (p_this, "sound font file required for synthesis"); dialog_Fatal (p_this, _("MIDI synthesis not set up"), _("A sound font file (.SF2) is required for MIDI synthesis.\n" "Please install a sound font and configure it " "from the VLC preferences " "(Input / Codecs > Audio codecs > FluidSynth).\n")); delete_fluid_synth (p_sys->synth); delete_fluid_settings (p_sys->settings); free (p_sys); return VLC_EGENERIC; } fluid_synth_set_chorus_on (p_sys->synth, var_InheritBool (p_this, "synth-chorus")); fluid_synth_set_gain (p_sys->synth, var_InheritFloat (p_this, "synth-gain")); fluid_synth_set_polyphony (p_sys->synth, var_InheritInteger (p_this, "synth-polyphony")); fluid_synth_set_reverb_on (p_sys->synth, var_InheritBool (p_this, "synth-reverb")); p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.audio.i_rate = var_InheritInteger (p_this, "synth-sample-rate");; fluid_synth_set_sample_rate (p_sys->synth, p_dec->fmt_out.audio.i_rate); 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; date_Init (&p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1); date_Set (&p_sys->end_date, 0); p_dec->p_sys = p_sys; p_dec->pf_decode_audio = DecodeBlock; return VLC_SUCCESS; }
/***************************************************************************** * ProcessHeaders: process Vorbis headers. *****************************************************************************/ static int ProcessHeaders( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; ogg_packet oggpacket; unsigned pi_size[XIPH_MAX_HEADER_COUNT]; void *pp_data[XIPH_MAX_HEADER_COUNT]; unsigned i_count; if( xiph_SplitHeaders( pi_size, pp_data, &i_count, p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) ) return VLC_EGENERIC; if( i_count < 3 ) return VLC_EGENERIC; oggpacket.granulepos = -1; oggpacket.e_o_s = 0; oggpacket.packetno = 0; /* Take care of the initial Vorbis header */ oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ oggpacket.bytes = pi_size[0]; oggpacket.packet = pp_data[0]; if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) { msg_Err( p_dec, "this bitstream does not contain Vorbis audio data"); return VLC_EGENERIC; } /* Setup the format */ p_dec->fmt_out.audio.i_rate = p_sys->vi.rate; p_dec->fmt_out.audio.i_channels = p_sys->vi.channels; if( p_dec->fmt_out.audio.i_channels >= ARRAY_SIZE(pi_channels_maps) ) { msg_Err( p_dec, "invalid number of channels (1-%zu): %i", ARRAY_SIZE(pi_channels_maps), p_dec->fmt_out.audio.i_channels ); return VLC_EGENERIC; } p_dec->fmt_out.audio.i_physical_channels = p_dec->fmt_out.audio.i_original_channels = pi_channels_maps[p_sys->vi.channels]; p_dec->fmt_out.i_bitrate = __MAX( 0, (int32_t) p_sys->vi.bitrate_nominal ); date_Init( &p_sys->end_date, p_sys->vi.rate, 1 ); msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ud", p_sys->vi.channels, p_sys->vi.rate, p_dec->fmt_out.i_bitrate ); /* The next packet in order is the comments header */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[1]; oggpacket.packet = pp_data[1]; if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) { msg_Err( p_dec, "2nd Vorbis header is corrupted" ); return VLC_EGENERIC; } ParseVorbisComments( p_dec ); /* The next packet in order is the codebooks header * We need to watch out that this packet is not missing as a * missing or corrupted header is fatal. */ oggpacket.b_o_s = 0; oggpacket.bytes = pi_size[2]; oggpacket.packet = pp_data[2]; if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 ) { msg_Err( p_dec, "3rd Vorbis header is corrupted" ); return VLC_EGENERIC; } if( !p_sys->b_packetizer ) { /* Initialize the Vorbis packet->PCM decoder */ vorbis_synthesis_init( &p_sys->vd, &p_sys->vi ); vorbis_block_init( &p_sys->vd, &p_sys->vb ); } else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); } ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels, p_dec->fmt_out.audio.i_physical_channels, true); return VLC_SUCCESS; }