fbe0f951e1
Play the decoded audio using SDL. The audio player frame sink receives the audio frames, resample them and write them to a byte buffer (introduced by this commit). On SDL audio callback (from an internal SDL thread), copy samples from this byte buffer to the SDL audio buffer. The byte buffer is protected by the SDL_AudioDeviceLock(), but it has been designed so that the producer and the consumer may write and read in parallel, provided that they don't access the same slices of the ring-buffer buffer. PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757> Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
78 lines
2.3 KiB
C
78 lines
2.3 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/average.h>
|
|
#include <util/bytebuf.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
|
|
|
|
// Audio buffer to communicate between the receiver and the SDL audio
|
|
// callback (protected by SDL_AudioDeviceLock())
|
|
struct sc_bytebuf buf;
|
|
|
|
// The previous number of bytes available in the buffer (only used by the
|
|
// receiver thread)
|
|
size_t previous_write_avail;
|
|
|
|
// 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;
|
|
|
|
// 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);
|
|
|
|
#endif
|