Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert VideoCodecParameters.extra_data to vector #323

Open
wants to merge 5 commits into
base: dev-0.6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions symphonia-common/src/mpeg/video/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,37 @@ impl HEVCDecoderConfigurationRecord {
})
}
}

#[derive(Debug, Default)]
pub struct DOVIDecoderConfigurationRecord {
pub dv_version_major: u8,
pub dv_version_minor: u8,
pub dv_profile: u8,
pub dv_level: u8,
pub rpu_present_flag: bool,
pub el_present_flag: bool,
pub bl_present_flag: bool,
pub dv_bl_signal_compatibility_id: u8,
}

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

// Parse the DOVIDecoderConfigurationRecord, point 3.2 from
// https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolby_vision_bitstreams_within_the_iso_base_media_file_format_dec2017.pdf

let config = DOVIDecoderConfigurationRecord {
dv_version_major: br.read_bits_leq32(8)? as u8,
dv_version_minor: br.read_bits_leq32(8)? as u8,
dv_profile: br.read_bits_leq32(7)? as u8,
dv_level: br.read_bits_leq32(6)? as u8,
rpu_present_flag: br.read_bool()?,
el_present_flag: br.read_bool()?,
bl_present_flag: br.read_bool()?,
dv_bl_signal_compatibility_id: br.read_bits_leq32(4)? as u8,
};

Ok(config)
}
}
64 changes: 49 additions & 15 deletions symphonia-core/src/codecs/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,29 @@ impl fmt::Display for VideoCodecId {
}
}

/// An `VideoExtraDataId` is a unique identifier used to identify a specific video extra data.
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VideoExtraDataId(u32);

/// Null video extra data ID.
pub const VIDEO_EXTRA_DATA_ID_NULL: VideoExtraDataId = VideoExtraDataId(0x0);

impl Default for VideoExtraDataId {
fn default() -> Self {
VIDEO_EXTRA_DATA_ID_NULL
}
}

/// Extra data for a video codec.
#[derive(Clone, Debug, Default)]
pub struct VideoExtraData {
/// The extra data ID.
pub id: VideoExtraDataId,
/// Extra data (defined by codec)
pub data: Box<[u8]>,
}

