From b15f54c7f9341099859337fa3bca49b0a6b1151a Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Tue, 12 Aug 2014 10:43:07 +0530 Subject: [PATCH 1/4] Intigration of ffmpeg in ccextractor --- linux/Makefile | 9 +++ src/ccextractor.c | 46 +++++++++++++++ src/ffmpeg_intgr.c | 144 +++++++++++++++++++++++++++++++++++++++++++++ src/ffmpeg_intgr.h | 22 +++++++ 4 files changed, 221 insertions(+) create mode 100644 src/ffmpeg_intgr.c create mode 100644 src/ffmpeg_intgr.h diff --git a/linux/Makefile b/linux/Makefile index 13743688..3451f446 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -39,6 +39,15 @@ CFLAGS+=-I/usr/local/include/tesseract -I/usr/local/include/leptonica CFLAGS+=-DENABLE_OCR LDFLAGS+= $(shell pkg-config --libs tesseract) endif +ifeq ($(ENABLE_FFMPEG),yes) +CFLAGS+=-DENABLE_FFMPEG +CFLAGS+= $(shell pkg-config --libs libavcodec) +CFLAGS+= $(shell pkg-config --libs libavformat) +CFLAGS+= $(shell pkg-config --libs libavutil) +LDFLAGS+= $(shell pkg-config --libs libavcodec ) +LDFLAGS+= $(shell pkg-config --libs libavformat ) +LDFLAGS+= $(shell pkg-config --libs libavutil ) +endif .PHONY: all all: objs_dir $(TARGET) diff --git a/src/ccextractor.c b/src/ccextractor.c index 7d938eb4..0aaa0f94 100644 --- a/src/ccextractor.c +++ b/src/ccextractor.c @@ -8,6 +8,7 @@ License: GPL 2.0 #include "cc_encoders_common.h" #include #include +#include "ffmpeg_intgr.h" void xds_cea608_test(); @@ -249,6 +250,7 @@ int main(int argc, char *argv[]) char *c; struct encoder_ctx enc_ctx[2]; struct cc_subtitle dec_sub; + void *ffmpeg_ctx = NULL; // Initialize some constants init_ts(); @@ -611,6 +613,50 @@ int main(int argc, char *argv[]) while (switch_to_next_file(0) && !processed_enough) { +#ifdef ENABLE_FFMPEG + ffmpeg_ctx = init_ffmpeg(inputfile[0]); + if(ffmpeg_ctx) + { + int i =0; + buffer = malloc(1024); + if(!buffer) + { + mprint("no memory left\n"); + break; + } + do + { + int ret = 0; + char *bptr = buffer; + int len = ff_get_ccframe(ffmpeg_ctx, bptr, 1024); + if(len == AVERROR(EAGAIN)) + { + continue; + } + else if(len == 0) + continue; + else if(len < 0 ) + { + mprint("Some Error \n"); + break; + + } + store_hdcc(bptr,len, i,i++,&dec_sub); + if(dec_sub.got_output) + { + encode_sub(enc_ctx, &dec_sub); + dec_sub.got_output = 0; + } + }while(1); + + free(buffer); + continue; + } + else + { + mprint ("\rFailed to initialized ffmpeg falling back to legacy\n"); + } +#endif prepare_for_new_file(); if (auto_stream == CCX_SM_AUTODETECT) diff --git a/src/ffmpeg_intgr.c b/src/ffmpeg_intgr.c new file mode 100644 index 00000000..02b983db --- /dev/null +++ b/src/ffmpeg_intgr.c @@ -0,0 +1,144 @@ +#include "ffmpeg_intgr.h" + +#ifdef ENABLE_FFMPEG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ffmpeg_ctx +{ + AVFormatContext *ifmt; + AVCodecContext *dec_ctx; + AVFrame *frame; + int stream_index; +}; +/** + * @path this path could be relative or absolute path of static file + * this path could be path of device + * + * @return ctx Context of ffmpeg + */ +void *init_ffmpeg(char *path) +{ + int ret = 0; + int stream_index = 0; + struct ffmpeg_ctx *ctx; + AVCodec *dec = NULL; + avcodec_register_all(); + av_register_all(); + + ctx = av_malloc(sizeof(*ctx)); + if(!ctx) + { + av_log(NULL,AV_LOG_ERROR,"Not enough memory\n"); + return NULL; + } + /** + * Initialize decoder according to the name of input + */ + ret = avformat_open_input(&ctx->ifmt, path, NULL, NULL); + if(ret < 0) + { + av_log(NULL,AV_LOG_ERROR,"could not open input(%s) format\n",path); + goto fail; + } + + ret = avformat_find_stream_info(ctx->ifmt,NULL); + if(ret < 0) + { + av_log(NULL,AV_LOG_ERROR,"could not find any stream\n"); + goto fail; + } + + /* first search in strean if not found search the video stream */ + ret = av_find_best_stream(ctx->ifmt, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); + if (ret < 0) + { + av_log(NULL, AV_LOG_ERROR, "no suitable subtitle or caption\n"); + goto fail; + } + stream_index = ret; + ctx->dec_ctx = ctx->ifmt->streams[stream_index]->codec; + ctx->stream_index = stream_index; + ret = avcodec_open2(ctx->dec_ctx, dec, NULL); + if(ret < 0) + { + av_log(NULL,AV_LOG_ERROR,"unable to open codec\n"); + goto fail; + } + + //Initialize frame where input frame will be stored + ctx->frame = av_frame_alloc(); + +fail: + return ctx; +} +/** + * @param ctx context of ffmpeg + * @param data preallocated buffer where data will be recieved + * @param maxlen length of buffer, where data will be copied + * @return number of bytes recieved as data + */ +int ff_get_ccframe(void *arg,char*data,int maxlen) +{ + struct ffmpeg_ctx *ctx = arg; + int len = 0; + int ret = 0; + int got_frame; + AVPacket packet; + + ret = av_read_frame(ctx->ifmt, &packet); + if(ret == AVERROR_EOF) + { + return ret; + } + else if(ret < 0) + { + av_log(NULL, AV_LOG_ERROR, "not able to read the packet\n"); + return ret; + } + else if(packet.stream_index != ctx->stream_index) + { + return AVERROR(EAGAIN); + } + + ret = avcodec_decode_video2(ctx->dec_ctx,ctx->frame, &got_frame,&packet); + if(ret < 0) + { + av_log(NULL,AV_LOG_ERROR,"unable to decode packet\n"); + } + else if (!got_frame) + { + return AVERROR(EAGAIN); + } + for(int i = 0;i< ctx->frame->nb_side_data;i++) + { + if(ctx->frame->side_data[i]->type == AV_FRAME_DATA_A53_CC) + { + if(ctx->frame->side_data[i]->size > maxlen) + av_log(NULL,AV_LOG_ERROR,"Please consider increaing length of data\n"); + else + { + memcpy(data,ctx->frame->side_data[i]->data,ctx->frame->side_data[i]->size); + len = ctx->frame->side_data[i]->size; + + } + } + } + + + if(ret < 0) + return ret; + + return len; +} + +#endif diff --git a/src/ffmpeg_intgr.h b/src/ffmpeg_intgr.h new file mode 100644 index 00000000..964e4d26 --- /dev/null +++ b/src/ffmpeg_intgr.h @@ -0,0 +1,22 @@ +#ifndef _FFMPEG_INTIGRATION +#define _FFMPEG_INTIGRATION + +#ifdef ENABLE_FFMPEG +#include "libavutil/error.h" +#endif +/** + * @path this path could be relative or absolute path of static file + * this path could be path of device + * + * @return ctx Context of ffmpeg + */ +void *init_ffmpeg(char *path); + +/** + * @param ctx context of ffmpeg + * @param data preallocated buffer where data will be recieved + * @param maxlen length of buffer, where data will be copied + * @return number of bytes recieved as data + */ +int ff_get_ccframe(void *arg,char*data,int maxlen); +#endif From 5789a0a22409701f69b759f37a27520c6fdf6055 Mon Sep 17 00:00:00 2001 From: cfsmp3 Date: Tue, 12 Aug 2014 17:15:39 +0200 Subject: [PATCH 2/4] Updated MD --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fd2d585..b6b1366e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,12 @@ ccextractor CCExtractor - Carlos' version (mainstream). -0.71 +GSOC - 0.72 +----------- +- Fix for WTV files with incorrect timing +- Added support for fps change using data from AVC video track in a H264 TS file. + +GSOC - 0.71 ----------- - Added feature to receive captions in BIN format according to CCExtractor's own protocol over TCP (-tcp port [-tcppassword password]) From 47bfe6bffc91eea4db39c0032d35cf64c6db838e Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Wed, 13 Aug 2014 17:48:00 +0530 Subject: [PATCH 3/4] corrected timing for tudor using ffmpeg --- src/608_srt.c | 4 +++- src/ccextractor.c | 10 +++++++--- src/ffmpeg_intgr.c | 47 ++++++++++++++++++++++++++++++++++++++++++++-- src/ffmpeg_intgr.h | 1 + src/sequencing.c | 4 ++-- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/608_srt.c b/src/608_srt.c index 738dcc9d..a035b3fb 100644 --- a/src/608_srt.c +++ b/src/608_srt.c @@ -86,11 +86,13 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context) char*str = NULL; #endif int used; + LLONG ms_start, ms_end; +#ifdef ENABLE_OCR unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; - LLONG ms_start, ms_end; char timeline[128]; int len = 0; +#endif x_pos = -1; y_pos = -1; diff --git a/src/ccextractor.c b/src/ccextractor.c index 0aaa0f94..9099dc3d 100644 --- a/src/ccextractor.c +++ b/src/ccextractor.c @@ -613,7 +613,9 @@ int main(int argc, char *argv[]) while (switch_to_next_file(0) && !processed_enough) { + prepare_for_new_file(); #ifdef ENABLE_FFMPEG + close_input_file(); ffmpeg_ctx = init_ffmpeg(inputfile[0]); if(ffmpeg_ctx) { @@ -628,20 +630,23 @@ int main(int argc, char *argv[]) { int ret = 0; char *bptr = buffer; + memset(bptr,0,1024); int len = ff_get_ccframe(ffmpeg_ctx, bptr, 1024); if(len == AVERROR(EAGAIN)) { continue; } + else if(len == AVERROR_EOF) + break; else if(len == 0) continue; else if(len < 0 ) { - mprint("Some Error \n"); + mprint("Error extracting Frame\n"); break; } - store_hdcc(bptr,len, i,i++,&dec_sub); + store_hdcc(bptr,len, i++,fts_now,&dec_sub); if(dec_sub.got_output) { encode_sub(enc_ctx, &dec_sub); @@ -657,7 +662,6 @@ int main(int argc, char *argv[]) mprint ("\rFailed to initialized ffmpeg falling back to legacy\n"); } #endif - prepare_for_new_file(); if (auto_stream == CCX_SM_AUTODETECT) { diff --git a/src/ffmpeg_intgr.c b/src/ffmpeg_intgr.c index 02b983db..193fc21e 100644 --- a/src/ffmpeg_intgr.c +++ b/src/ffmpeg_intgr.c @@ -13,6 +13,7 @@ #include #include +#include "ccextractor.h" struct ffmpeg_ctx { AVFormatContext *ifmt; @@ -20,6 +21,37 @@ struct ffmpeg_ctx AVFrame *frame; int stream_index; }; +/** + * call back function to be registered for avlog + */ +static void log_cb(void* ptr, int level, const char* fmt, va_list vl) +{ + if (level > av_log_get_level()) + return; + + const char*name = NULL; + FILE *flog; + + if (ccx_options.messages_target==CCX_MESSAGES_STDOUT) + flog = stdout; + else + flog = stderr; + + if (level == AV_LOG_PANIC) + fprintf(flog, "[panic][%s] ", name); + else if (level == AV_LOG_FATAL) + fprintf(flog, "[fatal][%s] ", name); + else if (level == AV_LOG_ERROR) + fprintf(flog, "[error][%s] ", name); + else if (level == AV_LOG_WARNING) + fprintf(flog, "[warning][%s] ", name); + else if (level == AV_LOG_INFO) + fprintf(flog, "[info][%s] ", name); + else if (level == AV_LOG_DEBUG) + fprintf(flog, "[debug][%s] ", name); + + vfprintf(flog, fmt, vl); +} /** * @path this path could be relative or absolute path of static file * this path could be path of device @@ -35,6 +67,13 @@ void *init_ffmpeg(char *path) avcodec_register_all(); av_register_all(); + if(ccx_options.debug_mask & CCX_DMT_VERBOSE) + av_log_set_level(AV_LOG_INFO); + else if (ccx_options.messages_target == 0) + av_log_set_level(AV_LOG_FATAL); + + av_log_set_callback(log_cb); + ctx = av_malloc(sizeof(*ctx)); if(!ctx) { @@ -119,12 +158,17 @@ int ff_get_ccframe(void *arg,char*data,int maxlen) { return AVERROR(EAGAIN); } + current_pts = av_frame_get_best_effort_timestamp(ctx->frame); + if(!pts_set) + pts_set = 1; + set_fts(); for(int i = 0;i< ctx->frame->nb_side_data;i++) { if(ctx->frame->side_data[i]->type == AV_FRAME_DATA_A53_CC) { + ctx->frame->pts = av_frame_get_best_effort_timestamp(ctx->frame); if(ctx->frame->side_data[i]->size > maxlen) - av_log(NULL,AV_LOG_ERROR,"Please consider increaing length of data\n"); + av_log(NULL,AV_LOG_ERROR,"Please consider increasing length of data\n"); else { memcpy(data,ctx->frame->side_data[i]->data,ctx->frame->side_data[i]->size); @@ -140,5 +184,4 @@ int ff_get_ccframe(void *arg,char*data,int maxlen) return len; } - #endif diff --git a/src/ffmpeg_intgr.h b/src/ffmpeg_intgr.h index 964e4d26..efc963d9 100644 --- a/src/ffmpeg_intgr.h +++ b/src/ffmpeg_intgr.h @@ -2,6 +2,7 @@ #define _FFMPEG_INTIGRATION #ifdef ENABLE_FFMPEG +#include "libavutil/common.h" #include "libavutil/error.h" #endif /** diff --git a/src/sequencing.c b/src/sequencing.c index f95edbdd..bdef978b 100644 --- a/src/sequencing.c +++ b/src/sequencing.c @@ -204,8 +204,8 @@ int do_cb (unsigned char *cc_block, struct cc_subtitle *sub) return 1; // Print raw data with FTS. - dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%02X:%02X", print_mstime(fts_now + fts_global),in_xds_mode, - cc_block[0], cc_block[1], cc_block[2]); + dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(fts_now + fts_global),in_xds_mode, + cc_block[0], cc_block[1]&0x7f,cc_block[2]&0x7f, cc_block[2]); /* In theory the writercwtdata() function could return early and not * go through the 608/708 cases below. We do that to get accurate From 918889c890da23ce6df43e8ef5541b85d008968e Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Thu, 14 Aug 2014 20:45:38 +0530 Subject: [PATCH 4/4] corrected timing in spupng xml file --- src/dvb_subtitle_decoder.c | 1 + src/spupng_encoder.c | 5 ++++- src/ts_tables.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dvb_subtitle_decoder.c b/src/dvb_subtitle_decoder.c index 76af7931..8256b5f0 100644 --- a/src/dvb_subtitle_decoder.c +++ b/src/dvb_subtitle_decoder.c @@ -1535,6 +1535,7 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct p = buf; p_end = buf + buf_size; + set_fts(); while (p_end - p >= 6 && *p == 0x0f) { p += 1; diff --git a/src/spupng_encoder.c b/src/spupng_encoder.c index e8a27297..69b6cb4c 100644 --- a/src/spupng_encoder.c +++ b/src/spupng_encoder.c @@ -614,8 +614,11 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte else if ( !(sub->flags & SUB_EOD_MARKER)) write_sputag(sp, sub->start_time, sub->end_time); - if(sub->nb_data == 0 ) + if(sub->nb_data == 0 && (sub->flags & SUB_EOD_MARKER)) + { + context->prev_start = -1; return 0; + } rect = sub->data; for(i = 0;i < sub->nb_data;i++) { diff --git a/src/ts_tables.c b/src/ts_tables.c index 249c5177..8fd419e7 100644 --- a/src/ts_tables.c +++ b/src/ts_tables.c @@ -286,7 +286,7 @@ int parse_PMT (unsigned char *buf,int len, int pos) break; ccx_options.ts_cappid = newcappid = elementary_PID; cap_stream_type = newcap_stream_type = ccx_stream_type; - max_dif = 10; + max_dif = 30; } } }