Skip to content

Commit 88c10a5

Browse files
committed
feat: implement DVB subtitle splitting (--split-dvb-subs)
Add --split-dvb-subs option to extract DVB subtitles from multi-stream files into separate output files, with one file per language/PID. Features: - Automatic DVB stream detection and splitting - Ring buffer deduplication to prevent repeated subtitles - Multi-pipeline support for individual stream processing - Post-EOF DVB packet handling for complete extraction - Language-based output file naming (e.g., output_deu.srt) - --no-dvb-dedup option to disable deduplication if needed
1 parent c65fb08 commit 88c10a5

30 files changed

+1652
-263
lines changed

docs/CHANGES.TXT

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
0.96.6 (unreleased)
22
-------------------
3+
- New: --split-dvb-subs option to extract each DVB subtitle stream to a separate output file with language-based naming
4+
- New: --no-dvb-dedup option to disable DVB subtitle deduplication
5+
- Improvement: Ring buffer deduplication prevents repeated subtitles in split DVB output
6+
- Improvement: Multi-pipeline support for parallel DVB stream processing
7+
- Improvement: Post-EOF DVB packet handling for complete extraction
38
- Fix: Clear status line output on Linux/WSL to prevent text artifacts (#2017)
49
- Fix: Prevent infinite loop on truncated MKV files
510
- Fix: Various memory safety and stability fixes in demuxers (MP4, PS, MKV, DVB)

linux/Makefile.am

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,10 @@ ccextractor_SOURCES = \
128128
../src/lib_ccx/configuration.c \
129129
../src/lib_ccx/configuration.h \
130130
../src/lib_ccx/disable_warnings.h \
131-
../src/lib_ccx/dvb_subtitle_decoder.c \
132-
../src/lib_ccx/dvb_subtitle_decoder.h \
131+
../src/lib_ccx/dvb_subtitle_decoder.c \
132+
../src/lib_ccx/dvb_subtitle_decoder.h \
133+
../src/lib_ccx/dvb_dedup.c \
134+
../src/lib_ccx/dvb_dedup.h \
133135
../src/lib_ccx/dvd_subtitle_decoder.c \
134136
../src/lib_ccx/dvd_subtitle_decoder.h \
135137
../src/lib_ccx/es_functions.c \

mac/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ ccextractor_SOURCES = \
100100
../src/lib_ccx/configuration.c \
101101
../src/lib_ccx/configuration.h \
102102
../src/lib_ccx/disable_warnings.h \
103+
../src/lib_ccx/dvb_dedup.c \
104+
../src/lib_ccx/dvb_dedup.h \
103105
../src/lib_ccx/dvb_subtitle_decoder.c \
104106
../src/lib_ccx/dvb_subtitle_decoder.h \
105107
../src/lib_ccx/dvd_subtitle_decoder.c \

src/CMakeLists.txt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ option (WITH_HARDSUBX "Build with support for burned-in subtitles" OFF)
99

1010
# Version number
1111
set (CCEXTRACTOR_VERSION_MAJOR 0)
12-
set (CCEXTRACTOR_VERSION_MINOR 96)
12+
set (CCEXTRACTOR_VERSION_MINOR 89)
1313

1414
# Get project directory
1515
get_filename_component(BASE_PROJ_DIR ../ ABSOLUTE)
@@ -255,13 +255,4 @@ endif (PKG_CONFIG_FOUND)
255255
target_link_libraries (ccextractor ${EXTRA_LIBS})
256256
target_include_directories (ccextractor PUBLIC ${EXTRA_INCLUDES})
257257

258-
# ccx_rust (Rust) calls C functions from ccx (like decode_vbi).
259-
# Force the linker to pull these symbols from ccx before processing ccx_rust.
260-
if (NOT WIN32 AND NOT APPLE)
261-
target_link_options (ccextractor PRIVATE
262-
-Wl,--undefined=decode_vbi
263-
-Wl,--undefined=do_cb
264-
-Wl,--undefined=store_hdcc)
265-
endif()
266-
267258
install (TARGETS ccextractor DESTINATION bin)

src/ccextractor.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ int start_ccx()
221221
if (!ret)
222222
ret = tmp;
223223
break;
224+
#ifdef GPAC_AVAILABLE
224225
case CCX_SM_MP4:
225226
mprint("\rAnalyzing data with GPAC (MP4 library)\n");
226227
close_input_file(ctx); // No need to have it open. GPAC will do it for us
@@ -241,6 +242,7 @@ int start_ccx()
241242
if (!ret)
242243
ret = tmp;
243244
break;
245+
#endif
244246
case CCX_SM_MKV:
245247
mprint("\rAnalyzing data in Matroska mode\n");
246248
tmp = matroska_loop(ctx);

src/lib_ccx/CMakeLists.txt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
cmake_policy (SET CMP0037 NEW)
22

33
if(MSVC)
4-
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W3 /wd4005 /wd4996")
4+
set (CMAKE_C_FLAGS "-W3 /wd4005 /wd4996")
55
else (MSVC)
6-
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -g -std=gnu99")
6+
set (CMAKE_C_FLAGS "-Wall -Wno-pointer-sign -g -std=gnu99")
77
endif(MSVC)
88

99
if(WIN32)
1010
add_definitions(-DWIN32)
1111
endif(WIN32)
1212

1313
find_package(PkgConfig)
14-
pkg_check_modules (GPAC REQUIRED gpac)
14+
pkg_check_modules (GPAC gpac)
1515

16-
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${GPAC_INCLUDE_DIRS})
17-
set (EXTRA_LIBS ${EXTRA_LIBS} ${GPAC_LIBRARIES})
16+
if (GPAC_FOUND)
17+
set (EXTRA_INCLUDES ${EXTRA_INCLUDES} ${GPAC_INCLUDE_DIRS})
18+
set (EXTRA_LIBS ${EXTRA_LIBS} ${GPAC_LIBRARIES})
19+
add_definitions(-DGPAC_AVAILABLE)
20+
endif()
1821

