/***************************************************************************** * Demux: *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; AVPacket pkt; block_t *p_frame; vlc_tick_t i_start_time; /* Read a frame */ int i_av_ret = av_read_frame( p_sys->ic, &pkt ); if( i_av_ret ) { /* Avoid EOF if av_read_frame returns AVERROR(EAGAIN) */ if( i_av_ret == AVERROR(EAGAIN) ) return 1; return 0; } if( pkt.stream_index < 0 || (unsigned) pkt.stream_index >= p_sys->i_tracks ) { av_packet_unref( &pkt ); return 1; } struct avformat_track_s *p_track = &p_sys->tracks[pkt.stream_index]; const AVStream *p_stream = p_sys->ic->streams[pkt.stream_index]; if( p_stream->time_base.den <= 0 ) { msg_Warn( p_demux, "Invalid time base for the stream %d", pkt.stream_index ); av_packet_unref( &pkt ); return 1; } if( p_stream->codecpar->codec_id == AV_CODEC_ID_SSA ) { p_frame = BuildSsaFrame( &pkt, p_sys->i_ssa_order++ ); if( !p_frame ) { av_packet_unref( &pkt ); return 1; } } else if( p_stream->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE ) { if( ( p_frame = block_Alloc( pkt.size + 3 ) ) == NULL ) { av_packet_unref( &pkt ); return 0; } p_frame->p_buffer[0] = 0x20; p_frame->p_buffer[1] = 0x00; memcpy( &p_frame->p_buffer[2], pkt.data, pkt.size ); p_frame->p_buffer[p_frame->i_buffer - 1] = 0x3f; } else { if( ( p_frame = block_Alloc( pkt.size ) ) == NULL ) { av_packet_unref( &pkt ); return 0; } memcpy( p_frame->p_buffer, pkt.data, pkt.size ); } if( pkt.flags & AV_PKT_FLAG_KEY ) p_frame->i_flags |= BLOCK_FLAG_TYPE_I; /* Used to avoid timestamps overlow */ if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ) { i_start_time = vlc_tick_from_frac(p_sys->ic->start_time, AV_TIME_BASE); } else i_start_time = 0; if( pkt.dts == (int64_t)AV_NOPTS_VALUE ) p_frame->i_dts = VLC_TICK_INVALID; else { p_frame->i_dts = vlc_tick_from_frac( pkt.dts * p_stream->time_base.num, p_stream->time_base.den ) - i_start_time + VLC_TICK_0; } if( pkt.pts == (int64_t)AV_NOPTS_VALUE ) p_frame->i_pts = VLC_TICK_INVALID; else { p_frame->i_pts = vlc_tick_from_frac( pkt.pts * p_stream->time_base.num, p_stream->time_base.den ) - i_start_time + VLC_TICK_0; } if( pkt.duration > 0 && p_frame->i_length <= 0 ) p_frame->i_length = vlc_tick_from_samples(pkt.duration * p_stream->time_base.num, p_stream->time_base.den ); /* Add here notoriously bugged file formats/samples */ if( !strcmp( p_sys->fmt->name, "flv" ) ) { /* FLV and video PTS */ if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt.dts != (int64_t)AV_NOPTS_VALUE && pkt.dts == pkt.pts ) p_frame->i_pts = VLC_TICK_INVALID; /* Handle broken dts/pts increase with AAC. Duration is correct. * sky_the80s_aacplus.flv #8195 */ if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && p_stream->codecpar->codec_id == AV_CODEC_ID_AAC ) { if( p_track->i_pcr != VLC_TICK_INVALID && p_track->i_pcr + p_frame->i_length > p_frame->i_dts ) { p_frame->i_dts = p_frame->i_pts = p_track->i_pcr + p_frame->i_length; } } } #ifdef AVFORMAT_DEBUG msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64, pkt.stream_index, p_frame->i_dts, p_frame->i_pts ); #endif if( p_frame->i_dts != VLC_TICK_INVALID && p_track->p_es != NULL ) p_track->i_pcr = p_frame->i_dts; vlc_tick_t i_ts_max = INT64_MIN; for( unsigned i = 0; i < p_sys->i_tracks; i++ ) { if( p_sys->tracks[i].p_es != NULL ) i_ts_max = __MAX( i_ts_max, p_sys->tracks[i].i_pcr ); } vlc_tick_t i_ts_min = INT64_MAX; for( unsigned i = 0; i < p_sys->i_tracks; i++ ) { if( p_sys->tracks[i].p_es != NULL && p_sys->tracks[i].i_pcr != VLC_TICK_INVALID && p_sys->tracks[i].i_pcr + VLC_TICK_FROM_SEC(10)>= i_ts_max ) i_ts_min = __MIN( i_ts_min, p_sys->tracks[i].i_pcr ); } if( i_ts_min >= p_sys->i_pcr && likely(i_ts_min != INT64_MAX) ) { p_sys->i_pcr = i_ts_min; es_out_SetPCR( p_demux->out, p_sys->i_pcr ); UpdateSeekPoint( p_demux, p_sys->i_pcr ); } if( p_track->p_es != NULL ) es_out_Send( p_demux->out, p_track->p_es, p_frame ); else block_Release( p_frame ); av_packet_unref( &pkt ); return 1; }
/***************************************************************************** * Demux: *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; AVPacket pkt; block_t *p_frame; int64_t i_start_time; /* Read a frame */ int i_av_ret = av_read_frame( p_sys->ic, &pkt ); if( i_av_ret ) { /* Avoid EOF if av_read_frame returns AVERROR(EAGAIN) */ if( i_av_ret == AVERROR(EAGAIN) ) return 1; return 0; } if( pkt.stream_index < 0 || pkt.stream_index >= p_sys->i_tk ) { av_packet_unref( &pkt ); return 1; } const AVStream *p_stream = p_sys->ic->streams[pkt.stream_index]; if( p_stream->time_base.den <= 0 ) { msg_Warn( p_demux, "Invalid time base for the stream %d", pkt.stream_index ); av_packet_unref( &pkt ); return 1; } if( p_stream->codecpar->codec_id == AV_CODEC_ID_SSA ) { p_frame = BuildSsaFrame( &pkt, p_sys->i_ssa_order++ ); if( !p_frame ) { av_packet_unref( &pkt ); return 1; } } else { if( ( p_frame = block_Alloc( pkt.size ) ) == NULL ) { av_packet_unref( &pkt ); return 0; } memcpy( p_frame->p_buffer, pkt.data, pkt.size ); } if( pkt.flags & AV_PKT_FLAG_KEY ) p_frame->i_flags |= BLOCK_FLAG_TYPE_I; /* Used to avoid timestamps overlow */ lldiv_t q; if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ) { q = lldiv( p_sys->ic->start_time, AV_TIME_BASE); i_start_time = q.quot * CLOCK_FREQ + q.rem * CLOCK_FREQ / AV_TIME_BASE; } else i_start_time = 0; if( pkt.dts == (int64_t)AV_NOPTS_VALUE ) p_frame->i_dts = VLC_TS_INVALID; else { q = lldiv( pkt.dts, p_stream->time_base.den ); p_frame->i_dts = q.quot * CLOCK_FREQ * p_stream->time_base.num + q.rem * CLOCK_FREQ * p_stream->time_base.num / p_stream->time_base.den - i_start_time + VLC_TS_0; } if( pkt.pts == (int64_t)AV_NOPTS_VALUE ) p_frame->i_pts = VLC_TS_INVALID; else { q = lldiv( pkt.pts, p_stream->time_base.den ); p_frame->i_pts = q.quot * CLOCK_FREQ * p_stream->time_base.num + q.rem * CLOCK_FREQ * p_stream->time_base.num / p_stream->time_base.den - i_start_time + VLC_TS_0; } if( pkt.duration > 0 && p_frame->i_length <= 0 ) p_frame->i_length = pkt.duration * CLOCK_FREQ * p_stream->time_base.num / p_stream->time_base.den; /* Add here notoriously bugged file formats/samples */ if( !strcmp( p_sys->fmt->name, "flv" ) ) { /* FLV and video PTS */ if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt.dts != (int64_t)AV_NOPTS_VALUE && pkt.dts == pkt.pts ) p_frame->i_pts = VLC_TS_INVALID; /* Handle broken dts/pts increase with AAC. Duration is correct. * sky_the80s_aacplus.flv #8195 */ if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && p_stream->codecpar->codec_id == AV_CODEC_ID_AAC ) { if( p_sys->tk_pcr[pkt.stream_index] != VLC_TS_INVALID && p_sys->tk_pcr[pkt.stream_index] + p_frame->i_length > p_frame->i_dts ) { p_frame->i_dts = p_frame->i_pts = p_sys->tk_pcr[pkt.stream_index] + p_frame->i_length; } } } #ifdef AVFORMAT_DEBUG msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64, pkt.stream_index, p_frame->i_dts, p_frame->i_pts ); #endif if( p_frame->i_dts > VLC_TS_INVALID ) p_sys->tk_pcr[pkt.stream_index] = p_frame->i_dts; int64_t i_ts_max = INT64_MIN; for( int i = 0; i < p_sys->i_tk; i++ ) i_ts_max = __MAX( i_ts_max, p_sys->tk_pcr[i] ); int64_t i_ts_min = INT64_MAX; for( int i = 0; i < p_sys->i_tk; i++ ) { if( p_sys->tk_pcr[i] > VLC_TS_INVALID && p_sys->tk_pcr[i] + 10 * CLOCK_FREQ >= i_ts_max ) i_ts_min = __MIN( i_ts_min, p_sys->tk_pcr[i] ); } if( i_ts_min >= p_sys->i_pcr ) { p_sys->i_pcr = i_ts_min; es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr ); UpdateSeekPoint( p_demux, p_sys->i_pcr ); } if( p_sys->tk[pkt.stream_index] != NULL ) es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame ); else block_Release( p_frame ); av_packet_unref( &pkt ); return 1; }