Skip to content

Commit

Permalink
fix(macos): fix broken streaming on MacOS (#2485)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazer authored May 14, 2024
1 parent c5d8e1b commit ff54ab2
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 33 deletions.
46 changes: 30 additions & 16 deletions src/platform/macos/av_img_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,56 @@

namespace platf {
struct av_sample_buf_t {
CMSampleBufferRef buf;

explicit av_sample_buf_t(CMSampleBufferRef buf):
buf((CMSampleBufferRef) CFRetain(buf)) {}

~av_sample_buf_t() {
CFRelease(buf);
if (buf != nullptr) {
CFRelease(buf);
}
}

CMSampleBufferRef buf;
};

struct av_pixel_buf_t {
explicit av_pixel_buf_t(CVPixelBufferRef buf):
buf((CVPixelBufferRef) CFRetain(buf)),
locked(false) {}
CVPixelBufferRef buf;

// Constructor
explicit av_pixel_buf_t(CMSampleBufferRef sb):
buf(
CMSampleBufferGetImageBuffer(sb)) {
CVPixelBufferLockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
}

[[nodiscard]] uint8_t *
lock() const {
if (!locked) {
CVPixelBufferLockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
}
return (uint8_t *) CVPixelBufferGetBaseAddress(buf);
data() const {
return static_cast<uint8_t *>(CVPixelBufferGetBaseAddress(buf));
}

// Destructor
~av_pixel_buf_t() {
if (locked) {
if (buf != nullptr) {
CVPixelBufferUnlockBaseAddress(buf, kCVPixelBufferLock_ReadOnly);
}
CFRelease(buf);
}
};

CVPixelBufferRef buf;
bool locked;
struct av_img_t: img_t {
std::shared_ptr<av_sample_buf_t> sample_buffer;
std::shared_ptr<av_pixel_buf_t> pixel_buffer;
};

struct av_img_t: public img_t {
struct temp_retain_av_img_t {
std::shared_ptr<av_sample_buf_t> sample_buffer;
std::shared_ptr<av_pixel_buf_t> pixel_buffer;
uint8_t *data;

temp_retain_av_img_t(
std::shared_ptr<av_sample_buf_t> sb,
std::shared_ptr<av_pixel_buf_t> pb,
uint8_t *dt):
sample_buffer(std::move(sb)),
pixel_buffer(std::move(pb)), data(dt) {}
};
} // namespace platf
44 changes: 30 additions & 14 deletions src/platform/macos/display.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
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) {
auto new_sample_buffer = std::make_shared<av_sample_buf_t>(sampleBuffer);
auto new_pixel_buffer = std::make_shared<av_pixel_buf_t>(new_sample_buffer->buf);

std::shared_ptr<img_t> img_out;
if (!pull_free_image_cb(img_out)) {
// got interrupt signal
Expand All @@ -39,17 +42,22 @@
}
auto av_img = std::static_pointer_cast<av_img_t>(img_out);

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
auto old_data_retainer = std::make_shared<temp_retain_av_img_t>(
av_img->sample_buffer,
av_img->pixel_buffer,
img_out->data);

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();
av_img->sample_buffer = new_sample_buffer;
av_img->pixel_buffer = new_pixel_buffer;
img_out->data = new_pixel_buffer->data();

img_out->width = (int) CVPixelBufferGetWidth(pixelBuffer);
img_out->height = (int) CVPixelBufferGetHeight(pixelBuffer);
img_out->row_pitch = (int) CVPixelBufferGetBytesPerRow(pixelBuffer);
img_out->width = (int) CVPixelBufferGetWidth(new_pixel_buffer->buf);
img_out->height = (int) CVPixelBufferGetHeight(new_pixel_buffer->buf);
img_out->row_pitch = (int) CVPixelBufferGetBytesPerRow(new_pixel_buffer->buf);
img_out->pixel_pitch = img_out->row_pitch / img_out->width;

old_data_retainer = nullptr;

if (!push_captured_image_cb(std::move(img_out), true)) {
// got interrupt signal
// returning false here stops capture backend
Expand Down Expand Up @@ -93,19 +101,27 @@
int
dummy_img(img_t *img) override {
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
auto new_sample_buffer = std::make_shared<av_sample_buf_t>(sampleBuffer);
auto new_pixel_buffer = std::make_shared<av_pixel_buf_t>(new_sample_buffer->buf);

auto av_img = (av_img_t *) img;

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
auto old_data_retainer = std::make_shared<temp_retain_av_img_t>(
av_img->sample_buffer,
av_img->pixel_buffer,
img->data);

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();
av_img->sample_buffer = new_sample_buffer;
av_img->pixel_buffer = new_pixel_buffer;
img->data = new_pixel_buffer->data();

img->width = (int) CVPixelBufferGetWidth(pixelBuffer);
img->height = (int) CVPixelBufferGetHeight(pixelBuffer);
img->row_pitch = (int) CVPixelBufferGetBytesPerRow(pixelBuffer);
img->width = (int) CVPixelBufferGetWidth(new_pixel_buffer->buf);
img->height = (int) CVPixelBufferGetHeight(new_pixel_buffer->buf);
img->row_pitch = (int) CVPixelBufferGetBytesPerRow(new_pixel_buffer->buf);
img->pixel_pitch = img->row_pitch / img->width;

old_data_retainer = nullptr;

// returning false here stops capture backend
return false;
}];
Expand Down
3 changes: 3 additions & 0 deletions src/platform/macos/nv12_zero_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
#include <utility>

#include "src/platform/macos/av_img_t.h"
#include "src/platform/macos/nv12_zero_device.h"

#include "src/video.h"
Expand All @@ -24,6 +25,8 @@ namespace platf {
CVPixelBufferRelease((CVPixelBufferRef) data);
}

util::safe_ptr<AVFrame, free_frame> av_frame;

int
nv12_zero_device::convert(platf::img_t &img) {
auto *av_img = (av_img_t *) &img;
Expand Down
1 change: 0 additions & 1 deletion src/platform/macos/nv12_zero_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#pragma once

#include "src/platform/common.h"
#include "src/platform/macos/av_img_t.h"

struct AVFrame;

Expand Down
9 changes: 7 additions & 2 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,9 @@ namespace video {
},
{}, // SDR-specific options
{}, // HDR-specific options
{}, // Fallback options
{
{ "flags"s, "-low_delay" },
}, // Fallback options
std::nullopt,
"h264_videotoolbox"s,
},
Expand Down Expand Up @@ -1451,7 +1453,10 @@ namespace video {
}
}

ctx->flags |= (AV_CODEC_FLAG_CLOSED_GOP | AV_CODEC_FLAG_LOW_DELAY);
// We forcefully reset the flags to avoid clash on reuse of AVCodecContext
ctx->flags = 0;
ctx->flags |= AV_CODEC_FLAG_CLOSED_GOP | AV_CODEC_FLAG_LOW_DELAY;

ctx->flags2 |= AV_CODEC_FLAG2_FAST;

auto avcodec_colorspace = avcodec_colorspace_from_sunshine_colorspace(colorspace);
Expand Down

0 comments on commit ff54ab2

Please sign in to comment.