mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-03-10 16:14:36 +00:00
Implement zero-copy 8/10 bit encoding for macOS
This commit is contained in:
parent
e535706a09
commit
c56ad91693
@ -187,6 +187,7 @@ namespace platf {
|
|||||||
vaapi,
|
vaapi,
|
||||||
dxgi,
|
dxgi,
|
||||||
cuda,
|
cuda,
|
||||||
|
videotoolbox,
|
||||||
unknown
|
unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,10 +77,10 @@ namespace platf {
|
|||||||
|
|
||||||
return std::make_unique<avcodec_encode_device_t>();
|
return std::make_unique<avcodec_encode_device_t>();
|
||||||
}
|
}
|
||||||
else if (pix_fmt == pix_fmt_e::nv12) {
|
else if (pix_fmt == pix_fmt_e::nv12 || pix_fmt == pix_fmt_e::p010) {
|
||||||
auto device = std::make_unique<nv12_zero_device>();
|
auto device = std::make_unique<nv12_zero_device>();
|
||||||
|
|
||||||
device->init(static_cast<void *>(av_capture), setResolution, setPixelFormat);
|
device->init(static_cast<void *>(av_capture), pix_fmt, setResolution, setPixelFormat);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ namespace platf {
|
|||||||
|
|
||||||
std::shared_ptr<display_t>
|
std::shared_ptr<display_t>
|
||||||
display(platf::mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
|
display(platf::mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
|
||||||
if (hwdevice_type != platf::mem_type_e::system) {
|
if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::videotoolbox) {
|
||||||
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
|
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -17,23 +17,19 @@ namespace platf {
|
|||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
nv12_zero_device::convert(platf::img_t &img) {
|
free_buffer(void *opaque, uint8_t *data) {
|
||||||
av_frame_make_writable(av_frame.get());
|
CVPixelBufferRelease((CVPixelBufferRef) data);
|
||||||
|
|
||||||
av_img_t *av_img = (av_img_t *) &img;
|
|
||||||
|
|
||||||
// Set up the data fields in the AVFrame to point into the mapped CVPixelBuffer
|
|
||||||
int planes = CVPixelBufferGetPlaneCount(av_img->pixel_buffer->buf);
|
|
||||||
for (int i = 0; i < planes; i++) {
|
|
||||||
av_frame->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(av_img->pixel_buffer->buf, i);
|
|
||||||
av_frame->data[i] = (uint8_t *) CVPixelBufferGetBaseAddressOfPlane(av_img->pixel_buffer->buf, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We just set data pointers to point into our CVPixelBuffer above, so we have to hold
|
int
|
||||||
// a reference to these buffers to keep them around until the AVFrame is done using them.
|
nv12_zero_device::convert(platf::img_t &img) {
|
||||||
backing_img.sample_buffer = av_img->sample_buffer;
|
av_img_t *av_img = (av_img_t *) &img;
|
||||||
backing_img.pixel_buffer = av_img->pixel_buffer;
|
|
||||||
|
av_buffer_unref(&av_frame->buf[0]);
|
||||||
|
|
||||||
|
av_frame->buf[0] = av_buffer_create((uint8_t *) CFRetain(av_img->pixel_buffer->buf), 0, free_buffer, NULL, 0);
|
||||||
|
av_frame->data[3] = (uint8_t *) av_img->pixel_buffer->buf;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -50,8 +46,10 @@ namespace platf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nv12_zero_device::init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn) {
|
nv12_zero_device::init(void *display, pix_fmt_e pix_fmt, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn) {
|
||||||
pixel_format_fn(display, '420v');
|
pixel_format_fn(display, pix_fmt == pix_fmt_e::nv12 ?
|
||||||
|
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange :
|
||||||
|
kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange);
|
||||||
|
|
||||||
this->display = display;
|
this->display = display;
|
||||||
this->resolution_fn = resolution_fn;
|
this->resolution_fn = resolution_fn;
|
||||||
|
@ -26,7 +26,7 @@ namespace platf {
|
|||||||
using pixel_format_fn_t = std::function<void(void *display, int pixelFormat)>;
|
using pixel_format_fn_t = std::function<void(void *display, int pixelFormat)>;
|
||||||
|
|
||||||
int
|
int
|
||||||
init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn);
|
init(void *display, pix_fmt_e pix_fmt, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn);
|
||||||
|
|
||||||
int
|
int
|
||||||
convert(img_t &img);
|
convert(img_t &img);
|
||||||
@ -35,7 +35,6 @@ namespace platf {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
util::safe_ptr<AVFrame, free_frame> av_frame;
|
util::safe_ptr<AVFrame, free_frame> av_frame;
|
||||||
av_img_t backing_img;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace platf
|
} // namespace platf
|
||||||
|
@ -94,6 +94,8 @@ namespace video {
|
|||||||
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
||||||
util::Either<avcodec_buffer_t, int>
|
util::Either<avcodec_buffer_t, int>
|
||||||
cuda_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
cuda_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
||||||
|
util::Either<avcodec_buffer_t, int>
|
||||||
|
vt_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *);
|
||||||
|
|
||||||
class avcodec_software_encode_device_t: public platf::avcodec_encode_device_t {
|
class avcodec_software_encode_device_t: public platf::avcodec_encode_device_t {
|
||||||
public:
|
public:
|
||||||
@ -930,10 +932,10 @@ namespace video {
|
|||||||
static encoder_t videotoolbox {
|
static encoder_t videotoolbox {
|
||||||
"videotoolbox"sv,
|
"videotoolbox"sv,
|
||||||
std::make_unique<encoder_platform_formats_avcodec>(
|
std::make_unique<encoder_platform_formats_avcodec>(
|
||||||
AV_HWDEVICE_TYPE_NONE, AV_HWDEVICE_TYPE_NONE,
|
AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_NONE,
|
||||||
AV_PIX_FMT_VIDEOTOOLBOX,
|
AV_PIX_FMT_VIDEOTOOLBOX,
|
||||||
AV_PIX_FMT_NV12, AV_PIX_FMT_NV12,
|
AV_PIX_FMT_NV12, AV_PIX_FMT_P010,
|
||||||
nullptr),
|
vt_init_avcodec_hardware_input_buffer),
|
||||||
{
|
{
|
||||||
// Common options
|
// Common options
|
||||||
{
|
{
|
||||||
@ -2634,6 +2636,20 @@ namespace video {
|
|||||||
return hw_device_buf;
|
return hw_device_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util::Either<avcodec_buffer_t, int>
|
||||||
|
vt_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *encode_device) {
|
||||||
|
avcodec_buffer_t hw_device_buf;
|
||||||
|
|
||||||
|
auto status = av_hwdevice_ctx_create(&hw_device_buf, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, nullptr, nullptr, 0);
|
||||||
|
if (status < 0) {
|
||||||
|
char string[AV_ERROR_MAX_STRING_SIZE];
|
||||||
|
BOOST_LOG(error) << "Failed to create a VideoToolbox device: "sv << av_make_error_string(string, AV_ERROR_MAX_STRING_SIZE, status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hw_device_buf;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2712,6 +2728,8 @@ namespace video {
|
|||||||
return platf::mem_type_e::cuda;
|
return platf::mem_type_e::cuda;
|
||||||
case AV_HWDEVICE_TYPE_NONE:
|
case AV_HWDEVICE_TYPE_NONE:
|
||||||
return platf::mem_type_e::system;
|
return platf::mem_type_e::system;
|
||||||
|
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
|
||||||
|
return platf::mem_type_e::videotoolbox;
|
||||||
default:
|
default:
|
||||||
return platf::mem_type_e::unknown;
|
return platf::mem_type_e::unknown;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user