@ -38,6 +38,7 @@
# include <dvdread/ifo_types.h>
# include <dvdread/nav_read.h>
# include "libavcodec/ac3_parser.h"
# include "libavutil/avstring.h"
# include "libavutil/avutil.h"
# include "libavutil/intreadwrite.h"
@ -166,6 +167,7 @@ typedef struct DVDVideoDemuxContext {
int64_t first_pts ; /* the PTS of the first video keyframe */
int play_started ; /* signal that playback has started */
DVDVideoPlaybackState play_state ; /* the active playback state */
int64_t * prev_pts ; /* track the previous PTS emitted per stream */
int64_t pts_offset ; /* PTS discontinuity offset (ex. VOB change) */
int seek_warned ; /* signal that we warned about seeking limits */
int subdemux_reset ; /* signal that subdemuxer should be reset */
@ -1566,7 +1568,7 @@ static int dvdvideo_read_header(AVFormatContext *s)
( ret = dvdvideo_subdemux_open ( s ) ) < 0 )
return ret ;
return 0 ;
goto end_ready ;
}
if ( c - > opt_pgc & & ( c - > opt_chapter_start > 1 | | c - > opt_chapter_end > 0 | | c - > opt_preindex ) ) {
@ -1603,6 +1605,14 @@ static int dvdvideo_read_header(AVFormatContext *s)
( ret = dvdvideo_subdemux_open ( s ) ) < 0 )
return ret ;
end_ready :
c - > prev_pts = av_malloc ( s - > nb_streams * sizeof ( int64_t ) ) ;
if ( ! c - > prev_pts )
return AVERROR ( ENOMEM ) ;
for ( int i = 0 ; i < s - > nb_streams ; i + + )
c - > prev_pts [ i ] = AV_NOPTS_VALUE ;
return 0 ;
}
@ -1614,6 +1624,8 @@ static int dvdvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
int is_key = 0 ;
int st_mapped = 0 ;
AVStream * st_subdemux ;
uint8_t ac3_bitstream_id ;
uint16_t ac3_frame_size ;
ret = av_read_frame ( c - > mpeg_ctx , pkt ) ;
if ( ret < 0 ) {
@ -1661,11 +1673,27 @@ static int dvdvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
if ( pkt - > pts < 0 )
goto discard ;
/* clean up after DVD muxers which end seamless PGs on duplicate or partial AC3 samples */
if ( st_subdemux - > codecpar - > codec_type = = AVMEDIA_TYPE_AUDIO & &
st_subdemux - > codecpar - > codec_id = = AV_CODEC_ID_AC3 ) {
if ( pkt - > pts < = c - > prev_pts [ pkt - > stream_index ] )
goto discard ;
ret = av_ac3_parse_header ( pkt - > buf - > data , pkt - > size ,
& ac3_bitstream_id , & ac3_frame_size ) ;
if ( ret < 0 | | pkt - > size ! = ac3_frame_size )
goto discard ;
}
av_log ( s , AV_LOG_TRACE , " st=%d pts=% " PRId64 " dts=% " PRId64 " "
" pts_offset=% " PRId64 " first_pts=% " PRId64 " \n " ,
pkt - > stream_index , pkt - > pts , pkt - > dts ,
c - > pts_offset , c - > first_pts ) ;
c - > prev_pts [ pkt - > stream_index ] = pkt - > pts ;
return 0 ;
discard :
@ -1673,6 +1701,9 @@ discard:
" Discarding frame @ st=%d pts=% " PRId64 " dts=% " PRId64 " is_key=%d st_mapped=%d \n " ,
st_mapped ? pkt - > stream_index : - 1 , pkt - > pts , pkt - > dts , is_key , st_mapped ) ;
if ( st_mapped )
c - > prev_pts [ pkt - > stream_index ] = pkt - > pts ;
return FFERROR_REDO ;
}
@ -1689,6 +1720,9 @@ static int dvdvideo_close(AVFormatContext *s)
dvdvideo_ifo_close ( s ) ;
if ( c - > prev_pts )
av_freep ( & c - > prev_pts ) ;
return 0 ;
}