diff --git a/video/closedcaption/src/cea708utils.rs b/video/closedcaption/src/cea708utils.rs index 333353634..41a11dfef 100644 --- a/video/closedcaption/src/cea708utils.rs +++ b/video/closedcaption/src/cea708utils.rs @@ -145,7 +145,16 @@ impl Cea708ServiceWriter { gst::trace!(CAT, "service is full"); break; } - if service.len() + code.byte_len() > available_bytes { + let service_header_bytes = if service.is_empty() { + if service.number() >= 7 { + 2 + } else { + 1 + } + } else { + 0 + }; + if service_header_bytes + service.len() + code.byte_len() > available_bytes { gst::trace!(CAT, "packet is full"); break; } diff --git a/video/closedcaption/tests/tttocea708.rs b/video/closedcaption/tests/tttocea708.rs index 4cc9b3633..31a3ef2bf 100644 --- a/video/closedcaption/tests/tttocea708.rs +++ b/video/closedcaption/tests/tttocea708.rs @@ -243,3 +243,51 @@ fn test_tttocea708_output_gaps() { let event = h.pull_event().unwrap(); assert_eq!(event.type_(), gst::EventType::Eos); } + +/* Here we verify that the element does not crash on large input buffers */ +#[test] +fn test_tttocea708_large_input() { + init(); + + let mut h = gst_check::Harness::new_parse("tttocea708 mode=roll-up"); + h.set_src_caps_str("text/x-raw"); + h.set_sink_caps_str("closedcaption/x-cea-708,format=cc_data,framerate=60/1"); + + while h.events_in_queue() != 0 { + let _event = h.pull_event().unwrap(); + } + + let inbuf = new_timed_buffer(" This is going to be a very long#& buffer that will exceed the output length of a single DTVCCPacket.#&", 0.nseconds(), ClockTime::SECOND); + assert_eq!(h.push(inbuf), Ok(gst::FlowSuccess::Ok)); + + h.push_event(gst::event::Eos::new()); + + loop { + let outbuf = h.pull().unwrap(); + println!("pts {}", outbuf.pts().unwrap().display()); + if outbuf.pts().unwrap() + outbuf.duration().unwrap() >= 200_000_000.nseconds() { + break; + } + + let data = outbuf.map_readable().unwrap(); + println!("data {:?}", &*data); + assert_ne!(&*data, &PADDING); + } + + /* Padding */ + loop { + let outbuf = h.pull().unwrap(); + println!("pts {}", outbuf.pts().unwrap().display()); + if outbuf.pts().unwrap() + outbuf.duration().unwrap() >= 1_000_000_000.nseconds() { + break; + } + + let data = outbuf.map_readable().unwrap(); + assert_eq!(&*data, &PADDING); + } + + assert_eq!(h.events_in_queue(), 1); + + let event = h.pull_event().unwrap(); + assert_eq!(event.type_(), gst::EventType::Eos); +}