mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-04-07 13:21:05 +00:00
Fix CVPixelBuffer/CMSampleBuffer ownership issues
This commit is contained in:
parent
ca041f2934
commit
e535706a09
@ -10,10 +10,43 @@
|
|||||||
#include <CoreVideo/CoreVideo.h>
|
#include <CoreVideo/CoreVideo.h>
|
||||||
|
|
||||||
namespace platf {
|
namespace platf {
|
||||||
struct av_img_t: public img_t {
|
struct av_sample_buf_t {
|
||||||
CVPixelBufferRef pixel_buffer = nullptr;
|
av_sample_buf_t(CMSampleBufferRef buf):
|
||||||
CMSampleBufferRef sample_buffer = nullptr;
|
buf((CMSampleBufferRef) CFRetain(buf)) {}
|
||||||
|
|
||||||
~av_img_t();
|
~av_sample_buf_t() {
|
||||||
|
CFRelease(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMSampleBufferRef buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct av_pixel_buf_t {
|
||||||
|
av_pixel_buf_t(CVPixelBufferRef buf):
|
||||||
|
buf((CVPixelBufferRef) CFRetain(buf)),
|
||||||
|
locked(false) {}
|
||||||
|
|
||||||
|
uint8_t *
|
||||||
|
lock() {
|
||||||
|
if (!locked) {
|
||||||
|
CVPixelBufferLockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
|
||||||
|
}
|
||||||
|
return (uint8_t *) CVPixelBufferGetBaseAddress(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
~av_pixel_buf_t() {
|
||||||
|
if (locked) {
|
||||||
|
CVPixelBufferUnlockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
|
||||||
|
}
|
||||||
|
CFRelease(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVPixelBufferRef buf;
|
||||||
|
bool locked;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct av_img_t: public img_t {
|
||||||
|
std::shared_ptr<av_sample_buf_t> sample_buffer;
|
||||||
|
std::shared_ptr<av_pixel_buf_t> pixel_buffer;
|
||||||
};
|
};
|
||||||
} // namespace platf
|
} // namespace platf
|
||||||
|
@ -20,18 +20,6 @@ namespace fs = std::filesystem;
|
|||||||
namespace platf {
|
namespace platf {
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
av_img_t::~av_img_t() {
|
|
||||||
if (pixel_buffer != NULL) {
|
|
||||||
CVPixelBufferUnlockBaseAddress(pixel_buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sample_buffer != nullptr) {
|
|
||||||
CFRelease(sample_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct av_display_t: public display_t {
|
struct av_display_t: public display_t {
|
||||||
AVVideo *av_capture;
|
AVVideo *av_capture;
|
||||||
CGDirectDisplayID display_id;
|
CGDirectDisplayID display_id;
|
||||||
@ -43,11 +31,6 @@ namespace platf {
|
|||||||
capture_e
|
capture_e
|
||||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||||
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
|
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
|
||||||
CFRetain(sampleBuffer);
|
|
||||||
|
|
||||||
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
|
||||||
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
|
||||||
|
|
||||||
std::shared_ptr<img_t> img_out;
|
std::shared_ptr<img_t> img_out;
|
||||||
if (!pull_free_image_cb(img_out)) {
|
if (!pull_free_image_cb(img_out)) {
|
||||||
// got interrupt signal
|
// got interrupt signal
|
||||||
@ -56,16 +39,11 @@ namespace platf {
|
|||||||
}
|
}
|
||||||
auto av_img = std::static_pointer_cast<av_img_t>(img_out);
|
auto av_img = std::static_pointer_cast<av_img_t>(img_out);
|
||||||
|
|
||||||
if (av_img->pixel_buffer != nullptr)
|
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
||||||
CVPixelBufferUnlockBaseAddress(av_img->pixel_buffer, 0);
|
|
||||||
|
|
||||||
if (av_img->sample_buffer != nullptr)
|
|
||||||
CFRelease(av_img->sample_buffer);
|
|
||||||
|
|
||||||
av_img->sample_buffer = sampleBuffer;
|
|
||||||
av_img->pixel_buffer = pixelBuffer;
|
|
||||||
img_out->data = (uint8_t *) CVPixelBufferGetBaseAddress(pixelBuffer);
|
|
||||||
|
|
||||||
|
av_img->sample_buffer = std::make_shared<av_sample_buf_t>(sampleBuffer);
|
||||||
|
av_img->pixel_buffer = std::make_shared<av_pixel_buf_t>(pixelBuffer);
|
||||||
|
img_out->data = av_img->pixel_buffer->lock();
|
||||||
|
|
||||||
img_out->width = CVPixelBufferGetWidth(pixelBuffer);
|
img_out->width = CVPixelBufferGetWidth(pixelBuffer);
|
||||||
img_out->height = CVPixelBufferGetHeight(pixelBuffer);
|
img_out->height = CVPixelBufferGetHeight(pixelBuffer);
|
||||||
@ -117,23 +95,11 @@ namespace platf {
|
|||||||
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
|
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
|
||||||
auto av_img = (av_img_t *) img;
|
auto av_img = (av_img_t *) img;
|
||||||
|
|
||||||
CFRetain(sampleBuffer);
|
|
||||||
|
|
||||||
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
||||||
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
|
||||||
|
|
||||||
// XXX: next_img->img should be moved to a smart pointer with
|
|
||||||
// the CFRelease as custom deallocator
|
|
||||||
if (av_img->pixel_buffer != nullptr)
|
|
||||||
CVPixelBufferUnlockBaseAddress(((av_img_t *) img)->pixel_buffer, 0);
|
|
||||||
|
|
||||||
if (av_img->sample_buffer != nullptr)
|
|
||||||
CFRelease(av_img->sample_buffer);
|
|
||||||
|
|
||||||
av_img->sample_buffer = sampleBuffer;
|
|
||||||
av_img->pixel_buffer = pixelBuffer;
|
|
||||||
img->data = (uint8_t *) CVPixelBufferGetBaseAddress(pixelBuffer);
|
|
||||||
|
|
||||||
|
av_img->sample_buffer = std::make_shared<av_sample_buf_t>(sampleBuffer);
|
||||||
|
av_img->pixel_buffer = std::make_shared<av_pixel_buf_t>(pixelBuffer);
|
||||||
|
img->data = av_img->pixel_buffer->lock();
|
||||||
|
|
||||||
img->width = CVPixelBufferGetWidth(pixelBuffer);
|
img->width = CVPixelBufferGetWidth(pixelBuffer);
|
||||||
img->height = CVPixelBufferGetHeight(pixelBuffer);
|
img->height = CVPixelBufferGetHeight(pixelBuffer);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
* @brief todo
|
* @brief todo
|
||||||
*/
|
*/
|
||||||
#include "src/platform/macos/nv12_zero_device.h"
|
#include "src/platform/macos/nv12_zero_device.h"
|
||||||
#include "src/platform/macos/av_img_t.h"
|
|
||||||
|
|
||||||
#include "src/video.h"
|
#include "src/video.h"
|
||||||
|
|
||||||
@ -18,8 +17,6 @@ namespace platf {
|
|||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::safe_ptr<AVFrame, free_frame> av_frame;
|
|
||||||
|
|
||||||
int
|
int
|
||||||
nv12_zero_device::convert(platf::img_t &img) {
|
nv12_zero_device::convert(platf::img_t &img) {
|
||||||
av_frame_make_writable(av_frame.get());
|
av_frame_make_writable(av_frame.get());
|
||||||
@ -33,6 +30,10 @@ namespace platf {
|
|||||||
av_frame->data[i] = (uint8_t *) CVPixelBufferGetBaseAddressOfPlane(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
|
||||||
|
// a reference to these buffers to keep them around until the AVFrame is done using them.
|
||||||
|
backing_img.sample_buffer = av_img->sample_buffer;
|
||||||
|
backing_img.pixel_buffer = av_img->pixel_buffer;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/platform/common.h"
|
#include "src/platform/common.h"
|
||||||
|
#include "src/platform/macos/av_img_t.h"
|
||||||
|
|
||||||
|
struct AVFrame;
|
||||||
|
|
||||||
namespace platf {
|
namespace platf {
|
||||||
|
void
|
||||||
|
free_frame(AVFrame *frame);
|
||||||
|
|
||||||
class nv12_zero_device: public avcodec_encode_device_t {
|
class nv12_zero_device: public avcodec_encode_device_t {
|
||||||
// display holds a pointer to an av_video object. Since the namespaces of AVFoundation
|
// display holds a pointer to an av_video object. Since the namespaces of AVFoundation
|
||||||
@ -27,6 +32,10 @@ namespace platf {
|
|||||||
convert(img_t &img);
|
convert(img_t &img);
|
||||||
int
|
int
|
||||||
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx);
|
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
util::safe_ptr<AVFrame, free_frame> av_frame;
|
||||||
|
av_img_t backing_img;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace platf
|
} // namespace platf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user