diff --git a/src/platform/macos/av_img_t.h b/src/platform/macos/av_img_t.h index fb0d7ecd0f5..f42f9ceb12e 100644 --- a/src/platform/macos/av_img_t.h +++ b/src/platform/macos/av_img_t.h @@ -10,43 +10,10 @@ #include namespace platf { - struct av_sample_buf_t { - explicit av_sample_buf_t(CMSampleBufferRef buf): - buf((CMSampleBufferRef) CFRetain(buf)) {} - - ~av_sample_buf_t() { - CFRelease(buf); - } - - CMSampleBufferRef buf; - }; - - struct av_pixel_buf_t { - explicit av_pixel_buf_t(CVPixelBufferRef buf): - buf((CVPixelBufferRef) CFRetain(buf)), - locked(false) {} - - [[nodiscard]] uint8_t * - lock() const { - 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 sample_buffer; - std::shared_ptr pixel_buffer; + CVPixelBufferRef pixel_buffer = nullptr; + CMSampleBufferRef sample_buffer = nullptr; + + ~av_img_t(); }; } // namespace platf diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index 3468d46f55e..67a602c80c1 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -20,6 +20,18 @@ namespace platf { 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 { AVVideo *av_capture {}; CGDirectDisplayID display_id {}; @@ -31,6 +43,11 @@ 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 { auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) { + CFRetain(sampleBuffer); + + CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); + CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); + std::shared_ptr img_out; if (!pull_free_image_cb(img_out)) { // got interrupt signal @@ -39,11 +56,16 @@ } auto av_img = std::static_pointer_cast(img_out); - CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); + if (av_img->pixel_buffer != nullptr) + 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(sampleBuffer); - av_img->pixel_buffer = std::make_shared(pixelBuffer); - img_out->data = av_img->pixel_buffer->lock(); img_out->width = (int) CVPixelBufferGetWidth(pixelBuffer); img_out->height = (int) CVPixelBufferGetHeight(pixelBuffer); @@ -95,11 +117,23 @@ auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) { auto av_img = (av_img_t *) img; + CFRetain(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(sampleBuffer); - av_img->pixel_buffer = std::make_shared(pixelBuffer); - img->data = av_img->pixel_buffer->lock(); img->width = (int) CVPixelBufferGetWidth(pixelBuffer); img->height = (int) CVPixelBufferGetHeight(pixelBuffer); diff --git a/src/platform/macos/nv12_zero_device.cpp b/src/platform/macos/nv12_zero_device.cpp index c217c637661..2a4eb476559 100644 --- a/src/platform/macos/nv12_zero_device.cpp +++ b/src/platform/macos/nv12_zero_device.cpp @@ -5,6 +5,7 @@ #include #include "src/platform/macos/nv12_zero_device.h" +#include "src/platform/macos/av_img_t.h" #include "src/video.h" @@ -24,6 +25,8 @@ namespace platf { CVPixelBufferRelease((CVPixelBufferRef) data); } + util::safe_ptr av_frame; + int nv12_zero_device::convert(platf::img_t &img) { auto *av_img = (av_img_t *) &img; @@ -36,10 +39,10 @@ namespace platf { // // The presence of the AVBufferRef allows FFmpeg to simply add a reference to the buffer // rather than having to perform a deep copy of the data buffers in avcodec_send_frame(). - av_frame->buf[0] = av_buffer_create((uint8_t *) CFRetain(av_img->pixel_buffer->buf), 0, free_buffer, nullptr, 0); + av_frame->buf[0] = av_buffer_create((uint8_t *) CFRetain(av_img->pixel_buffer), 0, free_buffer, nullptr, 0); // Place a CVPixelBufferRef at data[3] as required by AV_PIX_FMT_VIDEOTOOLBOX - av_frame->data[3] = (uint8_t *) av_img->pixel_buffer->buf; + av_frame->data[3] = (uint8_t *) av_img->pixel_buffer; return 0; } diff --git a/src/platform/macos/nv12_zero_device.h b/src/platform/macos/nv12_zero_device.h index b83210cb94f..8f29a99440b 100644 --- a/src/platform/macos/nv12_zero_device.h +++ b/src/platform/macos/nv12_zero_device.h @@ -5,13 +5,8 @@ #pragma once #include "src/platform/common.h" -#include "src/platform/macos/av_img_t.h" - -struct AVFrame; namespace platf { - void - free_frame(AVFrame *frame); class nv12_zero_device: public avcodec_encode_device_t { // display holds a pointer to an av_video object. Since the namespaces of AVFoundation @@ -32,9 +27,6 @@ namespace platf { convert(img_t &img) override; int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override; - - private: - util::safe_ptr av_frame; }; } // namespace platf