#include "encode_server_finder.h"
#include "player.h"
#include "player_video.h"
+#include "timer.h"
#include "encode_server_description.h"
#include "compose.hpp"
#include <libcxml/cxml.h>
#include <boost/foreach.hpp>
+#include <boost/thread/barrier.hpp>
#include <iostream>
#include "i18n.h"
+using std::min;
using std::list;
using std::cout;
using std::exception;
using dcp::Data;
using namespace dcpomatic;
+/* XXX */
+#define GPU_THREADS 4
+
/** @param film Film that we are encoding.
* @param writer Writer that we are using.
*/
, _history (200)
, _cpu_backend (new J2KEncoderCPUBackend())
, _writer (writer)
+ , _gpu_barrier (GPU_THREADS)
{
servers_list_changed ();
}
/* Wait until the queue has gone down a bit. Allow one thing in the queue even
when there are no threads.
*/
- while (_queue.size() >= (threads * 2) + 1) {
+ /* XXX: needs correct handling for GPU */
+ while (_queue.size() >= (threads * 2) + 1 + 48) {
LOG_TIMING ("decoder-sleep queue=%1 threads=%2", _queue.size(), threads);
_full_condition.wait (queue_lock);
LOG_TIMING ("decoder-wake queue=%1 threads=%2", _queue.size(), threads);
LOG_DEBUG_ENCODE("Frame @ %1 J2K", to_string(time));
/* This frame already has J2K data, so just write it */
_writer->write (pv->j2k(), position, pv->eyes ());
+ /*
} else if (_last_player_video[pv->eyes()] && _writer->can_repeat(position) && pv->same (_last_player_video[pv->eyes()])) {
LOG_DEBUG_ENCODE("Frame @ %1 REPEAT", to_string(time));
_writer->repeat (position, pv->eyes ());
+ */
} else {
LOG_DEBUG_ENCODE("Frame @ %1 ENCODE", to_string(time));
+ std::cout << "queue " << to_string(time) << "\n";
/* Queue this new frame for encoding */
LOG_TIMING ("add-frame-to-queue queue=%1", _queue.size ());
_queue.push_back (shared_ptr<DCPVideo> (
LOG_TIMING ("encoder-sleep thread=%1", thread_id ());
boost::mutex::scoped_lock lock (_queue_mutex);
- while (static_cast<int>(_queue.size()) < backend->quantity()) {
+ while (_queue.empty()) {
_empty_condition.wait (lock);
}
LOG_TIMING ("encoder-wake thread=%1 queue=%2", thread_id(), _queue.size());
vector<shared_ptr<DCPVideo> > video;
- for (int i = 0; i < backend->quantity(); ++i) {
+ int to_do = min(static_cast<int>(_queue.size()), backend->quantity());
+ for (int i = 0; i < to_do; ++i) {
video.push_back (_queue.front());
_queue.pop_front();
}
block has thread interruption disabled.
*/
{
- boost::this_thread::disable_interruption dis;
+ // XXX HACK!!
+ //boost::this_thread::disable_interruption dis;
LOG_TIMING ("encoder-pop thread=%1 frames=%2 eyes=%3", thread_id(), video.size());
vector<Data> encoded = backend->encode (video);
if (!encoded.empty()) {
- DCPOMATIC_ASSERT (static_cast<int>(encoded.size()) == backend->quantity());
- for (int i = 0; i < backend->quantity(); ++i) {
+ DCPOMATIC_ASSERT (encoded.size() == video.size());
+ for (size_t i = 0; i < video.size(); ++i) {
_writer->write (encoded[i], video[i]->index(), video[i]->frame()->eyes());
}
- frames_done (backend->quantity());
+ frames_done (video.size());
} else {
lock.lock ();
LOG_GENERAL (N_("[%1] J2KEncoder thread pushes %2 frames back onto queue after failure"), thread_id(), video.size());
/* Ignore these and just stop the thread */
_full_condition.notify_all ();
}
+catch (std::exception& e)
+{
+ std::cout << "encoder thread crashed " << e.what() << "\n";
+ store_current ();
+ /* Wake anything waiting on _full_condition so it can see the exception */
+ _full_condition.notify_all ();
+}
catch (...)
{
+ std::cout << "encoder thread crashed.\n";
store_current ();
/* Wake anything waiting on _full_condition so it can see the exception */
_full_condition.notify_all ();
}
}
- shared_ptr<J2KEncoderFastvideoBackend> fastvideo(new J2KEncoderFastvideoBackend());
- _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, fastvideo));
+ for (int i = 0; i < GPU_THREADS; ++i) {
+ shared_ptr<J2KEncoderFastvideoBackend> fastvideo(new J2KEncoderFastvideoBackend(_gpu_barrier));
+ _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, fastvideo));
+ }
_writer->set_encoder_threads (_threads->size());
}
-J2KEncoderFastvideoBackend::J2KEncoderFastvideoBackend ()
- : _setup_done (false)
+J2KEncoderFastvideoBackend::J2KEncoderFastvideoBackend (boost::barrier& barrier)
+ : _barrier (barrier)
+ , _setup_done (false)
{
fastSdkParametersHandle_t sdk_parameters;
fastStatus_t r = fastGetSdkParametersHandle(&sdk_parameters);
vector<Data>
J2KEncoderFastvideoBackend::encode (vector<shared_ptr<DCPVideo> > video)
{
- DCPOMATIC_ASSERT (static_cast<int>(video.size()) == quantity());
+ DCPOMATIC_ASSERT (static_cast<int>(video.size()) <= quantity());
std::cout << "FV: " << video.size() << " from " << video.front()->index() << "\n";
+ // XXX: works most of the time, not sure how it helps (need to ask) but screws
+ // things up when we're only encoding one frame
+ //_barrier.wait();
if (!_setup_done) {
setup (video.front()->frame()->out_size());
_setup_done = true;
}
+ std::cout << "hello dolly.\n";
BOOST_FOREACH (shared_ptr<DCPVideo> i, video) {
shared_ptr<dcpomatic::Image> image = i->frame()->image(boost::bind(&PlayerVideo::keep_xyz_or_rgb, _1), true, false);
if (i->frame()->colour_conversion()) {
/* XXX */
}
+ std::cout << "here we go.\n";
fastStatus_t r = fastImportFromHostCopy(
_adapter,
_xyz_buffer,
}
- int free_slots = 0;
- fastEncoderJ2kFreeSlotsInBatch(_encoder, &free_slots);
- DCPOMATIC_ASSERT (free_slots == 0);
-
fastEncoderJ2kReport_t report;
-
fastEncoderJ2kOutput_t output;
int const max_j2k_size = 1024 * 1024 * 2;
output.bufferSize = max_j2k_size;