From 779d38fb2e2d6b52ce6ae43a71396a7f935fd2e8 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Sat, 7 Mar 2026 00:39:22 +0530 Subject: [PATCH 1/7] Adding GStreamer test cases for Audio record and playback functionality, supports wav and flac codecs, added support in lib gstreamer sh function to handle pipelines Signed-off-by: Nitin Nakka --- .../Audio_Record_Playback.yaml | 26 + .../Audio/Audio_Record_Playback/README.md | 553 +++++++++++++++ .../Audio/Audio_Record_Playback/run.sh | 669 ++++++++++++++++++ Runner/utils/lib_gstreamer.sh | 90 ++- 4 files changed, 1318 insertions(+), 20 deletions(-) create mode 100644 Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml create mode 100644 Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md create mode 100644 Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh 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 new file mode 100644 index 000000000..3bdc919ee --- /dev/null +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/Audio_Record_Playback.yaml @@ -0,0 +1,26 @@ +metadata: + name: gstreamer-audio-record-playback + format: "Lava-Test Test Definition 1.0" + description: > + Audio record/playback validation using GStreamer (gst-launch-1.0). + Tests 8 scenarios: 4 encode (2 audiotestsrc + 2 pulsesrc) + 4 decode (playback). + Supports WAV and FLAC formats with both synthetic audio (audiotestsrc) and hardware capture (pulsesrc). + Duration controlled via AUDIO_DURATION (default 10s): audiotestsrc uses num-buffers, pulsesrc uses timeout. + os: + - linux + scope: + - functional + +params: + AUDIO_TEST_MODE: "all" + AUDIO_FORMATS: "wav,flac" + AUDIO_DURATION: "10" + AUDIO_GST_DEBUG: "2" + +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 + - $REPO_PATH/Runner/utils/send-to-lava.sh Audio_Record_Playback.res || true diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md new file mode 100644 index 000000000..60ce90f61 --- /dev/null +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md @@ -0,0 +1,553 @@ +# Audio_Record_Playback (GStreamer) — Runner Test + +This directory contains the **Audio_Record_Playback** validation test for Qualcomm Linux Testkit runners. + +It validates audio **recording and playback** using **GStreamer (`gst-launch-1.0`)** with: +- **audiotestsrc** - Synthetic audio generation (no microphone needed) +- **pulsesrc** - Hardware audio capture (microphone/line-in) +- **pulsesink** - PulseAudio playback +- **wavenc** / **flacenc** - Audio encoding +- **wavparse** / **flacparse + flacdec** - Audio decoding + +The script is designed to be **CI/LAVA-friendly**: +- Writes **PASS/FAIL/SKIP** into `Audio_Record_Playback.res` +- Always **exits 0** (even on FAIL/SKIP) to avoid terminating LAVA jobs early +- Logs the **final `gst-launch-1.0` command** to console and to log files +- Supports both synthetic audio (audiotestsrc) and hardware capture (pulsesrc) +- Dynamically calculates buffer count based on duration for audiotestsrc +- Uses timeout mechanism for pulsesrc duration control + +--- + +## Location in repo + +Expected path: + +``` +Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +``` + +Required shared utils (sourced from `Runner/utils` via `init_env`): +- `functestlib.sh` +- `lib_gstreamer.sh` - **Contains reusable audio pipeline builders** (see Library Functions section below) + +--- + +## What this test does + +At a high level, the test: + +1. Finds and sources `init_env` +2. Sources: + - `$TOOLS/functestlib.sh` + - `$TOOLS/lib_gstreamer.sh` +3. Checks for required GStreamer elements (audiotestsrc, pulsesrc, pulsesink, wavenc, flacenc, wavparse, flacparse, flacdec) +4. **Recording phase (ENCODE - 4 tests)**: + - **audiotestsrc tests**: Generates sine wave at 440Hz, encodes to WAV/FLAC + - **pulsesrc tests**: Captures from hardware audio input, encodes to WAV/FLAC + - Saves recorded files to `logs/Audio_Record_Playback/recorded/` + - Duration control: + - audiotestsrc: Buffer count calculated dynamically: `(44100 * duration) / 1024` + - pulsesrc: Uses timeout command to stop recording after specified duration +5. **Playback phase (DECODE - 4 tests)**: + - Reads the previously recorded files (both audiotestsrc and pulsesrc recordings) + - Decodes and plays back using pulsesink +6. Collects test results and emits PASS/FAIL/SKIP + +--- + +## Test Cases + +By default, the test runs **8 test cases** with 10 second duration: + +### ENCODE PHASE (4 tests) + +#### Recording Tests - audiotestsrc (Synthetic Audio) +1. **record_wav** - Record WAV format using audiotestsrc → audioconvert → wavenc +2. **record_flac** - Record FLAC format using audiotestsrc → audioconvert → flacenc + +#### Recording Tests - pulsesrc (Hardware Audio Capture) +3. **record_pulsesrc_wav** - Record WAV format using pulsesrc → audioconvert → wavenc +4. **record_pulsesrc_flac** - Record FLAC format using pulsesrc → audioconvert → flacenc + +### DECODE PHASE (4 tests) + +#### Playback Tests - audiotestsrc recordings +5. **playback_wav** - Playback WAV file using filesrc → wavparse → audioconvert → pulsesink +6. **playback_flac** - Playback FLAC file using filesrc → flacparse → flacdec → pulsesink + +#### Playback Tests - pulsesrc recordings +7. **playback_pulsesrc_wav** - Playback WAV file using filesrc → wavparse → audioconvert → pulsesink +8. **playback_pulsesrc_flac** - Playback FLAC file using filesrc → flacparse → flacdec → pulsesink + +**Total: 8 test cases** (4 encode + 4 decode) + +--- + +## PASS / FAIL / SKIP criteria + +### PASS +- **Recording**: Output file is created and has size > 1000 bytes +- **Playback**: Pipeline completes successfully (exit code 0, 124, or 143) +- **Overall**: At least one test passes and no tests fail + +### FAIL +- **Recording**: No output file created or file size too small +- **Playback**: Pipeline fails or GStreamer errors detected +- **Overall**: One or more tests fail + +### SKIP +- Missing required tools (`gst-launch-1.0`, `gst-inspect-1.0`) +- Required GStreamer elements not available (audiotestsrc, pulsesrc, pulsesink, wavenc, flacenc) +- For playback tests: corresponding recorded file not found (record must run first) +- For pulsesrc tests: pulsesrc plugin not available + +**Note:** The test always exits `0` even for FAIL/SKIP. The `.res` file is the source of truth. + +--- + +## Logs and artifacts + +By default, logs are written relative to the script working directory: + +``` +./Audio_Record_Playback.res +./logs/Audio_Record_Playback/ + gst.log # GStreamer debug output + record_wav.log # Individual test logs + record_flac.log + record_pulsesrc_wav.log + record_pulsesrc_flac.log + playback_wav.log + 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 +``` + +--- + +## Dependencies + +### Required +- `gst-launch-1.0` +- `gst-inspect-1.0` +- `audiotestsrc` GStreamer plugin +- `audioconvert` GStreamer plugin +- `pulsesink` GStreamer plugin + +### Optional (for hardware capture tests) +- `pulsesrc` GStreamer plugin +- Working audio input device (microphone/line-in) + +### Encoder Elements +- `wavenc` - WAV encoder +- `flacenc` - FLAC encoder + +### Decoder Elements +- `wavparse` - WAV parser +- `flacparse` - FLAC parser +- `flacdec` - FLAC decoder + +### Audio Backend +- PulseAudio server running + +--- + +## Usage + +Run: + +```bash +./run.sh [options] +``` + +Help: + +```bash +./run.sh --help +``` + +### Options + +- `--mode ` + - Default: `all` (run both record and playback tests) + - `record`: Run only recording tests (both audiotestsrc and pulsesrc) + - `playback`: Run only playback tests (requires recorded files from previous record run) + +- `--formats ` + - Comma-separated list of formats to test + - Default: `wav,flac` (both formats) + - Examples: `wav`, `flac`, `wav,flac` + +- `--duration ` + - Duration for recording (in seconds) + - Default: `10` + - For audiotestsrc: Determines buffer count: `(44100 * duration) / 1024` + - For pulsesrc: Uses timeout command to stop recording after this duration + - Example: 10 seconds → 430 buffers (audiotestsrc) or 10 second timeout (pulsesrc) + +- `--gst-debug ` + - Sets `GST_DEBUG=` (1-9) + - Values: + - `1` ERROR + - `2` WARNING (default) + - `3` FIXME + - `4` INFO + - `5` DEBUG + - `6` LOG + - `7` TRACE + - `8` MEMDUMP + - `9` MEMDUMP + - Default: `2` + +--- + +## Examples + +### 1) Run all tests (default - 8 tests: 4 encode + 4 decode for WAV and FLAC with 10 second duration) + +```bash +./run.sh +``` + +### 2) Run only recording tests (4 encode tests) + +```bash +./run.sh --mode record +``` + +### 3) Run only playback tests (4 decode tests - requires recorded files from previous run) + +```bash +./run.sh --mode playback +``` + +### 4) Test only WAV format (4 tests: 2 encode + 2 decode) + +```bash +./run.sh --formats wav +``` + +### 5) Test only FLAC format (4 tests: 2 encode + 2 decode) + +```bash +./run.sh --formats flac +``` + +### 6) Test with longer duration (30 seconds) + +```bash +./run.sh --duration 30 +``` + +### 7) Quick test - WAV only with 3 second duration (4 tests) + +```bash +./run.sh --formats wav --duration 3 +``` + +### 8) Increase GStreamer debug verbosity + +```bash +./run.sh --gst-debug 5 +``` + +--- + +## Pipeline Details + +### Recording Pipeline - audiotestsrc (WAV) + +``` +audiotestsrc wave=sine freq=440 volume=1.0 num-buffers= + ! audioconvert + ! wavenc + ! filesink location= +``` + +Where: +- `wave=sine` generates sine wave test tone +- `freq=440` sets frequency to 440Hz (A4 note) +- `volume=1.0` sets full volume +- `num-buffers` = (44100 * duration) / 1024 + - Example: 10 seconds → (44100 * 10) / 1024 = 430 buffers + +### Recording Pipeline - audiotestsrc (FLAC) + +``` +audiotestsrc wave=sine freq=440 volume=1.0 num-buffers= + ! audioconvert + ! flacenc + ! filesink location= +``` + +### Recording Pipeline - pulsesrc (WAV) + +``` +pulsesrc volume=10 + ! audioconvert + ! wavenc + ! filesink location= +``` + +**Duration Control**: Uses `timeout` command to stop recording after specified duration (e.g., 10 seconds) + +### Recording Pipeline - pulsesrc (FLAC) + +``` +pulsesrc volume=10 + ! audioconvert + ! flacenc + ! filesink location= +``` + +**Duration Control**: Uses `timeout` command to stop recording after specified duration (e.g., 10 seconds) + +### Playback Pipeline (WAV) + +``` +filesrc location= + ! wavparse + ! audioconvert + ! pulsesink volume=10 +``` + +### Playback Pipeline (FLAC) + +``` +filesrc location= + ! flacparse + ! flacdec + ! pulsesink volume=10 +``` + +--- + +## Audio Parameters + +The test uses these audio parameters for buffer calculation (audiotestsrc only): + +- **Sample Rate**: 44100 Hz (44.1 kHz - CD quality) +- **Samples per Buffer**: 1024 (standard buffer size) +- **Buffer Count Formula**: `(sample_rate * duration) / samples_per_buffer` + +Example calculations: +- 3 seconds: (44100 * 3) / 1024 = 129 buffers +- 10 seconds: (44100 * 10) / 1024 = 430 buffers +- 30 seconds: (44100 * 30) / 1024 = 1291 buffers + +**Note**: pulsesrc tests use timeout mechanism instead of buffer count for duration control. + +--- + +## Troubleshooting + +### A) "SKIP: Missing gstreamer runtime" +- Ensure `gst-launch-1.0` and `gst-inspect-1.0` are installed in the image. + +### B) "audiotestsrc element not available" +- Check if audiotestsrc plugin is available: + ```bash + gst-inspect-1.0 audiotestsrc + ``` +- Install gst-plugins-base if missing + +### C) "pulsesrc element not available" +- Check if pulsesrc plugin is available: + ```bash + gst-inspect-1.0 pulsesrc + ``` +- Install gst-plugins-good if missing +- Note: pulsesrc tests will be skipped if plugin is not available, but audiotestsrc tests will still run + +### D) "pulsesink element not available" +- Check if pulsesink plugin is available: + ```bash + gst-inspect-1.0 pulsesink + ``` +- Ensure PulseAudio is installed and running: + ```bash + pulseaudio --check + pactl info + ``` + +### E) "wavenc plugin not available" or "flacenc plugin not available" +- Check if encoder plugins are available: + ```bash + gst-inspect-1.0 wavenc + gst-inspect-1.0 flacenc + ``` +- Install gst-plugins-good if missing + +### F) Playback tests skip with "recorded file not found" +- Run record tests first: `./run.sh --mode record` +- Or run all tests: `./run.sh --mode all` + +### G) Recording fails or produces small files +- Check available disk space +- Check `logs/Audio_Record_Playback/record_*.log` for errors +- Try with shorter duration: `./run.sh --duration 3` +- Increase debug level: `./run.sh --gst-debug 5` + +### H) "FAIL: file too small" +- Recording may have failed silently +- Check individual test logs in `logs/Audio_Record_Playback/` +- Verify GStreamer plugins are properly installed + +### I) Playback fails with PulseAudio errors +- Check PulseAudio status: + ```bash + pulseaudio --check + pactl info + ``` +- Restart PulseAudio if needed: + ```bash + pulseaudio --kill + pulseaudio --start + ``` +- Check for audio sinks: + ```bash + pactl list sinks short + ``` + +### J) pulsesrc recording fails or produces no audio +- Check if audio input device is available: + ```bash + pactl list sources short + ``` +- Test audio input manually: + ```bash + gst-launch-1.0 pulsesrc ! audioconvert ! wavenc ! filesink location=/tmp/test.wav + # Let it run for a few seconds, then Ctrl+C + aplay /tmp/test.wav + ``` +- Verify microphone is not muted: + ```bash + pactl list sources | grep -A 10 "Name:" + ``` +- Check microphone permissions and hardware connection + +--- + +## Library Functions (Runner/utils/lib_gstreamer.sh) + +This test uses reusable helper functions from `lib_gstreamer.sh` that other GStreamer tests can leverage: + +### Audio Pipeline Builders + +**`gstreamer_build_audio_record_pipeline [num_buffers]`** +- Builds audio recording pipeline with specified source +- Parameters: + - `source_type`: `audiotestsrc` or `pulsesrc` + - `format`: `wav` or `flac` + - `output_file`: Output file path + - `num_buffers`: (optional) Number of buffers for audiotestsrc (ignored for pulsesrc) +- Returns: Complete pipeline string (or empty if format/source not supported) +- Example: + ```sh + # audiotestsrc recording + NUM_BUFFERS=$(( (44100 * 10) / 1024 )) # 10 seconds + pipeline=$(gstreamer_build_audio_record_pipeline "audiotestsrc" "wav" "/tmp/test.wav" "$NUM_BUFFERS") + gstreamer_run_gstlaunch_timeout 20 "$pipeline" + + # pulsesrc recording (uses timeout for duration control) + pipeline=$(gstreamer_build_audio_record_pipeline "pulsesrc" "flac" "/tmp/hw_capture.flac") + gstreamer_run_gstlaunch_timeout 10 "$pipeline" # Records for 10 seconds + ``` + +**`gstreamer_build_audio_playback_pipeline `** +- Builds audio playback pipeline using pulsesink +- Parameters: + - `format`: `wav` or `flac` + - `input_file`: Input file path +- Returns: Complete pipeline string (or empty if format not supported) +- Example: + ```sh + pipeline=$(gstreamer_build_audio_playback_pipeline "flac" "/tmp/test.flac") + gstreamer_run_gstlaunch_timeout 20 "$pipeline" + ``` + +### Usage in Other Tests + +To use these functions in your GStreamer audio test: + +```sh +#!/bin/sh +# Source init_env and lib_gstreamer.sh +. "$INIT_ENV" +. "$TOOLS/functestlib.sh" +. "$TOOLS/lib_gstreamer.sh" + +# Calculate buffer count for 5 seconds (audiotestsrc) +SAMPLE_RATE=44100 +SAMPLES_PER_BUFFER=1024 +duration=5 +NUM_BUFFERS=$(( (SAMPLE_RATE * duration) / SAMPLES_PER_BUFFER )) + +# Build and run audiotestsrc record pipeline +pipeline=$(gstreamer_build_audio_record_pipeline "audiotestsrc" "wav" "/tmp/output.wav" "$NUM_BUFFERS") +if [ -n "$pipeline" ]; then + gstreamer_run_gstlaunch_timeout 15 "$pipeline" +fi + +# Build and run pulsesrc record pipeline (timeout controls duration) +pipeline=$(gstreamer_build_audio_record_pipeline "pulsesrc" "flac" "/tmp/hw_capture.flac") +if [ -n "$pipeline" ]; then + gstreamer_run_gstlaunch_timeout 10 "$pipeline" # 10 second recording +fi + +# Build and run playback pipeline +pipeline=$(gstreamer_build_audio_playback_pipeline "wav" "/tmp/output.wav") +if [ -n "$pipeline" ]; then + gstreamer_run_gstlaunch_timeout 15 "$pipeline" +fi +``` + +--- + +## Notes for CI / LAVA + +- The test always exits `0`. +- Use the `.res` file for result: + - `PASS` - All tests passed + - `FAIL` - One or more tests failed + - `SKIP` - No tests executed or all skipped +- Test summary is logged showing pass/fail/skip counts +- Individual test logs are available in `logs/Audio_Record_Playback/` +- Recorded files are preserved in `logs/Audio_Record_Playback/recorded/` for debugging + +### LAVA Environment Variables + +The test supports these environment variables (can be set in LAVA job definition): + +- `AUDIO_TEST_MODE` - Test mode (all/record/playback) (default: all) +- `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 + +**Priority order for duration**: `AUDIO_DURATION` > `RUNTIMESEC` > default (10) + +### Test Counting + +- **Total tests**: 8 (when running with default wav,flac formats in all mode) + - 4 encode tests (2 audiotestsrc + 2 pulsesrc) + - 4 decode tests (2 audiotestsrc playback + 2 pulsesrc playback) +- **Pass/Fail/Skip are mutually exclusive**: Each test increments exactly one counter +- **Plugin unavailability**: pulsesrc tests will skip if pulsesrc plugin is not available, but audiotestsrc tests will still run + +--- + +## License + +``` +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh new file mode 100644 index 000000000..b42759979 --- /dev/null +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -0,0 +1,669 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear +# +# Audio Record/Playback Validation using GStreamer (8 tests total) +# +# Test Sequence: +# ENCODE PHASE (4 tests): +# 1. record_wav - audiotestsrc → wavenc → file +# 2. record_flac - audiotestsrc → flacenc → file +# 3. record_pulsesrc_wav - pulsesrc HW → wavenc → file +# 4. record_pulsesrc_flac- pulsesrc HW → flacenc → file +# +# DECODE PHASE (4 tests): +# 5. playback_wav - file → wavparse → pulsesink +# 6. playback_flac - file → flacparse → flacdec → pulsesink +# 7. playback_pulsesrc_wav - file → wavparse → pulsesink +# 8. playback_pulsesrc_flac - file → flacparse → flacdec → pulsesink +# +# Features: +# - audiotestsrc: Synthetic audio generation (uses num-buffers for duration control) +# - pulsesrc: Hardware audio capture (uses timeout for duration control) +# - pulsesink: Audio playback +# - Formats: WAV (wavenc/wavparse), FLAC (flacenc/flacparse/flacdec) +# - Duration control via AUDIO_DURATION env var (default: 10 seconds) +# +# Logs everything to console and local log files. +# PASS/FAIL/SKIP is emitted to .res. Always exits 0 (LAVA-friendly). + +# -------------------- Configuration -------------------- +# Audio parameters for buffer calculation +SAMPLE_RATE=44100 # 44.1 kHz +SAMPLES_PER_BUFFER=1024 # Standard buffer size + +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" + +TESTNAME="Audio_Record_Playback" +RES_FILE="${SCRIPT_DIR}/${TESTNAME}.res" +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" + +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" + +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then + INIT_ENV="$SEARCH/init_env" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" + +if [ -z "${INIT_ENV:-}" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true + exit 0 +fi + +if [ -z "${__INIT_ENV_LOADED:-}" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + __INIT_ENV_LOADED=1 +fi + +# shellcheck disable=SC1091 +. "$TOOLS/functestlib.sh" + +# shellcheck disable=SC1091 +. "$TOOLS/lib_gstreamer.sh" + +result="FAIL" +reason="unknown" +pass_count=0 +fail_count=0 +skip_count=0 +total_tests=0 + +# -------------------- Defaults (LAVA env vars -> defaults; CLI overrides) -------------------- +testMode="${AUDIO_TEST_MODE:-all}" +formatList="${AUDIO_FORMATS:-wav,flac}" +duration="${AUDIO_DURATION:-${RUNTIMESEC:-10}}" +gstDebugLevel="${AUDIO_GST_DEBUG:-${GST_DEBUG_LEVEL:-2}}" + +# 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="" + case "$param" in + AUDIO_DURATION) val="${AUDIO_DURATION-}" ;; + AUDIO_GST_DEBUG) val="${AUDIO_GST_DEBUG-}" ;; + GST_DEBUG_LEVEL) val="${GST_DEBUG_LEVEL-}" ;; + esac + + if [ -n "$val" ]; then + case "$val" in + ''|*[!0-9]*) + log_warn "$param must be numeric (got '$val')" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; + *) + if [ "$val" -le 0 ] 2>/dev/null; then + log_warn "$param must be positive (got '$val')" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + ;; + esac + fi +done + +cleanup() { + pkill -x gst-launch-1.0 >/dev/null 2>&1 || true +} +trap cleanup INT TERM EXIT + +# -------------------- Arg parse -------------------- +while [ $# -gt 0 ]; do + case "$1" in + --mode) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --mode" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && testMode="$2" + shift 2 + ;; + + --formats) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --formats" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && formatList="$2" + shift 2 + ;; + + --duration) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --duration" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + if [ -n "$2" ]; then + case "$2" in + ''|*[!0-9]*) + log_warn "Invalid --duration '$2' (must be numeric)" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; + *) + duration="$2" + ;; + esac + fi + shift 2 + ;; + + --gst-debug) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --gst-debug" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && gstDebugLevel="$2" + shift 2 + ;; + + -h|--help) + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; + + *) + log_warn "Unknown argument: $1" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; + esac +done + +# -------------------- Validate parsed values -------------------- +case "$testMode" in all|record|playback) : ;; *) + log_warn "Invalid --mode '$testMode'" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; +esac + +case "$gstDebugLevel" in 1|2|3|4|5|6|7|8|9) : ;; *) + log_warn "Invalid --gst-debug '$gstDebugLevel' (allowed: 1-9)" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; +esac + +case "$duration" in + ''|*[!0-9]*) + log_warn "Invalid duration '$duration' (must be numeric)" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + ;; + *) + if [ "$duration" -le 0 ] 2>/dev/null; then + log_warn "Duration must be positive (got '$duration')" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + ;; +esac + +# -------------------- 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)" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 +} + +log_info "Checking dependencies: gst-launch-1.0 gst-inspect-1.0 awk grep head sed tr stat find curl tar" +log_info "Test: $TESTNAME" +log_info "Mode: $testMode" +log_info "Formats: $formatList" +log_info "Duration: ${duration}s" +log_info "Backend: audiotestsrc + pulsesrc for recording, pulsesink for playback" +log_info "Audio params: sample_rate=${SAMPLE_RATE}Hz, samples_per_buffer=${SAMPLES_PER_BUFFER}" +log_info "Calculated num_buffers: $NUM_BUFFERS (for ${duration}s duration)" +log_info "GST debug: GST_DEBUG=$gstDebugLevel" +log_info "Logs: $OUTDIR" + +# -------------------- Required element validation -------------------- +check_required_elements() { + if ! has_element audiotestsrc; then + log_warn "audiotestsrc element not available" + return 1 + fi + if ! has_element pulsesink; then + log_warn "pulsesink element not available" + return 1 + fi + return 0 +} + +# -------------------- Record test function (audiotestsrc) -------------------- +run_record_test() { + fmt="$1" + + testname="record_${fmt}" + log_info "==========================================" + log_info "Running: $testname" + log_info "==========================================" + + # Check required plugins + case "$fmt" in + wav) + if ! has_element wavenc; then + log_warn "$testname: wavenc plugin not available" + return 1 + fi + ;; + flac) + if ! has_element flacenc; then + log_warn "$testname: flacenc plugin not available" + return 1 + fi + ;; + esac + + ext="$fmt" + output_file="$RECORDED_DIR/${testname}.${ext}" + test_log="$OUTDIR/${testname}.log" + + : >"$test_log" + + pipeline="$(gstreamer_build_audio_record_pipeline "audiotestsrc" "$fmt" "$output_file" "$NUM_BUFFERS")" + + if [ -z "$pipeline" ]; then + log_fail "$testname: FAIL (could not build record pipeline)" + fail_count=$((fail_count + 1)) + return 1 + fi + + log_info "Pipeline: $pipeline" + + # Run recording + if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then + gstRc=0 + else + gstRc=$? + fi + + log_info "Record exit code: $gstRc" + + # Check for GStreamer errors in log + if ! gstreamer_validate_log "$test_log" "$testname"; then + log_fail "$testname: FAIL (GStreamer errors detected)" + fail_count=$((fail_count + 1)) + return 1 + fi + + # Check if output file was created and has content + if [ -f "$output_file" ] && [ -s "$output_file" ]; then + file_size="$(gstreamer_file_size_bytes "$output_file")" + log_info "Recorded file: $output_file (size: $file_size bytes)" + + if [ "$file_size" -gt 1000 ]; then + log_pass "$testname: PASS" + pass_count=$((pass_count + 1)) + return 0 + else + log_fail "$testname: FAIL (file too small: $file_size bytes)" + fail_count=$((fail_count + 1)) + return 1 + fi + else + log_fail "$testname: FAIL (no output file created)" + fail_count=$((fail_count + 1)) + return 1 + fi +} + +# -------------------- Playback test function -------------------- +run_playback_test() { + fmt="$1" + + testname="playback_${fmt}" + log_info "==========================================" + log_info "Running: $testname" + log_info "==========================================" + + ext="$fmt" + input_file="$RECORDED_DIR/record_${fmt}.${ext}" + + if [ ! -f "$input_file" ]; then + log_warn "$testname: SKIP - recorded file not found: $input_file (run record first)" + skip_count=$((skip_count + 1)) + return 1 + fi + + test_log="$OUTDIR/${testname}.log" + : >"$test_log" + + pipeline="$(gstreamer_build_audio_playback_pipeline "$fmt" "$input_file")" + + if [ -z "$pipeline" ]; then + log_fail "$testname: FAIL (could not build playback pipeline)" + fail_count=$((fail_count + 1)) + return 1 + fi + + log_info "Pipeline: $pipeline" + + # Run playback + if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then + gstRc=0 + else + gstRc=$? + fi + + log_info "Playback exit code: $gstRc" + + # Check for GStreamer errors in log + if ! gstreamer_validate_log "$test_log" "$testname"; then + log_fail "$testname: FAIL (GStreamer errors detected)" + fail_count=$((fail_count + 1)) + return 1 + fi + + # Check for successful completion (rc=0 or timeout rc which means it played to end) + if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + log_pass "$testname: PASS" + pass_count=$((pass_count + 1)) + return 0 + else + log_fail "$testname: FAIL (rc=$gstRc)" + fail_count=$((fail_count + 1)) + return 1 + fi +} + +# -------------------- PulseSrc Record test function -------------------- +run_record_pulsesrc_test() { + fmt="$1" + + testname="record_pulsesrc_${fmt}" + log_info "==========================================" + log_info "Running: $testname" + log_info "==========================================" + + # Check required plugins + if ! has_element pulsesrc; then + log_warn "$testname: pulsesrc plugin not available" + skip_count=$((skip_count + 1)) + return 1 + fi + + case "$fmt" in + wav) + if ! has_element wavenc; then + log_warn "$testname: wavenc plugin not available" + skip_count=$((skip_count + 1)) + return 1 + fi + ;; + flac) + if ! has_element flacenc; then + log_warn "$testname: flacenc plugin not available" + skip_count=$((skip_count + 1)) + return 1 + fi + ;; + esac + + ext="$fmt" + output_file="$RECORDED_DIR/${testname}.${ext}" + test_log="$OUTDIR/${testname}.log" + + : >"$test_log" + + pipeline="$(gstreamer_build_audio_record_pipeline "pulsesrc" "$fmt" "$output_file")" + + if [ -z "$pipeline" ]; then + log_fail "$testname: FAIL (could not build pulsesrc record pipeline)" + fail_count=$((fail_count + 1)) + return 1 + fi + + log_info "Pipeline: $pipeline" + + # Run recording with timeout + if gstreamer_run_gstlaunch_timeout "$duration" "$pipeline" >>"$test_log" 2>&1; then + gstRc=0 + else + gstRc=$? + fi + + log_info "Record exit code: $gstRc" + + # Check for GStreamer errors in log + if ! gstreamer_validate_log "$test_log" "$testname"; then + log_fail "$testname: FAIL (GStreamer errors detected)" + fail_count=$((fail_count + 1)) + return 1 + fi + + # Check if output file was created and has content + if [ -f "$output_file" ] && [ -s "$output_file" ]; then + file_size="$(gstreamer_file_size_bytes "$output_file")" + log_info "Recorded file: $output_file (size: $file_size bytes)" + + if [ "$file_size" -gt 1000 ]; then + log_pass "$testname: PASS" + pass_count=$((pass_count + 1)) + return 0 + else + log_fail "$testname: FAIL (file too small: $file_size bytes)" + fail_count=$((fail_count + 1)) + return 1 + fi + else + log_fail "$testname: FAIL (no output file created)" + fail_count=$((fail_count + 1)) + return 1 + fi +} + +# -------------------- PulseSrc Playback test function -------------------- +run_playback_pulsesrc_test() { + fmt="$1" + + testname="playback_pulsesrc_${fmt}" + log_info "==========================================" + log_info "Running: $testname" + log_info "==========================================" + + ext="$fmt" + input_file="$RECORDED_DIR/record_pulsesrc_${fmt}.${ext}" + + if [ ! -f "$input_file" ]; then + log_warn "$testname: SKIP - recorded file not found: $input_file (run pulsesrc record first)" + skip_count=$((skip_count + 1)) + return 1 + fi + + test_log="$OUTDIR/${testname}.log" + : >"$test_log" + + pipeline="$(gstreamer_build_audio_playback_pipeline "$fmt" "$input_file")" + + if [ -z "$pipeline" ]; then + log_fail "$testname: FAIL (could not build playback pipeline)" + fail_count=$((fail_count + 1)) + return 1 + fi + + log_info "Pipeline: $pipeline" + + # Run playback + if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then + gstRc=0 + else + gstRc=$? + fi + + log_info "Playback exit code: $gstRc" + + # Check for GStreamer errors in log + if ! gstreamer_validate_log "$test_log" "$testname"; then + log_fail "$testname: FAIL (GStreamer errors detected)" + fail_count=$((fail_count + 1)) + return 1 + fi + + # Check for successful completion (rc=0 or timeout rc which means it played to end) + if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + log_pass "$testname: PASS" + pass_count=$((pass_count + 1)) + return 0 + else + log_fail "$testname: FAIL (rc=$gstRc)" + fail_count=$((fail_count + 1)) + return 1 + fi +} + +# -------------------- GStreamer debug capture -------------------- +export GST_DEBUG_NO_COLOR=1 +export GST_DEBUG="$gstDebugLevel" +export GST_DEBUG_FILE="$GST_LOG" + +# -------------------- Main test execution -------------------- +log_info "Starting audio record/playback tests..." + +# Check required elements +if ! check_required_elements; then + log_warn "Required GStreamer elements (audiotestsrc/pulsesink) not available" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 +fi +log_info "Required GStreamer elements verified" + +# 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 + 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 +fi + +# -------------------- Dmesg error scan -------------------- +log_info "==========================================" +log_info "DMESG ERROR SCAN" +log_info "==========================================" + +module_regex="audio|sound|pulse|codec|dsp" +exclude_regex="dummy regulator|supply [^ ]+ not found|using dummy regulator" + +if command -v scan_dmesg_errors >/dev/null 2>&1; then + scan_dmesg_errors "$DMESG_DIR" "$module_regex" "$exclude_regex" || true + + if [ -s "$DMESG_DIR/dmesg_errors.log" ]; then + log_warn "dmesg scan found audio-related warnings or errors in $DMESG_DIR/dmesg_errors.log" + else + log_info "No relevant audio-related errors found in dmesg" + fi +else + log_info "scan_dmesg_errors not available, skipping dmesg scan" +fi + +# -------------------- Summary -------------------- +log_info "==========================================" +log_info "TEST SUMMARY" +log_info "==========================================" +actual_total=$((pass_count + fail_count + skip_count)) +log_info "Total testcases: $actual_total" +log_info "Passed: $pass_count" +log_info "Failed: $fail_count" +log_info "Skipped: $skip_count" + +# -------------------- Emit result -------------------- +if [ "$fail_count" -eq 0 ] && [ "$pass_count" -gt 0 ]; then + result="PASS" + if [ "$skip_count" -gt 0 ]; then + reason="No failures (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" + else + reason="All tests passed ($pass_count/$actual_total)" + fi +elif [ "$fail_count" -gt 0 ]; then + result="FAIL" + reason="Some tests failed (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" +else + result="SKIP" + reason="No tests passed (skipped: $skip_count, total: $actual_total)" +fi + +case "$result" in + PASS) + log_pass "$TESTNAME $result: $reason" + echo "$TESTNAME PASS" >"$RES_FILE" + ;; + FAIL) + log_fail "$TESTNAME $result: $reason" + echo "$TESTNAME FAIL" >"$RES_FILE" + ;; + *) + log_warn "$TESTNAME $result: $reason" + echo "$TESTNAME SKIP" >"$RES_FILE" + ;; +esac + +exit 0 diff --git a/Runner/utils/lib_gstreamer.sh b/Runner/utils/lib_gstreamer.sh index 2af696496..56166aa03 100755 --- a/Runner/utils/lib_gstreamer.sh +++ b/Runner/utils/lib_gstreamer.sh @@ -471,30 +471,80 @@ gstreamer_run_gstlaunch_timeout() { return $? } -# -------------------- Playback pipeline builder (backend-aware) -------------------- -# gstreamer_build_playback_pipeline -gstreamer_build_playback_pipeline() { - backend="$1" - format="$2" - file="$3" - capsStr="$4" - alsadev="$5" +# -------------------- Audio Record/Playback pipeline builders -------------------- +# gstreamer_build_audio_record_pipeline [num_buffers] +# Builds audio recording pipeline with specified source +# Parameters: +# source_type: "audiotestsrc" or "pulsesrc" +# format: "wav" or "flac" +# output_file: path to output file +# num_buffers: (optional) number of buffers for audiotestsrc (ignored for pulsesrc) +# Prints: pipeline string or empty if format/source not supported +gstreamer_build_audio_record_pipeline() { + source_type="$1" + fmt="$2" + output_file="$3" + num_buffers="${4:-}" + + # Build source element + case "$source_type" in + audiotestsrc) + # num_buffers is required for audiotestsrc + if [ -z "$num_buffers" ]; then + printf '%s\n' "" + return 1 + fi + source_elem="audiotestsrc wave=sine freq=440 volume=1.0 num-buffers=${num_buffers}" + ;; + pulsesrc) + # pulsesrc doesn't use num_buffers (continuous capture until timeout) + source_elem="pulsesrc volume=10" + ;; + *) + printf '%s\n' "" + return 1 + ;; + esac - [ -n "$alsadev" ] || alsadev="default" + # Build encoder element + case "$fmt" in + wav) + encoder_elem="wavenc" + ;; + flac) + encoder_elem="flacenc" + ;; + *) + printf '%s\n' "" + return 1 + ;; + esac - dec="$(gstreamer_pick_decode_chain "$format")" - sinkElem="$(gstreamer_pick_sink_element "$backend" "$alsadev")" - if [ -z "$sinkElem" ]; then - printf '%s\n' "" - return 0 - fi + # Construct complete pipeline + printf '%s\n' "${source_elem} ! audioconvert ! ${encoder_elem} ! filesink location=${output_file}" + return 0 +} - if [ -n "$capsStr" ]; then - printf '%s\n' "filesrc location=${file} ! ${dec} ! audioconvert ! audioresample ! ${capsStr} ! ${sinkElem}" - return 0 - fi +# gstreamer_build_audio_playback_pipeline +# Builds audio playback pipeline using pulsesink +# Supports: wav, flac formats +# Prints: pipeline string or empty if format not supported +gstreamer_build_audio_playback_pipeline() { + fmt="$1" + input_file="$2" - printf '%s\n' "filesrc location=${file} ! ${dec} ! audioconvert ! audioresample ! ${sinkElem}" + case "$fmt" in + wav) + printf '%s\n' "filesrc location=${input_file} ! wavparse ! audioconvert ! pulsesink volume=10" + ;; + flac) + printf '%s\n' "filesrc location=${input_file} ! flacparse ! flacdec ! pulsesink volume=10" + ;; + *) + printf '%s\n' "" + return 1 + ;; + esac return 0 } From 7c601700acb1ec08da2d58fcbed20e1c2a3213da Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Sat, 7 Mar 2026 01:36:13 +0530 Subject: [PATCH 2/7] Modified video cleanup to better handle killing of gst-launch, in audio script added handle to check file size to be minimum 1000 bytes before initiating playback or else to skip it Signed-off-by: Nitin Nakka --- .../Audio/Audio_Record_Playback/run.sh | 21 ++++++++++++++++++- .../Video/Video_Encode_Decode/run.sh | 5 ++++- 2 files changed, 24 insertions(+), 2 deletions(-) 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 b42759979..076f0aa49 100644 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -130,7 +130,10 @@ for param in AUDIO_DURATION AUDIO_GST_DEBUG GST_DEBUG_LEVEL; do done cleanup() { - pkill -x gst-launch-1.0 >/dev/null 2>&1 || true + # Best-effort: try to kill only children first; fall back to name-based kill + if ! pkill -P "$$" -x gst-launch-1.0 >/dev/null 2>&1; then + pkill -x gst-launch-1.0 >/dev/null 2>&1 || true + fi } trap cleanup INT TERM EXIT @@ -358,6 +361,14 @@ run_playback_test() { return 1 fi + # Check if file has minimum content (same threshold as recording: 1000 bytes) + file_size="$(gstreamer_file_size_bytes "$input_file")" + if [ "$file_size" -le 1000 ]; then + log_warn "$testname: SKIP - recorded file too small: $file_size bytes (recording likely failed)" + skip_count=$((skip_count + 1)) + return 1 + fi + test_log="$OUTDIR/${testname}.log" : >"$test_log" @@ -503,6 +514,14 @@ run_playback_pulsesrc_test() { return 1 fi + # Check if file has minimum content (same threshold as recording: 1000 bytes) + file_size="$(gstreamer_file_size_bytes "$input_file")" + if [ "$file_size" -le 1000 ]; then + log_warn "$testname: SKIP - recorded file too small: $file_size bytes (pulsesrc recording likely failed)" + skip_count=$((skip_count + 1)) + return 1 + fi + test_log="$OUTDIR/${testname}.log" : >"$test_log" diff --git a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh index 318136a74..245c20a35 100755 --- a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh @@ -111,7 +111,10 @@ for param in VIDEO_DURATION RUNTIMESEC VIDEO_FRAMERATE VIDEO_GST_DEBUG GST_DEBUG done cleanup() { - pkill -x gst-launch-1.0 >/dev/null 2>&1 || true + # Best-effort: try to kill only children first; fall back to name-based kill + if ! pkill -P "$$" -x gst-launch-1.0 >/dev/null 2>&1; then + pkill -x gst-launch-1.0 >/dev/null 2>&1 || true + fi } trap cleanup INT TERM EXIT From afa337cc5d15ae34e1b4db276ea42a8f7a1881e6 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Sat, 7 Mar 2026 08:16:49 +0530 Subject: [PATCH 3/7] Fix: restore executable permission for Audio_Record_Playback run.sh Signed-off-by: Nitin Nakka --- .../Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh diff --git a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh old mode 100644 new mode 100755 From bec6a348ef80d2f7d35b97d62dea133d85969f7b Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Sun, 8 Mar 2026 00:54:57 +0530 Subject: [PATCH 4/7] Added two new playback support tests in audio for ogg and mp3 formats incl corresponding lib gstreamer Signed-off-by: Nitin Nakka --- .../Audio/Audio_Record_Playback/run.sh | 182 +++++++++++++++++- Runner/utils/lib_gstreamer.sh | 23 ++- 2 files changed, 195 insertions(+), 10 deletions(-) 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 076f0aa49..623a14816 100755 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -2,7 +2,7 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. # SPDX-License-Identifier: BSD-3-Clause-Clear # -# Audio Record/Playback Validation using GStreamer (8 tests total) +# Audio Record/Playback Validation using GStreamer (10 tests total) # # Test Sequence: # ENCODE PHASE (4 tests): @@ -11,17 +11,20 @@ # 3. record_pulsesrc_wav - pulsesrc HW → wavenc → file # 4. record_pulsesrc_flac- pulsesrc HW → flacenc → file # -# DECODE PHASE (4 tests): +# DECODE PHASE (6 tests): # 5. playback_wav - file → wavparse → pulsesink # 6. playback_flac - file → flacparse → flacdec → pulsesink # 7. playback_pulsesrc_wav - file → wavparse → pulsesink # 8. playback_pulsesrc_flac - file → flacparse → flacdec → pulsesink +# 9. playback_sample_ogg - file → oggdemux → vorbisdec → pulsesink +# 10. playback_sample_mp3 - file → mpegaudioparse → mpg123audiodec → pulsesink # # Features: # - audiotestsrc: Synthetic audio generation (uses num-buffers for duration control) # - pulsesrc: Hardware audio capture (uses timeout for duration control) # - pulsesink: Audio playback -# - Formats: WAV (wavenc/wavparse), FLAC (flacenc/flacparse/flacdec) +# - Formats: WAV (wavenc/wavparse), FLAC (flacenc/flacparse/flacdec), OGG (oggdemux/vorbisdec), MP3 (mpegaudioparse/mpg123audiodec) +# - Test file provisioning via URL download or local path # - Duration control via AUDIO_DURATION env var (default: 10 seconds) # # Logs everything to console and local log files. @@ -96,6 +99,8 @@ testMode="${AUDIO_TEST_MODE:-all}" 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 @@ -191,6 +196,26 @@ while [ $# -gt 0 ]; do shift 2 ;; + --clip-url) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --clip-url" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && clipUrl="$2" + shift 2 + ;; + + --clip-path) + if [ $# -lt 2 ] || [ "${2#--}" != "$2" ]; then + log_warn "Missing/invalid value for --clip-path" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + [ -n "$2" ] && clipPath="$2" + shift 2 + ;; + -h|--help) echo "$TESTNAME SKIP" >"$RES_FILE" exit 0 @@ -563,11 +588,152 @@ run_playback_pulsesrc_test() { fi } +# -------------------- Test file playback test function (OGG/MP3) -------------------- +run_playback_ogg_mp3_test() { + fmt="$1" + + testname="playback_sample_${fmt}" + log_info "==========================================" + log_info "Running: $testname" + log_info "==========================================" + + # Determine input file based on format + case "$fmt" in + ogg) + input_file="$OUTDIR/sample_audio.ogg" + ;; + mp3) + input_file="$OUTDIR/sample_audio.mp3" + ;; + *) + log_warn "$testname: SKIP - unsupported format: $fmt" + skip_count=$((skip_count + 1)) + return 1 + ;; + esac + + if [ ! -f "$input_file" ]; then + log_warn "$testname: SKIP - Test file not found: $input_file" + skip_count=$((skip_count + 1)) + return 1 + fi + + # Check if file has minimum content + file_size="$(gstreamer_file_size_bytes "$input_file")" + if [ "$file_size" -le 1000 ]; then + log_warn "$testname: SKIP - Test file too small: $file_size bytes" + skip_count=$((skip_count + 1)) + return 1 + fi + + test_log="$OUTDIR/${testname}.log" + : >"$test_log" + + pipeline="$(gstreamer_build_audio_playback_pipeline "$fmt" "$input_file")" + + if [ -z "$pipeline" ]; then + log_fail "$testname: FAIL (could not build playback pipeline - format not supported or elements missing)" + fail_count=$((fail_count + 1)) + return 1 + fi + + log_info "Pipeline: $pipeline" + + # Run playback + if gstreamer_run_gstlaunch_timeout "$((duration + 10))" "$pipeline" >>"$test_log" 2>&1; then + gstRc=0 + else + gstRc=$? + fi + + log_info "Playback exit code: $gstRc" + + # Check for GStreamer errors in log + if ! gstreamer_validate_log "$test_log" "$testname"; then + log_fail "$testname: FAIL (GStreamer errors detected)" + fail_count=$((fail_count + 1)) + return 1 + fi + + # Check for successful completion + if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + log_pass "$testname: PASS" + pass_count=$((pass_count + 1)) + return 0 + else + log_fail "$testname: FAIL (rc=$gstRc)" + fail_count=$((fail_count + 1)) + return 1 + fi +} + # -------------------- GStreamer debug capture -------------------- export GST_DEBUG_NO_COLOR=1 export GST_DEBUG="$gstDebugLevel" export GST_DEBUG_FILE="$GST_LOG" +# -------------------- Test file provisioning (OGG/MP3) -------------------- +provision_test_files() { + log_info "==========================================" + log_info "TEST FILE PROVISIONING" + log_info "==========================================" + + sample_ogg="$OUTDIR/sample_audio.ogg" + sample_mp3="$OUTDIR/sample_audio.mp3" + + # Check if Test files already exist + if [ -f "$sample_ogg" ] && [ -f "$sample_mp3" ]; then + log_info "Test files already exist" + else + # Try to get Test files from provided path or URL + if [ -n "$clipPath" ]; then + log_info "Attempting to get Test files from local path: $clipPath" + if [ -f "$clipPath/sample_audio.ogg" ]; then + cp "$clipPath/sample_audio.ogg" "$sample_ogg" 2>/dev/null || true + log_info "Sample OGG file copied from local path" + fi + if [ -f "$clipPath/sample_audio.mp3" ]; then + cp "$clipPath/sample_audio.mp3" "$sample_mp3" 2>/dev/null || true + log_info "Sample MP3 file copied from local path" + fi + fi + + # If not found locally, try URL download + if [ ! -f "$sample_ogg" ] || [ ! -f "$sample_mp3" ]; then + log_info "Test files not found locally; attempting download from URL..." + if extract_tar_from_url "$clipUrl" "$OUTDIR"; then + log_pass "Test files downloaded and extracted successfully" + else + log_warn "Test file download failed (offline or URL issue)" + fi + fi + fi + + # Check what we have + have_ogg=0 + have_mp3=0 + + if [ -f "$sample_ogg" ]; then + size=$(gstreamer_file_size_bytes "$sample_ogg") + if [ "$size" -gt 1000 ]; then + have_ogg=1 + log_info "OGG Test file available (size: $size bytes)" + fi + fi + + if [ -f "$sample_mp3" ]; then + size=$(gstreamer_file_size_bytes "$sample_mp3") + if [ "$size" -gt 1000 ]; then + have_mp3=1 + log_info "MP3 Test file available (size: $size bytes)" + fi + fi + + if [ "$have_ogg" -eq 0 ] && [ "$have_mp3" -eq 0 ]; then + log_warn "No Test files (OGG/MP3) available for playback tests" + fi +} + # -------------------- Main test execution -------------------- log_info "Starting audio record/playback tests..." @@ -579,6 +745,9 @@ 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 ',' ' ') @@ -622,6 +791,13 @@ if [ "$testMode" = "all" ] || [ "$testMode" = "playback" ]; then 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 # -------------------- Dmesg error scan -------------------- diff --git a/Runner/utils/lib_gstreamer.sh b/Runner/utils/lib_gstreamer.sh index 56166aa03..9d5b622a9 100755 --- a/Runner/utils/lib_gstreamer.sh +++ b/Runner/utils/lib_gstreamer.sh @@ -527,25 +527,34 @@ gstreamer_build_audio_record_pipeline() { # gstreamer_build_audio_playback_pipeline # Builds audio playback pipeline using pulsesink -# Supports: wav, flac formats +# Supports: wav, flac, ogg, mp3 formats # Prints: pipeline string or empty if format not supported gstreamer_build_audio_playback_pipeline() { - fmt="$1" - input_file="$2" + _fmt="$1" + _input_file="$2" - case "$fmt" in + case "$_fmt" in wav) - printf '%s\n' "filesrc location=${input_file} ! wavparse ! audioconvert ! pulsesink volume=10" + printf '%s\n' "filesrc location=${_input_file} ! wavparse ! audioconvert ! pulsesink volume=10" + return 0 ;; flac) - printf '%s\n' "filesrc location=${input_file} ! flacparse ! flacdec ! pulsesink volume=10" + printf '%s\n' "filesrc location=${_input_file} ! flacparse ! flacdec ! audioconvert ! pulsesink volume=10" + return 0 + ;; + ogg) + printf '%s\n' "filesrc location=${_input_file} ! oggdemux ! vorbisdec ! audioconvert ! pulsesink volume=10" + return 0 + ;; + mp3) + printf '%s\n' "filesrc location=${_input_file} ! mpegaudioparse ! mpg123audiodec ! audioconvert ! pulsesink volume=10" + return 0 ;; *) printf '%s\n' "" return 1 ;; esac - return 0 } # -------------------- GStreamer error log checker -------------------- From 9d7004f458eb133dd5ec30a61c1d21d0b149b861 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Tue, 10 Mar 2026 01:46:51 +0530 Subject: [PATCH 5/7] Comments on audio test addressed, back ported some of these items to existing video and display tests as well. Yaml files updated for all tests by removing || true in res line Signed-off-by: Nitin Nakka --- .../Audio_Record_Playback.yaml | 2 +- .../Audio/Audio_Record_Playback/run.sh | 97 +++++++++++++++---- .../Waylandsink_Playback.yaml | 2 +- .../Display/Waylandsink_Playback/run.sh | 2 - .../Video_Encode_Decode.yaml | 2 +- .../Video/Video_Encode_Decode/run.sh | 95 +++++++++++++++--- Runner/utils/lib_gstreamer.sh | 29 ++++++ 7 files changed, 191 insertions(+), 38 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 3bdc919ee..4aadc832f 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 @@ -23,4 +23,4 @@ run: - 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 - - $REPO_PATH/Runner/utils/send-to-lava.sh Audio_Record_Playback.res || true + - $REPO_PATH/Runner/utils/send-to-lava.sh Audio_Record_Playback.res 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 623a14816..7b600e858 100755 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -51,11 +51,6 @@ RECORDED_DIR="$OUTDIR/recorded" mkdir -p "$OUTDIR" "$DMESG_DIR" "$RECORDED_DIR" >/dev/null 2>&1 || true : >"$RES_FILE" : >"$GST_LOG" - -SCRIPT_DIR="$( - cd "$(dirname "$0")" || exit 1 - pwd -)" INIT_ENV="" SEARCH="$SCRIPT_DIR" @@ -67,8 +62,6 @@ while [ "$SEARCH" != "/" ]; do SEARCH=$(dirname "$SEARCH") done -RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" - if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true @@ -217,7 +210,76 @@ while [ $# -gt 0 ]; do ;; -h|--help) - echo "$TESTNAME SKIP" >"$RES_FILE" + cat < + Test mode (default: all) + - all: Run both record and playback tests + - record: Run only recording tests + - playback: Run only playback tests + + --formats + Comma-separated list of audio formats to test + (default: wav,flac) + Supported: wav, flac + + --duration Duration for recording/playback in seconds + (default: 10) + + --gst-debug GStreamer debug level (1-9) + (default: 2) + + --clip-url URL to download test audio files (OGG/MP3) + (default: GitHub release URL) + + --clip-path Local path to test audio files + (overrides --clip-url if files exist) + + -h, --help Display this help message + +ENVIRONMENT VARIABLES: + AUDIO_TEST_MODE Same as --mode + AUDIO_FORMATS Same as --formats + AUDIO_DURATION Same as --duration + AUDIO_GST_DEBUG Same as --gst-debug + AUDIO_CLIP_URL Same as --clip-url + AUDIO_CLIP_PATH Same as --clip-path + GST_DEBUG_LEVEL Alternative to AUDIO_GST_DEBUG + RUNTIMESEC Alternative to AUDIO_DURATION + +EXAMPLES: + # Run all tests with default settings + $0 + + # Run only recording tests for 5 seconds + $0 --mode record --duration 5 + + # Test only WAV format + $0 --formats wav + + # Use local test files + $0 --clip-path /path/to/audio/files + +TEST SEQUENCE: + ENCODE PHASE (4 tests): + 1. record_wav - audiotestsrc → wavenc → file + 2. record_flac - audiotestsrc → flacenc → file + 3. record_pulsesrc_wav - pulsesrc HW → wavenc → file + 4. record_pulsesrc_flac- pulsesrc HW → flacenc → file + + DECODE PHASE (6 tests): + 5. playback_wav - file → wavparse → pulsesink + 6. playback_flac - file → flacparse → flacdec → pulsesink + 7. playback_pulsesrc_wav - file → wavparse → pulsesink + 8. playback_pulsesrc_flac - file → flacparse → flacdec → pulsesink + 9. playback_sample_ogg - file → oggdemux → vorbisdec → pulsesink + 10. playback_sample_mp3 - file → mpegaudioparse → mpg123audiodec → pulsesink + +EOF exit 0 ;; @@ -423,8 +485,8 @@ run_playback_test() { return 1 fi - # Check for successful completion (rc=0 or timeout rc which means it played to end) - if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + # Check for successful completion + if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" pass_count=$((pass_count + 1)) return 0 @@ -576,8 +638,8 @@ run_playback_pulsesrc_test() { return 1 fi - # Check for successful completion (rc=0 or timeout rc which means it played to end) - if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + # Check for successful completion + if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" pass_count=$((pass_count + 1)) return 0 @@ -824,8 +886,7 @@ fi log_info "==========================================" log_info "TEST SUMMARY" log_info "==========================================" -actual_total=$((pass_count + fail_count + skip_count)) -log_info "Total testcases: $actual_total" +log_info "Total testcases: $total_tests" log_info "Passed: $pass_count" log_info "Failed: $fail_count" log_info "Skipped: $skip_count" @@ -834,16 +895,16 @@ log_info "Skipped: $skip_count" if [ "$fail_count" -eq 0 ] && [ "$pass_count" -gt 0 ]; then result="PASS" if [ "$skip_count" -gt 0 ]; then - reason="No failures (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" + reason="No failures (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $total_tests)" else - reason="All tests passed ($pass_count/$actual_total)" + reason="All tests passed ($pass_count/$total_tests)" fi elif [ "$fail_count" -gt 0 ]; then result="FAIL" - reason="Some tests failed (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" + reason="Some tests failed (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $total_tests)" else result="SKIP" - reason="No tests passed (skipped: $skip_count, total: $actual_total)" + reason="No tests passed (skipped: $skip_count, total: $total_tests)" fi case "$result" in diff --git a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/Waylandsink_Playback.yaml b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/Waylandsink_Playback.yaml index fcadd9b8a..e25a435be 100644 --- a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/Waylandsink_Playback.yaml +++ b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/Waylandsink_Playback.yaml @@ -25,4 +25,4 @@ run: - cd Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/ - export VIDEO_DURATION VIDEO_PATTERN VIDEO_WIDTH VIDEO_HEIGHT VIDEO_FRAMERATE VIDEO_GST_DEBUG - ./run.sh --resolution "${VIDEO_WIDTH}x${VIDEO_HEIGHT}" --pattern "${VIDEO_PATTERN}" --duration "${VIDEO_DURATION}" --framerate "${VIDEO_FRAMERATE}" --gst-debug "${VIDEO_GST_DEBUG}" || true - - $REPO_PATH/Runner/utils/send-to-lava.sh Waylandsink_Playback.res || true + - $REPO_PATH/Runner/utils/send-to-lava.sh Waylandsink_Playback.res diff --git a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh index 8c18ee1ba..6fdbb1327 100755 --- a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh @@ -38,8 +38,6 @@ while [ "$SEARCH" != "/" ]; do SEARCH=$(dirname "$SEARCH") done -RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" - if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true diff --git a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/Video_Encode_Decode.yaml b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/Video_Encode_Decode.yaml index ac8260ac6..2c33cb45a 100644 --- a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/Video_Encode_Decode.yaml +++ b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/Video_Encode_Decode.yaml @@ -27,4 +27,4 @@ run: - export VIDEO_TEST_MODE VIDEO_CODECS VIDEO_RESOLUTIONS VIDEO_DURATION VIDEO_FRAMERATE - export VIDEO_STACK VIDEO_GST_DEBUG VIDEO_CLIP_URL VIDEO_CLIP_PATH - ./run.sh --mode "${VIDEO_TEST_MODE}" --codecs "${VIDEO_CODECS}" --resolutions "${VIDEO_RESOLUTIONS}" --duration "${VIDEO_DURATION}" --framerate "${VIDEO_FRAMERATE}" --stack "${VIDEO_STACK}" --gst-debug "${VIDEO_GST_DEBUG}" --clip-url "${VIDEO_CLIP_URL}" --clip-path "${VIDEO_CLIP_PATH}" || true - - $REPO_PATH/Runner/utils/send-to-lava.sh Video_Encode_Decode.res || true + - $REPO_PATH/Runner/utils/send-to-lava.sh Video_Encode_Decode.res diff --git a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh index 245c20a35..47de483b9 100755 --- a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh @@ -23,11 +23,6 @@ ENCODED_DIR="$OUTDIR/encoded" mkdir -p "$OUTDIR" "$DMESG_DIR" "$ENCODED_DIR" >/dev/null 2>&1 || true : >"$RES_FILE" : >"$GST_LOG" - -SCRIPT_DIR="$( - cd "$(dirname "$0")" || exit 1 - pwd -)" INIT_ENV="" SEARCH="$SCRIPT_DIR" @@ -39,8 +34,6 @@ while [ "$SEARCH" != "/" ]; do SEARCH=$(dirname "$SEARCH") done -RES_FILE="$SCRIPT_DIR/${TESTNAME}.res" - if [ -z "${INIT_ENV:-}" ]; then echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true @@ -245,7 +238,81 @@ while [ $# -gt 0 ]; do shift 2 ;; -h|--help) - echo "$TESTNAME SKIP" >"$RES_FILE" + cat < + Test mode (default: all) + - all: Run both encode and decode tests + - encode: Run only encoding tests + - decode: Run only decoding tests + + --codecs + Comma-separated list of codecs to test + (default: h264,h265,vp9) + Supported: h264, h265, vp9 + + --resolutions + Comma-separated list of resolutions to test + (default: 480p) + Supported: 480p, 720p, 1080p, 4k + + --duration Duration for encoding/decoding in seconds + (default: 30) + + --framerate Framerate for video encoding + (default: 30) + + --stack + Video stack to use + (default: auto) + + --gst-debug GStreamer debug level (1-9) + (default: 2) + + --clip-url URL to download test video files (VP9) + (default: GitHub release URL) + + --clip-path Local path to test video files + (overrides --clip-url if files exist) + + -h, --help Display this help message + +ENVIRONMENT VARIABLES: + VIDEO_TEST_MODE Same as --mode + VIDEO_CODECS Same as --codecs + VIDEO_RESOLUTIONS Same as --resolutions + VIDEO_DURATION Same as --duration + VIDEO_FRAMERATE Same as --framerate + VIDEO_STACK Same as --stack + VIDEO_GST_DEBUG Same as --gst-debug + VIDEO_CLIP_URL Same as --clip-url + VIDEO_CLIP_PATH Same as --clip-path + GST_DEBUG_LEVEL Alternative to VIDEO_GST_DEBUG + RUNTIMESEC Alternative to VIDEO_DURATION + +EXAMPLES: + # Run all tests with default settings + $0 + + # Run only encoding tests for H.264 at 720p + $0 --mode encode --codecs h264 --resolutions 720p + + # Test multiple codecs and resolutions + $0 --codecs h264,h265 --resolutions 480p,720p + + # Use upstream video stack + $0 --stack upstream + +SUPPORTED CODECS: + - h264: H.264/AVC encoding and decoding (v4l2h264enc, v4l2h264dec) + - h265: H.265/HEVC encoding and decoding (v4l2h265enc, v4l2h265dec) + - vp9: VP9 decoding only (v4l2vp9dec) - uses pre-recorded WebM clip + +EOF exit 0 ;; *) @@ -630,9 +697,7 @@ fi log_info "==========================================" log_info "TEST SUMMARY" log_info "==========================================" -# Calculate actual total for display (sum of pass/fail/skip) -actual_total=$((pass_count + fail_count + skip_count)) -log_info "Total testcases: $actual_total" +log_info "Total testcases: $total_tests" log_info "Passed: $pass_count" log_info "Failed: $fail_count" log_info "Skipped: $skip_count" @@ -641,16 +706,16 @@ log_info "Skipped: $skip_count" if [ "$fail_count" -eq 0 ] && [ "$pass_count" -gt 0 ]; then result="PASS" if [ "$skip_count" -gt 0 ]; then - reason="No failures (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" + reason="No failures (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $total_tests)" else - reason="All tests passed ($pass_count/$actual_total)" + reason="All tests passed ($pass_count/$total_tests)" fi elif [ "$fail_count" -gt 0 ]; then result="FAIL" - reason="Some tests failed (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $actual_total)" + reason="Some tests failed (passed: $pass_count, failed: $fail_count, skipped: $skip_count, total: $total_tests)" else result="SKIP" - reason="No tests passed (skipped: $skip_count, total: $actual_total)" + reason="No tests passed (skipped: $skip_count, total: $total_tests)" fi case "$result" in diff --git a/Runner/utils/lib_gstreamer.sh b/Runner/utils/lib_gstreamer.sh index 9d5b622a9..c5c5514a8 100755 --- a/Runner/utils/lib_gstreamer.sh +++ b/Runner/utils/lib_gstreamer.sh @@ -525,6 +525,35 @@ gstreamer_build_audio_record_pipeline() { return 0 } + +# -------------------- Playback pipeline builder (backend-aware) -------------------- +# gstreamer_build_playback_pipeline +gstreamer_build_playback_pipeline() { + backend="$1" + format="$2" + file="$3" + capsStr="$4" + alsadev="$5" + + [ -n "$alsadev" ] || alsadev="default" + + dec="$(gstreamer_pick_decode_chain "$format")" + sinkElem="$(gstreamer_pick_sink_element "$backend" "$alsadev")" + if [ -z "$sinkElem" ]; then + printf '%s\n' "" + return 0 + fi + + if [ -n "$capsStr" ]; then + printf '%s\n' "filesrc location=${file} ! ${dec} ! audioconvert ! audioresample ! ${capsStr} ! ${sinkElem}" + return 0 + fi + + printf '%s\n' "filesrc location=${file} ! ${dec} ! audioconvert ! audioresample ! ${sinkElem}" + return 0 +} + + # gstreamer_build_audio_playback_pipeline # Builds audio playback pipeline using pulsesink # Supports: wav, flac, ogg, mp3 formats From 903ad59f562450a9b1414c6430b8f04a247ac059 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Tue, 10 Mar 2026 15:55:08 +0530 Subject: [PATCH 6/7] Added shellcheck disable=SC2317 for the cleanup function in all gst mm runner scripts, added help section and updated readme files for audio Signed-off-by: Nitin Nakka --- .../Audio/Audio_Record_Playback/README.md | 18 +++++++++++++----- .../Audio/Audio_Record_Playback/run.sh | 7 +++++-- .../Display/Waylandsink_Playback/run.sh | 1 + .../GSTreamer/Video/Video_Encode_Decode/run.sh | 1 + 4 files changed, 20 insertions(+), 7 deletions(-) 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 60ce90f61..5aa70a503 100644 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md @@ -58,7 +58,7 @@ At a high level, the test: ## Test Cases -By default, the test runs **8 test cases** with 10 second duration: +By default, the test runs **10 test cases** with 10 second duration: ### ENCODE PHASE (4 tests) @@ -70,7 +70,7 @@ By default, the test runs **8 test cases** with 10 second duration: 3. **record_pulsesrc_wav** - Record WAV format using pulsesrc → audioconvert → wavenc 4. **record_pulsesrc_flac** - Record FLAC format using pulsesrc → audioconvert → flacenc -### DECODE PHASE (4 tests) +### DECODE PHASE (6 tests) #### Playback Tests - audiotestsrc recordings 5. **playback_wav** - Playback WAV file using filesrc → wavparse → audioconvert → pulsesink @@ -80,7 +80,13 @@ By default, the test runs **8 test cases** with 10 second duration: 7. **playback_pulsesrc_wav** - Playback WAV file using filesrc → wavparse → audioconvert → pulsesink 8. **playback_pulsesrc_flac** - Playback FLAC file using filesrc → flacparse → flacdec → pulsesink -**Total: 8 test cases** (4 encode + 4 decode) +#### Playback Tests - External Test Files (OGG/MP3) +9. **playback_sample_ogg** - Playback OGG file using filesrc → oggdemux → vorbisdec → pulsesink +10. **playback_sample_mp3** - Playback MP3 file using filesrc → mpegaudioparse → mpg123audiodec → pulsesink + +**Total: 10 test cases** (4 encode + 6 decode) + +**Note:** OGG/MP3 playback tests require external test files (downloaded from URL or provided via `--clip-path`). If test files are not available, these tests will be skipped. --- @@ -88,12 +94,14 @@ By default, the test runs **8 test cases** with 10 second duration: ### PASS - **Recording**: Output file is created and has size > 1000 bytes -- **Playback**: Pipeline completes successfully (exit code 0, 124, or 143) +- **Playback**: Pipeline completes successfully with exit code 0 (clean completion) + - **Note**: Timeout (exit code 124) or termination (exit code 143) are treated as **FAIL** for controlled-duration recordings + - This ensures playback completed successfully rather than being interrupted - **Overall**: At least one test passes and no tests fail ### FAIL - **Recording**: No output file created or file size too small -- **Playback**: Pipeline fails or GStreamer errors detected +- **Playback**: Pipeline exits with non-zero code (including timeout 124 or termination 143) or GStreamer errors detected - **Overall**: One or more tests fail ### SKIP 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 7b600e858..7c12eedf3 100755 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/run.sh @@ -127,6 +127,7 @@ for param in AUDIO_DURATION AUDIO_GST_DEBUG GST_DEBUG_LEVEL; do fi done +# shellcheck disable=SC2317 cleanup() { # Best-effort: try to kill only children first; fall back to name-based kill if ! pkill -P "$$" -x gst-launch-1.0 >/dev/null 2>&1; then @@ -718,7 +719,7 @@ run_playback_ogg_mp3_test() { fi # Check for successful completion - if [ "$gstRc" -eq 0 ] || [ "$gstRc" -eq 124 ] || [ "$gstRc" -eq 143 ]; then + if [ "$gstRc" -eq 0 ]; then log_pass "$testname: PASS" pass_count=$((pass_count + 1)) return 0 @@ -769,9 +770,10 @@ provision_test_files() { log_warn "Test file download failed (offline or URL issue)" fi fi + fi - # Check what we have + # Check what we have AFTER all provisioning attempts have_ogg=0 have_mp3=0 @@ -791,6 +793,7 @@ provision_test_files() { fi fi + # Only warn if BOTH files are missing after all attempts if [ "$have_ogg" -eq 0 ] && [ "$have_mp3" -eq 0 ]; then log_warn "No Test files (OGG/MP3) available for playback tests" fi diff --git a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh index 6fdbb1327..435b2091a 100755 --- a/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Display/Waylandsink_Playback/run.sh @@ -92,6 +92,7 @@ height="${VIDEO_HEIGHT:-1080}" framerate="${VIDEO_FRAMERATE:-30}" gstDebugLevel="${VIDEO_GST_DEBUG:-${GST_DEBUG_LEVEL:-2}}" +# shellcheck disable=SC2317 cleanup() { # Best-effort: try to kill only children first; fall back to name-based kill if ! pkill -P "$$" -x gst-launch-1.0 >/dev/null 2>&1; then diff --git a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh index 47de483b9..e0bb4bc83 100755 --- a/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh +++ b/Runner/suites/Multimedia/GSTreamer/Video/Video_Encode_Decode/run.sh @@ -103,6 +103,7 @@ for param in VIDEO_DURATION RUNTIMESEC VIDEO_FRAMERATE VIDEO_GST_DEBUG GST_DEBUG fi done +# shellcheck disable=SC2317 cleanup() { # Best-effort: try to kill only children first; fall back to name-based kill if ! pkill -P "$$" -x gst-launch-1.0 >/dev/null 2>&1; then From 66487b241b5f2dfc8bc4bd51ed06e418fcceaa36 Mon Sep 17 00:00:00 2001 From: Nitin Nakka Date: Sun, 15 Mar 2026 12:18:07 +0530 Subject: [PATCH 7/7] Added 10 tests related changes in the readme and the yaml files Signed-off-by: Nitin Nakka --- .../Audio_Record_Playback.yaml | 4 ++-- .../Audio/Audio_Record_Playback/README.md | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 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 4aadc832f..cf1fbd372 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 @@ -3,8 +3,8 @@ metadata: format: "Lava-Test Test Definition 1.0" description: > Audio record/playback validation using GStreamer (gst-launch-1.0). - Tests 8 scenarios: 4 encode (2 audiotestsrc + 2 pulsesrc) + 4 decode (playback). - Supports WAV and FLAC formats with both synthetic audio (audiotestsrc) and hardware capture (pulsesrc). + 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. os: - linux 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 5aa70a503..c1247e42c 100644 --- a/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md +++ b/Runner/suites/Multimedia/GSTreamer/Audio/Audio_Record_Playback/README.md @@ -49,9 +49,10 @@ At a high level, the test: - Duration control: - audiotestsrc: Buffer count calculated dynamically: `(44100 * duration) / 1024` - pulsesrc: Uses timeout command to stop recording after specified duration -5. **Playback phase (DECODE - 4 tests)**: +5. **Playback phase (DECODE - 6 tests)**: - Reads the previously recorded files (both audiotestsrc and pulsesrc recordings) - Decodes and plays back using pulsesink + - Plays back external test files (OGG/MP3 formats) 6. Collects test results and emits PASS/FAIL/SKIP --- @@ -219,7 +220,7 @@ Help: ## Examples -### 1) Run all tests (default - 8 tests: 4 encode + 4 decode for WAV and FLAC with 10 second duration) +### 1) Run all tests (default - 10 tests: 4 encode + 6 decode for WAV, FLAC, OGG, and MP3 with 10 second duration) ```bash ./run.sh @@ -231,19 +232,19 @@ Help: ./run.sh --mode record ``` -### 3) Run only playback tests (4 decode tests - requires recorded files from previous run) +### 3) Run only playback tests (6 decode tests - requires recorded files from previous run, plus OGG/MP3 test files) ```bash ./run.sh --mode playback ``` -### 4) Test only WAV format (4 tests: 2 encode + 2 decode) +### 4) Test only WAV format (6 tests total: 2 encode + 2 decode + 2 OGG/MP3 playback) ```bash ./run.sh --formats wav ``` -### 5) Test only FLAC format (4 tests: 2 encode + 2 decode) +### 5) Test only FLAC format (6 tests total: 2 encode + 2 decode + 2 OGG/MP3 playback) ```bash ./run.sh --formats flac @@ -255,7 +256,7 @@ Help: ./run.sh --duration 30 ``` -### 7) Quick test - WAV only with 3 second duration (4 tests) +### 7) Quick test - WAV only with 3 second duration (6 tests total) ```bash ./run.sh --formats wav --duration 3 @@ -546,11 +547,12 @@ The test supports these environment variables (can be set in LAVA job definition ### Test Counting -- **Total tests**: 8 (when running with default wav,flac formats in all mode) +- **Total tests**: 10 (when running with default wav,flac formats in all mode) - 4 encode tests (2 audiotestsrc + 2 pulsesrc) - - 4 decode tests (2 audiotestsrc playback + 2 pulsesrc playback) + - 6 decode tests (2 audiotestsrc playback + 2 pulsesrc playback + 2 OGG/MP3 playback) - **Pass/Fail/Skip are mutually exclusive**: Each test increments exactly one counter - **Plugin unavailability**: pulsesrc tests will skip if pulsesrc plugin is not available, but audiotestsrc tests will still run +- **Test file availability**: OGG/MP3 playback tests will skip if test files are not available ---