pylibvpx 1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ additional_commands:
2
+ bullet_char: '*'
3
+ dangle_parens: false
4
+ enum_char: .
5
+ line_ending: unix
6
+ line_width: 120
7
+ max_pargs_hwrap: 3
8
+ separate_ctrl_name_with_space: false
9
+ separate_fn_name_with_space: false
10
+ tab_size: 2
@@ -0,0 +1,70 @@
1
+ cmake_minimum_required(VERSION 3.16)
2
+ project(pylibvpx LANGUAGES CXX VERSION "1.0")
3
+
4
+ # Default to Release build type
5
+ if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
6
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
7
+ endif()
8
+
9
+ # Fetch conan.cmake
10
+ list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
11
+ list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
12
+ if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
13
+ message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
14
+ file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
15
+ "${CMAKE_BINARY_DIR}/conan.cmake" TLS_VERIFY ON)
16
+ endif()
17
+ include(${CMAKE_BINARY_DIR}/conan.cmake)
18
+
19
+ # Get pybind11 and libvpx from conan
20
+ conan_cmake_configure(
21
+ REQUIRES pybind11/2.10.4 libvpx/1.11.0
22
+ GENERATORS cmake_find_package
23
+ )
24
+ conan_cmake_autodetect(settings)
25
+ if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
26
+ # MSVC 2022 can't build libvpx -> donwload binary for MSVC 2019
27
+ list(APPEND settings "libvpx:compiler.version=16")
28
+ endif()
29
+ conan_cmake_install(
30
+ PATH_OR_REFERENCE .
31
+ BUILD missing
32
+ REMOTE conancenter
33
+ SETTINGS ${settings}
34
+ )
35
+
36
+ # Create libvpx python library
37
+ find_package(pybind11 REQUIRED)
38
+ find_package(libvpx REQUIRED)
39
+ pybind11_add_module(${PROJECT_NAME} "pylibvpx.cpp" "vpxcommon.hpp" "vpxcommon_impl.hpp")
40
+ set_target_properties(${PROJECT_NAME} PROPERTIES
41
+ CXX_STANDARD 20
42
+ CXX_STANDARD_REQUIRED ON
43
+ )
44
+ target_link_libraries(${PROJECT_NAME} PRIVATE libvpx::libvpx)
45
+ target_compile_definitions(${PROJECT_NAME} PRIVATE
46
+ MODULE_NAME=${PROJECT_NAME}
47
+ MODULE_VERSION=${PROJECT_VERSION}
48
+ )
49
+
50
+ option(WITH_VPX_ENCODER "With vpx encoder" ON)
51
+ if(WITH_VPX_ENCODER)
52
+ message(STATUS "With VPX encoder")
53
+ target_sources(${PROJECT_NAME} PRIVATE "vpxencoder.hpp" "vpxencoder.cpp")
54
+ target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_VPX_ENCODER=1)
55
+ endif()
56
+
57
+ option(WITH_VPX_DECODER "With vpx decoder" ON)
58
+ if(WITH_VPX_DECODER)
59
+ message(STATUS "With VPX decoder")
60
+ target_sources(${PROJECT_NAME} PRIVATE "vpxdecoder.hpp" "vpxdecoder.cpp")
61
+ target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_VPX_DECODER=1)
62
+ endif()
63
+
64
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
65
+ target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic)
66
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
67
+ target_compile_options(${PROJECT_NAME} PUBLIC "/Zc:__cplusplus")
68
+ endif()
69
+
70
+ install(TARGETS ${PROJECT_NAME} DESTINATION ".")
pylibvpx-1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Peter Würtz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pylibvpx-1.0/PKG-INFO ADDED
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: pylibvpx
3
+ Version: 1.0
4
+ Summary: Python bindings for libvpx
5
+ Home-page: https://github.com/pwuertz/libvpx-bindings
6
+ Author: Peter Würtz
7
+ Author-email: pwuertz@gmail.com
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+
11
+ # Python `libvpx` bindings
12
+ Python bindings for VPX encoding/decoding library
pylibvpx-1.0/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # Python `libvpx` bindings
2
+ Python bindings for VPX encoding/decoding library
@@ -0,0 +1,97 @@
1
+ #include <Python.h>
2
+ #include <pybind11/pybind11.h>
3
+ #include <pybind11/pytypes.h>
4
+ #include <pybind11/numpy.h>
5
+ #include "vpxcommon.hpp"
6
+ #ifdef WITH_VPX_ENCODER
7
+ #include "vpxencoder.hpp"
8
+ #endif
9
+ #ifdef WITH_VPX_DECODER
10
+ #include "vpxdecoder.hpp"
11
+ #endif
12
+
13
+ #include <string_view>
14
+ #include <iostream>
15
+
16
+ namespace py = pybind11;
17
+
18
+ constexpr std::string_view VERSION_STR = PYBIND11_TOSTRING(MODULE_VERSION);
19
+
20
+ #ifdef WITH_VPX_ENCODER
21
+ void py_vpxe_encode(Vpx::Encoder& encoder, const py::object& fn)
22
+ {
23
+ const auto packetHandler = [&](const uint8_t* packet, const size_t size) {
24
+ fn(py::memoryview::from_memory(packet, size));
25
+ };
26
+ encoder.encode(packetHandler);
27
+ }
28
+ py::array_t<uint8_t, py::array::c_style> py_vpxe_yplane(Vpx::Encoder& encoder)
29
+ {
30
+ const Vpx::Plane plane = encoder.yPlane();
31
+ return py::array_t<uint8_t, py::array::c_style>(
32
+ std::vector<Py_ssize_t>{plane.height, plane.width},
33
+ std::vector<Py_ssize_t>{plane.stride, 1},
34
+ plane.data
35
+ );
36
+ }
37
+ void py_vpxe_copygray(Vpx::Encoder& encoder, const py::array& image)
38
+ {
39
+ const auto* imageData = static_cast<const uint8_t*>(image.data());
40
+ encoder.copyFromGray(imageData);
41
+ }
42
+ #endif
43
+
44
+ #ifdef WITH_VPX_DECODER
45
+ void py_vpxd_decode(Vpx::Decoder& decoder, const py::bytes& packet, const py::object& fn)
46
+ {
47
+ uint8_t* data; Py_ssize_t size;
48
+ PyBytes_AsStringAndSize(packet.ptr(), reinterpret_cast<char**>(&data), &size);
49
+ const auto frameHandler = [&](const Vpx::Plane& plane) {
50
+ py::array_t<uint8_t, py::array::c_style> img(
51
+ std::vector<Py_ssize_t>{plane.height, plane.width},
52
+ std::vector<Py_ssize_t>{plane.stride, 1},
53
+ plane.data
54
+ );
55
+ fn(img);
56
+ };
57
+ decoder.decode(data, static_cast<size_t>(size), frameHandler);
58
+ }
59
+ #endif
60
+
61
+
62
+ PYBIND11_MODULE(MODULE_NAME, m) {
63
+ m.attr("__version__") = py::str(VERSION_STR.data(), VERSION_STR.size());
64
+
65
+ py::enum_<Vpx::Gen>(m, "VpxGen")
66
+ .value("Vp8", Vpx::Gen::Vp8)
67
+ .value("Vp9", Vpx::Gen::Vp9);
68
+
69
+ #ifdef WITH_VPX_ENCODER
70
+ py::class_<Vpx::Encoder> vpxencCls(m, "VpxEncoder");
71
+ vpxencCls.def(py::init<const Vpx::Encoder::Config&>())
72
+ .def(py::init([](const unsigned int width, const unsigned int height) {
73
+ return new Vpx::Encoder({.width = width, .height = height});
74
+ }))
75
+ .def("encode", py_vpxe_encode)
76
+ .def("yPlane", py_vpxe_yplane)
77
+ .def("copyGray", py_vpxe_copygray);
78
+
79
+ py::class_<Vpx::Encoder::Config>(vpxencCls, "Config")
80
+ .def(py::init([](const unsigned int width, const unsigned int height) {
81
+ return new Vpx::Encoder::Config { .width=width, .height=height };
82
+ }))
83
+ .def_readwrite("width", &Vpx::Encoder::Config::width)
84
+ .def_readwrite("height", &Vpx::Encoder::Config::height)
85
+ .def_readwrite("fps", &Vpx::Encoder::Config::fps)
86
+ .def_readwrite("bitrate", &Vpx::Encoder::Config::bitrate)
87
+ .def_readwrite("threads", &Vpx::Encoder::Config::threads)
88
+ .def_readwrite("cpu_used", &Vpx::Encoder::Config::cpu_used)
89
+ .def_readwrite("gen", &Vpx::Encoder::Config::gen);
90
+ #endif
91
+
92
+ #ifdef WITH_VPX_DECODER
93
+ py::class_<Vpx::Decoder> vpxdecCls(m, "VpxDecoder");
94
+ vpxdecCls.def(py::init<Vpx::Gen>())
95
+ .def("decode", py_vpxd_decode);
96
+ #endif
97
+ }
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: pylibvpx
3
+ Version: 1.0
4
+ Summary: Python bindings for libvpx
5
+ Home-page: https://github.com/pwuertz/libvpx-bindings
6
+ Author: Peter Würtz
7
+ Author-email: pwuertz@gmail.com
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+
11
+ # Python `libvpx` bindings
12
+ Python bindings for VPX encoding/decoding library
@@ -0,0 +1,17 @@
1
+ .cmake-format.yaml
2
+ CMakeLists.txt
3
+ LICENSE
4
+ README.md
5
+ pylibvpx.cpp
6
+ pyproject.toml
7
+ setup.py
8
+ vpxcommon.hpp
9
+ vpxcommon_impl.hpp
10
+ vpxdecoder.cpp
11
+ vpxdecoder.hpp
12
+ vpxencoder.cpp
13
+ vpxencoder.hpp
14
+ pylibvpx.egg-info/PKG-INFO
15
+ pylibvpx.egg-info/SOURCES.txt
16
+ pylibvpx.egg-info/dependency_links.txt
17
+ pylibvpx.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ pylibvpx
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=56.0", "cmake_build_extension", "wheel", "conan~=1.50"]
3
+ build-backend = "setuptools.build_meta"
pylibvpx-1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
pylibvpx-1.0/setup.py ADDED
@@ -0,0 +1,24 @@
1
+ import pathlib
2
+ from setuptools import setup
3
+ from cmake_build_extension import BuildExtension, CMakeExtension
4
+
5
+ this_directory = pathlib.Path(__file__).parent
6
+ long_description = (this_directory / "README.md").read_text()
7
+ long_description_content_type="text/markdown"
8
+
9
+ setup(
10
+ name="pylibvpx",
11
+ version="1.0",
12
+ author="Peter Würtz",
13
+ author_email="pwuertz@gmail.com",
14
+ url="https://github.com/pwuertz/libvpx-bindings",
15
+ description="Python bindings for libvpx",
16
+ long_description=long_description,
17
+ long_description_content_type=long_description_content_type,
18
+ ext_modules=[CMakeExtension(
19
+ name="pylibvpx",
20
+ source_dir=".",
21
+ install_prefix=".",
22
+ )],
23
+ cmdclass=dict(build_ext=BuildExtension),
24
+ )
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+ #include <cstdint>
3
+
4
+ namespace Vpx {
5
+
6
+ enum class Gen {
7
+ Vp8,
8
+ Vp9,
9
+ };
10
+
11
+ struct Plane {
12
+ uint8_t* data;
13
+ const unsigned int height;
14
+ const unsigned int width;
15
+ const int stride;
16
+ };
17
+
18
+ } // namespace Vpx
@@ -0,0 +1,57 @@
1
+ #pragma once
2
+ #include <algorithm>
3
+ #include <stdexcept>
4
+ #include <vpx/vpx_image.h>
5
+ #include "vpxcommon.hpp"
6
+
7
+ namespace Vpx {
8
+
9
+ struct Image
10
+ {
11
+ Image(const unsigned int width, const unsigned int height)
12
+ {
13
+ if (vpx_img_alloc(&m_img, VPX_IMG_FMT_I420, width, height, 1) == nullptr) {
14
+ throw std::runtime_error("Failed to allocate image");
15
+ }
16
+ fillBlack();
17
+ }
18
+
19
+ Image(const Image&) = delete;
20
+ void operator=(const Image&) = delete;
21
+
22
+ ~Image() noexcept { vpx_img_free(&m_img); }
23
+
24
+ constexpr operator vpx_image_t*() noexcept { return &m_img; }
25
+ constexpr operator const vpx_image_t*() const noexcept { return &m_img; }
26
+
27
+ void fillBlack() noexcept
28
+ {
29
+ std::fill_n(m_img.planes[VPX_PLANE_Y], m_img.w * m_img.h, 0);
30
+ std::fill_n(m_img.planes[VPX_PLANE_U], m_img.w * m_img.h / 4, 128);
31
+ std::fill_n(m_img.planes[VPX_PLANE_V], m_img.w * m_img.h / 4, 128);
32
+ }
33
+
34
+ constexpr Plane yPlane() const noexcept
35
+ {
36
+ return {
37
+ .data = m_img.planes[VPX_PLANE_Y],
38
+ .height = m_img.d_h, .width = m_img.d_w,
39
+ .stride = m_img.stride[0]
40
+ };
41
+ }
42
+
43
+ void copyFromGrayscale(const uint8_t* src)
44
+ {
45
+ const auto yPlane = this->yPlane();
46
+ for (unsigned int row = 0; row < yPlane.height; ++row) {
47
+ const auto* srcRow = src + row * yPlane.width;
48
+ auto* dstRow = yPlane.data + row * yPlane.stride;
49
+ std::copy_n(srcRow, yPlane.width, dstRow);
50
+ }
51
+ }
52
+
53
+ private:
54
+ vpx_image_t m_img;
55
+ };
56
+
57
+ } // namespace Vpx
@@ -0,0 +1,75 @@
1
+ #include "vpxdecoder.hpp"
2
+ #include "vpxcommon_impl.hpp"
3
+ #include <algorithm>
4
+ #include <stdexcept>
5
+ #include <vpx/vpx_decoder.h>
6
+ #include <vpx/vp8dx.h>
7
+
8
+ using namespace Vpx;
9
+
10
+ namespace {
11
+
12
+ constexpr vpx_codec_iface_t* decoder_vp8 = &vpx_codec_vp8_dx_algo;
13
+ constexpr vpx_codec_iface_t* decoder_vp9 = &vpx_codec_vp9_dx_algo;
14
+
15
+ struct DecCtx
16
+ {
17
+ DecCtx(const Gen gen)
18
+ {
19
+ // Create decoder context
20
+ const auto* decoder_iface = (gen == Gen::Vp8) ? decoder_vp8 : decoder_vp9;
21
+ if (vpx_codec_dec_init(&m_ctx, decoder_iface, nullptr, 0) != VPX_CODEC_OK) {
22
+ throw std::runtime_error("Failed to create decoding context");
23
+ }
24
+ }
25
+
26
+ DecCtx(const DecCtx&) = delete;
27
+ void operator=(const DecCtx&) = delete;
28
+
29
+ ~DecCtx() noexcept { vpx_codec_destroy(&m_ctx); }
30
+
31
+ constexpr operator vpx_codec_ctx_t*() noexcept { return &m_ctx; }
32
+ constexpr operator const vpx_codec_ctx_t*() const noexcept { return &m_ctx; }
33
+
34
+ private:
35
+ vpx_codec_ctx_t m_ctx;
36
+ };
37
+
38
+ } // private namespace
39
+
40
+
41
+ struct Decoder::Ctx {
42
+ Ctx(const Gen gen) : m_ctx(gen) { }
43
+
44
+ template<typename Fn> void decode(const uint8_t* data, const size_t size, Fn&& fn)
45
+ {
46
+ constexpr auto VPX_DL_REALTIME = 1;
47
+ if (vpx_codec_decode(m_ctx, data, size, nullptr, VPX_DL_REALTIME) != VPX_CODEC_OK) {
48
+ throw std::runtime_error("Failed to decode packet");
49
+ }
50
+
51
+ vpx_codec_iter_t iter = nullptr;
52
+ vpx_image* img = nullptr;
53
+ while ((img = vpx_codec_get_frame(m_ctx, &iter)) != nullptr) {
54
+ fn(Plane {
55
+ .data = img->planes[VPX_PLANE_Y],
56
+ .height = img->d_h, .width = img->d_w,
57
+ .stride = img->stride[0]
58
+ });
59
+ }
60
+ }
61
+
62
+ private:
63
+ DecCtx m_ctx;
64
+ };
65
+
66
+ Decoder::Decoder(const Gen gen)
67
+ : ctx(std::make_unique<Ctx>(gen))
68
+ { }
69
+
70
+ Decoder::~Decoder() = default;
71
+
72
+ void Decoder::decode(const uint8_t* packet, size_t size, const frame_handler_t& fn)
73
+ {
74
+ ctx->decode(packet, size, fn);
75
+ }
@@ -0,0 +1,25 @@
1
+ #pragma once
2
+ #include <memory>
3
+ #include <cstdint>
4
+ #include <functional>
5
+ #include "vpxcommon.hpp"
6
+
7
+ namespace Vpx {
8
+
9
+ struct Decoder
10
+ {
11
+ private:
12
+ struct Ctx;
13
+
14
+ public:
15
+ Decoder(Gen gen = Gen::Vp8);
16
+ ~Decoder();
17
+
18
+ using frame_handler_t = std::function<void(const Plane&)>;
19
+ void decode(const uint8_t* packet, size_t size, const frame_handler_t& fn);
20
+
21
+ private:
22
+ std::unique_ptr<Ctx> ctx;
23
+ };
24
+
25
+ } // namespace Vpx
@@ -0,0 +1,116 @@
1
+ #include "vpxencoder.hpp"
2
+ #include "vpxcommon_impl.hpp"
3
+ #include <algorithm>
4
+ #include <vpx/vpx_encoder.h>
5
+ #include <vpx/vp8cx.h>
6
+ #include <iostream>
7
+
8
+ using namespace Vpx;
9
+
10
+ namespace {
11
+
12
+ constexpr vpx_codec_iface_t* encoder_vp8 = &vpx_codec_vp8_cx_algo;
13
+ constexpr vpx_codec_iface_t* encoder_vp9 = &vpx_codec_vp9_cx_algo;
14
+
15
+ struct EncCtx
16
+ {
17
+ EncCtx(const Encoder::Config& config)
18
+ {
19
+ // Encoder config from defaults + provided settings
20
+ vpx_codec_enc_cfg_t cfg;
21
+ const auto* encoder_iface = (config.gen == Gen::Vp8) ? encoder_vp8 : encoder_vp9;
22
+ if (vpx_codec_enc_config_default(encoder_iface, &cfg, 0) != VPX_CODEC_OK) {
23
+ throw std::runtime_error("Failed to get default codec config");
24
+ }
25
+ cfg.g_w = config.width;
26
+ cfg.g_h = config.height;
27
+ cfg.g_timebase.num = 1;
28
+ cfg.g_timebase.den = config.fps;
29
+ cfg.rc_target_bitrate = config.bitrate;
30
+ cfg.g_error_resilient = 0;
31
+ cfg.g_threads = config.threads;
32
+ // Create encoder context
33
+ constexpr auto use_flags = 0;
34
+ if (vpx_codec_enc_init(&m_ctx, encoder_iface, &cfg, use_flags) != VPX_CODEC_OK) {
35
+ throw std::runtime_error("Failed to create encoding context");
36
+ }
37
+ // Set codec parameters (destroy ctx on fail)
38
+ try {
39
+ if (vpx_codec_control(&m_ctx, VP8E_SET_CPUUSED, config.cpu_used) != VPX_CODEC_OK) {
40
+ throw std::runtime_error("Failed to set CPUUSED parameter");
41
+ }
42
+ }
43
+ catch(...) {
44
+ vpx_codec_destroy(&m_ctx);
45
+ throw;
46
+ }
47
+ }
48
+
49
+ EncCtx(const EncCtx&) = delete;
50
+ void operator=(const EncCtx&) = delete;
51
+
52
+ ~EncCtx() noexcept { vpx_codec_destroy(&m_ctx); }
53
+
54
+ constexpr operator vpx_codec_ctx_t*() noexcept { return &m_ctx; }
55
+ constexpr operator const vpx_codec_ctx_t*() const noexcept { return &m_ctx; }
56
+
57
+ private:
58
+ vpx_codec_ctx_t m_ctx;
59
+ };
60
+
61
+ } // private namespace
62
+
63
+
64
+ struct Encoder::Ctx {
65
+ Ctx(const Encoder::Config& config)
66
+ : m_img(config.width, config.height)
67
+ , m_ctx(config)
68
+ { }
69
+
70
+ constexpr Vpx::Image& frame() noexcept { return m_img; }
71
+ constexpr const Vpx::Image& frame() const noexcept { return m_img; }
72
+
73
+ constexpr const auto frameIdx() const noexcept { return m_frameIdx; }
74
+
75
+ template<typename Fn> void encode(Fn&& fn)
76
+ {
77
+ constexpr vpx_enc_frame_flags_t flags = 0;
78
+ if (vpx_codec_encode(m_ctx, m_img, ++m_frameIdx, 1, flags, VPX_DL_REALTIME) != VPX_CODEC_OK) {
79
+ throw std::runtime_error("Failed to encode frame");
80
+ }
81
+
82
+ vpx_codec_iter_t iter = nullptr;
83
+ const vpx_codec_cx_pkt_t *pkt = nullptr;
84
+ while ((pkt = vpx_codec_get_cx_data(m_ctx, &iter)) != nullptr) {
85
+ if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
86
+ fn(static_cast<const uint8_t*>(pkt->data.raw.buf), pkt->data.raw.sz);
87
+ }
88
+ }
89
+ }
90
+
91
+ private:
92
+ unsigned int m_frameIdx = 0;
93
+ Vpx::Image m_img;
94
+ EncCtx m_ctx;
95
+ };
96
+
97
+ Encoder::Encoder(const Config& config)
98
+ : ctx(std::make_unique<Ctx>(config))
99
+ { }
100
+
101
+ Encoder::~Encoder() = default;
102
+
103
+ void Encoder::encode(const packet_handler_t& fn)
104
+ {
105
+ ctx->encode(fn);
106
+ }
107
+
108
+ Plane Encoder::yPlane() const noexcept
109
+ {
110
+ return ctx->frame().yPlane();
111
+ }
112
+
113
+ void Encoder::copyFromGray(const uint8_t* data)
114
+ {
115
+ ctx->frame().copyFromGrayscale(data);
116
+ }
@@ -0,0 +1,39 @@
1
+ #pragma once
2
+ #include <memory>
3
+ #include <cstdint>
4
+ #include <functional>
5
+ #include "vpxcommon.hpp"
6
+
7
+ namespace Vpx {
8
+
9
+ struct Encoder
10
+ {
11
+ private:
12
+ struct Ctx;
13
+
14
+ public:
15
+ struct Config {
16
+ unsigned int width;
17
+ unsigned int height;
18
+ unsigned int fps = 30;
19
+ unsigned int bitrate = 3000;
20
+ unsigned int threads = 0;
21
+ int cpu_used = 16;
22
+ Gen gen = Gen::Vp8;
23
+ };
24
+
25
+ Encoder(const Config& config);
26
+ ~Encoder();
27
+
28
+ Plane yPlane() const noexcept;
29
+
30
+ void copyFromGray(const uint8_t* data);
31
+
32
+ using packet_handler_t = std::function<void(const uint8_t*, size_t)>;
33
+ void encode(const packet_handler_t& fn);
34
+
35
+ private:
36
+ std::unique_ptr<Ctx> ctx;
37
+ };
38
+
39
+ } // namespace Vpx