mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2024-12-25 04:11:38 +00:00
Added --analyzevideo
This commit is contained in:
parent
a842e1f7db
commit
d9796410bc
@ -6,7 +6,11 @@
|
|||||||
- New: Added build/installation script for .pkg.tar.xz (Arch Linux).
|
- New: Added build/installation script for .pkg.tar.xz (Arch Linux).
|
||||||
- New: Added tarball generation script.
|
- New: Added tarball generation script.
|
||||||
- New: Added Autoconf build scripts for CCExtractor to generate makefiles.
|
- New: Added Autoconf build scripts for CCExtractor to generate makefiles.
|
||||||
|
- New: Added --analyzevideo. If present the video stream will be processed even if the
|
||||||
|
subtitles are in a different stream. This is useful when we want video information
|
||||||
|
(resolution, frame type, etc). -vides now implies this option too.
|
||||||
|
[Note: Tentative - some possibly breaking changed were made for this, so if you
|
||||||
|
use it validate results]
|
||||||
|
|
||||||
0.85b (2017-1-26)
|
0.85b (2017-1-26)
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -69,6 +69,7 @@ void init_options (struct ccx_s_options *options)
|
|||||||
options->ocr_oem = 0; // By default, set Tesseract OEM mode OEM_TESSERACT_ONLY (0)
|
options->ocr_oem = 0; // By default, set Tesseract OEM mode OEM_TESSERACT_ONLY (0)
|
||||||
options->mkvlang = NULL; // By default, all the languages are extracted
|
options->mkvlang = NULL; // By default, all the languages are extracted
|
||||||
options->ignore_pts_jumps = 1;
|
options->ignore_pts_jumps = 1;
|
||||||
|
options->analyze_video_stream = 0;
|
||||||
|
|
||||||
/*HardsubX related stuff*/
|
/*HardsubX related stuff*/
|
||||||
options->hardsubx_ocr_mode = 0;
|
options->hardsubx_ocr_mode = 0;
|
||||||
|
@ -134,6 +134,7 @@ struct ccx_s_options // Options from user parameters
|
|||||||
char *ocrlang; // The name of the .traineddata file to be loaded with tesseract
|
char *ocrlang; // The name of the .traineddata file to be loaded with tesseract
|
||||||
int ocr_oem; // The Tesseract OEM mode, could be 0 (default), 1 or 2
|
int ocr_oem; // The Tesseract OEM mode, could be 0 (default), 1 or 2
|
||||||
char *mkvlang; // The name of the language stream for MKV
|
char *mkvlang; // The name of the language stream for MKV
|
||||||
|
int analyze_video_stream; // If 1, the video stream will be processed even if we're using a different one for subtitles.
|
||||||
|
|
||||||
/*HardsubX related stuff*/
|
/*HardsubX related stuff*/
|
||||||
int hardsubx_ocr_mode;
|
int hardsubx_ocr_mode;
|
||||||
|
@ -242,7 +242,7 @@ static int es_video_sequence(struct lib_cc_decode *ctx, struct bitstream *esstre
|
|||||||
ctx->no_bitstream_error = 0;
|
ctx->no_bitstream_error = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Sequence header
|
||||||
if (!ctx->in_pic_data && startcode == 0xB3)
|
if (!ctx->in_pic_data && startcode == 0xB3)
|
||||||
{
|
{
|
||||||
if (!read_seq_info(ctx, esstream))
|
if (!read_seq_info(ctx, esstream))
|
||||||
@ -254,7 +254,7 @@ static int es_video_sequence(struct lib_cc_decode *ctx, struct bitstream *esstre
|
|||||||
ctx->saw_seqgoppic = 1;
|
ctx->saw_seqgoppic = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Group of pictures
|
||||||
if (!ctx->in_pic_data && startcode == 0xB8)
|
if (!ctx->in_pic_data && startcode == 0xB8)
|
||||||
{
|
{
|
||||||
if (!read_gop_info(ctx, esstream,sub))
|
if (!read_gop_info(ctx, esstream,sub))
|
||||||
@ -266,7 +266,7 @@ static int es_video_sequence(struct lib_cc_decode *ctx, struct bitstream *esstre
|
|||||||
ctx->saw_seqgoppic = 2;
|
ctx->saw_seqgoppic = 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Picture
|
||||||
if (!ctx->in_pic_data && startcode == 0x00)
|
if (!ctx->in_pic_data && startcode == 0x00)
|
||||||
{
|
{
|
||||||
if (!read_pic_info(ctx, esstream, sub))
|
if (!read_pic_info(ctx, esstream, sub))
|
||||||
@ -679,6 +679,7 @@ static int gop_header(struct lib_cc_decode *ctx, struct bitstream *esstream, str
|
|||||||
// will point to where we want to restart after getting more.
|
// will point to where we want to restart after getting more.
|
||||||
static int read_pic_info(struct lib_cc_decode *ctx, struct bitstream *esstream, struct cc_subtitle *sub)
|
static int read_pic_info(struct lib_cc_decode *ctx, struct bitstream *esstream, struct cc_subtitle *sub)
|
||||||
{
|
{
|
||||||
|
char frame_type_to_char[] = { '?', 'I', 'P','B', 'D', '?', '?','?' };
|
||||||
debug("Read PIC Info\n");
|
debug("Read PIC Info\n");
|
||||||
|
|
||||||
// We only get here after seeing that start code
|
// We only get here after seeing that start code
|
||||||
@ -728,10 +729,17 @@ static int read_pic_info(struct lib_cc_decode *ctx, struct bitstream *esstream,
|
|||||||
{
|
{
|
||||||
set_fts(ctx->timing); // Initialize fts
|
set_fts(ctx->timing); // Initialize fts
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
dbg_print(CCX_DMT_VIDES, " t:%d r:%d p:%d", ctx->top_field_first,
|
dbg_print(CCX_DMT_VIDES, " frametype: %d (%c) t:%d r:%d p:%d", ctx->picture_coding_type,
|
||||||
|
frame_type_to_char[ctx->picture_coding_type], ctx->top_field_first,
|
||||||
ctx->repeat_first_field, ctx->progressive_frame);
|
ctx->repeat_first_field, ctx->progressive_frame);
|
||||||
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime_static(get_fts(ctx->timing, ctx->current_field)));
|
dbg_print(CCX_DMT_VIDES, " FTS: %lld (%s)\n", ctx->timing->current_pts,
|
||||||
|
print_mstime_static(get_fts(ctx->timing, ctx->current_field)));
|
||||||
|
*/
|
||||||
|
if (ctx->picture_coding_type == 1) // Write I-Frame in ffprobe format for easy comparison
|
||||||
|
{
|
||||||
|
dbg_print(CCX_DMT_VIDES, "key_frame=1|pkt_pts=%lld|pict_type=I\n", ctx->timing->current_pts);
|
||||||
|
}
|
||||||
|
|
||||||
// Set min_pts/sync_pts according to the current time stamp.
|
// Set min_pts/sync_pts according to the current time stamp.
|
||||||
// Use fts_at_gop_start as reference when a GOP header was seen
|
// Use fts_at_gop_start as reference when a GOP header was seen
|
||||||
|
@ -799,6 +799,7 @@ void segment_output_file(struct lib_ccx_ctx *ctx, struct lib_cc_decode *dec_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int general_loop(struct lib_ccx_ctx *ctx)
|
int general_loop(struct lib_ccx_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct lib_cc_decode *dec_ctx = NULL;
|
struct lib_cc_decode *dec_ctx = NULL;
|
||||||
@ -863,6 +864,7 @@ int general_loop(struct lib_ccx_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct cap_info* cinfo = NULL;
|
struct cap_info* cinfo = NULL;
|
||||||
struct encoder_ctx *enc_ctx = NULL;
|
struct encoder_ctx *enc_ctx = NULL;
|
||||||
|
// Find most promising stream: teletext, DVB, ISDB, ATSC, in that order
|
||||||
int pid = get_best_stream(ctx->demux_ctx);
|
int pid = get_best_stream(ctx->demux_ctx);
|
||||||
if(pid < 0)
|
if(pid < 0)
|
||||||
{
|
{
|
||||||
@ -873,6 +875,39 @@ int general_loop(struct lib_ccx_ctx *ctx)
|
|||||||
ignore_other_stream(ctx->demux_ctx, pid);
|
ignore_other_stream(ctx->demux_ctx, pid);
|
||||||
data_node = get_data_stream(datalist, pid);
|
data_node = get_data_stream(datalist, pid);
|
||||||
}
|
}
|
||||||
|
if (ccx_options.analyze_video_stream)
|
||||||
|
{
|
||||||
|
int video_pid= get_video_stream(ctx->demux_ctx);
|
||||||
|
if (video_pid != pid && video_pid!=-1)
|
||||||
|
{
|
||||||
|
struct cap_info* cinfo_video = get_cinfo(ctx->demux_ctx, pid); // Must be pid, not video_pid or DVB crashes (possibly buffer consumption?) - TODO
|
||||||
|
struct lib_cc_decode *dec_ctx_video = update_decoder_list_cinfo(ctx, cinfo_video);
|
||||||
|
struct cc_subtitle *dec_sub_video = &dec_ctx_video->dec_sub;
|
||||||
|
struct demuxer_data *data_node_video = get_data_stream(datalist, video_pid);
|
||||||
|
if (data_node_video)
|
||||||
|
{
|
||||||
|
if (data_node_video->pts != CCX_NOPTS)
|
||||||
|
{
|
||||||
|
struct ccx_rational tb = { 1,MPEG_CLOCK_FREQ };
|
||||||
|
LLONG pts;
|
||||||
|
if (data_node_video->tb.num != 1 || data_node_video->tb.den != MPEG_CLOCK_FREQ)
|
||||||
|
{
|
||||||
|
pts = change_timebase(data_node_video->pts, data_node_video->tb, tb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pts = data_node_video->pts;
|
||||||
|
set_current_pts(dec_ctx_video->timing, pts);
|
||||||
|
set_fts(dec_ctx_video->timing);
|
||||||
|
}
|
||||||
|
size_t got = process_m2v(dec_ctx_video, data_node_video->buffer, data_node_video->len, dec_sub_video);
|
||||||
|
if (got > 0)
|
||||||
|
{
|
||||||
|
memmove(data_node_video->buffer, data_node_video->buffer + got, (size_t)(data_node_video->len - got));
|
||||||
|
data_node_video->len -= got;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cinfo = get_cinfo(ctx->demux_ctx, pid);
|
cinfo = get_cinfo(ctx->demux_ctx, pid);
|
||||||
enc_ctx = update_encoder_list_cinfo(ctx, cinfo);
|
enc_ctx = update_encoder_list_cinfo(ctx, cinfo);
|
||||||
|
@ -1877,6 +1877,12 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
|||||||
if (strcmp (argv[i],"-vides")==0)
|
if (strcmp (argv[i],"-vides")==0)
|
||||||
{
|
{
|
||||||
opt->debug_mask |= CCX_DMT_VIDES;
|
opt->debug_mask |= CCX_DMT_VIDES;
|
||||||
|
opt->analyze_video_stream = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[i], "-anvid") == 0 || strcmp(argv[i], "--analyzevideo") == 0)
|
||||||
|
{
|
||||||
|
opt->analyze_video_stream = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp (argv[i],"-xds")==0)
|
if (strcmp (argv[i],"-xds")==0)
|
||||||
|
@ -578,7 +578,8 @@ int copy_payload_to_capbuf(struct cap_info *cinfo, struct ts_payload *payload)
|
|||||||
{
|
{
|
||||||
int newcapbuflen;
|
int newcapbuflen;
|
||||||
|
|
||||||
if(cinfo->ignore == CCX_TRUE)
|
if(cinfo->ignore == CCX_TRUE &&
|
||||||
|
(cinfo->stream != CCX_STREAM_TYPE_VIDEO_MPEG2 || !ccx_options.analyze_video_stream))
|
||||||
{
|
{
|
||||||
return CCX_OK;
|
return CCX_OK;
|
||||||
}
|
}
|
||||||
@ -914,7 +915,8 @@ long ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data)
|
|||||||
look_for_caption_data (ctx, &payload);
|
look_for_caption_data (ctx, &payload);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (cinfo->ignore)
|
else if (cinfo->ignore == CCX_TRUE &&
|
||||||
|
(cinfo->stream != CCX_STREAM_TYPE_VIDEO_MPEG2 || !ccx_options.analyze_video_stream))
|
||||||
{
|
{
|
||||||
if(cinfo->codec_private_data)
|
if(cinfo->codec_private_data)
|
||||||
{
|
{
|
||||||
|
@ -97,6 +97,17 @@ void ignore_other_sib_stream(struct cap_info* head, int pid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_video_stream(struct ccx_demuxer *ctx)
|
||||||
|
{
|
||||||
|
struct cap_info* iter;
|
||||||
|
list_for_each_entry(iter, &ctx->cinfo_tree.all_stream, all_stream, struct cap_info)
|
||||||
|
{
|
||||||
|
if (iter->stream == CCX_STREAM_TYPE_VIDEO_MPEG2)
|
||||||
|
return iter->pid;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int get_best_stream(struct ccx_demuxer *ctx)
|
int get_best_stream(struct ccx_demuxer *ctx)
|
||||||
{
|
{
|
||||||
struct cap_info* iter;
|
struct cap_info* iter;
|
||||||
|
@ -133,7 +133,7 @@ int parse_PMT (struct ccx_demuxer *ctx, unsigned char *buf, int len, struct pro
|
|||||||
}
|
}
|
||||||
else if (table_id == 0xC1)
|
else if (table_id == 0xC1)
|
||||||
{
|
{
|
||||||
//SCTE 57 2003
|
//SCTE 57 2003
|
||||||
dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM NAME Table need implementation");
|
dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM NAME Table need implementation");
|
||||||
unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes
|
unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes
|
||||||
dbg_print(CCX_DMT_PARSE, "Program name message length: %u", c0length);
|
dbg_print(CCX_DMT_PARSE, "Program name message length: %u", c0length);
|
||||||
|
Loading…
Reference in New Issue
Block a user