mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-02 06:02:20 +00:00
reqwesthttpsrc: Add support for parsing the Content-Type header
In iradio-mode we would put it as an additional field to the caps, otherwise if it's audio/L16 we would create audio/x-unaligned-raw caps accordingly.
This commit is contained in:
parent
12058a4c9a
commit
bc34fbd2eb
2 changed files with 96 additions and 3 deletions
|
@ -347,8 +347,8 @@ impl ReqwestHttpSrc {
|
||||||
) -> Result<State, Option<gst::ErrorMessage>> {
|
) -> Result<State, Option<gst::ErrorMessage>> {
|
||||||
use hyperx::header::{
|
use hyperx::header::{
|
||||||
qitem, AcceptEncoding, AcceptRanges, ByteRangeSpec, Connection, ContentLength,
|
qitem, AcceptEncoding, AcceptRanges, ByteRangeSpec, Connection, ContentLength,
|
||||||
ContentRange, ContentRangeSpec, Cookie, Encoding, Headers, Range, RangeUnit, RawLike,
|
ContentRange, ContentRangeSpec, ContentType, Cookie, Encoding, Headers, Range,
|
||||||
UserAgent,
|
RangeUnit, RawLike, UserAgent,
|
||||||
};
|
};
|
||||||
|
|
||||||
gst_debug!(self.cat, obj: src, "Creating new request for {}", uri);
|
gst_debug!(self.cat, obj: src, "Creating new request for {}", uri);
|
||||||
|
@ -557,7 +557,7 @@ impl ReqwestHttpSrc {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let caps = headers
|
let mut caps = headers
|
||||||
.get_raw("icy-metaint")
|
.get_raw("icy-metaint")
|
||||||
.and_then(|h| h.one())
|
.and_then(|h| h.one())
|
||||||
.and_then(|s| std::str::from_utf8(s).ok())
|
.and_then(|s| std::str::from_utf8(s).ok())
|
||||||
|
@ -568,6 +568,33 @@ impl ReqwestHttpSrc {
|
||||||
.build()
|
.build()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let Some(ContentType(ref content_type)) = headers.get() {
|
||||||
|
gst_debug!(self.cat, obj: src, "Got content type {}", content_type);
|
||||||
|
if let Some(ref mut caps) = caps {
|
||||||
|
let caps = caps.get_mut().unwrap();
|
||||||
|
let s = caps.get_mut_structure(0).unwrap();
|
||||||
|
s.set("content-type", &content_type.as_ref());
|
||||||
|
} else if content_type.type_() == "audio" && content_type.subtype() == "L16" {
|
||||||
|
let channels = content_type
|
||||||
|
.get_param("channels")
|
||||||
|
.and_then(|s| s.as_ref().parse::<i32>().ok())
|
||||||
|
.unwrap_or(2);
|
||||||
|
let rate = content_type
|
||||||
|
.get_param("rate")
|
||||||
|
.and_then(|s| s.as_ref().parse::<i32>().ok())
|
||||||
|
.unwrap_or(44_100);
|
||||||
|
|
||||||
|
caps = Some(
|
||||||
|
gst::Caps::builder("audio/x-unaligned-raw")
|
||||||
|
.field("format", &"S16BE")
|
||||||
|
.field("layout", &"interleaved")
|
||||||
|
.field("channels", &channels)
|
||||||
|
.field("rate", &rate)
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut tags = gst::TagList::new();
|
let mut tags = gst::TagList::new();
|
||||||
{
|
{
|
||||||
let tags = tags.get_mut().unwrap();
|
let tags = tags.get_mut().unwrap();
|
||||||
|
|
|
@ -590,6 +590,7 @@ fn test_iradio_mode() {
|
||||||
.header("icy-name", "Name")
|
.header("icy-name", "Name")
|
||||||
.header("icy-genre", "Genre")
|
.header("icy-genre", "Genre")
|
||||||
.header("icy-url", "http://www.example.com")
|
.header("icy-url", "http://www.example.com")
|
||||||
|
.header("Content-Type", "audio/mpeg; rate=44100")
|
||||||
.body(Body::from("Hello World"))
|
.body(Body::from("Hello World"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
},
|
},
|
||||||
|
@ -634,6 +635,7 @@ fn test_iradio_mode() {
|
||||||
caps,
|
caps,
|
||||||
gst::Caps::builder("application/x-icy")
|
gst::Caps::builder("application/x-icy")
|
||||||
.field("metadata-interval", &8192i32)
|
.field("metadata-interval", &8192i32)
|
||||||
|
.field("content-type", &"audio/mpeg; rate=44100")
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -657,6 +659,70 @@ fn test_iradio_mode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_audio_l16() {
|
||||||
|
use std::io::{Cursor, Read};
|
||||||
|
init();
|
||||||
|
|
||||||
|
// Set up a harness that returns "Hello World" for any HTTP request and check if the
|
||||||
|
// audio/L16 content type is parsed correctly and put into the caps
|
||||||
|
let mut h = Harness::new(
|
||||||
|
|_req| {
|
||||||
|
use hyper::{Body, Response};
|
||||||
|
|
||||||
|
Response::builder()
|
||||||
|
.header("Content-Type", "audio/L16; rate=48000; channels=2")
|
||||||
|
.body(Body::from("Hello World"))
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
|_src| {
|
||||||
|
// No additional setup needed here
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the HTTP source to Playing so that everything can start
|
||||||
|
h.run(|src| {
|
||||||
|
src.set_state(gst::State::Playing).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// And now check if the data we receive is exactly what we expect it to be
|
||||||
|
let expected_output = "Hello World";
|
||||||
|
let mut cursor = Cursor::new(expected_output);
|
||||||
|
|
||||||
|
while let Some(buffer) = h.wait_buffer_or_eos() {
|
||||||
|
// On the first buffer also check if the duration reported by the HTTP source is what we
|
||||||
|
// would expect it to be
|
||||||
|
if cursor.position() == 0 {
|
||||||
|
assert_eq!(
|
||||||
|
h.src.query_duration::<gst::format::Bytes>(),
|
||||||
|
Some(gst::format::Bytes::from(expected_output.len() as u64))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the buffer readable and check if it contains exactly the data we would expect at
|
||||||
|
// this point after reading everything else we read in previous runs
|
||||||
|
let map = buffer.map_readable().unwrap();
|
||||||
|
let mut read_buf = vec![0; map.get_size()];
|
||||||
|
assert_eq!(cursor.read(&mut read_buf).unwrap(), map.get_size());
|
||||||
|
assert_eq!(&*map, &*read_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if everything was read
|
||||||
|
assert_eq!(cursor.position(), 11);
|
||||||
|
|
||||||
|
let srcpad = h.src.get_static_pad("src").unwrap();
|
||||||
|
let caps = srcpad.get_current_caps().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
caps,
|
||||||
|
gst::Caps::builder("audio/x-unaligned-raw")
|
||||||
|
.field("format", &"S16BE")
|
||||||
|
.field("layout", &"interleaved")
|
||||||
|
.field("channels", &2i32)
|
||||||
|
.field("rate", &48_000i32)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_authorization() {
|
fn test_authorization() {
|
||||||
use std::io::{Cursor, Read};
|
use std::io::{Cursor, Read};
|
||||||
|
|
Loading…
Reference in a new issue