Make audio recording optional

This commit is contained in:
dec05eba 2020-08-26 02:54:05 +02:00
parent bf9df281d2
commit 78ab032cf5
2 changed files with 92 additions and 85 deletions

View File

@ -11,11 +11,12 @@ When recording a 4k game, fps drops from 30 to 7 when using OBS Studio, however
the fps remains at 30. the fps remains at 30.
# Installation # Installation
gpu screen recorder can be built using [sibs](https://github.com/DEC05EBA/sibs) or if you are running Arch Linux, then you can find it on aur under the name gpu-screen-recorder-git (`yay -S gpu-screen-recorder-git`). gpu screen recorder can be built using [sibs](https://git.dec05eba.com/sibs) or if you are running Arch Linux, then you can find it on aur under the name gpu-screen-recorder-git (`yay -S gpu-screen-recorder-git`).
# How to use # How to use
Run `interactive.sh` or run gpu-screen-recorder directly, for example: `gpu-screen-recorder -w 0x1c00001 -c mp4 -f 60 -a bluez_sink.00_18_09_8A_07_93.a2dp_sink.monitor > test_video.mp4`\ Run `interactive.sh` or run gpu-screen-recorder directly, for example: `gpu-screen-recorder -w 0x1c00001 -c mp4 -f 60 -a bluez_sink.00_18_09_8A_07_93.a2dp_sink.monitor > test_video.mp4`\
Then stop the screen recorder with Ctrl+C. Then stop the screen recorder with Ctrl+C.\
There is also a gui for the gpu-screen-recorder, called [gpu-screen-recorder-gtk](https://git.dec05eba.com/gpu-screen-recorder-gtk/).
# Demo # Demo
[![Click here to watch a demo video on youtube](https://img.youtube.com/vi/n5tm0g01n6A/0.jpg)](https://www.youtube.com/watch?v=n5tm0g01n6A) [![Click here to watch a demo video on youtube](https://img.youtube.com/vi/n5tm0g01n6A/0.jpg)](https://www.youtube.com/watch?v=n5tm0g01n6A)

View File

@ -565,44 +565,42 @@ static void int_handler(int dummy) {
running = 0; running = 0;
} }
struct Arg {
const char *value;
bool optional;
};
int main(int argc, char **argv) { int main(int argc, char **argv) {
signal(SIGINT, int_handler); signal(SIGINT, int_handler);
std::map<std::string, std::string> args = { std::map<std::string, Arg> args = {
{ "-w", "" }, { "-w", Arg { nullptr, false } },
{ "-c", "" }, { "-c", Arg { nullptr, false } },
{ "-f", "" }, { "-f", Arg { nullptr, false } },
{ "-a", "" }, { "-a", Arg { nullptr, true } }
}; };
for(int i = 1; i < argc; i += 2) { for(int i = 1; i < argc - 1; i += 2) {
bool valid_arg = false; auto it = args.find(argv[i]);
for(auto &it : args) { if(it == args.end()) {
if(strcmp(argv[i], it.first.c_str()) == 0) {
it.second = argv[i + 1];
valid_arg = true;
break;
}
}
if(!valid_arg) {
fprintf(stderr, "Invalid argument '%s'\n", argv[i]); fprintf(stderr, "Invalid argument '%s'\n", argv[i]);
usage(); usage();
} }
it->second.value = argv[i + 1];
} }
for(auto &it : args) { for(auto &it : args) {
if(it.second.empty()) { if(!it.second.optional && !it.second.value) {
fprintf(stderr, "Missing argument '%s'\n", it.first.c_str()); fprintf(stderr, "Missing argument '%s'\n", it.first.c_str());
usage(); usage();
} }
} }
Window src_window_id = strtol(args["-w"].c_str(), nullptr, 0); Window src_window_id = strtol(args["-w"].value, nullptr, 0);
const char *container_format = args["-c"].c_str(); const char *container_format = args["-c"].value;
int fps = atoi(args["-f"].c_str()); int fps = atoi(args["-f"].value);
if(fps <= 0 || fps > 255) { if(fps <= 0 || fps > 255) {
fprintf(stderr, "invalid fps argument: %s\n", args["-f"].c_str()); fprintf(stderr, "invalid fps argument: %s\n", args["-f"].value);
return 1; return 1;
} }
@ -807,8 +805,13 @@ int main(int argc, char **argv) {
int window_width = xwa.width; int window_width = xwa.width;
int window_height = xwa.height; int window_height = xwa.height;
std::mutex write_output_mutex;
std::thread audio_thread;
SoundDevice sound_device; SoundDevice sound_device;
if(sound_device_get_by_name(&sound_device, args["-a"].c_str(), audio_stream->codec->channels, audio_stream->codec->frame_size) != 0) { Arg &audio_input_arg = args["-a"];
if(audio_input_arg.value) {
if(sound_device_get_by_name(&sound_device, audio_input_arg.value, audio_stream->codec->channels, audio_stream->codec->frame_size) != 0) {
fprintf(stderr, "failed to get 'pulse' sound device\n"); fprintf(stderr, "failed to get 'pulse' sound device\n");
exit(1); exit(1);
} }
@ -817,12 +820,13 @@ int main(int argc, char **argv) {
uint8_t *audio_frame_buf = (uint8_t *)av_malloc(audio_buffer_size); uint8_t *audio_frame_buf = (uint8_t *)av_malloc(audio_buffer_size);
avcodec_fill_audio_frame(audio_frame, audio_stream->codec->channels, audio_stream->codec->sample_fmt, (const uint8_t*)audio_frame_buf, audio_buffer_size, 1); avcodec_fill_audio_frame(audio_frame, audio_stream->codec->channels, audio_stream->codec->sample_fmt, (const uint8_t*)audio_frame_buf, audio_buffer_size, 1);
audio_thread = std::thread([audio_buffer_size](AVFormatContext *av_format_context, AVStream *audio_stream, uint8_t *audio_frame_buf, SoundDevice *sound_device, AVFrame *audio_frame, std::mutex *write_output_mutex) mutable {
AVPacket audio_packet; AVPacket audio_packet;
av_new_packet(&audio_packet, audio_buffer_size); if(av_new_packet(&audio_packet, audio_buffer_size) != 0) {
fprintf(stderr, "Failed to create audio packet\n");
exit(1);
}
std::mutex write_output_mutex;
std::thread audio_thread([](AVFormatContext *av_format_context, AVStream *audio_stream, AVPacket *audio_packet, uint8_t *audio_frame_buf, SoundDevice *sound_device, AVFrame *audio_frame, std::mutex *write_output_mutex) mutable {
SwrContext *swr = swr_alloc(); SwrContext *swr = swr_alloc();
if(!swr) { if(!swr) {
fprintf(stderr, "Failed to create SwrContext\n"); fprintf(stderr, "Failed to create SwrContext\n");
@ -849,17 +853,17 @@ int main(int argc, char **argv) {
//++audio_frame_index; //++audio_frame_index;
int got_frame = 0; int got_frame = 0;
int ret = avcodec_encode_audio2(audio_stream->codec, audio_packet, audio_frame, &got_frame); int ret = avcodec_encode_audio2(audio_stream->codec, &audio_packet, audio_frame, &got_frame);
if(ret < 0){ if(ret < 0){
printf("Failed to encode!\n"); printf("Failed to encode!\n");
break; break;
} }
if (got_frame==1){ if (got_frame==1){
//printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size); //printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size);
audio_packet->stream_index = audio_stream->index; audio_packet.stream_index = audio_stream->index;
std::lock_guard<std::mutex> lock(*write_output_mutex); std::lock_guard<std::mutex> lock(*write_output_mutex);
ret = av_write_frame(av_format_context, audio_packet); ret = av_write_frame(av_format_context, &audio_packet);
av_free_packet(audio_packet); av_free_packet(&audio_packet);
} }
} else { } else {
fprintf(stderr, "failed to read sound from device, error: %d\n", sound_buffer_size); fprintf(stderr, "failed to read sound from device, error: %d\n", sound_buffer_size);
@ -867,7 +871,8 @@ int main(int argc, char **argv) {
} }
swr_free(&swr); swr_free(&swr);
}, av_format_context, audio_stream, &audio_packet, audio_frame_buf, &sound_device, audio_frame, &write_output_mutex); }, av_format_context, audio_stream, audio_frame_buf, &sound_device, audio_frame, &write_output_mutex);
}
bool redraw = true; bool redraw = true;
XEvent e; XEvent e;
@ -1000,9 +1005,10 @@ int main(int argc, char **argv) {
} }
running = 0; running = 0;
if(audio_input_arg.value) {
audio_thread.join(); audio_thread.join();
sound_device_close(&sound_device); sound_device_close(&sound_device);
}
//Flush Encoder //Flush Encoder
#if 0 #if 0