@ -69,6 +69,8 @@ struct DVDemuxContext {
uint8_t audio_buf [ 4 ] [ 8192 ] ;
int ach ;
int frames ;
int64_t next_pts_video ;
} ;
static inline uint16_t dv_audio_12to16 ( uint16_t sample )
@ -314,8 +316,6 @@ static int dv_extract_video_info(DVDemuxContext *c, const uint8_t *frame)
par = c - > vst - > codecpar ;
avpriv_set_pts_info ( c - > vst , 64 , c - > sys - > time_base . num ,
c - > sys - > time_base . den ) ;
c - > vst - > avg_frame_rate = av_inv_q ( c - > vst - > time_base ) ;
/* finding out SAR is a little bit messy */
@ -360,6 +360,8 @@ static int dv_init_demux(AVFormatContext *s, DVDemuxContext *c)
c - > vst - > codecpar - > bit_rate = 25000000 ;
c - > vst - > start_time = 0 ;
avpriv_set_pts_info ( c - > vst , 64 , 1 , DV_TIMESCALE_VIDEO ) ;
/* Audio streams are added later as they are encountered. */
s - > ctx_flags | = AVFMTCTX_NOHEADER ;
@ -463,7 +465,10 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
pkt - > size = size ;
pkt - > flags | = AV_PKT_FLAG_KEY ;
pkt - > stream_index = c - > vst - > index ;
pkt - > pts = c - > frames ;
pkt - > pts = c - > next_pts_video ;
pkt - > duration = av_rescale_q ( 1 , c - > sys - > time_base , c - > vst - > time_base ) ;
c - > next_pts_video + = pkt - > duration ;
}
c - > frames + + ;
@ -472,28 +477,34 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
}
static int64_t dv_frame_offset ( AVFormatContext * s , DVDemuxContext * c ,
int64_t timestamp , int flags )
int64_t * timestamp )
{
// FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
FFFormatContext * const si = ffformatcontext ( s ) ;
const int frame_size = c - > sys - > frame_size ;
int64_t frame_count = av_rescale_q ( * timestamp , c - > vst - > time_base , c - > sys - > time_base ) ;
int64_t offset ;
int64_t size = avio_size ( s - > pb ) - si - > data_offset ;
int64_t max_offset = ( ( size - 1 ) / frame_size ) * frame_size ;
offset = frame_size * timestamp ;
offset = frame_size * frame_count ;
if ( size > = 0 & & offset > max_offset )
offset = max_offset ;
else if ( offset < 0 )
offset = 0 ;
* timestamp = av_rescale_q ( offset / frame_size , c - > sys - > time_base , c - > vst - > time_base ) ;
return offset + si - > data_offset ;
}
void ff_dv_offset _reset ( DVDemuxContext * c , int64_t frame_offset )
void ff_dv_ts _reset ( DVDemuxContext * c , int64_t ts )
{
c - > frames = frame_offset ;
c - > frames = ! c - > sys ? 0 :
av_rescale_q ( ts , c - > vst - > time_base , c - > sys - > time_base ) ;
c - > next_pts_video = ts ;
c - > audio_pkt [ 0 ] . size = c - > audio_pkt [ 1 ] . size = 0 ;
c - > audio_pkt [ 2 ] . size = c - > audio_pkt [ 3 ] . size = 0 ;
}
@ -618,12 +629,19 @@ static int dv_read_seek(AVFormatContext *s, int stream_index,
{
RawDVContext * r = s - > priv_data ;
DVDemuxContext * c = & r - > dv_demux ;
int64_t offset = dv_frame_offset ( s , c , timestamp , flags ) ;
int64_t offset ;
// seek using the video stream
if ( stream_index ! = c - > vst - > index )
timestamp = av_rescale_q ( timestamp , s - > streams [ stream_index ] - > time_base ,
c - > vst - > time_base ) ;
offset = dv_frame_offset ( s , c , & timestamp ) ;
if ( avio_seek ( s - > pb , offset , SEEK_SET ) < 0 )
return - 1 ;
ff_dv_offset_reset ( c , offset / c - > sys - > frame_size ) ;
ff_dv_ts _reset ( c , timestamp ) ;
return 0 ;
}