summaryrefslogtreecommitdiff
path: root/libavformat/microdvddec.c
diff options
context:
space:
mode:
authorClément Bœsch <ubitux@gmail.com>2012-05-26 22:37:02 +0200
committerClément Bœsch <ubitux@gmail.com>2012-05-29 21:33:28 +0200
commit2d52ee8a1a4f9438df90f3c95a6fbfc8f6e812f3 (patch)
tree13f4a32e21cffcaa53526d5f5f5dc420028d3aeb /libavformat/microdvddec.c
parentd51e08bb89f7a93f471bc14ad00c14ac986cfcf0 (diff)
downloadffmpeg-2d52ee8a1a4f9438df90f3c95a6fbfc8f6e812f3.tar.gz
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
Diffstat (limited to 'libavformat/microdvddec.c')
-rw-r--r--libavformat/microdvddec.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c
index 4055ee105a..5e37bc38a3 100644
--- a/libavformat/microdvddec.c
+++ b/libavformat/microdvddec.c
@@ -29,6 +29,8 @@
typedef struct {
uint8_t lines[3][MAX_LINESIZE];
int64_t pos[3];
+ AVPacket last_pkt;
+ int last_pkt_ready;
} MicroDVDContext;
@@ -96,7 +98,7 @@ static int get_duration(const char *buf)
if (sscanf(buf, "{%d}{%d}", &frame_start, &frame_end) == 2)
return frame_end - frame_start;
- return 0;
+ return -1;
}
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);
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++) {
if (microdvd->lines[i][0]) {
strcpy(buffer, microdvd->lines[i]);
@@ -118,13 +127,40 @@ static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
if (!len)
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);
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pos = pos;
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);
+ 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;
}