1922
if (WITH_FFMPEG)
2023
find_package(PkgConfig)
@@ -59,6 +62,10 @@ endif (WITH_OCR)
5962

6063
aux_source_directory ("${PROJECT_SOURCE_DIR}/lib_ccx/" SOURCEFILE)
6164

65+
if (NOT GPAC_FOUND)
66+
list(FILTER SOURCEFILE EXCLUDE REGEX "mp4.c$")
67+
endif()
68+
6269
add_library (ccx ${SOURCEFILE} ccx_dtvcc.h ccx_dtvcc.c ccx_encoders_mcc.c ccx_encoders_mcc.h)
6370
target_link_libraries (ccx ${EXTRA_LIBS})
6471
target_include_directories (ccx PUBLIC ${EXTRA_INCLUDES})
@@ -101,4 +108,4 @@ file (WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
101108

102109
install (TARGETS ccx DESTINATION lib)
103110
install (FILES ${HeaderFiles} DESTINATION include)
104-
install (FILES ccx.pc DESTINATION lib/pkgconfig)
111+
install (FILES ccx.pc DESTINATION lib/pkgconfig)

src/lib_ccx/ccx_common_option.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,7 @@ void init_options(struct ccx_s_options *options)
181181
stringztoms(DEF_VAL_STARTCREDITSFORATMOST, &options->enc_cfg.startcreditsforatmost);
182182
stringztoms(DEF_VAL_ENDCREDITSFORATLEAST, &options->enc_cfg.endcreditsforatleast);
183183
stringztoms(DEF_VAL_ENDCREDITSFORATMOST, &options->enc_cfg.endcreditsforatmost);
184+
185+
options->split_dvb_subs = 0; // Default: legacy single-stream behavior
186+
options->no_dvb_dedup = 0; // Default: deduplication enabled
184187
}

src/lib_ccx/ccx_common_option.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ struct ccx_s_options // Options from user parameters
201201
int multiprogram;
202202
int out_interval;
203203
int segment_on_key_frames_only;
204-
int scc_framerate; // SCC input framerate: 0=29.97 (default), 1=24, 2=25, 3=30
204+
int split_dvb_subs; // Enable per-stream DVB subtitle extraction (0=disabled, 1=enabled)
205+
int no_dvb_dedup; // Disable DVB subtitle deduplication (0=dedup enabled, 1=dedup disabled)
206+
int scc_framerate; // SCC input framerate: 0=29.97 (default), 1=24, 2=25, 3=30
205207
#ifdef WITH_LIBCURL
206208
char *curlposturl;
207209
#endif

src/lib_ccx/ccx_decoders_structs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct ccx_decoders_common_settings_t
124124
unsigned send_to_srv;
125125
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
126126
int program_number;
127+
int pid;
127128
enum ccx_code_type codec;
128129
int xds_write_to_file;
129130
void *private_data;
@@ -162,6 +163,7 @@ struct lib_cc_decode
162163
unsigned total_pulldownfields;
163164
unsigned total_pulldownframes;
164165
int program_number;
166+
int pid;
165167
struct list_head list;
166168
struct ccx_common_timing_ctx *timing;
167169
enum ccx_code_type codec;
@@ -208,7 +210,7 @@ struct lib_cc_decode
208210
int false_pict_header;
209211

210212
dtvcc_ctx *dtvcc;
211-
void *dtvcc_rust; // Persistent Rust CEA-708 decoder context
213+
void *dtvcc_rust; // Persistent Rust CEA-708 decoder context
212214
int current_field;
213215
// Analyse/use the picture information
214216
int maxtref; // Use to remember the temporal reference number

src/lib_ccx/ccx_demuxer.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ void ccx_demuxer_delete(struct ccx_demuxer **ctx)
323323
}
324324

325325
freep(&lctx->filebuffer);
326+
327+
// Reset potential stream discovery data
328+
lctx->potential_stream_count = 0;
329+
memset(lctx->potential_streams, 0, sizeof(lctx->potential_streams));
330+
326331
freep(ctx);
327332
}
328333

@@ -406,6 +411,9 @@ struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg)
406411
init_ts(ctx);
407412
ctx->filebuffer = NULL;
408413

414+
// Initialize stream discovery for multi-stream DVB subtitle extraction
415+
ctx->potential_stream_count = 0;
416+
409417
return ctx;
410418
}
411419

0 commit comments

Comments
 (0)