X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fsccdec.c;h=5ad21a1f8bb3560df773ec87c3c089b6c61738e1;hb=bc70684e74a185d7b80c8b80bdedda659cb581b8;hp=89d21b9c1fb25a1cc8be842a2d3d41a53c22abf1;hpb=5c1aafff2d844b177b0b20db4a38d8460992558b;p=ffmpeg diff --git a/libavformat/sccdec.c b/libavformat/sccdec.c index 89d21b9c1fb..5ad21a1f8bb 100644 --- a/libavformat/sccdec.c +++ b/libavformat/sccdec.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -29,7 +30,7 @@ typedef struct SCCContext { FFDemuxSubtitlesQueue q; } SCCContext; -static int scc_probe(AVProbeData *p) +static int scc_probe(const AVProbeData *p) { char buf[18]; FFTextReader tr; @@ -62,9 +63,9 @@ static int scc_read_header(AVFormatContext *s) { SCCContext *scc = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); - char line[4096], line2[4096]; - int count = 0, ret = 0; - ptrdiff_t len2, len; + char line2[4096], line[4096]; + int64_t pos, ts, next_ts = AV_NOPTS_VALUE; + ptrdiff_t len; uint8_t out[4096]; FFTextReader tr; @@ -76,74 +77,107 @@ static int scc_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_EIA_608; - while (!ff_text_eof(&tr)) { - const int64_t pos = ff_text_pos(&tr); + while (!ff_text_eof(&tr) || next_ts == AV_NOPTS_VALUE || line2[0]) { char *saveptr = NULL, *lline; - int hh1, mm1, ss1, fs1, i; - int hh2, mm2, ss2, fs2; - int64_t ts_start, ts_end; + int hh, mm, ss, fs, i; AVPacket *sub; - if (count == 0) { + if (next_ts == AV_NOPTS_VALUE) { while (!ff_text_eof(&tr)) { len = ff_subtitles_read_line(&tr, line, sizeof(line)); - if (len > 13) + if (len <= 13) + continue; + if (!strncmp(line, "Scenarist_SCC V1.0", 18)) + continue; + if (av_sscanf(line, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) break; } - } - if (!strncmp(line, "Scenarist_SCC V1.0", 18)) - continue; - if (sscanf(line, "%d:%d:%d%*[:;]%d", &hh1, &mm1, &ss1, &fs1) != 4) - continue; + ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL; - ts_start = (hh1 * 3600LL + mm1 * 60LL + ss1) * 1000LL + fs1 * 33; + while (!ff_text_eof(&tr)) { + len = ff_subtitles_read_line(&tr, line2, sizeof(line2)); + if (len <= 13) + continue; - while (!ff_text_eof(&tr)) { - len2 = ff_subtitles_read_line(&tr, line2, sizeof(line2)); - if (len2 > 13) - break; + if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) + break; + } + } else { + memmove(line, line2, sizeof(line)); + line2[0] = 0; + + while (!ff_text_eof(&tr)) { + len = ff_subtitles_read_line(&tr, line2, sizeof(line2)); + if (len <= 13) + continue; + + if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) + break; + } } - if (sscanf(line2, "%d:%d:%d%*[:;]%d", &hh2, &mm2, &ss2, &fs2) != 4) - continue; - ts_end = (hh2 * 3600LL + mm2 * 60LL + ss2) * 1000LL + fs2 * 33; - count++; + next_ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL; + pos = ff_text_pos(&tr); lline = (char *)&line; lline += 12; for (i = 0; i < 4095; i += 3) { char *ptr = av_strtok(lline, " ", &saveptr); char c1, c2, c3, c4; + uint8_t o1, o2; if (!ptr) break; - if (sscanf(ptr, "%c%c%c%c", &c1, &c2, &c3, &c4) != 4) + if (av_sscanf(ptr, "%c%c%c%c", &c1, &c2, &c3, &c4) != 4) break; + o1 = convert(c2) | (convert(c1) << 4); + o2 = convert(c4) | (convert(c3) << 4); lline = NULL; + + if (i > 12 && o1 == 0x94 && o2 == 0x20 && saveptr && + (av_strncasecmp(saveptr, "942f", 4) && !av_strncasecmp(saveptr, "942c", 4))) { + + out[i] = 0; + + sub = ff_subtitles_queue_insert(&scc->q, out, i, 0); + if (!sub) + goto fail; + + sub->pos = pos; + pos += i; + sub->pts = ts; + sub->duration = i * 11; + ts += sub->duration; + i = 0; + } + out[i+0] = 0xfc; - out[i+1] = convert(c2) | (convert(c1) << 4); - out[i+2] = convert(c4) | (convert(c3) << 4); + out[i+1] = o1; + out[i+2] = o2; } + out[i] = 0; sub = ff_subtitles_queue_insert(&scc->q, out, i, 0); if (!sub) - return AVERROR(ENOMEM); + goto fail; sub->pos = pos; - sub->pts = ts_start; - sub->duration = FFMAX(1200, ts_end - ts_start); - memmove(line, line2, sizeof(line)); - FFSWAP(ptrdiff_t, len, len2); + sub->pts = ts; + sub->duration = next_ts - ts; + ts = next_ts; } ff_subtitles_queue_finalize(s, &scc->q); - return ret; + return 0; +fail: + ff_subtitles_queue_clean(&scc->q); + return AVERROR(ENOMEM); } static int scc_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -167,7 +201,7 @@ static int scc_read_close(AVFormatContext *s) return 0; } -AVInputFormat ff_scc_demuxer = { +const AVInputFormat ff_scc_demuxer = { .name = "scc", .long_name = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"), .priv_data_size = sizeof(SCCContext),