VirtualBox

Ignore:
Timestamp:
May 31, 2021 12:43:16 PM (4 years ago)
Author:
vboxsync
Message:

Audio/ValKit: First guest / host mode code for VKAT. bugref:10008

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89387 r89399  
    110110*   Structures and Typedefs                                                                                                      *
    111111*********************************************************************************************************************************/
     112/**
     113 * Enumeration specifying the current audio test mode.
     114 */
     115typedef enum AUDIOTESTMODE
     116{
     117    /** Unknown mode. */
     118    AUDIOTESTMODE_UNKNOWN = 0,
     119    /** VKAT is running on the guest side. */
     120    AUDIOTESTMODE_GUEST,
     121    /** VKAT is running on the host side. */
     122    AUDIOTESTMODE_HOST
     123} AUDIOTESTMODE;
     124
    112125struct AUDIOTESTENV;
    113126/** Pointer a audio test environment. */
     
    202215typedef struct AUDIOTESTENV
    203216{
     217    /** Audio testing mode. */
     218    AUDIOTESTMODE           enmMode;
    204219    /** Output path for storing the test environment's final test files. */
    205220    char                    szPathOut[RTPATH_MAX];
     
    214229    /** The audio test set to use. */
    215230    AUDIOTESTSET            Set;
     231    union
     232    {
     233        struct
     234        {
     235            /** ATS instance to use. */
     236            ATSSERVER       Srv;
     237        } Guest;
     238        struct
     239        {
     240            ATSCLIENT       Client;
     241        } Host;
     242    } u;
    216243} AUDIOTESTENV;
    217244
     
    233260} AUDIOTESTDESC;
    234261
     262/**
     263 * Structure for keeping a user context for the test service callbacks.
     264 */
     265typedef struct ATSCALLBACKCTX
     266{
     267    PAUDIOTESTENV pTstEnv;
     268} ATSCALLBACKCTX;
     269typedef ATSCALLBACKCTX *PATSCALLBACKCTX;
     270
    235271
    236272/*********************************************************************************************************************************
     
    267303    VKAT_TEST_OPT_COUNT = 900,
    268304    VKAT_TEST_OPT_DEV,
     305    VKAT_TEST_OPT_ATS_ADDR,
     306    VKAT_TEST_OPT_ATS_PORT,
     307    VKAT_TEST_OPT_MODE,
    269308    VKAT_TEST_OPT_OUTDIR,
    270309    VKAT_TEST_OPT_PAUSE,
     
    314353    { "--exclude",          'e',                          RTGETOPT_REQ_UINT32  },
    315354    { "--exclude-all",      'a',                          RTGETOPT_REQ_NOTHING },
     355    { "--mode",             VKAT_TEST_OPT_MODE,           RTGETOPT_REQ_STRING  },
     356    { "--ats-address",      VKAT_TEST_OPT_ATS_ADDR,       RTGETOPT_REQ_STRING  },
     357    { "--ats-port",         VKAT_TEST_OPT_ATS_PORT,       RTGETOPT_REQ_UINT32  },
    316358    { "--include",          'i',                          RTGETOPT_REQ_UINT32  },
    317359    { "--outdir",           VKAT_TEST_OPT_OUTDIR,         RTGETOPT_REQ_STRING  },
     
    377419AssertCompile(sizeof(g_aBackends) > 0 /* port me */);
    378420
     421static volatile bool g_fTerminated = false;
    379422/** The test handle. */
    380 static RTTEST       g_hTest;
     423static RTTEST        g_hTest;
    381424/** The release logger. */
    382425static PRTLOGGER    g_pRelLogger = NULL;
    383426/** The current verbosity level. */
    384 static unsigned     g_uVerbosity = 0;
     427static unsigned      g_uVerbosity = 0;
    385428/** DrvAudio: Enable debug (or not). */
    386 static bool         g_fDrvAudioDebug = 0;
     429static bool          g_fDrvAudioDebug = 0;
    387430/** DrvAudio: The debug output path. */
    388 static const char  *g_pszDrvAudioDebug = NULL;
     431static const char   *g_pszDrvAudioDebug = NULL;
    389432
    390433
     
    13781421
    13791422/*********************************************************************************************************************************
     1423*   ATS Callback Implementations                                                                                                 *
     1424*********************************************************************************************************************************/
     1425
     1426/**
     1427 * Note: Called within server (client serving) thread.
     1428 */
     1429static DECLCALLBACK(int) audioTestSvcTonePlayCallback(void const *pvUser, PPDMAUDIOSTREAMCFG pStreamCfg, PAUDIOTESTTONEPARMS pToneParms)
     1430{
     1431    PATSCALLBACKCTX pCtx    = (PATSCALLBACKCTX)pvUser;
     1432    PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
     1433
     1434    AUDIOTESTTONE TstTone;
     1435    AudioTestToneInitRandom(&TstTone, &pStreamCfg->Props);
     1436
     1437    int rc;
     1438
     1439    const PPDMAUDIOSTREAM pStream = pTstEnv->aStreams[0].pStream; /** @todo Make this dynamic. */
     1440
     1441    if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream))
     1442    {
     1443        uint32_t cbBuf;
     1444        uint8_t  abBuf[_4K];
     1445
     1446        const uint64_t tsStartMs     = RTTimeMilliTS();
     1447        const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Chose a random scheduling (in ms). */
     1448        const uint32_t cbPerMs       = PDMAudioPropsMilliToBytes(&pStream->Props, cSchedulingMs);
     1449
     1450        do
     1451        {
     1452            rc = AudioTestToneGenerate(&TstTone, abBuf, RT_MIN(cbPerMs, sizeof(abBuf)), &cbBuf);
     1453            if (RT_SUCCESS(rc))
     1454            {
     1455                uint32_t cbWritten;
     1456                rc = audioTestDriverStackStreamPlay(&pTstEnv->DrvStack, pStream, abBuf, cbBuf, &cbWritten);
     1457            }
     1458
     1459            if (RTTimeMilliTS() - tsStartMs >= pToneParms->msDuration)
     1460                break;
     1461
     1462            if (RT_FAILURE(rc))
     1463                break;
     1464
     1465            RTThreadSleep(cSchedulingMs);
     1466
     1467        } while (RT_SUCCESS(rc));
     1468    }
     1469    else
     1470        rc = VERR_AUDIO_STREAM_NOT_READY;
     1471
     1472    return rc;
     1473}
     1474
     1475
     1476/*********************************************************************************************************************************
    13801477*   Implementation of audio test environment handling                                                                            *
    13811478*********************************************************************************************************************************/
     
    13881485 * @param   fWithDrvAudio       Whether to include DrvAudio in the stack or not.
    13891486 * @param   pszTag              Tag name to use. If NULL, a generated UUID will be used.
    1390  */
    1391 static int audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio, const char *pszTag)
     1487 * @param   pszTcpAddr          TCP/IP address to connect to.
     1488 * @param   uTcpPort            TCP/IP port to connect to.
     1489 */
     1490static int audioTestEnvInit(PAUDIOTESTENV pTstEnv,
     1491                            PCPDMDRVREG pDrvReg, bool fWithDrvAudio, const char *pszTag,
     1492                            const char *pszTcpAddr, uint32_t uTcpPort)
    13921493{
    13931494    PDMAudioHostEnumInit(&pTstEnv->DevEnum);
     
    13961497    if (RT_FAILURE(rc))
    13971498        return rc;
     1499
     1500    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test mode is '%s'\n", pTstEnv->enmMode == AUDIOTESTMODE_HOST ? "host" : "guest");
     1501    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using tag '%s'\n", pszTag);
     1502    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Output directory is '%s'\n", pTstEnv->szPathOut);
     1503    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Temp directory is '%s'\n", pTstEnv->szPathTemp);
    13981504
    13991505    char szPathTemp[RTPATH_MAX];
     
    14131519        rc = AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, pszTag);
    14141520
    1415     if (RT_SUCCESS(rc))
    1416     {
    1417         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using tag '%s'\n", pszTag);
    1418         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Output directory is '%s'\n", pTstEnv->szPathOut);
    1419         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Temp directory is '%s'\n", pTstEnv->szPathTemp);
    1420     }
    1421 
    14221521    if (RT_FAILURE(rc))
    1423         audioTestDriverStackDelete(&pTstEnv->DrvStack);
     1522        return rc;
     1523
     1524    /** @todo Implement NAT mode like we do for TxS later? */
     1525    if (pTstEnv->enmMode == AUDIOTESTMODE_GUEST)
     1526    {
     1527        ATSCALLBACKCTX Ctx;
     1528        Ctx.pTstEnv = pTstEnv;
     1529
     1530        ATSCALLBACKS Callbacks;
     1531        Callbacks.pfnTonePlay = audioTestSvcTonePlayCallback;
     1532        Callbacks.pvUser      = &Ctx;
     1533
     1534        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Starting ATS ...\n");
     1535        rc = AudioTestSvcInit(&pTstEnv->u.Guest.Srv, &Callbacks);
     1536        if (RT_SUCCESS(rc))
     1537            rc = AudioTestSvcStart(&pTstEnv->u.Guest.Srv);
     1538
     1539        if (RT_FAILURE(rc))
     1540        {
     1541            RTTestFailed(g_hTest, "Initializing ATS failed with %Rrc\n", rc);
     1542            return rc;
     1543        }
     1544
     1545        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "ATS running\n");
     1546
     1547        while (!g_fTerminated) /** @todo Implement signal handling. */
     1548        {
     1549            RTThreadSleep(100);
     1550        }
     1551
     1552        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Shutting down ATS ...\n");
     1553
     1554        int rc2 = AudioTestSvcShutdown(&pTstEnv->u.Guest.Srv);
     1555        if (RT_SUCCESS(rc))
     1556            rc = rc2;
     1557    }
     1558    else
     1559    {
     1560        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Connecting to ATS at %s:%RU32 ...\n", pszTcpAddr, uTcpPort);
     1561        rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.Client, pszTcpAddr, uTcpPort);
     1562        if (RT_FAILURE(rc))
     1563        {
     1564            RTTestFailed(g_hTest, "Connecting to ATS failed with %Rrc\n", rc);
     1565            return rc;
     1566        }
     1567    }
     1568
     1569    audioTestDriverStackDelete(&pTstEnv->DrvStack);
    14241570
    14251571    return rc;
     
    20772223    uint32_t    uPcmHz        = 0;
    20782224    bool        fPcmSigned    = true;
     2225    const char *pszTcpAddr    = NULL;
     2226    uint16_t    uTcpPort      = 0;
    20792227
    20802228    int           rc;
     
    21122260                break;
    21132261
     2262            case VKAT_TEST_OPT_ATS_ADDR:
     2263                if (TstEnv.enmMode == AUDIOTESTMODE_UNKNOWN)
     2264                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must specify a test mode first!");
     2265                pszTcpAddr = ValueUnion.psz;
     2266                break;
     2267
     2268            case VKAT_TEST_OPT_ATS_PORT:
     2269                if (TstEnv.enmMode == AUDIOTESTMODE_UNKNOWN)
     2270                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must specify a test mode first!");
     2271                uTcpPort = ValueUnion.u32;
     2272                break;
     2273
     2274            case VKAT_TEST_OPT_MODE:
     2275                if (TstEnv.enmMode != AUDIOTESTMODE_UNKNOWN)
     2276                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Test mode (guest / host) already specified");
     2277                TstEnv.enmMode = RTStrICmp(ValueUnion.psz, "guest") == 0 ? AUDIOTESTMODE_GUEST : AUDIOTESTMODE_HOST;
     2278                break;
     2279
    21142280            case 'i':
    21152281                if (ValueUnion.u32 >= RT_ELEMENTS(g_aTests))
     
    21812347                      uPcmHz ? uPcmHz : 44100);
    21822348
     2349    if (TstEnv.enmMode == AUDIOTESTMODE_UNKNOWN)
     2350        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No test mode specified!\n");
     2351
     2352    if (TstEnv.enmMode == AUDIOTESTMODE_HOST)
     2353    {
     2354        /* Use the default port is none is specified. */
     2355        if (!uTcpPort)
     2356            uTcpPort = ATS_DEFAULT_PORT;
     2357
     2358        if (!pszTcpAddr)
     2359            return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--ats-address missing\n");
     2360    }
     2361
    21832362    /* For now all tests have the same test environment. */
    2184     rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio, pszTag);
     2363    rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio, pszTag, pszTcpAddr, uTcpPort);
    21852364    if (RT_SUCCESS(rc))
    21862365    {
     
    26542833
    26552834/**
    2656  * Structure for keeping a user context for the test service callbacks.
    2657  */
    2658 typedef struct ATSCALLBACKCTX
    2659 {
    2660     /** Driver stack to use. */
    2661     PAUDIOTESTDRVSTACK pDrvStack;
    2662     /** Audio stream to use. */
    2663     PPDMAUDIOSTREAM    pStream;
    2664 } ATSCALLBACKCTX;
    2665 typedef ATSCALLBACKCTX *PATSCALLBACKCTX;
    2666 
    2667 /**
    2668  * Note: Called within server (client serving) thread.
    2669  */
    2670 static DECLCALLBACK(int) audioTestSvcTonePlayCallback(void const *pvUser, PPDMAUDIOSTREAMCFG pStreamCfg, PAUDIOTESTTONEPARMS pToneParms)
    2671 {
    2672     PATSCALLBACKCTX pCtx = (PATSCALLBACKCTX)pvUser;
    2673 
    2674     AUDIOTESTTONE TstTone;
    2675     AudioTestToneInitRandom(&TstTone, &pStreamCfg->Props);
    2676 
    2677     int rc;
    2678 
    2679     if (audioTestDriverStackStreamIsOkay(pCtx->pDrvStack, pCtx->pStream))
    2680     {
    2681         uint32_t cbBuf;
    2682         uint8_t  abBuf[_4K];
    2683 
    2684         const uint64_t tsStartMs     = RTTimeMilliTS();
    2685         const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Chose a random scheduling (in ms). */
    2686         const uint32_t cbPerMs       = PDMAudioPropsMilliToBytes(&pCtx->pStream->Props, cSchedulingMs);
    2687 
    2688         do
    2689         {
    2690             rc = AudioTestToneGenerate(&TstTone, abBuf, RT_MIN(cbPerMs, sizeof(abBuf)), &cbBuf);
    2691             if (RT_SUCCESS(rc))
    2692             {
    2693                 uint32_t cbWritten;
    2694                 rc = audioTestDriverStackStreamPlay(pCtx->pDrvStack, pCtx->pStream, abBuf, cbBuf, &cbWritten);
    2695             }
    2696 
    2697             if (RTTimeMilliTS() - tsStartMs >= pToneParms->msDuration)
    2698                 break;
    2699 
    2700             if (RT_FAILURE(rc))
    2701                 break;
    2702 
    2703             RTThreadSleep(cSchedulingMs);
    2704 
    2705         } while (RT_SUCCESS(rc));
    2706     }
    2707     else
    2708         rc = VERR_AUDIO_STREAM_NOT_READY;
    2709 
    2710     return rc;
    2711 }
    2712 
    2713 /**
    27142835 * Tests the Audio Test Service (ATS).
    27152836 *
     
    27212842static int audioTestDoSelftestAts(PCPDMDRVREG pDrvReg, const char *pszAdr)
    27222843{
    2723     AUDIOTESTDRVSTACK DrvStack;
    2724     int rc = audioTestDriverStackInit(&DrvStack, pDrvReg, true /* fWithDrvAudio */);
     2844    AUDIOTESTENV TstEnv;
     2845    int rc = audioTestDriverStackInit(&TstEnv.DrvStack, pDrvReg, true /* fWithDrvAudio */);
    27252846    if (RT_SUCCESS(rc))
    27262847    {
     
    27312852        PDMAUDIOSTREAMCFG CfgAcq;
    27322853        PPDMAUDIOSTREAM   pStream = NULL;
    2733         rc = audioTestDriverStackStreamCreateOutput(&DrvStack, &Props,
     2854        rc = audioTestDriverStackStreamCreateOutput(&TstEnv.DrvStack, &Props,
    27342855                                                    UINT32_MAX /* cMsBufferSize */,
    27352856                                                    UINT32_MAX /* cMsPreBuffer */,
     
    27372858        if (RT_SUCCESS(rc))
    27382859        {
    2739             rc = audioTestDriverStackStreamEnable(&DrvStack, pStream);
     2860            rc = audioTestDriverStackStreamEnable(&TstEnv.DrvStack, pStream);
    27402861            if (RT_SUCCESS(rc))
    27412862            {
    27422863                ATSCALLBACKCTX Ctx;
    2743                 Ctx.pDrvStack = &DrvStack;
    2744                 Ctx.pStream   = pStream;
     2864                Ctx.pTstEnv = &TstEnv;
    27452865
    27462866                ATSCALLBACKS Callbacks;
     
    27682888                {
    27692889                    ATSCLIENT Conn;
    2770                     rc = AudioTestSvcClientConnect(&Conn, NULL);
     2890                    rc = AudioTestSvcClientConnect(&Conn, NULL, 0);
    27712891                    if (RT_SUCCESS(rc))
    27722892                    {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette