Skip to content

Commit

Permalink
chore: create utils-format to reuse code between formats
Browse files Browse the repository at this point in the history
  • Loading branch information
sscobici committed Oct 6, 2024
1 parent 6066078 commit 3840b3c
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 94 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"symphonia-format-riff",
"symphonia-metadata",
"symphonia-play",
"symphonia-utils-format",
"symphonia-utils-xiph",
"symphonia-check",
]
3 changes: 2 additions & 1 deletion symphonia-format-isomp4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ encoding_rs = "0.8.17"
log = "0.4"
symphonia-core = { version = "0.5.4", path = "../symphonia-core" }
symphonia-metadata = { version = "0.5.4", path = "../symphonia-metadata" }
symphonia-utils-xiph = { version = "0.5.4", path = "../symphonia-utils-xiph" }
symphonia-utils-xiph = { version = "0.5.4", path = "../symphonia-utils-xiph" }
symphonia-utils-format = { version = "0.5.4", path = "../symphonia-utils-format" }
31 changes: 5 additions & 26 deletions symphonia-format-isomp4/src/atoms/avcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
use symphonia_core::codecs::video::well_known::CODEC_ID_H264;
use symphonia_core::codecs::video::VideoCodecParameters;
use symphonia_core::codecs::CodecProfile;
use symphonia_core::errors::{decode_error, Error, Result};
use symphonia_core::io::{BitReaderLtr, ReadBitsLtr, ReadBytes};
use symphonia_core::errors::{Error, Result};
use symphonia_core::io::ReadBytes;
use symphonia_utils_format::video::AVCDecoderConfigurationRecord;

use crate::atoms::{Atom, AtomHeader};

Expand All @@ -32,31 +33,9 @@ impl Atom for AvcCAtom {

let extra_data = reader.read_boxed_slice_exact(len as usize)?;

dbg!(extra_data.len());
let avc_config = AVCDecoderConfigurationRecord::read(&extra_data)?;

// Parse the AVCDecoderConfigurationRecord to get the profile and level. Defined in
// ISO/IEC 14496-15 section 5.3.3.1.
let mut br = BitReaderLtr::new(&extra_data);

// Configuration version is always 1.
let configuration_version = br.read_bits_leq32(8)?;

if configuration_version != 1 {
return decode_error(
"isomp4 (avc): unexpected avc decoder configuration record version",
);
}

// AVC profile as defined in ISO/IEC 14496-10.
let avc_profile_indication = br.read_bits_leq32(8)?;
let _profile_compatibility = br.read_bits_leq32(8)?;
let avc_level_indication = br.read_bits_leq32(8)?;

Ok(Self {
extra_data,
profile: CodecProfile::new(avc_profile_indication),
level: avc_level_indication,
})
Ok(Self { extra_data, profile: avc_config.profile, level: avc_config.level })
}
}

Expand Down
3 changes: 2 additions & 1 deletion symphonia-format-mkv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ log = "0.4"
lazy_static = "1.4.0"
symphonia-core = { version = "0.5.4", path = "../symphonia-core" }
symphonia-metadata = { version = "0.5.4", path = "../symphonia-metadata" }
symphonia-utils-xiph = { version = "0.5.4", path = "../symphonia-utils-xiph" }
symphonia-utils-xiph = { version = "0.5.4", path = "../symphonia-utils-xiph" }
symphonia-utils-format = { version = "0.5.4", path = "../symphonia-utils-format" }
71 changes: 5 additions & 66 deletions symphonia-format-mkv/src/codecs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use symphonia_core::codecs::video::{well_known::*, VideoCodecId, VideoCodecParam
use symphonia_core::codecs::{CodecId, CodecParameters, CodecProfile};
use symphonia_core::errors::{decode_error, Error, Result};

use symphonia_core::io::{BitReaderLtr, BufReader, ReadBitsLtr, ReadBytes};
use symphonia_core::io::{BufReader, ReadBytes};
use symphonia_utils_format::video::{
AVCDecoderConfigurationRecord, HEVCDecoderConfigurationRecord,
};
use symphonia_utils_xiph::flac::metadata::{MetadataBlockHeader, MetadataBlockType};

use crate::lacing::read_xiph_sizes;
Expand Down Expand Up @@ -342,7 +345,7 @@ fn get_codec_profile_and_level(track: &TrackElement) -> (Option<CodecProfile>, O
track
.codec_private
.as_ref()
.and_then(|buf| HevcDecoderConfigurationRecord::read(buf).ok())
.and_then(|buf| HEVCDecoderConfigurationRecord::read(buf).ok())
.map(|cfg| (Some(cfg.profile), Some(cfg.level)))
.unwrap_or_else(|| (None, None))
}
Expand All @@ -351,67 +354,3 @@ fn get_codec_profile_and_level(track: &TrackElement) -> (Option<CodecProfile>, O
_ => (None, None),
}
}

struct AVCDecoderConfigurationRecord {
profile: CodecProfile,
level: u32,
}

impl AVCDecoderConfigurationRecord {
fn read(buf: &[u8]) -> Result<Self> {
let mut br = BitReaderLtr::new(buf);

// Parse the AVCDecoderConfigurationRecord to get the profile and level. Defined in
// ISO/IEC 14496-15 section 5.3.3.1.

// Configuration version is always 1.
let configuration_version = br.read_bits_leq32(8)?;

if configuration_version != 1 {
return decode_error("mkv (avc): unexpected avc decoder configuration record version");
}

// AVC profile as defined in ISO/IEC 14496-10.
let avc_profile_indication = br.read_bits_leq32(8)?;
let _profile_compatibility = br.read_bits_leq32(8)?;
let avc_level_indication = br.read_bits_leq32(8)?;

Ok(AVCDecoderConfigurationRecord {
profile: CodecProfile::new(avc_profile_indication),
level: avc_level_indication,
})
}
}

