X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fquicksync_encoder.cpp;h=c1621892178c562b70a19b4c4b1be9cf320024ca;hb=refs%2Fheads%2Fkaeru-cef-overlay-hack;hp=70bf8002073d64aba40f2aa6021c3e19ddf9a352;hpb=dcb238eb81768be4021f01dc7102c6c73821d0c0;p=nageru diff --git a/nageru/quicksync_encoder.cpp b/nageru/quicksync_encoder.cpp index 70bf800..c162189 100644 --- a/nageru/quicksync_encoder.cpp +++ b/nageru/quicksync_encoder.cpp @@ -40,7 +40,7 @@ extern "C" { #include #include #include -#include +#include } // namespace @@ -728,101 +728,16 @@ void QuickSyncEncoderImpl::enable_zerocopy_if_possible() global_flags.use_zerocopy = use_zerocopy; } -VADisplayWithCleanup::~VADisplayWithCleanup() +static unique_ptr try_open_va_h264(const string &va_display, VAProfile *h264_profile, string *error) { - if (va_dpy != nullptr) { - vaTerminate(va_dpy); - } - if (x11_display != nullptr) { - XCloseDisplay(x11_display); - } - if (drm_fd != -1) { - close(drm_fd); - } -} - -unique_ptr va_open_display(const string &va_display) -{ - if (va_display.empty() || va_display[0] != '/') { // An X display. - Display *x11_display = XOpenDisplay(va_display.empty() ? nullptr : va_display.c_str()); - if (x11_display == nullptr) { - fprintf(stderr, "error: can't connect to X server!\n"); - return nullptr; - } - - unique_ptr ret(new VADisplayWithCleanup); - ret->x11_display = x11_display; - ret->can_use_zerocopy = true; - ret->va_dpy = vaGetDisplay(x11_display); - if (ret->va_dpy == nullptr) { - return nullptr; - } - return ret; - } else { // A DRM node on the filesystem (e.g. /dev/dri/renderD128). - int drm_fd = open(va_display.c_str(), O_RDWR); - if (drm_fd == -1) { - perror(va_display.c_str()); - return NULL; - } - unique_ptr ret(new VADisplayWithCleanup); - ret->drm_fd = drm_fd; - ret->can_use_zerocopy = false; - ret->va_dpy = vaGetDisplayDRM(drm_fd); - if (ret->va_dpy == nullptr) { - return nullptr; - } - return ret; - } -} - -unique_ptr try_open_va(const string &va_display, VAProfile *h264_profile, string *error) -{ - unique_ptr va_dpy = va_open_display(va_display); - if (va_dpy == nullptr) { - if (error) *error = "Opening VA display failed"; - return nullptr; - } - int major_ver, minor_ver; - VAStatus va_status = vaInitialize(va_dpy->va_dpy, &major_ver, &minor_ver); - if (va_status != VA_STATUS_SUCCESS) { - char buf[256]; - snprintf(buf, sizeof(buf), "vaInitialize() failed with status %d\n", va_status); - if (error != nullptr) *error = buf; - return nullptr; - } - - int num_entrypoints = vaMaxNumEntrypoints(va_dpy->va_dpy); - unique_ptr entrypoints(new VAEntrypoint[num_entrypoints]); - if (entrypoints == nullptr) { - if (error != nullptr) *error = "Failed to allocate memory for VA entry points"; - return nullptr; - } - - // Try the profiles from highest to lowest until we find one that can be encoded. - constexpr VAProfile profile_list[] = { VAProfileH264High, VAProfileH264Main, VAProfileH264ConstrainedBaseline }; - for (unsigned i = 0; i < sizeof(profile_list) / sizeof(profile_list[0]); ++i) { - vaQueryConfigEntrypoints(va_dpy->va_dpy, profile_list[i], entrypoints.get(), &num_entrypoints); - for (int slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) { - if (entrypoints[slice_entrypoint] != VAEntrypointEncSlice) { - continue; - } - - // We found a usable encoder, so return it. - if (h264_profile != nullptr) { - *h264_profile = profile_list[i]; - } - return va_dpy; - } - } - - if (error != nullptr) *error = "Can't find VAEntrypointEncSlice for H264 profiles"; - return nullptr; + return try_open_va(va_display, { VAProfileH264High, VAProfileH264Main, VAProfileH264ConstrainedBaseline }, + VAEntrypointEncSlice, /*desired_configs=*/{}, h264_profile, error); } int QuickSyncEncoderImpl::init_va(const string &va_display) { string error; - va_dpy = try_open_va(va_display, &h264_profile, &error); + va_dpy = try_open_va_h264(va_display, &h264_profile, &error); if (va_dpy == nullptr) { fprintf(stderr, "error: %s\n", error.c_str()); abort(); @@ -1520,8 +1435,8 @@ void QuickSyncEncoderImpl::release_gl_resources() has_released_gl_resources = true; } -QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, AVOutputFormat *oformat, X264Encoder *x264_encoder, DiskSpaceEstimator *disk_space_estimator) - : current_storage_frame(0), resource_pool(resource_pool), surface(surface), x264_encoder(x264_encoder), frame_width(width), frame_height(height), disk_space_estimator(disk_space_estimator) +QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, const AVOutputFormat *oformat, X264Encoder *http_encoder, X264Encoder *disk_encoder, DiskSpaceEstimator *disk_space_estimator) + : current_storage_frame(0), resource_pool(resource_pool), surface(surface), x264_http_encoder(http_encoder), x264_disk_encoder(disk_encoder), frame_width(width), frame_height(height), disk_space_estimator(disk_space_estimator) { file_audio_encoder.reset(new AudioEncoder(AUDIO_OUTPUT_CODEC_NAME, DEFAULT_AUDIO_OUTPUT_BIT_RATE, oformat)); open_output_file(filename); @@ -1533,9 +1448,11 @@ QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, Resource //print_input(); if (global_flags.x264_video_to_http || global_flags.x264_video_to_disk) { - assert(x264_encoder != nullptr); + assert(x264_http_encoder != nullptr); + assert(x264_disk_encoder != nullptr); } else { - assert(x264_encoder == nullptr); + assert(x264_http_encoder == nullptr); + assert(x264_disk_encoder == nullptr); } enable_zerocopy_if_possible(); @@ -1816,7 +1733,7 @@ void QuickSyncEncoderImpl::open_output_file(const std::string &filename) string video_extradata; // FIXME: See other comment about global headers. if (global_flags.x264_video_to_disk) { - video_extradata = x264_encoder->get_global_headers(); + video_extradata = x264_disk_encoder->get_global_headers(); } current_file_mux_metrics.reset(); @@ -1832,7 +1749,7 @@ void QuickSyncEncoderImpl::open_output_file(const std::string &filename) metric_current_file_start_time_seconds = get_timestamp_for_metrics(); if (global_flags.x264_video_to_disk) { - x264_encoder->add_mux(file_mux.get()); + x264_disk_encoder->add_mux(file_mux.get()); } } @@ -1995,7 +1912,10 @@ void QuickSyncEncoderImpl::pass_frame(QuickSyncEncoderImpl::PendingFrame frame, if (global_flags.uncompressed_video_to_http) { add_packet_for_uncompressed_frame(pts, duration, data); } else if (global_flags.x264_video_to_http || global_flags.x264_video_to_disk) { - x264_encoder->add_frame(pts, duration, frame.ycbcr_coefficients, data, received_ts); + x264_http_encoder->add_frame(pts, duration, frame.ycbcr_coefficients, data, received_ts); + } + if (global_flags.x264_separate_disk_encode) { + x264_disk_encoder->add_frame(pts, duration, frame.ycbcr_coefficients, data, received_ts); } if (v4l_output != nullptr) { @@ -2097,8 +2017,8 @@ void QuickSyncEncoderImpl::encode_frame(QuickSyncEncoderImpl::PendingFrame frame } // Proxy object. -QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, AVOutputFormat *oformat, X264Encoder *x264_encoder, DiskSpaceEstimator *disk_space_estimator) - : impl(new QuickSyncEncoderImpl(filename, resource_pool, surface, va_display, width, height, oformat, x264_encoder, disk_space_estimator)) {} +QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, const AVOutputFormat *oformat, X264Encoder *http_encoder, X264Encoder *disk_encoder, DiskSpaceEstimator *disk_space_estimator) + : impl(new QuickSyncEncoderImpl(filename, resource_pool, surface, va_display, width, height, oformat, http_encoder, disk_encoder, disk_space_estimator)) {} // Must be defined here because unique_ptr<> destructor needs to know the impl. QuickSyncEncoder::~QuickSyncEncoder() {} @@ -2153,7 +2073,7 @@ string QuickSyncEncoder::get_usable_va_display() } // First try the default (ie., whatever $DISPLAY is set to). - unique_ptr va_dpy = try_open_va("", nullptr, nullptr); + unique_ptr va_dpy = try_open_va_h264("", nullptr, nullptr); if (va_dpy != nullptr) { if (need_env_reset) { unsetenv("LIBVA_MESSAGING_LEVEL"); @@ -2171,7 +2091,7 @@ string QuickSyncEncoder::get_usable_va_display() } else { for (size_t i = 0; i < g.gl_pathc; ++i) { string path = g.gl_pathv[i]; - va_dpy = try_open_va(path, nullptr, nullptr); + va_dpy = try_open_va_h264(path, nullptr, nullptr); if (va_dpy != nullptr) { fprintf(stderr, "Autodetected %s as a suitable replacement; using it.\n", path.c_str());