static int Control(demux_t *demux, int query, va_list args) { demux_sys_t *sys = demux->p_sys; switch (query) { case DEMUX_CAN_SEEK: *va_arg(args, bool *) = sys->duration >= 0 && !sys->is_realtime; return VLC_SUCCESS; case DEMUX_GET_POSITION: { double *position = va_arg(args, double *); if (sys->duration > 0) *position = date_Get(&sys->pts) / (double)sys->duration; else *position = 0; return VLC_SUCCESS; } case DEMUX_SET_POSITION: { if (sys->duration < 0 || sys->is_realtime) return VLC_EGENERIC; double position = va_arg(args, double); date_Set(&sys->pts, position * sys->duration); return VLC_SUCCESS; } case DEMUX_GET_TIME: { int64_t *time = va_arg(args, int64_t *); *time = sys->pts_origin + date_Get(&sys->pts); return VLC_SUCCESS; } case DEMUX_SET_TIME: { if (sys->duration < 0 || sys->is_realtime) return VLC_EGENERIC; int64_t time = va_arg(args, int64_t); date_Set(&sys->pts, VLC_CLIP(time - sys->pts_origin, 0, sys->duration)); return VLC_SUCCESS; } case DEMUX_SET_NEXT_DEMUX_TIME: { int64_t pts_next = VLC_TS_0 + va_arg(args, int64_t); if (sys->pts_next <= VLC_TS_INVALID) sys->pts_origin = pts_next; sys->pts_next = pts_next; return VLC_SUCCESS; } case DEMUX_GET_LENGTH: { int64_t *length = va_arg(args, int64_t *); *length = __MAX(sys->duration, 0); return VLC_SUCCESS; } case DEMUX_GET_FPS: { double *fps = va_arg(args, double *); *fps = (double)sys->pts.i_divider_num / sys->pts.i_divider_den; return VLC_SUCCESS; } case DEMUX_GET_META: case DEMUX_HAS_UNSUPPORTED_META: case DEMUX_GET_ATTACHMENTS: default: return VLC_EGENERIC; } }
/**************************************************************************** * 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; }
static int Control (demux_t *demux, int query, va_list args) { demux_sys_t *sys = demux->p_sys; switch (query) { case DEMUX_GET_POSITION: *va_arg (args, float *) = 0.f; break; case DEMUX_GET_LENGTH: *va_arg (args, int64_t *) = INT64_C(0); break; case DEMUX_GET_TIME: *va_arg (args, int64_t *) = date_Get (&sys->date); break; case DEMUX_SET_TIME: date_Set (&sys->date, va_arg (args, int64_t)); break; case DEMUX_SET_NEXT_DEMUX_TIME: { const mtime_t pts = va_arg (args, int64_t ); if (sys->next_time == VLC_TS_INVALID) /* first invocation? */ { date_Set (&sys->date, pts); date_Decrement (&sys->date, 1); } sys->next_time = pts; break; } case DEMUX_GET_PTS_DELAY: { int64_t *v = va_arg (args, int64_t *); *v = INT64_C(1000) * var_InheritInteger (demux, "live-caching"); break; } case DEMUX_CAN_PAUSE: case DEMUX_CAN_CONTROL_PACE: case DEMUX_CAN_SEEK: *va_arg (args, bool *) = true; break; default: return VLC_EGENERIC; } return VLC_SUCCESS; }
static int Audio_OnNewBlock(decoder_t *p_dec, block_t *p_block) { decoder_sys_t *p_sys = p_dec->p_sys; if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) { if (DecodeFlush(p_dec) != VLC_SUCCESS) return -1; date_Set(&p_sys->u.audio.i_end_date, VLC_TS_INVALID); return 0; } /* We've just started the stream, wait for the first PTS. */ if (!date_Get(&p_sys->u.audio.i_end_date)) { if (p_block->i_pts <= VLC_TS_INVALID) return 0; date_Set(&p_sys->u.audio.i_end_date, p_block->i_pts); } /* try delayed opening if there is a new extra data */ if (!p_sys->api->b_started) { bool b_delayed_start = false; switch (p_dec->fmt_in.i_codec) { case VLC_CODEC_VORBIS: case VLC_CODEC_MP4A: if (p_dec->fmt_in.i_extra) b_delayed_start = true; default: break; } if (!p_dec->p_sys->u.audio.i_channels && p_dec->fmt_in.audio.i_channels) { p_dec->p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels; b_delayed_start = true; } if (b_delayed_start && !p_dec->p_sys->u.audio.i_channels && p_sys->u.audio.b_need_channels) b_delayed_start = false; if (b_delayed_start && StartMediaCodec(p_dec) != VLC_SUCCESS) return -1; if (!p_sys->api->b_started) return 0; } return 1; }
/***************************************************************************** * 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; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_OPUS ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL ) return VLC_ENOMEM; p_dec->p_sys->b_has_headers = false; date_Set( &p_sys->end_date, 0 ); /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = VLC_CODEC_FL32; p_dec->pf_decode_audio = DecodeBlock; p_dec->pf_packetize = DecodeBlock; p_sys->p_st = NULL; 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; }
/***************************************************************************** * 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; vlc_tick_t i_date; p_block = vlc_stream_Block( p_demux->s, CDG_FRAME_SIZE ); if( p_block == NULL ) { msg_Dbg( p_demux, "cannot read data, eof" ); return VLC_DEMUXER_EOF; } i_date = PosToDate( p_demux ); if( i_date >= date_Get( &p_sys->pts ) + CDG_FRAME_DELTA ) { p_block->i_dts = p_block->i_pts = VLC_TICK_0 + i_date; date_Set( &p_sys->pts, VLC_TICK_0 + i_date ); } else { p_block->i_dts = VLC_TICK_0 + i_date; 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 ); return VLC_DEMUXER_SUCCESS; }
/***************************************************************************** * ProcessPacket: processes a Opus packet. *****************************************************************************/ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; /* Date management */ if( p_block && 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 ); } if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ if( p_block ) block_Release( p_block ); return NULL; } *pp_block = NULL; /* To avoid being fed the same packet again */ if( !p_block ) return NULL; block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket, p_block->i_nb_samples, (int)p_block->i_length ); block_Release( p_block ); return p_aout_buffer; }
/***************************************************************************** * OpenCommon: *****************************************************************************/ static int OpenCommon( vlc_object_t *p_this, bool b_packetizer ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL ) return VLC_ENOMEM; /* Misc init */ p_sys->b_packetizer = b_packetizer; p_sys->i_state = STATE_NOSYNC; date_Set( &p_sys->end_date, 0 ); p_sys->b_dts_hd = false; p_sys->i_pts = VLC_TS_INVALID; block_BytestreamInit( &p_sys->bytestream ); /* Set output properties */ p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_codec = VLC_CODEC_DTS; p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */ /* Set callback */ p_dec->pf_decode_audio = DecodeBlock; p_dec->pf_packetize = DecodeBlock; return VLC_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; mtime_t i_date; mtime_t i_delta; i_delta = INT64_C(1000000) / CDG_FRAME_RATE; p_block = vlc_stream_Block( p_demux->s, CDG_FRAME_SIZE ); if( p_block == NULL ) { msg_Dbg( p_demux, "cannot read data, eof" ); return 0; } i_date = vlc_stream_Tell( p_demux->s ) / CDG_FRAME_SIZE * i_delta; if( i_date >= date_Get( &p_sys->pts ) + i_delta ) { p_block->i_dts = p_block->i_pts = i_date; date_Set( &p_sys->pts, i_date ); } else { p_block->i_dts = i_date; 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 ); return 1; }
/**************************************************************************** * Helpers ****************************************************************************/ static void PacketizeReset( void *p_private, bool b_broken ) { decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; if( b_broken || !p_sys->b_slice ) { DropStoredNAL( p_sys ); p_sys->b_new_sps = false; p_sys->b_new_pps = false; p_sys->p_active_pps = NULL; p_sys->p_active_sps = NULL; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->slice.type = H264_SLICE_TYPE_UNKNOWN; p_sys->b_slice = false; /* POC */ h264_poc_context_init( &p_sys->pocctx ); p_sys->prevdatedpoc.pts = VLC_TS_INVALID; /* From SEI */ p_sys->i_dpb_output_delay = 0; p_sys->i_pic_struct = UINT8_MAX; p_sys->i_recovery_frame_cnt = UINT_MAX; } p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY; p_sys->b_recovered = false; p_sys->i_recoveryfnum = UINT_MAX; date_Set( &p_sys->dts, VLC_TS_INVALID ); }
static int Audio_OnNewBlock(decoder_t *p_dec, block_t *p_block, int *p_flags) { decoder_sys_t *p_sys = p_dec->p_sys; /* We've just started the stream, wait for the first PTS. */ if (!date_Get(&p_sys->u.audio.i_end_date)) { if (p_block->i_pts <= VLC_TS_INVALID) return 0; date_Set(&p_sys->u.audio.i_end_date, p_block->i_pts); } /* try delayed opening if there is a new extra data */ if (!p_sys->api->b_started) { p_dec->p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels; *p_flags |= NEWBLOCK_FLAG_RESTART; /* Don't start if we don't have any csd */ if ((p_sys->i_quirks & OMXCODEC_QUIRKS_NEED_CSD) && !p_dec->fmt_in.i_extra) *p_flags &= ~NEWBLOCK_FLAG_RESTART; /* Don't start if we don't have a valid channels count */ if ((p_sys->i_quirks & OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS) && !p_dec->p_sys->u.audio.i_channels) *p_flags &= ~NEWBLOCK_FLAG_RESTART; } return 1; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with complete frames. ****************************************************************************/ static block_t *DecodeBlock( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) ) { date_Set( &p_sys->pts, p_block->i_dts ); if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) { block_Release( p_block ); return NULL; } } 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->size ) { msg_Warn( p_dec, "invalid frame size (%zu < %zu)", p_block->i_buffer, p_sys->size ); block_Release( p_block ); return NULL; } return p_block; }
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; }
static void PacketizeFlush( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; date_Set( &p_sys->date, VLC_TICK_INVALID ); p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY; packetizer_Flush( &p_sys->packetizer ); }
/** * 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 ); }
/***************************************************************************** * ProcessPacket: processes a Vorbis packet. *****************************************************************************/ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; *pp_block = NULL; /* To avoid being fed the same packet again */ if( !p_block ) return NULL; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) date_Set( &p_sys->end_date, 0 ); if( ( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) != 0 ) { block_Release(p_block); return NULL; } /* Date management */ 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 ); } if( !date_Get( &p_sys->end_date ) ) { /* We've just started the stream, wait for the first PTS. */ if( p_block ) block_Release( p_block ); return NULL; } if( p_sys->b_packetizer ) { return SendPacket( p_dec, p_oggpacket, p_block ); } else { block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket ); if( p_block ) block_Release( p_block ); return p_aout_buffer; } }
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; }
void aout_DecFlush (audio_output_t *aout) { aout_owner_t *owner = aout_owner (aout); aout_lock (aout); date_Set (&owner->sync.date, VLC_TS_INVALID); aout_OutputFlush (aout, false); aout_unlock (aout); }
/***************************************************************************** * Helpers: *****************************************************************************/ static void PacketizeReset( void *p_private, bool b_broken ) { VLC_UNUSED(b_broken); decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; date_Set( &p_sys->date, VLC_TICK_INVALID ); p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY; }
static void PacketizeFlush( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; p_sys->b_discontinuity = true; date_Set( &p_sys->end_date, 0 ); p_sys->i_state = STATE_NOSYNC; block_BytestreamEmpty( &p_sys->bytestream ); }
/**************************************************************************** * 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; }
void aout_DecChangePause (audio_output_t *aout, bool paused, mtime_t date) { aout_owner_t *owner = aout_owner (aout); aout_lock (aout); /* XXX: Should the date be offset by the pause duration instead? */ date_Set (&owner->sync.date, VLC_TS_INVALID); aout_OutputPause (aout, paused, date); aout_unlock (aout); }
/***************************************************************************** * 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 ); date_Set( &p_fifo->end_date, VLC_TS_INVALID ); }
/**************************************************************************** * 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; }
/***************************************************************************** * Flush: *****************************************************************************/ static void Flush( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; date_Set( &p_sys->end_date, 0 ); mpg123_close( p_sys->p_handle ); mpg123_delete( p_sys->p_handle ); p_sys->b_opened = false; MPG123Open( p_dec ); }
static void Flush (decoder_t *p_dec) { decoder_sys_t *p_sys = p_dec->p_sys; date_Set (&p_sys->end_date, VLC_TS_INVALID); //fluid_synth_system_reset (p_sys->synth); fluid_synth_program_reset (p_sys->synth); for (unsigned channel = 0; channel < 16; channel++) for (unsigned note = 0; note < 128; note++) fluid_synth_noteoff (p_sys->synth, channel, note); }
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; }