mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-02 17:53:48 +00:00
net/hlsmultivariantsink: Drop cros-codecs as a dependency
This copies over the required bits of code from cros-codecs and drops the dependency on cros-codecs. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2054>
This commit is contained in:
parent
e3049e272c
commit
6911e865c9
15 changed files with 4012 additions and 76 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -1342,23 +1342,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cros-codecs"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4862478feb3de946be3e4b7f316b18957a45d88d1c3695c606bdf6e76a2d2bfb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitreader",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"crc32fast",
|
||||
"enumn",
|
||||
"log",
|
||||
"nix",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
|
@ -2730,8 +2713,11 @@ name = "gst-plugin-hlsmultivariantsink"
|
|||
version = "0.14.0-alpha.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitreader",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"cros-codecs",
|
||||
"enumn",
|
||||
"gio",
|
||||
"gst-plugin-fmp4",
|
||||
"gst-plugin-hlssink3",
|
||||
|
@ -2743,7 +2729,7 @@ dependencies = [
|
|||
"gstreamer-pbutils",
|
||||
"gstreamer-video",
|
||||
"m3u8-rs",
|
||||
"sprintf",
|
||||
"thiserror 2.0.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -14,10 +14,13 @@ gst-app.workspace = true
|
|||
gio.workspace = true
|
||||
m3u8-rs = "5.0"
|
||||
chrono = "0.4"
|
||||
sprintf = "0.2"
|
||||
gst-pbutils = { workspace = true, features = ["v1_22"] }
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
cros-codecs = { version = "0.0.5", default-features = false }
|
||||
anyhow = "1"
|
||||
bitreader = "0.3"
|
||||
bytes = "1"
|
||||
byteorder = "1.5"
|
||||
enumn = "0.1"
|
||||
thiserror = "2"
|
||||
|
||||
[dev-dependencies]
|
||||
gst-audio.workspace = true
|
||||
|
|
26
net/hlsmultivariantsink/src/cros_codecs/LICENSE
Normal file
26
net/hlsmultivariantsink/src/cros_codecs/LICENSE
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright 2022 The ChromiumOS Authors
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1
net/hlsmultivariantsink/src/cros_codecs/README.md
Normal file
1
net/hlsmultivariantsink/src/cros_codecs/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
The code here has been taken from [cros-codecs](https://android.googlesource.com/platform/system/cros-codecs/) with the GitHub mirror being [here](https://github.com/chromeos/cros-codecs). Only the required bits for parsing of SPS in H264/H265 has been copied. Copied code is from the released version on crates.io at the time of this writing was v0.0.5.
|
3
net/hlsmultivariantsink/src/cros_codecs/h264/mod.rs
Normal file
3
net/hlsmultivariantsink/src/cros_codecs/h264/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod nalu;
|
||||
pub mod nalu_reader;
|
||||
pub mod parser;
|
107
net/hlsmultivariantsink/src/cros_codecs/h264/nalu.rs
Normal file
107
net/hlsmultivariantsink/src/cros_codecs/h264/nalu.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2023 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Debug;
|
||||
use std::io::Cursor;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use bytes::Buf;
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
pub trait Header: Sized {
|
||||
/// Parse the NALU header, returning it.
|
||||
fn parse<T: AsRef<[u8]>>(cursor: &Cursor<T>) -> anyhow::Result<Self>;
|
||||
/// Whether this header type indicates EOS.
|
||||
fn is_end(&self) -> bool;
|
||||
/// The length of the header.
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Nalu<'a, U> {
|
||||
pub header: U,
|
||||
/// The mapping that backs this NALU. Possibly shared with the other NALUs
|
||||
/// in the Access Unit.
|
||||
pub data: Cow<'a, [u8]>,
|
||||
|
||||
pub size: usize,
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
impl<'a, U> Nalu<'a, U>
|
||||
where
|
||||
U: Debug + Header,
|
||||
{
|
||||
/// Find the next Annex B encoded NAL unit.
|
||||
pub fn next(cursor: &mut Cursor<&'a [u8]>) -> anyhow::Result<Nalu<'a, U>> {
|
||||
let bitstream = cursor.clone().into_inner();
|
||||
let pos = usize::try_from(cursor.position())?;
|
||||
|
||||
// Find the start code for this NALU
|
||||
let current_nalu_offset = match Nalu::<'a, U>::find_start_code(cursor, pos) {
|
||||
Some(offset) => offset,
|
||||
None => return Err(anyhow!("No NAL found")),
|
||||
};
|
||||
|
||||
let mut start_code_offset = pos + current_nalu_offset;
|
||||
|
||||
// If the preceding byte is 00, then we actually have a four byte SC,
|
||||
// i.e. 00 00 00 01 Where the first 00 is the "zero_byte()"
|
||||
if start_code_offset > 0 && cursor.get_ref()[start_code_offset - 1] == 00 {
|
||||
start_code_offset -= 1;
|
||||
}
|
||||
|
||||
// The NALU offset is its offset + 3 bytes to skip the start code.
|
||||
let nalu_offset = pos + current_nalu_offset + 3;
|
||||
|
||||
// Set the bitstream position to the start of the current NALU
|
||||
cursor.set_position(u64::try_from(nalu_offset)?);
|
||||
|
||||
let hdr = U::parse(cursor)?;
|
||||
|
||||
// Find the start of the subsequent NALU.
|
||||
let mut next_nalu_offset = match Nalu::<'a, U>::find_start_code(cursor, nalu_offset) {
|
||||
Some(offset) => offset,
|
||||
None => cursor.chunk().len(), // Whatever data is left must be part of the current NALU
|
||||
};
|
||||
|
||||
while next_nalu_offset > 0 && cursor.get_ref()[nalu_offset + next_nalu_offset - 1] == 00 {
|
||||
// Discard trailing_zero_8bits
|
||||
next_nalu_offset -= 1;
|
||||
}
|
||||
|
||||
let nal_size = if hdr.is_end() {
|
||||
// the NALU is comprised of only the header
|
||||
hdr.len()
|
||||
} else {
|
||||
next_nalu_offset
|
||||
};
|
||||
|
||||
Ok(Nalu {
|
||||
header: hdr,
|
||||
data: Cow::from(&bitstream[start_code_offset..nalu_offset + nal_size]),
|
||||
size: nal_size,
|
||||
offset: nalu_offset - start_code_offset,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, U> Nalu<'a, U>
|
||||
where
|
||||
U: Debug,
|
||||
{
|
||||
fn find_start_code(data: &mut Cursor<&'a [u8]>, offset: usize) -> Option<usize> {
|
||||
// discard all zeroes until the start code pattern is found
|
||||
data.get_ref()[offset..]
|
||||
.windows(3)
|
||||
.position(|window| window == [0x00, 0x00, 0x01])
|
||||
}
|
||||
}
|
||||
|
||||
impl<U> AsRef<[u8]> for Nalu<'_, U> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.data[self.offset..self.offset + self.size]
|
||||
}
|
||||
}
|
180
net/hlsmultivariantsink/src/cros_codecs/h264/nalu_reader.rs
Normal file
180
net/hlsmultivariantsink/src/cros_codecs/h264/nalu_reader.rs
Normal file
|
@ -0,0 +1,180 @@
|
|||
// Copyright 2022 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::io::Cursor;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Context;
|
||||
use byteorder::ReadBytesExt;
|
||||
use thiserror::Error;
|
||||
|
||||
/// A bit reader for h264 bitstreams. It properly handles emulation-prevention
|
||||
/// bytes and stop bits.
|
||||
pub(crate) struct NaluReader<'a> {
|
||||
/// A reference into the next unread byte in the stream.
|
||||
data: Cursor<&'a [u8]>,
|
||||
/// Contents of the current byte. First unread bit starting at position 8 -
|
||||
/// num_remaining_bits_in_curr_bytes.
|
||||
curr_byte: u8,
|
||||
/// Number of bits remaining in `curr_byte`
|
||||
num_remaining_bits_in_curr_byte: usize,
|
||||
/// Used in epb detection.
|
||||
prev_two_bytes: u16,
|
||||
/// Number of epbs (i.e. 0x000003) we found.
|
||||
num_epb: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub(crate) enum GetByteError {
|
||||
#[error("reader ran out of bits")]
|
||||
OutOfBits,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub(crate) enum ReadBitsError {
|
||||
#[error("more than 31 ({0}) bits were requested")]
|
||||
TooManyBytesRequested(usize),
|
||||
#[error("failed to advance the current byte")]
|
||||
GetByte(#[from] GetByteError),
|
||||
#[error("failed to convert read input to target type")]
|
||||
ConversionFailed,
|
||||
}
|
||||
|
||||
impl<'a> NaluReader<'a> {
|
||||
pub fn new(data: &'a [u8]) -> Self {
|
||||
Self {
|
||||
data: Cursor::new(data),
|
||||
curr_byte: Default::default(),
|
||||
num_remaining_bits_in_curr_byte: Default::default(),
|
||||
prev_two_bytes: 0xffff,
|
||||
num_epb: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a single bit from the stream.
|
||||
pub fn read_bit(&mut self) -> Result<bool, ReadBitsError> {
|
||||
let bit = self.read_bits::<u32>(1)?;
|
||||
match bit {
|
||||
1 => Ok(true),
|
||||
0 => Ok(false),
|
||||
_ => panic!("Unexpected value {}", bit),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read up to 31 bits from the stream.
|
||||
pub fn read_bits<U: TryFrom<u32>>(&mut self, num_bits: usize) -> Result<U, ReadBitsError> {
|
||||
if num_bits > 31 {
|
||||
return Err(ReadBitsError::TooManyBytesRequested(num_bits));
|
||||
}
|
||||
|
||||
let mut bits_left = num_bits;
|
||||
let mut out = 0u32;
|
||||
|
||||
while self.num_remaining_bits_in_curr_byte < bits_left {
|
||||
out |= (self.curr_byte as u32) << (bits_left - self.num_remaining_bits_in_curr_byte);
|
||||
bits_left -= self.num_remaining_bits_in_curr_byte;
|
||||
self.update_curr_byte()?;
|
||||
}
|
||||
|
||||
out |= (self.curr_byte >> (self.num_remaining_bits_in_curr_byte - bits_left)) as u32;
|
||||
out &= (1 << num_bits) - 1;
|
||||
self.num_remaining_bits_in_curr_byte -= bits_left;
|
||||
|
||||
U::try_from(out).map_err(|_| ReadBitsError::ConversionFailed)
|
||||
}
|
||||
|
||||
/// Skip `num_bits` bits from the stream.
|
||||
pub fn skip_bits(&mut self, mut num_bits: usize) -> Result<(), ReadBitsError> {
|
||||
while num_bits > 0 {
|
||||
let n = std::cmp::min(num_bits, 31);
|
||||
self.read_bits::<u32>(n)?;
|
||||
num_bits -= n;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_ue<U: TryFrom<u32>>(&mut self) -> anyhow::Result<U> {
|
||||
let mut num_bits = 0;
|
||||
|
||||
while self.read_bits::<u32>(1)? == 0 {
|
||||
num_bits += 1;
|
||||
}
|
||||
|
||||
if num_bits > 31 {
|
||||
return Err(anyhow!("invalid stream"));
|
||||
}
|
||||
|
||||
let value = ((1u32 << num_bits) - 1)
|
||||
.checked_add(self.read_bits::<u32>(num_bits)?)
|
||||
.context("read number cannot fit in 32 bits")?;
|
||||
|
||||
U::try_from(value).map_err(|_| anyhow!("conversion error"))
|
||||
}
|
||||
|
||||
pub fn read_ue_bounded<U: TryFrom<u32>>(&mut self, min: u32, max: u32) -> anyhow::Result<U> {
|
||||
let ue = self.read_ue()?;
|
||||
if ue > max || ue < min {
|
||||
Err(anyhow!(
|
||||
"Value out of bounds: expected {} - {}, got {}",
|
||||
min,
|
||||
max,
|
||||
ue
|
||||
))
|
||||
} else {
|
||||
Ok(U::try_from(ue).map_err(|_| anyhow!("Conversion error"))?)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_ue_max<U: TryFrom<u32>>(&mut self, max: u32) -> anyhow::Result<U> {
|
||||
self.read_ue_bounded(0, max)
|
||||
}
|
||||
|
||||
pub fn read_se<U: TryFrom<i32>>(&mut self) -> anyhow::Result<U> {
|
||||
let ue = self.read_ue::<u32>()? as i32;
|
||||
|
||||
if ue % 2 == 0 {
|
||||
Ok(U::try_from(-ue / 2).map_err(|_| anyhow!("Conversion error"))?)
|
||||
} else {
|
||||
Ok(U::try_from(ue / 2 + 1).map_err(|_| anyhow!("Conversion error"))?)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_se_bounded<U: TryFrom<i32>>(&mut self, min: i32, max: i32) -> anyhow::Result<U> {
|
||||
let se = self.read_se()?;
|
||||
if se < min || se > max {
|
||||
Err(anyhow!(
|
||||
"Value out of bounds, expected between {}-{}, got {}",
|
||||
min,
|
||||
max,
|
||||
se
|
||||
))
|
||||
} else {
|
||||
Ok(U::try_from(se).map_err(|_| anyhow!("Conversion error"))?)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_byte(&mut self) -> Result<u8, GetByteError> {
|
||||
self.data.read_u8().map_err(|_| GetByteError::OutOfBits)
|
||||
}
|
||||
|
||||
fn update_curr_byte(&mut self) -> Result<(), GetByteError> {
|
||||
let mut byte = self.get_byte()?;
|
||||
|
||||
if self.prev_two_bytes == 0 && byte == 0x03 {
|
||||
// We found an epb
|
||||
self.num_epb += 1;
|
||||
// Read another byte
|
||||
byte = self.get_byte()?;
|
||||
// We need another 3 bytes before another epb can happen.
|
||||
self.prev_two_bytes = 0xffff;
|
||||
}
|
||||
|
||||
self.num_remaining_bits_in_curr_byte = 8;
|
||||
self.prev_two_bytes = (self.prev_two_bytes << 8) | u16::from(byte);
|
||||
|
||||
self.curr_byte = byte;
|
||||
Ok(())
|
||||
}
|
||||
}
|
1231
net/hlsmultivariantsink/src/cros_codecs/h264/parser.rs
Normal file
1231
net/hlsmultivariantsink/src/cros_codecs/h264/parser.rs
Normal file
File diff suppressed because it is too large
Load diff
1
net/hlsmultivariantsink/src/cros_codecs/h265/mod.rs
Normal file
1
net/hlsmultivariantsink/src/cros_codecs/h265/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod parser;
|
2440
net/hlsmultivariantsink/src/cros_codecs/h265/parser.rs
Normal file
2440
net/hlsmultivariantsink/src/cros_codecs/h265/parser.rs
Normal file
File diff suppressed because it is too large
Load diff
2
net/hlsmultivariantsink/src/cros_codecs/mod.rs
Normal file
2
net/hlsmultivariantsink/src/cros_codecs/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod h264;
|
||||
pub mod h265;
|
|
@ -1308,12 +1308,10 @@ impl HlsMultivariantSink {
|
|||
drop(state);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn parse_h264_sps(&self, buffer: &[u8], group_id: String) {
|
||||
use cros_codecs::codec::h264::parser as H264Parser;
|
||||
use crate::cros_codecs::h264::parser as H264Parser;
|
||||
use std::io::Cursor;
|
||||
|
||||
let mut caps_codec_str: Option<String> = None;
|
||||
let mut cursor = Cursor::new(buffer);
|
||||
let mut parser = H264Parser::Parser::default();
|
||||
|
||||
|
@ -1340,34 +1338,19 @@ impl HlsMultivariantSink {
|
|||
constraint_flags += 2u32.pow(7 - index as u32) * (*bit) as u32;
|
||||
});
|
||||
|
||||
match sprintf::sprintf!("avc1.%02X%02X%02X", profile, constraint_flags, level) {
|
||||
Ok(codec_str) => {
|
||||
caps_codec_str = Some(codec_str);
|
||||
}
|
||||
Err(e) => {
|
||||
gst::element_error!(
|
||||
self.obj(),
|
||||
gst::ResourceError::Failed,
|
||||
["Failed to format codec string with error: {:?}", e]
|
||||
);
|
||||
}
|
||||
}
|
||||
let codec_str = format!("avc1.{profile:02X}{constraint_flags:02X}{level:02X}");
|
||||
|
||||
self.build_codec_str_and_write_multivariant_playlist(codec_str, group_id);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(codec_str) = caps_codec_str {
|
||||
self.build_codec_str_and_write_multivariant_playlist(codec_str, group_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn parse_h265_sps(&self, buffer: &[u8], group_id: String) {
|
||||
use cros_codecs::codec::h265::parser as H265Parser;
|
||||
use crate::cros_codecs::h265::parser as H265Parser;
|
||||
use std::io::Cursor;
|
||||
|
||||
let mut caps_codec_str: Option<String> = None;
|
||||
let mut cursor = Cursor::new(buffer);
|
||||
let mut parser = H265Parser::Parser::default();
|
||||
|
||||
|
@ -1429,37 +1412,15 @@ impl HlsMultivariantSink {
|
|||
constraint_indicator_flag += 2u32.pow(7 - index as u32) * (*bit) as u32;
|
||||
});
|
||||
|
||||
match sprintf::sprintf!(
|
||||
"%s.%X.%hu.%c%d.%02X",
|
||||
codec_str,
|
||||
profile_idc,
|
||||
compat_flag_parameter,
|
||||
tier_flag,
|
||||
level_idc,
|
||||
constraint_indicator_flag
|
||||
) {
|
||||
Ok(codec_str) => {
|
||||
caps_codec_str = Some(codec_str);
|
||||
}
|
||||
Err(e) => {
|
||||
gst::element_error!(
|
||||
self.obj(),
|
||||
gst::ResourceError::Failed,
|
||||
["Failed to format codec string with error: {:?}", e]
|
||||
);
|
||||
}
|
||||
}
|
||||
let codec_str = format!("{codec_str}.{profile_idc:X}.{compat_flag_parameter}.{tier_flag}{level_idc}.{constraint_indicator_flag:02X}");
|
||||
|
||||
self.build_codec_str_and_write_multivariant_playlist(codec_str, group_id);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(codec_str) = caps_codec_str {
|
||||
self.build_codec_str_and_write_multivariant_playlist(codec_str, group_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn parse_sps(
|
||||
&self,
|
||||
caps: &gst::Caps,
|
||||
|
@ -1510,12 +1471,7 @@ impl HlsMultivariantSink {
|
|||
* with SPS. codec-utils helpers cannot give us codec string
|
||||
* without the codec_data. For MPEG-TS, parse SPS and figure
|
||||
* out the relevant information to generate codec string.
|
||||
*
|
||||
* parse_sps function relies on cros_codecs which supports
|
||||
* only linux. On other platforms for MPEG-TS, users need to
|
||||
* specify codec string manually.
|
||||
*/
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let settings = self.settings.lock().unwrap();
|
||||
let is_mpegts = settings.muxer_type == HlsMultivariantSinkMuxerType::MpegTs;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
use gst::glib;
|
||||
use gst::prelude::*;
|
||||
|
||||
mod cros_codecs;
|
||||
mod imp;
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)]
|
||||
|
|
|
@ -812,7 +812,6 @@ low/video.m3u8
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn hlsmultivariantsink_multiple_audio_rendition_multiple_video_variant_with_mpegts(
|
||||
) -> Result<(), ()> {
|
||||
|
@ -988,7 +987,6 @@ low/video.m3u8
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn hlsmultivariantsink_multiple_video_variant_with_mpegts_audio_video_muxed() -> Result<(), ()> {
|
||||
init();
|
||||
|
|
|
@ -18,6 +18,7 @@ Ines = "Ines"
|
|||
|
||||
# net/hlsmultivariantsink
|
||||
cros = "cros"
|
||||
ue = "ue"
|
||||
|
||||
[files]
|
||||
extend-exclude = [
|
||||
|
|
Loading…
Reference in a new issue