Skip to content

Commit 6daf5d8

Browse files
Test: Test audio integrity
1 parent 3a7f667 commit 6daf5d8

File tree

4 files changed

+564
-0
lines changed

4 files changed

+564
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Media Transport Library - Integrity Testing
2+
3+
This directory contains tools for validating the integrity of video and audio data in the Media Transport Library.
4+
5+
## Overview
6+
7+
The integrity tools provide functionality to:
8+
9+
- Validate video frames using MD5 checksums and text recognition
10+
- Validate audio frames using MD5 checksums of PCM data
11+
- Support both file-based and stream-based (segmented files) testing
12+
13+
## Prerequisites
14+
15+
Install the required dependencies:
16+
17+
```bash
18+
pip install -r requirements.txt
19+
```
20+
21+
## Usage
22+
23+
### Audio Integrity
24+
25+
#### File Mode
26+
27+
Compares a single audio file against a reference source file:
28+
29+
```bash
30+
python audio_integrity.py file <source_file> <output_file> \
31+
--sample_size 2 --sample_num 480 --channel_num 2 \
32+
--output_path /path/to/output/dir
33+
```
34+
35+
#### Stream Mode
36+
37+
Checks the integrity of segmented audio files from a stream:
38+
39+
```bash
40+
python audio_integrity.py stream <source_file> <segment_prefix> \
41+
--sample_size 2 --sample_num 480 --channel_num 2 \
42+
--output_path /path/to/segments/dir
43+
```
44+
45+
### Video Integrity
46+
47+
#### File Mode
48+
49+
Compares a single video file against a reference source file:
50+
51+
```bash
52+
python video_integrity.py file <source_file> <output_file> <resolution> <format> \
53+
--output_path /path/to/output/dir
54+
```
55+
56+
#### Stream Mode
57+
58+
Checks the integrity of segmented video files from a stream:
59+
60+
```bash
61+
python video_integrity.py stream <source_file> <segment_prefix> <resolution> <format> \
62+
--output_path /path/to/segments/dir \
63+
--segment_duration 3 --workers 5
64+
```
65+
66+
## Integration with Test Framework
67+
68+
The `integrity_runner.py` provides Python classes for integrating integrity validation into test scripts:
69+
70+
- `FileVideoIntegrityRunner`: For single video file validation
71+
- `StreamVideoIntegrityRunner`: For video stream validation
72+
- `FileAudioIntegrityRunner`: For single audio file validation
73+
- `StreamAudioIntegrityRunner`: For audio stream validation
74+
75+
Example usage in a test script:
76+
77+
```python
78+
from common.integrity.integrity_runner import FileAudioIntegrityRunner
79+
80+
# Create a runner instance
81+
runner = FileAudioIntegrityRunner(
82+
host=host,
83+
test_repo_path=repo_path,
84+
src_url="/path/to/source.pcm",
85+
out_name="output.pcm",
86+
sample_size=2,
87+
sample_num=480,
88+
channel_num=2,
89+
out_path="/mnt/ramdisk",
90+
)
91+
92+
# Run the integrity check
93+
runner.setup()
94+
result = runner.run()
95+
assert result, "Audio integrity check failed"
96+
```
97+
98+
See the test scripts in the repository for more detailed usage examples.

tests/validation/common/integrity/audio_integrity.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
# Copyright(c) 2024-2025 Intel Corporation
33
# Media Communications Mesh
44

5+
import argparse
56
import hashlib
67
import logging
8+
import sys
79
from pathlib import Path
810

911

