From 37ac48e9e0d765ec9944ee74ff4b7bde83accf94 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Tue, 24 Mar 2026 07:34:47 +0530 Subject: [PATCH] Audio: improve record/playback tests using shared directory handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use common recorded directory across audio tests - Update run.sh and YAML for consistent folder handling - Allow individual test execution - Address review feedback# This is the 1st commit message: Audio: fix/update record‑playback test to use shared recorded directory Signed-off-by: Nitin Nakka addressed comments related to making common util for folder handling for video and audio Signed-off-by: Nitin Nakka added individual test case run possibility for audio suite Signed-off-by: Nitin Nakka Modified yaml file to handle common directory structure for files Signed-off-by: Nitin Nakka Modified run sh file to handle common dir Signed-off-by: Nitin Nakka Modified Audio scripts based on comments received Signed-off-by: nitinn audio: address final review comments Signed-off-by: nitinn --- .../Audio_Record_Playback.yaml | 11 +- .../Audio/Audio_Record_Playback/README.md | 39 +++- .../Audio/Audio_Record_Playback/run.sh | 219 +++++++++++++----- Runner/utils/lib_gstreamer.sh | 74 ++++-- 4 files changed, 263 insertions(+), 80 deletions(-) diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml index cf1fbd37..6c76237f 100644 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml @@ -5,7 +5,8 @@ metadata: Audio record/playback validation using GStreamer (gst-launch-1.0). Tests 10 scenarios: 4 encode (2 audiotestsrc + 2 pulsesrc) + 6 decode (4 playback + 2 OGG/MP3). Supports WAV, FLAC, OGG, and MP3 formats with both synthetic audio (audiotestsrc) and hardware capture (pulsesrc). - Duration controlled via AUDIO_DURATION (default 10s): audiotestsrc uses num-buffers, pulsesrc uses timeout. + Duration controlled via AUDIO_DURATION (default 10s): audiotestsrc uses num-buffers calculated after argument parsing, pulsesrc uses timeout. + Uses AUDIO_SHARED_RECORDED_DIR for shared artifact storage across test runs. os: - linux scope: @@ -13,6 +14,7 @@ metadata: params: AUDIO_TEST_MODE: "all" + AUDIO_TEST_NAME: "" AUDIO_FORMATS: "wav,flac" AUDIO_DURATION: "10" AUDIO_GST_DEBUG: "2" @@ -20,7 +22,8 @@ params: run: steps: - REPO_PATH="$PWD" - - cd Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/ - - export AUDIO_TEST_MODE AUDIO_FORMATS AUDIO_DURATION AUDIO_GST_DEBUG - - ./run.sh --mode "${AUDIO_TEST_MODE}" --formats "${AUDIO_FORMATS}" --duration "${AUDIO_DURATION}" --gst-debug "${AUDIO_GST_DEBUG}" || true + - cd "$REPO_PATH/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback" + - AUDIO_SHARED_RECORDED_DIR="${REPO_PATH%%/tests/*}/shared/audio-record-playback" + - export REPO_PATH AUDIO_SHARED_RECORDED_DIR AUDIO_TEST_MODE AUDIO_TEST_NAME AUDIO_FORMATS AUDIO_DURATION AUDIO_GST_DEBUG + - ./run.sh || true - $REPO_PATH/Runner/utils/send-to-lava.sh Audio_Record_Playback.res diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md index c1247e42..728f47fc 100644 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md @@ -131,15 +131,39 @@ By default, logs are written relative to the script working directory: playback_flac.log playback_pulsesrc_wav.log playback_pulsesrc_flac.log - recorded/ # Recorded audio files - record_wav.wav - record_flac.flac - record_pulsesrc_wav.wav - record_pulsesrc_flac.flac dmesg/ # dmesg scan outputs (if available) dmesg_errors.log ``` +### Recorded Audio Artifacts + +Recorded audio files are stored in a shared directory to enable artifact reuse across test runs: + +**Local/Manual Runs** (fallback): +``` +./logs/Audio_Record_Playback/recorded/ + record_wav.wav + record_flac.flac + record_pulsesrc_wav.wav + record_pulsesrc_flac.flac +``` + +**CI/LAVA Runs** (shared path): +``` +/shared/audio-record-playback/ + record_wav.wav + record_flac.flac + record_pulsesrc_wav.wav + record_pulsesrc_flac.flac +``` + +The recorded artifact directory is determined by: +1. **Explicit override**: `AUDIO_SHARED_RECORDED_DIR` environment variable (if set) +2. **LAVA/tests detection**: Shared path derived from repository structure (if script path contains `/tests/`) +3. **Local fallback**: `./logs/Audio_Record_Playback/recorded/` (for manual runs) + +This ensures that in CI/LAVA environments, recorded artifacts are placed in a shared location accessible across multiple test runs, while local/manual runs use a simple local directory. + --- ## Dependencies @@ -537,14 +561,19 @@ fi The test supports these environment variables (can be set in LAVA job definition): - `AUDIO_TEST_MODE` - Test mode (all/record/playback) (default: all) +- `AUDIO_TEST_NAME` - Individual test name for single test execution (optional) - `AUDIO_FORMATS` - Comma-separated format list (default: `wav,flac`) - `AUDIO_DURATION` - Recording duration in seconds (default: 10) - `RUNTIMESEC` - Alternative to AUDIO_DURATION (for backward compatibility) - `AUDIO_GST_DEBUG` - GStreamer debug level (default: 2) - `GST_DEBUG_LEVEL` - Alternative to AUDIO_GST_DEBUG +- `AUDIO_SHARED_RECORDED_DIR` - Shared directory for recorded audio artifacts (optional) +- `REPO_PATH` - Repository root path (set by YAML, used for path resolution) **Priority order for duration**: `AUDIO_DURATION` > `RUNTIMESEC` > default (10) +**Shared Artifact Directory**: The test uses `AUDIO_SHARED_RECORDED_DIR` to store recorded audio files in a shared location across multiple test runs. If not set, the test will automatically determine the appropriate directory based on the environment (LAVA vs local). + ### Test Counting - **Total tests**: 10 (when running with default wav,flac formats in all mode) diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh index 7c12eedf..ee3f3ca5 100755 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -46,12 +46,7 @@ LOG_DIR="${SCRIPT_DIR}/logs" OUTDIR="$LOG_DIR/$TESTNAME" GST_LOG="$OUTDIR/gst.log" DMESG_DIR="$OUTDIR/dmesg" -RECORDED_DIR="$OUTDIR/recorded" -mkdir -p "$OUTDIR" "$DMESG_DIR" "$RECORDED_DIR" >/dev/null 2>&1 || true -: >"$RES_FILE" -: >"$GST_LOG" - INIT_ENV="" SEARCH="$SCRIPT_DIR" while [ "$SEARCH" != "/" ]; do @@ -80,6 +75,35 @@ fi # shellcheck disable=SC1091 . "$TOOLS/lib_gstreamer.sh" +# Create required directories now that log functions are available +if ! mkdir -p "$OUTDIR" "$DMESG_DIR"; then + log_error "Failed to create required directories:" + log_error " OUTDIR=$OUTDIR" + log_error " DMESG_DIR=$DMESG_DIR" + echo "$TESTNAME FAIL" >"$RES_FILE" 2>/dev/null || true + exit 0 +fi +: >"$RES_FILE" +: >"$GST_LOG" + +# -------------------- Set up shared recorded directory -------------------- +# Use gstreamer_shared_recorded_dir() as single source of truth for directory resolution +# Priority: 1) AUDIO_SHARED_RECORDED_DIR env var, 2) LAVA/tests shared path, 3) local fallback +if [ -n "${AUDIO_SHARED_RECORDED_DIR:-}" ]; then + RECORDED_DIR="$AUDIO_SHARED_RECORDED_DIR" +elif command -v gstreamer_shared_recorded_dir >/dev/null 2>&1; then + RECORDED_DIR="$(gstreamer_shared_recorded_dir "$SCRIPT_DIR" "$OUTDIR")" +else + RECORDED_DIR="$OUTDIR/recorded" +fi + +# Create the recorded directory +if ! mkdir -p "$RECORDED_DIR"; then + log_error "Failed to create recorded directory: $RECORDED_DIR" + echo "$TESTNAME FAIL" >"$RES_FILE" + exit 0 +fi + result="FAIL" reason="unknown" pass_count=0 @@ -89,17 +113,13 @@ total_tests=0 # -------------------- Defaults (LAVA env vars -> defaults; CLI overrides) -------------------- testMode="${AUDIO_TEST_MODE:-all}" +testName="${AUDIO_TEST_NAME:-}" formatList="${AUDIO_FORMATS:-wav,flac}" duration="${AUDIO_DURATION:-${RUNTIMESEC:-10}}" gstDebugLevel="${AUDIO_GST_DEBUG:-${GST_DEBUG_LEVEL:-2}}" clipUrl="${AUDIO_CLIP_URL:-https://github.com/qualcomm-linux/qcom-linux-testkit/releases/download/GST-Audio-Files-v1.0/audio_clips_gst.tar.gz}" clipPath="${AUDIO_CLIP_PATH:-}" -# Calculate num_buffers based on duration -# Formula: num_buffers = (sample_rate * duration) / samples_per_buffer -# Example: (44100 * 10) / 1024 = 430 buffers for 10 seconds -NUM_BUFFERS=$(( (SAMPLE_RATE * duration) / SAMPLES_PER_BUFFER )) - # Validate numeric parameters (only validate if explicitly set) for param in AUDIO_DURATION AUDIO_GST_DEBUG GST_DEBUG_LEVEL; do val="" @@ -210,6 +230,16 @@ while [ $# -gt 0 ]; do shift 2 ;; + --test-name) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --test-name" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && testName="$2" + shift 2 + ;; + -h|--help) cat <"$RES_FILE" + exit 0 + ;; + esac +fi + +# Calculate num_buffers based on final duration value +# Formula: num_buffers = (sample_rate * duration) / samples_per_buffer +# Example: (44100 * 10) / 1024 = 430 buffers for 10 seconds +NUM_BUFFERS=$(( (SAMPLE_RATE * duration) / SAMPLES_PER_BUFFER )) + # -------------------- Pre-checks -------------------- check_dependencies "gst-launch-1.0 gst-inspect-1.0 awk grep head sed tr stat find curl tar" >/dev/null 2>&1 || { log_skip "Missing required tools (gst-launch-1.0, gst-inspect-1.0, awk, grep, head, sed, tr, stat, find, curl, tar)" @@ -339,6 +393,7 @@ log_info "Audio params: sample_rate=${SAMPLE_RATE}Hz, samples_per_buffer=${SAMPL log_info "Calculated num_buffers: $NUM_BUFFERS (for ${duration}s duration)" log_info "GST debug: GST_DEBUG=$gstDebugLevel" log_info "Logs: $OUTDIR" +log_info "Recorded artifact dir: $RECORDED_DIR" # -------------------- Required element validation -------------------- check_required_elements() { @@ -810,59 +865,109 @@ if ! check_required_elements; then fi log_info "Required GStreamer elements verified" -# Provision Test files for OGG/MP3 playback tests -provision_test_files - # Parse format list formats=$(printf '%s' "$formatList" | tr ',' ' ') -# Run ALL record/encode tests first (4 tests total) -if [ "$testMode" = "all" ] || [ "$testMode" = "record" ]; then - log_info "==========================================" - log_info "RECORD TESTS" - log_info "==========================================" - - # 1. Record with audiotestsrc (2 tests: wav, flac) - log_info "Recording with audiotestsrc..." - for fmt in $formats; do - total_tests=$((total_tests + 1)) - run_record_test "$fmt" || true - done - - # 2. Record with pulsesrc HW (2 tests: wav, flac) - log_info "Recording with pulsesrc HW..." - for fmt in $formats; do - total_tests=$((total_tests + 1)) - run_record_pulsesrc_test "$fmt" || true - done -fi - -# Run ALL playback/decode tests after recording (4 tests total) -if [ "$testMode" = "all" ] || [ "$testMode" = "playback" ]; then +# -------------------- Individual Test Mode -------------------- +if [ -n "$testName" ]; then + # Only provision test files if running OGG/MP3 playback tests + case "$testName" in + playback_sample_ogg|playback_sample_mp3) + provision_test_files + ;; + esac log_info "==========================================" - log_info "PLAYBACK TESTS" + log_info "INDIVIDUAL TEST MODE: $testName" log_info "==========================================" - - # 3. Playback audiotestsrc recordings (2 tests: wav, flac) - log_info "Playing back audiotestsrc recordings..." - for fmt in $formats; do - total_tests=$((total_tests + 1)) - run_playback_test "$fmt" || true - done - - # 4. Playback pulsesrc recordings (2 tests: wav, flac) - log_info "Playing back pulsesrc recordings..." - for fmt in $formats; do - total_tests=$((total_tests + 1)) - run_playback_pulsesrc_test "$fmt" || true - done - # 5. Playback Test files (2 tests: ogg, mp3) - log_info "Playing back Test files (OGG/MP3)..." - for fmt in ogg mp3; do - total_tests=$((total_tests + 1)) - run_playback_ogg_mp3_test "$fmt" || true - done + total_tests=1 + + case "$testName" in + record_wav) + run_record_test "wav" || true + ;; + record_flac) + run_record_test "flac" || true + ;; + record_pulsesrc_wav) + run_record_pulsesrc_test "wav" || true + ;; + record_pulsesrc_flac) + run_record_pulsesrc_test "flac" || true + ;; + playback_wav) + run_playback_test "wav" || true + ;; + playback_flac) + run_playback_test "flac" || true + ;; + playback_pulsesrc_wav) + run_playback_pulsesrc_test "wav" || true + ;; + playback_pulsesrc_flac) + run_playback_pulsesrc_test "flac" || true + ;; + playback_sample_ogg) + run_playback_ogg_mp3_test "ogg" || true + ;; + playback_sample_mp3) + run_playback_ogg_mp3_test "mp3" || true + ;; + esac + +# -------------------- Grouped Test Mode (Original) -------------------- +else + # Run ALL record/encode tests first (4 tests total) + if [ "$testMode" = "all" ] || [ "$testMode" = "record" ]; then + log_info "==========================================" + log_info "RECORD TESTS" + log_info "==========================================" + + # 1. Record with audiotestsrc (2 tests: wav, flac) + log_info "Recording with audiotestsrc..." + for fmt in $formats; do + total_tests=$((total_tests + 1)) + run_record_test "$fmt" || true + done + + # 2. Record with pulsesrc HW (2 tests: wav, flac) + log_info "Recording with pulsesrc HW..." + for fmt in $formats; do + total_tests=$((total_tests + 1)) + run_record_pulsesrc_test "$fmt" || true + done + fi + + # Run ALL playback/decode tests after recording (6 tests total) + if [ "$testMode" = "all" ] || [ "$testMode" = "playback" ]; then + # Provision test files only when running playback tests + provision_test_files + + log_info "==========================================" + log_info "PLAYBACK TESTS" + log_info "==========================================" + + # 3. Playback audiotestsrc recordings (2 tests: wav, flac) + log_info "Playing back audiotestsrc recordings..." + for fmt in $formats; do + total_tests=$((total_tests + 1)) + run_playback_test "$fmt" || true + done + + # 4. Playback pulsesrc recordings (2 tests: wav, flac) + log_info "Playing back pulsesrc recordings..." + for fmt in $formats; do + total_tests=$((total_tests + 1)) + run_playback_pulsesrc_test "$fmt" || true + done + + # 5. Playback Test files (2 tests: ogg, mp3) + log_info "Playing back Test files (OGG/MP3)..." + for fmt in ogg mp3; do + total_tests=$((total_tests + 1)) + run_playback_ogg_mp3_test "$fmt" || true + done + fi fi # -------------------- Dmesg error scan -------------------- diff --git a/Runner/utils/lib_gstreamer.sh b/Runner/utils/lib_gstreamer.sh index 243394b7..901dbbde 100755 --- a/Runner/utils/lib_gstreamer.sh +++ b/Runner/utils/lib_gstreamer.sh @@ -1,6 +1,6 @@ #!/bin/sh # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. -# SPDX-License-Identifier: BSD-3-Clause# +# SPDX-License-Identifier: BSD-3-Clause # Runner/utils/lib_gstreamer.sh # # GStreamer helpers. @@ -20,31 +20,77 @@ GSTLAUNCHFLAGS="${GSTLAUNCHFLAGS:--e -v -m}" # GST_ALSA_PLAYBACK_DEVICE=hw:0,0 # GST_ALSA_CAPTURE_DEVICE=hw:0,1 -# -------------------- Shared encoded-artifact directory -------------------- -# gstreamer_shared_encoded_dir -# Prints a directory path to use for encoded video artifacts. +# -------------------- Shared artifact directory (generic) -------------------- +# gstreamer_shared_artifact_dir +# Generic function to get shared artifact directory for any test type. # Priority: -# 1. VIDEO_SHARED_ENCODE_DIR if explicitly provided +# 1. Environment variable if explicitly provided (e.g., VIDEO_SHARED_ENCODE_DIR, AUDIO_SHARED_RECORDED_DIR) # 2. A job-shared path derived from the common LAVA prefix before /tests/ -# 3. Fallback to /encoded for local/manual runs -gstreamer_shared_encoded_dir() { - script_dir="$1" - outdir="$2" - - if [ -n "${VIDEO_SHARED_ENCODE_DIR:-}" ]; then - printf '%s\n' "$VIDEO_SHARED_ENCODE_DIR" +# 3. Fallback to / for local/manual runs +# +# Parameters: +# env_var_name: Name of environment variable to check (e.g., "VIDEO_SHARED_ENCODE_DIR") +# shared_subdir: Subdirectory name for shared path (e.g., "video-encode-decode", "audio-record-playback") +# local_subdir: Subdirectory name for local fallback (e.g., "encoded", "recorded") +# script_dir: Script directory path +# outdir: Output directory path +# +# Example usage: +# gstreamer_shared_artifact_dir "VIDEO_SHARED_ENCODE_DIR" "video-encode-decode" "encoded" "$SCRIPT_DIR" "$OUTDIR" +# gstreamer_shared_artifact_dir "AUDIO_SHARED_RECORDED_DIR" "audio-record-playback" "recorded" "$SCRIPT_DIR" "$OUTDIR" +gstreamer_shared_artifact_dir() { + env_var_name="$1" + shared_subdir="$2" + local_subdir="$3" + script_dir="$4" + outdir="$5" + + # Check if environment variable is set (using eval for dynamic variable name) + env_value=$(eval "printf '%s' \"\${${env_var_name}:-}\"") + if [ -n "$env_value" ]; then + printf '%s\n' "$env_value" return 0 fi + # Check if we're in a LAVA test structure (contains /tests/) case "$script_dir" in */tests/*) - printf '%s/shared/video-encode-decode\n' "${script_dir%%/tests/*}" + printf '%s/shared/%s\n' "${script_dir%%/tests/*}" "$shared_subdir" ;; *) - printf '%s/encoded\n' "$outdir" + printf '%s/%s\n' "$outdir" "$local_subdir" ;; esac } + +# -------------------- Shared encoded-artifact directory (video) -------------------- +# gstreamer_shared_encoded_dir +# Prints a directory path to use for encoded video artifacts. +# This is a wrapper around gstreamer_shared_artifact_dir for backward compatibility. +# Priority: +# 1. VIDEO_SHARED_ENCODE_DIR if explicitly provided +# 2. A job-shared path derived from the common LAVA prefix before /tests/ +# 3. Fallback to /encoded for local/manual runs +gstreamer_shared_encoded_dir() { + script_dir="$1" + outdir="$2" + + gstreamer_shared_artifact_dir "VIDEO_SHARED_ENCODE_DIR" "video-encode-decode" "encoded" "$script_dir" "$outdir" +} + +# -------------------- Shared recorded-artifact directory (audio) -------------------- +# gstreamer_shared_recorded_dir +# Prints a directory path to use for recorded audio artifacts. +# Priority: +# 1. AUDIO_SHARED_RECORDED_DIR if explicitly provided +# 2. A job-shared path derived from the common LAVA prefix before /tests/ +# 3. Fallback to /recorded for local/manual runs +gstreamer_shared_recorded_dir() { + script_dir="$1" + outdir="$2" + + gstreamer_shared_artifact_dir "AUDIO_SHARED_RECORDED_DIR" "audio-record-playback" "recorded" "$script_dir" "$outdir" +} # -------------------- Element check -------------------- has_element() { elem="$1"