summaryrefslogtreecommitdiffstats
path: root/libavformat/wav.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/wav.c')
-rw-r--r--libavformat/wav.c112
1 files changed, 101 insertions, 11 deletions
diff --git a/libavformat/wav.c b/libavformat/wav.c
index d809451..bd8c847 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -6,20 +6,20 @@
* RF64 demuxer
* Copyright (c) 2009 Daniel Verkamp
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -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
@@ -237,7 +244,7 @@ static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
int64_t size;
for (;;) {
- if (pb->eof_reached)
+ if (url_feof(pb))
return -1;
size = next_tag(pb, &tag);
if (tag == tag1)
@@ -387,11 +394,13 @@ static int wav_read_header(AVFormatContext *s,
int rf64;
unsigned int tag;
AVIOContext *pb = s->pb;
- AVStream *st;
+ AVStream *st = NULL;
WAVContext *wav = s->priv_data;
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);
@@ -407,7 +416,7 @@ static int wav_read_header(AVFormatContext *s,
if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
return -1;
size = avio_rl32(pb);
- if (size < 16)
+ if (size < 24)
return -1;
avio_rl64(pb); /* RIFF size */
data_size = avio_rl64(pb);
@@ -418,14 +427,16 @@ static int wav_read_header(AVFormatContext *s,
data_size, sample_count);
return AVERROR_INVALIDDATA;
}
- avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
+ avio_skip(pb, size - 24); /* skip rest of ds64 chunk */
+
}
for (;;) {
+ AVStream *vst;
size = next_tag(pb, &tag);
next_tag_ofs = avio_tell(pb) + size;
- if (pb->eof_reached)
+ if (url_feof(pb))
break;
switch (tag) {
@@ -467,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 */
@@ -501,7 +537,7 @@ static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16])
uint8_t guid[16];
int64_t size;
- while (!pb->eof_reached) {
+ while (!url_feof(pb)) {
avio_read(pb, guid, 16);
size = avio_rl64(pb);
if (size <= 24)
@@ -526,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);
@@ -534,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;
}
@@ -557,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) {
OpenPOWER on IntegriCloud