By default, audio is enabled (--no-audio must be explicitly passed to disable it). However, some devices may not support audio capture (typically devices below Android 11, or Android 11 when the shell application is not foreground on start). In that case, make the server notify the client to dynamically disable audio forwarding so that it does not wait indefinitely for an audio stream. Also disable audio on unknown codec or missing decoder on the client-side, for the same reasons. PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
88 lines
2.3 KiB
C
88 lines
2.3 KiB
C
#ifndef SC_RECORDER_H
|
|
#define SC_RECORDER_H
|
|
|
|
#include "common.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include "coords.h"
|
|
#include "options.h"
|
|
#include "trait/packet_sink.h"
|
|
#include "util/queue.h"
|
|
#include "util/thread.h"
|
|
|
|
struct sc_record_packet {
|
|
AVPacket *packet;
|
|
struct sc_record_packet *next;
|
|
};
|
|
|
|
struct sc_recorder_queue SC_QUEUE(struct sc_record_packet);
|
|
|
|
struct sc_recorder {
|
|
struct sc_packet_sink video_packet_sink;
|
|
struct sc_packet_sink audio_packet_sink;
|
|
|
|
/* The audio flag is unprotected:
|
|
* - it is initialized from sc_recorder_init() from the main thread;
|
|
* - it may be reset once from the recorder thread if the audio is
|
|
* disabled dynamically.
|
|
*
|
|
* Therefore, once the recorder thread is started, only the recorder thread
|
|
* may access it without data races.
|
|
*/
|
|
bool audio;
|
|
|
|
char *filename;
|
|
enum sc_record_format format;
|
|
AVFormatContext *ctx;
|
|
struct sc_size declared_frame_size;
|
|
|
|
sc_thread thread;
|
|
sc_mutex mutex;
|
|
sc_cond queue_cond;
|
|
// set on sc_recorder_stop(), packet_sink close or recording failure
|
|
bool stopped;
|
|
struct sc_recorder_queue video_queue;
|
|
struct sc_recorder_queue audio_queue;
|
|
|
|
// wake up the recorder thread once the video or audio codec is known
|
|
sc_cond stream_cond;
|
|
const AVCodec *video_codec;
|
|
const AVCodec *audio_codec;
|
|
// Instead of providing an audio_codec, the demuxer may notify that the
|
|
// stream is disabled if the device could not capture audio
|
|
bool audio_disabled;
|
|
|
|
int video_stream_index;
|
|
int audio_stream_index;
|
|
|
|
const struct sc_recorder_callbacks *cbs;
|
|
void *cbs_userdata;
|
|
};
|
|
|
|
struct sc_recorder_callbacks {
|
|
void (*on_ended)(struct sc_recorder *recorder, bool success,
|
|
void *userdata);
|
|
};
|
|
|
|
bool
|
|
sc_recorder_init(struct sc_recorder *recorder, const char *filename,
|
|
enum sc_record_format format, bool audio,
|
|
struct sc_size declared_frame_size,
|
|
const struct sc_recorder_callbacks *cbs, void *cbs_userdata);
|
|
|
|
bool
|
|
sc_recorder_start(struct sc_recorder *recorder);
|
|
|
|
void
|
|
sc_recorder_stop(struct sc_recorder *recorder);
|
|
|
|
void
|
|
sc_recorder_join(struct sc_recorder *recorder);
|
|
|
|
void
|
|
sc_recorder_destroy(struct sc_recorder *recorder);
|
|
|
|
#endif
|