2 Copyright (C) 2023 Grok Image Compression Inc.
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
23 #include "../config.h"
24 #include "../dcp_video.h"
27 #include "../dcpomatic_log.h"
28 #include "../writer.h"
29 #include "messenger.h"
30 #include <dcp/array_data.h>
33 static std::mutex launchMutex;
38 struct GrokLogger : public MessengerLogger {
39 explicit GrokLogger(const std::string &preamble) : MessengerLogger(preamble)
41 virtual ~GrokLogger() = default;
42 void info(const char* fmt, ...) override{
45 dcpomatic_log->log(preamble_ + log_message(fmt, arg),LogEntry::TYPE_GENERAL);
48 void warn(const char* fmt, ...) override{
51 dcpomatic_log->log(preamble_ + log_message(fmt, arg),LogEntry::TYPE_WARNING);
54 void error(const char* fmt, ...) override{
57 dcpomatic_log->log(preamble_ + log_message(fmt, arg),LogEntry::TYPE_ERROR);
63 FrameProxy(int index, Eyes eyes, DCPVideo dcpv) : index_(index), eyes_(eyes), vf(dcpv)
68 Eyes eyes(void) const {
76 struct DcpomaticContext {
78 std::shared_ptr<const Film> film,
80 EventHistory& history,
81 boost::filesystem::path const& location
93 void setDimensions(uint32_t w, uint32_t h) {
97 std::shared_ptr<const Film> film_;
99 EventHistory &history_;
100 boost::filesystem::path _location;
109 explicit GrokContext(DcpomaticContext const& dcpomatic_context)
110 : _dcpomatic_context(dcpomatic_context)
111 , messenger_(nullptr)
114 if (Config::instance()->enable_gpu ()) {
115 boost::filesystem::path folder(_dcpomatic_context._location);
116 boost::filesystem::path binaryPath = folder / "grk_compress";
117 if (!boost::filesystem::exists(binaryPath)) {
118 getMessengerLogger()->error(
119 "Invalid binary location %s", _dcpomatic_context._location.c_str()
123 auto proc = [this](const std::string& str) {
126 auto tag = msg.next();
127 if(tag == GRK_MSGR_BATCH_SUBMIT_COMPRESSED)
129 auto clientFrameId = msg.nextUint();
130 auto compressedFrameId = msg.nextUint();
131 (void)compressedFrameId;
132 auto compressedFrameLength = msg.nextUint();
134 [this](FrameProxy srcFrame, uint8_t* compressed, uint32_t compressedFrameLength)
136 auto compressed_data = std::make_shared<dcp::ArrayData>(compressed, compressedFrameLength);
137 _dcpomatic_context.writer_.write(compressed_data, srcFrame.index(), srcFrame.eyes());
140 int const minimum_size = 16384;
141 bool needsRecompression = compressedFrameLength < minimum_size;
142 messenger_->processCompressed(str, processor, needsRecompression);
143 if (needsRecompression) {
144 auto fp = messenger_->retrieve(clientFrameId);
149 auto encoded = std::make_shared<dcp::ArrayData>(fp->vf.encode_locally());
150 _dcpomatic_context.writer_.write(encoded, fp->vf.index(), fp->vf.eyes());
154 } catch (std::exception &ex){
155 getMessengerLogger()->error("%s",ex.what());
159 MessengerInit(clientToGrokMessageBuf, clientSentSynch, grokReceiveReadySynch,
160 grokToClientMessageBuf, grokSentSynch, clientReceiveReadySynch, proc,
161 std::thread::hardware_concurrency());
162 messenger_ = new ScheduledMessenger<FrameProxy>(clientInit);
168 bool launch(DCPVideo dcpv, int device){
173 std::unique_lock<std::mutex> lk_global(launchMutex);
178 if (MessengerInit::firstLaunch(true)) {
179 auto s = dcpv.get_size();
180 _dcpomatic_context.setDimensions(s.width, s.height);
181 auto config = Config::instance();
182 messenger_->launchGrok(
183 _dcpomatic_context._location,
184 _dcpomatic_context.width_,_dcpomatic_context.width_,
185 _dcpomatic_context.height_,
187 _dcpomatic_context.film_->resolution() == Resolution::FOUR_K,
188 _dcpomatic_context.film_->video_frame_rate(),
189 _dcpomatic_context.film_->j2k_bandwidth(),
190 config->gpu_license_server(),
191 config->gpu_license_port(),
192 config->gpu_license()
195 launched_ = messenger_->waitForClientInit();
199 bool scheduleCompress(DCPVideo const& vf){
203 auto fp = FrameProxy(vf.index(), vf.eyes(), vf);
204 auto cvt = [this, &fp](BufferSrc src){
206 fp.vf.convert_to_xyz((uint16_t*)src.framePtr_);
208 return messenger_->scheduleCompress(fp, cvt);
214 std::unique_lock<std::mutex> lk_global(launchMutex);
218 messenger_->shutdown();
220 messenger_ = nullptr;
223 _dcpomatic_context.history_.event();
226 DcpomaticContext _dcpomatic_context;
227 ScheduledMessenger<FrameProxy> *messenger_;