blob: 7508e716e8b499dc380ba6e77dd0617dc4447160 [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.
#![cfg(test)]
mod pcm_audio;
mod test_suite;
mod timestamp_validator;
use crate::test_suite::*;
use fidl_fuchsia_media::*;
use fuchsia_async as fasync;
use std::rc::Rc;
use stream_processor_test::*;
// INSTRUCTIONS FOR ADDING HASH TESTS
//
// 1. If adding a new pcm input configuration, write the saw wave to file and check it in in the
// `test_data` directory. It should only be a few thousand PCM frames.
// 2. Set the `output_file` field to write the encoded output into
// `/tmp/r/sys/fuchsia.com:audio_encoder_test:0#meta:audio_encoder_test.cmx ` so you can copy
// it to host.
// 3. Create an encoded stream with the same settings using another encoder (for sbc, use sbcenc or
// ffmpeg; for aac use faac) on the reference saw wave.
// 4. Verify the output
// a. If the codec should produce the exact same bytes for the same settings, `diff` the two
// files.
// b. If the codec is permitted to produce different encoded bytes for the same settings, do a
// similarity check:
// b1. Decode both the reference and our encoded stream (sbcdec, faad, etc)
// b2. Import both tracks into Audacity
// b3. Apply Effect > Invert to one track
// b4. Select both tracks and Tracks > Mix > Mix and Render to New Track
// b5. On the resulting track use Effect > Amplify and observe the new peak amplitude
// 5. If all looks good, commit the hash.
#[test]
fn sbc_test_suite() -> Result<()> {
with_large_stack(|| {
let sub_bands = SbcSubBands::SubBands4;
let block_count = SbcBlockCount::BlockCount8;
let sbc_tests = AudioEncoderTestCase {
input_framelength: (sub_bands.into_primitive() * block_count.into_primitive()) as usize,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Sbc(SbcEncoderSettings {
allocation: SbcAllocation::AllocLoudness,
sub_bands,
block_count,
channel_mode: SbcChannelMode::Mono,
// Recommended bit pool value for these parameters, from SBC spec.
bit_pool: 59,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
output_file: None,
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 94,
expected_digests: vec![ExpectedDigest::new(
"Sbc: 44.1kHz/Loudness/Mono/bitpool 56/blocks 8/subbands 4",
"5c65a88bda3f132538966d87df34aa8675f85c9892b7f9f5571f76f3c7813562",
)],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(sbc_tests.run())
})
}
#[test]
fn aac_test_suite() -> Result<()> {
with_large_stack(|| {
let aac_raw_tests = AudioEncoderTestCase {
input_framelength: 1024,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Aac(AacEncoderSettings {
transport: AacTransport::Raw(AacTransportRaw {}),
channel_mode: AacChannelMode::Mono,
bit_rate: AacBitRate::Variable(AacVariableBitRate::V5),
aot: AacAudioObjectType::Mpeg2AacLc,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 5,
output_file: None,
expected_digests: vec![
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Raw Arm",
"11fe39d40b09c3158172adf86ecb715d98f5e0ca9d5b541629ac80922f79fc1c",
),
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Raw x64",
"5be551b15b856508a186daa008e06b5ea2d7c2b18ae7977c5037ddee92d4ef9b",
),
],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(aac_raw_tests.run())?;
// Test the MPEG4 AAC_LC variant. This affects encoder behavior but in this test case the
// resulting bit streams are identical.
let aac_raw_tests = AudioEncoderTestCase {
input_framelength: 1024,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Aac(AacEncoderSettings {
transport: AacTransport::Raw(AacTransportRaw {}),
channel_mode: AacChannelMode::Mono,
bit_rate: AacBitRate::Variable(AacVariableBitRate::V5),
aot: AacAudioObjectType::Mpeg4AacLc,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 5,
output_file: None,
expected_digests: vec![
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Raw Arm",
"11fe39d40b09c3158172adf86ecb715d98f5e0ca9d5b541629ac80922f79fc1c",
),
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Raw x64",
"5be551b15b856508a186daa008e06b5ea2d7c2b18ae7977c5037ddee92d4ef9b",
),
],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(aac_raw_tests.run())
})
}
#[test]
fn aac_adts_test_suite() -> Result<()> {
with_large_stack(|| {
let aac_adts_tests = AudioEncoderTestCase {
input_framelength: 1024,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Aac(AacEncoderSettings {
transport: AacTransport::Adts(AacTransportAdts {}),
channel_mode: AacChannelMode::Mono,
bit_rate: AacBitRate::Variable(AacVariableBitRate::V5),
aot: AacAudioObjectType::Mpeg2AacLc,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 5,
output_file: None,
expected_digests: vec![
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Adts Arm",
"c9d1ebb5844b9d90c09b0a26db14ddcf4189e77087efc064061f1c88df51e296",
),
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Adts x64",
"e88afc9130dc3cf429719f4e66fa7c60a17161c5ac30b37c527ab98e83f30750",
),
],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(aac_adts_tests.run())
})
}
#[test]
fn aac_latm_test_suite() -> Result<()> {
with_large_stack(|| {
let aac_latm_with_mux_config_test = AudioEncoderTestCase {
input_framelength: 1024,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Aac(AacEncoderSettings {
transport: AacTransport::Latm(AacTransportLatm { mux_config_present: true }),
channel_mode: AacChannelMode::Mono,
bit_rate: AacBitRate::Variable(AacVariableBitRate::V5),
aot: AacAudioObjectType::Mpeg2AacLc,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 5,
output_file: None,
expected_digests: vec![
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Latm/MuxConfig Arm",
"85ce565087981c36e47c873be7df2d57d3c0e8273e6641477e1b6d20c41c29b4",
),
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Latm/MuxConfig x64",
"6f2eadfe6dd88b189a38b00b9711160fea4b2d8a6acc24ea9008708d2a355735",
),
],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(aac_latm_with_mux_config_test.run())?;
let aac_latm_without_mux_config_test = AudioEncoderTestCase {
input_framelength: 1024,
settings: Rc::new(move || -> EncoderSettings {
EncoderSettings::Aac(AacEncoderSettings {
transport: AacTransport::Latm(AacTransportLatm { mux_config_present: false }),
channel_mode: AacChannelMode::Mono,
bit_rate: AacBitRate::Variable(AacVariableBitRate::V5),
aot: AacAudioObjectType::Mpeg2AacLc,
})
}),
channel_count: 1,
hash_tests: vec![AudioEncoderHashTest {
input_format: PcmFormat {
pcm_mode: AudioPcmMode::Linear,
bits_per_sample: 16,
frames_per_second: 44100,
channel_map: vec![AudioChannelId::Cf],
},
output_packet_count: 5,
output_file: None,
expected_digests: vec![
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Latm/NoMuxConfig Arm",
"09f7e4a6c55873f21772a8ef6d28d96eab287a93290d6d3cd612a11bc2abe6e3",
),
ExpectedDigest::new(
"Aac: 44.1kHz/Mono/V5/Mpeg2 LC/Latm/NoMuxConfig x64",
"a139f287f77c06e3f0a318a8712ea2cabf93c94b7b7106825747f3dd752fc7c0",
),
],
}],
};
fasync::Executor::new().unwrap().run_singlethreaded(aac_latm_without_mux_config_test.run())
})
}