/// Codec parameters for video codecs.
#[derive(Clone, Debug, Default)]
pub struct VideoCodecParameters {
Expand All @@ -67,21 +90,10 @@ pub struct VideoCodecParameters {
/// Video height.
pub height: Option<u16>,
/// Extra data (defined by the codec).
pub extra_data: Option<Box<[u8]>>,
pub extra_data: Vec<VideoExtraData>,
}

impl VideoCodecParameters {
pub fn new() -> VideoCodecParameters {
VideoCodecParameters {
codec: CODEC_ID_NULL_VIDEO,
profile: None,
level: None,
width: None,
height: None,
extra_data: None,
}
}

/// Provide the `VideoCodecId`.
pub fn for_codec(&mut self, codec: VideoCodecId) -> &mut Self {
self.codec = codec;
Expand Down Expand Up @@ -112,9 +124,9 @@ impl VideoCodecParameters {
self
}

/// Provide codec extra data.
pub fn with_extra_data(&mut self, data: Box<[u8]>) -> &mut Self {
self.extra_data = Some(data);
/// Adds codec's extra data.
pub fn add_extra_data(&mut self, data: VideoExtraData) -> &mut Self {
self.extra_data.push(data);
self
}
}
Expand Down Expand Up @@ -379,4 +391,26 @@ pub mod well_known {
/// VC-1 Advanced Profile
pub const CODEC_PROFILE_VC1_ADVANCED: CodecProfile = CodecProfile(2);
}

pub mod extra_data {
use crate::codecs::video::VideoExtraDataId;

/// AVCDecoderConfigurationRecord
pub const VIDEO_EXTRA_DATA_ID_AVC_DECODER_CONFIG: VideoExtraDataId = VideoExtraDataId(1);

/// HEVCDecoderConfigurationRecord
pub const VIDEO_EXTRA_DATA_ID_HEVC_DECODER_CONFIG: VideoExtraDataId = VideoExtraDataId(2);

/// VP9DecoderConfiguration
pub const VIDEO_EXTRA_DATA_ID_VP9_DECODER_CONFIG: VideoExtraDataId = VideoExtraDataId(3);

/// AV1DecoderConfiguration
pub const VIDEO_EXTRA_DATA_ID_AV1_DECODER_CONFIG: VideoExtraDataId = VideoExtraDataId(4);

/// DolbyVisionConfiguration
pub const VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG: VideoExtraDataId = VideoExtraDataId(5);

/// DolbyVision EL HEVC
pub const VIDEO_EXTRA_DATA_ID_DOLBY_VISION_EL_HEVC: VideoExtraDataId = VideoExtraDataId(6);
}
}
7 changes: 4 additions & 3 deletions symphonia-format-isomp4/src/atoms/alac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_core::codecs::audio::well_known::CODEC_ID_ALAC;
use symphonia_core::codecs::audio::AudioCodecParameters;
use symphonia_core::errors::{decode_error, unsupported_error, Result};
use symphonia_core::io::ReadBytes;

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

#[allow(dead_code)]
Expand Down Expand Up @@ -46,7 +46,8 @@ impl Atom for AlacAtom {
}

impl AlacAtom {
pub fn fill_codec_params(&self, codec_params: &mut AudioCodecParameters) {
codec_params.for_codec(CODEC_ID_ALAC).with_extra_data(self.extra_data.clone());
pub fn fill_audio_sample_entry(&self, entry: &mut AudioSampleEntry) {
entry.codec_id = CODEC_ID_ALAC;
entry.extra_data = Some(self.extra_data.clone());
}
}
38 changes: 23 additions & 15 deletions symphonia-format-isomp4/src/atoms/avcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,53 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_common::mpeg::video::AVCDecoderConfigurationRecord;
use symphonia_core::codecs::video::well_known::extra_data::VIDEO_EXTRA_DATA_ID_AVC_DECODER_CONFIG;
use symphonia_core::codecs::video::well_known::CODEC_ID_H264;
use symphonia_core::codecs::video::VideoCodecParameters;
use symphonia_core::codecs::video::VideoExtraData;
use symphonia_core::codecs::CodecProfile;
use symphonia_core::errors::{Error, Result};
use symphonia_core::errors::{decode_error, Result};
use symphonia_core::io::ReadBytes;

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

const MAX_ATOM_SIZE: u64 = 1024;

#[allow(dead_code)]
#[derive(Debug)]
pub struct AvcCAtom {
/// AVC extra data (AVCDecoderConfigurationRecord).
extra_data: Box<[u8]>,
extra_data: VideoExtraData,
profile: CodecProfile,
level: u32,
}

impl Atom for AvcCAtom {
fn read<B: ReadBytes>(reader: &mut B, header: AtomHeader) -> Result<Self> {
// The AVCConfiguration atom payload is a single AVCDecoderConfigurationRecord. This record
// forms the defacto codec extra data.
let len = header
.data_len()
.ok_or_else(|| Error::DecodeError("isomp4 (avcC): expected atom size to be known"))?;
// forms the defacto codec extra data. It should not exceed 1kb
let len = match header.data_len() {
Some(len) if len <= MAX_ATOM_SIZE => len as usize,
Some(_) => return decode_error("isomp4 (avcC): atom size is greater than 1kb"),
None => return decode_error("isomp4 (avcC): expected atom size to be known"),
};

let extra_data = reader.read_boxed_slice_exact(len as usize)?;
let extra_data = VideoExtraData {
id: VIDEO_EXTRA_DATA_ID_AVC_DECODER_CONFIG,
data: reader.read_boxed_slice_exact(len)?,
};

let avc_config = AVCDecoderConfigurationRecord::read(&extra_data)?;
let avc_config = AVCDecoderConfigurationRecord::read(&extra_data.data)?;

Ok(Self { extra_data, profile: avc_config.profile, level: avc_config.level })
}
}

impl AvcCAtom {
pub fn fill_codec_params(&self, codec_params: &mut VideoCodecParameters) {
codec_params
.for_codec(CODEC_ID_H264)
.with_profile(self.profile)
.with_level(self.level)
.with_extra_data(self.extra_data.clone());
pub fn fill_video_sample_entry(&self, entry: &mut VisualSampleEntry) {
entry.codec_id = CODEC_ID_H264;
entry.profile = Some(self.profile);
entry.level = Some(self.level);
entry.extra_data.push(self.extra_data.clone());
}
}
7 changes: 4 additions & 3 deletions symphonia-format-isomp4/src/atoms/dac3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_core::codecs::audio::well_known::CODEC_ID_AC3;
use symphonia_core::codecs::audio::AudioCodecParameters;
use symphonia_core::errors::{Error, Result};
use symphonia_core::io::ReadBytes;

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

#[allow(dead_code)]
Expand All @@ -33,7 +33,8 @@ impl Atom for Dac3Atom {
}

impl Dac3Atom {
pub fn fill_codec_params(&self, codec_params: &mut AudioCodecParameters) {
codec_params.for_codec(CODEC_ID_AC3).with_extra_data(self.extra_data.clone());
pub fn fill_audio_sample_entry(&self, entry: &mut AudioSampleEntry) {
entry.codec_id = CODEC_ID_AC3;
entry.extra_data = Some(self.extra_data.clone());
}
}
7 changes: 4 additions & 3 deletions symphonia-format-isomp4/src/atoms/dec3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_core::codecs::audio::well_known::CODEC_ID_EAC3;
use symphonia_core::codecs::audio::AudioCodecParameters;
use symphonia_core::errors::{Error, Result};
use symphonia_core::io::ReadBytes;

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

#[allow(dead_code)]
Expand All @@ -33,7 +33,8 @@ impl Atom for Dec3Atom {
}

impl Dec3Atom {
pub fn fill_codec_params(&self, codec_params: &mut AudioCodecParameters) {
codec_params.for_codec(CODEC_ID_EAC3).with_extra_data(self.extra_data.clone());
pub fn fill_audio_sample_entry(&self, entry: &mut AudioSampleEntry) {
entry.codec_id = CODEC_ID_EAC3;
entry.extra_data = Some(self.extra_data.clone());
}
}
49 changes: 49 additions & 0 deletions symphonia-format-isomp4/src/atoms/dovi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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::video::well_known::extra_data::VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG;
use symphonia_core::codecs::video::VideoExtraData;
use symphonia_core::errors::{decode_error, Result};
use symphonia_core::io::ReadBytes;

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

const DOVI_CONFIG_SIZE: u64 = 24;

#[allow(dead_code)]
#[derive(Debug)]
pub struct DoviAtom {
extra_data: VideoExtraData,
}

impl Atom for DoviAtom {
fn read<B: ReadBytes>(reader: &mut B, header: AtomHeader) -> Result<Self> {
// The Dolby Vision Configuration atom payload (dvvC and dvcC).
// Contains DOVIDecoderConfigurationRecord, point 3.2 from
// https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolby_vision_bitstreams_within_the_iso_base_media_file_format_dec2017.pdf
// It should be 24 bytes
let len = match header.data_len() {
Some(len @ DOVI_CONFIG_SIZE) => len as usize,
Some(_) => return decode_error("isomp4 (dvcC/dvvC): atom size is not 24 bytes"),
None => return decode_error("isomp4 (dvcC/dvvC): expected atom size to be known"),
};

let dovi_data = VideoExtraData {
sscobici marked this conversation as resolved.
Show resolved Hide resolved
id: VIDEO_EXTRA_DATA_ID_DOLBY_VISION_CONFIG,
data: reader.read_boxed_slice_exact(len)?,
};

Ok(Self { extra_data: dovi_data })
}
}

impl DoviAtom {
pub fn fill_video_sample_entry(&self, entry: &mut VisualSampleEntry) {
entry.extra_data.push(self.extra_data.clone());
}
}
Loading