Commit 2d52ee8a authored by Clément Bœsch's avatar Clément Bœsch

lavf/microdvd: support events lasting to the next one.

Example:

{3350}{}this subtitle...
{3390}{}...continues up to...
{4000}{4500}this one.
{4600}{}and now...
{4800}{}...to the end of the presentation
parent d51e08bb
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
typedef struct { typedef struct {
uint8_t lines[3][MAX_LINESIZE]; uint8_t lines[3][MAX_LINESIZE];
int64_t pos[3]; int64_t pos[3];
AVPacket last_pkt;
int last_pkt_ready;
} MicroDVDContext; } MicroDVDContext;
...@@ -96,7 +98,7 @@ static int get_duration(const char *buf) ...@@ -96,7 +98,7 @@ static int get_duration(const char *buf)
if (sscanf(buf, "{%d}{%d}", &frame_start, &frame_end) == 2) if (sscanf(buf, "{%d}{%d}", &frame_start, &frame_end) == 2)
return frame_end - frame_start; return frame_end - frame_start;
return 0; return -1;
} }
static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
...@@ -106,6 +108,13 @@ static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -106,6 +108,13 @@ static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
int64_t pos = avio_tell(s->pb); int64_t pos = avio_tell(s->pb);
int i, len = 0, res = AVERROR_EOF; int i, len = 0, res = AVERROR_EOF;
// last packet has its duration set but couldn't be raised earlier
if (microdvd->last_pkt_ready) {
*pkt = microdvd->last_pkt;
microdvd->last_pkt_ready = 0;
return 0;
}
for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) { for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) {
if (microdvd->lines[i][0]) { if (microdvd->lines[i][0]) {
strcpy(buffer, microdvd->lines[i]); strcpy(buffer, microdvd->lines[i]);
...@@ -118,13 +127,40 @@ static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -118,13 +127,40 @@ static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
if (!len) if (!len)
len = ff_get_line(s->pb, buffer, sizeof(buffer)); len = ff_get_line(s->pb, buffer, sizeof(buffer));
if (buffer[0] && !(res = av_new_packet(pkt, len))) { if (microdvd->last_pkt.duration == -1 && !buffer[0]) {
// if the previous subtitle line had no duration, last until the end of
// the presentation
microdvd->last_pkt.duration = 0;
*pkt = microdvd->last_pkt;
pkt->duration = -1;
res = 0;
} else if (buffer[0] && !(res = av_new_packet(pkt, len))) {
memcpy(pkt->data, buffer, len); memcpy(pkt->data, buffer, len);
pkt->flags |= AV_PKT_FLAG_KEY; pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pos = pos; pkt->pos = pos;
pkt->pts = pkt->dts = get_pts(buffer); pkt->pts = pkt->dts = get_pts(buffer);
if (pkt->pts != AV_NOPTS_VALUE) // TODO: handle "{}" duration
if (pkt->pts != AV_NOPTS_VALUE) {
pkt->duration = get_duration(buffer); pkt->duration = get_duration(buffer);
if (microdvd->last_pkt.duration == -1) {
// previous packet wasn't raised because it was lacking the
// duration info, so set its duration with the new packet pts
// and raise it
AVPacket tmp_pkt;
tmp_pkt = microdvd->last_pkt;
tmp_pkt.duration = pkt->pts - tmp_pkt.pts;
microdvd->last_pkt = *pkt;
microdvd->last_pkt_ready = pkt->duration != -1;
*pkt = tmp_pkt;
} else if (pkt->duration == -1) {
// no packet without duration queued, and current one is
// lacking the duration info, we need to parse another subtitle
// event.
microdvd->last_pkt = *pkt;
res = AVERROR(EAGAIN);
}
}
} }
return res; return res;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment