Skip to content

Commit 3438e88

Browse files
megapro17rom1v
authored andcommitted
Add support for FLAC audio codec
PR Genymobile#4410 <#Genymobile#4410> Co-authored-by: Romain Vimont <[email protected]> Signed-off-by: Romain Vimont <[email protected]>
1 parent 22e2c4d commit 3438e88

File tree

12 files changed

+103
-16
lines changed

12 files changed

+103
-16
lines changed

app/data/bash-completion/scrcpy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ _scrcpy() {
9797
return
9898
;;
9999
--audio-codec)
100-
COMPREPLY=($(compgen -W 'opus aac raw' -- "$cur"))
100+
COMPREPLY=($(compgen -W 'opus aac flac raw' -- "$cur"))
101101
return
102102
;;
103103
--video-source)
@@ -125,7 +125,7 @@ _scrcpy() {
125125
return
126126
;;
127127
--record-format)
128-
COMPREPLY=($(compgen -W 'mp4 mkv m4a mka opus aac' -- "$cur"))
128+
COMPREPLY=($(compgen -W 'mp4 mkv m4a mka opus aac flac' -- "$cur"))
129129
return
130130
;;
131131
--render-driver)

app/data/zsh-completion/_scrcpy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ arguments=(
1111
'--always-on-top[Make scrcpy window always on top \(above other windows\)]'
1212
'--audio-bit-rate=[Encode the audio at the given bit-rate]'
1313
'--audio-buffer=[Configure the audio buffering delay (in milliseconds)]'
14-
'--audio-codec=[Select the audio codec]:codec:(opus aac raw)'
14+
'--audio-codec=[Select the audio codec]:codec:(opus aac flac raw)'
1515
'--audio-codec-options=[Set a list of comma-separated key\:type=value options for the device audio encoder]'
1616
'--audio-encoder=[Use a specific MediaCodec audio encoder]'
1717
'--audio-source=[Select the audio source]:source:(output mic)'
@@ -65,7 +65,7 @@ arguments=(
6565
'--push-target=[Set the target directory for pushing files to the device by drag and drop]'
6666
{-r,--record=}'[Record screen to file]:record file:_files'
6767
'--raw-key-events[Inject key events for all input keys, and ignore text events]'
68-
'--record-format=[Force recording format]:format:(mp4 mkv m4a mka opus aac)'
68+
'--record-format=[Force recording format]:format:(mp4 mkv m4a mka opus aac flac)'
6969
'--render-driver=[Request SDL to use the given render driver]:driver name:(direct3d opengl opengles2 opengles metal software)'
7070
'--require-audio=[Make scrcpy fail if audio is enabled but does not work]'
7171
'--rotation=[Set the initial display rotation]:rotation values:(0 1 2 3)'

app/scrcpy.1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Default is 50.
3535

3636
.TP
3737
.BI "\-\-audio\-codec " name
38-
Select an audio codec (opus, aac or raw).
38+
Select an audio codec (opus, aac, flac or raw).
3939

4040
Default is opus.
4141

@@ -355,7 +355,7 @@ Inject key events for all input keys, and ignore text events.
355355

356356
.TP
357357
.BI "\-\-record\-format " format
358-
Force recording format (mp4, mkv, m4a, mka, opus or aac).
358+
Force recording format (mp4, mkv, m4a, mka, opus, aac or flac).
359359

360360
.TP
361361
.BI "\-\-render\-driver " name

app/src/cli.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ static const struct sc_option options[] = {
152152
.longopt_id = OPT_AUDIO_CODEC,
153153
.longopt = "audio-codec",
154154
.argdesc = "name",
155-
.text = "Select an audio codec (opus, aac or raw).\n"
155+
.text = "Select an audio codec (opus, aac, flac or raw).\n"
156156
"Default is opus.",
157157
},
158158
{
@@ -594,7 +594,8 @@ static const struct sc_option options[] = {
594594
.longopt_id = OPT_RECORD_FORMAT,
595595
.longopt = "record-format",
596596
.argdesc = "format",
597-
.text = "Force recording format (mp4, mkv, m4a, mka, opus or aac).",
597+
.text = "Force recording format (mp4, mkv, m4a, mka, opus, aac or "
598+
"flac).",
598599
},
599600
{
600601
.longopt_id = OPT_RENDER_DRIVER,
@@ -1626,6 +1627,9 @@ get_record_format(const char *name) {
16261627
if (!strcmp(name, "aac")) {
16271628
return SC_RECORD_FORMAT_AAC;
16281629
}
1630+
if (!strcmp(name, "flac")) {
1631+
return SC_RECORD_FORMAT_FLAC;
1632+
}
16291633
return 0;
16301634
}
16311635

@@ -1695,11 +1699,15 @@ parse_audio_codec(const char *optarg, enum sc_codec *codec) {
16951699
*codec = SC_CODEC_AAC;
16961700
return true;
16971701
}
1702+
if (!strcmp(optarg, "flac")) {
1703+
*codec = SC_CODEC_FLAC;
1704+
return true;
1705+
}
16981706
if (!strcmp(optarg, "raw")) {
16991707
*codec = SC_CODEC_RAW;
17001708
return true;
17011709
}
1702-
LOGE("Unsupported audio codec: %s (expected opus, aac or raw)", optarg);
1710+
LOGE("Unsupported audio codec: %s (expected opus, aac, flac or raw)", optarg);
17031711
return false;
17041712
}
17051713

@@ -2376,6 +2384,16 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
23762384
"(try with --audio-codec=aac)");
23772385
return false;
23782386
}
2387+
if (opts->record_format == SC_RECORD_FORMAT_FLAC
2388+
&& opts->audio_codec != SC_CODEC_FLAC) {
2389+
LOGE("Recording to FLAC file requires a FLAC audio stream "
2390+
"(try with --audio-codec=flac)");
2391+
return false;
2392+
}
2393+
}
2394+
2395+
if (opts->audio_codec == SC_CODEC_FLAC && opts->audio_bit_rate) {
2396+
LOGW("--audio-bit-rate is ignored for FLAC audio codec");
23792397
}
23802398

23812399
if (opts->audio_codec == SC_CODEC_RAW) {

app/src/demuxer.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ sc_demuxer_to_avcodec_id(uint32_t codec_id) {
2525
#define SC_CODEC_ID_H265 UINT32_C(0x68323635) // "h265" in ASCII
2626
#define SC_CODEC_ID_AV1 UINT32_C(0x00617631) // "av1" in ASCII
2727
#define SC_CODEC_ID_OPUS UINT32_C(0x6f707573) // "opus" in ASCII
28-
#define SC_CODEC_ID_AAC UINT32_C(0x00616163) // "aac in ASCII"
28+
#define SC_CODEC_ID_AAC UINT32_C(0x00616163) // "aac" in ASCII
29+
#define SC_CODEC_ID_FLAC UINT32_C(0x666c6163) // "flac" in ASCII
2930
#define SC_CODEC_ID_RAW UINT32_C(0x00726177) // "raw" in ASCII
3031
switch (codec_id) {
3132
case SC_CODEC_ID_H264:
@@ -43,6 +44,8 @@ sc_demuxer_to_avcodec_id(uint32_t codec_id) {
4344
return AV_CODEC_ID_OPUS;
4445
case SC_CODEC_ID_AAC:
4546
return AV_CODEC_ID_AAC;
47+
case SC_CODEC_ID_FLAC:
48+
return AV_CODEC_ID_FLAC;
4649
case SC_CODEC_ID_RAW:
4750
return AV_CODEC_ID_PCM_S16LE;
4851
default:
@@ -207,6 +210,11 @@ run_demuxer(void *data) {
207210
codec_ctx->channels = 2;
208211
#endif
209212
codec_ctx->sample_rate = 48000;
213+
214+
if (raw_codec_id == SC_CODEC_ID_FLAC) {
215+
// The sample_fmt is not set by the FLAC decoder
216+
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;
217+
}
210218
}
211219

212220
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {

app/src/options.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ enum sc_record_format {
2525
SC_RECORD_FORMAT_MKA,
2626
SC_RECORD_FORMAT_OPUS,
2727
SC_RECORD_FORMAT_AAC,
28+
SC_RECORD_FORMAT_FLAC,
2829
};
2930

3031
static inline bool
3132
sc_record_format_is_audio_only(enum sc_record_format fmt) {
3233
return fmt == SC_RECORD_FORMAT_M4A
3334
|| fmt == SC_RECORD_FORMAT_MKA
3435
|| fmt == SC_RECORD_FORMAT_OPUS
35-
|| fmt == SC_RECORD_FORMAT_AAC;
36+
|| fmt == SC_RECORD_FORMAT_AAC
37+
|| fmt == SC_RECORD_FORMAT_FLAC;
3638
}
3739

3840
enum sc_codec {
@@ -41,6 +43,7 @@ enum sc_codec {
4143
SC_CODEC_AV1,
4244
SC_CODEC_OPUS,
4345
SC_CODEC_AAC,
46+
SC_CODEC_FLAC,
4447
SC_CODEC_RAW,
4548
};
4649

app/src/recorder.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ sc_recorder_get_format_name(enum sc_record_format format) {
6969
return "matroska";
7070
case SC_RECORD_FORMAT_OPUS:
7171
return "opus";
72+
case SC_RECORD_FORMAT_FLAC:
73+
return "flac";
7274
default:
7375
return NULL;
7476
}

app/src/server.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ sc_server_get_codec_name(enum sc_codec codec) {
178178
return "opus";
179179
case SC_CODEC_AAC:
180180
return "aac";
181+
case SC_CODEC_FLAC:
182+
return "flac";
181183
case SC_CODEC_RAW:
182184
return "raw";
183185
default:

doc/audio.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ scrcpy --audio-source=mic --no-video --no-playback --record=file.opus
6262

6363
## Codec
6464

65-
The audio codec can be selected. The possible values are `opus` (default), `aac`
66-
and `raw` (uncompressed PCM 16-bit LE):
65+
The audio codec can be selected. The possible values are `opus` (default),
66+
`aac`, `flac` and `raw` (uncompressed PCM 16-bit LE):
6767

6868
```bash
6969
scrcpy --audio-codec=opus # default
7070
scrcpy --audio-codec=aac
71+
scrcpy --audio-codec=flac
7172
scrcpy --audio-codec=raw
7273
```
7374

@@ -80,7 +81,14 @@ then your device has no Opus encoder: try `scrcpy --audio-codec=aac`.
8081
For advanced usage, to pass arbitrary parameters to the [`MediaFormat`],
8182
check `--audio-codec-options` in the manpage or in `scrcpy --help`.
8283

84+
For example, to change the [FLAC compression level]:
85+
86+
```bash
87+
scrcpy --audio-codec=flac --audio-codec-options=flac-compression-level=8
88+
```
89+
8390
[`MediaFormat`]: https://developer.android.com/reference/android/media/MediaFormat
91+
[FLAC compression level]: https://developer.android.com/reference/android/media/MediaFormat#KEY_FLAC_COMPRESSION_LEVEL
8492

8593

8694
## Encoder

doc/recording.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ To record only the audio:
1818
```bash
1919
scrcpy --no-video --record=file.opus
2020
scrcpy --no-video --audio-codec=aac --record=file.aac
21-
# .m4a/.mp4 and .mka/.mkv are also supported for both opus and aac
21+
scrcpy --no-video --audio-codec=flac --record=file.flac
22+
# .m4a/.mp4 and .mka/.mkv are also supported for opus, aac and flac
2223
```
2324

2425
Timestamps are captured on the device, so [packet delay variation] does not
@@ -35,6 +36,7 @@ client side. Several formats (containers) are supported:
3536
- MP4 (`.mp4`, `.m4a`, `.aac`)
3637
- Matroska (`.mkv`, `.mka`)
3738
- OPUS (`.opus`)
39+
- FLAC (`.flac`)
3840

3941
The container is automatically selected based on the filename.
4042

0 commit comments

Comments
 (0)