/* the packet queue */
AVPacket **packets;
int num_packets;
+ AVPacket *prev_pkt;
int done;
int has_cluster_id;
}
static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska,
- AVPacket *pkt)
+ AVPacket *pkt, uint64_t display_duration)
{
char *line, *layer, *ptr = pkt->data, *end = ptr+pkt->size;
for (; *ptr!=',' && ptr<end-1; ptr++);
layer = ++ptr;
for (; *ptr!=',' && ptr<end-1; ptr++);
if (*ptr == ',') {
- int64_t end_pts = pkt->pts + pkt->convergence_duration;
+ int64_t end_pts = pkt->pts + display_duration;
int sc = matroska->time_scale * pkt->pts / 10000000;
int ec = matroska->time_scale * end_pts / 10000000;
int sh, sm, ss, eh, em, es, len;
len = 50 + end-ptr + FF_INPUT_BUFFER_PADDING_SIZE;
if (!(line = av_malloc(len)))
return;
- snprintf(line,len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s",
+ snprintf(line,len,"Dialogue: %s,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s\r\n",
layer, sh, sm, ss, sc, eh, em, es, ec, ptr);
av_free(pkt->data);
pkt->data = line;
}
}
+static void matroska_merge_packets(AVPacket *out, AVPacket *in)
+{
+ out->data = av_realloc(out->data, out->size+in->size);
+ memcpy(out->data+out->size, in->data, in->size);
+ out->size += in->size;
+ av_destruct_packet(in);
+ av_free(in);
+}
+
static void matroska_convert_tags(AVFormatContext *s, EbmlList *list)
{
MatroskaTag *tags = list->elem;
pkt->pts = timecode;
pkt->pos = pos;
- if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE)
+ if (st->codec->codec_id == CODEC_ID_TEXT)
pkt->convergence_duration = duration;
- else
+ else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE)
pkt->duration = duration;
if (st->codec->codec_id == CODEC_ID_SSA)
- matroska_fix_ass_packet(matroska, pkt);
-
+ matroska_fix_ass_packet(matroska, pkt, duration);
+
+ if (matroska->prev_pkt &&
+ timecode != AV_NOPTS_VALUE &&
+ matroska->prev_pkt->pts == timecode &&
+ matroska->prev_pkt->stream_index == st->index)
+ matroska_merge_packets(matroska->prev_pkt, pkt);
+ else {
dynarray_add(&matroska->packets, &matroska->num_packets, pkt);
+ matroska->prev_pkt = pkt;
+ }
}
if (timecode != AV_NOPTS_VALUE)
MatroskaBlock *blocks;
int i, res;
offset_t pos = url_ftell(matroska->ctx->pb);
+ matroska->prev_pkt = NULL;
if (matroska->has_cluster_id){
/* For the first cluster we parse, its ID was already read as
part of matroska_read_header(), so don't read it again */
AVStream *st = s->streams[stream_index];
int i, index, index_sub, index_min;
- if (timestamp < 0)
- timestamp = 0;
+ if (!st->nb_index_entries)
+ return 0;
+ timestamp = FFMAX(timestamp, st->index_entries[0].timestamp);
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
- if (st->nb_index_entries)
- url_fseek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET);
+ url_fseek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET);
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
matroska_clear_queue(matroska);
if (matroska_parse_cluster(matroska) < 0)