@ -45,6 +45,13 @@ typedef struct {
int last_duration ;
int last_duration ;
int w64 ;
int w64 ;
int write_bext ;
int write_bext ;
int64_t smv_data_ofs ;
int smv_block_size ;
int smv_frames_per_jpeg ;
int smv_block ;
int smv_last_stream ;
int smv_eof ;
int audio_eof ;
} WAVContext ;
} WAVContext ;
# if CONFIG_WAV_MUXER
# if CONFIG_WAV_MUXER
@ -392,6 +399,8 @@ static int wav_read_header(AVFormatContext *s,
int ret , got_fmt = 0 ;
int ret , got_fmt = 0 ;
int64_t next_tag_ofs , data_ofs = - 1 ;
int64_t next_tag_ofs , data_ofs = - 1 ;
wav - > smv_data_ofs = - 1 ;
/* check RIFF header */
/* check RIFF header */
tag = avio_rl32 ( pb ) ;
tag = avio_rl32 ( pb ) ;
@ -423,6 +432,7 @@ static int wav_read_header(AVFormatContext *s,
}
}
for ( ; ; ) {
for ( ; ; ) {
AVStream * vst ;
size = next_tag ( pb , & tag ) ;
size = next_tag ( pb , & tag ) ;
next_tag_ofs = avio_tell ( pb ) + size ;
next_tag_ofs = avio_tell ( pb ) + size ;
@ -468,6 +478,31 @@ static int wav_read_header(AVFormatContext *s,
if ( ( ret = wav_parse_bext_tag ( s , size ) ) < 0 )
if ( ( ret = wav_parse_bext_tag ( s , size ) ) < 0 )
return ret ;
return ret ;
break ;
break ;
case MKTAG ( ' S ' , ' M ' , ' V ' , ' 0 ' ) :
// SMV file, a wav file with video appended.
if ( size ! = MKTAG ( ' 0 ' , ' 2 ' , ' 0 ' , ' 0 ' ) ) {
av_log ( s , AV_LOG_ERROR , " Unknown SMV version found \n " ) ;
goto break_loop ;
}
av_log ( s , AV_LOG_DEBUG , " Found SMV data \n " ) ;
vst = av_new_stream ( s , 1 ) ;
if ( ! vst )
return AVERROR ( ENOMEM ) ;
avio_r8 ( pb ) ;
vst - > codec - > codec_type = AVMEDIA_TYPE_VIDEO ;
vst - > codec - > codec_id = CODEC_ID_MJPEG ;
vst - > codec - > width = avio_rl24 ( pb ) ;
vst - > codec - > height = avio_rl24 ( pb ) ;
size = avio_rl24 ( pb ) ;
wav - > smv_data_ofs = avio_tell ( pb ) + ( size - 5 ) * 3 ;
avio_rl24 ( pb ) ;
wav - > smv_block_size = avio_rl24 ( pb ) ;
av_set_pts_info ( vst , 32 , 1 , avio_rl24 ( pb ) ) ;
vst - > duration = avio_rl24 ( pb ) ;
avio_rl24 ( pb ) ;
avio_rl24 ( pb ) ;
wav - > smv_frames_per_jpeg = avio_rl24 ( pb ) ;
goto break_loop ;
}
}
/* seek to next tag unless we know that we'll run into EOF */
/* seek to next tag unless we know that we'll run into EOF */
@ -527,6 +562,45 @@ static int wav_read_packet(AVFormatContext *s,
AVStream * st ;
AVStream * st ;
WAVContext * wav = s - > priv_data ;
WAVContext * wav = s - > priv_data ;
if ( wav - > smv_data_ofs > 0 ) {
int64_t audio_dts , video_dts ;
smv_retry :
audio_dts = s - > streams [ 0 ] - > cur_dts ;
video_dts = s - > streams [ 1 ] - > cur_dts ;
if ( audio_dts ! = AV_NOPTS_VALUE & & video_dts ! = AV_NOPTS_VALUE ) {
audio_dts = av_rescale_q ( audio_dts , s - > streams [ 0 ] - > time_base , AV_TIME_BASE_Q ) ;
video_dts = av_rescale_q ( video_dts , s - > streams [ 1 ] - > time_base , AV_TIME_BASE_Q ) ;
wav - > smv_last_stream = video_dts > = audio_dts ;
}
wav - > smv_last_stream = ! wav - > smv_last_stream ;
wav - > smv_last_stream | = wav - > audio_eof ;
wav - > smv_last_stream & = ! wav - > smv_eof ;
if ( wav - > smv_last_stream ) {
uint64_t old_pos = avio_tell ( s - > pb ) ;
uint64_t new_pos = wav - > smv_data_ofs +
wav - > smv_block * wav - > smv_block_size ;
if ( avio_seek ( s - > pb , new_pos , SEEK_SET ) < 0 ) {
ret = AVERROR_EOF ;
goto smv_out ;
}
size = avio_rl24 ( s - > pb ) ;
ret = av_get_packet ( s - > pb , pkt , size ) ;
if ( ret < 0 )
goto smv_out ;
pkt - > pos - = 3 ;
pkt - > pts = wav - > smv_block * wav - > smv_frames_per_jpeg ;
wav - > smv_block + + ;
pkt - > stream_index = 1 ;
smv_out :
avio_seek ( s - > pb , old_pos , SEEK_SET ) ;
if ( ret = = AVERROR_EOF ) {
wav - > smv_eof = 1 ;
goto smv_retry ;
}
return ret ;
}
}
st = s - > streams [ 0 ] ;
st = s - > streams [ 0 ] ;
left = wav - > data_end - avio_tell ( s - > pb ) ;
left = wav - > data_end - avio_tell ( s - > pb ) ;
@ -535,8 +609,12 @@ static int wav_read_packet(AVFormatContext *s,
left = find_guid ( s - > pb , guid_data ) - 24 ;
left = find_guid ( s - > pb , guid_data ) - 24 ;
else
else
left = find_tag ( s - > pb , MKTAG ( ' d ' , ' a ' , ' t ' , ' a ' ) ) ;
left = find_tag ( s - > pb , MKTAG ( ' d ' , ' a ' , ' t ' , ' a ' ) ) ;
if ( left < 0 )
if ( left < 0 ) {
wav - > audio_eof = 1 ;
if ( wav - > smv_data_ofs > 0 & & ! wav - > smv_eof )
goto smv_retry ;
return AVERROR_EOF ;
return AVERROR_EOF ;
}
wav - > data_end = avio_tell ( s - > pb ) + left ;
wav - > data_end = avio_tell ( s - > pb ) + left ;
}
}
@ -558,7 +636,18 @@ static int wav_read_packet(AVFormatContext *s,
static int wav_read_seek ( AVFormatContext * s ,
static int wav_read_seek ( AVFormatContext * s ,
int stream_index , int64_t timestamp , int flags )
int stream_index , int64_t timestamp , int flags )
{
{
WAVContext * wav = s - > priv_data ;
AVStream * st ;
AVStream * st ;
wav - > smv_eof = 0 ;
wav - > audio_eof = 0 ;
if ( wav - > smv_data_ofs > 0 ) {
int64_t smv_timestamp = timestamp ;
if ( stream_index = = 0 )
smv_timestamp = av_rescale_q ( timestamp , s - > streams [ 0 ] - > time_base , s - > streams [ 1 ] - > time_base ) ;
else
timestamp = av_rescale_q ( smv_timestamp , s - > streams [ 1 ] - > time_base , s - > streams [ 0 ] - > time_base ) ;
wav - > smv_block = smv_timestamp / wav - > smv_frames_per_jpeg ;
}
st = s - > streams [ 0 ] ;
st = s - > streams [ 0 ] ;
switch ( st - > codec - > codec_id ) {
switch ( st - > codec - > codec_id ) {