|
|
@@ -45,6 +45,13 @@ typedef struct { |
|
|
|
int last_duration; |
|
|
|
int w64; |
|
|
|
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; |
|
|
|
|
|
|
|
#if CONFIG_WAV_MUXER |
|
|
@@ -392,6 +399,8 @@ static int wav_read_header(AVFormatContext *s, |
|
|
|
int ret, got_fmt = 0; |
|
|
|
int64_t next_tag_ofs, data_ofs = -1; |
|
|
|
|
|
|
|
wav->smv_data_ofs = -1; |
|
|
|
|
|
|
|
/* check RIFF header */ |
|
|
|
tag = avio_rl32(pb); |
|
|
|
|
|
|
@@ -423,6 +432,7 @@ static int wav_read_header(AVFormatContext *s, |
|
|
|
} |
|
|
|
|
|
|
|
for (;;) { |
|
|
|
AVStream *vst; |
|
|
|
size = next_tag(pb, &tag); |
|
|
|
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) |
|
|
|
return ret; |
|
|
|
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 */ |
|
|
@@ -527,6 +562,45 @@ static int wav_read_packet(AVFormatContext *s, |
|
|
|
AVStream *st; |
|
|
|
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]; |
|
|
|
|
|
|
|
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; |
|
|
|
else |
|
|
|
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; |
|
|
|
} |
|
|
|
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, |
|
|
|
int stream_index, int64_t timestamp, int flags) |
|
|
|
{ |
|
|
|
WAVContext *wav = s->priv_data; |
|
|
|
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]; |
|
|
|
switch (st->codec->codec_id) { |
|
|
|