Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2021-02-12 04:07:32 +0300
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2021-02-15 22:25:18 +0300
commit3c982a3de0bd350e586f87b8e50567552dd868f1 (patch)
tree472d42ed21f051c8fd1f75c4ff4b22d410f4857c
parent19611f0ebe84ff813f1779c80f256739449fa81f (diff)
ccdetect: extract CDP parser to a separate module
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/474>
-rw-r--r--video/closedcaption/src/ccdetect/imp.rs138
-rw-r--r--video/closedcaption/src/ccutils.rs152
-rw-r--r--video/closedcaption/src/lib.rs1
3 files changed, 157 insertions, 134 deletions
diff --git a/video/closedcaption/src/ccdetect/imp.rs b/video/closedcaption/src/ccdetect/imp.rs
index deaa430b2..c19b537c1 100644
--- a/video/closedcaption/src/ccdetect/imp.rs
+++ b/video/closedcaption/src/ccdetect/imp.rs
@@ -22,11 +22,9 @@ use gst::subclass::prelude::*;
use gst::{gst_trace, gst_warning};
use gst_base::subclass::prelude::*;
-use byteorder::{BigEndian, ByteOrder};
-
+use crate::ccutils::{extract_cdp, ParseError, ParseErrorCode};
use once_cell::sync::Lazy;
-use std::fmt;
use std::sync::Mutex;
use std::u64;
@@ -83,29 +81,6 @@ struct CCPacketContents {
cc708: bool,
}
-#[allow(clippy::enum_variant_names)]
-#[derive(Debug, Clone, Copy)]
-enum ParseErrorCode {
- WrongLength,
- WrongMagicSequence,
- WrongLayout,
-}
-
-#[derive(Debug, Clone)]
-struct ParseError {
- code: ParseErrorCode,
- byte: usize,
- msg: String,
-}
-
-impl fmt::Display for ParseError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{:?} at byte {}: {}", self.code, self.byte, self.msg)
- }
-}
-
-impl std::error::Error for ParseError {}
-
impl CCDetect {
fn detect_cc_data(data: &[u8]) -> Result<CCPacketContents, ParseError> {
if data.len() % 3 != 0 {
@@ -172,115 +147,10 @@ impl CCDetect {
})
}
- fn detect_cdp(mut data: &[u8]) -> Result<CCPacketContents, ParseError> {
- /* logic from ccconverter */
- let data_len = data.len();
-
- if data.len() < 11 {
- return Err(ParseError {
- code: ParseErrorCode::WrongLength,
- byte: data_len - data.len(),
- msg: format!(
- "cdp packet too short {}. expected at least {}",
- data.len(),
- 11
- ),
- });
- }
-
- if 0x9669 != BigEndian::read_u16(&data[..2]) {
- return Err(ParseError {
- code: ParseErrorCode::WrongMagicSequence,
- byte: data_len - data.len(),
- msg: String::from("cdp packet does not have initial magic bytes of 0x9669"),
- });
- }
- data = &data[2..];
-
- if (data[0] as usize) != data_len {
- return Err(ParseError {
- code: ParseErrorCode::WrongLength,
- byte: data_len - data.len(),
- msg: format!(
- "advertised cdp packet length {} does not match length of data {}",
- data[0], data_len
- ),
- });
- }
- data = &data[1..];
-
- /* skip framerate value */
- data = &data[1..];
-
- let flags = data[0];
- data = &data[1..];
-
- if flags & 0x40 == 0 {
- /* no cc_data */
- return Ok(CCPacketContents {
- cc608: false,
- cc708: false,
- });
- }
-
- /* skip sequence counter */
- data = &data[2..];
-
- /* timecode present? */
- if flags & 0x80 == 0x80 {
- if data.len() < 5 {
- return Err(ParseError {
- code: ParseErrorCode::WrongLength,
- byte: data_len - data.len(),
- msg: String::from("cdp packet signals a timecode but is not large enough to contain a timecode")
- });
- }
- data = &data[5..];
- }
-
- /* cc_data */
- if data.len() < 2 {
- return Err(ParseError {
- code: ParseErrorCode::WrongLength,
- byte: data_len - data.len(),
- msg: String::from(
- "cdp packet signals cc_data but is not large enough to contain cc_data",
- ),
- });
- }
-
- if data[0] != 0x72 {
- return Err(ParseError {
- code: ParseErrorCode::WrongMagicSequence,
- byte: data_len - data.len(),
- msg: String::from("ccp is missing start code 0x72"),
- });
- }
- data = &data[1..];
-
- let cc_count = data[0];
- data = &data[1..];
- if cc_count & 0xe0 != 0xe0 {
- return Err(ParseError {
- code: ParseErrorCode::WrongMagicSequence,
- byte: data_len - data.len(),
- msg: format!("reserved bits are not 0xe0, found {:02x}", cc_count & 0xe0),
- });
- }
- let cc_count = cc_count & 0x1f;
- let len = 3 * cc_count as usize;
-
- if len > data.len() {
- return Err(ParseError {
- code: ParseErrorCode::WrongLength,
- byte: data_len - data.len(),
- msg: String::from("cc_data length extends past the end of the cdp packet"),
- });
- }
-
- /* TODO: validate checksum */
+ fn detect_cdp(data: &[u8]) -> Result<CCPacketContents, ParseError> {
+ let data = extract_cdp(data)?;
- Self::detect_cc_data(&data[..len])
+ Self::detect_cc_data(data)
}
fn detect(format: CCFormat, data: &[u8]) -> Result<CCPacketContents, ParseError> {
diff --git a/video/closedcaption/src/ccutils.rs b/video/closedcaption/src/ccutils.rs
new file mode 100644
index 000000000..8d7fdadfd
--- /dev/null
+++ b/video/closedcaption/src/ccutils.rs
@@ -0,0 +1,152 @@
+// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
+// Boston, MA 02110-1335, USA.
+
+use byteorder::{BigEndian, ByteOrder};
+use std::fmt;
+
+#[allow(clippy::enum_variant_names)]
+#[derive(Debug, Clone, Copy)]
+pub enum ParseErrorCode {
+ WrongLength,
+ WrongMagicSequence,
+ WrongLayout,
+}
+
+#[derive(Debug, Clone)]
+pub struct ParseError {
+ pub code: ParseErrorCode,
+ pub byte: usize,
+ pub msg: String,
+}
+
+pub fn extract_cdp(mut data: &[u8]) -> Result<&[u8], ParseError> {
+ /* logic from ccconverter */
+ let data_len = data.len();
+
+ if data.len() < 11 {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongLength,
+ byte: data_len - data.len(),
+ msg: format!(
+ "cdp packet too short {}. expected at least {}",
+ data.len(),
+ 11
+ ),
+ });
+ }
+
+ if 0x9669 != BigEndian::read_u16(&data[..2]) {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongMagicSequence,
+ byte: data_len - data.len(),
+ msg: String::from("cdp packet does not have initial magic bytes of 0x9669"),
+ });
+ }
+ data = &data[2..];
+
+ if (data[0] as usize) != data_len {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongLength,
+ byte: data_len - data.len(),
+ msg: format!(
+ "advertised cdp packet length {} does not match length of data {}",
+ data[0], data_len
+ ),
+ });
+ }
+ data = &data[1..];
+
+ /* skip framerate value */
+ data = &data[1..];
+
+ let flags = data[0];
+ data = &data[1..];
+
+ if flags & 0x40 == 0 {
+ /* no cc_data */
+ return Ok(&[]);
+ }
+
+ /* skip sequence counter */
+ data = &data[2..];
+
+ /* timecode present? */
+ if flags & 0x80 == 0x80 {
+ if data.len() < 5 {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongLength,
+ byte: data_len - data.len(),
+ msg: String::from(
+ "cdp packet signals a timecode but is not large enough to contain a timecode",
+ ),
+ });
+ }
+ data = &data[5..];
+ }
+
+ /* cc_data */
+ if data.len() < 2 {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongLength,
+ byte: data_len - data.len(),
+ msg: String::from(
+ "cdp packet signals cc_data but is not large enough to contain cc_data",
+ ),
+ });
+ }
+
+ if data[0] != 0x72 {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongMagicSequence,
+ byte: data_len - data.len(),
+ msg: String::from("ccp is missing start code 0x72"),
+ });
+ }
+ data = &data[1..];
+
+ let cc_count = data[0];
+ data = &data[1..];
+ if cc_count & 0xe0 != 0xe0 {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongMagicSequence,
+ byte: data_len - data.len(),
+ msg: format!("reserved bits are not 0xe0, found {:02x}", cc_count & 0xe0),
+ });
+ }
+ let cc_count = cc_count & 0x1f;
+ let len = 3 * cc_count as usize;
+
+ if len > data.len() {
+ return Err(ParseError {
+ code: ParseErrorCode::WrongLength,
+ byte: data_len - data.len(),
+ msg: String::from("cc_data length extends past the end of the cdp packet"),
+ });
+ }
+
+ /* TODO: validate checksum */
+
+ Ok(&data[..len])
+}
+
+impl fmt::Display for ParseError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?} at byte {}: {}", self.code, self.byte, self.msg)
+ }
+}
+
+impl std::error::Error for ParseError {}
diff --git a/video/closedcaption/src/lib.rs b/video/closedcaption/src/lib.rs
index 84fa5b7ac..30b8e74ed 100644
--- a/video/closedcaption/src/lib.rs
+++ b/video/closedcaption/src/lib.rs
@@ -24,6 +24,7 @@ mod ffi;
mod caption_frame;
mod ccdetect;
+mod ccutils;
mod cea608overlay;
mod cea608tott;
mod line_reader;