-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathmain.cpp
More file actions
161 lines (135 loc) · 5.07 KB
/
main.cpp
File metadata and controls
161 lines (135 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "BanubaClientToken.hpp"
#include <GlfwRenderer.hpp>
#include <Utils.hpp>
#include <bnb/effect_player/utility.hpp>
#include <bnb/effect_player/interfaces/types.hpp>
#include <bnb/player_api/interfaces/player/player.hpp>
#include <bnb/player_api/interfaces/input.hpp>
#include <bnb/player_api/interfaces/output/window_output.hpp>
#include <bnb/player_api/interfaces/render_target/opengl_render_target.hpp>
#include <bnb/player_api/interfaces/render_target/metal_render_target.hpp>
#include <stb_gif.hpp>
#include <thread>
#include <filesystem>
#include <chrono>
#include <atomic>
#include <mutex>
using namespace bnb::interfaces;
namespace
{
render_backend_type render_backend = render_backend_type::opengl;
}
// Custom input for gif file
class gif_stream_input : public bnb::player_api::interfaces::input
{
public:
gif_stream_input(const std::string& path)
: m_gif(path)
{
auto config = bnb::interfaces::processor_configuration::create();
m_frame_processor = bnb::interfaces::frame_processor::create_video_processor(config);
m_gif.rewind();
m_thread = std::thread([this](){;
bnb::image_format format;
format.width = m_gif.width();
format.height = m_gif.height();
format.orientation = bnb::camera_orientation::deg_0;
while (!m_quit) {
if (!m_play) {
std::this_thread::yield();
continue;
}
if (!m_gif.jump_to_next_frame()){ // End of file
m_gif.rewind();
std::this_thread::yield();
continue;
}
auto frame = m_gif.current_frame();
bnb::bpc8_image_t::pixel_format_t pixel_format{bnb::bpc8_image_t::pixel_format_t::rgba};
auto color_plane = bnb::color_plane(const_cast<bnb::color_plane_data_t*>(get_pixel_data(frame)), [frame](bnb::color_plane_data_t*) {
// Hold the copy of the frame here, unil deleter called
});
bnb::bpc8_image_t rgba_image(color_plane, pixel_format, format);
bnb::full_image_t image(std::move(rgba_image));
auto fd = bnb::interfaces::frame_data::create();
fd->add_full_img(std::move(image));
m_frame_processor->push(fd);
{
std::lock_guard<std::mutex> lock(m_mutex);
m_timestamp_us = frame.timepoint();
}
std::this_thread::sleep_for(std::chrono::milliseconds(frame.delay()));
}
});
}
~gif_stream_input()
{
m_quit = true;
m_thread.join();
}
bnb::player_api::frame_processor_sptr get_frame_processor() const noexcept override
{
return m_frame_processor;
}
uint64_t get_frame_time_us() const noexcept override
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_timestamp_us;
}
void play()
{
m_play = true;
}
void stop()
{
m_play = false;
}
private:
uint8_t* get_pixel_data(const stbi::gif::frame& frame)
{
if (!frame) {
return {};
}
return static_cast<uint8_t*>(const_cast<void*>(frame.data()));
}
uint64_t m_timestamp_us{0};
bnb::player_api::frame_processor_sptr m_frame_processor{nullptr};
std::atomic<bool> m_quit{false};
std::atomic<bool> m_play{false};
std::thread m_thread;
stbi::gif m_gif;
mutable std::mutex m_mutex;
};
int main()
{
// Initialize BanubaSDK with token and paths to resources
bnb::utility utility({bnb::sdk_resources_path(), BNB_RESOURCES_FOLDER}, BNB_CLIENT_TOKEN);
// Create render delegate based on GLFW
auto renderer = std::make_shared<GLFWRenderer>(render_backend);
// Create render target
bnb::player_api::render_target_sptr render_target;
if (render_backend == render_backend_type::opengl) {
render_target = bnb::player_api::opengl_render_target::create();
} else if (render_backend == render_backend_type::metal) {
render_target = bnb::player_api::metal_render_target::create();
}
// Create player
auto player = bnb::player_api::player::create(30, render_target, renderer);
// Create custom input for gif
auto input = std::make_shared<gif_stream_input>((std::filesystem::path(BNB_RESOURCES_FOLDER) / "face600x600.gif").string());
// on-screen output
auto window_output = bnb::player_api::window_output::create(renderer->get_native_surface());
player->use(input).use(window_output);
player->load_async("effects/TrollGrandma");
input->play();
// Setup callbacks for glfw window
// resize and on-quit events
renderer->get_window()->set_callbacks([window_output](uint32_t w, uint32_t h){
window_output->set_frame_layout(0, 0, w, h);
}, [input](){
input->stop();
});
// Run main loop
renderer->get_window()->show_window_and_run_events_loop();
return 0;
}