On 01/03/2015 08:40 PM, Michael Niedermayer wrote: > On Sat, Jan 03, 2015 at 12:57:04PM +0530, Anshul wrote: >> On 01/03/2015 01:42 AM, Michael Niedermayer wrote: >>> On Wed, Dec 31, 2014 at 07:09:33PM +0530, Anshul wrote: > [..] >> Makefile | 1 >> allcodecs.c | 1 >> ccaption_dec.c | 361 >> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 363 insertions(+) >> 54d4896ef8724994e1022eec6a9c79d0cddec29d >> 0001-Adding-Closed-caption-Support.patch >> From 17a564409b84fc18293833cc3f2151792209bb8b Mon Sep 17 00:00:00 2001 >> From: Anshul Maheshwari <anshul.ffm...@gmail.com> >> Date: Sat, 3 Jan 2015 12:40:35 +0530 >> Subject: [PATCH 1/2] Adding Closed caption Support >> >> Signed-off-by: Anshul Maheshwari <anshul.ffm...@gmail.com> >> >> To test Closed caption use following command >> /ffmpeg -f lavfi -i >> "movie=/home/a141982112/test_videos/Starship_Troopers.vob[out0+subcc]" -map >> s some.srt >> --- >> libavcodec/Makefile | 1 + >> libavcodec/allcodecs.c | 1 + >> libavcodec/ccaption_dec.c | 361 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 363 insertions(+) >> create mode 100644 libavcodec/ccaption_dec.c >> >> diff --git a/libavcodec/Makefile b/libavcodec/Makefile >> index 107661b..33051c4 100644 >> --- a/libavcodec/Makefile >> +++ b/libavcodec/Makefile >> @@ -173,6 +173,7 @@ OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o >> OBJS-$(CONFIG_C93_DECODER) += c93.o >> OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ >> cavsdata.o mpeg12data.o >> +OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o >> OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o >> OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o >> OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o >> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c >> index 8ceee2f..ef77dec 100644 >> --- a/libavcodec/allcodecs.c >> +++ b/libavcodec/allcodecs.c >> @@ -481,6 +481,7 @@ void avcodec_register_all(void) >> /* subtitles */ >> REGISTER_ENCDEC (SSA, ssa); >> REGISTER_ENCDEC (ASS, ass); >> + REGISTER_DECODER(CCAPTION, ccaption); >> REGISTER_ENCDEC (DVBSUB, dvbsub); >> REGISTER_ENCDEC (DVDSUB, dvdsub); >> REGISTER_DECODER(JACOSUB, jacosub); >> diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c >> new file mode 100644 >> index 0000000..d351efe >> --- /dev/null >> +++ b/libavcodec/ccaption_dec.c >> @@ -0,0 +1,361 @@ >> +/* >> + * Closed Caption Decoding >> + * Copyright (c) 2014 Anshul Maheshwari >> + * >> + * 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 >> + */ >> + >> +#include "avcodec.h" >> +#include "ass.h" >> +#include "libavutil/opt.h" >> + >> +#undef CHAR_DEBUG >> +#define SCREEN_ROWS 15 >> +#define SCREEN_COLUMNS 32 >> + >> +#define SET_FLAG(var, val) ( var |= ( 1 << (val) ) ) >> +#define UNSET_FLAG(var, val) ( var &= ~( 1 << (val)) ) >> +#define CHECK_FLAG(var, val) ( (var) & (1 << (val) ) ) >> + >> +enum cc_mode { >> + CCMODE_POPON, >> + CCMODE_PAINTON, >> + CCMODE_ROLLUP_2, >> + CCMODE_ROLLUP_3, >> + CCMODE_ROLLUP_4, >> + CCMODE_TEXT, >> +}; >> + >> +struct Screen { >> + /* +1 is used to compensate null character of string */ >> + uint8_t characters[SCREEN_ROWS][SCREEN_COLUMNS+1]; >> + /* >> + * Bitmask of used rows; if a bit is not set, the >> + * corresponding row is not used. >> + * for setting row 1 use row | (0 << 1) >> + * for setting row 15 use row | (1 << 14) >> + */ >> + int16_t row_used; > you can use an array here, this would simplify the code and also > avoid the *_FLAG macros > > to check whether any row is used or not, It will have for loop for 15 rows, now row_used can be used directly in if and for loop to see whether any row is used or not.
In ccextractor we use array for it, but its more complicated. This version of closed caption decoder is not full fledged, we will need to use row_used in many more commands. >> +}; >> + >> + >> +typedef struct CCaptionSubContext { >> + AVClass *class; >> + int parity_table[256]; > this can be a static uint8_t table > I don't think static variable in structure are allowed in c language that is cpp thing. If you meant to remove that table from structure, then too its not efficient, we have to make parity table every time decode function is called. >> + int row_cnt; >> + struct Screen screen[2]; >> + int active_screen; >> + uint8_t cursor_row; >> + uint8_t cursor_column; >> + AVBPrint buffer; >> + int erase_display_memory; >> + int rollup; >> + enum cc_mode mode; >> + int64_t start_time; >> + /* visible screen time */ >> + int64_t startv_time; >> + int64_t end_time; >> + char prev_cmd[2]; >> + /* buffer to store pkt data */ >> + AVBufferRef *pktbuf; > as you memcopy the data each time, theres no need for a AVBufferRef > a simple uint8_t * would do the same > but i think not even that is needed, > all uses of the data go through process_cc608() it would be > very simply to strip one bit in the arguments there, so no rewriting > of the table would be needed > > [...] cant do that, for error resistance we need to escape 1st byte if parity does not match, for escaping I write 0x7f instead of whatever data is. Some closed caption insert-er don't care much for parity when they are not using the data. I was using AVBufferRef instead of uint8_t * , so that I don't have to take care for length, and length and data are in one context. and there is already lot of error handling is done while realloc, means I don't have to copy buffer pointer somewhere, if realloc fails. and in future if someone want to make data channel 1 and data channel 2 to be processed in parallel, then he may use reference thing too. still its my opinion, if you think uint8_t will have better performance, I will change it to that. >> +static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t >> pts) >> +{ >> + struct Screen *screen = get_writing_screen(ctx); >> + char *row = screen->characters[ctx->cursor_row] + ctx->cursor_column; >> + >> + SET_FLAG(screen->row_used,ctx->cursor_row); >> + >> + *row++ = hi; >> + ctx->cursor_column++; >> + if(lo) { >> + *row++ = lo; >> + ctx->cursor_column++; >> + } >> + *row = 0; > this code appears to lack validity checks on the column index Added in todo list, will do it while implementing backspace. > >> + /* reset prev command since character can repeat */ >> + ctx->prev_cmd[0] = 0; >> + ctx->prev_cmd[1] = 0; >> +#ifdef CHAR_DEBUG >> + av_log(ctx, AV_LOG_DEBUG,"(%c,%c)\n",hi,lo); >> +#endif >> +} >> +static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, >> uint8_t lo) >> +{ >> + int ret = 0; >> +#define COR3(var, with1, with2, with3) ( (var) == (with1) || (var) == >> (with2) || (var) == (with3) ) >> + if ( hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) { >> + /* ignore redundant command */ >> + } else if ( (hi == 0x10 && (lo >= 0x40 || lo <= 0x5f)) || >> + ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) >> ) { >> + handle_pac(ctx, hi, lo); >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x20 ) { >> + /* resume caption loading */ >> + ctx->mode = CCMODE_POPON; >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x25 ) { >> + ctx->rollup = 2; >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x26 ) { >> + ctx->rollup = 3; >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x27 ) { >> + ctx->rollup = 4; >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x29 ) { >> + /* resume direct captioning */ >> + ctx->mode = CCMODE_PAINTON; >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2C ) { >> + /* erase display memory */ >> + ret = handle_edm(ctx, pts); >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2D ) { >> + /* carriage return */ >> + ctx->row_cnt++; >> + if(ctx->row_cnt == ctx->rollup) { >> + ctx->row_cnt = 0; > this check appears insufficient to prevent the index fro getting > out of array > > rollup can be decresed below row_cnt if iam not missing something > done, changed to >= >> + ret = handle_edm(ctx, pts); >> + ctx->active_screen = !ctx->active_screen; >> + } >> + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2F ) { >> + /* end of caption */ >> + ret = handle_eoc(ctx, pts); >> + } else if (hi>=0x20) { >> + /* Standard characters (always in pairs) */ >> + handle_char(ctx, hi, lo, pts); >> + } else { >> + /* Ignoring all other non data code */ >> + } >> + >> + /* set prev command */ >> + ctx->prev_cmd[0] = hi; >> + ctx->prev_cmd[1] = lo; >> + >> +#undef COR3 >> + return ret; >> + >> +} >> +static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket >> *avpkt) >> +{ >> + CCaptionSubContext *ctx = avctx->priv_data; >> + AVSubtitle *sub = data; >> + uint8_t *bptr = NULL; >> + int len = avpkt->size; >> + int ret = 0; >> + int i; >> + >> + if ( ctx->pktbuf->size < len) { >> + ret = av_buffer_realloc(&ctx->pktbuf, len); >> + if(ret) >> + len = ctx->pktbuf->size; >> + } > [...] > > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel I have attached another patch set. -Anshul Maheswari
>From 7d3737a84b8475c1c5aae7dfc27e4f2b0dd59eeb Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari <anshul.ffm...@gmail.com> Date: Sun, 4 Jan 2015 20:13:06 +0530 Subject: [PATCH 1/2] Adding Closed caption Support Signed-off-by: Anshul Maheshwari <anshul.ffm...@gmail.com> To test Closed caption use following command ffmpeg -f lavfi -i "movie=/home/a141982112/test_videos/Starship_Troopers.vob[out0+subcc]" -map s some.srt --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/ccaption_dec.c | 367 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 369 insertions(+) create mode 100644 libavcodec/ccaption_dec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 107661b..33051c4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -173,6 +173,7 @@ OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o mpeg12data.o +OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8ceee2f..ef77dec 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -481,6 +481,7 @@ void avcodec_register_all(void) /* subtitles */ REGISTER_ENCDEC (SSA, ssa); REGISTER_ENCDEC (ASS, ass); + REGISTER_DECODER(CCAPTION, ccaption); REGISTER_ENCDEC (DVBSUB, dvbsub); REGISTER_ENCDEC (DVDSUB, dvdsub); REGISTER_DECODER(JACOSUB, jacosub); diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c new file mode 100644 index 0000000..7c44836 --- /dev/null +++ b/libavcodec/ccaption_dec.c @@ -0,0 +1,367 @@ +/* + * Closed Caption Decoding + * Copyright (c) 2014 Anshul Maheshwari + * + * 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 + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/opt.h" + +#undef CHAR_DEBUG +#define SCREEN_ROWS 15 +#define SCREEN_COLUMNS 32 + +#define SET_FLAG(var, val) ( var |= ( 1 << (val) ) ) +#define UNSET_FLAG(var, val) ( var &= ~( 1 << (val)) ) +#define CHECK_FLAG(var, val) ( (var) & (1 << (val) ) ) + +/* + * TODO list + * 1) check cursor column + */ +enum cc_mode { + CCMODE_POPON, + CCMODE_PAINTON, + CCMODE_ROLLUP_2, + CCMODE_ROLLUP_3, + CCMODE_ROLLUP_4, + CCMODE_TEXT, +}; + +struct Screen { + /* +1 is used to compensate null character of string */ + uint8_t characters[SCREEN_ROWS][SCREEN_COLUMNS+1]; + /* + * Bitmask of used rows; if a bit is not set, the + * corresponding row is not used. + * for setting row 1 use row | (0 << 1) + * for setting row 15 use row | (1 << 14) + */ + int16_t row_used; +}; + + +typedef struct CCaptionSubContext { + AVClass *class; + uint8_t parity_table[256]; + int row_cnt; + struct Screen screen[2]; + int active_screen; + uint8_t cursor_row; + uint8_t cursor_column; + AVBPrint buffer; + int erase_display_memory; + int rollup; + enum cc_mode mode; + int64_t start_time; + /* visible screen time */ + int64_t startv_time; + int64_t end_time; + char prev_cmd[2]; + /* buffer to store pkt data */ + AVBufferRef *pktbuf; +}CCaptionSubContext; + +static void build_parity_table(uint8_t *parity_table) +{ + unsigned int byte; + int parity_v; + for (byte = 0; byte <= 127; byte++) { + parity_v = av_popcount(byte) & 1; + parity_table[byte] = parity_v; + parity_table[byte | 0x80] = !parity_v; + } +} + +static av_cold int init_decoder(AVCodecContext *avctx) +{ + int ret; + CCaptionSubContext *ctx = avctx->priv_data; + + build_parity_table(ctx->parity_table); + av_bprint_init(&ctx->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + /* taking by default roll up to 2 */ + ctx->rollup = 2; + ret = ff_ass_subtitle_header_default(avctx); + /* allocate pkt buffer */ + ctx->pktbuf = av_buffer_alloc(128); + if( !ctx->pktbuf) { + ret = AVERROR(ENOMEM); + } + + + return ret; +} + +static av_cold int close_decoder(AVCodecContext *avctx) +{ + CCaptionSubContext *ctx = avctx->priv_data; + av_bprint_finalize( &ctx->buffer, NULL); + av_buffer_unref(&ctx->pktbuf); + return 0; +} + +/** + * 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. + */ +static int validate_cc_data_pair (uint8_t *cc_data_pair, uint8_t *parity_table) +{ + 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 (!parity_table[cc_data_pair[2]]) { + return AVERROR_INVALIDDATA; + } + if (!parity_table[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 + if(cc_type == 3 || cc_type == 2 ) + return AVERROR_PATCHWELCOME; + + /* remove parity bit */ + cc_data_pair[1] &= 0x7F; + cc_data_pair[2] &= 0x7F; + + + return 0; + +} +static void handle_pac( CCaptionSubContext *ctx, uint8_t hi, uint8_t lo ) +{ + static const int8_t row_map[] = { + 11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10 + }; + const int index = ( (hi<<1) & 0x0e) | ( (lo>>5) & 0x01 ); + + if( row_map[index] <= 0 ) + return; + + ctx->cursor_row = row_map[index] - 1; + ctx->cursor_column = 0; + +} + +/** + * @param pts it is required to set end time + */ +static int handle_edm(CCaptionSubContext *ctx,int64_t pts) +{ + int i; + int ret = 0; + struct Screen *screen = ctx->screen + ctx->active_screen; + + ctx->start_time = ctx->startv_time; + for( i = 0; screen->row_used && i < SCREEN_ROWS; i++) + { + if(CHECK_FLAG(screen->row_used,i)) { + av_bprint_append_data(&ctx->buffer, screen->characters[i], strlen(screen->characters[i])); + av_bprint_append_data(&ctx->buffer, "\\N",2); + UNSET_FLAG(screen->row_used, i); + ret = av_bprint_is_complete(&ctx->buffer); + if( ret) { + ret = AVERROR(ENOMEM); + break; + } + } + + } + ctx->startv_time = pts; + ctx->erase_display_memory = 1; + ctx->end_time = pts; + return ret; +} +static int handle_eoc(CCaptionSubContext *ctx, int64_t pts) +{ + int ret; + ret = handle_edm(ctx,pts); + ctx->active_screen = !ctx->active_screen; + return ret; +} +static struct Screen *get_writing_screen(CCaptionSubContext *ctx) +{ + switch (ctx->mode) { + case CCMODE_POPON: + // use Inactive screen + return ctx->screen + !ctx->active_screen; + case CCMODE_PAINTON: + case CCMODE_ROLLUP_2: + case CCMODE_ROLLUP_3: + case CCMODE_ROLLUP_4: + case CCMODE_TEXT: + // use active screen + return ctx->screen + ctx->active_screen; + } + /* It was never an option */ + return NULL; +} +static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts) +{ + struct Screen *screen = get_writing_screen(ctx); + char *row = screen->characters[ctx->cursor_row] + ctx->cursor_column; + + SET_FLAG(screen->row_used,ctx->cursor_row); + + *row++ = hi; + ctx->cursor_column++; + if(lo) { + *row++ = lo; + ctx->cursor_column++; + } + *row = 0; + /* reset prev command since character can repeat */ + ctx->prev_cmd[0] = 0; + ctx->prev_cmd[1] = 0; +#ifdef CHAR_DEBUG + av_log(ctx, AV_LOG_DEBUG,"(%c,%c)\n",hi,lo); +#endif +} +static int process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo) +{ + int ret = 0; +#define COR3(var, with1, with2, with3) ( (var) == (with1) || (var) == (with2) || (var) == (with3) ) + if ( hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) { + /* ignore redundant command */ + } else if ( (hi == 0x10 && (lo >= 0x40 || lo <= 0x5f)) || + ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) { + handle_pac(ctx, hi, lo); + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x20 ) { + /* resume caption loading */ + ctx->mode = CCMODE_POPON; + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x25 ) { + ctx->rollup = 2; + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x26 ) { + ctx->rollup = 3; + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x27 ) { + ctx->rollup = 4; + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x29 ) { + /* resume direct captioning */ + ctx->mode = CCMODE_PAINTON; + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2C ) { + /* erase display memory */ + ret = handle_edm(ctx, pts); + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2D ) { + /* carriage return */ + ctx->row_cnt++; + if(ctx->row_cnt >= ctx->rollup) { + ctx->row_cnt = 0; + ret = handle_edm(ctx, pts); + ctx->active_screen = !ctx->active_screen; + } + } else if ( COR3(hi, 0x14, 0x15, 0x1C) && lo == 0x2F ) { + /* end of caption */ + ret = handle_eoc(ctx, pts); + } else if (hi>=0x20) { + /* Standard characters (always in pairs) */ + handle_char(ctx, hi, lo, pts); + } else { + /* Ignoring all other non data code */ + } + + /* set prev command */ + ctx->prev_cmd[0] = hi; + ctx->prev_cmd[1] = lo; + +#undef COR3 + return ret; + +} +static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt) +{ + CCaptionSubContext *ctx = avctx->priv_data; + AVSubtitle *sub = data; + uint8_t *bptr = NULL; + int len = avpkt->size; + int ret = 0; + int i; + + if ( ctx->pktbuf->size < len) { + ret = av_buffer_realloc(&ctx->pktbuf, len); + if(ret) + len = ctx->pktbuf->size; + } + memcpy(ctx->pktbuf->data, avpkt->data, len); + bptr = ctx->pktbuf->data; + + + for (i = 0; i < len; i += 3) { + uint8_t cc_type = *(bptr + i) & 3; + if (validate_cc_data_pair( bptr + i, ctx->parity_table ) ) + continue; + /* ignoring data field 1 */ + if(cc_type == 1) + continue; + else + process_cc608(ctx, avpkt->pts, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f); + } + if(ctx->erase_display_memory && *ctx->buffer.str) + { + int start_time = av_rescale_q(ctx->start_time, avctx->time_base, (AVRational){ 1, 100 }); + int end_time = av_rescale_q(ctx->end_time, avctx->time_base, (AVRational){ 1, 100 }); +#ifdef CHAR_DEBUG + av_log(ctx, AV_LOG_DEBUG,"cdp writing data (%s)\n",ctx->buffer.str); +#endif + ret = ff_ass_add_rect(sub, ctx->buffer.str, start_time, end_time - start_time , 0); + if (ret < 0) + return ret; + sub->pts = av_rescale_q(ctx->start_time, avctx->time_base, AV_TIME_BASE_Q); + ctx->erase_display_memory = 0; + av_bprint_clear(&ctx->buffer); + } + + *got_sub = sub->num_rects > 0; + return 0; +} +static const AVOption options[] = { + {NULL} +}; +static const AVClass ccaption_dec_class = { + .class_name = "Closed caption Decoder", + .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) Decoder"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_EIA_608, + .priv_data_size = sizeof(CCaptionSubContext), + .init = init_decoder, + .close = close_decoder, + .decode = decode, + .priv_class = &ccaption_dec_class, +}; -- 1.8.1.4
>From c69ae645d85e3d7b562d7d327f5218f7b47b4759 Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari <anshul.ffm...@gmail.com> Date: Sun, 4 Jan 2015 20:14:16 +0530 Subject: [PATCH 2/2] Adding Closed caption accessories Signed-off-by: Anshul Maheshwari <anshul.ffm...@gmail.com> --- Changelog | 1 + MAINTAINERS | 1 + libavcodec/version.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 37ce0f0..d4efd74 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ version <next>: - RTP/mpegts muxer - non continuous cache protocol support - tblend filter +- Closed caption Decoder version 2.5: diff --git a/MAINTAINERS b/MAINTAINERS index 6e46280..13b211e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -156,6 +156,7 @@ Codecs: celp_filters.* Vitor Sessak cinepak.c Roberto Togni cinepakenc.c Rl / Aetey G.T. AB + ccaption_dec.c Anshul Maheshwari cljr Alex Beregszaszi cllc.c Derek Buitenhuis cook.c, cookdata.h Benjamin Larsson diff --git a/libavcodec/version.h b/libavcodec/version.h index d8c891d..7e51f3b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 56 -#define LIBAVCODEC_VERSION_MINOR 19 +#define LIBAVCODEC_VERSION_MINOR 20 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- 1.8.1.4
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel