VirtualBox

Changeset 73370 in vbox for trunk/include/VBox


Ignore:
Timestamp:
Jul 26, 2018 1:52:12 PM (6 years ago)
Author:
vboxsync
Message:

Audio: Implemented backend-independent (pre-)buffering support. Work in progress.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r73242 r73370  
    44
    55/*
    6  * Copyright (C) 2006-2017 Oracle Corporation
     6 * Copyright (C) 2006-2018 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    8282 * A PDMAUDIOFRAME is the internal representation of a single audio frame, which consists of a single left
    8383 * and right audio sample in time. Only mono (1) and stereo (2) channel(s) currently are supported.
     84 *
     85 *
     86 * == Timing
     87 *
     88 * Handling audio data in a virtual environment is hard, as the human perception is very sensitive
     89 * to the slightest cracks and stutters in the audible data. This can happen if the VM's timing is
     90 * lagging behind or not within the expected time frame.
     91 *
     92 * The two main components which unfortunately contradict each other is a) the audio device emulation
     93 * and b) the audio backend(s) on the host. Those need to be served in a timely manner to function correctly.
     94 * To make e.g. the device emulation rely on the pace the host backend(s) set - or vice versa - will not work,
     95 * as the guest's audio system / drivers then will not be able to compensate this accordingly.
     96 *
     97 * So each component, the device emulation, the audio connector(s) and the backend(s) must do its thing
     98 * *when* it needs to do it, independently of the others. For that we use various (small) ring buffers to
     99 * (hopefully) serve all components with the amount of data *when* they need it.
     100 *
     101 * Additionally, the device emulation can run with a different audio frame size, while the backends(s) may
     102 * require a different frame size (16 bit stereo -> 8 bit mono, for example).
     103 *
     104 * The device emulation can give the audio connector(s) a scheduling hint (optional), e.g. in which interval
     105 * it expects any data processing.
     106 *
     107 * A data transfer for playing audio data from the guest on the host looks like this:
     108 * (RB = Ring Buffer, MB = Mixing Buffer)
     109 *
     110 * (A) Device DMA -> (B) Device RB -> (C) Audio Connector Guest MB -> (D) Audio Connector Host MB -> \
     111 * (E) Backend RB (optional, up to the backend) > (F) Backend audio framework
     112 *
     113 * For capturing audio data the above chain is similar, just in a different direction, of course.
     114 *
     115 * The audio connector hereby plays a key role when it comes to (pre-) buffering data to minimize any audio stutters
     116 * and/or cracks. The following values, which also can be tweaked via CFGM / extra-data are available:
     117 *
     118 * - The pre-buffering time (in ms): Audio data which needs to be buffered before any playback (or capturing) can happen.
     119 * - The actual buffer size (in ms): How big the mixing buffer (for C and D) will be.
     120 * - The period size (in ms): How big a chunk of audio (often called period or fragment) for F must be to get handled correctly.
     121 *
     122 * The above values can be set on a per-driver level, whereas input and output streams for a driver also can be handled
     123 * set independently. The verbose audio (release) log will tell about the (final) state of each audio stream.
    84124 *
    85125 *
     
    535575     *      The audio data will get handled as PDMAUDIOFRAME frames without any modification done. */
    536576    PDMAUDIOSTREAMLAYOUT     enmLayout;
    537     /** Hint about the optimal frame buffer size (in audio frames).
    538      *  0 if no hint is given. */
    539     uint32_t                 cFrameBufferHint;
     577    /** Device emulation-specific data needed for the audio connector. */
    540578    struct
    541579    {
    542         /** Scheduling hint given from the device emulation about when this stream is being served on average.
     580        /** Scheduling hint set by the device emulation about when this stream is being served on average (in ms).
    543581         *  Can be 0 if not hint given or some other mechanism (e.g. callbacks) is being used. */
    544582        uint32_t             uSchedulingHintMs;
     
    546584    /**
    547585     * Backend-specific data for the stream.
     586     * On input (requested configuration) those values are set by the audio connector to let the backend know what we expect.
     587     * On output (acquired configuration) those values reflect the values set and used by the backend.
    548588     * Set by the backend on return. Not all backends support all values / features.
    549589     */
     
    9991039    PDMAUDIOSTREAMCTX      enmCtx;
    10001040    /** Timestamp (in ms) since last iteration. */
    1001     uint64_t               tsLastIterateMS;
     1041    uint64_t               tsLastIteratedMs;
     1042    /** Timestamp (in ms) since last playback / capture. */
     1043    uint64_t               tsLastPlayedCapturedMs;
     1044    /** Timestamp (in ms) since last read (input streams) or
     1045     *  write (output streams). */
     1046    uint64_t               tsLastReadWrittenMs;
     1047    /** For output streams this indicates whether the stream has reached
     1048     *  its playback threshold, e.g. is playing audio.
     1049     *  For input streams this  indicates whether the stream has enough input
     1050     *  data to actually start reading audio. */
     1051    bool                   fThresholdReached;
    10021052    /** Union for input/output specifics. */
    10031053    union
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