> > c9153590e5f167e41910d867639eb887164e28d2 > > 0001-closed-caption-decoder-accept-and-decode-a-new-codec.patch > > From bf29fe5330e83e37cf064b18918185c6b00d9b9f Mon Sep 17 00:00:00 2001 > > From: rogerdpack <rogerpack2...@gmail.com> > > Date: Tue, 28 Apr 2020 05:15:15 +0000 > > Subject: [PATCH 1/3] closed caption decoder: accept and decode a new codec > > type of 'raw 608 byte pairs' > > breaks fate > > TEST sub-cc-realtime > --- ./tests/ref/fate/sub-cc-realtime 2020-04-28 15:43:10.506887112 +0200 > +++ tests/data/fate/sub-cc-realtime 2020-04-28 19:31:37.164407976 +0200
OK I believe to have fixed that, see the latest attached. Plus a few more aesthetic cleanups to boot. Thanks!
From 5d7c12a3f703e794e1092087355bc9523d5f4d93 Mon Sep 17 00:00:00 2001 From: rogerdpack <rogerpack2005@gmail.com> Date: Tue, 28 Apr 2020 05:15:15 +0000 Subject: [PATCH 1/3] closed caption decoder: accept and decode a new codec type of 'raw 608 byte pairs' Signed-off-by: rogerdpack <rogerpack2005@gmail.com> --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/allcodecs.c | 1 + libavcodec/ccaption_dec.c | 116 ++++++++++++++++++++++++++------------ libavcodec/codec_desc.c | 7 +++ libavcodec/codec_id.h | 1 + libavcodec/version.h | 4 +- 7 files changed, 92 insertions(+), 40 deletions(-) diff --git a/configure b/configure index 080d93a129..8a0a6cce7c 100755 --- a/configure +++ b/configure @@ -2681,6 +2681,7 @@ bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs" binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs" cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp" +ccaption_raw_608_decoder_select="ccaption_decoder" clearvideo_decoder_select="idctdsp" cllc_decoder_select="bswapdsp" comfortnoise_encoder_select="lpc" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 28076c2c83..006eb40107 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -246,6 +246,7 @@ OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o +OBJS-$(CONFIG_CCAPTION_RAW_608_DECODER) += ccaption_dec.o ass.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDTOONS_DECODER) += cdtoons.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o @@ -463,7 +464,6 @@ OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o -OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 54d40ebdbc..b78f58cb4c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -645,6 +645,7 @@ extern AVCodec ff_ssa_decoder; extern AVCodec ff_ass_encoder; extern AVCodec ff_ass_decoder; extern AVCodec ff_ccaption_decoder; +extern AVCodec ff_ccaption_raw_608_decoder; extern AVCodec ff_dvbsub_encoder; extern AVCodec ff_dvbsub_decoder; extern AVCodec ff_dvdsub_encoder; diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index bf3563a0bc..a2197cd673 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -341,43 +341,51 @@ static void write_char(CCaptionSubContext *ctx, struct Screen *screen, char ch) } /** - * This function after validating parity bit, also remove it from data pair. - * The first byte doesn't pass parity, we replace it with a solid blank - * and process the pair. - * If the second byte doesn't pass parity, it returns INVALIDDATA - * user can ignore the whole pair and pass the other pair. + * This function accepts a byte pair [EIA 608 first byte, EIA 608 second byte] + * checks both for parity and strips parity on success. + * If the first byte doesn't pass parity, replace it with a solid blank + * and process the pair anyway. + * Returns failure for parity failure or "no data" (padding bytes). + */ +static int validate_eia_608_byte_pair(uint8_t *cc_data_pair) { + if (!av_parity(cc_data_pair[1])) { + return AVERROR_INVALIDDATA; + } + if (!av_parity(cc_data_pair[0])) { + cc_data_pair[0]=0x7F; // solid blank + } + if ((cc_data_pair[0] & 0x7F) == 0 && (cc_data_pair[1] & 0x7F) == 0) { + return AVERROR_INVALIDDATA; // padding bytes + } + /* remove parity bit */ + cc_data_pair[0] &= 0x7F; + cc_data_pair[1] &= 0x7F; + return 0; +} + +/** + * This function accepts "cc_data_pair" = [708 header byte, EIA 608 first byte, EIA 608 second byte] + * This function after validating parity bits, also removes parity bits them from 608 data pair. */ static int validate_cc_data_pair(uint8_t *cc_data_pair) { + int ret; uint8_t cc_valid = (*cc_data_pair & 4) >>2; uint8_t cc_type = *cc_data_pair & 3; if (!cc_valid) return AVERROR_INVALIDDATA; - // if EIA-608 data then verify parity. - if (cc_type==0 || cc_type==1) { - if (!av_parity(cc_data_pair[2])) { - return AVERROR_INVALIDDATA; - } - if (!av_parity(cc_data_pair[1])) { - cc_data_pair[1]=0x7F; - } - } - - //Skip non-data - if ((cc_data_pair[0] == 0xFA || cc_data_pair[0] == 0xFC || cc_data_pair[0] == 0xFD) - && (cc_data_pair[1] & 0x7F) == 0 && (cc_data_pair[2] & 0x7F) == 0) - return AVERROR_PATCHWELCOME; - - //skip 708 data + // skip 708 data, we only support "608 over 708" not native 708 if (cc_type == 3 || cc_type == 2) return AVERROR_PATCHWELCOME; - /* remove parity bit */ - cc_data_pair[1] &= 0x7F; - cc_data_pair[2] &= 0x7F; - + // Must be EIA-608 data, verify parity. + if (cc_type==0 || cc_type==1) { + if (ret = validate_eia_608_byte_pair(cc_data_pair + 1)) { + return ret; + } + } return 0; } @@ -756,6 +764,8 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp int len = avpkt->size; int ret = 0; int i; + int stride; + int raw_608 = avctx->codec_id == AV_CODEC_ID_EIA_608_RAW_BYTE_PAIRS; av_fast_padded_malloc(&ctx->pktbuf, &ctx->pktbuf_size, len); if (!ctx->pktbuf) { @@ -764,16 +774,28 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp } memcpy(ctx->pktbuf, avpkt->data, len); bptr = ctx->pktbuf; - - for (i = 0; i < len; i += 3) { - uint8_t cc_type = *(bptr + i) & 3; - if (validate_cc_data_pair(bptr + i)) - continue; - /* ignoring data field 1 */ - if(cc_type == 1) - continue; - else - process_cc608(ctx, start_time, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f); + if (raw_608) { + stride = 2; // expect 2 byte "per packet" + } else { + stride = 3; // eia 708 Closed caption data packet + } + for (i = 0; i < len; i += stride) { + if (raw_608) { + if (validate_eia_608_byte_pair(bptr)) { + continue; + } + process_cc608(ctx, start_time, *(bptr + i), *(bptr + i + 1)); + } else { + // look for 608 over 708 bytes + uint8_t cc_type = *(bptr + i) & 3; + if (validate_cc_data_pair(bptr + i)) + continue; + /* ignore NTSC_CC_FIELD_2 (cc_type 1) for now */ + if (cc_type == 1) + continue; + else + process_cc608(ctx, start_time, *(bptr + i + 1), *(bptr + i + 2)); + } if (!ctx->buffer_changed) continue; @@ -781,7 +803,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp if (*ctx->buffer.str || ctx->real_time) { - ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str); + ff_dlog(ctx, "writing data (%s)\n",ctx->buffer.str); ret = ff_ass_add_rect(sub, ctx->buffer.str, ctx->readorder++, 0, NULL, NULL); if (ret < 0) return ret; @@ -829,9 +851,16 @@ static const AVClass ccaption_dec_class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVClass ccaption_raw_608_dec_class = { + .class_name = "Closed caption Decoder Raw 608", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_ccaption_decoder = { .name = "cc_dec", - .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 / CEA-708)"), + .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 over CEA-708)"), .type = AVMEDIA_TYPE_SUBTITLE, .id = AV_CODEC_ID_EIA_608, .priv_data_size = sizeof(CCaptionSubContext), @@ -841,3 +870,16 @@ AVCodec ff_ccaption_decoder = { .decode = decode, .priv_class = &ccaption_dec_class, }; + +AVCodec ff_ccaption_raw_608_decoder = { + .name = "cc_raw_608_dec", + .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 raw byte pairs)"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_EIA_608_RAW_BYTE_PAIRS, + .priv_data_size = sizeof(CCaptionSubContext), + .init = init_decoder, + .close = close_decoder, + .flush = flush_decoder, + .decode = decode, + .priv_class = &ccaption_raw_608_dec_class, +}; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 93433b5a27..c0e32c57bc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3180,6 +3180,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("EIA-608 closed captions"), .props = AV_CODEC_PROP_TEXT_SUB, }, + { + .id = AV_CODEC_ID_EIA_608_RAW_BYTE_PAIRS, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "eia_608_raw_byte_pairs", + .long_name = NULL_IF_CONFIG_SMALL("EIA-608 closed captions raw byte pairs"), + .props = AV_CODEC_PROP_TEXT_SUB, + }, { .id = AV_CODEC_ID_JACOSUB, .type = AVMEDIA_TYPE_SUBTITLE, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index e7d6e059db..805e18758b 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -513,6 +513,7 @@ enum AVCodecID { AV_CODEC_ID_MICRODVD = 0x17800, AV_CODEC_ID_EIA_608, + AV_CODEC_ID_EIA_608_RAW_BYTE_PAIRS, AV_CODEC_ID_JACOSUB, AV_CODEC_ID_SAMI, AV_CODEC_ID_REALTEXT, diff --git a/libavcodec/version.h b/libavcodec/version.h index 3de16c884c..552129e0a3 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 82 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MINOR 83 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ -- 2.17.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-requ...@ffmpeg.org with subject "unsubscribe".