Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

# Copyright (c) 2013-2017, EPFL/Blue Brain Project
# Copyright (c) 2013-2018, EPFL/Blue Brain Project
# Raphael Dumusc <raphael.dumusc@epfl.ch>
# Daniel Nachbaur <daniel.nachbaur@epfl.ch>

cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(Deflect VERSION 0.14.1)
project(Deflect VERSION 1.0.0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-)

set(Deflect_VERSION_ABI 7)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/common)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Welcome to Deflect, a C++ library for streaming pixels to other Deflect-based
applications, for example [Tide](https://github.com/BlueBrain/Tide).
Deflect offers a stable API marked with version 1.7 (for the client part).
Deflect offers a stable API marked with version 1.0 (for the client part).

## Overview

Expand Down Expand Up @@ -55,5 +55,5 @@ environments are tested:
* Linux: Ubuntu 16.04 and RHEL 6 (Makefile, Ninja; x64)
* Mac OS X: 10.7 - 10.10 (Makefile, Ninja; x86_64)

The [latest API documentation](http://bluebrain.github.io/Deflect-0.14/index.html)
The [latest API documentation](http://bluebrain.github.io/Deflect-1.0/index.html)
can be found on [bluebrain.github.io](http://bluebrain.github.io).
32 changes: 8 additions & 24 deletions deflect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@

# Copyright (c) 2013-2017, EPFL/Blue Brain Project
# Copyright (c) 2013-2018, EPFL/Blue Brain Project
# Raphael Dumusc <raphael.dumusc@epfl.ch>
# Daniel Nachbaur <daniel.nachbaur@epfl.ch>

set(DEFLECT_PUBLIC_HEADERS
config.h
Event.h
EventReceiver.h
Frame.h
ImageWrapper.h
Observer.h
Segment.h
SegmentParameters.h
Server.h
SizeHints.h
Stream.h
types.h
)

set(DEFLECT_HEADERS
FrameDispatcher.h
moodycamel/blockingconcurrentqueue.h
moodycamel/concurrentqueue.h
ImageSegmenter.h
MessageHeader.h
MTQueue.h
NetworkProtocol.h
ReceiveBuffer.h
ServerWorker.h
Segment.h
SegmentParameters.h
Socket.h
SourceBuffer.h
StreamPrivate.h
TaskBuilder.h
)

set(DEFLECT_SOURCES
Event.cpp
Frame.cpp
FrameDispatcher.cpp
ImageSegmenter.cpp
ImageWrapper.cpp
MessageHeader.cpp
MetaTypeRegistration.cpp
Observer.cpp
ReceiveBuffer.cpp
Server.cpp
ServerWorker.cpp
Socket.cpp
SourceBuffer.cpp
Stream.cpp
StreamPrivate.cpp
StreamSendWorker.cpp
Expand All @@ -61,23 +49,19 @@ if(APPLE)
endif()

if(DEFLECT_USE_LIBJPEGTURBO)
list(APPEND DEFLECT_PUBLIC_HEADERS
SegmentDecoder.h
)
list(APPEND DEFLECT_HEADERS
ImageJpegCompressor.h
ImageJpegDecompressor.h
)
list(APPEND DEFLECT_SOURCES
ImageJpegCompressor.cpp
ImageJpegDecompressor.cpp
SegmentDecoder.cpp
)
list(APPEND DEFLECT_LINK_LIBRARIES ${LibJpegTurbo_LIBRARIES})
list(APPEND DEFLECT_LINK_LIBRARIES PRIVATE ${LibJpegTurbo_LIBRARIES})
endif()

common_library(Deflect)

add_subdirectory(server)

if(Qt5Qml_FOUND AND Qt5Quick_FOUND AND NOT Qt5Quick_VERSION VERSION_LESS 5.4)
add_subdirectory(qt)
endif()
46 changes: 15 additions & 31 deletions deflect/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,48 +144,32 @@ struct Event
};

/** The type of event */
EventType type;
EventType type = EVT_NONE;

/** @name Mouse and touch events */
//@{
double mouseX; /**< Normalized X mouse/touch position relative to the
window */
double mouseY; /**< Normalized Y mouse/touch position relative to the
window */
double dx; /**< Normalized horizontal delta for pan/pinch events /
delta in pixels for wheel events */
double dy; /**< Normalized vertical delta for pan/pinch events /
delta in pixels for wheel events */
bool mouseLeft; /**< State of the left mouse button (pressed=true) */
bool mouseRight; /**< State of the right mouse button (pressed=true) */
bool mouseMiddle; /**< State of the middle mouse button (pressed=true) */
double mouseX = 0.0; /**< Normalized X mouse/touch position relative to the
window */
double mouseY = 0.0; /**< Normalized Y mouse/touch position relative to the
window */
double dx = 0.0; /**< Normalized horizontal delta for pan/pinch events /
delta in pixels for wheel events */
double dy = 0.0; /**< Normalized vertical delta for pan/pinch events /
delta in pixels for wheel events */
bool mouseLeft = false; /**< State of left mouse button (pressed=true) */
bool mouseRight = false; /**< State of right mouse button (pressed=true) */
bool mouseMiddle = false; /**< State of middle mouse button (pressed=true)*/
//@}

/** @name Keyboard events */
//@{
int key; /**< The key code, see QKeyEvent::key() / number of fingers
int key = 0; /**< The key code, see QKeyEvent::key() / number of fingers
for gestures / point id for touch events */
int modifiers; /**< The keyboard modifiers, see QKeyEvent::modifiers() */
int modifiers = 0; /**< The keyboard modifiers, see QKeyEvent::modifiers()*/
char text[UNICODE_TEXT_SIZE]; /**< Carries unicode for key, see
QKeyEvent::text() */
QKeyEvent::text() */
//@}

/** Construct a new event. @version 1.0 */
Event()
: type(EVT_NONE)
, mouseX(0)
, mouseY(0)
, dx(0)
, dy(0)
, mouseLeft(false)
, mouseRight(false)
, mouseMiddle(false)
, key(0)
, modifiers(0)
, text()
{
}

/** The size of the QDataStream serialized output. */
static const uint32_t serializedSize;
};
Expand Down
2 changes: 1 addition & 1 deletion deflect/ImageJpegCompressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
namespace deflect
{
/**
* Perform JPEG compression for a PixelStreamSegment
* Perform JPEG compression for a region of an image.
*/
class ImageJpegCompressor
{
Expand Down
39 changes: 21 additions & 18 deletions deflect/ImageSegmenter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************/
/* Copyright (c) 2013-2017, EPFL/Blue Brain Project */
/* Copyright (c) 2013-2018, EPFL/Blue Brain Project */
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
/* Stefan.Eilemann@epfl.ch */
/* All rights reserved. */
Expand Down Expand Up @@ -53,14 +53,11 @@

namespace deflect
{
namespace
{
bool _isOnRightSideOfSideBySideImage(const Segment& segment)
bool ImageSegmenter::_isOnRightSideOfSideBySideImage(const SegmentTask& segment)
{
return segment.sourceImage->view == View::side_by_side &&
segment.view == View::right_eye;
}
}

bool ImageSegmenter::generate(const ImageWrapper& image, Handler handler)
{
Expand All @@ -71,7 +68,7 @@ bool ImageSegmenter::generate(const ImageWrapper& image, Handler handler)

Segment ImageSegmenter::createSingleSegment(const ImageWrapper& image)
{
auto segments = _generateSegments(image);
auto segments = _generateSegmentTasks(image);
if (segments.size() > 1)
throw std::runtime_error(
"createSingleSegment only works for small images");
Expand All @@ -83,7 +80,7 @@ Segment ImageSegmenter::createSingleSegment(const ImageWrapper& image)
segment.imageData.reserve(segment.parameters.width *
segment.parameters.height *
image.getBytesPerPixel());
segment.parameters.dataType = DataType::rgba;
segment.parameters.format = Format::rgba;
segment.imageData.append((const char*)image.data,
int(image.getBufferSize()));
}
Expand Down Expand Up @@ -114,7 +111,7 @@ bool ImageSegmenter::_generateJpeg(const ImageWrapper& image,
{
#ifdef DEFLECT_USE_LIBJPEGTURBO
// The resulting Jpeg segments
auto segments = _generateSegments(image);
auto segments = _generateSegmentTasks(image);

// start creating JPEGs for each segment, in parallel
QtConcurrent::map(segments, std::bind(&ImageSegmenter::_computeJpeg, this,
Expand All @@ -129,8 +126,13 @@ bool ImageSegmenter::_generateJpeg(const ImageWrapper& image,
{
bool result = true;
for (; i < segments.size(); ++i)
if (!handler(_sendQueue.dequeue()))
{
const auto segment = _sendQueue.dequeue();
if (segment.exception)
std::rethrow_exception(segment.exception);
if (!handler(segment))
result = false;
}
return result;
}
catch (...)
Expand All @@ -155,7 +157,7 @@ bool ImageSegmenter::_generateJpeg(const ImageWrapper& image,
#endif
}

void ImageSegmenter::_computeJpeg(Segment& segment, const bool sendSegment)
void ImageSegmenter::_computeJpeg(SegmentTask& segment, const bool sendSegment)
{
#ifdef DEFLECT_USE_LIBJPEGTURBO
QRect imageRegion(segment.parameters.x - segment.sourceImage->x,
Expand All @@ -179,7 +181,7 @@ void ImageSegmenter::_computeJpeg(Segment& segment, const bool sendSegment)
segment.exception = std::current_exception();
}

segment.parameters.dataType = DataType::jpeg;
segment.parameters.format = Format::jpeg;
if (sendSegment)
_sendQueue.enqueue(segment);
#endif
Expand All @@ -188,13 +190,13 @@ void ImageSegmenter::_computeJpeg(Segment& segment, const bool sendSegment)
bool ImageSegmenter::_generateRaw(const ImageWrapper& image,
const Handler& handler) const
{
auto segments = _generateSegments(image);
auto segments = _generateSegmentTasks(image);
for (auto& segment : segments)
{
segment.imageData.reserve(segment.parameters.width *
segment.parameters.height *
image.getBytesPerPixel());
segment.parameters.dataType = DataType::rgba;
segment.parameters.format = Format::rgba;

if (segments.size() == 1)
{
Expand Down Expand Up @@ -230,17 +232,18 @@ bool ImageSegmenter::_generateRaw(const ImageWrapper& image,
return true;
}

Segments ImageSegmenter::_generateSegments(const ImageWrapper& image) const
ImageSegmenter::SegmentTasks ImageSegmenter::_generateSegmentTasks(
const ImageWrapper& image) const
{
Segments segments;
SegmentTasks segments;
for (const auto& params : _makeSegmentParameters(image))
{
Segment segment;
SegmentTask segment;
segment.parameters = params;
segment.view =
image.view == View::side_by_side ? View::left_eye : image.view;
segment.sourceImage = &image;
segment.rowOrder = image.rowOrder;
segment.sourceImage = &image;
segments.push_back(segment);
}

Expand All @@ -262,7 +265,7 @@ Segments ImageSegmenter::_generateSegments(const ImageWrapper& image) const
return segments;
}

SegmentParametersList ImageSegmenter::_makeSegmentParameters(
ImageSegmenter::SegmentParametersList ImageSegmenter::_makeSegmentParameters(
const ImageWrapper& image) const
{
const auto info = _makeSegmentationInfo(image);
Expand Down
31 changes: 22 additions & 9 deletions deflect/ImageSegmenter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*********************************************************************/
/* Copyright (c) 2013-2017, EPFL/Blue Brain Project */
/* Copyright (c) 2013-2018, EPFL/Blue Brain Project */
/* Raphael Dumusc <raphael.dumusc@epfl.ch> */
/* Stefan.Eilemann@epfl.ch */
/* All rights reserved. */
Expand Down Expand Up @@ -66,13 +66,13 @@ class ImageSegmenter
/**
* Generate segments.
*
* The generation might be parallelized, calling the handler function
* concurrently in multiple threads for different segments. When one handler
* fails, the remaining handlers may or may not be executed.
* The generation might be parallelized, but the Handler callback is always
* executed from the calling thread. When one handle() fails, the remaining
* handle() calls may or may not be executed.
*
* @param image The image to be segmented
* @param image The image to be segmented.
* @param handler the function to handle the generated segment.
* @return true if all image handlers returned true, false on failure
* @return true if all image handlers returned true, false on failure.
* @see setNominalSegmentDimensions()
*/
DEFLECT_API bool generate(const ImageWrapper& image, Handler handler);
Expand Down Expand Up @@ -117,19 +117,32 @@ class ImageSegmenter
uint lastHeight = 0;
};

struct SegmentTask : Segment
{
/** Uncompressed source image used for compression */
const ImageWrapper* sourceImage = nullptr;

/** Holds potential exception from compression thread */
std::exception_ptr exception;
};
static bool _isOnRightSideOfSideBySideImage(const SegmentTask& segment);

bool _generateJpeg(const ImageWrapper& image, const Handler& handler);
void _computeJpeg(Segment& task, bool sendSegment);
void _computeJpeg(SegmentTask& segment, bool sendSegment);
bool _generateRaw(const ImageWrapper& image, const Handler& handler) const;

Segments _generateSegments(const ImageWrapper& image) const;
using SegmentTasks = std::vector<SegmentTask>;
SegmentTasks _generateSegmentTasks(const ImageWrapper& image) const;

using SegmentParametersList = std::vector<SegmentParameters>;
SegmentParametersList _makeSegmentParameters(
const ImageWrapper& image) const;
SegmentationInfo _makeSegmentationInfo(const ImageWrapper& image) const;

uint _nominalSegmentWidth = 0;
uint _nominalSegmentHeight = 0;

MTQueue<Segment> _sendQueue;
MTQueue<SegmentTask> _sendQueue;
};
}
#endif
Loading