diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/capture/nvfbc.c | 8 | ||||
-rw-r--r-- | src/capture/xcomposite_cuda.c | 11 | ||||
-rw-r--r-- | src/capture/xcomposite_drm.c | 1 | ||||
-rw-r--r-- | src/main.cpp | 22 |
4 files changed, 32 insertions, 10 deletions
diff --git a/src/capture/nvfbc.c b/src/capture/nvfbc.c index 68732f9..c1c998b 100644 --- a/src/capture/nvfbc.c +++ b/src/capture/nvfbc.c @@ -160,7 +160,7 @@ static bool ffmpeg_create_cuda_contexts(gsr_capture_nvfbc *cap_nvfbc, AVCodecCon AVHWFramesContext *hw_frame_context = (AVHWFramesContext*)frame_context->data; hw_frame_context->width = video_codec_context->width; hw_frame_context->height = video_codec_context->height; - hw_frame_context->sw_format = AV_PIX_FMT_0RGB32; + hw_frame_context->sw_format = AV_PIX_FMT_BGR0; hw_frame_context->format = video_codec_context->pix_fmt; hw_frame_context->device_ref = device_ctx; hw_frame_context->device_ctx = (AVHWDeviceContext*)device_ctx->data; @@ -381,6 +381,7 @@ static void gsr_capture_nvfbc_tick(gsr_capture *cap, AVCodecContext *video_codec (*frame)->color_primaries = video_codec_context->color_primaries; (*frame)->color_trc = video_codec_context->color_trc; (*frame)->colorspace = video_codec_context->colorspace; + (*frame)->chroma_location = video_codec_context->chroma_sample_location; } } @@ -414,7 +415,12 @@ static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame) { */ frame->data[0] = (uint8_t*)cu_device_ptr; + //frame->data[1] = (uint8_t*)cu_device_ptr; + //frame->data[2] = (uint8_t*)cu_device_ptr; frame->linesize[0] = frame->width * 4; + // TODO: Use these when outputting yuv444 by changing nvfbc color to YUV444P and sw_format to YUV444P + //frame->linesize[1] = frame->width * 1; + //frame->linesize[2] = frame->width * 1; return 0; } diff --git a/src/capture/xcomposite_cuda.c b/src/capture/xcomposite_cuda.c index bf8a053..1ce80f5 100644 --- a/src/capture/xcomposite_cuda.c +++ b/src/capture/xcomposite_cuda.c @@ -117,7 +117,7 @@ static bool cuda_create_codec_context(gsr_capture_xcomposite_cuda *cap_xcomp, AV (AVHWFramesContext *)frame_context->data; hw_frame_context->width = video_codec_context->width; hw_frame_context->height = video_codec_context->height; - hw_frame_context->sw_format = AV_PIX_FMT_0RGB32; + hw_frame_context->sw_format = AV_PIX_FMT_BGR0; hw_frame_context->format = video_codec_context->pix_fmt; hw_frame_context->device_ref = device_ctx; hw_frame_context->device_ctx = (AVHWDeviceContext*)device_ctx->data; @@ -387,6 +387,7 @@ static void gsr_capture_xcomposite_cuda_tick(gsr_capture *cap, AVCodecContext *v (*frame)->color_primaries = video_codec_context->color_primaries; (*frame)->color_trc = video_codec_context->color_trc; (*frame)->colorspace = video_codec_context->colorspace; + (*frame)->chroma_location = video_codec_context->chroma_sample_location; if(av_hwframe_get_buffer(video_codec_context->hw_frames_ctx, *frame, 0) < 0) { fprintf(stderr, "gsr error: gsr_capture_xcomposite_cuda_tick: av_hwframe_get_buffer failed\n"); @@ -439,6 +440,9 @@ static int gsr_capture_xcomposite_cuda_capture(gsr_capture *cap, AVFrame *frame) cap_xcomp->egl.eglSwapBuffers(cap_xcomp->egl.egl_display, cap_xcomp->egl.egl_surface); frame->linesize[0] = frame->width * 4; + //frame->linesize[0] = frame->width * 1; + //frame->linesize[1] = frame->width * 1; + //frame->linesize[2] = frame->width * 1; CUDA_MEMCPY2D memcpy_struct; memcpy_struct.srcXInBytes = 0; @@ -452,10 +456,13 @@ static int gsr_capture_xcomposite_cuda_capture(gsr_capture *cap, AVFrame *frame) memcpy_struct.srcArray = cap_xcomp->mapped_array; memcpy_struct.dstDevice = (CUdeviceptr)frame->data[0]; memcpy_struct.dstPitch = frame->linesize[0]; - memcpy_struct.WidthInBytes = frame->width * 4; + memcpy_struct.WidthInBytes = frame->width * 4;//frame->width * 1; memcpy_struct.Height = frame->height; cap_xcomp->cuda.cuMemcpy2D_v2(&memcpy_struct); + //frame->data[1] = frame->data[0]; + //frame->data[2] = frame->data[0]; + return 0; } diff --git a/src/capture/xcomposite_drm.c b/src/capture/xcomposite_drm.c index a4810a8..fbd96fc 100644 --- a/src/capture/xcomposite_drm.c +++ b/src/capture/xcomposite_drm.c @@ -376,6 +376,7 @@ static void gsr_capture_xcomposite_drm_tick(gsr_capture *cap, AVCodecContext *vi (*frame)->color_primaries = video_codec_context->color_primaries; (*frame)->color_trc = video_codec_context->color_trc; (*frame)->colorspace = video_codec_context->colorspace; + (*frame)->chroma_location = video_codec_context->chroma_sample_location; int res = av_hwframe_get_buffer(video_codec_context->hw_frames_ctx, *frame, 0); if(res < 0) { diff --git a/src/main.cpp b/src/main.cpp index 2a555cd..80f29a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -370,10 +370,11 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, } codec_context->max_b_frames = 0; codec_context->pix_fmt = pix_fmt; - //codec_context->color_range = AVCOL_RANGE_JPEG; - //codec_context->color_primaries = AVCOL_PRI_BT709; - //codec_context->color_trc = AVCOL_TRC_BT709; - //codec_context->colorspace = AVCOL_SPC_BT709; + codec_context->color_range = AVCOL_RANGE_JPEG; + codec_context->color_primaries = AVCOL_PRI_BT709; + codec_context->color_trc = AVCOL_TRC_BT709; + codec_context->colorspace = AVCOL_SPC_BT709; + //codec_context->chroma_sample_location = AVCHROMA_LOC_CENTER; if(codec->id == AV_CODEC_ID_HEVC) codec_context->codec_tag = MKTAG('h', 'v', 'c', '1'); switch(video_quality) { @@ -422,6 +423,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, #endif av_opt_set_int(codec_context->priv_data, "b_ref_mode", 0, 0); + //av_opt_set_int(codec_context->priv_data, "cbr", true, 0); if(vendor != GPU_VENDOR_NVIDIA) { // TODO: More options, better options @@ -606,6 +608,9 @@ static void open_video(AVCodecContext *codec_context, VideoQuality video_quality av_dict_set(&options, "profile", "high444p", 0); break; } + } else { + //av_dict_set(&options, "profile", "main10", 0); + //av_dict_set(&options, "pix_fmt", "yuv420p16le", 0); } } else { switch(video_quality) { @@ -649,7 +654,7 @@ static void open_video(AVCodecContext *codec_context, VideoQuality video_quality } static void usage() { - fprintf(stderr, "usage: gpu-screen-recorder -w <window_id|monitor|focused> [-c <container_format>] [-s WxH] -f <fps> [-a <audio_input>...] [-q <quality>] [-r <replay_buffer_size_sec>] [-k h264|h265] [-ac aac|opus|flac] [-oc yes|no] [-pixfmt yuv420|yuv444] [-o <output_file>]\n"); + fprintf(stderr, "usage: gpu-screen-recorder -w <window_id|monitor|focused> [-c <container_format>] [-s WxH] -f <fps> [-a <audio_input>...] [-q <quality>] [-r <replay_buffer_size_sec>] [-k h264|h265] [-ac aac|opus|flac] [-oc yes|no] [-o <output_file>]\n"); fprintf(stderr, "OPTIONS:\n"); fprintf(stderr, " -w Window to record, a display, \"screen\", \"screen-direct\", \"screen-direct-force\" or \"focused\". The display is the display (monitor) name in xrandr and if \"screen\" or \"screen-direct\" is selected then all displays are recorded. If this is \"focused\" then the currently focused window is recorded. When recording the focused window then the -s option has to be used as well.\n" " \"screen-direct\"/\"screen-direct-force\" skips one texture copy for fullscreen applications so it may lead to better performance and it works with VRR monitors when recording fullscreen application but may break some applications, such as mpv in fullscreen mode. Direct mode doesn't capture cursor either. \"screen-direct-force\" is not recommended unless you use a VRR monitor because there might be driver issues that cause the video to stutter or record a black screen.\n"); @@ -664,7 +669,7 @@ static void usage() { fprintf(stderr, " -k Video codec to use. Should be either 'auto', 'h264' or 'h265'. Defaults to 'auto' which defaults to 'h265' on nvidia unless recording at a higher resolution than 3840x2160. On AMD/Intel this defaults to 'auto' which defaults to 'h264'. Forcefully set to 'h264' if -c is 'flv'.\n"); fprintf(stderr, " -ac Audio codec to use. Should be either 'aac', 'opus' or 'flac'. Defaults to 'opus' for .mp4/.mkv files, otherwise defaults to 'aac'. 'opus' and 'flac' is only supported by .mp4/.mkv files. 'opus' is recommended for best performance and smallest audio size.\n"); fprintf(stderr, " -oc Overclock memory transfer rate to the maximum performance level. This only applies to NVIDIA and exists to overcome a bug in NVIDIA driver where performance level is dropped when you record a game. Only needed if you are recording a game that is bottlenecked by GPU. Works only if your have \"Coolbits\" set to \"12\" in NVIDIA X settings, see README for more information. Note! use at your own risk! Optional, disabled by default\n"); - fprintf(stderr, " -pixfmt The pixel format to use for the output video. yuv420 is the most common format and is best supported, but the color is compressed, so colors can look washed outandr certain colors of text can look bad. Use yuv444 for no color compression, but the video may not work everywhere and it may not work with hardware video decoding. Optional, defaults to yuv420\n"); + // fprintf(stderr, " -pixfmt The pixel format to use for the output video. yuv420 is the most common format and is best supported, but the color is compressed, so colors can look washed out and certain colors of text can look bad. Use yuv444 for no color compression, but the video may not work everywhere and it may not work with hardware video decoding. Optional, defaults to yuv420\n"); fprintf(stderr, " -o The output file path. If omitted then the encoded data is sent to stdout. Required in replay mode (when using -r). In replay mode this has to be an existing directory instead of a file.\n"); fprintf(stderr, "NOTES:\n"); fprintf(stderr, " Send signal SIGINT (Ctrl+C) to gpu-screen-recorder to stop and save the recording (when not using replay mode).\n"); @@ -1646,6 +1651,7 @@ int main(int argc, char **argv) { if(replay_buffer_size_secs == -1) { AVDictionary *options = nullptr; av_dict_set(&options, "strict", "experimental", 0); + //av_dict_set_int(&av_format_context->metadata, "video_full_range_flag", 1, 0); int ret = avformat_write_header(av_format_context, &options); if (ret < 0) { @@ -1674,6 +1680,7 @@ int main(int argc, char **argv) { frame->color_primaries = video_codec_context->color_primaries; frame->color_trc = video_codec_context->color_trc; frame->colorspace = video_codec_context->colorspace; + frame->chroma_location = video_codec_context->chroma_sample_location; std::mutex write_output_mutex; std::mutex audio_filter_mutex; @@ -1854,6 +1861,7 @@ int main(int argc, char **argv) { // TODO: Check if duplicate frame can be saved just by writing it with a different pts instead of sending it again for(int i = 0; i < num_frames; ++i) { video_frame->pts = video_pts_counter + i; + int ret = avcodec_send_frame(video_codec_context, video_frame); if(ret == 0) { // TODO: Move to separate thread because this could write to network (for example when livestreaming) @@ -1914,6 +1922,7 @@ int main(int argc, char **argv) { double frame_time_overflow = frame_timer_elapsed - target_fps; if (frame_time_overflow >= 0.0) { + frame_time_overflow = std::min(frame_time_overflow, target_fps); frame_timer_start = time_now - frame_time_overflow; gsr_capture_capture(capture, frame); std::lock_guard<std::mutex> lock(video_frame_mutex); @@ -1963,7 +1972,6 @@ int main(int argc, char **argv) { video_frame_cv.notify_one(); } video_send_encode_thread.join(); - //video_packet_save_thread.join(); if(latest_video_frame) { av_frame_free(&latest_video_frame); |