Skip to content

Commit

Permalink
core, isomp4: collect many extra_data in VideoCodecParameters
Browse files Browse the repository at this point in the history
  • Loading branch information
sscobici committed Oct 20, 2024
1 parent 5ce3a2a commit 58b5718
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 147 deletions.
61 changes: 46 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,23 @@ pub mod well_known {
/// VC-1 Advanced Profile
pub const CODEC_PROFILE_VC1_ADVANCED: CodecProfile = CodecProfile(2);
}

pub mod extra_data {
use super::super::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);
}
}
27 changes: 16 additions & 11 deletions symphonia-format-isomp4/src/atoms/avcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@
// 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::io::ReadBytes;

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

use super::stsd::VisualSampleEntry;

#[allow(dead_code)]
#[derive(Debug)]
pub struct AvcCAtom {
/// AVC extra data (AVCDecoderConfigurationRecord).
extra_data: Box<[u8]>,
extra_data: VideoExtraData,
profile: CodecProfile,
level: u32,
}
Expand All @@ -31,20 +34,22 @@ impl Atom for AvcCAtom {
.data_len()
.ok_or_else(|| Error::DecodeError("isomp4 (avcC): expected atom size to be known"))?;

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

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

Ok(Self { extra_data, profile: avc_config.profile, level: avc_config.level })
Ok(Self { extra_data: avc_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());
}
}
17 changes: 11 additions & 6 deletions symphonia-format-isomp4/src/atoms/esds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_core::codecs::audio::AudioCodecParameters;
use symphonia_core::codecs::video::VideoCodecParameters;
use symphonia_core::codecs::video::{VideoExtraData, VIDEO_EXTRA_DATA_ID_NULL};
use symphonia_core::codecs::CodecId;
use symphonia_core::errors::{decode_error, unsupported_error, Error, Result};
use symphonia_core::io::{FiniteStream, ReadBytes, ScopedStream};
Expand All @@ -15,6 +15,8 @@ use crate::atoms::{Atom, AtomHeader};

use log::{debug, warn};

use super::stsd::VisualSampleEntry;

const ES_DESCRIPTOR: u8 = 0x03;
const DECODER_CONFIG_DESCRIPTOR: u8 = 0x04;
const DECODER_SPECIFIC_DESCRIPTOR: u8 = 0x05;
Expand Down Expand Up @@ -109,27 +111,30 @@ impl EsdsAtom {
}

/// If the elementary stream descriptor describes an video stream, populate the provided
/// video codec parameters.
pub fn fill_video_codec_params(&self, codec_params: &mut VideoCodecParameters) -> Result<()> {
/// video sample entry.
pub fn fill_video_sample_entry(&self, entry: &mut VisualSampleEntry) -> Result<()> {
use symphonia_core::codecs::video::CODEC_ID_NULL_VIDEO;

match get_codec_id_from_object_type(self.descriptor.dec_config.object_type_indication) {
Some(CodecId::Video(id)) => {
// Object type indication identified an video codec.
codec_params.for_codec(id);
entry.codec_id = id;
}
Some(_) => {
// Object type indication identified a non-video codec. This is unexpected.
return decode_error("isomp4 (esds): expected a video codec type");
}
None => {
// Unknown object type indication.
codec_params.for_codec(CODEC_ID_NULL_VIDEO);
entry.codec_id = CODEC_ID_NULL_VIDEO;
}
}

if let Some(ds_config) = &self.descriptor.dec_config.dec_specific_info {
codec_params.with_extra_data(ds_config.extra_data.clone());
entry.extra_data.push(VideoExtraData {
id: VIDEO_EXTRA_DATA_ID_NULL,
data: ds_config.extra_data.clone(),
});
}

Ok(())
Expand Down
27 changes: 16 additions & 11 deletions symphonia-format-isomp4/src/atoms/hvcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use symphonia_common::mpeg::video::HEVCDecoderConfigurationRecord;
use symphonia_core::codecs::video::well_known::extra_data::VIDEO_EXTRA_DATA_ID_HEVC_DECODER_CONFIG;
use symphonia_core::codecs::video::well_known::CODEC_ID_HEVC;
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::io::ReadBytes;

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

use super::stsd::VisualSampleEntry;

#[allow(dead_code)]
#[derive(Debug)]
pub struct HvcCAtom {
/// HEVC extra data (HEVCDecoderConfigurationRecord).
extra_data: Box<[u8]>,
extra_data: VideoExtraData,
profile: CodecProfile,
level: u32,
}
Expand All @@ -31,20 +34,22 @@ impl Atom for HvcCAtom {
.data_len()
.ok_or_else(|| Error::DecodeError("isomp4 (hvcC): expected atom size to be known"))?;

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

let hevc_config = HEVCDecoderConfigurationRecord::read(&extra_data)?;
let hevc_config = HEVCDecoderConfigurationRecord::read(&hevc_data.data)?;

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

impl HvcCAtom {
pub fn fill_codec_params(&self, codec_params: &mut VideoCodecParameters) {
codec_params
.for_codec(CODEC_ID_HEVC)
.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_HEVC;
entry.profile = Some(self.profile);
entry.level = Some(self.level);
entry.extra_data.push(self.extra_data.clone());
}
}
Loading

0 comments on commit 58b5718

Please sign in to comment.