diff --git a/src/lib_ccx/ccx_encoders_common.c b/src/lib_ccx/ccx_encoders_common.c index 135477531..964f18cd7 100644 --- a/src/lib_ccx/ccx_encoders_common.c +++ b/src/lib_ccx/ccx_encoders_common.c @@ -667,8 +667,13 @@ static int init_output_ctx(struct encoder_ctx *ctx, struct encoder_cfg *cfg) if (cfg->cc_to_stdout) { +#ifdef WIN32 + ctx->dtvcc_writers[i].fd = -1; + ctx->dtvcc_writers[i].fhandle = GetStdHandle(STD_OUTPUT_HANDLE); +#else ctx->dtvcc_writers[i].fd = STDOUT_FILENO; ctx->dtvcc_writers[i].fhandle = NULL; +#endif ctx->dtvcc_writers[i].charset = NULL; ctx->dtvcc_writers[i].filename = NULL; ctx->dtvcc_writers[i].cd = (iconv_t)-1; diff --git a/src/rust/src/decoder/service_decoder.rs b/src/rust/src/decoder/service_decoder.rs index 2037b62ba..3ce528b32 100644 --- a/src/rust/src/decoder/service_decoder.rs +++ b/src/rust/src/decoder/service_decoder.rs @@ -1118,7 +1118,6 @@ impl dtvcc_service_decoder { /// Process the character and add it to the current window pub fn process_character(&mut self, sym: dtvcc_symbol) { - debug!("{}", self.current_window); let window = &mut self.windows[self.current_window as usize]; let window_state = if is_true(window.is_defined) { "OK" diff --git a/src/rust/src/decoder/tv_screen.rs b/src/rust/src/decoder/tv_screen.rs index 4b8579cb3..c6d5529fd 100644 --- a/src/rust/src/decoder/tv_screen.rs +++ b/src/rust/src/decoder/tv_screen.rs @@ -735,4 +735,77 @@ mod test { assert!(!screen.is_row_empty(0)); assert!(screen.is_row_empty(1)); } + + #[test] + #[cfg(unix)] + fn test_writer_output_with_valid_fd() { + // Test that writer_output works when fd is already set (stdout mode) + // This tests the fix for issue #1693 + use std::fs::File; + use std::os::unix::io::{FromRawFd, IntoRawFd}; + use tempfile::tempfile; + + let screen = get_zero_allocated_obj::(); + let mut writer_ctx = get_zero_allocated_obj::(); + let transcript_settings = get_zero_allocated_obj::(); + + // Create a temp file and use its fd (simulates stdout being pre-set) + let temp_file = tempfile().expect("Failed to create temp file"); + writer_ctx.fd = temp_file.into_raw_fd(); + writer_ctx.filename = std::ptr::null_mut(); // filename is null in stdout mode + + let mut counter = 0u32; + let mut writer = Writer::new( + &mut counter, + 0, + ccx_output_format::CCX_OF_SRT, + &mut writer_ctx, + 0, + &transcript_settings, + 0, + ); + + // This should succeed without error (fd is valid, not -1) + let result = screen.writer_output(&mut writer); + assert!( + result.is_ok(), + "writer_output should succeed when fd is valid" + ); + + // Clean up: convert fd back to File so it gets closed on drop + let _file = unsafe { File::from_raw_fd(writer_ctx.fd) }; + } + + #[test] + #[cfg(unix)] + fn test_writer_output_missing_filename_and_fd() { + // Test that writer_output returns error when both filename and fd are invalid + // This is the expected behavior that was causing panic before the fix + let screen = get_zero_allocated_obj::(); + let mut writer_ctx = get_zero_allocated_obj::(); + let transcript_settings = get_zero_allocated_obj::(); + + // Both filename is null and fd is -1 (invalid state) + writer_ctx.fd = -1; + writer_ctx.filename = std::ptr::null_mut(); + + let mut counter = 0u32; + let mut writer = Writer::new( + &mut counter, + 0, + ccx_output_format::CCX_OF_SRT, + &mut writer_ctx, + 0, + &transcript_settings, + 0, + ); + + // This should return an error, not panic + let result = screen.writer_output(&mut writer); + assert!( + result.is_err(), + "writer_output should return error when filename and fd are invalid" + ); + assert_eq!(result.unwrap_err(), "Filename missing"); + } } diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 2ec8a8bac..0be931841 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -192,7 +192,8 @@ extern "C" { pub fn ccx_gxf_init(arg: *mut ccx_demuxer) -> *mut ccx_gxf; } -/// Initialize env logger with custom format, using stdout as target +/// Initialize env logger with custom format, using stderr as target +/// This ensures debug output doesn't pollute stdout when using --stdout option /// /// # Safety /// @@ -204,7 +205,7 @@ pub extern "C" fn ccxr_init_logger() { builder() .format(|buf, record| writeln!(buf, "[CEA-708] {}", record.args())) .filter_level(LevelFilter::Debug) - .target(Target::Stdout) + .target(Target::Stderr) .init(); }