browser(firefox): do not leak vpx codec (#16034)
This commit is contained in:
parent
dcbcb93c26
commit
b479869ddc
|
|
@ -1,2 +1,2 @@
|
||||||
1336
|
1337
|
||||||
Changed: lushnikov@chromium.org Tue Jul 26 17:42:25 MSK 2022
|
Changed: yurys@chromium.org Thu Jul 28 13:35:27 PDT 2022
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,18 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct VpxCodecDeleter {
|
||||||
|
void operator()(vpx_codec_ctx_t* codec) {
|
||||||
|
if (codec) {
|
||||||
|
vpx_codec_err_t ret = vpx_codec_destroy(codec);
|
||||||
|
if (ret != VPX_CODEC_OK)
|
||||||
|
fprintf(stderr, "Failed to destroy codec: %s\n", vpx_codec_error(codec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ScopedVpxCodec = std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter>;
|
||||||
|
|
||||||
// Number of timebase unints per one frame.
|
// Number of timebase unints per one frame.
|
||||||
constexpr int timeScale = 1000;
|
constexpr int timeScale = 1000;
|
||||||
|
|
||||||
|
|
@ -183,8 +195,8 @@ private:
|
||||||
|
|
||||||
class ScreencastEncoder::VPXCodec {
|
class ScreencastEncoder::VPXCodec {
|
||||||
public:
|
public:
|
||||||
VPXCodec(vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
|
VPXCodec(ScopedVpxCodec codec, vpx_codec_enc_cfg_t cfg, FILE* file)
|
||||||
: m_codec(codec)
|
: m_codec(std::move(codec))
|
||||||
, m_cfg(cfg)
|
, m_cfg(cfg)
|
||||||
, m_file(file)
|
, m_file(file)
|
||||||
, m_writer(new WebMFileWriter(file, &m_cfg))
|
, m_writer(new WebMFileWriter(file, &m_cfg))
|
||||||
|
|
@ -233,14 +245,14 @@ private:
|
||||||
vpx_codec_iter_t iter = nullptr;
|
vpx_codec_iter_t iter = nullptr;
|
||||||
const vpx_codec_cx_pkt_t *pkt = nullptr;
|
const vpx_codec_cx_pkt_t *pkt = nullptr;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME);
|
const vpx_codec_err_t res = vpx_codec_encode(m_codec.get(), img, m_pts, duration, flags, VPX_DL_REALTIME);
|
||||||
if (res != VPX_CODEC_OK) {
|
if (res != VPX_CODEC_OK) {
|
||||||
fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
|
fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(m_codec.get()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gotPkts = false;
|
bool gotPkts = false;
|
||||||
while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) {
|
while ((pkt = vpx_codec_get_cx_data(m_codec.get(), &iter)) != nullptr) {
|
||||||
gotPkts = true;
|
gotPkts = true;
|
||||||
|
|
||||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||||
|
|
@ -266,7 +278,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<nsIThread> m_encoderQueue;
|
RefPtr<nsIThread> m_encoderQueue;
|
||||||
vpx_codec_ctx_t m_codec;
|
ScopedVpxCodec m_codec;
|
||||||
vpx_codec_enc_cfg_t m_cfg;
|
vpx_codec_enc_cfg_t m_cfg;
|
||||||
FILE* m_file { nullptr };
|
FILE* m_file { nullptr };
|
||||||
std::unique_ptr<WebMFileWriter> m_writer;
|
std::unique_ptr<WebMFileWriter> m_writer;
|
||||||
|
|
@ -277,7 +289,7 @@ private:
|
||||||
std::unique_ptr<vpx_image_t> m_image;
|
std::unique_ptr<vpx_image_t> m_image;
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, const gfx::IntMargin& margin)
|
ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec> vpxCodec, const gfx::IntMargin& margin)
|
||||||
: m_vpxCodec(std::move(vpxCodec))
|
: m_vpxCodec(std::move(vpxCodec))
|
||||||
, m_margin(margin)
|
, m_margin(margin)
|
||||||
{
|
{
|
||||||
|
|
@ -314,9 +326,9 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
|
||||||
cfg.g_timebase.den = fps * timeScale;
|
cfg.g_timebase.den = fps * timeScale;
|
||||||
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
||||||
|
|
||||||
vpx_codec_ctx_t codec;
|
ScopedVpxCodec codec(new vpx_codec_ctx_t);
|
||||||
if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) {
|
if (vpx_codec_enc_init(codec.get(), codec_interface, &cfg, 0)) {
|
||||||
errorString.AppendPrintf("Failed to initialize encoder: %s", vpx_codec_error(&codec));
|
errorString.AppendPrintf("Failed to initialize encoder: %s", vpx_codec_error(codec.get()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,7 +338,7 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(codec, cfg, file));
|
std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(std::move(codec), cfg, file));
|
||||||
// fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
|
// fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
|
||||||
return new ScreencastEncoder(std::move(vpxCodec), margin);
|
return new ScreencastEncoder(std::move(vpxCodec), margin);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin);
|
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin);
|
||||||
|
|
||||||
class VPXCodec;
|
class VPXCodec;
|
||||||
ScreencastEncoder(std::unique_ptr<VPXCodec>&&, const gfx::IntMargin& margin);
|
ScreencastEncoder(std::unique_ptr<VPXCodec>, const gfx::IntMargin& margin);
|
||||||
|
|
||||||
void encodeFrame(const webrtc::VideoFrame& videoFrame);
|
void encodeFrame(const webrtc::VideoFrame& videoFrame);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
1336
|
1337
|
||||||
Changed: lushnikov@chromium.org Tue Jul 26 17:42:25 MSK 2022
|
Changed: yurys@chromium.org Thu Jul 28 13:34:25 PDT 2022
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,18 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct VpxCodecDeleter {
|
||||||
|
void operator()(vpx_codec_ctx_t* codec) {
|
||||||
|
if (codec) {
|
||||||
|
vpx_codec_err_t ret = vpx_codec_destroy(codec);
|
||||||
|
if (ret != VPX_CODEC_OK)
|
||||||
|
fprintf(stderr, "Failed to destroy codec: %s\n", vpx_codec_error(codec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ScopedVpxCodec = std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter>;
|
||||||
|
|
||||||
// Number of timebase unints per one frame.
|
// Number of timebase unints per one frame.
|
||||||
constexpr int timeScale = 1000;
|
constexpr int timeScale = 1000;
|
||||||
|
|
||||||
|
|
@ -183,8 +195,8 @@ private:
|
||||||
|
|
||||||
class ScreencastEncoder::VPXCodec {
|
class ScreencastEncoder::VPXCodec {
|
||||||
public:
|
public:
|
||||||
VPXCodec(vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
|
VPXCodec(ScopedVpxCodec codec, vpx_codec_enc_cfg_t cfg, FILE* file)
|
||||||
: m_codec(codec)
|
: m_codec(std::move(codec))
|
||||||
, m_cfg(cfg)
|
, m_cfg(cfg)
|
||||||
, m_file(file)
|
, m_file(file)
|
||||||
, m_writer(new WebMFileWriter(file, &m_cfg))
|
, m_writer(new WebMFileWriter(file, &m_cfg))
|
||||||
|
|
@ -233,14 +245,14 @@ private:
|
||||||
vpx_codec_iter_t iter = nullptr;
|
vpx_codec_iter_t iter = nullptr;
|
||||||
const vpx_codec_cx_pkt_t *pkt = nullptr;
|
const vpx_codec_cx_pkt_t *pkt = nullptr;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME);
|
const vpx_codec_err_t res = vpx_codec_encode(m_codec.get(), img, m_pts, duration, flags, VPX_DL_REALTIME);
|
||||||
if (res != VPX_CODEC_OK) {
|
if (res != VPX_CODEC_OK) {
|
||||||
fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
|
fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(m_codec.get()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gotPkts = false;
|
bool gotPkts = false;
|
||||||
while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) {
|
while ((pkt = vpx_codec_get_cx_data(m_codec.get(), &iter)) != nullptr) {
|
||||||
gotPkts = true;
|
gotPkts = true;
|
||||||
|
|
||||||
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||||
|
|
@ -266,7 +278,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<nsIThread> m_encoderQueue;
|
RefPtr<nsIThread> m_encoderQueue;
|
||||||
vpx_codec_ctx_t m_codec;
|
ScopedVpxCodec m_codec;
|
||||||
vpx_codec_enc_cfg_t m_cfg;
|
vpx_codec_enc_cfg_t m_cfg;
|
||||||
FILE* m_file { nullptr };
|
FILE* m_file { nullptr };
|
||||||
std::unique_ptr<WebMFileWriter> m_writer;
|
std::unique_ptr<WebMFileWriter> m_writer;
|
||||||
|
|
@ -277,7 +289,7 @@ private:
|
||||||
std::unique_ptr<vpx_image_t> m_image;
|
std::unique_ptr<vpx_image_t> m_image;
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, const gfx::IntMargin& margin)
|
ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec> vpxCodec, const gfx::IntMargin& margin)
|
||||||
: m_vpxCodec(std::move(vpxCodec))
|
: m_vpxCodec(std::move(vpxCodec))
|
||||||
, m_margin(margin)
|
, m_margin(margin)
|
||||||
{
|
{
|
||||||
|
|
@ -314,9 +326,9 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
|
||||||
cfg.g_timebase.den = fps * timeScale;
|
cfg.g_timebase.den = fps * timeScale;
|
||||||
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
||||||
|
|
||||||
vpx_codec_ctx_t codec;
|
ScopedVpxCodec codec(new vpx_codec_ctx_t);
|
||||||
if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) {
|
if (vpx_codec_enc_init(codec.get(), codec_interface, &cfg, 0)) {
|
||||||
errorString.AppendPrintf("Failed to initialize encoder: %s", vpx_codec_error(&codec));
|
errorString.AppendPrintf("Failed to initialize encoder: %s", vpx_codec_error(codec.get()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,7 +338,7 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(codec, cfg, file));
|
std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(std::move(codec), cfg, file));
|
||||||
// fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
|
// fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
|
||||||
return new ScreencastEncoder(std::move(vpxCodec), margin);
|
return new ScreencastEncoder(std::move(vpxCodec), margin);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin);
|
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin);
|
||||||
|
|
||||||
class VPXCodec;
|
class VPXCodec;
|
||||||
ScreencastEncoder(std::unique_ptr<VPXCodec>&&, const gfx::IntMargin& margin);
|
ScreencastEncoder(std::unique_ptr<VPXCodec>, const gfx::IntMargin& margin);
|
||||||
|
|
||||||
void encodeFrame(const webrtc::VideoFrame& videoFrame);
|
void encodeFrame(const webrtc::VideoFrame& videoFrame);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue