mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-14 00:58:38 +02:00
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
This commit is contained in:
parent
d51e08bb89
commit
2d52ee8a1a
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user