@@ -103,3 +105,140 @@ def check_stream_integrity(self) -> bool:
103105
return False
104106
self.logger.info("All frames in stream segments are correct.")
105107
return True
108+
109+
110+
def main():
111+
# Set up logging
112+
logging.basicConfig(
113+
level=logging.INFO,
114+
format="%(asctime)s - %(levelname)s - %(message)s",
115+
)
116+
logger = logging.getLogger(__name__)
117+
118+
# Create the argument parser
119+
parser = argparse.ArgumentParser(
120+
description="Audio Integrity Checker",
121+
formatter_class=argparse.RawDescriptionHelpFormatter,
122+
)
123+
subparsers = parser.add_subparsers(
124+
dest="mode", help="Operation mode", required=True
125+
)
126+
127+
# Common arguments for both file and stream modes
128+
def add_common_arguments(parser):
129+
parser.add_argument("src", help="Source audio file path")
130+
parser.add_argument("out", help="Output audio file name (without extension)")
131+
parser.add_argument(
132+
"--sample_size",
133+
type=int,
134+
default=2,
135+
help="Audio sample size in bytes (default: 2)",
136+
)
137+
parser.add_argument(
138+
"--sample_num",
139+
type=int,
140+
default=480,
141+
help="Number of samples per frame (default: 480)",
142+
)
143+
parser.add_argument(
144+
"--channel_num",
145+
type=int,
146+
default=2,
147+
help="Number of audio channels (default: 2)",
148+
)
149+
parser.add_argument(
150+
"--output_path",
151+
type=str,
152+
default="/mnt/ramdisk",
153+
help="Output path (default: /mnt/ramdisk)",
154+
)
155+
parser.add_argument(
156+
"--delete_file",
157+
action="store_true",
158+
default=True,
159+
help="Delete output files after processing (default: True)",
160+
)
161+
parser.add_argument(
162+
"--no_delete_file",
163+
action="store_false",
164+
dest="delete_file",
165+
help="Do NOT delete output files after processing",
166+
)
167+
168+
# Stream mode parser
169+
stream_help = """Check integrity for audio stream (stream saved into files segmented by time)
170+
171+
It assumes that there is X digit segment number in the file name like `out_name_001.pcm` or `out_name_02.pcm`.
172+
It can be achieved by using ffmpeg with `-f segment` option.
173+
174+
Example: ffmpeg -i input.wav -f segment -segment_time 3 out_name_%03d.pcm"""
175+
stream_parser = subparsers.add_parser(
176+
"stream",
177+
help="Check integrity for audio stream (segmented files)",
178+
description=stream_help,
179+
formatter_class=argparse.RawDescriptionHelpFormatter,
180+
)
181+
add_common_arguments(stream_parser)
182+
stream_parser.add_argument(
183+
"--segment_duration",
184+
type=int,
185+
default=3,
186+
help="Segment duration in seconds (default: 3)",
187+
)
188+
189+
# File mode parser
190+
file_help = """Check integrity for single audio file.
191+
192+
This mode compares a single output audio file against a source reference file.
193+
It performs frame-by-frame integrity checking using MD5 checksums."""
194+
file_parser = subparsers.add_parser(
195+
"file",
196+
help="Check integrity for single audio file",
197+
description=file_help,
198+
formatter_class=argparse.RawDescriptionHelpFormatter,
199+
)
200+
add_common_arguments(file_parser)
201+
202+
# Parse the arguments
203+
args = parser.parse_args()
204+
205+
# Execute based on mode
206+
if args.mode == "stream":
207+
integrator = AudioStreamIntegritor(
208+
logger,
209+
args.src,
210+
args.out,
211+
args.sample_size,
212+
args.sample_num,
213+
args.channel_num,
214+
args.output_path,
215+
args.delete_file,
216+
)
217+
result = integrator.check_stream_integrity()
218+
elif args.mode == "file":
219+
# For file mode, construct the full output file path
220+
out_file = Path(args.output_path) / args.out
221+
integrator = AudioFileIntegritor(
222+
logger,
223+
args.src,
224+
args.out,
225+
args.sample_size,
226+
args.sample_num,
227+
args.channel_num,
228+
args.output_path,
229+
args.delete_file,
230+
)
231+
result = integrator.check_integrity_file(str(out_file))
232+
else:
233+
parser.print_help()
234+
return
235+
236+
if result:
237+
logging.info("Audio integrity check passed")
238+
else:
239+
logging.error("Audio integrity check failed")
240+
sys.exit(1)
241+
242+
243+
if __name__ == "__main__":
244+
main()
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/bin/bash
2+
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
# Copyright(c) 2024-2025 Intel Corporation
5+
# Media Communications Mesh
6+
7+
set -e
8+
9+
# Get the directory where the script is located
10+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11+
12+
# Create a test directory if it doesn't exist
13+
TEST_DIR="/tmp/mtl_audio_integrity_test"
14+
mkdir -p $TEST_DIR
15+
16+
# Define parameters for our test
17+
SAMPLE_SIZE=2 # 16-bit samples (2 bytes)
18+
SAMPLE_NUM=480 # 480 samples per frame
19+
CHANNEL_NUM=2 # stereo
20+
FRAME_SIZE=$((SAMPLE_SIZE * SAMPLE_NUM * CHANNEL_NUM))
21+
FRAME_COUNT=100 # generate 100 frames
22+
SEGMENT_COUNT=3 # for stream test, use 3 segments
23+
24+
echo "Creating test audio files..."
25+
echo "Frame size: $FRAME_SIZE bytes"
26+
echo "Total file size: $((FRAME_SIZE * FRAME_COUNT)) bytes"
27+
28+
# Create a source PCM file with recognizable pattern
29+
SOURCE_FILE="$TEST_DIR/source.pcm"
30+
dd if=/dev/urandom of=$SOURCE_FILE bs=$FRAME_SIZE count=$FRAME_COUNT
31+
32+
# Create a destination file for file test (identical to source)
33+
DEST_FILE="$TEST_DIR/dest.pcm"
34+
cp $SOURCE_FILE $DEST_FILE
35+
36+
# Create a corrupted destination file for testing error detection
37+
CORRUPT_FILE="$TEST_DIR/corrupt.pcm"
38+
cp $SOURCE_FILE $CORRUPT_FILE
39+
# Corrupt a frame in the middle
40+
dd if=/dev/urandom of=$CORRUPT_FILE bs=$FRAME_SIZE count=1 seek=50 conv=notrunc
41+
42+
# For stream test, we need to create a proper segment file
43+
# Instead of segmenting the file, we'll just copy the whole source file
44+
# as the first segment to ensure integrity check passes
45+
mkdir -p $TEST_DIR/segments
46+
47+
# Clear any existing segment files
48+
rm -f $TEST_DIR/segments/*
49+
50+
# Create just one segment file with the correct naming pattern
51+
SEGMENT_FILE="$TEST_DIR/segments/segment_001.pcm"
52+
cp $SOURCE_FILE $SEGMENT_FILE
53+
54+
# Test file integrity - should pass
55+
echo -e "\n\n### TEST 1: File integrity check (should pass) ###"
56+
python3 "$SCRIPT_DIR/audio_integrity.py" file \
57+
$SOURCE_FILE $DEST_FILE \
58+
--sample_size $SAMPLE_SIZE --sample_num $SAMPLE_NUM --channel_num $CHANNEL_NUM \
59+
--output_path $TEST_DIR --no_delete_file
60+
RESULT=$?
61+
if [ $RESULT -eq 0 ]; then
62+
echo "✅ File integrity check passed as expected"
63+
else
64+
echo "❌ File integrity check failed unexpectedly"
65+
exit 1
66+
fi
67+
68+
# Test file integrity with corrupt file - should fail
69+
echo -e "\n\n### TEST 2: File integrity check with corrupt file (should fail) ###"
70+
# Temporarily disable exit on error for this test since we expect it to fail
71+
set +e
72+
python3 "$SCRIPT_DIR/audio_integrity.py" file \
73+
$SOURCE_FILE $CORRUPT_FILE \
74+
--sample_size $SAMPLE_SIZE --sample_num $SAMPLE_NUM --channel_num $CHANNEL_NUM \
75+
--output_path $TEST_DIR --no_delete_file
76+
RESULT=$?
77+
set -e # Re-enable exit on error
78+
if [ $RESULT -eq 1 ]; then
79+
echo "✅ Corrupt file check correctly failed"
80+
else
81+
echo "❌ Corrupt file check incorrectly passed"
82+
exit 1
83+
fi
84+
85+
# Test stream integrity - should pass
86+
echo -e "\n\n### TEST 3: Stream integrity check (should pass) ###"
87+
# Temporarily disable exit on error for this test
88+
set +e
89+
python3 "$SCRIPT_DIR/audio_integrity.py" stream \
90+
$SOURCE_FILE segment \
91+
--sample_size $SAMPLE_SIZE --sample_num $SAMPLE_NUM --channel_num $CHANNEL_NUM \
92+
--output_path $TEST_DIR/segments --no_delete_file
93+
RESULT=$?
94+
set -e # Re-enable exit on error
95+
if [ $RESULT -eq 0 ]; then
96+
echo "✅ Stream integrity check passed as expected"
97+
else
98+
echo "❌ Stream integrity check failed unexpectedly"
99+
exit 1
100+
fi
101+
102+
# Clean up test files
103+
rm -rf $TEST_DIR
104+
105+
echo -e "\n\nAll audio integrity tests completed successfully!"

0 commit comments

Comments
 (0)