int smv_eof;
int audio_eof;
int ignore_length;
+ int max_size;
int spdif;
- int smv_cur_pt;
int smv_given_first;
int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
int rifx; // RIFX: integer byte order for parameters is big endian
static void handle_stream_probing(AVStream *st)
{
if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
- st->request_probe = AVPROBE_SCORE_EXTENSION;
+ st->internal->request_probe = AVPROBE_SCORE_EXTENSION;
st->probe_packets = FFMIN(st->probe_packets, 32);
}
}
return AVERROR_INVALIDDATA;
}
AV_WL32(vst->codecpar->extradata, wav->smv_frames_per_jpeg);
- wav->smv_cur_pt = 0;
goto break_loop;
case MKTAG('L', 'I', 'S', 'T'):
+ case MKTAG('l', 'i', 's', 't'):
if (size < 4) {
av_log(s, AV_LOG_ERROR, "too short LIST tag\n");
return AVERROR_INVALIDDATA;
switch (avio_rl32(pb)) {
case MKTAG('I', 'N', 'F', 'O'):
ff_read_riff_info(s, size - 4);
+ break;
+ case MKTAG('a', 'd', 't', 'l'):
+ if (s->nb_chapters > 0) {
+ while (avio_tell(pb) < next_tag_ofs &&
+ !avio_feof(pb)) {
+ char cue_label[512];
+ unsigned id, sub_size;
+
+ if (avio_rl32(pb) != MKTAG('l', 'a', 'b', 'l'))
+ break;
+
+ sub_size = avio_rl32(pb);
+ if (sub_size < 5)
+ break;
+ id = avio_rl32(pb);
+ avio_get_str(pb, sub_size - 4, cue_label, sizeof(cue_label));
+ avio_skip(pb, avio_tell(pb) & 1);
+
+ for (int i = 0; i < s->nb_chapters; i++) {
+ if (s->chapters[i]->id == id) {
+ av_dict_set(&s->chapters[i]->metadata, "title", cue_label, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
}
break;
case MKTAG('I', 'D', '3', ' '):
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
}
break;
+ case MKTAG('c', 'u', 'e', ' '):
+ if (size >= 4 && got_fmt && st->codecpar->sample_rate > 0) {
+ AVRational tb = {1, st->codecpar->sample_rate};
+ unsigned nb_cues = avio_rl32(pb);
+
+ if (size >= nb_cues * 24LL + 4LL) {
+ for (int i = 0; i < nb_cues; i++) {
+ unsigned offset, id = avio_rl32(pb);
+
+ if (avio_feof(pb))
+ return AVERROR_INVALIDDATA;
+
+ avio_skip(pb, 16);
+ offset = avio_rl32(pb);
+
+ if (!avpriv_new_chapter(s, id, tb, offset, AV_NOPTS_VALUE, NULL))
+ return AVERROR(ENOMEM);
+ }
+ }
+ }
+ break;
}
/* seek to next tag unless we know that we'll run into EOF */
} else if (st->codecpar->codec_id == AV_CODEC_ID_XMA1 ||
st->codecpar->codec_id == AV_CODEC_ID_XMA2) {
st->codecpar->block_align = 2048;
- } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->channels > 2) {
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->channels > 2 &&
+ st->codecpar->block_align < INT_MAX / st->codecpar->channels) {
st->codecpar->block_align *= st->codecpar->channels;
}
while (!avio_feof(pb)) {
avio_read(pb, guid, 16);
size = avio_rl64(pb);
- if (size <= 24)
+ if (size <= 24 || size > INT64_MAX - 8)
return AVERROR_INVALIDDATA;
if (!memcmp(guid, guid1, 16))
return size;
return AVERROR_EOF;
}
-#define MAX_SIZE 4096
-
static int wav_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, size;
if (ret < 0)
goto smv_out;
pkt->pos -= 3;
- pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt;
- wav->smv_cur_pt++;
- if (wav->smv_frames_per_jpeg > 0)
- wav->smv_cur_pt %= wav->smv_frames_per_jpeg;
- if (!wav->smv_cur_pt)
- wav->smv_block++;
+ pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
+ pkt->duration = wav->smv_frames_per_jpeg;
+ wav->smv_block++;
pkt->stream_index = 1;
smv_out:
wav->data_end = avio_tell(s->pb) + left;
}
- size = MAX_SIZE;
+ size = wav->max_size;
if (st->codecpar->block_align > 1) {
if (size < st->codecpar->block_align)
size = st->codecpar->block_align;
timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
if (wav->smv_frames_per_jpeg > 0) {
wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
- wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg;
}
}
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption demux_options[] = {
{ "ignore_length", "Ignore length", OFFSET(ignore_length), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC },
+ { "max_size", "max size of single packet", OFFSET(max_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 1024, 1 << 22, DEC },
{ NULL },
};
} else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) {
int64_t start, end, cur;
uint32_t count, chunk_size, i;
+ int64_t filesize = avio_size(s->pb);
start = avio_tell(pb);
end = start + FFALIGN(size, INT64_C(8)) - 24;
chunk_key[4] = 0;
avio_read(pb, chunk_key, 4);
chunk_size = avio_rl32(pb);
- if (chunk_size == UINT32_MAX)
+ if (chunk_size == UINT32_MAX || (filesize >= 0 && chunk_size > filesize))
return AVERROR_INVALIDDATA;
- value = av_mallocz(chunk_size + 1);
+ value = av_malloc(chunk_size + 1);
if (!value)
return AVERROR(ENOMEM);
ret = avio_get_str16le(pb, chunk_size, value, chunk_size);
+ if (ret < 0) {
+ av_free(value);
+ return ret;
+ }
avio_skip(pb, chunk_size - ret);
av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL);
return 0;
}
+#define OFFSET(x) offsetof(WAVDemuxContext, x)
+#define DEC AV_OPT_FLAG_DECODING_PARAM
+static const AVOption w64_demux_options[] = {
+ { "max_size", "max size of single packet", OFFSET(max_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 1024, 1 << 22, DEC },
+ { NULL }
+};
+
+static const AVClass w64_demuxer_class = {
+ .class_name = "W64 demuxer",
+ .item_name = av_default_item_name,
+ .option = w64_demux_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVInputFormat ff_w64_demuxer = {
.name = "w64",
.long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"),
.read_seek = wav_read_seek,
.flags = AVFMT_GENERIC_INDEX,
.codec_tag = (const AVCodecTag * const []) { ff_codec_wav_tags, 0 },
+ .priv_class = &w64_demuxer_class,
};
#endif /* CONFIG_W64_DEMUXER */