mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2024-12-24 11:53:25 +00:00
Merge from upstream
-
This commit is contained in:
commit
597304e932
@ -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])
|
||||
|
@ -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)
|
||||
|
@ -85,14 +85,14 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
|
||||
#ifdef ENABLE_OCR
|
||||
char*str = NULL;
|
||||
#endif
|
||||
//int used;
|
||||
#ifdef ENABLE_OCR
|
||||
unsigned h1, m1, s1, ms1;
|
||||
unsigned h2, m2, s2, ms2;
|
||||
#endif
|
||||
int used;
|
||||
LLONG ms_start, ms_end;
|
||||
//char timeline[128];
|
||||
#ifdef ENABLE_OCR
|
||||
unsigned h1,m1,s1,ms1;
|
||||
unsigned h2,m2,s2,ms2;
|
||||
char timeline[128];
|
||||
int len = 0;
|
||||
#endif
|
||||
|
||||
x_pos = -1;
|
||||
y_pos = -1;
|
||||
|
@ -7,6 +7,7 @@ License: GPL 2.0
|
||||
#include "configuration.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "ffmpeg_intgr.h"
|
||||
|
||||
void xds_cea608_test();
|
||||
|
||||
@ -203,6 +204,7 @@ int main(int argc, char *argv[])
|
||||
char *c;
|
||||
struct encoder_ctx enc_ctx[2];
|
||||
struct cc_subtitle dec_sub;
|
||||
void *ffmpeg_ctx = NULL;
|
||||
|
||||
// Need to set the 608 data for the report to the correct variable.
|
||||
file_report.data_from_608 = ccx_decoder_608_report;
|
||||
@ -568,6 +570,54 @@ 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)
|
||||
{
|
||||
int i =0;
|
||||
buffer = malloc(1024);
|
||||
if(!buffer)
|
||||
{
|
||||
mprint("no memory left\n");
|
||||
break;
|
||||
}
|
||||
do
|
||||
{
|
||||
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("Error extracting Frame\n");
|
||||
break;
|
||||
|
||||
}
|
||||
store_hdcc(bptr,len, i++,fts_now,&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
|
||||
|
||||
if (auto_stream == CCX_SM_AUTODETECT)
|
||||
{
|
||||
|
@ -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;
|
||||
|
187
src/ffmpeg_intgr.c
Normal file
187
src/ffmpeg_intgr.c
Normal file
@ -0,0 +1,187 @@
|
||||
#include "ffmpeg_intgr.h"
|
||||
|
||||
#ifdef ENABLE_FFMPEG
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/avfiltergraph.h>
|
||||
#include <libavfilter/avcodec.h>
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/avstring.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/audio_fifo.h>
|
||||
#include <libavutil/log.h>
|
||||
#include <libavutil/error.h>
|
||||
|
||||
#include "ccextractor.h"
|
||||
struct ffmpeg_ctx
|
||||
{
|
||||
AVFormatContext *ifmt;
|
||||
AVCodecContext *dec_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
|
||||
*
|
||||
* @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();
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 increasing 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
|
23
src/ffmpeg_intgr.h
Normal file
23
src/ffmpeg_intgr.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _FFMPEG_INTIGRATION
|
||||
#define _FFMPEG_INTIGRATION
|
||||
|
||||
#ifdef ENABLE_FFMPEG
|
||||
#include "libavutil/common.h"
|
||||
#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
|
@ -201,8 +201,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
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user