Skip to content

Commit

Permalink
Add SCC support for CEA-708 Decoder (CCExtractor#1426)
Browse files Browse the repository at this point in the history
  • Loading branch information
voidash committed Apr 15, 2022
1 parent e449557 commit 54a0351
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 23 deletions.
1 change: 1 addition & 0 deletions docs/CHANGES.TXT
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
0.95 (to be released)
-----------------
- New: Add SCC Support for CEA-708 Decoder (#1426)
- Fix: crash in Rust decoder on ATSC1.0 TS Files (#1407)
- Removed the --with-gui flag for linux/configure and mac/configure (use the Flutter GUI instead)
- Fix: segmentation fault in using hardsubx
Expand Down
29 changes: 22 additions & 7 deletions src/lib_ccx/ccx_decoders_708_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,16 @@ unsigned char adjust_odd_parity(const unsigned char value)
return value;
}

void dtvcc_write_scc_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
char *buf = (char *)encoder->buffer;
// 18 characters long + 2 new lines
memset(buf, 0, 20);
sprintf(buf, "Scenarist_SCC V1.0\n\n");

write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
}

void dtvcc_write_scc(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struct encoder_ctx *encoder) {
dtvcc_tv_screen *tv = decoder->tv;

Expand All @@ -345,11 +355,16 @@ void dtvcc_write_scc(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, s
return;

char *buf = (char *) encoder -> buffer;
if (tv->cc_count == 2) {
dtvcc_write_scc_header(tv, encoder);
}
print_scc_time(tv->time_ms_show + encoder->subs_delay, buf);

// {clear buffer} {pop on caption} {row15 column1}
sprintf(buf+strlen(buf),"94ae 9420 9470 ");

for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++) {
if(!dtvcc_is_row_empty(tv,i)) {
// {clear buffer} {pop on caption} {row15 column1}
sprintf(buf+strlen(buf),"94ae 9420 9470 ");
int first, last, bytes_written = 0;
dtvcc_get_write_interval(tv, i, &first, &last);
for (int j = first; j <= last; j++) {
Expand All @@ -359,16 +374,17 @@ void dtvcc_write_scc(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, s
}
bytes_written += 1;
}
//filler 0x80 if the number of bytes written are not even
// if byte pair are not even then make it even by adding 0x80 as padding
if (bytes_written % 2 == 1) {
sprintf(buf +strlen(buf), "80");
sprintf(buf +strlen(buf), "80 ");
}else {
sprintf(buf +strlen(buf), " ");
}

}
}
sprintf(buf +strlen(buf), "\n\n");
write_wrapped(encoder->dtvcc_writers[tv->service_number - 1].fd,buf,strlen(buf));
// when hiding substract a frame
// when hiding subtract a frame
// 1 frame = 34 ms
print_scc_time(tv->time_ms_hide + encoder->subs_delay - 34, buf);
// clear caption command
Expand Down Expand Up @@ -439,7 +455,6 @@ void dtvcc_write(dtvcc_writer_ctx *writer, dtvcc_service_decoder *decoder, struc
dtvcc_write_sami(writer, decoder, encoder);
break;
case CCX_OF_SCC:
dtvcc_write_debug(decoder->tv);
dtvcc_write_scc(writer, decoder, encoder);
break;
case CCX_OF_MCC:
Expand Down
9 changes: 9 additions & 0 deletions src/rust/src/decoder/timing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,12 @@ pub fn get_time_str(time: LLONG) -> String {
let ms = time - 1000 * (ss + 60 * (mm + 60 * hh));
format!("{:02}:{:02}:{:02},{:03}", hh, mm, ss, ms)
}

///Returns a hh:mm:ss:frame string of time for SCC format
pub fn get_scc_time_str(time: LLONG) -> String {
let hh = time / 1000 / 60 / 60;
let mm = time / 1000 / 60 - 60 * hh;
let ss = time / 1000 - 60 * (mm + 60 * hh);
let frame = ((time - 1000 * (ss + 60 * (mm + 60 * hh))) as f32 * 29.97/1000.00) as u8;
format!("{:02}:{:02}:{:02}:{:02}", hh, mm, ss, frame)
}
33 changes: 17 additions & 16 deletions src/rust/src/decoder/tv_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::os::windows::io::IntoRawHandle;
use std::{ffi::CStr, fs::File};

use super::output::{color_to_hex, write_char, Writer};
use super::timing::get_time_str;
use super::timing::{get_time_str,get_scc_time_str};
use super::{CCX_DTVCC_SCREENGRID_COLUMNS, CCX_DTVCC_SCREENGRID_ROWS};
use crate::{
bindings::*,
Expand Down Expand Up @@ -308,8 +308,8 @@ impl dtvcc_tv_screen {
}


/// Write captions in SCC format
pub fn write_scc(&self, writer: &mut Writer) -> Result<(), String> {

fn adjust_odd_parity(value: u8) -> u8{
let mut ones = 0;
for j in 0..7 {
Expand All @@ -327,19 +327,20 @@ impl dtvcc_tv_screen {
return Ok(());
}

for row_index in 0..CCX_DTVCC_SCREENGRID_ROWS as usize {
if !self.is_row_empty(row_index) {
let time_show = get_time_str(self.time_ms_show);
let time_hide = get_time_str(self.time_ms_hide);
let mut buf = String::new();
let time_show = get_scc_time_str(self.time_ms_show);
let time_end = get_scc_time_str(self.time_ms_hide);

debug!("{} {}", time_show, time_hide);
buf.push_str(&time_show);
// {clear buffer} {start pop on} {row15 col0 white}
buf.push_str(" 94ae 9420 9470");

for row_index in 0..CCX_DTVCC_SCREENGRID_ROWS as usize {
if !self.is_row_empty(row_index) {
debug!("{}", time_show);
let (first, last) = self.get_write_interval(row_index);
debug!("First: {}, Last: {}", first, last);

let mut buf = String::new();
// {rollup} {unknown} {row15 col0 white}
buf.push_str("9426 94ad 9470");
let mut bytes_written = 0;
for i in 0..last + 1 {
if bytes_written % 2 == 0 {
Expand All @@ -348,18 +349,18 @@ impl dtvcc_tv_screen {
let adjusted_val = adjust_odd_parity(self.chars[row_index][i].sym as u8);
buf = format!("{}{:x}", buf, adjusted_val);
bytes_written += 1;
// debug!(" value {:x} {} ",adjusted_val, (adjusted_val) as char);
}
// add 0x80 as filler if number of bytes is not even
// add 0x80 padding and form byte pair if the last byte pair is not form
if bytes_written % 2 == 1 {
buf.push_str("80");
}
buf.push_str("\r\n");

debug!("{}", buf);
writer.write_to_file(buf.as_bytes())?;
}
}
buf.push_str("\n\n");
writer.write_to_file(buf.as_bytes())?;
// clear screen
buf = format!("{} 942c 942c \n\n",time_end);
writer.write_to_file(buf.as_bytes())?;
return Ok(());
}

Expand Down

0 comments on commit 54a0351

Please sign in to comment.