diff --git a/docs/CHANGES.TXT b/docs/CHANGES.TXT index cc5ca4e6..939acd36 100644 --- a/docs/CHANGES.TXT +++ b/docs/CHANGES.TXT @@ -6,7 +6,11 @@ - New: Added build/installation script for .pkg.tar.xz (Arch Linux). - New: Added tarball generation script. - 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) ----------------- diff --git a/src/lib_ccx/ccx_common_option.c b/src/lib_ccx/ccx_common_option.c index 7a7265f8..c97c0dc1 100644 --- a/src/lib_ccx/ccx_common_option.c +++ b/src/lib_ccx/ccx_common_option.c @@ -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->mkvlang = NULL; // By default, all the languages are extracted options->ignore_pts_jumps = 1; + options->analyze_video_stream = 0; /*HardsubX related stuff*/ options->hardsubx_ocr_mode = 0; diff --git a/src/lib_ccx/ccx_common_option.h b/src/lib_ccx/ccx_common_option.h index 5723707e..d45d91c9 100644 --- a/src/lib_ccx/ccx_common_option.h +++ b/src/lib_ccx/ccx_common_option.h @@ -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 int ocr_oem; // The Tesseract OEM mode, could be 0 (default), 1 or 2 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*/ int hardsubx_ocr_mode; diff --git a/src/lib_ccx/es_functions.c b/src/lib_ccx/es_functions.c index 69e055bd..63fcda7c 100644 --- a/src/lib_ccx/es_functions.c +++ b/src/lib_ccx/es_functions.c @@ -242,7 +242,7 @@ static int es_video_sequence(struct lib_cc_decode *ctx, struct bitstream *esstre ctx->no_bitstream_error = 0; break; } - + // Sequence header if (!ctx->in_pic_data && startcode == 0xB3) { 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; continue; } - + // Group of pictures if (!ctx->in_pic_data && startcode == 0xB8) { 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; continue; } - + // Picture if (!ctx->in_pic_data && startcode == 0x00) { 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. 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"); // 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 } - - 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); - 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. // Use fts_at_gop_start as reference when a GOP header was seen diff --git a/src/lib_ccx/general_loop.c b/src/lib_ccx/general_loop.c index 527591f1..07e5a426 100644 --- a/src/lib_ccx/general_loop.c +++ b/src/lib_ccx/general_loop.c @@ -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) { 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 encoder_ctx *enc_ctx = NULL; + // Find most promising stream: teletext, DVB, ISDB, ATSC, in that order int pid = get_best_stream(ctx->demux_ctx); if(pid < 0) { @@ -873,6 +875,39 @@ int general_loop(struct lib_ccx_ctx *ctx) ignore_other_stream(ctx->demux_ctx, 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); enc_ctx = update_encoder_list_cinfo(ctx, cinfo); diff --git a/src/lib_ccx/params.c b/src/lib_ccx/params.c index f4f0f90d..8afe454c 100644 --- a/src/lib_ccx/params.c +++ b/src/lib_ccx/params.c @@ -1877,6 +1877,12 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[]) if (strcmp (argv[i],"-vides")==0) { 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; } if (strcmp (argv[i],"-xds")==0) diff --git a/src/lib_ccx/ts_functions.c b/src/lib_ccx/ts_functions.c index 564152a7..c55d37be 100644 --- a/src/lib_ccx/ts_functions.c +++ b/src/lib_ccx/ts_functions.c @@ -578,7 +578,8 @@ int copy_payload_to_capbuf(struct cap_info *cinfo, struct ts_payload *payload) { 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; } @@ -914,7 +915,8 @@ long ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data) look_for_caption_data (ctx, &payload); 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) { diff --git a/src/lib_ccx/ts_info.c b/src/lib_ccx/ts_info.c index add97742..ee8c0705 100644 --- a/src/lib_ccx/ts_info.c +++ b/src/lib_ccx/ts_info.c @@ -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) { struct cap_info* iter; diff --git a/src/lib_ccx/ts_tables.c b/src/lib_ccx/ts_tables.c index 4f774516..1da39dfa 100644 --- a/src/lib_ccx/ts_tables.c +++ b/src/lib_ccx/ts_tables.c @@ -133,7 +133,7 @@ int parse_PMT (struct ccx_demuxer *ctx, unsigned char *buf, int len, struct pro } else if (table_id == 0xC1) { - //SCTE 57 2003 + //SCTE 57 2003 dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM NAME Table need implementation"); unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes dbg_print(CCX_DMT_PARSE, "Program name message length: %u", c0length);