* [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1)
@ 2024-03-12 5:59 Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
` (5 more replies)
0 siblings, 6 replies; 30+ messages in thread
From: Marth64 @ 2024-03-12 5:59 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
In this patchset are improvements for Closed Captions. This set overrides
the 3 patches I sent in the past few days, hence the v3 moniker.
Feedback should be addressed. Details about each change is in the commit.
Narrative:
(1) First, fix the MPEG-2 decoder so it does not try to overlap different
CC streams when content has mixed CC formats
(2) Fix invalid ASS tags produced by ccaption_dec, as well as the tests
(3) Fix leading padding produced by ccaption_dec (ignore leading NBSP)
(4) Correct wrong documentation on rcwtenc
(5) Add a RCWT demuxer. Now, one can fully mux/demux extracted
CCs in a bit-exact way from both ffmpeg and ccextractor.
The added benefit is this allows for easy archival of CCs
for later processing.
(6) Fix an unused include in SCC demuxer
FATE tests pass.
There is still more to do, I will slowly work on this.
Thank you,
Signed-off-by: Marth64 <marth64@proxyid.net>
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 11:00 ` Stefano Sabatini
2024-03-28 9:29 ` Anton Khirnov
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags Marth64
` (4 subsequent siblings)
5 siblings, 2 replies; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
In MPEG-2 user data, there can be different types of Closed Captions
formats embedded (A53, SCTE-20, or DVD). The current behavior of the
CC extraction code in the MPEG-2 decoder is to not be aware of
multiple formats if multiple exist, therefore allowing one format
to overwrite the other during the extraction process since the CC
extraction shares one output buffer for the normalized bytes.
This causes sources that have two CC formats to produce flawed output.
There exist real-world samples which contain both A53 and SCTE-20 captions
in the same MPEG-2 stream, and that manifest this problem. Example of symptom:
THANK YOU (expected) --> THTHANANK K YOYOUU (actual)
The solution is to pick only the first CC substream observed with valid bytes,
and ignore the other types. Additionally, provide an option for users
to manually "force" a type in the event that this matters for a particular
source.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavcodec/mpeg12dec.c | 67 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 64 insertions(+), 3 deletions(-)
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 3a2f17e508..8961a290a3 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -62,6 +62,16 @@
#define A53_MAX_CC_COUNT 2000
+enum Mpeg2ClosedCaptionsFormat {
+ CC_FORMAT_AUTO,
+ CC_FORMAT_A53_PART4,
+ CC_FORMAT_SCTE20,
+ CC_FORMAT_DVD
+};
+static const char mpeg2_cc_format_labels[4][12] = {
+ "Unknown", "A/53 Part 4", "SCTE-20", "DVD"
+};
+
typedef struct Mpeg1Context {
MpegEncContext mpeg_enc_ctx;
int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
@@ -70,6 +80,7 @@ typedef struct Mpeg1Context {
AVStereo3D stereo3d;
int has_stereo3d;
AVBufferRef *a53_buf_ref;
+ enum Mpeg2ClosedCaptionsFormat cc_format;
uint8_t afd;
int has_afd;
int slice_count;
@@ -1903,12 +1914,27 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
return 0;
}
+static void mpeg_set_cc_format(AVCodecContext *avctx, enum Mpeg2ClosedCaptionsFormat format)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+
+ av_assert2(format != CC_FORMAT_AUTO);
+
+ if (!s1->cc_format) {
+ s1->cc_format = format;
+
+ av_log(avctx, AV_LOG_DEBUG, "CC: first seen substream is %s format\n",
+ mpeg2_cc_format_labels[format]);
+ }
+}
+
static int mpeg_decode_a53_cc(AVCodecContext *avctx,
const uint8_t *p, int buf_size)
{
Mpeg1Context *s1 = avctx->priv_data;
- if (buf_size >= 6 &&
+ if ((!s1->cc_format || s1->cc_format == CC_FORMAT_A53_PART4) &&
+ buf_size >= 6 &&
p[0] == 'G' && p[1] == 'A' && p[2] == '9' && p[3] == '4' &&
p[4] == 3 && (p[5] & 0x40)) {
/* extract A53 Part 4 CC data */
@@ -1927,9 +1953,11 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
memcpy(s1->a53_buf_ref->data + old_size, p + 7, cc_count * UINT64_C(3));
avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
+ mpeg_set_cc_format(avctx, CC_FORMAT_A53_PART4);
}
return 1;
- } else if (buf_size >= 2 &&
+ } else if ((!s1->cc_format || s1->cc_format == CC_FORMAT_SCTE20) &&
+ buf_size >= 2 &&
p[0] == 0x03 && (p[1]&0x7f) == 0x01) {
/* extract SCTE-20 CC data */
GetBitContext gb;
@@ -1973,10 +2001,13 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
cap += 3;
}
}
+
avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
+ mpeg_set_cc_format(avctx, CC_FORMAT_SCTE20);
}
return 1;
- } else if (buf_size >= 11 &&
+ } else if ((!s1->cc_format || s1->cc_format == CC_FORMAT_DVD) &&
+ buf_size >= 11 &&
p[0] == 'C' && p[1] == 'C' && p[2] == 0x01 && p[3] == 0xf8) {
/* extract DVD CC data
*
@@ -2033,7 +2064,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
p += 6;
}
}
+
avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
+ mpeg_set_cc_format(avctx, CC_FORMAT_DVD);
}
return 1;
}
@@ -2598,11 +2631,39 @@ const FFCodec ff_mpeg1video_decoder = {
},
};
+#define M2V_OFFSET(x) offsetof(Mpeg1Context, x)
+#define M2V_PARAM AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption mpeg2video_options[] = {
+ { "cc_format", "extract a specific Closed Captions format",
+ M2V_OFFSET(cc_format), AV_OPT_TYPE_INT, { .i64 = CC_FORMAT_AUTO },
+ CC_FORMAT_AUTO, CC_FORMAT_DVD, M2V_PARAM, .unit = "cc_format" },
+
+ { "auto", "pick first seen CC substream", 0, AV_OPT_TYPE_CONST,
+ { .i64 = CC_FORMAT_AUTO }, .flags = M2V_PARAM, .unit = "cc_format" },
+ { "a53", "pick A/53 Part 4 CC substream", 0, AV_OPT_TYPE_CONST,
+ { .i64 = CC_FORMAT_A53_PART4 }, .flags = M2V_PARAM, .unit = "cc_format" },
+ { "scte20", "pick SCTE-20 CC substream", 0, AV_OPT_TYPE_CONST,
+ { .i64 = CC_FORMAT_SCTE20 }, .flags = M2V_PARAM, .unit = "cc_format" },
+ { "dvd", "pick DVD CC substream", 0, AV_OPT_TYPE_CONST,
+ { .i64 = CC_FORMAT_DVD }, .flags = M2V_PARAM, .unit = "cc_format" },
+ { NULL }
+};
+
+static const AVClass mpeg2video_class = {
+ .class_name = "MPEG-2 video",
+ .item_name = av_default_item_name,
+ .option = mpeg2video_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_DECODER,
+};
+
const FFCodec ff_mpeg2video_decoder = {
.p.name = "mpeg2video",
CODEC_LONG_NAME("MPEG-2 video"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_MPEG2VIDEO,
+ .p.priv_class = &mpeg2video_class,
.priv_data_size = sizeof(Mpeg1Context),
.init = mpeg_decode_init,
.close = mpeg_decode_end,
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 13:49 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces Marth64
` (3 subsequent siblings)
5 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Closed Captions decoder prints multiple \pos ASS tags per cue,
and preceding the \pos tag is a fixed \an7 that fixes rendering
position from the top left corner and enforces justification.
Printing multiple \an and \pos tags in this way is invalid behavior,
because only the first \pos tag in a cue is honored by ASS anyway.
Don't write multiple \an and \pos tags.
Also, update tests accordingly.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavcodec/ccaption_dec.c | 8 +-
tests/ref/fate/sub-cc | 2 +-
tests/ref/fate/sub-cc-realtime | 8 +-
tests/ref/fate/sub-cc-scte20 | 4 +-
tests/ref/fate/sub-scc | 146 ++++++++++++++++-----------------
5 files changed, 86 insertions(+), 82 deletions(-)
diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index faf058ce97..9d4a93647c 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -456,7 +456,7 @@ static void roll_up(CCaptionSubContext *ctx)
static int capture_screen(CCaptionSubContext *ctx)
{
- int i, j, tab = 0;
+ int i, j, tab = 0, seen_row = 0;
struct Screen *screen = ctx->screen + ctx->active_screen;
enum cc_font prev_font = CCFONT_REGULAR;
enum cc_color_code prev_color = CCCOL_WHITE;
@@ -496,7 +496,11 @@ static int capture_screen(CCaptionSubContext *ctx)
x = ASS_DEFAULT_PLAYRESX * (0.1 + 0.0250 * j);
y = ASS_DEFAULT_PLAYRESY * (0.1 + 0.0533 * i);
- av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y);
+
+ if (!seen_row) {
+ av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y);
+ seen_row = 1;
+ }
for (; j < SCREEN_COLUMNS; j++) {
const char *e_tag = "", *s_tag = "", *c_tag = "", *b_tag = "";
diff --git a/tests/ref/fate/sub-cc b/tests/ref/fate/sub-cc
index f5216b3de2..d4ab974c2f 100644
--- a/tests/ref/fate/sub-cc
+++ b/tests/ref/fate/sub-cc
@@ -13,4 +13,4 @@ Style: Default,Monospace,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,3,1,0,
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.83,0:00:02.97,Default,,0,0,0,,{\an7}{\pos(38,44)}({\i1} inaudible radio chatter{\i0} )
-Dialogue: 0,0:00:02.97,0:00:04.34,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N{\an7}{\pos(38,44)}>> Safety remains our number one
+Dialogue: 0,0:00:02.97,0:00:04.34,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N>> Safety remains our number one
diff --git a/tests/ref/fate/sub-cc-realtime b/tests/ref/fate/sub-cc-realtime
index bda890bfe5..da06307221 100644
--- a/tests/ref/fate/sub-cc-realtime
+++ b/tests/ref/fate/sub-cc-realtime
@@ -16,7 +16,7 @@ Dialogue: 0,0:00:00.97,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,44)}(
Dialogue: 0,0:00:01.17,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,44)}({\i1} inaudibl
Dialogue: 0,0:00:01.37,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,44)}({\i1} inaudible radio chat
Dialogue: 0,0:00:01.57,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,44)}({\i1} inaudible radio chatter{\i0} )
-Dialogue: 0,0:00:03.10,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N{\an7}{\pos(38,44)}>>
-Dialogue: 0,0:00:03.30,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N{\an7}{\pos(38,44)}>> Safety rema
-Dialogue: 0,0:00:03.50,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N{\an7}{\pos(38,44)}>> Safety remains our numb
-Dialogue: 0,0:00:03.70,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N{\an7}{\pos(38,44)}>> Safety remains our number one
+Dialogue: 0,0:00:03.10,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N>>
+Dialogue: 0,0:00:03.30,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N>> Safety rema
+Dialogue: 0,0:00:03.50,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N>> Safety remains our numb
+Dialogue: 0,0:00:03.70,9:59:59.99,Default,,0,0,0,,{\an7}{\pos(38,28)}({\i1} inaudible radio chatter{\i0} )\N>> Safety remains our number one
diff --git a/tests/ref/fate/sub-cc-scte20 b/tests/ref/fate/sub-cc-scte20
index 49715301de..09fa3fb330 100644
--- a/tests/ref/fate/sub-cc-scte20
+++ b/tests/ref/fate/sub-cc-scte20
@@ -13,5 +13,5 @@ Style: Default,Monospace,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,3,1,0,
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:01.44,Default,,0,0,0,,{\an7}{\pos(48,182)}BESIDES THE
-Dialogue: 0,0:00:01.43,0:00:03.93,Default,,0,0,0,,{\an7}{\pos(38,166)}\hBESIDES THE \N{\an7}{\pos(38,197)}SPENDING AND THIS, IS THAT CAR
-Dialogue: 0,0:00:03.94,0:00:06.31,Default,,0,0,0,,{\an7}{\pos(38,182)}SPENDING AND THIS, IS THAT CAR \N{\an7}{\pos(38,197)}MANUFACTURERS ARE ABOUT AS
+Dialogue: 0,0:00:01.43,0:00:03.93,Default,,0,0,0,,{\an7}{\pos(38,166)}\hBESIDES THE \NSPENDING AND THIS, IS THAT CAR
+Dialogue: 0,0:00:03.94,0:00:06.31,Default,,0,0,0,,{\an7}{\pos(38,182)}SPENDING AND THIS, IS THAT CAR \NMANUFACTURERS ARE ABOUT AS
diff --git a/tests/ref/fate/sub-scc b/tests/ref/fate/sub-scc
index a9ff3676be..d29d6ff485 100644
--- a/tests/ref/fate/sub-scc
+++ b/tests/ref/fate/sub-scc
@@ -12,95 +12,95 @@ Style: Default,Monospace,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,3,1,0,
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
-Dialogue: 0,0:00:-2.-47,0:00:00.70,Default,,0,0,0,,{\an7}{\pos(76,228)}WE HAVE FOUND A WITCH !\N{\an7}{\pos(76,243)}MAY WE BURN HER ?
-Dialogue: 0,0:00:00.69,0:00:03.29,Default,,0,0,0,,{\an7}{\pos(115,228)}[ Crowd ]\N{\an7}{\pos(115,243)}BURN HER ! BURN HER !
-Dialogue: 0,0:00:03.30,0:00:07.07,Default,,0,0,0,,{\an7}{\pos(38,197)}HOW DO YOU KNOW\N{\an7}{\pos(38,213)}SHE IS A WITCH ?\N{\an7}{\pos(153,243)}SHE LOOKS LIKE ONE !
-Dialogue: 0,0:00:07.07,0:00:09.27,Default,,0,0,0,,{\an7}{\pos(192,228)}[ Shouting\N{\an7}{\pos(192,243)}\h\hAffirmations ]
+Dialogue: 0,0:00:-2.-47,0:00:00.70,Default,,0,0,0,,{\an7}{\pos(76,228)}WE HAVE FOUND A WITCH !\NMAY WE BURN HER ?
+Dialogue: 0,0:00:00.69,0:00:03.29,Default,,0,0,0,,{\an7}{\pos(115,228)}[ Crowd ]\NBURN HER ! BURN HER !
+Dialogue: 0,0:00:03.30,0:00:07.07,Default,,0,0,0,,{\an7}{\pos(38,197)}HOW DO YOU KNOW\NSHE IS A WITCH ?\NSHE LOOKS LIKE ONE !
+Dialogue: 0,0:00:07.07,0:00:09.27,Default,,0,0,0,,{\an7}{\pos(192,228)}[ Shouting\N\h\hAffirmations ]
Dialogue: 0,0:00:09.26,0:00:11.06,Default,,0,0,0,,{\an7}{\pos(38,243)}BRING HER FORWARD.
-Dialogue: 0,0:00:11.07,0:00:14.27,Default,,0,0,0,,{\an7}{\pos(115,228)}I’M NOT A WITCH.\N{\an7}{\pos(115,243)}\hI’M{\i1} NOT{\i0} A WITCH.
-Dialogue: 0,0:00:14.26,0:00:16.03,Default,,0,0,0,,{\an7}{\pos(38,228)}BUT YOU ARE DRESSED\N{\an7}{\pos(38,243)}AS ONE.
-Dialogue: 0,0:00:16.03,0:00:19.03,Default,,0,0,0,,{\an7}{\pos(76,197)}THEY DRESSED ME UP\N{\an7}{\pos(76,213)}LIKE THIS.\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hNO ! WE DIDN’T !
-Dialogue: 0,0:00:19.03,0:00:22.95,Default,,0,0,0,,{\an7}{\pos(115,228)}AND THIS ISN’T MY NOSE.\N{\an7}{\pos(115,243)}IT’S A FALSE ONE.
-Dialogue: 0,0:00:25.30,0:00:28.43,Default,,0,0,0,,{\an7}{\pos(76,197)}WELL ?\N{\an7}{\pos(76,228)}\h\h\h\h\h\h\h\hWELL, WE DID\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hDO THE NOSE.
-Dialogue: 0,0:00:28.43,0:00:30.07,Default,,0,0,0,,{\an7}{\pos(76,197)}THE NOSE ?\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hAND THE HAT.
-Dialogue: 0,0:00:30.07,0:00:35.50,Default,,0,0,0,,{\an7}{\pos(115,197)}BUT SHE IS A WITCH.\N{\an7}{\pos(115,228)}YEAH ! BURN HER !\N{\an7}{\pos(115,243)}BURN HER ! BURN HER !
-Dialogue: 0,0:00:35.50,0:00:38.47,Default,,0,0,0,,{\an7}{\pos(76,213)}- DID YOU DRESS HER UP\N{\an7}{\pos(76,228)}\h\hLIKE THIS ?\N{\an7}{\pos(76,243)}- NO !
-Dialogue: 0,0:00:38.46,0:00:39.86,Default,,0,0,0,,{\an7}{\pos(192,197)}\h\h\h\h\h\h\h\hNO !\N{\an7}{\pos(192,213)}NO !\N{\an7}{\pos(192,243)}\h\h\h\hNO !
-Dialogue: 0,0:00:39.86,0:00:41.63,Default,,0,0,0,,{\an7}{\pos(153,228)}YES. YES.\N{\an7}{\pos(153,243)}YEAH, A BIT.
-Dialogue: 0,0:00:41.63,0:00:44.83,Default,,0,0,0,,{\an7}{\pos(153,197)}\h\h\h\h\h\h\h\hA BIT.\N{\an7}{\pos(153,213)}\h\h\h\h\h\h\h\h\hA BIT.\N{\an7}{\pos(153,243)}SHE HAS GOT A WART.
-Dialogue: 0,0:00:44.83,0:00:47.04,Default,,0,0,0,,{\an7}{\pos(38,228)}WHAT MAKES YOU THINK\N{\an7}{\pos(38,243)}SHE IS A WITCH ?
-Dialogue: 0,0:00:47.03,0:00:49.53,Default,,0,0,0,,{\an7}{\pos(115,228)}WELL, SHE TURNED ME\N{\an7}{\pos(115,243)}INTO A NEWT !
+Dialogue: 0,0:00:11.07,0:00:14.27,Default,,0,0,0,,{\an7}{\pos(115,228)}I’M NOT A WITCH.\N\hI’M{\i1} NOT{\i0} A WITCH.
+Dialogue: 0,0:00:14.26,0:00:16.03,Default,,0,0,0,,{\an7}{\pos(38,228)}BUT YOU ARE DRESSED\NAS ONE.
+Dialogue: 0,0:00:16.03,0:00:19.03,Default,,0,0,0,,{\an7}{\pos(76,197)}THEY DRESSED ME UP\NLIKE THIS.\N\h\h\h\h\h\h\h\hNO ! WE DIDN’T !
+Dialogue: 0,0:00:19.03,0:00:22.95,Default,,0,0,0,,{\an7}{\pos(115,228)}AND THIS ISN’T MY NOSE.\NIT’S A FALSE ONE.
+Dialogue: 0,0:00:25.30,0:00:28.43,Default,,0,0,0,,{\an7}{\pos(76,197)}WELL ?\N\h\h\h\h\h\h\h\hWELL, WE DID\N\h\h\h\h\h\h\h\hDO THE NOSE.
+Dialogue: 0,0:00:28.43,0:00:30.07,Default,,0,0,0,,{\an7}{\pos(76,197)}THE NOSE ?\N\h\h\h\h\h\h\h\hAND THE HAT.
+Dialogue: 0,0:00:30.07,0:00:35.50,Default,,0,0,0,,{\an7}{\pos(115,197)}BUT SHE IS A WITCH.\NYEAH ! BURN HER !\NBURN HER ! BURN HER !
+Dialogue: 0,0:00:35.50,0:00:38.47,Default,,0,0,0,,{\an7}{\pos(76,213)}- DID YOU DRESS HER UP\N\h\hLIKE THIS ?\N- NO !
+Dialogue: 0,0:00:38.46,0:00:39.86,Default,,0,0,0,,{\an7}{\pos(192,197)}\h\h\h\h\h\h\h\hNO !\NNO !\N\h\h\h\hNO !
+Dialogue: 0,0:00:39.86,0:00:41.63,Default,,0,0,0,,{\an7}{\pos(153,228)}YES. YES.\NYEAH, A BIT.
+Dialogue: 0,0:00:41.63,0:00:44.83,Default,,0,0,0,,{\an7}{\pos(153,197)}\h\h\h\h\h\h\h\hA BIT.\N\h\h\h\h\h\h\h\h\hA BIT.\NSHE HAS GOT A WART.
+Dialogue: 0,0:00:44.83,0:00:47.04,Default,,0,0,0,,{\an7}{\pos(38,228)}WHAT MAKES YOU THINK\NSHE IS A WITCH ?
+Dialogue: 0,0:00:47.03,0:00:49.53,Default,,0,0,0,,{\an7}{\pos(115,228)}WELL, SHE TURNED ME\NINTO A NEWT !
Dialogue: 0,0:00:49.53,0:00:52.30,Default,,0,0,0,,{\an7}{\pos(76,243)}A NEWT ?
Dialogue: 0,0:00:55.46,0:00:57.39,Default,,0,0,0,,{\an7}{\pos(115,243)}I GOT BETTER.
Dialogue: 0,0:00:57.40,0:00:58.90,Default,,0,0,0,,{\an7}{\pos(153,243)}BURN HER ANYWAY !
-Dialogue: 0,0:00:58.89,0:01:01.03,Default,,0,0,0,,{\an7}{\pos(76,197)}BURN HER !\N{\an7}{\pos(76,228)}\h\h\h\h\h\h\h\hBURN HER !\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hCRACKLE, CRACKLE !
-Dialogue: 0,0:01:01.03,0:01:04.00,Default,,0,0,0,,{\an7}{\pos(38,197)}\h\h\h\h[ Shouting\N{\an7}{\pos(38,213)}\h\h\h\h\h\hContinues ]\N{\an7}{\pos(38,243)}QUIET. QUIET.
-Dialogue: 0,0:01:04.00,0:01:05.43,Default,,0,0,0,,{\an7}{\pos(38,228)}QUIET !\N{\an7}{\pos(48,243)}QUIET !
-Dialogue: 0,0:01:05.43,0:01:09.13,Default,,0,0,0,,{\an7}{\pos(38,228)}THERE ARE WAYS OF TELLING\N{\an7}{\pos(38,243)}WHETHER SHE IS A WITCH.
-Dialogue: 0,0:01:09.13,0:01:10.96,Default,,0,0,0,,{\an7}{\pos(38,228)}ARE THERE ?\N{\an7}{\pos(38,243)}WHAT ARE THEY ?
-Dialogue: 0,0:01:10.96,0:01:13.30,Default,,0,0,0,,{\an7}{\pos(38,197)}TELL US !\N{\an7}{\pos(153,213)}TELL US !\N{\an7}{\pos(153,243)}\h\h\h\hDO THEY HURT ?
-Dialogue: 0,0:01:13.30,0:01:16.23,Default,,0,0,0,,{\an7}{\pos(38,228)}TELL ME,\N{\an7}{\pos(38,243)}WHAT DO YOU DO WITH WITCHES ?
-Dialogue: 0,0:01:16.23,0:01:19.20,Default,,0,0,0,,{\an7}{\pos(76,213)}\h\h\h\h\h\h\h\h\h\h\h\hBURN THEM !\N{\an7}{\pos(76,228)}\h\h\h\h\h\h\h\h\h\h\h\h\hBURN THEM UP !\N{\an7}{\pos(76,243)}BURN !
-Dialogue: 0,0:01:19.20,0:01:22.33,Default,,0,0,0,,{\an7}{\pos(38,228)}AND WHAT DO YOU BURN,\N{\an7}{\pos(38,243)}APART FROM WITCHES ?
-Dialogue: 0,0:01:22.33,0:01:24.59,Default,,0,0,0,,{\an7}{\pos(38,197)}MORE WITCHES !\N{\an7}{\pos(153,243)}SHH !
+Dialogue: 0,0:00:58.89,0:01:01.03,Default,,0,0,0,,{\an7}{\pos(76,197)}BURN HER !\N\h\h\h\h\h\h\h\hBURN HER !\N\h\h\h\h\h\h\h\hCRACKLE, CRACKLE !
+Dialogue: 0,0:01:01.03,0:01:04.00,Default,,0,0,0,,{\an7}{\pos(38,197)}\h\h\h\h[ Shouting\N\h\h\h\h\h\hContinues ]\NQUIET. QUIET.
+Dialogue: 0,0:01:04.00,0:01:05.43,Default,,0,0,0,,{\an7}{\pos(38,228)}QUIET !\NQUIET !
+Dialogue: 0,0:01:05.43,0:01:09.13,Default,,0,0,0,,{\an7}{\pos(38,228)}THERE ARE WAYS OF TELLING\NWHETHER SHE IS A WITCH.
+Dialogue: 0,0:01:09.13,0:01:10.96,Default,,0,0,0,,{\an7}{\pos(38,228)}ARE THERE ?\NWHAT ARE THEY ?
+Dialogue: 0,0:01:10.96,0:01:13.30,Default,,0,0,0,,{\an7}{\pos(38,197)}TELL US !\NTELL US !\N\h\h\h\hDO THEY HURT ?
+Dialogue: 0,0:01:13.30,0:01:16.23,Default,,0,0,0,,{\an7}{\pos(38,228)}TELL ME,\NWHAT DO YOU DO WITH WITCHES ?
+Dialogue: 0,0:01:16.23,0:01:19.20,Default,,0,0,0,,{\an7}{\pos(76,213)}\h\h\h\h\h\h\h\h\h\h\h\hBURN THEM !\N\h\h\h\h\h\h\h\h\h\h\h\h\hBURN THEM UP !\NBURN !
+Dialogue: 0,0:01:19.20,0:01:22.33,Default,,0,0,0,,{\an7}{\pos(38,228)}AND WHAT DO YOU BURN,\NAPART FROM WITCHES ?
+Dialogue: 0,0:01:22.33,0:01:24.59,Default,,0,0,0,,{\an7}{\pos(38,197)}MORE WITCHES !\NSHH !
Dialogue: 0,0:01:24.59,0:01:25.62,Default,,0,0,0,,{\an7}{\pos(192,243)}WOOD !
-Dialogue: 0,0:01:25.63,0:01:29.33,Default,,0,0,0,,{\an7}{\pos(38,228)}SO,\N{\an7}{\pos(38,243)}WHY DO WITCHES BURN ?
+Dialogue: 0,0:01:25.63,0:01:29.33,Default,,0,0,0,,{\an7}{\pos(38,228)}SO,\NWHY DO WITCHES BURN ?
Dialogue: 0,0:01:32.69,0:01:35.03,Default,,0,0,0,,{\an7}{\pos(192,243)}B--
-Dialogue: 0,0:01:39.13,0:01:42.46,Default,,0,0,0,,{\an7}{\pos(76,213)}- ’CAUSE THEY’RE\N{\an7}{\pos(76,228)}\h\hMADE OF W-- WOOD ?\N{\an7}{\pos(76,243)}- GOOD !
-Dialogue: 0,0:01:42.46,0:01:44.00,Default,,0,0,0,,{\an7}{\pos(192,213)}OH, YEAH.\N{\an7}{\pos(192,243)}[ Murmuring ]
-Dialogue: 0,0:01:44.00,0:01:48.50,Default,,0,0,0,,{\an7}{\pos(38,213)}SO, HOW DO WE TELL\N{\an7}{\pos(38,228)}WHETHER SHE\N{\an7}{\pos(38,243)}IS MADE OF WOOD ?
-Dialogue: 0,0:01:48.50,0:01:50.10,Default,,0,0,0,,{\an7}{\pos(153,228)}BUILD A BRIDGE\N{\an7}{\pos(153,243)}OUT OF HER !
-Dialogue: 0,0:01:50.10,0:01:54.13,Default,,0,0,0,,{\an7}{\pos(38,228)}AH, BUT CAN YOU NOT ALSO\N{\an7}{\pos(38,243)}MAKE BRIDGES OUT OF STONE ?
-Dialogue: 0,0:01:54.13,0:01:57.26,Default,,0,0,0,,{\an7}{\pos(76,197)}OH, YEAH.\N{\an7}{\pos(76,228)}\h\h\h\h\h\h\h\hOH, YEAH.\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hTRUE. UH--
-Dialogue: 0,0:01:57.26,0:01:59.72,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}DOES WOOD\N{\an7}{\pos(38,243)}SINK IN WATER ?
-Dialogue: 0,0:01:59.73,0:02:02.17,Default,,0,0,0,,{\an7}{\pos(76,197)}NO, NO.\N{\an7}{\pos(76,228)}\h\h\h\h\h\h\h\hNO, IT FLOATS !\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\hIT FLOATS !
-Dialogue: 0,0:02:02.17,0:02:07.04,Default,,0,0,0,,{\an7}{\pos(76,197)}THROW HER INTO THE POND !\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\h[ All Shouting ]
-Dialogue: 0,0:02:07.36,0:02:10.49,Default,,0,0,0,,{\an7}{\pos(38,228)}WHAT ALSO FLOATS\N{\an7}{\pos(38,243)}IN WATER ?
-Dialogue: 0,0:02:10.50,0:02:12.14,Default,,0,0,0,,{\an7}{\pos(76,197)}BREAD !\N{\an7}{\pos(76,243)}\h\h\h\h\h\h\h\h\h\h\h\hAPPLES !
+Dialogue: 0,0:01:39.13,0:01:42.46,Default,,0,0,0,,{\an7}{\pos(76,213)}- ’CAUSE THEY’RE\N\h\hMADE OF W-- WOOD ?\N- GOOD !
+Dialogue: 0,0:01:42.46,0:01:44.00,Default,,0,0,0,,{\an7}{\pos(192,213)}OH, YEAH.\N[ Murmuring ]
+Dialogue: 0,0:01:44.00,0:01:48.50,Default,,0,0,0,,{\an7}{\pos(38,213)}SO, HOW DO WE TELL\NWHETHER SHE\NIS MADE OF WOOD ?
+Dialogue: 0,0:01:48.50,0:01:50.10,Default,,0,0,0,,{\an7}{\pos(153,228)}BUILD A BRIDGE\NOUT OF HER !
+Dialogue: 0,0:01:50.10,0:01:54.13,Default,,0,0,0,,{\an7}{\pos(38,228)}AH, BUT CAN YOU NOT ALSO\NMAKE BRIDGES OUT OF STONE ?
+Dialogue: 0,0:01:54.13,0:01:57.26,Default,,0,0,0,,{\an7}{\pos(76,197)}OH, YEAH.\N\h\h\h\h\h\h\h\hOH, YEAH.\N\h\h\h\h\h\h\h\hTRUE. UH--
+Dialogue: 0,0:01:57.26,0:01:59.72,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}DOES WOOD\NSINK IN WATER ?
+Dialogue: 0,0:01:59.73,0:02:02.17,Default,,0,0,0,,{\an7}{\pos(76,197)}NO, NO.\N\h\h\h\h\h\h\h\hNO, IT FLOATS !\N\h\h\h\h\h\h\h\hIT FLOATS !
+Dialogue: 0,0:02:02.17,0:02:07.04,Default,,0,0,0,,{\an7}{\pos(76,197)}THROW HER INTO THE POND !\N\h\h\h\h\h\h\h\h[ All Shouting ]
+Dialogue: 0,0:02:07.36,0:02:10.49,Default,,0,0,0,,{\an7}{\pos(38,228)}WHAT ALSO FLOATS\NIN WATER ?
+Dialogue: 0,0:02:10.50,0:02:12.14,Default,,0,0,0,,{\an7}{\pos(76,197)}BREAD !\N\h\h\h\h\h\h\h\h\h\h\h\hAPPLES !
Dialogue: 0,0:02:12.13,0:02:13.23,Default,,0,0,0,,{\an7}{\pos(76,243)}UH, VERY SMALL ROCKS.
-Dialogue: 0,0:02:13.23,0:02:16.49,Default,,0,0,0,,{\an7}{\pos(86,228)}{\i1}- CIDER ! CHERRIES !\N{\an7}{\pos(86,243)}{\i0}- UH, GRA-- GRAVY ! MUD !
-Dialogue: 0,0:02:16.50,0:02:18.76,Default,,0,0,0,,{\an7}{\pos(86,228)}- CHURCHES ! CHURCHES !\N{\an7}{\pos(86,243)}{\i1}- LEAD ! LEAD !
-Dialogue: 0,0:02:18.76,0:02:22.30,Default,,0,0,0,,{\an7}{\pos(76,228)}- A DUCK !\N{\an7}{\pos(76,243)}- [ Crowd Gasps, Murmurs ]
+Dialogue: 0,0:02:13.23,0:02:16.49,Default,,0,0,0,,{\an7}{\pos(86,228)}{\i1}- CIDER ! CHERRIES !\N{\i0}- UH, GRA-- GRAVY ! MUD !
+Dialogue: 0,0:02:16.50,0:02:18.76,Default,,0,0,0,,{\an7}{\pos(86,228)}- CHURCHES ! CHURCHES !\N{\i1}- LEAD ! LEAD !
+Dialogue: 0,0:02:18.76,0:02:22.30,Default,,0,0,0,,{\an7}{\pos(76,228)}- A DUCK !\N- [ Crowd Gasps, Murmurs ]
Dialogue: 0,0:02:22.30,0:02:24.63,Default,,0,0,0,,{\an7}{\pos(115,243)}EXACTLY !
Dialogue: 0,0:02:25.36,0:02:27.59,Default,,0,0,0,,{\an7}{\pos(76,243)}SO, LOGICALLY--
Dialogue: 0,0:02:27.59,0:02:29.76,Default,,0,0,0,,{\an7}{\pos(192,243)}IF... SHE...
-Dialogue: 0,0:02:29.76,0:02:33.56,Default,,0,0,0,,{\an7}{\pos(192,213)}WEIGHS...\N{\an7}{\pos(192,228)}THE SAME\N{\an7}{\pos(192,243)}AS A DUCK...
+Dialogue: 0,0:02:29.76,0:02:33.56,Default,,0,0,0,,{\an7}{\pos(192,213)}WEIGHS...\NTHE SAME\NAS A DUCK...
Dialogue: 0,0:02:34.40,0:02:36.50,Default,,0,0,0,,{\an7}{\pos(153,243)}SHE’S MADE OF WOOD !
Dialogue: 0,0:02:36.50,0:02:38.47,Default,,0,0,0,,{\an7}{\pos(38,243)}AND THEREFORE ?
-Dialogue: 0,0:02:39.50,0:02:42.17,Default,,0,0,0,,{\an7}{\pos(38,228)}- A WITCH !\N{\an7}{\pos(38,243)}{\i1}- [ All ] A WITCH ! A WITCH !
+Dialogue: 0,0:02:39.50,0:02:42.17,Default,,0,0,0,,{\an7}{\pos(38,228)}- A WITCH !\N{\i1}- [ All ] A WITCH ! A WITCH !
Dialogue: 0,0:02:42.17,0:02:44.07,Default,,0,0,0,,{\an7}{\pos(76,243)}[ Shouting Continues ]
-Dialogue: 0,0:02:44.07,0:02:45.76,Default,,0,0,0,,{\an7}{\pos(192,213)}HERE’S A DUCK !\N{\an7}{\pos(192,243)}[ Quacking ]
-Dialogue: 0,0:02:45.76,0:02:49.79,Default,,0,0,0,,{\an7}{\pos(76,213)}VERY GOOD.\N{\an7}{\pos(76,228)}WE SHALL USE\N{\an7}{\pos(76,243)}MY LARGEST SCALES.
+Dialogue: 0,0:02:44.07,0:02:45.76,Default,,0,0,0,,{\an7}{\pos(192,213)}HERE’S A DUCK !\N[ Quacking ]
+Dialogue: 0,0:02:45.76,0:02:49.79,Default,,0,0,0,,{\an7}{\pos(76,213)}VERY GOOD.\NWE SHALL USE\NMY LARGEST SCALES.
Dialogue: 0,0:02:49.79,0:02:52.72,Default,,0,0,0,,{\an7}{\pos(76,243)}[ Shouting Continues ]
-Dialogue: 0,0:02:52.73,0:02:55.17,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN !\N{\an7}{\pos(115,243)}\hBURN THE WITCH !
-Dialogue: 0,0:02:55.17,0:02:57.63,Default,,0,0,0,,{\an7}{\pos(153,228)}BURN HER !\N{\an7}{\pos(153,243)}\hBURN THE WITCH !
-Dialogue: 0,0:02:57.63,0:03:01.63,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN HER !\N{\an7}{\pos(115,243)}\hBURN HER ! BURN HER !
-Dialogue: 0,0:03:01.63,0:03:04.14,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN HER !\N{\an7}{\pos(115,243)}\hBURN HER !
-Dialogue: 0,0:03:04.13,0:03:06.59,Default,,0,0,0,,{\an7}{\pos(230,228)}BURN HER !\N{\an7}{\pos(230,243)}\hBURN HER !
+Dialogue: 0,0:02:52.73,0:02:55.17,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN !\N\hBURN THE WITCH !
+Dialogue: 0,0:02:55.17,0:02:57.63,Default,,0,0,0,,{\an7}{\pos(153,228)}BURN HER !\N\hBURN THE WITCH !
+Dialogue: 0,0:02:57.63,0:03:01.63,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN HER !\N\hBURN HER ! BURN HER !
+Dialogue: 0,0:03:01.63,0:03:04.14,Default,,0,0,0,,{\an7}{\pos(115,228)}BURN HER !\N\hBURN HER !
+Dialogue: 0,0:03:04.13,0:03:06.59,Default,,0,0,0,,{\an7}{\pos(230,228)}BURN HER !\N\hBURN HER !
Dialogue: 0,0:03:06.59,0:03:08.00,Default,,0,0,0,,{\an7}{\pos(201,243)}{\i1}[ Man Grunts ]
-Dialogue: 0,0:03:08.00,0:03:14.30,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}RIGHT !\N{\an7}{\pos(38,243)}REMOVE THE SUPPORTS !
-Dialogue: 0,0:03:17.07,0:03:19.17,Default,,0,0,0,,{\an7}{\pos(38,197)}A WITCH !\N{\an7}{\pos(230,243)}A WITCH !
+Dialogue: 0,0:03:08.00,0:03:14.30,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}RIGHT !\NREMOVE THE SUPPORTS !
+Dialogue: 0,0:03:17.07,0:03:19.17,Default,,0,0,0,,{\an7}{\pos(38,197)}A WITCH !\NA WITCH !
Dialogue: 0,0:03:19.17,0:03:20.04,Default,,0,0,0,,{\an7}{\pos(76,243)}IT’S A FAIR COP.
-Dialogue: 0,0:03:20.03,0:03:25.29,Default,,0,0,0,,{\an7}{\pos(38,213)}- BURN HER !\N{\an7}{\pos(38,228)}- [ Crowd Continues Shouting ]\N{\an7}{\pos(57,243)}BURN HER ! BURN HER !
-Dialogue: 0,0:03:28.86,0:03:32.73,Default,,0,0,0,,{\an7}{\pos(38,213)}WHO ARE YOU,\N{\an7}{\pos(38,228)}WHO ARE SO WISE\N{\an7}{\pos(38,243)}IN THE WAYS OF SCIENCE ?
-Dialogue: 0,0:03:32.73,0:03:35.76,Default,,0,0,0,,{\an7}{\pos(153,228)}I AM ARTHUR,\N{\an7}{\pos(153,243)}KING OF THE BRITONS.
+Dialogue: 0,0:03:20.03,0:03:25.29,Default,,0,0,0,,{\an7}{\pos(38,213)}- BURN HER !\N- [ Crowd Continues Shouting ]\NBURN HER ! BURN HER !
+Dialogue: 0,0:03:28.86,0:03:32.73,Default,,0,0,0,,{\an7}{\pos(38,213)}WHO ARE YOU,\NWHO ARE SO WISE\NIN THE WAYS OF SCIENCE ?
+Dialogue: 0,0:03:32.73,0:03:35.76,Default,,0,0,0,,{\an7}{\pos(153,228)}I AM ARTHUR,\NKING OF THE BRITONS.
Dialogue: 0,0:03:35.76,0:03:36.96,Default,,0,0,0,,{\an7}{\pos(76,243)}MY LIEGE !
-Dialogue: 0,0:03:36.96,0:03:40.37,Default,,0,0,0,,{\an7}{\pos(115,213)}GOOD SIR KNIGHT,\N{\an7}{\pos(115,228)}WILL YOU COME WITH ME\N{\an7}{\pos(115,243)}TO CAMELOT...
-Dialogue: 0,0:03:40.36,0:03:43.39,Default,,0,0,0,,{\an7}{\pos(153,228)}AND JOIN US\N{\an7}{\pos(153,243)}AT THE ROUND TABLE ?
-Dialogue: 0,0:03:43.40,0:03:45.53,Default,,0,0,0,,{\an7}{\pos(38,228)}MY LIEGE,\N{\an7}{\pos(38,243)}I WOULD BE HONORED !
-Dialogue: 0,0:03:45.53,0:03:48.70,Default,,0,0,0,,{\an7}{\pos(38,197)}\h\h\h\h\h\h\h\h\h\h\h\hWHAT IS YOUR NAME ?\N{\an7}{\pos(38,243)}BEDEVERE, MY LIEGE.
-Dialogue: 0,0:03:48.69,0:03:52.49,Default,,0,0,0,,{\an7}{\pos(163,228)}THEN I DUB YOU\N{\an7}{\pos(163,243)}{\i1}SIR{\i0} BEDEVERE,
-Dialogue: 0,0:03:52.50,0:03:54.86,Default,,0,0,0,,{\an7}{\pos(153,228)}KNIGHT\N{\an7}{\pos(153,243)}OF THE ROUND TABLE.
-Dialogue: 0,0:03:54.86,0:03:56.76,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}[ Narrator ]\N{\an7}{\pos(38,243)}THE WISE SIR BEDEVERE...
-Dialogue: 0,0:03:56.76,0:03:59.69,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WAS THE FIRST TO JOIN\N{\an7}{\pos(38,243)}KING ARTHUR’S KNIGHTS.
-Dialogue: 0,0:03:59.69,0:04:03.26,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}BUT OTHER ILLUSTRIOUS NAMES\N{\an7}{\pos(38,243)}WERE SOON TO FOLLOW:
+Dialogue: 0,0:03:36.96,0:03:40.37,Default,,0,0,0,,{\an7}{\pos(115,213)}GOOD SIR KNIGHT,\NWILL YOU COME WITH ME\NTO CAMELOT...
+Dialogue: 0,0:03:40.36,0:03:43.39,Default,,0,0,0,,{\an7}{\pos(153,228)}AND JOIN US\NAT THE ROUND TABLE ?
+Dialogue: 0,0:03:43.40,0:03:45.53,Default,,0,0,0,,{\an7}{\pos(38,228)}MY LIEGE,\NI WOULD BE HONORED !
+Dialogue: 0,0:03:45.53,0:03:48.70,Default,,0,0,0,,{\an7}{\pos(38,197)}\h\h\h\h\h\h\h\h\h\h\h\hWHAT IS YOUR NAME ?\NBEDEVERE, MY LIEGE.
+Dialogue: 0,0:03:48.69,0:03:52.49,Default,,0,0,0,,{\an7}{\pos(163,228)}THEN I DUB YOU\N{\i1}SIR{\i0} BEDEVERE,
+Dialogue: 0,0:03:52.50,0:03:54.86,Default,,0,0,0,,{\an7}{\pos(153,228)}KNIGHT\NOF THE ROUND TABLE.
+Dialogue: 0,0:03:54.86,0:03:56.76,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}[ Narrator ]\NTHE WISE SIR BEDEVERE...
+Dialogue: 0,0:03:56.76,0:03:59.69,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WAS THE FIRST TO JOIN\NKING ARTHUR’S KNIGHTS.
+Dialogue: 0,0:03:59.69,0:04:03.26,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}BUT OTHER ILLUSTRIOUS NAMES\NWERE SOON TO FOLLOW:
Dialogue: 0,0:04:03.26,0:04:06.03,Default,,0,0,0,,{\an7}{\pos(38,243)}{\i1}SIR LAUNCELOT THE BRAVE;
Dialogue: 0,0:04:06.03,0:04:07.95,Default,,0,0,0,,{\an7}{\pos(38,243)}{\i1}SIR GALAHAD THE PURE;
-Dialogue: 0,0:04:07.96,0:04:11.27,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}AND SIR ROBIN\N{\an7}{\pos(38,228)}THE NOT-QUITE-SO-BRAVE-\N{\an7}{\pos(38,243)}AS-SIR-LAUNCELOT,
-Dialogue: 0,0:04:11.26,0:04:13.92,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WHO HAD NEARLY FOUGHT\N{\an7}{\pos(38,243)}THE DRAGON OF ANGNOR,
-Dialogue: 0,0:04:13.92,0:04:16.89,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}WHO HAD NEARLY\N{\an7}{\pos(38,228)}STOOD UP TO THE VICIOUS\N{\an7}{\pos(38,243)}CHICKEN OF BRISTOL...
-Dialogue: 0,0:04:16.89,0:04:20.73,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}AND WHO HAD\N{\an7}{\pos(38,228)}PERSONALLY WET HIMSELF\N{\an7}{\pos(38,243)}AT THE BATTLE OF BADON HILL;
-Dialogue: 0,0:04:20.73,0:04:25.43,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}AND THE APTLY NAMED\N{\an7}{\pos(38,243)}SIR NOT-APPEARING-IN-THIS-FILM.
-Dialogue: 0,0:04:25.59,0:04:29.03,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}TOGETHER THEY FORMED A BAND\N{\an7}{\pos(38,243)}WHOSE NAMES AND DEEDS...
-Dialogue: 0,0:04:29.03,0:04:31.72,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WERE TO BE RETOLD\N{\an7}{\pos(38,243)}THROUGHOUT THE CENTURIES.
-Dialogue: 0,0:04:31.73,0:04:33.86,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}THE KNIGHTS\N{\an7}{\pos(38,243)}OF THE ROUND TABLE.
+Dialogue: 0,0:04:07.96,0:04:11.27,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}AND SIR ROBIN\NTHE NOT-QUITE-SO-BRAVE-\NAS-SIR-LAUNCELOT,
+Dialogue: 0,0:04:11.26,0:04:13.92,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WHO HAD NEARLY FOUGHT\NTHE DRAGON OF ANGNOR,
+Dialogue: 0,0:04:13.92,0:04:16.89,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}WHO HAD NEARLY\NSTOOD UP TO THE VICIOUS\NCHICKEN OF BRISTOL...
+Dialogue: 0,0:04:16.89,0:04:20.73,Default,,0,0,0,,{\an7}{\pos(38,213)}{\i1}AND WHO HAD\NPERSONALLY WET HIMSELF\NAT THE BATTLE OF BADON HILL;
+Dialogue: 0,0:04:20.73,0:04:25.43,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}AND THE APTLY NAMED\NSIR NOT-APPEARING-IN-THIS-FILM.
+Dialogue: 0,0:04:25.59,0:04:29.03,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}TOGETHER THEY FORMED A BAND\NWHOSE NAMES AND DEEDS...
+Dialogue: 0,0:04:29.03,0:04:31.72,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}WERE TO BE RETOLD\NTHROUGHOUT THE CENTURIES.
+Dialogue: 0,0:04:31.73,0:04:33.86,Default,,0,0,0,,{\an7}{\pos(38,228)}{\i1}THE KNIGHTS\NOF THE ROUND TABLE.
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 13:50 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation Marth64
` (2 subsequent siblings)
5 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
In Closed Captions (US), the non-breaking space (0xA0) can be used to
align text horizontally from the left when used as a leading character.
However, CC decoder does not ignore it as a leading character
like it does an ordinary space, so a blank padding is rendered
on the black CC box. This is not the intended viewing experience.
Ignore the leading non-breaking spaces, thus creating the intended
transparency which aligns the text. Since all characters are
fixed-width in CC, it can be handled the same way as we currently
treat leading ordinary spaces.
Also, as a nit, lowercase the NBSP's hex code in the entry table to match
casing of the other hex codes.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavcodec/ccaption_dec.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index 9d4a93647c..25b0f2e064 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -91,7 +91,7 @@ enum cc_charset {
ENTRY(0x36, "\u00a3") \
ENTRY(0x37, "\u266a") \
ENTRY(0x38, "\u00e0") \
- ENTRY(0x39, "\u00A0") \
+ ENTRY(0x39, "\u00a0") \
ENTRY(0x3a, "\u00e8") \
ENTRY(0x3b, "\u00e2") \
ENTRY(0x3c, "\u00ea") \
@@ -471,7 +471,8 @@ static int capture_screen(CCaptionSubContext *ctx)
const char *row = screen->characters[i];
const char *charset = screen->charsets[i];
j = 0;
- while (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN)
+ while ((row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN) ||
+ (row[j] == 0x39 && charset[j] == CCSET_SPECIAL_AMERICAN))
j++;
if (!tab || j < tab)
tab = j;
@@ -491,7 +492,9 @@ static int capture_screen(CCaptionSubContext *ctx)
j = 0;
/* skip leading space */
- while (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN && j < tab)
+ while (j < tab &&
+ (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN) ||
+ (row[j] == 0x39 && charset[j] == CCSET_SPECIAL_AMERICAN))
j++;
x = ASS_DEFAULT_PLAYRESX * (0.1 + 0.0250 * j);
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
` (2 preceding siblings ...)
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 13:52 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include Marth64
5 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
The formal title of the muxer according to the specification
is "RCWT (Raw Captions With Time)", so canonize this
in the long name of the codec and docs.
In the documentation section, point #2 was wrong: ccextractor
extracts the Closed Captions data and stores normalized bits
similarly to this muxer.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavformat/rcwtenc.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/libavformat/rcwtenc.c b/libavformat/rcwtenc.c
index a6060ba7c4..ed72de81ef 100644
--- a/libavformat/rcwtenc.c
+++ b/libavformat/rcwtenc.c
@@ -1,6 +1,5 @@
/*
- * Raw Captions With Time (RCWT) muxer
- * Author: Marth64 <marth64@proxyid.net>
+ * RCWT (Raw Captions With Time) muxer
*
* This file is part of FFmpeg.
*
@@ -20,16 +19,16 @@
*/
/*
- * Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
- * used open source tool for processing 608/708 closed caption (CC) sources.
+ * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
+ * used open source tool for processing 608/708 Closed Captions (CC) sources.
* It can be used to archive the original, raw CC bitstream and to produce
* a source file for later CC processing or conversion. As a result,
* it also allows for interopability with ccextractor for processing CC data
* extracted via ffmpeg. The format is simple to parse and can be used
* to retain all lines and variants of CC.
*
- * This muxer implements the specification as of 2024-01-05, which has
- * been stable and unchanged for 10 years as of this writing.
+ * This muxer implements the specification as of March 2024, which has
+ * been stable and unchanged since April 2014.
*
* This muxer will have some nuances from the way that ccextractor muxes RCWT.
* No compatibility issues when processing the output with ccextractor
@@ -40,13 +39,7 @@
* (1) This muxer will identify as "FF" as the writing program identifier, so
* as to be honest about the output's origin.
*
- * (2) ffmpeg's MPEG-1/2, H264, HEVC, etc. decoders extract closed captioning
- * data differently than ccextractor from embedded SEI/user data.
- * For example, DVD captioning bytes will be translated to ATSC A53 format.
- * This allows ffmpeg to handle 608/708 in a consistant way downstream.
- * This is a lossless conversion and the meaningful data is retained.
- *
- * (3) This muxer will not alter the extracted data except to remove invalid
+ * (2) This muxer will not alter the extracted data except to remove invalid
* packets in between valid CC blocks. On the other hand, ccextractor
* will by default remove mid-stream padding, and add padding at the end
* of the stream (in order to convey the end time of the source video).
@@ -172,7 +165,7 @@ static int rcwt_write_trailer(AVFormatContext *avf)
const FFOutputFormat ff_rcwt_muxer = {
.p.name = "rcwt",
- .p.long_name = NULL_IF_CONFIG_SMALL("Raw Captions With Time"),
+ .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"),
.p.extensions = "bin",
.p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
.p.subtitle_codec = AV_CODEC_ID_EIA_608,
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
` (3 preceding siblings ...)
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 11:44 ` Andreas Rheinhardt
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include Marth64
5 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
used open source tool for processing 608/708 Closed Captions (CC) sources.
RCWT can be used to archive the original CC bitstream. The muxer was added
in January 2024. In this commit, add the demuxer.
One can now demux RCWT files for rendering in ccaption_dec or interoperate
with ccextractor (which produces RCWT). Using the muxer/demuxer combination,
the CC bits can be kept for further processing or rendering with either tool.
This can be an effective approach to backup original CC presentations.
Prior to this, the next best solution was FFmpeg's SCC muxer, but SCC itself
is not compatible with ccextractor (which is a de facto OSS CC processing tool)
and it is a proprietary format.
Tests will follow.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/rcwtdec.c | 158 +++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+)
create mode 100644 libavformat/rcwtdec.c
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 8811a0ffc9..2092ca9f38 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -493,6 +493,7 @@ OBJS-$(CONFIG_QOA_DEMUXER) += qoadec.o
OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
+OBJS-$(CONFIG_RCWT_DEMUXER) += rcwtdec.o subtitles.o
OBJS-$(CONFIG_RCWT_MUXER) += rcwtenc.o subtitles.o
OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 0a0e76138f..b89a49b6ec 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -391,6 +391,7 @@ extern const FFInputFormat ff_qoa_demuxer;
extern const FFInputFormat ff_r3d_demuxer;
extern const FFInputFormat ff_rawvideo_demuxer;
extern const FFOutputFormat ff_rawvideo_muxer;
+extern const FFInputFormat ff_rcwt_demuxer;
extern const FFOutputFormat ff_rcwt_muxer;
extern const FFInputFormat ff_realtext_demuxer;
extern const FFInputFormat ff_redspark_demuxer;
diff --git a/libavformat/rcwtdec.c b/libavformat/rcwtdec.c
new file mode 100644
index 0000000000..f553f13366
--- /dev/null
+++ b/libavformat/rcwtdec.c
@@ -0,0 +1,158 @@
+/*
+ * RCWT (Raw Captions With Time) demuxer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
+ * used open source tool for processing 608/708 Closed Captions (CC) sources.
+ * It can be used to archive the original, raw CC bitstream and to produce
+ * a source file for later CC processing or conversion. As a result,
+ * it also allows for interopability with ccextractor for processing CC data
+ * extracted via ffmpeg. The format is simple to parse and can be used
+ * to retain all lines and variants of CC.
+ *
+ * This demuxer implements the specification as of March 2024, which has
+ * been stable and unchanged since April 2014.
+ *
+ * A free specification of RCWT can be found here:
+ * @url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
+ */
+
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "subtitles.h"
+#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
+
+#define RCWT_CLUSTER_MAX_BLOCKS 65535
+#define RCWT_BLOCK_SIZE 3
+#define RCWT_HEADER_SIZE 11
+
+typedef struct RCWTContext {
+ FFDemuxSubtitlesQueue q;
+} RCWTContext;
+
+static int rcwt_read_header(AVFormatContext *avf)
+{
+ RCWTContext *rcwt = avf->priv_data;
+
+ AVPacket *sub = NULL;
+ AVStream *st;
+ uint8_t header[RCWT_HEADER_SIZE] = {0};
+ int nb_bytes = 0;
+
+ int64_t cluster_pts = AV_NOPTS_VALUE;
+ int cluster_nb_blocks = 0;
+ int cluster_size = 0;
+ uint8_t *cluster_buf;
+
+ /* validate the header */
+ nb_bytes = avio_read(avf->pb, header, RCWT_HEADER_SIZE);
+ if (nb_bytes != RCWT_HEADER_SIZE || AV_RB16(header) != 0xCCCC || header[2] != 0xED) {
+ av_log(avf, AV_LOG_ERROR, "Input is not an RCWT file\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((header[3] != 0xCC && header[3] != 0xFF) || header[4] != 0x00) {
+ av_log(avf, AV_LOG_ERROR, "Input writing application is not supported, only "
+ "0xCC00 (ccextractor) or 0xFF00 (FFmpeg) are compatible\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (AV_RB16(header + 6) != 0x0001) {
+ av_log(avf, AV_LOG_ERROR, "Input RCWT version is not compatible "
+ "(only version 0.001 is known)\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (header[3] == 0xFF && header[5] != 0x60) {
+ av_log(avf, AV_LOG_ERROR, "Input was written by a different version of FFmpeg "
+ "and unsupported, consider upgrading\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* setup AVStream */
+ st = avformat_new_stream(avf, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+ st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
+
+ avpriv_set_pts_info(st, 64, 1, 1000);
+
+ /* demux */
+ while (!avio_feof(avf->pb)) {
+ cluster_pts = avio_rl64(avf->pb);
+ cluster_nb_blocks = avio_rl16(avf->pb);
+ if (cluster_nb_blocks == 0)
+ continue;
+
+ cluster_size = cluster_nb_blocks * RCWT_BLOCK_SIZE;
+ cluster_buf = av_calloc(cluster_nb_blocks, RCWT_BLOCK_SIZE);
+ if (!cluster_buf)
+ return AVERROR(ENOMEM);
+
+ nb_bytes = avio_read(avf->pb, cluster_buf, cluster_size);
+ if (nb_bytes != cluster_size) {
+ av_freep(&cluster_buf);
+ av_log(avf, AV_LOG_ERROR, "Input cluster has invalid size "
+ "(expected=%d actual=%d pos=%ld)\n",
+ cluster_size, nb_bytes, avio_tell(avf->pb));
+ return AVERROR_INVALIDDATA;
+ }
+
+ sub = ff_subtitles_queue_insert(&rcwt->q, cluster_buf, cluster_size, 0);
+ if (!sub) {
+ av_freep(&cluster_buf);
+ return AVERROR(ENOMEM);
+ }
+
+ sub->pos = avio_tell(avf->pb);
+ sub->pts = cluster_pts;
+
+ av_freep(&cluster_buf);
+ cluster_buf = NULL;
+ }
+
+ ff_subtitles_queue_finalize(avf, &rcwt->q);
+
+ return 0;
+}
+
+static int rcwt_probe(const AVProbeData *p)
+{
+ return p->buf_size > RCWT_HEADER_SIZE &&
+ AV_RB16(p->buf) == 0xCCCC && AV_RB8(p->buf + 2) == 0xED ? 50 : 0;
+}
+
+const FFInputFormat ff_rcwt_demuxer = {
+ .p.name = "rcwt",
+ .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"),
+ .p.extensions = "bin",
+ .p.flags = AVFMT_TS_DISCONT,
+ .priv_data_size = sizeof(RCWTContext),
+ .flags_internal = FF_FMT_INIT_CLEANUP,
+ .read_probe = rcwt_probe,
+ .read_header = rcwt_read_header,
+ .read_packet = ff_subtitles_read_packet,
+ .read_seek2 = ff_subtitles_read_seek,
+ .read_close = ff_subtitles_read_close
+};
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
` (4 preceding siblings ...)
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer Marth64
@ 2024-03-12 6:00 ` Marth64
2024-03-12 13:53 ` Stefano Sabatini
5 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-12 6:00 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavformat/sccdec.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libavformat/sccdec.c b/libavformat/sccdec.c
index 5f2f95d80e..f6d5f29a0a 100644
--- a/libavformat/sccdec.c
+++ b/libavformat/sccdec.c
@@ -24,7 +24,6 @@
#include "internal.h"
#include "subtitles.h"
#include "libavutil/avstring.h"
-#include "libavutil/bprint.h"
#include "libavutil/intreadwrite.h"
typedef struct SCCContext {
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
@ 2024-03-12 11:00 ` Stefano Sabatini
2024-03-12 11:52 ` Andreas Rheinhardt
2024-03-28 9:29 ` Anton Khirnov
1 sibling, 1 reply; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-12 11:00 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-12 01:00:00 -0500, Marth64 wrote:
> In MPEG-2 user data, there can be different types of Closed Captions
> formats embedded (A53, SCTE-20, or DVD). The current behavior of the
> CC extraction code in the MPEG-2 decoder is to not be aware of
> multiple formats if multiple exist, therefore allowing one format
> to overwrite the other during the extraction process since the CC
> extraction shares one output buffer for the normalized bytes.
>
> This causes sources that have two CC formats to produce flawed output.
> There exist real-world samples which contain both A53 and SCTE-20 captions
> in the same MPEG-2 stream, and that manifest this problem. Example of symptom:
> THANK YOU (expected) --> THTHANANK K YOYOUU (actual)
>
> The solution is to pick only the first CC substream observed with valid bytes,
> and ignore the other types. Additionally, provide an option for users
> to manually "force" a type in the event that this matters for a particular
> source.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavcodec/mpeg12dec.c | 67 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 64 insertions(+), 3 deletions(-)
>
> diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
> index 3a2f17e508..8961a290a3 100644
> --- a/libavcodec/mpeg12dec.c
> +++ b/libavcodec/mpeg12dec.c
> @@ -62,6 +62,16 @@
>
> #define A53_MAX_CC_COUNT 2000
>
> +enum Mpeg2ClosedCaptionsFormat {
> + CC_FORMAT_AUTO,
> + CC_FORMAT_A53_PART4,
> + CC_FORMAT_SCTE20,
> + CC_FORMAT_DVD
> +};
> +static const char mpeg2_cc_format_labels[4][12] = {
nit: this might be
static const char *mpeg2_cc_format_labels[4] = {
to avoid unnecessary constraints on the string length, or you might
pass the CC name in the function directly to avoid to maintain the
array (as it is not shared at the moment)
> + "Unknown", "A/53 Part 4", "SCTE-20", "DVD"
> +};
> +
[...]
LGTM otherwise.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer Marth64
@ 2024-03-12 11:44 ` Andreas Rheinhardt
2024-03-12 14:12 ` Marth64
2024-03-17 4:29 ` [FFmpeg-devel] [PATCH v4] " Marth64
0 siblings, 2 replies; 30+ messages in thread
From: Andreas Rheinhardt @ 2024-03-12 11:44 UTC (permalink / raw)
To: ffmpeg-devel
Marth64:
> Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
> used open source tool for processing 608/708 Closed Captions (CC) sources.
> RCWT can be used to archive the original CC bitstream. The muxer was added
> in January 2024. In this commit, add the demuxer.
>
> One can now demux RCWT files for rendering in ccaption_dec or interoperate
> with ccextractor (which produces RCWT). Using the muxer/demuxer combination,
> the CC bits can be kept for further processing or rendering with either tool.
> This can be an effective approach to backup original CC presentations.
>
> Prior to this, the next best solution was FFmpeg's SCC muxer, but SCC itself
> is not compatible with ccextractor (which is a de facto OSS CC processing tool)
> and it is a proprietary format.
>
> Tests will follow.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/rcwtdec.c | 158 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 160 insertions(+)
> create mode 100644 libavformat/rcwtdec.c
>
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 8811a0ffc9..2092ca9f38 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -493,6 +493,7 @@ OBJS-$(CONFIG_QOA_DEMUXER) += qoadec.o
> OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
> OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
> OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
> +OBJS-$(CONFIG_RCWT_DEMUXER) += rcwtdec.o subtitles.o
> OBJS-$(CONFIG_RCWT_MUXER) += rcwtenc.o subtitles.o
> OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
> OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 0a0e76138f..b89a49b6ec 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -391,6 +391,7 @@ extern const FFInputFormat ff_qoa_demuxer;
> extern const FFInputFormat ff_r3d_demuxer;
> extern const FFInputFormat ff_rawvideo_demuxer;
> extern const FFOutputFormat ff_rawvideo_muxer;
> +extern const FFInputFormat ff_rcwt_demuxer;
> extern const FFOutputFormat ff_rcwt_muxer;
> extern const FFInputFormat ff_realtext_demuxer;
> extern const FFInputFormat ff_redspark_demuxer;
> diff --git a/libavformat/rcwtdec.c b/libavformat/rcwtdec.c
> new file mode 100644
> index 0000000000..f553f13366
> --- /dev/null
> +++ b/libavformat/rcwtdec.c
> @@ -0,0 +1,158 @@
> +/*
> + * RCWT (Raw Captions With Time) demuxer
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/*
> + * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
> + * used open source tool for processing 608/708 Closed Captions (CC) sources.
> + * It can be used to archive the original, raw CC bitstream and to produce
> + * a source file for later CC processing or conversion. As a result,
> + * it also allows for interopability with ccextractor for processing CC data
> + * extracted via ffmpeg. The format is simple to parse and can be used
> + * to retain all lines and variants of CC.
> + *
> + * This demuxer implements the specification as of March 2024, which has
> + * been stable and unchanged since April 2014.
> + *
> + * A free specification of RCWT can be found here:
> + * @url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
> + */
> +
> +#include "avformat.h"
> +#include "demux.h"
> +#include "internal.h"
> +#include "subtitles.h"
> +#include "libavutil/avstring.h"
> +#include "libavutil/intreadwrite.h"
What are these two headers used for? (Didn't you add the same unused
headers to the muxer?)
> +
> +#define RCWT_CLUSTER_MAX_BLOCKS 65535
> +#define RCWT_BLOCK_SIZE 3
> +#define RCWT_HEADER_SIZE 11
> +
> +typedef struct RCWTContext {
> + FFDemuxSubtitlesQueue q;
> +} RCWTContext;
> +
> +static int rcwt_read_header(AVFormatContext *avf)
> +{
> + RCWTContext *rcwt = avf->priv_data;
> +
> + AVPacket *sub = NULL;
> + AVStream *st;
> + uint8_t header[RCWT_HEADER_SIZE] = {0};
> + int nb_bytes = 0;
> +
> + int64_t cluster_pts = AV_NOPTS_VALUE;
> + int cluster_nb_blocks = 0;
> + int cluster_size = 0;
> + uint8_t *cluster_buf;
Use smaller scope for these.
> +
> + /* validate the header */
> + nb_bytes = avio_read(avf->pb, header, RCWT_HEADER_SIZE);
> + if (nb_bytes != RCWT_HEADER_SIZE || AV_RB16(header) != 0xCCCC || header[2] != 0xED) {
> + av_log(avf, AV_LOG_ERROR, "Input is not an RCWT file\n");
> + return AVERROR_INVALIDDATA;
> + }
Such checks belong in a probe function (where it already is); the
demuxer is simply supposed to demux based upon the assumption that the
file is of the format.
> +
> + if ((header[3] != 0xCC && header[3] != 0xFF) || header[4] != 0x00) {
> + av_log(avf, AV_LOG_ERROR, "Input writing application is not supported, only "
> + "0xCC00 (ccextractor) or 0xFF00 (FFmpeg) are compatible\n");
> + return AVERROR_INVALIDDATA;
This will basically make it impossible to create a new application for
writing this format (or rather: it will force this new muxer to lie for
compatibility reasons).
> + }
> +
> + if (AV_RB16(header + 6) != 0x0001) {
> + av_log(avf, AV_LOG_ERROR, "Input RCWT version is not compatible "
> + "(only version 0.001 is known)\n");
> + return AVERROR_INVALIDDATA;
> + }
> +
> + if (header[3] == 0xFF && header[5] != 0x60) {
> + av_log(avf, AV_LOG_ERROR, "Input was written by a different version of FFmpeg "
> + "and unsupported, consider upgrading\n");
> + return AVERROR_INVALIDDATA;
> + }
> +
> + /* setup AVStream */
> + st = avformat_new_stream(avf, NULL);
> + if (!st)
> + return AVERROR(ENOMEM);
> +
> + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
> + st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
> +
> + avpriv_set_pts_info(st, 64, 1, 1000);
> +
> + /* demux */
> + while (!avio_feof(avf->pb)) {
> + cluster_pts = avio_rl64(avf->pb);
> + cluster_nb_blocks = avio_rl16(avf->pb);
> + if (cluster_nb_blocks == 0)
> + continue;
> +
> + cluster_size = cluster_nb_blocks * RCWT_BLOCK_SIZE;
> + cluster_buf = av_calloc(cluster_nb_blocks, RCWT_BLOCK_SIZE);
Why are you zeroing when you are overwriting everything lateron anyway?
> + if (!cluster_buf)
> + return AVERROR(ENOMEM);
> +
> + nb_bytes = avio_read(avf->pb, cluster_buf, cluster_size);
> + if (nb_bytes != cluster_size) {
> + av_freep(&cluster_buf);
> + av_log(avf, AV_LOG_ERROR, "Input cluster has invalid size "
> + "(expected=%d actual=%d pos=%ld)\n",
> + cluster_size, nb_bytes, avio_tell(avf->pb));
Not really useful message.
> + return AVERROR_INVALIDDATA;
You should better use ffio_read() and return the error.
> + }
> +
> + sub = ff_subtitles_queue_insert(&rcwt->q, cluster_buf, cluster_size, 0);
> + if (!sub) {
> + av_freep(&cluster_buf);
> + return AVERROR(ENOMEM);
> + }
> +
> + sub->pos = avio_tell(avf->pb);
> + sub->pts = cluster_pts;
> +
> + av_freep(&cluster_buf);
> + cluster_buf = NULL;
The muxer splits packets with >= 2^16 blocks. Should the demuxer
recombine such packets?
> + }
> +
> + ff_subtitles_queue_finalize(avf, &rcwt->q);
> +
> + return 0;
> +}
> +
> +static int rcwt_probe(const AVProbeData *p)
> +{
> + return p->buf_size > RCWT_HEADER_SIZE &&
> + AV_RB16(p->buf) == 0xCCCC && AV_RB8(p->buf + 2) == 0xED ? 50 : 0;
> +}
> +
> +const FFInputFormat ff_rcwt_demuxer = {
> + .p.name = "rcwt",
> + .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"),
> + .p.extensions = "bin",
> + .p.flags = AVFMT_TS_DISCONT,
> + .priv_data_size = sizeof(RCWTContext),
> + .flags_internal = FF_FMT_INIT_CLEANUP,
> + .read_probe = rcwt_probe,
> + .read_header = rcwt_read_header,
> + .read_packet = ff_subtitles_read_packet,
> + .read_seek2 = ff_subtitles_read_seek,
> + .read_close = ff_subtitles_read_close
> +};
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream
2024-03-12 11:00 ` Stefano Sabatini
@ 2024-03-12 11:52 ` Andreas Rheinhardt
0 siblings, 0 replies; 30+ messages in thread
From: Andreas Rheinhardt @ 2024-03-12 11:52 UTC (permalink / raw)
To: ffmpeg-devel
Stefano Sabatini:
> On date Tuesday 2024-03-12 01:00:00 -0500, Marth64 wrote:
>> In MPEG-2 user data, there can be different types of Closed Captions
>> formats embedded (A53, SCTE-20, or DVD). The current behavior of the
>> CC extraction code in the MPEG-2 decoder is to not be aware of
>> multiple formats if multiple exist, therefore allowing one format
>> to overwrite the other during the extraction process since the CC
>> extraction shares one output buffer for the normalized bytes.
>>
>> This causes sources that have two CC formats to produce flawed output.
>> There exist real-world samples which contain both A53 and SCTE-20 captions
>> in the same MPEG-2 stream, and that manifest this problem. Example of symptom:
>> THANK YOU (expected) --> THTHANANK K YOYOUU (actual)
>>
>> The solution is to pick only the first CC substream observed with valid bytes,
>> and ignore the other types. Additionally, provide an option for users
>> to manually "force" a type in the event that this matters for a particular
>> source.
>>
>> Signed-off-by: Marth64 <marth64@proxyid.net>
>> ---
>> libavcodec/mpeg12dec.c | 67 ++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 64 insertions(+), 3 deletions(-)
>>
>> diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
>> index 3a2f17e508..8961a290a3 100644
>> --- a/libavcodec/mpeg12dec.c
>> +++ b/libavcodec/mpeg12dec.c
>> @@ -62,6 +62,16 @@
>>
>> #define A53_MAX_CC_COUNT 2000
>>
>> +enum Mpeg2ClosedCaptionsFormat {
>> + CC_FORMAT_AUTO,
>> + CC_FORMAT_A53_PART4,
>> + CC_FORMAT_SCTE20,
>> + CC_FORMAT_DVD
>> +};
>
>> +static const char mpeg2_cc_format_labels[4][12] = {
>
> nit: this might be
> static const char *mpeg2_cc_format_labels[4] = {
>
This would add relocations and put this into .data.rel.ro.
> to avoid unnecessary constraints on the string length, or you might
> pass the CC name in the function directly to avoid to maintain the
> array (as it is not shared at the moment)
>
That sound like a good idea.
>> + "Unknown", "A/53 Part 4", "SCTE-20", "DVD"
>> +};
>> +
>
> [...]
>
> LGTM otherwise.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags Marth64
@ 2024-03-12 13:49 ` Stefano Sabatini
0 siblings, 0 replies; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-12 13:49 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-12 01:00:01 -0500, Marth64 wrote:
> Closed Captions decoder prints multiple \pos ASS tags per cue,
> and preceding the \pos tag is a fixed \an7 that fixes rendering
> position from the top left corner and enforces justification.
>
> Printing multiple \an and \pos tags in this way is invalid behavior,
> because only the first \pos tag in a cue is honored by ASS anyway.
> Don't write multiple \an and \pos tags.
>
> Also, update tests accordingly.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavcodec/ccaption_dec.c | 8 +-
> tests/ref/fate/sub-cc | 2 +-
> tests/ref/fate/sub-cc-realtime | 8 +-
> tests/ref/fate/sub-cc-scte20 | 4 +-
> tests/ref/fate/sub-scc | 146 ++++++++++++++++-----------------
> 5 files changed, 86 insertions(+), 82 deletions(-)
>
> diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
> index faf058ce97..9d4a93647c 100644
> --- a/libavcodec/ccaption_dec.c
> +++ b/libavcodec/ccaption_dec.c
> @@ -456,7 +456,7 @@ static void roll_up(CCaptionSubContext *ctx)
>
> static int capture_screen(CCaptionSubContext *ctx)
> {
> - int i, j, tab = 0;
> + int i, j, tab = 0, seen_row = 0;
> struct Screen *screen = ctx->screen + ctx->active_screen;
> enum cc_font prev_font = CCFONT_REGULAR;
> enum cc_color_code prev_color = CCCOL_WHITE;
> @@ -496,7 +496,11 @@ static int capture_screen(CCaptionSubContext *ctx)
>
> x = ASS_DEFAULT_PLAYRESX * (0.1 + 0.0250 * j);
> y = ASS_DEFAULT_PLAYRESY * (0.1 + 0.0533 * i);
> - av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y);
> +
> + if (!seen_row) {
> + av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y);
> + seen_row = 1;
> + }
probably it might be useful to print debug logs in case the pos
coordinates are found but not rendered?
[...]
LGTM otherwise.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces Marth64
@ 2024-03-12 13:50 ` Stefano Sabatini
2024-03-17 4:27 ` Marth64
0 siblings, 1 reply; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-12 13:50 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-12 01:00:02 -0500, Marth64 wrote:
> In Closed Captions (US), the non-breaking space (0xA0) can be used to
> align text horizontally from the left when used as a leading character.
> However, CC decoder does not ignore it as a leading character
> like it does an ordinary space, so a blank padding is rendered
> on the black CC box. This is not the intended viewing experience.
>
> Ignore the leading non-breaking spaces, thus creating the intended
> transparency which aligns the text. Since all characters are
> fixed-width in CC, it can be handled the same way as we currently
> treat leading ordinary spaces.
>
> Also, as a nit, lowercase the NBSP's hex code in the entry table to match
> casing of the other hex codes.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavcodec/ccaption_dec.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
Still LGTM.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation Marth64
@ 2024-03-12 13:52 ` Stefano Sabatini
0 siblings, 0 replies; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-12 13:52 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-12 01:00:03 -0500, Marth64 wrote:
> The formal title of the muxer according to the specification
> is "RCWT (Raw Captions With Time)", so canonize this
> in the long name of the codec and docs.
>
> In the documentation section, point #2 was wrong: ccextractor
> extracts the Closed Captions data and stores normalized bits
> similarly to this muxer.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavformat/rcwtenc.c | 21 +++++++--------------
> 1 file changed, 7 insertions(+), 14 deletions(-)
LGTM, will apply.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include Marth64
@ 2024-03-12 13:53 ` Stefano Sabatini
0 siblings, 0 replies; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-12 13:53 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-12 01:00:05 -0500, Marth64 wrote:
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavformat/sccdec.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/libavformat/sccdec.c b/libavformat/sccdec.c
> index 5f2f95d80e..f6d5f29a0a 100644
> --- a/libavformat/sccdec.c
> +++ b/libavformat/sccdec.c
> @@ -24,7 +24,6 @@
> #include "internal.h"
> #include "subtitles.h"
> #include "libavutil/avstring.h"
> -#include "libavutil/bprint.h"
> #include "libavutil/intreadwrite.h"
Will apply, thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-12 11:44 ` Andreas Rheinhardt
@ 2024-03-12 14:12 ` Marth64
2024-03-17 4:29 ` [FFmpeg-devel] [PATCH v4] " Marth64
1 sibling, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-12 14:12 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Will address, thanks for the review.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces
2024-03-12 13:50 ` Stefano Sabatini
@ 2024-03-17 4:27 ` Marth64
0 siblings, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-17 4:27 UTC (permalink / raw)
To: FFmpeg development discussions and patches, Marth64
Hi Stefano,
I would like to withdraw this patch for now.
I have found content where this breaks center
justified text further (which is already not supported).
I will instead try to implement center justification
and incorporate this through that route.
Please ignore it.
Thank you for understanding,
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-12 11:44 ` Andreas Rheinhardt
2024-03-12 14:12 ` Marth64
@ 2024-03-17 4:29 ` Marth64
2024-03-18 20:12 ` Marth64
2024-03-19 14:35 ` Stefano Sabatini
1 sibling, 2 replies; 30+ messages in thread
From: Marth64 @ 2024-03-17 4:29 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
used open source tool for processing 608/708 Closed Captions (CC) sources.
RCWT can be used to archive the original CC bitstream. The muxer was added
in January 2024. In this commit, add the demuxer.
One can now demux RCWT files for rendering in ccaption_dec or interoperate
with ccextractor (which produces RCWT). Using the muxer/demuxer combination,
the CC bits can be kept for further processing or rendering with either tool.
This can be an effective approach to backup original CC presentations.
Prior to this, the next best solution was FFmpeg's SCC muxer, but SCC itself
is not compatible with ccextractor (which is a de facto OSS CC processing tool)
and it is a proprietary format.
Tests will follow.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/rcwtdec.c | 153 +++++++++++++++++++++++++++++++++++++++
3 files changed, 155 insertions(+)
create mode 100644 libavformat/rcwtdec.c
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 94a949f555..a6de720d8c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -493,6 +493,7 @@ OBJS-$(CONFIG_QOA_DEMUXER) += qoadec.o
OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
+OBJS-$(CONFIG_RCWT_DEMUXER) += rcwtdec.o subtitles.o
OBJS-$(CONFIG_RCWT_MUXER) += rcwtenc.o subtitles.o
OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index e15d0fa6d7..3140018f8d 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -391,6 +391,7 @@ extern const FFInputFormat ff_qoa_demuxer;
extern const FFInputFormat ff_r3d_demuxer;
extern const FFInputFormat ff_rawvideo_demuxer;
extern const FFOutputFormat ff_rawvideo_muxer;
+extern const FFInputFormat ff_rcwt_demuxer;
extern const FFOutputFormat ff_rcwt_muxer;
extern const FFInputFormat ff_realtext_demuxer;
extern const FFInputFormat ff_redspark_demuxer;
diff --git a/libavformat/rcwtdec.c b/libavformat/rcwtdec.c
new file mode 100644
index 0000000000..1fd35be41b
--- /dev/null
+++ b/libavformat/rcwtdec.c
@@ -0,0 +1,153 @@
+/*
+ * RCWT (Raw Captions With Time) demuxer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
+ * used open source tool for processing 608/708 Closed Captions (CC) sources.
+ * It can be used to archive the original, raw CC bitstream and to produce
+ * a source file for later CC processing or conversion. As a result,
+ * it also allows for interopability with ccextractor for processing CC data
+ * extracted via ffmpeg. The format is simple to parse and can be used
+ * to retain all lines and variants of CC.
+ *
+ * This demuxer implements the specification as of March 2024, which has
+ * been stable and unchanged since April 2014.
+ *
+ * A free specification of RCWT can be found here:
+ * @url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
+ */
+
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "subtitles.h"
+#include "libavutil/intreadwrite.h"
+
+#define RCWT_CLUSTER_MAX_BLOCKS 65535
+#define RCWT_BLOCK_SIZE 3
+#define RCWT_HEADER_SIZE 11
+
+typedef struct RCWTContext {
+ FFDemuxSubtitlesQueue q;
+} RCWTContext;
+
+static int rcwt_read_header(AVFormatContext *avf)
+{
+ RCWTContext *rcwt = avf->priv_data;
+
+ AVPacket *sub = NULL;
+ AVStream *st;
+ uint8_t header[RCWT_HEADER_SIZE] = {0};
+ int nb_bytes = 0;
+
+ /* validate the header */
+ nb_bytes = avio_read(avf->pb, header, RCWT_HEADER_SIZE);
+ if (nb_bytes != RCWT_HEADER_SIZE) {
+ av_log(avf, AV_LOG_ERROR, "Header does not have the expected size "
+ "(expected=%d actual=%d)\n",
+ RCWT_HEADER_SIZE, nb_bytes);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (AV_RB16(header + 6) != 0x0001) {
+ av_log(avf, AV_LOG_ERROR, "RCWT format version is not compatible "
+ "(only version 0.001 is known)\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ av_log(avf, AV_LOG_DEBUG, "RCWT writer application: %02X version: %02x\n",
+ header[3], header[5]);
+
+ /* setup AVStream */
+ st = avformat_new_stream(avf, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+ st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
+
+ avpriv_set_pts_info(st, 64, 1, 1000);
+
+ /* demux */
+ while (!avio_feof(avf->pb)) {
+ int64_t cluster_pts = AV_NOPTS_VALUE;
+ int cluster_nb_blocks = 0;
+ int cluster_size = 0;
+ uint8_t *cluster_buf;
+
+ cluster_pts = avio_rl64(avf->pb);
+ cluster_nb_blocks = avio_rl16(avf->pb);
+ if (cluster_nb_blocks == 0)
+ continue;
+
+ cluster_size = cluster_nb_blocks * RCWT_BLOCK_SIZE;
+ cluster_buf = av_malloc(cluster_size);
+ if (!cluster_buf)
+ return AVERROR(ENOMEM);
+
+ nb_bytes = avio_read(avf->pb, cluster_buf, cluster_size);
+ if (nb_bytes < 0)
+ return nb_bytes;
+
+ if (nb_bytes != cluster_size) {
+ av_freep(&cluster_buf);
+ av_log(avf, AV_LOG_ERROR, "Cluster does not have the expected size "
+ "(expected=%d actual=%d pos=%ld)\n",
+ cluster_size, nb_bytes, avio_tell(avf->pb));
+ return AVERROR_INVALIDDATA;
+ }
+
+ sub = ff_subtitles_queue_insert(&rcwt->q, cluster_buf, cluster_size, 0);
+ if (!sub) {
+ av_freep(&cluster_buf);
+ return AVERROR(ENOMEM);
+ }
+
+ sub->pos = avio_tell(avf->pb);
+ sub->pts = cluster_pts;
+
+ av_freep(&cluster_buf);
+ cluster_buf = NULL;
+ }
+
+ ff_subtitles_queue_finalize(avf, &rcwt->q);
+
+ return 0;
+}
+
+static int rcwt_probe(const AVProbeData *p)
+{
+ return p->buf_size > RCWT_HEADER_SIZE &&
+ AV_RB16(p->buf) == 0xCCCC && AV_RB8(p->buf + 2) == 0xED ? 50 : 0;
+}
+
+const FFInputFormat ff_rcwt_demuxer = {
+ .p.name = "rcwt",
+ .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"),
+ .p.extensions = "bin",
+ .p.flags = AVFMT_TS_DISCONT,
+ .priv_data_size = sizeof(RCWTContext),
+ .flags_internal = FF_FMT_INIT_CLEANUP,
+ .read_probe = rcwt_probe,
+ .read_header = rcwt_read_header,
+ .read_packet = ff_subtitles_read_packet,
+ .read_seek2 = ff_subtitles_read_seek,
+ .read_close = ff_subtitles_read_close
+};
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-17 4:29 ` [FFmpeg-devel] [PATCH v4] " Marth64
@ 2024-03-18 20:12 ` Marth64
2024-03-19 14:35 ` Stefano Sabatini
1 sibling, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-18 20:12 UTC (permalink / raw)
To: ffmpeg-devel
Bump on this small demuxer if possible. v4 in the last reply. Thank you.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-17 4:29 ` [FFmpeg-devel] [PATCH v4] " Marth64
2024-03-18 20:12 ` Marth64
@ 2024-03-19 14:35 ` Stefano Sabatini
2024-03-19 15:55 ` Marth64
1 sibling, 1 reply; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-19 14:35 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Saturday 2024-03-16 23:29:41 -0500, Marth64 wrote:
> Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
> used open source tool for processing 608/708 Closed Captions (CC) sources.
> RCWT can be used to archive the original CC bitstream. The muxer was added
> in January 2024. In this commit, add the demuxer.
>
> One can now demux RCWT files for rendering in ccaption_dec or interoperate
> with ccextractor (which produces RCWT). Using the muxer/demuxer combination,
> the CC bits can be kept for further processing or rendering with either tool.
> This can be an effective approach to backup original CC presentations.
>
> Prior to this, the next best solution was FFmpeg's SCC muxer, but SCC itself
> is not compatible with ccextractor (which is a de facto OSS CC processing tool)
> and it is a proprietary format.
>
> Tests will follow.
>
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/rcwtdec.c | 153 +++++++++++++++++++++++++++++++++++++++
missing Changelog entry
> 3 files changed, 155 insertions(+)
> create mode 100644 libavformat/rcwtdec.c
>
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 94a949f555..a6de720d8c 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -493,6 +493,7 @@ OBJS-$(CONFIG_QOA_DEMUXER) += qoadec.o
> OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
> OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
> OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
> +OBJS-$(CONFIG_RCWT_DEMUXER) += rcwtdec.o subtitles.o
> OBJS-$(CONFIG_RCWT_MUXER) += rcwtenc.o subtitles.o
> OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
> OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index e15d0fa6d7..3140018f8d 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -391,6 +391,7 @@ extern const FFInputFormat ff_qoa_demuxer;
> extern const FFInputFormat ff_r3d_demuxer;
> extern const FFInputFormat ff_rawvideo_demuxer;
> extern const FFOutputFormat ff_rawvideo_muxer;
> +extern const FFInputFormat ff_rcwt_demuxer;
> extern const FFOutputFormat ff_rcwt_muxer;
> extern const FFInputFormat ff_realtext_demuxer;
> extern const FFInputFormat ff_redspark_demuxer;
> diff --git a/libavformat/rcwtdec.c b/libavformat/rcwtdec.c
> new file mode 100644
> index 0000000000..1fd35be41b
> --- /dev/null
> +++ b/libavformat/rcwtdec.c
> @@ -0,0 +1,153 @@
> +/*
> + * RCWT (Raw Captions With Time) demuxer
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/*
> + * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
> + * used open source tool for processing 608/708 Closed Captions (CC) sources.
> + * It can be used to archive the original, raw CC bitstream and to produce
> + * a source file for later CC processing or conversion. As a result,
> + * it also allows for interopability with ccextractor for processing CC data
> + * extracted via ffmpeg. The format is simple to parse and can be used
> + * to retain all lines and variants of CC.
> + *
> + * This demuxer implements the specification as of March 2024, which has
> + * been stable and unchanged since April 2014.
> + *
> + * A free specification of RCWT can be found here:
> + * @url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
> + */
move part of this content to doc/demuxers.texi
Also having some practical example might be useful.
[...]
LGTM otherwise, thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-19 14:35 ` Stefano Sabatini
@ 2024-03-19 15:55 ` Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
0 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-19 15:55 UTC (permalink / raw)
To: FFmpeg development discussions and patches, Marth64
Thank you, v5 on the way with documentation updates and examples.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-19 15:55 ` Marth64
@ 2024-03-19 17:39 ` Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 2/4] avformat/rcwtenc: remove repeated documentation Marth64
` (4 more replies)
0 siblings, 5 replies; 30+ messages in thread
From: Marth64 @ 2024-03-19 17:39 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Signed-off-by: Marth64 <marth64@proxyid.net>
---
Changelog | 2 +-
doc/demuxers.texi | 29 ++++++++
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/rcwtdec.c | 148 +++++++++++++++++++++++++++++++++++++++
5 files changed, 180 insertions(+), 1 deletion(-)
create mode 100644 libavformat/rcwtdec.c
diff --git a/Changelog b/Changelog
index e3ca52430c..be871f75cd 100644
--- a/Changelog
+++ b/Changelog
@@ -19,7 +19,7 @@ version <next>:
- lavu/eval: introduce randomi() function in expressions
- VVC decoder
- fsync filter
-- Raw Captions with Time (RCWT) closed caption muxer
+- Raw Captions with Time (RCWT) closed caption muxer and demuxer
- ffmpeg CLI -bsf option may now be used for input as well as output
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
to -opt <contents of file <path>>
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index b70f3a38d7..26d4ba18a1 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -1038,6 +1038,35 @@ the command:
ffplay -f rawvideo -pixel_format rgb24 -video_size 320x240 -framerate 10 input.raw
@end example
+@anchor{rcwtdec}
+@section rcwt
+
+RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
+used open source tool for processing 608/708 Closed Captions (CC) sources.
+It can be used to archive the original, raw CC bitstream and to produce
+a source file for later CC processing or conversion. This demuxer can process
+RCWT sources created by ccextractor or FFmpeg. For more information on the format,
+see @ref{rcwtenc,,,ffmpeg-formats}.
+
+This demuxer implements the specification as of March 2024, which has
+been stable and unchanged since April 2014.
+
+@subsection Examples
+
+@itemize
+@item
+Render Closed Captions to ASSA (using FFmpeg's CC decoder):
+@example
+ffmpeg -i CC.rcwt.bin CC.ass
+@end example
+
+@item
+Convert an RCWT backup to SCC:
+@example
+ffmpeg -i CC.rcwt.bin -c:s copy CC.scc
+@end example
+@end itemize
+
@section sbg
SBaGen script demuxer.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 94a949f555..a6de720d8c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -493,6 +493,7 @@ OBJS-$(CONFIG_QOA_DEMUXER) += qoadec.o
OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o
OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o
OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o
+OBJS-$(CONFIG_RCWT_DEMUXER) += rcwtdec.o subtitles.o
OBJS-$(CONFIG_RCWT_MUXER) += rcwtenc.o subtitles.o
OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o
OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index e15d0fa6d7..3140018f8d 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -391,6 +391,7 @@ extern const FFInputFormat ff_qoa_demuxer;
extern const FFInputFormat ff_r3d_demuxer;
extern const FFInputFormat ff_rawvideo_demuxer;
extern const FFOutputFormat ff_rawvideo_muxer;
+extern const FFInputFormat ff_rcwt_demuxer;
extern const FFOutputFormat ff_rcwt_muxer;
extern const FFInputFormat ff_realtext_demuxer;
extern const FFInputFormat ff_redspark_demuxer;
diff --git a/libavformat/rcwtdec.c b/libavformat/rcwtdec.c
new file mode 100644
index 0000000000..1baa571231
--- /dev/null
+++ b/libavformat/rcwtdec.c
@@ -0,0 +1,148 @@
+/*
+ * RCWT (Raw Captions With Time) demuxer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
+ * used open source tool for processing 608/708 Closed Captions (CC) sources.
+ *
+ * This demuxer implements the specification as of March 2024, which has
+ * been stable and unchanged since April 2014.
+ *
+ * A free specification of RCWT can be found here:
+ * @url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
+ */
+
+#include "avformat.h"
+#include "demux.h"
+#include "internal.h"
+#include "subtitles.h"
+#include "libavutil/intreadwrite.h"
+
+#define RCWT_CLUSTER_MAX_BLOCKS 65535
+#define RCWT_BLOCK_SIZE 3
+#define RCWT_HEADER_SIZE 11
+
+typedef struct RCWTContext {
+ FFDemuxSubtitlesQueue q;
+} RCWTContext;
+
+static int rcwt_read_header(AVFormatContext *avf)
+{
+ RCWTContext *rcwt = avf->priv_data;
+
+ AVPacket *sub = NULL;
+ AVStream *st;
+ uint8_t header[RCWT_HEADER_SIZE] = {0};
+ int nb_bytes = 0;
+
+ /* validate the header */
+ nb_bytes = avio_read(avf->pb, header, RCWT_HEADER_SIZE);
+ if (nb_bytes != RCWT_HEADER_SIZE) {
+ av_log(avf, AV_LOG_ERROR, "Header does not have the expected size "
+ "(expected=%d actual=%d)\n",
+ RCWT_HEADER_SIZE, nb_bytes);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (AV_RB16(header + 6) != 0x0001) {
+ av_log(avf, AV_LOG_ERROR, "RCWT format version is not compatible "
+ "(only version 0.001 is known)\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ av_log(avf, AV_LOG_DEBUG, "RCWT writer application: %02X version: %02x\n",
+ header[3], header[5]);
+
+ /* setup AVStream */
+ st = avformat_new_stream(avf, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+
+ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+ st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
+
+ avpriv_set_pts_info(st, 64, 1, 1000);
+
+ /* demux */
+ while (!avio_feof(avf->pb)) {
+ int64_t cluster_pts = AV_NOPTS_VALUE;
+ int cluster_nb_blocks = 0;
+ int cluster_size = 0;
+ uint8_t *cluster_buf;
+
+ cluster_pts = avio_rl64(avf->pb);
+ cluster_nb_blocks = avio_rl16(avf->pb);
+ if (cluster_nb_blocks == 0)
+ continue;
+
+ cluster_size = cluster_nb_blocks * RCWT_BLOCK_SIZE;
+ cluster_buf = av_malloc(cluster_size);
+ if (!cluster_buf)
+ return AVERROR(ENOMEM);
+
+ nb_bytes = avio_read(avf->pb, cluster_buf, cluster_size);
+ if (nb_bytes < 0)
+ return nb_bytes;
+
+ if (nb_bytes != cluster_size) {
+ av_freep(&cluster_buf);
+ av_log(avf, AV_LOG_ERROR, "Cluster does not have the expected size "
+ "(expected=%d actual=%d pos=%ld)\n",
+ cluster_size, nb_bytes, avio_tell(avf->pb));
+ return AVERROR_INVALIDDATA;
+ }
+
+ sub = ff_subtitles_queue_insert(&rcwt->q, cluster_buf, cluster_size, 0);
+ if (!sub) {
+ av_freep(&cluster_buf);
+ return AVERROR(ENOMEM);
+ }
+
+ sub->pos = avio_tell(avf->pb);
+ sub->pts = cluster_pts;
+
+ av_freep(&cluster_buf);
+ cluster_buf = NULL;
+ }
+
+ ff_subtitles_queue_finalize(avf, &rcwt->q);
+
+ return 0;
+}
+
+static int rcwt_probe(const AVProbeData *p)
+{
+ return p->buf_size > RCWT_HEADER_SIZE &&
+ AV_RB16(p->buf) == 0xCCCC && AV_RB8(p->buf + 2) == 0xED ? 50 : 0;
+}
+
+const FFInputFormat ff_rcwt_demuxer = {
+ .p.name = "rcwt",
+ .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"),
+ .p.extensions = "bin",
+ .p.flags = AVFMT_TS_DISCONT,
+ .priv_data_size = sizeof(RCWTContext),
+ .flags_internal = FF_FMT_INIT_CLEANUP,
+ .read_probe = rcwt_probe,
+ .read_header = rcwt_read_header,
+ .read_packet = ff_subtitles_read_packet,
+ .read_seek2 = ff_subtitles_read_seek,
+ .read_close = ff_subtitles_read_close
+};
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v5 2/4] avformat/rcwtenc: remove repeated documentation
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
@ 2024-03-19 17:39 ` Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 3/4] doc/muxers: refresh and simplify RCWT muxer documentation Marth64
` (3 subsequent siblings)
4 siblings, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-19 17:39 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
The high level summary of RCWT can be delegated doc/muxers, which
makes it easier to maintain and more consistent with the documentation
of the demuxer.
Signed-off-by: Marth64 <marth64@proxyid.net>
---
libavformat/rcwtenc.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/libavformat/rcwtenc.c b/libavformat/rcwtenc.c
index ed72de81ef..a1a8c06533 100644
--- a/libavformat/rcwtenc.c
+++ b/libavformat/rcwtenc.c
@@ -21,11 +21,6 @@
/*
* RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
* used open source tool for processing 608/708 Closed Captions (CC) sources.
- * It can be used to archive the original, raw CC bitstream and to produce
- * a source file for later CC processing or conversion. As a result,
- * it also allows for interopability with ccextractor for processing CC data
- * extracted via ffmpeg. The format is simple to parse and can be used
- * to retain all lines and variants of CC.
*
* This muxer implements the specification as of March 2024, which has
* been stable and unchanged since April 2014.
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v5 3/4] doc/muxers: refresh and simplify RCWT muxer documentation
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 2/4] avformat/rcwtenc: remove repeated documentation Marth64
@ 2024-03-19 17:39 ` Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer Marth64
` (2 subsequent siblings)
4 siblings, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-19 17:39 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Signed-off-by: Marth64 <marth64@proxyid.net>
---
doc/muxers.texi | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi
index d9dd72e613..9e8de3dc42 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -2987,16 +2987,15 @@ ogg files can be safely chained.
@end table
-@anchor{rcwt}
+@anchor{rcwtenc}
@section rcwt
Raw Captions With Time (RCWT) is a format native to ccextractor, a commonly
-used open source tool for processing 608/708 closed caption (CC) sources.
-It can be used to archive the original, raw CC bitstream and to produce
-a source file for later CC processing or conversion. As a result,
-it also allows for interopability with ccextractor for processing CC data
-extracted via ffmpeg. The format is simple to parse and can be used
-to retain all lines and variants of CC.
+used open source tool for processing 608/708 Closed Captions (CC) sources.
+It can be used to archive the original extracted CC bitstream and to produce
+a source file for later processing or conversion. The format allows
+for interopability between ccextractor and FFmpeg, is simple to parse,
+and can be used to create a backup of the CC presentation.
This muxer implements the specification as of 2024-01-05, which has
been stable and unchanged for 10 years as of this writing.
@@ -3006,9 +3005,19 @@ No compatibility issues when processing the output with ccextractor
have been observed as a result of this so far, but mileage may vary
and outputs will not be a bit-exact match.
-A free specification of RCWT can be found here:
+A free specification of RCWT can be found at:
@url{https://github.com/CCExtractor/ccextractor/blob/master/docs/BINARY_FILE_FORMAT.TXT}
+@subsection Examples
+
+@itemize
+@item
+Extract Closed Captions to RCWT using lavfi:
+@example
+ffmpeg -f lavfi -i "movie=INPUT.mkv[out+subcc]" -map 0:s:0 -c:s copy CC.rcwt.bin
+@end example
+@end itemize
+
@anchor{segment}
@section segment, stream_segment, ssegment
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 2/4] avformat/rcwtenc: remove repeated documentation Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 3/4] doc/muxers: refresh and simplify RCWT muxer documentation Marth64
@ 2024-03-19 17:39 ` Marth64
2024-03-20 14:13 ` Stefano Sabatini
2024-03-19 21:41 ` [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer Michael Niedermayer
2024-03-20 14:11 ` Stefano Sabatini
4 siblings, 1 reply; 30+ messages in thread
From: Marth64 @ 2024-03-19 17:39 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Marth64
Signed-off-by: Marth64 <marth64@proxyid.net>
---
doc/indevs.texi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/indevs.texi b/doc/indevs.texi
index d1b2bacf8b..fc14737181 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -1069,9 +1069,9 @@ ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]"
@end example
@item
-Dump decoded frames to images and closed captions to a file (experimental):
+Dump decoded frames to images and Closed Captions to an RCWT backup:
@example
-ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy -f rawvideo subcc.bin
+ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy subcc.bin
@end example
@end itemize
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
` (2 preceding siblings ...)
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer Marth64
@ 2024-03-19 21:41 ` Michael Niedermayer
2024-03-19 22:07 ` Marth64
2024-03-20 14:11 ` Stefano Sabatini
4 siblings, 1 reply; 30+ messages in thread
From: Michael Niedermayer @ 2024-03-19 21:41 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 970 bytes --]
On Tue, Mar 19, 2024 at 12:39:10PM -0500, Marth64 wrote:
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> Changelog | 2 +-
> doc/demuxers.texi | 29 ++++++++
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/rcwtdec.c | 148 +++++++++++++++++++++++++++++++++++++++
> 5 files changed, 180 insertions(+), 1 deletion(-)
> create mode 100644 libavformat/rcwtdec.c
[...]
> +static int rcwt_probe(const AVProbeData *p)
> +{
> + return p->buf_size > RCWT_HEADER_SIZE &&
> + AV_RB16(p->buf) == 0xCCCC && AV_RB8(p->buf + 2) == 0xED ? 50 : 0;
> +}
this fails
tools/probetest 256 4096
Failure of rcwt probing code with score=50 type=2 p=F01 size=16
can you make the test more robust ?
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The worst form of inequality is to try to make unequal things equal.
-- Aristotle
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-19 21:41 ` [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer Michael Niedermayer
@ 2024-03-19 22:07 ` Marth64
0 siblings, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-19 22:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Yes, v6 is on the way with fix (validated working with probetest parameters
above). I can check the format version, of which there is only 1 known
version.
Thanks for catching this.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
` (3 preceding siblings ...)
2024-03-19 21:41 ` [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer Michael Niedermayer
@ 2024-03-20 14:11 ` Stefano Sabatini
4 siblings, 0 replies; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-20 14:11 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-19 12:39:10 -0500, Marth64 wrote:
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> Changelog | 2 +-
> doc/demuxers.texi | 29 ++++++++
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/rcwtdec.c | 148 +++++++++++++++++++++++++++++++++++++++
> 5 files changed, 180 insertions(+), 1 deletion(-)
> create mode 100644 libavformat/rcwtdec.c
>
> diff --git a/Changelog b/Changelog
> index e3ca52430c..be871f75cd 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -19,7 +19,7 @@ version <next>:
> - lavu/eval: introduce randomi() function in expressions
> - VVC decoder
> - fsync filter
> -- Raw Captions with Time (RCWT) closed caption muxer
> +- Raw Captions with Time (RCWT) closed caption muxer and demuxer
> - ffmpeg CLI -bsf option may now be used for input as well as output
> - ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
> to -opt <contents of file <path>>
> diff --git a/doc/demuxers.texi b/doc/demuxers.texi
> index b70f3a38d7..26d4ba18a1 100644
> --- a/doc/demuxers.texi
> +++ b/doc/demuxers.texi
> @@ -1038,6 +1038,35 @@ the command:
> ffplay -f rawvideo -pixel_format rgb24 -video_size 320x240 -framerate 10 input.raw
> @end example
>
> +@anchor{rcwtdec}
> +@section rcwt
> +
> +RCWT (Raw Captions With Time) is a format native to ccextractor, a commonly
> +used open source tool for processing 608/708 Closed Captions (CC) sources.
> +It can be used to archive the original, raw CC bitstream and to produce
> +a source file for later CC processing or conversion. This demuxer can process
> +RCWT sources created by ccextractor or FFmpeg. For more information on the format,
> +see @ref{rcwtenc,,,ffmpeg-formats}.
> +
> +This demuxer implements the specification as of March 2024, which has
> +been stable and unchanged since April 2014.
> +
> +@subsection Examples
> +
> +@itemize
> +@item
> +Render Closed Captions to ASSA (using FFmpeg's CC decoder):
ASS ??
> +@example
> +ffmpeg -i CC.rcwt.bin CC.ass
> +@end example
> +
> +@item
> +Convert an RCWT backup to SCC:
for the sake of exclicitness, I'd avoid more acronyms, I'd guess this
is source Closed Caption?
[...]
Looks good to me otherwise, thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer Marth64
@ 2024-03-20 14:13 ` Stefano Sabatini
0 siblings, 0 replies; 30+ messages in thread
From: Stefano Sabatini @ 2024-03-20 14:13 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
On date Tuesday 2024-03-19 12:39:13 -0500, Marth64 wrote:
> Signed-off-by: Marth64 <marth64@proxyid.net>
> ---
> doc/indevs.texi | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index d1b2bacf8b..fc14737181 100644
> --- a/doc/indevs.texi
> +++ b/doc/indevs.texi
> @@ -1069,9 +1069,9 @@ ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]"
> @end example
>
> @item
> -Dump decoded frames to images and closed captions to a file (experimental):
> +Dump decoded frames to images and Closed Captions to an RCWT backup:
> @example
> -ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy -f rawvideo subcc.bin
> +ffmpeg -f lavfi -i "movie=test.ts[out0+subcc]" -map v frame%08d.png -map s -c copy subcc.bin
> @end example
Other patches look good as well. Once you update the first one, we can
wait a few more days for comments and eventually apply them.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
2024-03-12 11:00 ` Stefano Sabatini
@ 2024-03-28 9:29 ` Anton Khirnov
2024-03-28 15:41 ` Marth64
1 sibling, 1 reply; 30+ messages in thread
From: Anton Khirnov @ 2024-03-28 9:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Marth64
Quoting Marth64 (2024-03-12 07:00:00)
> In MPEG-2 user data, there can be different types of Closed Captions
> formats embedded (A53, SCTE-20, or DVD). The current behavior of the
> CC extraction code in the MPEG-2 decoder is to not be aware of
> multiple formats if multiple exist, therefore allowing one format
> to overwrite the other during the extraction process since the CC
> extraction shares one output buffer for the normalized bytes.
>
> This causes sources that have two CC formats to produce flawed output.
> There exist real-world samples which contain both A53 and SCTE-20 captions
> in the same MPEG-2 stream, and that manifest this problem. Example of symptom:
> THANK YOU (expected) --> THTHANANK K YOYOUU (actual)
>
> The solution is to pick only the first CC substream observed with valid bytes,
> and ignore the other types. Additionally, provide an option for users
> to manually "force" a type in the event that this matters for a particular
> source.
Is it not possible to extract all of them simultaneously?
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream
2024-03-28 9:29 ` Anton Khirnov
@ 2024-03-28 15:41 ` Marth64
0 siblings, 0 replies; 30+ messages in thread
From: Marth64 @ 2024-03-28 15:41 UTC (permalink / raw)
To: FFmpeg development discussions and patches, Marth64
>Is it not possible to extract all of them simultaneously?
Each of the extractable CC bitstreams would need to be exposed as an
independent eia608 AVStream, because each represents a distinct stream.
They can’t be commingled (which is what this patch addressed). I’m not sure
of a way to sanely present multiple eia608 streams to the end user.
AVStreamGroup gives me hope for the future, but I can’t think of a
technique in present day.
This is because: as it stands now the only way I know of to open a context
on an mpeg2/h26x source with an eia608 AVStream exposed is via the lavfi
movie=in[out+subcc] technique - but that only exposes one stream.
I guess the subcc keyword in the filter can be expanded to expose multiple
bitstreams, even via AVStreamGroup, but user would have to be aware and
opt-in. Otherwise it could get confusing. How would the user easily know
which bitstreams are in the source file? We can probe this to some extent,
but what if the eia608 bytes don’t show until halfway through the source?
Open to ideas, thoughts, as I’m gathering my own on this in a notebook over
the past few weeks.
Respectfully,
Marth64
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2024-03-28 15:41 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-12 5:59 [FFmpeg-devel] [PATCH v3 0/6] Closed Captions improvements (phase 1) Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 1/6] avcodec/mpeg12dec: extract only one type of CC substream Marth64
2024-03-12 11:00 ` Stefano Sabatini
2024-03-12 11:52 ` Andreas Rheinhardt
2024-03-28 9:29 ` Anton Khirnov
2024-03-28 15:41 ` Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 2/6] avcodec/ccaption_dec: don't print multiple \an and \pos tags Marth64
2024-03-12 13:49 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 3/6] avcodec/ccaption_dec: ignore leading non-breaking spaces Marth64
2024-03-12 13:50 ` Stefano Sabatini
2024-03-17 4:27 ` Marth64
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 4/6] avcodec/rcwtenc: canonize name and refresh documentation Marth64
2024-03-12 13:52 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 5/6] avformat/rcwtdec: add RCWT Closed Captions demuxer Marth64
2024-03-12 11:44 ` Andreas Rheinhardt
2024-03-12 14:12 ` Marth64
2024-03-17 4:29 ` [FFmpeg-devel] [PATCH v4] " Marth64
2024-03-18 20:12 ` Marth64
2024-03-19 14:35 ` Stefano Sabatini
2024-03-19 15:55 ` Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 1/4] " Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 2/4] avformat/rcwtenc: remove repeated documentation Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 3/4] doc/muxers: refresh and simplify RCWT muxer documentation Marth64
2024-03-19 17:39 ` [FFmpeg-devel] [PATCH v5 4/4] doc/indevs: update CC extraction example to use RCWT muxer Marth64
2024-03-20 14:13 ` Stefano Sabatini
2024-03-19 21:41 ` [FFmpeg-devel] [PATCH v5 1/4] avformat/rcwtdec: add RCWT Closed Captions demuxer Michael Niedermayer
2024-03-19 22:07 ` Marth64
2024-03-20 14:11 ` Stefano Sabatini
2024-03-12 6:00 ` [FFmpeg-devel] [PATCH v3 6/6] avformat/sccdec: remove unused bprint.h include Marth64
2024-03-12 13:53 ` Stefano Sabatini
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git