|
|
|
@@ -1566,7 +1566,8 @@ static int matroska_read_header(AVFormatContext *s) |
|
|
|
/* Apply some sanity checks. */ |
|
|
|
if (track->type != MATROSKA_TRACK_TYPE_VIDEO && |
|
|
|
track->type != MATROSKA_TRACK_TYPE_AUDIO && |
|
|
|
track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
track->type != MATROSKA_TRACK_TYPE_SUBTITLE && |
|
|
|
track->type != MATROSKA_TRACK_TYPE_METADATA) { |
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
"Unknown or unsupported track type %"PRIu64"\n", |
|
|
|
track->type); |
|
|
|
@@ -1862,6 +1863,16 @@ static int matroska_read_header(AVFormatContext *s) |
|
|
|
st->codec->bits_per_coded_sample = track->audio.bitdepth; |
|
|
|
if (st->codec->codec_id != AV_CODEC_ID_AAC) |
|
|
|
st->need_parsing = AVSTREAM_PARSE_HEADERS; |
|
|
|
} else if (codec_id == AV_CODEC_ID_WEBVTT) { |
|
|
|
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; |
|
|
|
|
|
|
|
if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { |
|
|
|
st->disposition |= AV_DISPOSITION_CAPTIONS; |
|
|
|
} else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { |
|
|
|
st->disposition |= AV_DISPOSITION_DESCRIPTIONS; |
|
|
|
} else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { |
|
|
|
st->disposition |= AV_DISPOSITION_METADATA; |
|
|
|
} |
|
|
|
} else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; |
|
|
|
#if FF_API_ASS_SSA |
|
|
|
@@ -2228,6 +2239,120 @@ fail: |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, |
|
|
|
MatroskaTrack *track, |
|
|
|
AVStream *st, |
|
|
|
uint8_t *data, int data_len, |
|
|
|
uint64_t timecode, |
|
|
|
uint64_t duration, |
|
|
|
int64_t pos) |
|
|
|
{ |
|
|
|
AVPacket *pkt; |
|
|
|
uint8_t *id, *settings, *text, *buf; |
|
|
|
int id_len, settings_len, text_len; |
|
|
|
uint8_t *p, *q; |
|
|
|
int err; |
|
|
|
|
|
|
|
if (data_len <= 0) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
p = data; |
|
|
|
q = data + data_len; |
|
|
|
|
|
|
|
id = p; |
|
|
|
id_len = -1; |
|
|
|
while (p < q) { |
|
|
|
if (*p == '\r' || *p == '\n') { |
|
|
|
id_len = p - id; |
|
|
|
if (*p == '\r') |
|
|
|
p++; |
|
|
|
break; |
|
|
|
} |
|
|
|
p++; |
|
|
|
} |
|
|
|
|
|
|
|
if (p >= q || *p != '\n') |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
p++; |
|
|
|
|
|
|
|
settings = p; |
|
|
|
settings_len = -1; |
|
|
|
while (p < q) { |
|
|
|
if (*p == '\r' || *p == '\n') { |
|
|
|
settings_len = p - settings; |
|
|
|
if (*p == '\r') |
|
|
|
p++; |
|
|
|
break; |
|
|
|
} |
|
|
|
p++; |
|
|
|
} |
|
|
|
|
|
|
|
if (p >= q || *p != '\n') |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
p++; |
|
|
|
|
|
|
|
text = p; |
|
|
|
text_len = q - p; |
|
|
|
while (text_len > 0) { |
|
|
|
const int len = text_len - 1; |
|
|
|
const uint8_t c = p[len]; |
|
|
|
if (c != '\r' && c != '\n') |
|
|
|
break; |
|
|
|
text_len = len; |
|
|
|
} |
|
|
|
|
|
|
|
if (text_len <= 0) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
pkt = av_mallocz(sizeof(*pkt)); |
|
|
|
err = av_new_packet(pkt, text_len); |
|
|
|
if (err < 0) { |
|
|
|
av_free(pkt); |
|
|
|
return AVERROR(err); |
|
|
|
} |
|
|
|
|
|
|
|
memcpy(pkt->data, text, text_len); |
|
|
|
|
|
|
|
if (id_len > 0) { |
|
|
|
buf = av_packet_new_side_data(pkt, |
|
|
|
AV_PKT_DATA_WEBVTT_IDENTIFIER, |
|
|
|
id_len); |
|
|
|
if (buf == NULL) { |
|
|
|
av_free(pkt); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
memcpy(buf, id, id_len); |
|
|
|
} |
|
|
|
|
|
|
|
if (settings_len > 0) { |
|
|
|
buf = av_packet_new_side_data(pkt, |
|
|
|
AV_PKT_DATA_WEBVTT_SETTINGS, |
|
|
|
settings_len); |
|
|
|
if (buf == NULL) { |
|
|
|
av_free(pkt); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
memcpy(buf, settings, settings_len); |
|
|
|
} |
|
|
|
|
|
|
|
// Do we need this for subtitles? |
|
|
|
// pkt->flags = AV_PKT_FLAG_KEY; |
|
|
|
|
|
|
|
pkt->stream_index = st->index; |
|
|
|
pkt->pts = timecode; |
|
|
|
|
|
|
|
// Do we need this for subtitles? |
|
|
|
// pkt->dts = timecode; |
|
|
|
|
|
|
|
pkt->duration = duration; |
|
|
|
pkt->pos = pos; |
|
|
|
|
|
|
|
dynarray_add(&matroska->packets, &matroska->num_packets, pkt); |
|
|
|
matroska->prev_pkt = pkt; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int matroska_parse_frame(MatroskaDemuxContext *matroska, |
|
|
|
MatroskaTrack *track, |
|
|
|
AVStream *st, |
|
|
|
@@ -2456,6 +2581,14 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, |
|
|
|
if (res) |
|
|
|
goto end; |
|
|
|
|
|
|
|
} else if (st->codec->codec_id == AV_CODEC_ID_WEBVTT) { |
|
|
|
res = matroska_parse_webvtt(matroska, track, st, |
|
|
|
data, lace_size[n], |
|
|
|
timecode, lace_duration, |
|
|
|
pos); |
|
|
|
if (res) |
|
|
|
goto end; |
|
|
|
|
|
|
|
} else { |
|
|
|
res = matroska_parse_frame(matroska, track, st, data, lace_size[n], |
|
|
|
timecode, lace_duration, |
|
|
|
|