diff options
-rw-r--r-- | include/sound.hpp | 2 | ||||
-rwxr-xr-x | list-sinks.sh | 3 | ||||
-rw-r--r-- | project.conf | 4 | ||||
-rw-r--r-- | src/main.cpp | 48 | ||||
-rw-r--r-- | src/sound.cpp | 58 | ||||
-rwxr-xr-x | twitch-stream.sh | 5 |
6 files changed, 102 insertions, 18 deletions
diff --git a/include/sound.hpp b/include/sound.hpp index c512c31..3c67b02 100644 --- a/include/sound.hpp +++ b/include/sound.hpp @@ -24,6 +24,4 @@ void sound_device_close(SoundDevice *device); */ int sound_device_read_next_chunk(SoundDevice *device, void **buffer); -int sound_device_get_buffer_size(SoundDevice *device); - #endif /* GPU_SCREEN_RECORDER_H */ diff --git a/list-sinks.sh b/list-sinks.sh new file mode 100755 index 0000000..e5fc44f --- /dev/null +++ b/list-sinks.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +pactl list | grep -E '(Description: Monitor of)|(Monitor Source: )' diff --git a/project.conf b/project.conf index 816b703..dd5d572 100644 --- a/project.conf +++ b/project.conf @@ -8,6 +8,9 @@ platforms = ["posix"] include_dirs = ["/opt/cuda/targets/x86_64-linux/include"] libs = ["/usr/lib/libcuda.so"] +[define] +PULSEAUDIO = "1" + [dependencies] glew = ">=2" glx = ">=1" @@ -22,5 +25,6 @@ xdamage = "1" glfw3 = "3" alsa = "1" +libpulse-simple = "13" libswresample = "3"
\ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 27dd225..f16af2b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include <vector> #include <thread> #include <mutex> +#include <map> #include <unistd.h> @@ -503,17 +504,46 @@ static void close_video(AVStream *video_stream, AVFrame *frame) { // av_frame_free(&frame); } +static void usage() { + fprintf(stderr, "usage: gpu-screen-recorder -w <window_id> -c <container_format> -f <fps> -a <audio_input>\n"); + exit(1); +} + int main(int argc, char **argv) { - if (argc < 4) { - fprintf(stderr, "usage: gpu-screen-recorder <window_id> <container_format> <fps>\n"); - return 1; + std::map<std::string, std::string> args = { + { "-w", "" }, + { "-c", "" }, + { "-f", "" }, + { "-a", "" }, + }; + + for(int i = 1; i < argc; i += 2) { + bool valid_arg = false; + for(auto &it : args) { + if(strcmp(argv[i], it.first.c_str()) == 0) { + it.second = argv[i + 1]; + valid_arg = true; + } + } + + if(!valid_arg) { + fprintf(stderr, "Invalid argument '%s'\n", argv[i]); + usage(); + } + } + + for(auto &it : args) { + if(it.second.empty()) { + fprintf(stderr, "Missing argument '%s'\n", it.first.c_str()); + usage(); + } } - Window src_window_id = strtol(argv[1], nullptr, 0); - const char *container_format = argv[2]; - int fps = atoi(argv[3]); + Window src_window_id = strtol(args["-w"].c_str(), nullptr, 0); + const char *container_format = args["-c"].c_str(); + int fps = atoi(args["-f"].c_str()); if(fps <= 0 || fps > 255) { - fprintf(stderr, "invalid fps argument: %s\n", argv[3]); + fprintf(stderr, "invalid fps argument: %s\n", args["-f"].c_str()); return 1; } @@ -550,7 +580,7 @@ int main(int argc, char **argv) { } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); @@ -719,7 +749,7 @@ int main(int argc, char **argv) { int window_height = xwa.height; SoundDevice sound_device; - if(sound_device_get_by_name(&sound_device, "pulse", audio_stream->codec->channels, audio_stream->codec->frame_size) != 0) { + if(sound_device_get_by_name(&sound_device, args["-a"].c_str(), audio_stream->codec->channels, audio_stream->codec->frame_size) != 0) { fprintf(stderr, "failed to get 'pulse' sound device\n"); exit(1); } diff --git a/src/sound.cpp b/src/sound.cpp index c9ee5e7..8d8472d 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -3,6 +3,55 @@ #include <stdlib.h> #include <stdio.h> +#ifdef PULSEAUDIO +#include <pulse/simple.h> +#include <pulse/error.h> + +int sound_device_get_by_name(SoundDevice *device, const char *name, unsigned int num_channels, unsigned int period_frame_size) { + pa_sample_spec ss; + ss.format = PA_SAMPLE_S16LE; + ss.rate = 48000; + ss.channels = num_channels; + int error; + + pa_simple *pa_handle = pa_simple_new(nullptr, "gpu-screen-recorder", PA_STREAM_RECORD, name, "record", &ss, nullptr, nullptr, &error); + if(!pa_handle) { + fprintf(stderr, "pa_simple_new() failed: %s\n", pa_strerror(error)); + return -1; + } + + int buffer_size = period_frame_size * 2 * num_channels; // 2 bytes/sample, @num_channels channels + void *buffer = malloc(buffer_size); + if(!buffer) { + fprintf(stderr, "failed to allocate buffer for audio\n"); + pa_simple_free(pa_handle); + return -1; + } + + fprintf(stderr, "Using pulseaudio\n"); + + device->handle = pa_handle; + device->buffer = buffer; + device->buffer_size = buffer_size; + device->frames = period_frame_size; + return 0; +} + +void sound_device_close(SoundDevice *device) { + pa_simple_free((pa_simple*)device->handle); + free(device->buffer); +} + +int sound_device_read_next_chunk(SoundDevice *device, void **buffer) { + int error; + if(pa_simple_read((pa_simple*)device->handle, device->buffer, device->buffer_size, &error) < 0) { + fprintf(stderr, "pa_simple_read() failed: %s\n", pa_strerror(error)); + return -1; + } + *buffer = device->buffer; + return device->frames; +} +#else #define ALSA_PCM_NEW_HW_PARAMS_API #include <alsa/asoundlib.h> @@ -52,7 +101,9 @@ int sound_device_get_by_name(SoundDevice *device, const char *name, unsigned int return -1; } - device->handle = (void*)handle; + fprintf(stderr, "Using alsa\n"); + + device->handle = handle; device->buffer = buffer; device->buffer_size = buffer_size; device->frames = frames; @@ -83,7 +134,4 @@ int sound_device_read_next_chunk(SoundDevice *device, void **buffer) { *buffer = device->buffer; return rc; } - -int sound_device_get_buffer_size(SoundDevice *device) { - return device->buffer_size; -} +#endif diff --git a/twitch-stream.sh b/twitch-stream.sh index d4da530..cb051d0 100755 --- a/twitch-stream.sh +++ b/twitch-stream.sh @@ -1,4 +1,5 @@ #!/bin/sh -[ "$#" -ne 3 ] && echo "usage: twitch-stream.sh <window_id> <fps> <livestream_key>" && exit 1 -sibs build --release && ./sibs-build/linux_x86_64/release/gpu-screen-recorder "$1" h264 "$2" | ffmpeg -i pipe:0 -c:v copy -f flv "rtmp://live.twitch.tv/app/$3" +[ "$#" -ne 4 ] && echo "usage: twitch-stream.sh <window_id> <fps> <audio_input> <livestream_key>" && exit 1 +#ismv +sibs build --release && ./sibs-build/linux_x86_64/release/gpu-screen-recorder -w "$1" -c flv -f "$2" -a "$3" | ffmpeg -i pipe:0 -c:v copy -f flv "rtmp://live.twitch.tv/app/$4" |