diff --git a/media/webrtc/signaling/gtest/sdp_unittests.cpp b/media/webrtc/signaling/gtest/sdp_unittests.cpp index 17cc91822599..f65c2f79620d 100644 --- a/media/webrtc/signaling/gtest/sdp_unittests.cpp +++ b/media/webrtc/signaling/gtest/sdp_unittests.cpp @@ -3750,7 +3750,6 @@ const std::string kMalformedImageattr = TEST_P(NewSdpTest, CheckMalformedImageattr) { - SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432930 if (::testing::get<0>(GetParam())) { // Don't do a parse/serialize before running this test return; diff --git a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp index 81d70502cfdd..2fa52bfaaa9e 100644 --- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp +++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp @@ -1023,6 +1023,65 @@ RsdparsaSdpAttributeList::LoadSimulcast(RustAttributeList* attributeList) } } +SdpImageattrAttributeList::XYRange +LoadImageattrXYRange(const RustSdpAttributeImageAttrXYRange& rustXYRange) +{ + SdpImageattrAttributeList::XYRange xyRange; + + if (!rustXYRange.discrete_values) { + xyRange.min = rustXYRange.min; + xyRange.max = rustXYRange.max; + xyRange.step = rustXYRange.step; + + } else { + xyRange.discreteValues = convertU32Vec(rustXYRange.discrete_values); + } + + return xyRange; +} + +std::vector +LoadImageattrSets(const RustSdpAttributeImageAttrSetVec* rustSets) +{ + std::vector sets; + + size_t rustSetCount = sdp_imageattr_get_set_count(rustSets); + if (!rustSetCount) { + return sets; + } + + auto rustSetArray = MakeUnique(rustSetCount); + sdp_imageattr_get_sets(rustSets, rustSetCount, rustSetArray.get()); + + for(size_t i = 0; i < rustSetCount; i++) { + const RustSdpAttributeImageAttrSet& rustSet = rustSetArray[i]; + SdpImageattrAttributeList::Set set; + + set.xRange = LoadImageattrXYRange(rustSet.x); + set.yRange = LoadImageattrXYRange(rustSet.y); + + if (rustSet.has_sar) { + if (!rustSet.sar.discrete_values) { + set.sRange.min = rustSet.sar.min; + set.sRange.max = rustSet.sar.max; + } else { + set.sRange.discreteValues = convertF32Vec(rustSet.sar.discrete_values); + } + } + + if (rustSet.has_par) { + set.pRange.min = rustSet.par.min; + set.pRange.max = rustSet.par.max; + } + + set.qValue = rustSet.q; + + sets.push_back(set); + } + + return sets; +} + void RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) { @@ -1030,17 +1089,31 @@ RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) if (numImageattrs == 0) { return; } - auto rustImageattrs = MakeUnique(numImageattrs); + auto rustImageattrs = MakeUnique(numImageattrs); sdp_get_imageattrs(attributeList, numImageattrs, rustImageattrs.get()); auto imageattrList = MakeUnique(); for(size_t i = 0; i < numImageattrs; i++) { - StringView& imageAttr = rustImageattrs[i]; - std::string image = convertStringView(imageAttr); - std::string error; - size_t errorPos; - if (!imageattrList->PushEntry(image, &error, &errorPos)) { - // TODO: handle error, see Bug 1438237 + const RustSdpAttributeImageAttr& rustImageAttr = rustImageattrs[i]; + + SdpImageattrAttributeList::Imageattr imageAttr; + + if (rustImageAttr.payloadType != std::numeric_limits::max()) { + imageAttr.pt = Some(rustImageAttr.payloadType); } + + if (rustImageAttr.send.sets) { + imageAttr.sendSets = LoadImageattrSets(rustImageAttr.send.sets); + } else { + imageAttr.sendAll = true; + } + + if (rustImageAttr.recv.sets) { + imageAttr.recvSets = LoadImageattrSets(rustImageAttr.recv.sets); + } else { + imageAttr.recvAll = true; + } + + imageattrList->mImageattrs.push_back(imageAttr); } SetAttribute(imageattrList.release()); } diff --git a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp index d0138d887a3c..46a8df2eb230 100644 --- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp +++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp @@ -73,4 +73,32 @@ std::vector convertU16Vec(U16Vec* vec) return ret; } +std::vector convertU32Vec(U32Vec* vec) +{ + std::vector ret; + + size_t len = u32_vec_len(vec); + for (size_t i = 0; i < len; i++) { + uint32_t num; + u32_vec_get(vec, i, &num); + ret.push_back(num); + } + + return ret; +} + +std::vector convertF32Vec(F32Vec* vec) +{ + std::vector ret; + + size_t len = f32_vec_len(vec); + for (size_t i = 0; i < len; i++) { + float flt; + f32_vec_get(vec, i, &flt); + ret.push_back(flt); + } + + return ret; +} + } diff --git a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h index fbe3e5688d5f..6ad1f44e8bb0 100644 --- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h +++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h @@ -26,6 +26,8 @@ std::vector convertStringVec(StringVec* vec); sdp::AddrType convertAddressType(RustSdpAddrType addr); std::vector convertU8Vec(U8Vec* vec); std::vector convertU16Vec(U16Vec* vec); +std::vector convertU32Vec(U32Vec* vec); +std::vector convertF32Vec(F32Vec* vec); } diff --git a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h index d930990120c7..02fdce60bdc7 100644 --- a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h +++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h @@ -20,6 +20,7 @@ struct StringVec; struct U8Vec; struct U32Vec; struct U16Vec; +struct F32Vec; struct RustHeapString; enum class RustSdpAddrType { @@ -131,6 +132,45 @@ struct RustSdpAttributeRid { StringVec* depends; }; +struct RustSdpAttributeImageAttrXYRange { + uint32_t min; + uint32_t max; + uint32_t step; + U32Vec* discrete_values; +}; + +struct RustSdpAttributeImageAttrSRange { + float min; + float max; + F32Vec* discrete_values; +}; + +struct RustSdpAttributeImageAttrPRange { + float min; + float max; +}; + +struct RustSdpAttributeImageAttrSet { + RustSdpAttributeImageAttrXYRange x; + RustSdpAttributeImageAttrXYRange y; + bool has_sar; + RustSdpAttributeImageAttrSRange sar; + bool has_par; + RustSdpAttributeImageAttrPRange par; + float q; +}; + +struct RustSdpAttributeImageAttrSetVec; +struct RustSdpAttributeImageAttrSetList { + RustSdpAttributeImageAttrSetVec* sets; +}; + +struct RustSdpAttributeImageAttr { + uint32_t payloadType; + RustSdpAttributeImageAttrSetList send; + RustSdpAttributeImageAttrSetList recv; +}; + struct RustSdpAttributeFmtpParameters { // H264 uint32_t packetization_mode; @@ -254,6 +294,9 @@ size_t string_vec_len(const StringVec* vec); nsresult string_vec_get_view(const StringVec* vec, size_t index, StringView* str); +size_t f32_vec_len(const F32Vec* vec); +nsresult f32_vec_get(const F32Vec* vec, size_t index, float* ret); + size_t u32_vec_len(const U32Vec* vec); nsresult u32_vec_get(const U32Vec* vec, size_t index, uint32_t* ret); @@ -375,7 +418,11 @@ void sdp_get_rtcpfbs(const RustAttributeList* aList, size_t listSize, size_t sdp_get_imageattr_count(const RustAttributeList* aList); void sdp_get_imageattrs(const RustAttributeList* aList, size_t listSize, - StringView* ret); + RustSdpAttributeImageAttr* ret); + +size_t sdp_imageattr_get_set_count(const RustSdpAttributeImageAttrSetVec* sets); +void sdp_imageattr_get_sets(const RustSdpAttributeImageAttrSetVec* sets, + size_t listSize, RustSdpAttributeImageAttrSet* ret); size_t sdp_get_sctpmap_count(const RustAttributeList* aList); void sdp_get_sctpmaps(const RustAttributeList* aList, size_t listSize, diff --git a/media/webrtc/signaling/src/sdp/SdpAttribute.h b/media/webrtc/signaling/src/sdp/SdpAttribute.h index 31896c63a2f1..48212aa1d61b 100644 --- a/media/webrtc/signaling/src/sdp/SdpAttribute.h +++ b/media/webrtc/signaling/src/sdp/SdpAttribute.h @@ -721,9 +721,13 @@ public: public: XYRange() : min(0), max(0), step(1) {} void Serialize(std::ostream& os) const; + // TODO: Remove this Bug 1469702 bool Parse(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseAfterBracket(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseAfterMin(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseDiscreteValues(std::istream& is, std::string* error); std::vector discreteValues; // min/max are used iff discreteValues is empty @@ -737,9 +741,13 @@ public: public: SRange() : min(0), max(0) {} void Serialize(std::ostream& os) const; + // TODO: Remove this Bug 1469702 bool Parse(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseAfterBracket(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseAfterMin(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseDiscreteValues(std::istream& is, std::string* error); bool IsSet() const { @@ -756,6 +764,7 @@ public: public: PRange() : min(0), max(0) {} void Serialize(std::ostream& os) const; + // TODO: Remove this Bug 1469702 bool Parse(std::istream& is, std::string* error); bool IsSet() const { @@ -770,6 +779,7 @@ public: public: Set() : qValue(-1) {} void Serialize(std::ostream& os) const; + // TODO: Remove this Bug 1469702 bool Parse(std::istream& is, std::string* error); XYRange xRange; XYRange yRange; @@ -783,7 +793,9 @@ public: public: Imageattr() : pt(), sendAll(false), recvAll(false) {} void Serialize(std::ostream& os) const; + // TODO: Remove this Bug 1469702 bool Parse(std::istream& is, std::string* error); + // TODO: Remove this Bug 1469702 bool ParseSets(std::istream& is, std::string* error); // If not set, this means all payload types Maybe pt; @@ -794,6 +806,8 @@ public: }; virtual void Serialize(std::ostream& os) const override; + + // TODO: Remove this Bug 1469702 bool PushEntry(const std::string& raw, std::string* error, size_t* errorPos); std::vector mImageattrs; diff --git a/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs b/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs index bb69b769c154..b8faab71471c 100644 --- a/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs +++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs @@ -1,6 +1,7 @@ use std::net::IpAddr; use std::str::FromStr; use std::fmt; +use std::iter; use SdpType; use error::SdpParserInternalError; @@ -293,16 +294,14 @@ pub struct SdpAttributeFingerprint { #[cfg_attr(feature="serialize", derive(Serialize))] pub enum SdpAttributeImageAttrXYRange { Range(u32,u32,Option), // min, max, step - DiscrateValues(Vec), - Value(u32) + DiscreteValues(Vec), } #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature="serialize", derive(Serialize))] pub enum SdpAttributeImageAttrSRange { Range(f32,f32), // min, max - DiscrateValues(Vec), - Value(f32) + DiscreteValues(Vec), } #[derive(Debug, PartialEq, Clone)] @@ -1222,17 +1221,50 @@ fn parse_ice_options(to_parse: &str) -> Result Result { - if to_parse.starts_with("[") { - if !to_parse.ends_with("]") { - return Err(SdpParserInternalError::Generic( - "imageattr's xyrange has no closing tag ']'".to_string() - )) +fn parse_imageattr_tokens(to_parse: &str, separator: char) -> Vec { + let mut tokens = Vec::new(); + let mut open_braces_counter = 0; + let mut current_tokens = Vec::new(); + + for token in to_parse.split(separator) { + if token.contains("[") { + open_braces_counter+=1; } + if token.contains("]") { + open_braces_counter-=1; + } + + current_tokens.push(token.to_string()); + + if open_braces_counter == 0 { + tokens.push(current_tokens.join(&separator.to_string())); + current_tokens = Vec::new(); + } + } + + tokens +} + +fn parse_imagettr_braced_token(to_parse: &str) -> Option<&str> { + if !to_parse.ends_with("]") { + return None; + } + + Some(&to_parse[1..to_parse.len()-1]) +} + +fn parse_image_attr_xyrange(to_parse: &str) -> Result { + if to_parse.starts_with("[") { + let value_tokens = parse_imagettr_braced_token(to_parse).ok_or( + SdpParserInternalError::Generic( + "imageattr's xyrange has no closing tag ']'".to_string() + ) + )?; if to_parse.contains(":") { // Range values - let range_tokens:Vec<&str> = to_parse[1..to_parse.len()-1].split(":").collect(); + let range_tokens:Vec<&str> = value_tokens.split(":").collect(); if range_tokens.len() == 3 { Ok(SdpAttributeImageAttrXYRange::Range( @@ -1253,57 +1285,31 @@ fn parse_image_attr_xyrange(to_parse: &str) -> Result()) - .collect::, _>>()?; + let values = value_tokens.split(",") + .map(|x| x.parse::()) + .collect::, _>>()?; - if values.len() == 0 { + if values.len() < 2 { return Err(SdpParserInternalError::Generic( - "imageattr's discrete value list is empty".to_string() + "imageattr's discrete value list must have at least two elements".to_string() )) } - Ok(SdpAttributeImageAttrXYRange::DiscrateValues(values)) + Ok(SdpAttributeImageAttrXYRange::DiscreteValues(values)) } } else { - Ok(SdpAttributeImageAttrXYRange::Value(to_parse.parse::()?)) + Ok(SdpAttributeImageAttrXYRange::DiscreteValues(vec![to_parse.parse::()?])) } } -fn parse_image_attr_set(to_parse: &str) -> Result { - let result_from_option = |opt, error_msg: &str| { - match opt { - Some(x) => Ok(x), - None => Err(SdpParserInternalError::Generic(error_msg.to_string())) - } - }; +fn parse_image_attr_set(to_parse: &str) -> Result { + let mut tokens = parse_imageattr_tokens(to_parse, ',').into_iter(); - let mut tokens = Vec::new(); - let mut currently_in_braces = false; - let mut current_tokens = Vec::new(); - - for token in to_parse.split(",") { - if token.contains("[") { - currently_in_braces = true; - } - if token.contains("]") { - currently_in_braces = false; - } - - current_tokens.push(token.to_string()); - - if !currently_in_braces { - tokens.push(current_tokens.join(",")); - current_tokens = Vec::new(); - } - } - - - let mut tokens = tokens.into_iter(); - - let x_token = result_from_option(tokens.next(),"imageattr set is missing the 'x=' token")?; + let x_token = tokens.next().ok_or(SdpParserInternalError::Generic( + "imageattr set is missing the 'x=' token".to_string() + ))?; if !x_token.starts_with("x=") { return Err(SdpParserInternalError::Generic( "The first token in an imageattr set must begin with 'x='".to_string() @@ -1312,7 +1318,9 @@ fn parse_image_attr_set(to_parse: &str) -> Result()?; + let max = minmax_pair[1].parse::()?; if min >= max { return Err(SdpParserInternalError::Generic( @@ -1354,26 +1357,26 @@ fn parse_image_attr_set(to_parse: &str) -> Result()) - .collect::, _>>()?; + let values = sar_values.split(",") + .map(|x| x.parse::()) + .collect::, _>>()?; - if values.len() == 0 { + if values.len() < 2 { return Err(SdpParserInternalError::Generic( - "imageattr's sar discrete value list is empty".to_string() + "imageattr's sar discrete value list must have at least two values" + .to_string() )) } @@ -1388,31 +1391,33 @@ fn parse_image_attr_set(to_parse: &str) -> Result()?)) + sar = Some(SdpAttributeImageAttrSRange::DiscreteValues( + vec![value_token.parse::()?]) + ) } } else if current_token.starts_with("par=") { let braced_value_token = ¤t_token[4..]; - if !braced_value_token.starts_with("[") || !braced_value_token.ends_with("]") { + if !braced_value_token.starts_with("[") { return Err(SdpParserInternalError::Generic( - "imageattr's par value is missing braces".to_string() + "imageattr's par value must start with '['".to_string() )) } - let range = parse_ps_range(&braced_value_token)?; + let par_values = parse_imagettr_braced_token(braced_value_token).ok_or( + SdpParserInternalError::Generic( + "imageattr's par value must be enclosed with ']'".to_string() + ) + )?; + let range = parse_ps_range(par_values)?; par = Some(SdpAttributeImageAttrPRange { min: range.0, max: range.1, }) } else if current_token.starts_with("q=") { q = Some(current_token[2..].parse::()?); - } else { - return Err(SdpParserInternalError::Generic( - format!("imageattr set contains unknown value token '{:?}'", current_token) - .to_string() - )) } } @@ -1425,70 +1430,62 @@ fn parse_image_attr_set(to_parse: &str) -> Result Result { - let result_from_option = |opt, error_msg: &str| { - match opt { - Some(x) => Ok(x), - None => Err(SdpParserInternalError::Generic(error_msg.to_string())) - } - }; - let mut tokens = to_parse.split(' ').peekable(); - - let pt = parse_payload_type(result_from_option(tokens.next(), - "imageattr's requires a payload token")?)?; - let first_direction = parse_single_direction(result_from_option(tokens.next(), "")?)?; - +fn parse_image_attr_set_list(tokens: &mut iter::Peekable) + -> Result + where I: Iterator + Clone { let parse_set = |set_token:&str| -> Result { - Ok(parse_image_attr_set(&set_token[1..set_token.len()-1])?) + Ok(parse_image_attr_set(parse_imagettr_braced_token(set_token).ok_or( + SdpParserInternalError::Generic( + "imageattr sets must be enclosed by ']'".to_string() + ))?)?) }; - let first_set_list = match result_from_option(tokens.next(), - "imageattr must have at least one parameter set")? { - "*" => SdpAttributeImageAttrSetList::Wildcard, - x @ _ => { + match tokens.next().ok_or(SdpParserInternalError::Generic( + "imageattr must have a parameter set after a direction token".to_string() + ))?.as_str() { + "*" => Ok(SdpAttributeImageAttrSetList::Wildcard), + x => { let mut sets = vec![parse_set(x)?]; while let Some(set_str) = tokens.clone().peek() { - if set_str.starts_with("[") && set_str.ends_with("]") { - sets.push(parse_set(tokens.next().unwrap())?); + if set_str.starts_with("[") { + sets.push(parse_set(&tokens.next().unwrap())?); } else { break; } } - SdpAttributeImageAttrSetList::Sets(sets) + Ok(SdpAttributeImageAttrSetList::Sets(sets)) } - }; + } +} + +fn parse_image_attr(to_parse: &str) -> Result { + let mut tokens = parse_imageattr_tokens(to_parse, ' ').into_iter().peekable(); + + let pt = parse_payload_type(tokens.next().ok_or(SdpParserInternalError::Generic( + "imageattr requires a payload token".to_string() + ))?.as_str())?; + let first_direction = parse_single_direction(tokens.next().ok_or( + SdpParserInternalError::Generic( + "imageattr's second token must be a direction token".to_string() + ))?.as_str())?; + + let first_set_list = parse_image_attr_set_list(&mut tokens)?; let mut second_set_list = SdpAttributeImageAttrSetList::Sets(Vec::new()); // Check if there is a second direction defined - if let Some(x) = tokens.next() { - if parse_single_direction(x)? == first_direction { + if let Some(direction_token) = tokens.next() { + if parse_single_direction(direction_token.as_str())? == first_direction { return Err(SdpParserInternalError::Generic( - "image-attr's second direction token must be different from the first one" + "imageattr's second direction token must be different from the first one" .to_string() )) } - second_set_list = match result_from_option(tokens.next(), - "imageattr must have a parameter set after a direction token")? { - "*" => SdpAttributeImageAttrSetList::Wildcard, - x @ _ => { - let mut sets = vec![parse_set(x)?]; - while let Some(set_str) = tokens.clone().peek() { - if set_str.starts_with("[") && set_str.ends_with("]") { - sets.push(parse_set(tokens.next().unwrap())?); - } else { - break; - } - } - - SdpAttributeImageAttrSetList::Sets(sets) - } - }; + second_set_list = parse_image_attr_set_list(&mut tokens)?; } - if let Some(_) = tokens.next() { return Err(SdpParserInternalError::Generic( "imageattr must not contain any token after the second set list".to_string() @@ -2242,10 +2239,10 @@ fn test_parse_attribute_imageattr() { assert_eq!(sets.len(), 1); let set = &sets[0]; - assert_eq!(set.x, SdpAttributeImageAttrXYRange::Value(800)); - assert_eq!(set.y, SdpAttributeImageAttrXYRange::DiscrateValues(vec![50,80,30])); + assert_eq!(set.x, SdpAttributeImageAttrXYRange::DiscreteValues(vec![800])); + assert_eq!(set.y, SdpAttributeImageAttrXYRange::DiscreteValues(vec![50,80,30])); assert_eq!(set.par, None); - assert_eq!(set.sar, Some(SdpAttributeImageAttrSRange::Value(1.1))); + assert_eq!(set.sar, Some(SdpAttributeImageAttrSRange::DiscreteValues(vec![1.1]))); assert_eq!(set.q, None); }, @@ -2256,10 +2253,10 @@ fn test_parse_attribute_imageattr() { assert_eq!(sets.len(), 1); let set = &sets[0]; - assert_eq!(set.x, SdpAttributeImageAttrXYRange::Value(330)); - assert_eq!(set.y, SdpAttributeImageAttrXYRange::Value(250)); + assert_eq!(set.x, SdpAttributeImageAttrXYRange::DiscreteValues(vec![330])); + assert_eq!(set.y, SdpAttributeImageAttrXYRange::DiscreteValues(vec![250])); assert_eq!(set.par, None); - assert_eq!(set.sar, Some(SdpAttributeImageAttrSRange::DiscrateValues(vec![1.1,1.3,1.9]))); + assert_eq!(set.sar, Some(SdpAttributeImageAttrSRange::DiscreteValues(vec![1.1,1.3,1.9]))); assert_eq!(set.q, Some(0.1)); }, _ => { unreachable!(); } @@ -2273,7 +2270,7 @@ fn test_parse_attribute_imageattr() { let first_set = &sets[0]; assert_eq!(first_set.x, SdpAttributeImageAttrXYRange::Range(480, 800, Some(16))); - assert_eq!(first_set.y, SdpAttributeImageAttrXYRange::DiscrateValues(vec![100, 200, 300])); + assert_eq!(first_set.y, SdpAttributeImageAttrXYRange::DiscreteValues(vec![100, 200, 300])); assert_eq!(first_set.par, Some(SdpAttributeImageAttrPRange { min: 1.2, max: 1.3 @@ -2282,10 +2279,10 @@ fn test_parse_attribute_imageattr() { assert_eq!(first_set.q, Some(0.6)); let second_set = &sets[1]; - assert_eq!(second_set.x, SdpAttributeImageAttrXYRange::Value(1080)); + assert_eq!(second_set.x, SdpAttributeImageAttrXYRange::DiscreteValues(vec![1080])); assert_eq!(second_set.y, SdpAttributeImageAttrXYRange::Range(144, 176, None)); assert_eq!(second_set.par, None); - assert_eq!(second_set.sar, Some(SdpAttributeImageAttrSRange::Range(0.5, 0.7))); + assert_eq!(second_set.sar, Some(SdpAttributeImageAttrSRange::Range(0.5, 0.7))); assert_eq!(second_set.q, None); }, _ => { unreachable!(); } @@ -2294,6 +2291,8 @@ fn test_parse_attribute_imageattr() { assert!(parse_attribute("imageattr:99 send [x=320,y=240]").is_ok()); assert!(parse_attribute("imageattr:100 recv [x=320,y=240]").is_ok()); + assert!(parse_attribute("imageattr:97 recv [x=800,y=640,sar=1.1,foo=[123,456],q=0.5] send [x=330,y=250,bar=foo,sar=[20-40]]").is_ok()); + assert!(parse_attribute("imageattr:97 recv [x=800,y=640,sar=1.1,foo=abc xyz,q=0.5] send [x=330,y=250,bar=foo,sar=[20-40]]").is_ok()); assert!(parse_attribute("imageattr:").is_err()); assert!(parse_attribute("imageattr:100").is_err()); diff --git a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs index 53aa6c4d2fbf..6eeba01f4f6d 100644 --- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs +++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs @@ -1,5 +1,6 @@ use std::slice; -use libc::{size_t, uint8_t, uint16_t, uint32_t, int64_t, uint64_t}; +use libc::{size_t, uint8_t, uint16_t, uint32_t, int64_t, uint64_t, c_float}; +use std::ptr; use rsdparsa::SdpSession; use rsdparsa::attribute_type::*; @@ -743,12 +744,178 @@ pub unsafe extern "C" fn sdp_get_rtcpfbs(attributes: *const Vec, r rtcpfbs.clone_from_slice(attrs.as_slice()); } +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RustSdpAttributeImageAttrXYRange { + // range + pub min: uint32_t, + pub max: uint32_t, + pub step: uint32_t, + + // discrete values + pub discrete_values: *const Vec, +} + +impl<'a> From<&'a SdpAttributeImageAttrXYRange > for RustSdpAttributeImageAttrXYRange { + fn from(other: &SdpAttributeImageAttrXYRange) -> Self { + match other { + &SdpAttributeImageAttrXYRange::Range(min, max, step) => { + RustSdpAttributeImageAttrXYRange { + min, + max, + step: step.unwrap_or(1), + discrete_values: ptr::null(), + } + }, + &SdpAttributeImageAttrXYRange::DiscreteValues(ref discrete_values) => { + RustSdpAttributeImageAttrXYRange { + min: 0, + max: 1, + step: 1, + discrete_values, + } + } + } + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RustSdpAttributeImageAttrSRange { + // range + pub min: c_float, + pub max: c_float, + + // discrete values + pub discrete_values: *const Vec, +} + +impl<'a> From<&'a SdpAttributeImageAttrSRange> for RustSdpAttributeImageAttrSRange { + fn from(other: &SdpAttributeImageAttrSRange) -> Self { + match other { + &SdpAttributeImageAttrSRange::Range(min, max) => { + RustSdpAttributeImageAttrSRange { + min, + max, + discrete_values: ptr::null(), + } + }, + &SdpAttributeImageAttrSRange::DiscreteValues(ref discrete_values) => { + RustSdpAttributeImageAttrSRange { + min: 0.0, + max: 1.0, + discrete_values, + } + }, + } + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RustSdpAttributeImageAttrPRange { + pub min: c_float, + pub max: c_float, +} + +impl<'a> From<&'a SdpAttributeImageAttrPRange > for RustSdpAttributeImageAttrPRange { + fn from(other: &SdpAttributeImageAttrPRange) -> Self { + RustSdpAttributeImageAttrPRange { + min: other.min, + max: other.max + } + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RustSdpAttributeImageAttrSet { + pub x: RustSdpAttributeImageAttrXYRange, + pub y: RustSdpAttributeImageAttrXYRange, + + pub has_sar: bool, + pub sar: RustSdpAttributeImageAttrSRange, + + pub has_par: bool, + pub par: RustSdpAttributeImageAttrPRange, + + pub q: c_float, +} + +impl<'a> From<&'a SdpAttributeImageAttrSet > for RustSdpAttributeImageAttrSet { + fn from(other: &SdpAttributeImageAttrSet) -> Self { + RustSdpAttributeImageAttrSet { + x: RustSdpAttributeImageAttrXYRange::from(&other.x), + y: RustSdpAttributeImageAttrXYRange::from(&other.y), + + has_sar: other.sar.is_some(), + sar: match other.sar { + Some(ref x) => RustSdpAttributeImageAttrSRange::from(x), + // This is just any valid value accepted by rust, + // it might as well by uninitilized + None => RustSdpAttributeImageAttrSRange::from( + &SdpAttributeImageAttrSRange::DiscreteValues(vec![])) + }, + + has_par: other.par.is_some(), + par: match other.par { + Some(ref x) => RustSdpAttributeImageAttrPRange::from(x), + // This is just any valid value accepted by rust, + // it might as well by uninitilized + None => RustSdpAttributeImageAttrPRange { + min: 0.0, + max: 1.0, + } + }, + + q: other.q.unwrap_or(0.5), + } + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RustSdpAttributeImageAttrSetList { + pub sets: *const Vec +} + +impl<'a> From<&'a SdpAttributeImageAttrSetList > for RustSdpAttributeImageAttrSetList { + fn from(other: &SdpAttributeImageAttrSetList) -> Self { + match other { + &SdpAttributeImageAttrSetList::Wildcard => + RustSdpAttributeImageAttrSetList{ + sets: ptr::null(), + }, + &SdpAttributeImageAttrSetList::Sets(ref sets) => + RustSdpAttributeImageAttrSetList { + sets: sets, + } + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn sdp_imageattr_get_set_count(sets: *const Vec) + -> size_t { + (*sets).len() +} + +#[no_mangle] +pub unsafe extern "C" fn sdp_imageattr_get_sets(sets: *const Vec, + ret_size: size_t, + ret: *mut RustSdpAttributeImageAttrSet) { + let rust_sets: Vec<_> = (*sets).iter().map(RustSdpAttributeImageAttrSet::from).collect(); + let sets = slice::from_raw_parts_mut(ret, ret_size); + sets.clone_from_slice(rust_sets.as_slice()); +} #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttr { pub pt: u32, + pub send: RustSdpAttributeImageAttrSetList, + pub recv: RustSdpAttributeImageAttrSetList, } impl<'a> From<&'a SdpAttributeImageAttr> for RustSdpAttributeImageAttr { @@ -758,6 +925,8 @@ impl<'a> From<&'a SdpAttributeImageAttr> for RustSdpAttributeImageAttr { SdpAttributePayloadType::Wildcard => u32::max_value(), SdpAttributePayloadType::PayloadType(x) => x as u32, }, + send: RustSdpAttributeImageAttrSetList::from(&other.send), + recv: RustSdpAttributeImageAttrSetList::from(&other.recv), } } } diff --git a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs index d7578333b47b..56c455ffc231 100644 --- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs +++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs @@ -76,6 +76,24 @@ pub unsafe extern "C" fn string_vec_get_view(vec: *const Vec, } } +#[no_mangle] +pub unsafe extern "C" fn f32_vec_len(vec: *const Vec) -> size_t { + (*vec).len() +} + +#[no_mangle] +pub unsafe extern "C" fn f32_vec_get(vec: *const Vec, + index: size_t, + ret: *mut f32) -> nsresult { + match (*vec).get(index) { + Some(val) => { + *ret = *val; + NS_OK + }, + None => NS_ERROR_INVALID_ARG + } +} + #[no_mangle] pub unsafe extern "C" fn u32_vec_len(vec: *const Vec) -> size_t { (*vec).len()