cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

audio-buffer.h (10557B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H
     21#define GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H
     22
     23#include <guacamole/stream.h>
     24#include <guacamole/user.h>
     25#include <pthread.h>
     26#include <time.h>
     27
     28/**
     29 * The minimum number of milliseconds of audio data that each instance of
     30 * guac_rdp_audio_buffer should provide storage for. This buffer space does not
     31 * induce additional latency, but is required to compensate for latency and
     32 * functions as an upper limit on the amount of latency the buffer will
     33 * compensate for.
     34 */
     35#define GUAC_RDP_AUDIO_BUFFER_MIN_DURATION 250
     36
     37/**
     38 * A buffer of arbitrary audio data. Received audio data can be written to this
     39 * buffer, and will automatically be flushed via a given handler once the
     40 * internal buffer reaches capacity.
     41 */
     42typedef struct guac_rdp_audio_buffer guac_rdp_audio_buffer;
     43
     44/**
     45 * Handler which is invoked when a guac_rdp_audio_buffer's internal packet
     46 * buffer has reached capacity and must be flushed.
     47 *
     48 * @param audio_buffer
     49 *     The guac_rdp_audio_buffer that has reached capacity and needs to be
     50 *     flushed.
     51 *
     52 * @param length
     53 *     The number of bytes stored within the buffer. This is guaranteed to be
     54 *     identical to the packet_size value specified when the audio buffer was
     55 *     initialized.
     56 */
     57typedef void guac_rdp_audio_buffer_flush_handler(guac_rdp_audio_buffer* audio_buffer, int length);
     58
     59/**
     60 * A description of an arbitrary PCM audio format.
     61 */
     62typedef struct guac_rdp_audio_format {
     63
     64    /**
     65     * The rate of the audio data in samples per second.
     66     */
     67    int rate;
     68
     69    /**
     70     * The number of channels included in the audio data. This will be 1 for
     71     * monaural audio and 2 for stereo.
     72     */
     73    int channels;
     74
     75    /**
     76     * The size of each sample within the audio data, in bytes.
     77     */
     78    int bps;
     79
     80} guac_rdp_audio_format;
     81
     82struct guac_rdp_audio_buffer {
     83
     84    /**
     85     * Lock which is acquired/released to ensure accesses to the audio buffer
     86     * are atomic. This lock is also bound to the modified pthread_cond_t,
     87     * which should be signalled whenever the audio buffer structure has been
     88     * modified.
     89     */
     90    pthread_mutex_t lock;
     91
     92    /**
     93     * Condition which is signalled when any part of the audio buffer structure
     94     * has been modified.
     95     */
     96    pthread_cond_t modified;
     97
     98    /**
     99     * The guac_client instance handling the relevant RDP connection.
    100     */
    101    guac_client* client;
    102
    103    /**
    104     * The user from which this audio buffer will receive data. If no user has
    105     * yet opened an associated audio stream, or if the audio stream has been
    106     * closed, this will be NULL.
    107     */
    108    guac_user* user;
    109
    110    /**
    111     * The stream from which this audio buffer will receive data. If no user
    112     * has yet opened an associated audio stream, or if the audio stream has
    113     * been closed, this will be NULL.
    114     */
    115    guac_stream* stream;
    116
    117    /**
    118     * The PCM format of the audio stream being received from the user, if any.
    119     * If no stream is yet associated, the values stored within this format are
    120     * undefined.
    121     */
    122    guac_rdp_audio_format in_format;
    123
    124    /**
    125     * The PCM format of the audio stream expected by RDP, if any. If no audio
    126     * stream has yet been requested by the RDP server, the values stored
    127     * within this format are undefined.
    128     */
    129    guac_rdp_audio_format out_format;
    130
    131    /**
    132     * The size that each audio packet must be, in bytes. The packet buffer
    133     * within this structure will be at least this size.
    134     */
    135    size_t packet_size;
    136
    137    /**
    138     * The total number of bytes available within the packet buffer.
    139     */
    140    size_t packet_buffer_size;
    141
    142    /**
    143     * The number of bytes currently stored within the packet buffer.
    144     */
    145    int bytes_written;
    146
    147    /**
    148     * The total number of bytes having ever been received by the Guacamole
    149     * server for the current audio stream.
    150     */
    151    int total_bytes_received;
    152
    153    /**
    154     * The total number of bytes having ever been sent to the RDP server for
    155     * the current audio stream.
    156     */
    157    int total_bytes_sent;
    158
    159    /**
    160     * All audio data being prepared for sending to the AUDIO_INPUT channel.
    161     */
    162    char* packet;
    163
    164    /**
    165     * Thread which flushes the audio buffer at a rate that does not exceed the
    166     * the audio sample rate (which might result in dropped samples due to
    167     * overflow of the remote audio buffer).
    168     */
    169    pthread_t flush_thread;
    170
    171    /**
    172     * The absolute point in time that the next packet of audio data sould be
    173     * flushed. Another packet of received data should not be flushed prior to
    174     * this time.
    175     */
    176    struct timespec next_flush;
    177
    178    /**
    179     * Handler function which will be invoked when a full audio packet is
    180     * ready to be flushed to the AUDIO_INPUT channel, if defined. If NULL,
    181     * audio packets will simply be ignored.
    182     */
    183    guac_rdp_audio_buffer_flush_handler* flush_handler;
    184
    185    /**
    186     * Whether guac_rdp_audio_buffer_free() has been invoked and the audio
    187     * buffer is being cleaned up.
    188     */
    189    int stopping;
    190
    191    /**
    192     * Arbitrary data assigned by the AUDIO_INPUT plugin implementation.
    193     */
    194    void* data;
    195
    196};
    197
    198/**
    199 * Allocates a new audio buffer. The new audio buffer will ignore any received
    200 * data until guac_rdp_audio_buffer_begin() is invoked, and will resume
    201 * ignoring received data once guac_rdp_audio_buffer_end() is invoked.
    202 *
    203 * @param client
    204 *     The guac_client instance handling the relevant RDP connection.
    205 *
    206 * @return
    207 *     A newly-allocated audio buffer.
    208 */
    209guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc(guac_client* client);
    210
    211/**
    212 * Associates the given audio buffer with the underlying audio stream which
    213 * has been received from the given Guacamole user. Once both the Guacamole
    214 * audio stream and the RDP audio stream are ready, an appropriate "ack"
    215 * message will be sent.
    216 *
    217 * @param audio_buffer
    218 *     The audio buffer associated with the audio stream just received.
    219 *
    220 * @param user
    221 *     The Guacamole user that created the audio stream.
    222 *
    223 * @param stream
    224 *     The guac_stream object representing the audio stream.
    225 *
    226 * @param rate
    227 *     The rate of the audio stream being received from the user, if any, in
    228 *     samples per second.
    229 *
    230 * @param channels
    231 *     The number of channels included in the audio stream being received from
    232 *     the user, if any.
    233 *
    234 * @param bps
    235 *     The size of each sample within the audio stream being received from the
    236 *     user, if any, in bytes.
    237 */
    238void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer,
    239        guac_user* user, guac_stream* stream, int rate, int channels, int bps);
    240
    241/**
    242 * Defines the output format that should be used by the audio buffer when
    243 * flushing packets of audio data received via guac_rdp_audio_buffer_write().
    244 * As this format determines how the underlying packet buffer will be
    245 * allocated, this function MUST be called prior to the call to
    246 * guac_rdp_audio_buffer_begin().
    247 *
    248 * @param audio_buffer
    249 *     The audio buffer to set the output format of.
    250 *
    251 * @param rate
    252 *     The rate of the audio stream expected by RDP, in samples per second.
    253 *
    254 * @param channels
    255 *     The number of channels included in the audio stream expected by RDP.
    256 *
    257 * @param bps
    258 *     The size of each sample within the audio stream expected by RDP, in
    259 *     bytes.
    260 */
    261void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer,
    262        int rate, int channels, int bps);
    263
    264/**
    265 * Begins handling of audio data received via guac_rdp_audio_buffer_write() and
    266 * allocates the necessary underlying packet buffer. Audio packets having
    267 * exactly packet_frames frames will be flushed as available using the provided
    268 * flush_handler. An audio frame is a set of single samples, one sample per
    269 * channel. The guac_rdp_audio_buffer_set_output() function MUST have
    270 * been invoked first.
    271 *
    272 * @param audio_buffer
    273 *     The audio buffer to begin.
    274 *
    275 * @param packet_frames
    276 *     The exact number of frames (a set of samples, one for each channel)
    277 *     which MUST be included in all audio packets provided to the
    278 *     given flush_handler.
    279 *
    280 * @param flush_handler
    281 *     The function to invoke when an audio packet must be flushed.
    282 *
    283 * @param data
    284 *     Arbitrary data to provide to the flush_handler when an audio packet
    285 *     needs to be flushed.
    286 */
    287void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer,
    288        int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler,
    289        void* data);
    290
    291/**
    292 * Writes the given buffer of audio data to the given audio buffer. A new
    293 * packet will be flushed using the associated flush handler once sufficient
    294 * bytes have been accumulated.
    295 *
    296 * @param audio_buffer
    297 *     The audio buffer to which the given audio data should be written.
    298 *
    299 * @param buffer
    300 *     The buffer of audio data to write to the given audio buffer.
    301 *
    302 * @param length
    303 *     The number of bytes to write.
    304 */
    305void guac_rdp_audio_buffer_write(guac_rdp_audio_buffer* audio_buffer,
    306        char* buffer, int length);
    307
    308/**
    309 * Stops handling of audio data received via guac_rdp_audio_buffer_write() and
    310 * frees the underlying packet buffer. Further audio data will be ignored until
    311 * guac_rdp_audio_buffer_begin() is invoked again.
    312 *
    313 * @param audio_buffer
    314 *     The audio buffer to end.
    315 */
    316void guac_rdp_audio_buffer_end(guac_rdp_audio_buffer* audio_buffer);
    317
    318/**
    319 * Frees the given audio buffer. If guac_rdp_audio_buffer_end() has not yet
    320 * been called, its associated packet buffer will also be freed.
    321 *
    322 * @param audio_buffer
    323 *     The audio buffer to free.
    324 */
    325void guac_rdp_audio_buffer_free(guac_rdp_audio_buffer* audio_buffer);
    326
    327#endif
    328