/***************************************************************************** * DecodePacket: decodes a Speex packet. *****************************************************************************/ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_oggpacket->bytes ) { /* Copy Ogg packet to Speex bitstream */ speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet, p_oggpacket->bytes ); p_sys->i_frame_in_packet = 0; } /* Decode one frame at a time */ if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet ) { block_t *p_aout_buffer; if( p_sys->p_header->frame_size == 0 ) return NULL; p_aout_buffer = decoder_NewAudioBuffer( p_dec, p_sys->p_header->frame_size ); if( !p_aout_buffer ) { return NULL; } switch( speex_decode_int( p_sys->p_state, &p_sys->bits, (int16_t *)p_aout_buffer->p_buffer ) ) { case -2: msg_Err( p_dec, "decoding error: corrupted stream?" ); case -1: /* End of stream */ return NULL; } if( speex_bits_remaining( &p_sys->bits ) < 0 ) { msg_Err( p_dec, "decoding overflow: corrupted stream?" ); } if( p_sys->p_header->nb_channels == 2 ) speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer, p_sys->p_header->frame_size, &p_sys->stereo ); /* Date management */ p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, p_sys->p_header->frame_size ) - p_aout_buffer->i_pts; p_sys->i_frame_in_packet++; return p_aout_buffer; } else { return NULL; } }
/***************************************************************************** * SplitBuffer: Needed because aout really doesn't like big audio chunk and * wma produces easily > 30000 samples... *****************************************************************************/ static aout_buffer_t *SplitBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_samples = __MIN( p_sys->i_samples, 4096 ); aout_buffer_t *p_buffer; if( i_samples == 0 ) return NULL; if( ( p_buffer = decoder_NewAudioBuffer( p_dec, i_samples ) ) == NULL ) return NULL; p_buffer->i_pts = date_Get( &p_sys->end_date ); p_buffer->i_length = date_Increment( &p_sys->end_date, i_samples ) - p_buffer->i_pts; if( p_sys->b_extract ) aout_ChannelExtract( p_buffer->p_buffer, p_dec->fmt_out.audio.i_channels, p_sys->p_samples, p_sys->p_context->channels, i_samples, p_sys->pi_extraction, p_dec->fmt_out.audio.i_bitspersample ); else memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_buffer ); p_sys->p_samples += i_samples * p_sys->p_context->channels * ( p_dec->fmt_out.audio.i_bitspersample / 8 ); p_sys->i_samples -= i_samples; return p_buffer; }
static int Demux (demux_t *demux) { demux_sys_t *sys = demux->p_sys; /* Next track */ if (gme_track_ended (sys->emu)) { msg_Dbg (demux, "track %u ended", sys->track_id); if (++sys->track_id >= (unsigned)gme_track_count (sys->emu)) return 0; demux->info.i_update |= INPUT_UPDATE_TITLE; demux->info.i_title = sys->track_id; gme_start_track (sys->emu, sys->track_id); } block_t *block = block_Alloc (2 * 2 * SAMPLES); if (unlikely(block == NULL)) return 0; gme_err_t ret = gme_play (sys->emu, 2 * SAMPLES, (void *)block->p_buffer); if (ret != NULL) { block_Release (block); msg_Err (demux, "%s", ret); return 0; } block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts); es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); es_out_Send (demux->out, sys->es, block); date_Increment (&sys->pts, SAMPLES); return 1; }
/***************************************************************************** * Demux: *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; block_t *p_frame; const int i_bk = ( p_sys->fmt.audio.i_bitspersample / 8 ) * p_sys->fmt.audio.i_channels; p_frame = block_Alloc( p_sys->fmt.audio.i_rate / 10 * i_bk ); if( !p_frame ) return VLC_DEMUXER_EGENERIC; const int i_read = ModPlug_Read( p_sys->f, p_frame->p_buffer, p_frame->i_buffer ); if( i_read <= 0 ) { /* EOF */ block_Release( p_frame ); return VLC_DEMUXER_EOF; } p_frame->i_buffer = i_read; p_frame->i_dts = p_frame->i_pts = date_Get( &p_sys->pts ); es_out_SetPCR( p_demux->out, p_frame->i_pts ); es_out_Send( p_demux->out, p_sys->es, p_frame ); date_Increment( &p_sys->pts, i_read / i_bk ); return VLC_DEMUXER_SUCCESS; }
static int Demux (demux_t *demux) { demux_sys_t *sys = demux->p_sys; block_t *block = block_Alloc( sys->block_size); if (unlikely(block==NULL)) return 0; if (!sys->tune->getStatus()) { block_Release (block); return 0; } int i_read = sys->player->play ((void*)block->p_buffer, block->i_buffer); if (i_read <= 0) { block_Release (block); return 0; } block->i_buffer = i_read; block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts); es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); es_out_Send (demux->out, sys->es, block); date_Increment (&sys->pts, i_read / sys->bytes_per_frame); return 1; }
static int DemuxOnce (demux_t *demux, bool master) { demux_sys_t *sys = demux->p_sys; mtime_t pts = date_Get (&sys->date); lldiv_t d; unsigned h, m, s, f; d = lldiv (pts, CLOCK_FREQ); f = d.rem * sys->date.i_divider_num / sys->date.i_divider_den / CLOCK_FREQ; d = lldiv (d.quot, 60); s = d.rem; d = lldiv (d.quot, 60); m = d.rem; h = d.quot; char *str; int len = asprintf (&str, "%02u:%02u:%02u:%02u", h, m, s, f); if (len == -1) return -1; block_t *block = block_heap_Alloc (str, len + 1); if (unlikely(block == NULL)) return -1; block->i_buffer = len; assert(str[len] == '\0'); block->i_pts = block->i_dts = pts; block->i_length = date_Increment (&sys->date, 1) - pts; es_out_Send (demux->out, sys->es, block); if (master) es_out_SetPCR(demux->out, pts); return 1; }
/***************************************************************************** * Demux: read packet and send them to decoders ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; int64_t i_offset = vlc_stream_Tell( p_demux->s ); unsigned i_frames = p_sys->i_block_frames; if( p_sys->i_data_size > 0 && (i_offset - HEADER_LENGTH) >= p_sys->i_data_size ) { return VLC_DEMUXER_EOF; } p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size * i_frames ); if( p_block == NULL ) { msg_Warn( p_demux, "cannot read data" ); return VLC_DEMUXER_EOF; } i_frames = p_block->i_buffer / p_sys->i_frame_size; p_block->i_dts = p_block->i_pts = date_Get( &p_sys->pts ); es_out_SetPCR( p_demux->out, p_block->i_pts ); es_out_Send( p_demux->out, p_sys->p_es, p_block ); date_Increment( &p_sys->pts, i_frames * FRAME_LENGTH ); return VLC_DEMUXER_SUCCESS; }
/***************************************************************************** * Demux: read packet and send them to decoders ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; int64_t i_offset; unsigned i_frames = p_sys->i_block_frames; i_offset = stream_Tell( p_demux->s ); if( p_sys->i_data_size > 0 && i_offset >= p_sys->i_data_offset + p_sys->i_data_size ) { /* EOF */ return 0; } p_block = stream_Block( p_demux->s, p_sys->fmt.audio.i_bytes_per_frame * i_frames ); if( p_block == NULL ) { msg_Warn( p_demux, "cannot read data" ); return 0; } i_frames = p_block->i_buffer / p_sys->fmt.audio.i_bytes_per_frame; p_block->i_dts = p_block->i_pts = VLC_TS_0 + date_Get( &p_sys->pts ); es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts ); es_out_Send( p_demux->out, p_sys->p_es, p_block ); date_Increment( &p_sys->pts, i_frames * p_sys->fmt.audio.i_frame_length ); return 1; }
static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) { decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; const uint8_t *p_buf = &p_block->p_buffer[2]; size_t i_buf = p_block->i_buffer - 2; while( i_buf > 4 && p_buf[0] == 0xFF ) { size_t i_size = 2 + GetWBE( &p_buf[2] ); if( i_size > i_buf ) break; if( p_buf[1] == 0xC0 && i_buf > 9 ) { uint16_t i_height = GetWBE( &p_buf[5] ); uint16_t i_width = GetWBE( &p_buf[7] ); if( i_height && i_width && (p_dec->fmt_out.video.i_height != i_height || p_dec->fmt_out.video.i_width != i_width) ) { p_dec->fmt_out.video.i_width = p_dec->fmt_out.video.i_visible_width = i_width; p_dec->fmt_out.video.i_height = p_dec->fmt_out.video.i_visible_height = i_height; } break; } i_buf -= i_size; p_buf += i_size; } if( p_block->i_dts == VLC_TICK_INVALID ) p_block->i_dts = p_block->i_pts; else if( p_block->i_pts == VLC_TICK_INVALID ) p_block->i_pts = p_block->i_dts; vlc_tick_t i_prev_dts = date_Get( &p_sys->date ); if( p_block->i_dts != VLC_TICK_INVALID ) { date_Set( &p_sys->date, p_block->i_dts ); } else if( p_dec->fmt_in.video.i_frame_rate && p_dec->fmt_in.video.i_frame_rate_base ) { date_Increment( &p_sys->date, 1 ); p_block->i_dts = p_block->i_pts = date_Get( &p_sys->date ); } if( i_prev_dts != VLC_TICK_INVALID && p_block->i_dts != VLC_TICK_INVALID ) p_block->i_length = p_block->i_dts - i_prev_dts; *pb_ts_used = true; p_block->i_flags = p_sys->i_next_block_flags | BLOCK_FLAG_TYPE_I; p_sys->i_next_block_flags = 0; return p_block; }
/***************************************************************************** * DecodePacket: decodes a Opus packet. *****************************************************************************/ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket, int i_nb_samples, int i_end_trim ) { decoder_sys_t *p_sys = p_dec->p_sys; if( !p_oggpacket->bytes ) return NULL; int spp; spp=opus_packet_get_nb_frames(p_oggpacket->packet,p_oggpacket->bytes); if(spp>0)spp*=opus_packet_get_samples_per_frame(p_oggpacket->packet,48000); if(spp<120||spp>120*48)return NULL; block_t *p_aout_buffer=decoder_NewAudioBuffer( p_dec, spp ); if ( !p_aout_buffer ) { msg_Err(p_dec, "Oops: No new buffer was returned!"); return NULL; } spp=opus_multistream_decode_float(p_sys->p_st, p_oggpacket->packet, p_oggpacket->bytes, (float *)p_aout_buffer->p_buffer, spp, 0); if( spp < 0 || i_nb_samples <= 0 || i_end_trim >= i_nb_samples) { block_Release(p_aout_buffer); if( spp < 0 ) msg_Err( p_dec, "Error: corrupted stream?" ); return NULL; } p_aout_buffer->i_buffer = (i_nb_samples - i_end_trim) * p_sys->header.channels * sizeof(float); if( spp > i_nb_samples ) { memmove(p_aout_buffer->p_buffer, p_aout_buffer->p_buffer + (spp - i_nb_samples)*p_sys->header.channels*sizeof(float), (i_nb_samples - i_end_trim)*p_sys->header.channels*sizeof(float)); } i_nb_samples -= i_end_trim; #ifndef OPUS_SET_GAIN if(p_sys->header.gain!=0) { float gain = pow(10., p_sys->header.gain/5120.); float *buf =(float *)p_aout_buffer->p_buffer; int i; for( i = 0; i < i_nb_samples*p_sys->header.channels; i++) buf[i] *= gain; } #endif p_aout_buffer->i_nb_samples = i_nb_samples; p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, i_nb_samples ) - p_aout_buffer->i_pts; return p_aout_buffer; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with complete frames. ****************************************************************************/ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; void *p_buf; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; if( p_block->i_pts <= VLC_TS_INVALID && p_block->i_dts <= VLC_TS_INVALID && !date_Get( &p_sys->pts ) ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); return NULL; } /* Date management: If there is a pts avaliable, use that. */ if( p_block->i_pts > VLC_TS_INVALID ) { date_Set( &p_sys->pts, p_block->i_pts ); } else if( p_block->i_dts > VLC_TS_INVALID ) { /* NB, davidf doesn't quite agree with this in general, it is ok * for rawvideo since it is in order (ie pts=dts), however, it * may not be ok for an out-of-order codec, so don't copy this * without thinking */ date_Set( &p_sys->pts, p_block->i_dts ); } if( p_block->i_buffer < p_sys->i_raw_size ) { msg_Warn( p_dec, "invalid frame size (%zu < %zu)", p_block->i_buffer, p_sys->i_raw_size ); block_Release( p_block ); return NULL; } if( p_sys->b_packetizer ) { p_buf = SendFrame( p_dec, p_block ); } else { p_buf = DecodeFrame( p_dec, p_block ); } /* Date management: 1 frame per packet */ date_Increment( &p_sys->pts, 1 ); *pp_block = NULL; return p_buf; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with whole samples (see nBlockAlign). ****************************************************************************/ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; if( !pp_block || !*pp_block ) return NULL; block_t *p_block = *pp_block; if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } else if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); return NULL; } /* Don't re-use the same pts twice */ p_block->i_pts = VLC_TS_INVALID; unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits; if( samples == 0 ) { block_Release( p_block ); return NULL; } /* Create chunks of max 1024 samples */ if( samples > 1024 ) samples = 1024; block_t *p_out = decoder_NewAudioBuffer( p_dec, samples ); if( p_out == NULL ) { block_Release( p_block ); return NULL; } p_out->i_pts = date_Get( &p_sys->end_date ); p_out->i_length = date_Increment( &p_sys->end_date, samples ) - p_out->i_pts; if( p_sys->decode != NULL ) p_sys->decode( p_out->p_buffer, p_block->p_buffer, samples * p_dec->fmt_in.audio.i_channels ); else memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_buffer ); samples = (samples * p_sys->framebits) / 8; p_block->p_buffer += samples; p_block->i_buffer -= samples; return p_out; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with whole samples (see nBlockAlign). ****************************************************************************/ static int DecodeBlock( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) ) { Flush( p_dec ); if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) goto skip; } if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } else if( !date_Get( &p_sys->end_date ) ) /* We've just started the stream, wait for the first PTS. */ goto skip; unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits; if( samples == 0 ) goto skip; if( p_sys->decode != NULL ) { if( decoder_UpdateAudioFormat( p_dec ) ) goto skip; block_t *p_out = decoder_NewAudioBuffer( p_dec, samples ); if( p_out == NULL ) goto skip; p_sys->decode( p_out->p_buffer, p_block->p_buffer, samples * p_dec->fmt_in.audio.i_channels ); block_Release( p_block ); p_block = p_out; } else { decoder_UpdateAudioFormat( p_dec ); p_block->i_nb_samples = samples; p_block->i_buffer = samples * (p_sys->framebits / 8); } p_block->i_pts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, samples ) - p_block->i_pts; decoder_QueueAudio( p_dec, p_block ); return VLCDEC_SUCCESS; skip: block_Release( p_block ); return VLCDEC_SUCCESS; }
int transcode_audio_process( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *in, block_t **out ) { sout_stream_sys_t *p_sys = p_stream->p_sys; block_t *p_block, *p_audio_buf; *out = NULL; while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder, &in )) ) { sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 ); if( p_sys->b_master_sync ) { mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1; if ( p_audio_buf->i_pts - i_dts > MASTER_SYNC_MAX_DRIFT || p_audio_buf->i_pts - i_dts < -MASTER_SYNC_MAX_DRIFT ) { msg_Dbg( p_stream, "drift is too high, resetting master sync" ); date_Set( &id->interpolated_pts, p_audio_buf->i_pts ); i_dts = p_audio_buf->i_pts + 1; } p_sys->i_master_drift = p_audio_buf->i_pts - i_dts; date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples ); p_audio_buf->i_pts -= p_sys->i_master_drift; } p_audio_buf->i_dts = p_audio_buf->i_pts; /* Run filter chain */ if( id->p_uf_chain ) { p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain, p_audio_buf ); if( !p_audio_buf ) abort(); } p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf ); if( !p_audio_buf ) abort(); p_audio_buf->i_dts = p_audio_buf->i_pts; audio_timer_start( id->p_encoder ); p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf ); audio_timer_stop( id->p_encoder ); block_ChainAppend( out, p_block ); block_Release( p_audio_buf ); } return VLC_SUCCESS; }
/***************************************************************************** * Fill buffer *****************************************************************************/ static int FillBuffer( int16_t *p_data, int *pi_data, date_t *pi_date, date_t *pi_date_end, goom_thread_t *p_this ) { int i_samples = 0; block_t *p_block; while( *pi_data < 512 ) { if( !p_this->i_blocks ) return VLC_EGENERIC; p_block = p_this->pp_blocks[0]; i_samples = __MIN( (unsigned)(512 - *pi_data), p_block->i_buffer / sizeof(float) / p_this->i_channels ); /* Date management */ if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( pi_date_end ) ) { date_Set( pi_date_end, p_block->i_pts ); } p_block->i_pts = VLC_TS_INVALID; date_Increment( pi_date_end, i_samples ); while( i_samples > 0 ) { float *p_float = (float *)p_block->p_buffer; p_data[*pi_data] = FloatToInt16( p_float[0] ); if( p_this->i_channels > 1 ) p_data[512 + *pi_data] = FloatToInt16( p_float[1] ); (*pi_data)++; p_block->p_buffer += (sizeof(float) * p_this->i_channels); p_block->i_buffer -= (sizeof(float) * p_this->i_channels); i_samples--; } if( !p_block->i_buffer ) { block_Release( p_block ); p_this->i_blocks--; if( p_this->i_blocks ) memmove( p_this->pp_blocks, p_this->pp_blocks + 1, p_this->i_blocks * sizeof(block_t *) ); } } *pi_date = *pi_date_end; *pi_data = 0; return VLC_SUCCESS; }
/***************************************************************************** * Demux: read chunks and send them to the synthesizer ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/ static int Demux (demux_t *p_demux) { stream_t *s = p_demux->s; demux_sys_t *p_sys = p_demux->p_sys; uint64_t pulse = p_sys->pulse, next_pulse = UINT64_MAX; if (pulse == UINT64_MAX) return 0; /* all tracks are done */ es_out_Control (p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + date_Get (&p_sys->pts)); for (unsigned i = 0; i < p_sys->trackc; i++) { mtrk_t *track = p_sys->trackv + i; while (track->next == pulse) { if (HandleMessage (p_demux, track) || ReadDeltaTime (s, track)) { msg_Err (p_demux, "fatal parsing error"); return VLC_EGENERIC; } } if (track->next < next_pulse) next_pulse = track->next; } mtime_t cur_tick = (date_Get (&p_sys->pts) + 9999) / 10000, last_tick; if (next_pulse != UINT64_MAX) last_tick = date_Increment (&p_sys->pts, next_pulse - pulse) / 10000; else last_tick = cur_tick + 1; /* MIDI Tick emulation (ping the decoder every 10ms) */ while (cur_tick < last_tick) { block_t *tick = block_New (p_demux, 1); if (tick == NULL) break; tick->p_buffer[0] = 0xF9; tick->i_dts = tick->i_pts = VLC_TS_0 + cur_tick++ * 10000; es_out_Send (p_demux->out, p_sys->es, tick); } p_sys->pulse = next_pulse; return 1; }
/***************************************************************************** * SendPacket: send an ogg packet to the stream output. *****************************************************************************/ static block_t *SendPacket( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; /* Date management */ p_block->i_dts = p_block->i_pts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, p_sys->p_header->frame_size ) - p_block->i_pts; return p_block; }
/***************************************************************************** * GetSoutBuffer: *****************************************************************************/ static block_t *GetSoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = block_New( p_dec, p_sys->frame.i_size ); if( p_block ) { 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_sys->frame.i_samples ) - p_block->i_pts; } return p_block; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with whole samples (see nBlockAlign). ****************************************************************************/ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; if( pp_block == NULL ) return NULL; block_t *p_block = *pp_block; if( p_block == NULL ) return NULL; *pp_block = NULL; if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->end_date ) ) { date_Set( &p_sys->end_date, p_block->i_pts ); } else if( !date_Get( &p_sys->end_date ) ) /* We've just started the stream, wait for the first PTS. */ goto skip; unsigned samples = (8 * p_block->i_buffer) / p_sys->framebits; if( samples == 0 ) goto skip; if( p_sys->decode != NULL ) { block_t *p_out = decoder_NewAudioBuffer( p_dec, samples ); if( p_out == NULL ) goto skip; p_sys->decode( p_out->p_buffer, p_block->p_buffer, samples * p_dec->fmt_in.audio.i_channels ); block_Release( p_block ); p_block = p_out; } else { decoder_UpdateAudioFormat( p_dec ); p_block->i_nb_samples = samples; p_block->i_buffer = samples * (p_sys->framebits / 8); } p_block->i_pts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, samples ) - p_block->i_pts; return p_block; skip: block_Release( p_block ); return NULL; }
/***************************************************************************** * GetAoutBuffer: *****************************************************************************/ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; aout_buffer_t *p_buf = decoder_NewAudioBuffer( p_dec, p_sys->frame.i_samples ); if( p_buf ) { p_buf->i_pts = date_Get( &p_sys->end_date ); p_buf->i_length = date_Increment( &p_sys->end_date, p_sys->frame.i_samples ) - p_buf->i_pts; } return p_buf; }
/***************************************************************************** * GetSoutBuffer: *****************************************************************************/ static block_t *GetSoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; p_block = block_Alloc( p_sys->i_frame_size ); if( p_block == NULL ) return NULL; 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_sys->i_frame_length ) - p_block->i_pts; return p_block; }
/***************************************************************************** * aout_DecPlay : filter & mix the decoded buffer *****************************************************************************/ int aout_DecPlay (audio_output_t *p_aout, block_t *p_buffer, int i_input_rate) { aout_owner_t *owner = aout_owner (p_aout); aout_input_t *input; assert( i_input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE && i_input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE ); assert( p_buffer->i_pts > 0 ); p_buffer->i_length = (mtime_t)p_buffer->i_nb_samples * 1000000 / owner->input_format.i_rate; aout_lock( p_aout ); aout_CheckRestart( p_aout ); input = owner->input; if (unlikely(input == NULL)) /* can happen due to restart */ { aout_unlock( p_aout ); aout_BufferFree( p_buffer ); return -1; } /* Input */ p_buffer = aout_InputPlay (p_aout, input, p_buffer, i_input_rate, &owner->sync.date); if( p_buffer != NULL ) { date_Increment (&owner->sync.date, p_buffer->i_nb_samples); /* Mixer */ if (owner->volume.mixer != NULL) { float amp = owner->volume.multiplier * vlc_atomic_getf (&owner->gain.multiplier); aout_MixerRun (owner->volume.mixer, p_buffer, amp); } /* Output */ aout_OutputPlay( p_aout, p_buffer ); } aout_unlock( p_aout ); #ifdef __unix__ sched_yield(); #endif return 0; }
/***************************************************************************** * DecodePacket: decodes a Vorbis packet. *****************************************************************************/ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_samples; INTERLEAVE_TYPE **pp_pcm; if( p_oggpacket->bytes && vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 ) vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb ); /* **pp_pcm is a multichannel float vector. In stereo, for * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is * the size of each channel. Convert the float values * (-1.<=range<=1.) to whatever PCM format and write it out */ if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 ) { block_t *p_aout_buffer; if( decoder_UpdateAudioFormat( p_dec ) ) return NULL; p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_samples ); if( p_aout_buffer == NULL ) return NULL; /* Interleave the samples */ Interleave( (INTERLEAVE_TYPE*)p_aout_buffer->p_buffer, (const INTERLEAVE_TYPE**)pp_pcm, p_sys->vi.channels, i_samples, p_sys->pi_chan_table); /* Tell libvorbis how many samples we actually consumed */ vorbis_synthesis_read( &p_sys->vd, i_samples ); /* Date management */ p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, i_samples ) - p_aout_buffer->i_pts; return p_aout_buffer; } else { return NULL; } }
/***************************************************************************** * Demux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size ); if( p_block == NULL ) return VLC_DEMUXER_EOF; p_block->i_dts = p_block->i_pts = date_Get( &p_sys->pts ); es_out_SetPCR( p_demux->out, p_block->i_pts ); es_out_Send( p_demux->out, p_sys->p_es, p_block ); date_Increment( &p_sys->pts, p_sys->i_frame_samples ); return VLC_DEMUXER_SUCCESS; }
/***************************************************************************** * SendPacket: send an ogg dated packet to the stream output. *****************************************************************************/ static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_block_size, i_samples; i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket ); if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */ i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2; p_sys->i_last_block_size = i_block_size; /* Date management */ p_block->i_dts = p_block->i_pts = date_Get( &p_sys->end_date ); p_block->i_length = date_Increment( &p_sys->end_date, i_samples ) - p_block->i_pts; return p_block; }
/***************************************************************************** * aout_FifoPush : push a packet into the FIFO *****************************************************************************/ void aout_FifoPush( aout_fifo_t * p_fifo, aout_buffer_t * p_buffer ) { *p_fifo->pp_last = p_buffer; p_fifo->pp_last = &p_buffer->p_next; *p_fifo->pp_last = NULL; /* Enforce the continuity of the stream. */ if ( date_Get( &p_fifo->end_date ) ) { p_buffer->i_pts = date_Get( &p_fifo->end_date ); p_buffer->i_length = date_Increment( &p_fifo->end_date, p_buffer->i_nb_samples ); p_buffer->i_length -= p_buffer->i_pts; } else { date_Set( &p_fifo->end_date, p_buffer->i_pts + p_buffer->i_length ); } }
static int Demux(demux_t *demux) { demux_sys_t *sys = demux->p_sys; if (!sys->data) return 0; mtime_t deadline; const mtime_t pts_first = sys->pts_origin + date_Get(&sys->pts); if (sys->pts_next > VLC_TS_INVALID) { deadline = sys->pts_next; } else if (sys->is_realtime) { deadline = mdate(); const mtime_t max_wait = CLOCK_FREQ / 50; if (deadline + max_wait < pts_first) { es_out_Control(demux->out, ES_OUT_SET_PCR, deadline); /* That's ugly, but not yet easily fixable */ mwait(deadline + max_wait); return 1; } } else { deadline = 1 + pts_first; } for (;;) { const mtime_t pts = sys->pts_origin + date_Get(&sys->pts); if (sys->duration >= 0 && pts >= sys->pts_origin + sys->duration) return 0; if (pts >= deadline) return 1; block_t *data = block_Duplicate(sys->data); if (!data) return -1; data->i_dts = data->i_pts = VLC_TS_0 + pts; es_out_Control(demux->out, ES_OUT_SET_PCR, data->i_pts); es_out_Send(demux->out, sys->es, data); date_Increment(&sys->pts, 1); } }
/***************************************************************************** * DecodeFrame: decodes a video frame. *****************************************************************************/ static int DecodeFrame( decoder_t *p_dec, block_t *p_block ) { if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; p_block = DecodeBlock( p_dec, p_block ); if( p_block == NULL ) return VLCDEC_SUCCESS; decoder_sys_t *p_sys = p_dec->p_sys; /* Get a new picture */ picture_t *p_pic = NULL; if( !decoder_UpdateVideoFormat( p_dec ) ) p_pic = decoder_NewPicture( p_dec ); if( p_pic == NULL ) { block_Release( p_block ); return VLCDEC_SUCCESS; } FillPicture( p_dec, p_block, p_pic ); /* Date management: 1 frame per packet */ p_pic->date = date_Get( &p_dec->p_sys->pts ); date_Increment( &p_sys->pts, 1 ); if( p_block->i_flags & BLOCK_FLAG_INTERLACED_MASK ) { p_pic->b_progressive = false; p_pic->i_nb_fields = (p_block->i_flags & BLOCK_FLAG_SINGLE_FIELD) ? 1 : 2; if( p_block->i_flags & BLOCK_FLAG_TOP_FIELD_FIRST ) p_pic->b_top_field_first = true; else p_pic->b_top_field_first = false; } else p_pic->b_progressive = true; block_Release( p_block ); decoder_QueueVideo( p_dec, p_pic ); return VLCDEC_SUCCESS; }
/***************************************************************************** * GetAoutBuffer: *****************************************************************************/ static block_t *GetAoutBuffer( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_buf; /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time * (plus a few header bytes) */ p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 ); if( p_buf == NULL ) return NULL; p_buf->i_nb_samples = p_sys->i_frame_length; p_buf->i_buffer = p_sys->i_frame_size; p_buf->i_pts = date_Get( &p_sys->end_date ); p_buf->i_length = date_Increment( &p_sys->end_date, p_sys->i_frame_length ) - p_buf->i_pts; return p_buf; }
/***************************************************************************** * Demux: read packet and send them to decoders ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; p_block = stream_Block( p_demux->s, CDG_FRAME_SIZE ); if( p_block == NULL ) { msg_Dbg( p_demux, "cannot read data, eof" ); return 0; } p_block->i_dts = p_block->i_pts = date_Increment( &p_sys->pts, 1 ); es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts ); es_out_Send( p_demux->out, p_sys->p_es, p_block ); return 1; }