@@ -567,6 +567,104 @@ static size_t process_raw_for_mcc(struct encoder_ctx *enc_ctx, struct lib_cc_dec
567567}
568568
569569// Raw file process
570+ // Parse raw CDP (Caption Distribution Packet) data
571+ // Returns number of bytes processed
572+ static size_t process_raw_cdp (struct encoder_ctx * enc_ctx , struct lib_cc_decode * dec_ctx ,
573+ struct cc_subtitle * sub , unsigned char * buffer , size_t len )
574+ {
575+ size_t pos = 0 ;
576+ int cdp_count = 0 ;
577+
578+ while (pos + 10 < len ) // Minimum CDP size
579+ {
580+ // Check for CDP identifier
581+ if (buffer [pos ] != 0x96 || buffer [pos + 1 ] != 0x69 )
582+ {
583+ pos ++ ;
584+ continue ;
585+ }
586+
587+ unsigned char cdp_length = buffer [pos + 2 ];
588+ if (pos + cdp_length > len )
589+ break ; // Incomplete CDP packet
590+
591+ unsigned char framerate_byte = buffer [pos + 3 ];
592+ int framerate_code = framerate_byte >> 4 ;
593+
594+ // Skip to find cc_data section (0x72)
595+ size_t cdp_pos = pos + 4 ; // After identifier, length, framerate
596+ int cc_count = 0 ;
597+ unsigned char * cc_data = NULL ;
598+
599+ // Skip header sequence counter (2 bytes)
600+ cdp_pos += 2 ;
601+
602+ // Look for cc_data section (0x72) within CDP
603+ while (cdp_pos < pos + cdp_length - 4 )
604+ {
605+ if (buffer [cdp_pos ] == 0x72 ) // cc_data section
606+ {
607+ cc_count = buffer [cdp_pos + 1 ] & 0x1F ;
608+ cc_data = buffer + cdp_pos + 2 ;
609+ break ;
610+ }
611+ else if (buffer [cdp_pos ] == 0x71 ) // time code section
612+ {
613+ cdp_pos += 5 ; // Skip time code section
614+ }
615+ else if (buffer [cdp_pos ] == 0x73 ) // service info section
616+ {
617+ break ; // Past cc_data
618+ }
619+ else if (buffer [cdp_pos ] == 0x74 ) // footer
620+ {
621+ break ;
622+ }
623+ else
624+ {
625+ cdp_pos ++ ;
626+ }
627+ }
628+
629+ if (cc_count > 0 && cc_data != NULL )
630+ {
631+ // Calculate PTS based on CDP frame count and frame rate
632+ static const int fps_table [] = {0 , 24 , 24 , 25 , 30 , 30 , 50 , 60 , 60 };
633+ int fps = (framerate_code < 9 ) ? fps_table [framerate_code ] : 30 ;
634+ LLONG pts = (LLONG )cdp_count * 90000 / fps ;
635+
636+ // Set timing if not already set
637+ if (dec_ctx -> timing -> pts_set == 0 )
638+ {
639+ dec_ctx -> timing -> min_pts = pts ;
640+ dec_ctx -> timing -> pts_set = 2 ;
641+ dec_ctx -> timing -> sync_pts = pts ;
642+ }
643+ set_current_pts (dec_ctx -> timing , pts );
644+ set_fts (dec_ctx -> timing );
645+
646+ #ifndef DISABLE_RUST
647+ // Enable DTVCC decoder for CEA-708 captions
648+ if (dec_ctx -> dtvcc_rust )
649+ {
650+ int is_active = ccxr_dtvcc_is_active (dec_ctx -> dtvcc_rust );
651+ if (!is_active )
652+ {
653+ ccxr_dtvcc_set_active (dec_ctx -> dtvcc_rust , 1 );
654+ }
655+ }
656+ #endif
657+ // Process cc_data triplets through process_cc_data for 708 support
658+ process_cc_data (enc_ctx , dec_ctx , cc_data , cc_count , sub );
659+ cdp_count ++ ;
660+ }
661+
662+ pos += cdp_length ;
663+ }
664+
665+ return pos ;
666+ }
667+
570668int raw_loop (struct lib_ccx_ctx * ctx )
571669{
572670 LLONG ret ;
@@ -577,6 +675,7 @@ int raw_loop(struct lib_ccx_ctx *ctx)
577675 int caps = 0 ;
578676 int is_dvdraw = 0 ; // Flag to track if this is DVD raw format
579677 int is_scc = 0 ; // Flag to track if this is SCC format
678+ int is_cdp = 0 ; // Flag to track if this is raw CDP format
580679 int is_mcc_output = 0 ; // Flag for MCC output format
581680
582681 dec_ctx = update_decoder_list (ctx );
@@ -622,7 +721,15 @@ int raw_loop(struct lib_ccx_ctx *ctx)
622721 mprint ("Detected SCC (Scenarist Closed Caption) format\n" );
623722 }
624723
625- if (is_mcc_output && !is_dvdraw && !is_scc )
724+ // Check if this is raw CDP format (starts with 0x9669)
725+ if (!is_cdp && !is_scc && !is_dvdraw && data -> len >= 2 &&
726+ data -> buffer [0 ] == 0x96 && data -> buffer [1 ] == 0x69 )
727+ {
728+ is_cdp = 1 ;
729+ mprint ("Detected raw CDP (Caption Distribution Packet) format\n" );
730+ }
731+
732+ if (is_mcc_output && !is_dvdraw && !is_scc && !is_cdp )
626733 {
627734 // For MCC output, encode raw data directly without decoding
628735 // This preserves the original CEA-608 byte pairs in CDP format
@@ -640,6 +747,13 @@ int raw_loop(struct lib_ccx_ctx *ctx)
640747 // Use Rust SCC implementation - handles timing internally via SMPTE timecodes
641748 ret = ccxr_process_scc (dec_ctx , dec_sub , data -> buffer , (unsigned int )data -> len , ccx_options .scc_framerate );
642749 }
750+ else if (is_cdp )
751+ {
752+ // Process raw CDP packets (e.g., from SDI VANC capture)
753+ ret = process_raw_cdp (enc_ctx , dec_ctx , dec_sub , data -> buffer , data -> len );
754+ if (ret > 0 )
755+ caps = 1 ;
756+ }
643757 else
644758 {
645759 ret = process_raw (dec_ctx , dec_sub , data -> buffer , data -> len );
0 commit comments