struct HevcDecoderConfigurationRecord {
profile: CodecProfile,
level: u32,
}

impl HevcDecoderConfigurationRecord {
fn read(buf: &[u8]) -> Result<Self> {
let mut br = BitReaderLtr::new(buf);

// Parse the HevcDecoderConfigurationRecord to get the profile and level. Defined in
// ISO/IEC 14496-15 section 8.3.3.1.

// Configuration version is always 1.
let configuration_version = br.read_bits_leq32(8)?;

if configuration_version != 1 {
return decode_error("mkv (hevc): unexpected avc decoder configuration record version");
}

let _general_profile_space = br.read_bits_leq32(2)?;
let _general_tier_flag = br.read_bit()?;
let general_profile_idc = br.read_bits_leq32(5)?;
let _general_profile_compatibility_flags = br.read_bits_leq32(32)?;
let _general_constraint_indicator_flags = br.read_bits_leq64(48)?;
let general_level_idc = br.read_bits_leq32(8)?;

Ok(HevcDecoderConfigurationRecord {
profile: CodecProfile::new(general_profile_idc),
level: general_level_idc,
})
}
}
17 changes: 17 additions & 0 deletions symphonia-utils-format/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "symphonia-utils-format"
version = "0.5.4"
description = "Project Symphonia utilities for formats."
homepage = "https://github.com/pdeljanov/Symphonia"
repository = "https://github.com/pdeljanov/Symphonia"
authors = ["Philip Deljanov <philip.deljanov@gmail.com>"]
license = "MPL-2.0"
readme = "README.md"
categories = ["multimedia", "multimedia::audio", "multimedia::encoding"]
keywords = ["audio", "multimedia", "media", "mpeg"]
edition = "2021"
rust-version = "1.56"

[dependencies]
symphonia-core = { version = "0.5.4", path = "../symphonia-core" }
symphonia-metadata = { version = "0.5.4", path = "../symphonia-metadata" }
15 changes: 15 additions & 0 deletions symphonia-utils-format/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Symphonia Format Utilities

[![Docs](https://docs.rs/symphonia-utils-format/badge.svg)](https://docs.rs/symphonia-utils-format)

Common utilities for formats for Project Symphonia.

**Note:** This crate is part of Symphonia. Please use the [`symphonia`](https://crates.io/crates/symphonia) crate instead of this one directly.

## License

Symphonia is provided under the MPL v2.0 license. Please refer to the LICENSE file for more details.

## Contributing

Symphonia is a free and open-source project that welcomes contributions! To get started, please read our [Contribution Guidelines](https://github.com/pdeljanov/Symphonia/tree/master/CONTRIBUTING.md).
15 changes: 15 additions & 0 deletions symphonia-utils-format/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Symphonia
// Copyright (c) 2019-2022 The Project Symphonia Developers.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

// The following lints are allowed in all Symphonia crates. Please see clippy.toml for their
// justification.
#![allow(clippy::comparison_chain)]
#![allow(clippy::excessive_precision)]
#![allow(clippy::identity_op)]
#![allow(clippy::manual_range_contains)]

pub mod video;
78 changes: 78 additions & 0 deletions symphonia-utils-format/src/video/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Symphonia
// Copyright (c) 2019-2022 The Project Symphonia Developers.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_core::codecs::CodecProfile;
use symphonia_core::errors::{decode_error, Result};
use symphonia_core::io::{BitReaderLtr, ReadBitsLtr};

pub struct AVCDecoderConfigurationRecord {
pub profile: CodecProfile,
pub level: u32,
}

impl AVCDecoderConfigurationRecord {
pub fn read(buf: &[u8]) -> Result<Self> {
let mut br = BitReaderLtr::new(buf);

// Parse the AVCDecoderConfigurationRecord to get the profile and level. Defined in
// ISO/IEC 14496-15 section 5.3.3.1.

// Configuration version is always 1.
let configuration_version = br.read_bits_leq32(8)?;

if configuration_version != 1 {
return decode_error(
"utils (avc): unexpected avc decoder configuration record version",
);
}

// AVC profile as defined in ISO/IEC 14496-10.
let avc_profile_indication = br.read_bits_leq32(8)?;
let _profile_compatibility = br.read_bits_leq32(8)?;
let avc_level_indication = br.read_bits_leq32(8)?;

Ok(AVCDecoderConfigurationRecord {
profile: CodecProfile::new(avc_profile_indication),
level: avc_level_indication,
})
}
}

pub struct HEVCDecoderConfigurationRecord {
pub profile: CodecProfile,
pub level: u32,
}

impl HEVCDecoderConfigurationRecord {
pub fn read(buf: &[u8]) -> Result<Self> {
let mut br = BitReaderLtr::new(buf);

// Parse the HEVCDecoderConfigurationRecord to get the profile and level. Defined in
// ISO/IEC 14496-15 section 8.3.3.1.

// Configuration version is always 1.
let configuration_version = br.read_bits_leq32(8)?;

if configuration_version != 1 {
return decode_error(
"utils (hevc): unexpected hevc decoder configuration record version",
);
}

let _general_profile_space = br.read_bits_leq32(2)?;
let _general_tier_flag = br.read_bit()?;
let general_profile_idc = br.read_bits_leq32(5)?;
let _general_profile_compatibility_flags = br.read_bits_leq32(32)?;
let _general_constraint_indicator_flags = br.read_bits_leq64(48)?;
let general_level_idc = br.read_bits_leq32(8)?;

Ok(HEVCDecoderConfigurationRecord {
profile: CodecProfile::new(general_profile_idc),
level: general_level_idc,
})
}
}

0 comments on commit 3840b3c

Please sign in to comment.