From b15f54c7f9341099859337fa3bca49b0a6b1151a Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Tue, 12 Aug 2014 10:43:07 +0530 Subject: [PATCH] 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