blob: 4c0b9e210d8d62a0d550a326d2b07204a268cac6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This test is run with --test-threasds=1 to prevent any tests from running in parallel.
//
// Running in parallel is something we want to control for specific tests cases especially
// when testing hardware stream processors.
#![cfg(test)]
use h264_stream::*;
use std::fs::File;
use std::io::Read;
use std::rc::Rc;
use std::result::Result;
use std::sync::LazyLock;
use stream_processor_decoder_factory::*;
use stream_processor_test::*;
use video_frame_hasher::*;
pub const BEAR_TEST_FILE: &str = "/pkg/data/bear.h264";
static BEAR_DIGEST: LazyLock<ExpectedDigest> = LazyLock::new(|| {
ExpectedDigest::new_with_per_frame_digest(
"bear.h264 decoded digest",
"1dc4d1510fc4d26173480f5e689e38dca7c1fa2df1894085f1bcee9c0d19acf7",
vec![
"0f1d46e5b13b0bb96b42d0c3ead24f656e3e000b3f287714be85572b11fa747f",
"a1c64f7db1ffcc90f493494fd66a49fd90581e7b4b9cf01e44cc3d1b48f1b2ba",
"0bce4a93ed09cda3967d193a46d3dac770852849059b63e58c59ca37ec02dae0",
"a3dd10db3320fc8679c522e4638c56623cb4cc04763147ab263a014158a4de83",
"32ee2c4e9d7efe149871a5bad5fc3a965353976b7b09f6ca402cd20b768cf512",
"f65970e9ac1fe36cc8d4652ca49be6bc936a39f44102b24353280f3de1567937",
"4f2921b3304608f4fdbbddbb20f1415321deb1a5ba06df25e0860025340bcb52",
"9e8becc472fbec2ac3c1f7beb17737bdd46b824f0198fe14f5bfc15cc55f86a1",
"97d49f5ca990970317890c15106deb55fc8fbe98602621953293a8384983ff73",
"4bc568295e668a245242961c98c78ac4a2068973c941b99fc9ba8e24f05badcf",
"52dc2c4a765617b2d2e8675bf1da3cb7275a44a1efa792833e049aedd330ebdf",
"6b4136c0f952aceec0ccfd27ac3e7ae8f2de7164145520593ae634c40bce2874",
"2894c4c09598098cba30be9721063e7d5354fccf41a301788d0dda25e1e9df3a",
"e2ba87ad32ea7429093c594e74465bc3b33f5a22c1d08f9c6534ff027e7d7124",
"b3ea3627c5f7a61ca327bf79377d296273fddb98d0cd18a64cef699640a1b28a",
"c60813c1be8abe568a20e802ddf6997dd77f673ddc9847d5655ee107f8b16934",
"b5d01e7f4012ff375231a2dc66c35109f852adbd90e63704653a6c9bd4f012a7",
"aed3b808d3cbe0b37209ebe8c84c6e7c95b7b690b5bf4ce5484b182c9e56d4e0",
"de7483a21de0d78b6c9cf4ae31f487dd7da22296eb1dbecd201fe07b5d5ed0e6",
"219a6d4029d0f75501dd8b4f8a16c31240d1491d623d2c26bca096615820de48",
"8efa6fbe7b3479e43537e7226b3e079e778bb1442de52c69122b55df6e4c5e8c",
"2930e0b080180312a6add0478161f93009b683bdafcfafc20e6205ebc8b9d4b5",
"52193a2d808e2b7c7b82bf2833d5a6c1da8e6344ec1c7759f59db1cad8d02dd0",
"2edf5bcb1825e50d8e5871c68b322e47196b5087b165b3d11af502084bd3363a",
"542e0d748ee037034ab360822f65df2edc5ef1d10a37a3f6ac9f35b09eb49593",
"6ffacaad59095ba5c2e8e9d727386fdb55d618ffc2a3fbe039d8dd9189cd9d2c",
"8c537610171663df07ab7a87de3598cd63cb18eb2852f1184088aeb9ef0a70d6",
"00ddc6d257a5223a30c0d652d37cc7a37c3e65de922f10a6e8a8a5cda61c2365",
"8c25f9fbe01f491c343d9ab7c0bd3ffb6fc7f0fed546fbf7f49ad1f661f53d50",
"1dc4d1510fc4d26173480f5e689e38dca7c1fa2df1894085f1bcee9c0d19acf7",
],
)
});
// TODO(turnage): Add test spec for buffers released between streams.
// TODO(turnage): Add hash validator for NV12 and YV12.
#[fuchsia::test]
fn test_bear() -> std::result::Result<(), ::anyhow::Error> {
with_large_stack(|| {
let stream = Rc::new(TimestampedStream {
source: H264Stream::from_file(BEAR_TEST_FILE)?,
timestamps: 0..,
});
let frame_count_validator = Rc::new(OutputPacketCountValidator {
expected_output_packet_count: stream.video_frame_count(),
});
let hash_validator = Rc::new(VideoFrameHasher { expected_digest: BEAR_DIGEST.clone() });
let spec = TestSpec {
cases: vec![TestCase {
name: "Simple bear test run 1",
stream: stream.clone(),
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator.clone(),
hash_validator.clone(),
],
stream_options: None,
}],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}
#[fuchsia::test]
fn test_serial_bear_on_same_codec() -> std::result::Result<(), ::anyhow::Error> {
with_large_stack(|| {
let stream = Rc::new(TimestampedStream {
source: H264Stream::from_file(BEAR_TEST_FILE)?,
timestamps: 0..,
});
let frame_count_validator = Rc::new(OutputPacketCountValidator {
expected_output_packet_count: stream.video_frame_count(),
});
let hash_validator = Rc::new(VideoFrameHasher { expected_digest: BEAR_DIGEST.clone() });
let spec = TestSpec {
cases: vec![
TestCase {
name: "Simple bear test run 1 on same channel",
stream: stream.clone(),
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator.clone(),
hash_validator.clone(),
],
stream_options: None,
},
TestCase {
name: "Simple bear test run 2 on same channel",
stream: stream.clone(),
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 3 },
}),
frame_count_validator.clone(),
hash_validator.clone(),
],
stream_options: Some(StreamOptions {
queue_format_details: false,
..StreamOptions::default()
}),
},
],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}
#[fuchsia::test]
fn bear_with_sei_itu_t35() -> Result<(), anyhow::Error> {
with_large_stack(|| {
let mut nal_stream = H264SeiItuT35 {
country_code: H264SeiItuT35::COUNTRY_CODE_UNITED_STATES,
country_code_extension: 0,
payload: vec![0xde, 0xad, 0xbe, 0xef],
}
.as_bytes()?;
File::open(BEAR_TEST_FILE)?.read_to_end(&mut nal_stream)?;
let stream =
Rc::new(TimestampedStream { source: H264Stream::from(nal_stream), timestamps: 0.. });
let frame_count_validator = Rc::new(OutputPacketCountValidator {
expected_output_packet_count: stream.video_frame_count(),
});
let hash_validator = Rc::new(VideoFrameHasher { expected_digest: BEAR_DIGEST.clone() });
let spec = TestSpec {
cases: vec![TestCase {
name: "Modified Bear with SEI ITU-T T.35 data test run",
stream: stream,
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator,
hash_validator,
],
stream_options: None,
}],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}
#[fuchsia::test]
fn bear_with_large_sei_itu_t35() -> Result<(), anyhow::Error> {
with_large_stack(|| {
let mut nal_stream = H264SeiItuT35 {
country_code: H264SeiItuT35::COUNTRY_CODE_UNITED_STATES,
country_code_extension: 0,
payload: vec![0xde, 0xad, 0xbe, 0xef],
}
.as_bytes()?;
// Appending 0s to an annex-B NAL shouldn't change the behavior.
nal_stream.resize(428, 0);
File::open(BEAR_TEST_FILE)?.read_to_end(&mut nal_stream)?;
let stream =
Rc::new(TimestampedStream { source: H264Stream::from(nal_stream), timestamps: 0.. });
let frame_count_validator = Rc::new(OutputPacketCountValidator {
expected_output_packet_count: stream.video_frame_count(),
});
let hash_validator = Rc::new(VideoFrameHasher { expected_digest: BEAR_DIGEST.clone() });
let spec = TestSpec {
cases: vec![TestCase {
name: "Modified Bear with Large SEI ITU-T T.35 data test run",
stream: stream,
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator,
hash_validator,
],
stream_options: None,
}],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}
#[fuchsia::test]
fn bear_with_gaps() -> Result<(), anyhow::Error> {
with_large_stack(|| {
let mut nal_stream = Vec::new();
let mut bear = Vec::new();
File::open(BEAR_TEST_FILE)?.read_to_end(&mut bear)?;
// Append bear up till somewhere in middle, but then drop a NonIDR frame. Index of NonIDR in bear found by adding logging to H264NalIter.
nal_stream.extend_from_slice(&bear[0..7635]);
nal_stream.extend(&bear[8858..]);
let stream =
Rc::new(TimestampedStream { source: H264Stream::from(nal_stream), timestamps: 0.. });
let frame_count_validator =
Rc::new(OutputPacketCountValidator { expected_output_packet_count: 29 });
let spec = TestSpec {
cases: vec![TestCase {
name: "Bear with gaps",
stream: stream,
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator,
],
stream_options: None,
}],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}
#[fuchsia::test]
fn test_bear_avcc() -> std::result::Result<(), ::anyhow::Error> {
with_large_stack(|| {
let stream = Rc::new(TimestampedStream {
source: H264AVCCStream::from_annexb_stream(H264Stream::from_file(BEAR_TEST_FILE)?)?,
timestamps: 0..,
});
let frame_count_validator = Rc::new(OutputPacketCountValidator {
expected_output_packet_count: stream.video_frame_count(),
});
let hash_validator = Rc::new(VideoFrameHasher { expected_digest: BEAR_DIGEST.clone() });
let spec = TestSpec {
cases: vec![TestCase {
name: "Simple bear test run with AVCC",
stream: stream.clone(),
validators: vec![
Rc::new(TerminatesWithValidator {
expected_terminal_output: Output::Eos { stream_lifetime_ordinal: 1 },
}),
frame_count_validator.clone(),
hash_validator.clone(),
],
stream_options: None,
}],
relation: CaseRelation::Serial,
stream_processor_factory: Rc::new(DecoderFactory),
};
fuchsia_async::TestExecutor::new().run_singlethreaded(spec.run()).map(|_| ())
})
}