mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2024-12-25 22:55:55 -05:00
more anamorphic streams
* my dad's GW4089IP cameras use 720x480 * some Reolink cameras use 640x352 * I'm playing with rotated cameras (16x9 -> 9x16) I'd prefer to calculate pasp from a configured camera aspect ratio than to hardcode the assumption these are 16x9, but that requires a schema change. This is an improvement for now.
This commit is contained in:
parent
54bd068706
commit
0068a9ae70
1
server/Cargo.lock
generated
1
server/Cargo.lock
generated
@ -1265,6 +1265,7 @@ dependencies = [
|
|||||||
"mylog",
|
"mylog",
|
||||||
"nix",
|
"nix",
|
||||||
"nom",
|
"nom",
|
||||||
|
"num-rational",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"protobuf",
|
"protobuf",
|
||||||
"reffers",
|
"reffers",
|
||||||
|
@ -64,6 +64,7 @@ url = "2.1.1"
|
|||||||
uuid = { version = "0.8", features = ["serde", "std", "v4"] }
|
uuid = { version = "0.8", features = ["serde", "std", "v4"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
num-rational = { version = "0.3.2", default-features = false, features = ["std"] }
|
||||||
reqwest = { version = "0.11.0", default-features = false, features = ["json"] }
|
reqwest = { version = "0.11.0", default-features = false, features = ["json"] }
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
|
|
||||||
|
@ -30,11 +30,15 @@ const NAL_UNIT_PIC_PARAMETER_SET: u8 = 8;
|
|||||||
const NAL_UNIT_TYPE_MASK: u8 = 0x1F; // bottom 5 bits of first byte of unit.
|
const NAL_UNIT_TYPE_MASK: u8 = 0x1F; // bottom 5 bits of first byte of unit.
|
||||||
|
|
||||||
// For certain common sub stream anamorphic resolutions, add a pixel aspect ratio box.
|
// For certain common sub stream anamorphic resolutions, add a pixel aspect ratio box.
|
||||||
const PIXEL_ASPECT_RATIOS: [((u16, u16), (u16, u16)); 4] = [
|
// Assume the camera is 16x9. These are just the standard wide mode; default_pixel_aspect_ratio
|
||||||
|
// tries the transpose also.
|
||||||
|
const PIXEL_ASPECT_RATIOS: [((u16, u16), (u16, u16)); 6] = [
|
||||||
((320, 240), (4, 3)),
|
((320, 240), (4, 3)),
|
||||||
((352, 240), (40, 33)),
|
((352, 240), (40, 33)),
|
||||||
|
((640, 352), (44, 45)),
|
||||||
((640, 480), (4, 3)),
|
((640, 480), (4, 3)),
|
||||||
((704, 480), (40, 33)),
|
((704, 480), (40, 33)),
|
||||||
|
((720, 480), (32, 27)),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Get the pixel aspect ratio to use if none is specified.
|
/// Get the pixel aspect ratio to use if none is specified.
|
||||||
@ -47,13 +51,19 @@ const PIXEL_ASPECT_RATIOS: [((u16, u16), (u16, u16)); 4] = [
|
|||||||
/// Note that at least in the case of .mp4 muxing, we don't need to fix up the underlying SPS.
|
/// Note that at least in the case of .mp4 muxing, we don't need to fix up the underlying SPS.
|
||||||
/// SPS; PixelAspectRatioBox's definition says that it overrides the H.264-level declaration.
|
/// SPS; PixelAspectRatioBox's definition says that it overrides the H.264-level declaration.
|
||||||
fn default_pixel_aspect_ratio(width: u16, height: u16) -> (u16, u16) {
|
fn default_pixel_aspect_ratio(width: u16, height: u16) -> (u16, u16) {
|
||||||
let dims = (width, height);
|
if width >= height {
|
||||||
for r in &PIXEL_ASPECT_RATIOS {
|
PIXEL_ASPECT_RATIOS
|
||||||
if r.0 == dims {
|
.iter()
|
||||||
return r.1;
|
.find(|r| r.0 == (width, height))
|
||||||
}
|
.map(|r| r.1)
|
||||||
|
.unwrap_or((1, 1))
|
||||||
|
} else {
|
||||||
|
PIXEL_ASPECT_RATIOS
|
||||||
|
.iter()
|
||||||
|
.find(|r| r.0 == (height, width))
|
||||||
|
.map(|r| (r.1 .1, r.1 .0))
|
||||||
|
.unwrap_or((1, 1))
|
||||||
}
|
}
|
||||||
(1, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a H.264 Annex B byte stream into NAL units. Calls `f` for each NAL unit in the byte
|
/// Decodes a H.264 Annex B byte stream into NAL units. Calls `f` for each NAL unit in the byte
|
||||||
@ -435,4 +445,18 @@ mod tests {
|
|||||||
super::transform_sample_data(&INPUT, &mut out).unwrap();
|
super::transform_sample_data(&INPUT, &mut out).unwrap();
|
||||||
assert_eq!(&out[..], &EXPECTED_OUTPUT[..]);
|
assert_eq!(&out[..], &EXPECTED_OUTPUT[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pixel_aspect_ratios() {
|
||||||
|
use super::default_pixel_aspect_ratio;
|
||||||
|
use num_rational::Ratio;
|
||||||
|
for &((w, h), _) in &super::PIXEL_ASPECT_RATIOS {
|
||||||
|
let (h_spacing, v_spacing) = default_pixel_aspect_ratio(w, h);
|
||||||
|
assert_eq!(Ratio::new(w * h_spacing, h * v_spacing), Ratio::new(16, 9));
|
||||||
|
|
||||||
|
// 90 or 270 degree rotation.
|
||||||
|
let (h_spacing, v_spacing) = default_pixel_aspect_ratio(h, w);
|
||||||
|
assert_eq!(Ratio::new(h * h_spacing, w * v_spacing), Ratio::new(9, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user