39544f34b4
On some systems, the SDL audio callback is not called frequently enough (for example it requests 5ms of samples every 10ms), because the output buffer is too small. By default, we want to use a small value (5ms) to minimize latency and buffer underrun, but if it does not work well, users need a way to increase it. Refs #3793 <https://github.com/Genymobile/scrcpy/issues/3793>
90 lines
2.7 KiB
C
90 lines
2.7 KiB
C
#ifndef SC_AUDIO_PLAYER_H
|
|
#define SC_AUDIO_PLAYER_H
|
|
|
|
#include "common.h"
|
|
|
|
#include <stdbool.h>
|
|
#include "trait/frame_sink.h"
|
|
#include <util/audiobuf.h>
|
|
#include <util/average.h>
|
|
#include <util/thread.h>
|
|
#include <util/tick.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
#include <libswresample/swresample.h>
|
|
#include <SDL2/SDL.h>
|
|
|
|
struct sc_audio_player {
|
|
struct sc_frame_sink frame_sink;
|
|
|
|
SDL_AudioDeviceID device;
|
|
|
|
// The target buffering between the producer and the consumer. This value
|
|
// is directly use for compensation.
|
|
// Since audio capture and/or encoding on the device typically produce
|
|
// blocks of 960 samples (20ms) or 1024 samples (~21.3ms), this target
|
|
// value should be higher.
|
|
sc_tick target_buffering_delay;
|
|
uint32_t target_buffering; // in samples
|
|
|
|
// SDL audio output buffer size.
|
|
sc_tick output_buffer_duration;
|
|
uint16_t output_buffer;
|
|
|
|
// Audio buffer to communicate between the receiver and the SDL audio
|
|
// callback (protected by SDL_AudioDeviceLock())
|
|
struct sc_audiobuf buf;
|
|
|
|
// The previous empty space in the buffer (only used by the receiver
|
|
// thread)
|
|
uint32_t previous_can_write;
|
|
|
|
// Resampler (only used from the receiver thread)
|
|
struct SwrContext *swr_ctx;
|
|
|
|
// The sample rate is the same for input and output
|
|
unsigned sample_rate;
|
|
// The number of channels is the same for input and output
|
|
unsigned nb_channels;
|
|
// The number of bytes per sample for a single channel
|
|
unsigned out_bytes_per_sample;
|
|
|
|
// Target buffer for resampling (only used by the receiver thread)
|
|
uint8_t *swr_buf;
|
|
size_t swr_buf_alloc_size;
|
|
|
|
// Number of buffered samples (may be negative on underflow) (only used by
|
|
// the receiver thread)
|
|
struct sc_average avg_buffering;
|
|
// Count the number of samples to trigger a compensation update regularly
|
|
// (only used by the receiver thread)
|
|
uint32_t samples_since_resync;
|
|
|
|
// Number of silence samples inserted since the last received packet
|
|
// (protected by SDL_AudioDeviceLock())
|
|
uint32_t underflow;
|
|
|
|
// Current applied compensation value (only used by the receiver thread)
|
|
int compensation;
|
|
|
|
// Set to true the first time a sample is received (protected by
|
|
// SDL_AudioDeviceLock())
|
|
bool received;
|
|
|
|
// Set to true the first time the SDL callback is called (protected by
|
|
// SDL_AudioDeviceLock())
|
|
bool played;
|
|
|
|
const struct sc_audio_player_callbacks *cbs;
|
|
void *cbs_userdata;
|
|
};
|
|
|
|
struct sc_audio_player_callbacks {
|
|
void (*on_ended)(struct sc_audio_player *ap, bool success, void *userdata);
|
|
};
|
|
|
|
void
|
|
sc_audio_player_init(struct sc_audio_player *ap, sc_tick target_buffering,
|
|
sc_tick audio_output_buffer);
|
|
|
|
#endif
|