Abstraction of semaphore to a class
This commit is contained in:
parent
1e3b38f777
commit
4f1e1fa1d7
8 changed files with 809 additions and 216 deletions
69
Doxyfile
69
Doxyfile
|
@ -1,4 +1,4 @@
|
||||||
# Doxyfile 1.8.6
|
# Doxyfile 1.8.7
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
|
@ -70,6 +70,14 @@ OUTPUT_DIRECTORY = ./docs
|
||||||
|
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
|
|
||||||
|
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
|
||||||
|
# characters to appear in the names of generated files. If set to NO, non-ASCII
|
||||||
|
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
|
||||||
|
# U+3044.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
|
||||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||||
# documentation generated by doxygen is written. Doxygen will use this
|
# documentation generated by doxygen is written. Doxygen will use this
|
||||||
# information to generate all constant output in the proper language.
|
# information to generate all constant output in the proper language.
|
||||||
|
@ -261,9 +269,12 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
|
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||||
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
|
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||||
# (default is Fortran), use: inc=Fortran f=C.
|
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||||
|
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||||
|
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||||
|
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note For files without extension you can use no_extension as a placeholder.
|
# Note For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
|
@ -1230,7 +1241,8 @@ GENERATE_CHI = NO
|
||||||
CHM_INDEX_ENCODING =
|
CHM_INDEX_ENCODING =
|
||||||
|
|
||||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
||||||
# YES) or a normal table of contents ( NO) in the .chm file.
|
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
|
||||||
|
# enables the Previous and Next buttons.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
|
@ -1470,11 +1482,11 @@ SEARCHENGINE = YES
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using Javascript. There
|
||||||
# are two flavours of web server based searching depending on the
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# searching and an index file used by the script. When EXTERNAL_SEARCH is
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
# enabled the indexing and searching needs to be provided by external tools. See
|
# and searching needs to be provided by external tools. See the section
|
||||||
# the section "External Indexing and Searching" for details.
|
# "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
|
@ -1762,6 +1774,13 @@ MAN_OUTPUT = man
|
||||||
|
|
||||||
MAN_EXTENSION = .3
|
MAN_EXTENSION = .3
|
||||||
|
|
||||||
|
# The MAN_SUBDIR tag determines the name of the directory created within
|
||||||
|
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
|
||||||
|
# MAN_EXTENSION with the initial . removed.
|
||||||
|
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||||
|
|
||||||
|
MAN_SUBDIR =
|
||||||
|
|
||||||
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
||||||
# will generate one additional man file for each entity documented in the real
|
# will generate one additional man file for each entity documented in the real
|
||||||
# man page(s). These additional files only source the real man page, but without
|
# man page(s). These additional files only source the real man page, but without
|
||||||
|
@ -1789,18 +1808,6 @@ GENERATE_XML = NO
|
||||||
|
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
|
|
||||||
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
|
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_SCHEMA =
|
|
||||||
|
|
||||||
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_DTD =
|
|
||||||
|
|
||||||
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
||||||
# listings (including syntax highlighting and cross-referencing information) to
|
# listings (including syntax highlighting and cross-referencing information) to
|
||||||
# the XML output. Note that enabling this will significantly increase the size
|
# the XML output. Note that enabling this will significantly increase the size
|
||||||
|
@ -1947,9 +1954,9 @@ PREDEFINED =
|
||||||
EXPAND_AS_DEFINED =
|
EXPAND_AS_DEFINED =
|
||||||
|
|
||||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||||
# remove all refrences to function-like macros that are alone on a line, have an
|
# remove all references to function-like macros that are alone on a line, have
|
||||||
# all uppercase name, and do not end with a semicolon. Such function macros are
|
# an all uppercase name, and do not end with a semicolon. Such function macros
|
||||||
# typically used for boiler-plate code, and will confuse the parser if not
|
# are typically used for boiler-plate code, and will confuse the parser if not
|
||||||
# removed.
|
# removed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
@ -1969,7 +1976,7 @@ SKIP_FUNCTION_MACROS = YES
|
||||||
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
||||||
# section "Linking to external documentation" for more information about the use
|
# section "Linking to external documentation" for more information about the use
|
||||||
# of tag files.
|
# of tag files.
|
||||||
# Note: Each tag file must have an unique name (where the name does NOT include
|
# Note: Each tag file must have a unique name (where the name does NOT include
|
||||||
# the path). If a tag file is not located in the directory in which doxygen is
|
# the path). If a tag file is not located in the directory in which doxygen is
|
||||||
# run, you must also specify the path to the tagfile here.
|
# run, you must also specify the path to the tagfile here.
|
||||||
|
|
||||||
|
@ -2061,6 +2068,16 @@ HAVE_DOT = NO
|
||||||
|
|
||||||
DOT_NUM_THREADS = 0
|
DOT_NUM_THREADS = 0
|
||||||
|
|
||||||
|
# When you want a differently looking font n the dot files that doxygen
|
||||||
|
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||||
|
# sure dot is able to find the font, which can be done by putting it in a
|
||||||
|
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||||
|
# setting DOT_FONTPATH to the directory containing the font.
|
||||||
|
# The default value is: Helvetica.
|
||||||
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
DOT_FONTNAME = Helvetica
|
||||||
|
|
||||||
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
|
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
|
||||||
# dot graphs.
|
# dot graphs.
|
||||||
# Minimum value: 4, maximum value: 24, default value: 10.
|
# Minimum value: 4, maximum value: 24, default value: 10.
|
||||||
|
|
|
@ -12,10 +12,17 @@
|
||||||
|
|
||||||
namespace Converter {
|
namespace Converter {
|
||||||
|
|
||||||
|
///\brief The base constructor
|
||||||
Converter::Converter(){
|
Converter::Converter(){
|
||||||
fillFFMpegEncoders();
|
fillFFMpegEncoders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief A function that fill the internal variables with values provided by examing ffmpeg output
|
||||||
|
///
|
||||||
|
///Checks for the following encoders:
|
||||||
|
/// - AAC
|
||||||
|
/// - H264
|
||||||
|
/// - MP3
|
||||||
void Converter::fillFFMpegEncoders(){
|
void Converter::fillFFMpegEncoders(){
|
||||||
std::vector<char*> cmd;
|
std::vector<char*> cmd;
|
||||||
cmd.reserve(3);
|
cmd.reserve(3);
|
||||||
|
@ -45,10 +52,14 @@ namespace Converter {
|
||||||
fclose( outFile );
|
fclose( outFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief A function to obtain all available codecs that have been obtained from the encoders.
|
||||||
|
///\return A reference to the allCodecs member.
|
||||||
converterInfo & Converter::getCodecs(){
|
converterInfo & Converter::getCodecs(){
|
||||||
return allCodecs;
|
return allCodecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief A function to obtain the available encoders in JSON format.
|
||||||
|
///\return A JSON::Value containing all encoder:codec pairs.
|
||||||
JSON::Value Converter::getEncoders(){
|
JSON::Value Converter::getEncoders(){
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){
|
for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){
|
||||||
|
@ -64,6 +75,9 @@ namespace Converter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Looks in a given path for all files that could be converted
|
||||||
|
///\param myPath The location to look at, this should be a folder.
|
||||||
|
///\return A JSON::Value containing all media files in the location, with their corresponding metadata values.
|
||||||
JSON::Value Converter::queryPath(std::string myPath){
|
JSON::Value Converter::queryPath(std::string myPath){
|
||||||
char const * cmd[3] = {0, 0, 0};
|
char const * cmd[3] = {0, 0, 0};
|
||||||
std::string mistPath = Util::getMyPath() + "MistInfo";
|
std::string mistPath = Util::getMyPath() + "MistInfo";
|
||||||
|
@ -89,6 +103,20 @@ namespace Converter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Start a conversion with the given parameters
|
||||||
|
///\param name The name to use for logging the conversion.
|
||||||
|
///\param parameters The parameters, accepted are the following:
|
||||||
|
/// - input The input url
|
||||||
|
/// - output The output url
|
||||||
|
/// - encoder The encoder to use
|
||||||
|
/// - video An object containing video parameters, if not existant no video will be output. Values are:
|
||||||
|
/// - width The width of the resulting video
|
||||||
|
/// - height The height of the resulting video
|
||||||
|
/// - codec The codec to encode video in, or copy to use the current codec
|
||||||
|
/// - fpks The framerate in fps * 1000
|
||||||
|
/// - audio An object containing audio parameters, if not existant no audio will be output. Values are:
|
||||||
|
/// - codec The codec to encode audio in, or copy to use the current codec
|
||||||
|
/// - samplerate The target samplerate for the audio, in hz
|
||||||
void Converter::startConversion(std::string name, JSON::Value parameters) {
|
void Converter::startConversion(std::string name, JSON::Value parameters) {
|
||||||
if ( !parameters.isMember("input")){
|
if ( !parameters.isMember("input")){
|
||||||
statusHistory[name] = "No input file supplied";
|
statusHistory[name] = "No input file supplied";
|
||||||
|
@ -185,6 +213,9 @@ namespace Converter {
|
||||||
allConversions[name]["status"]["time"] = 0;
|
allConversions[name]["status"]["time"] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Updates the internal status of the converter class.
|
||||||
|
///
|
||||||
|
///Will check for each running conversion whether it is still running, and update its status accordingly
|
||||||
void Converter::updateStatus(){
|
void Converter::updateStatus(){
|
||||||
if (allConversions.size()){
|
if (allConversions.size()){
|
||||||
std::map<std::string,JSON::Value>::iterator cIt;
|
std::map<std::string,JSON::Value>::iterator cIt;
|
||||||
|
@ -249,6 +280,11 @@ namespace Converter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Parses a single ffmpeg status line into a JSON format
|
||||||
|
///\param statusLine The current status of ffmpeg
|
||||||
|
///\return A JSON::Value with the following values set:
|
||||||
|
/// - frame The current last encoded frame
|
||||||
|
/// - time The current last encoded timestamp
|
||||||
JSON::Value Converter::parseFFMpegStatus(std::string statusLine){
|
JSON::Value Converter::parseFFMpegStatus(std::string statusLine){
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
int curOffset = statusLine.find("frame=") + 6;
|
int curOffset = statusLine.find("frame=") + 6;
|
||||||
|
@ -263,6 +299,8 @@ namespace Converter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Obtain the current internal status of the conversion class
|
||||||
|
///\return A JSON::Value with the status of each conversion
|
||||||
JSON::Value Converter::getStatus(){
|
JSON::Value Converter::getStatus(){
|
||||||
updateStatus();
|
updateStatus();
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
|
@ -281,6 +319,7 @@ namespace Converter {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Clears the status history of all conversions
|
||||||
void Converter::clearStatus(){
|
void Converter::clearStatus(){
|
||||||
statusHistory.clear();
|
statusHistory.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,15 @@
|
||||||
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
|
///\brief A typedef to simplify accessing all codecs
|
||||||
typedef std::map<std::string,std::string> codecInfo;
|
typedef std::map<std::string,std::string> codecInfo;
|
||||||
|
///\brief A typedef to simplify accessing all encoders
|
||||||
typedef std::map<std::string,codecInfo> converterInfo;
|
typedef std::map<std::string,codecInfo> converterInfo;
|
||||||
|
|
||||||
|
///\brief A namespace containing all functions for handling the conversion API
|
||||||
namespace Converter {
|
namespace Converter {
|
||||||
|
|
||||||
|
///\brief A class containing the basic conversion API functionality
|
||||||
class Converter {
|
class Converter {
|
||||||
public:
|
public:
|
||||||
Converter();
|
Converter();
|
||||||
|
@ -20,8 +25,11 @@ namespace Converter {
|
||||||
JSON::Value parseFFMpegStatus(std::string statusLine);
|
JSON::Value parseFFMpegStatus(std::string statusLine);
|
||||||
private:
|
private:
|
||||||
void fillFFMpegEncoders();
|
void fillFFMpegEncoders();
|
||||||
|
///\brief Holds a list of all current known codecs
|
||||||
converterInfo allCodecs;
|
converterInfo allCodecs;
|
||||||
|
///\brief Holds a list of all the current conversions
|
||||||
std::map<std::string,JSON::Value> allConversions;
|
std::map<std::string,JSON::Value> allConversions;
|
||||||
|
///\brief Stores the status of all conversions, and the history
|
||||||
std::map<std::string,std::string> statusHistory;
|
std::map<std::string,std::string> statusHistory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,7 @@ namespace DTSC {
|
||||||
char data[11];
|
char data[11];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///\brief Basic class for storage of a read-only track
|
||||||
class readOnlyTrack {
|
class readOnlyTrack {
|
||||||
public:
|
public:
|
||||||
readOnlyTrack();
|
readOnlyTrack();
|
||||||
|
@ -248,6 +249,7 @@ namespace DTSC {
|
||||||
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///\brief Class for storage of track data
|
||||||
class Track : public readOnlyTrack {
|
class Track : public readOnlyTrack {
|
||||||
public:
|
public:
|
||||||
Track();
|
Track();
|
||||||
|
@ -270,6 +272,7 @@ namespace DTSC {
|
||||||
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///\brief Class for storage of read-only meta data
|
||||||
class readOnlyMeta {
|
class readOnlyMeta {
|
||||||
public:
|
public:
|
||||||
readOnlyMeta();
|
readOnlyMeta();
|
||||||
|
@ -291,6 +294,7 @@ namespace DTSC {
|
||||||
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///\brief Class for storage of meta data
|
||||||
class Meta : public readOnlyMeta {
|
class Meta : public readOnlyMeta {
|
||||||
public:
|
public:
|
||||||
Meta();
|
Meta();
|
||||||
|
|
142
lib/dtscmeta.cpp
142
lib/dtscmeta.cpp
|
@ -115,6 +115,7 @@ namespace DTSC {
|
||||||
|
|
||||||
/// Internally used resize function for when operating in copy mode and the internal buffer is too small.
|
/// Internally used resize function for when operating in copy mode and the internal buffer is too small.
|
||||||
/// It will only resize up, never down.
|
/// It will only resize up, never down.
|
||||||
|
///\param len The length th scale the buffer up to if necessary
|
||||||
void Packet::resize(unsigned int len) {
|
void Packet::resize(unsigned int len) {
|
||||||
if (master && len > bufferLen) {
|
if (master && len > bufferLen) {
|
||||||
char * tmp = (char *)realloc(data, len);
|
char * tmp = (char *)realloc(data, len);
|
||||||
|
@ -127,6 +128,10 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Initializes a packet with new data
|
||||||
|
///\param data_ The new data for the packet
|
||||||
|
///\param len The length of the data pointed to by data_
|
||||||
|
///\param noCopy Determines whether to make a copy or not
|
||||||
void Packet::reInit(const char * data_, unsigned int len, bool noCopy) {
|
void Packet::reInit(const char * data_, unsigned int len, bool noCopy) {
|
||||||
if (!data_){
|
if (!data_){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "ReInit received a null pointer with len %d, ignoring", len);
|
DEBUG_MSG(DLVL_DEVEL, "ReInit received a null pointer with len %d, ignoring", len);
|
||||||
|
@ -240,6 +245,9 @@ namespace DTSC {
|
||||||
return (char*)1;//out of packet! 1 == error
|
return (char*)1;//out of packet! 1 == error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Locates an identifier within the payload
|
||||||
|
///\param identifier The identifier to find
|
||||||
|
///\return A pointer to the location of the identifier
|
||||||
char * Packet::findIdentifier(const char * identifier){
|
char * Packet::findIdentifier(const char * identifier){
|
||||||
char * p = data;
|
char * p = data;
|
||||||
if (version == DTSC_V2){
|
if (version == DTSC_V2){
|
||||||
|
@ -251,6 +259,10 @@ namespace DTSC {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as a string
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\param result A location on which the string will be returned
|
||||||
|
///\param len An integer in which the length of the string will be returned
|
||||||
void Packet::getString(const char * identifier, char *& result, int & len) {
|
void Packet::getString(const char * identifier, char *& result, int & len) {
|
||||||
char * pos = findIdentifier(identifier);
|
char * pos = findIdentifier(identifier);
|
||||||
if (pos < (char*)2) {
|
if (pos < (char*)2) {
|
||||||
|
@ -267,6 +279,9 @@ namespace DTSC {
|
||||||
len = ntohl(((int *)(pos + 1))[0]);
|
len = ntohl(((int *)(pos + 1))[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as a string
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\param result The string in which to store the result
|
||||||
void Packet::getString(const char * identifier, std::string & result) {
|
void Packet::getString(const char * identifier, std::string & result) {
|
||||||
char * data = NULL;
|
char * data = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
@ -274,6 +289,9 @@ namespace DTSC {
|
||||||
result = std::string(data, len);
|
result = std::string(data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as an integer
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\param result The result is stored in this integer
|
||||||
void Packet::getInt(const char * identifier, int & result) {
|
void Packet::getInt(const char * identifier, int & result) {
|
||||||
char * pos = findIdentifier(identifier);
|
char * pos = findIdentifier(identifier);
|
||||||
if (pos < (char*)2) {
|
if (pos < (char*)2) {
|
||||||
|
@ -287,28 +305,42 @@ namespace DTSC {
|
||||||
result = ((long long int)pos[1] << 56) | ((long long int)pos[2] << 48) | ((long long int)pos[3] << 40) | ((long long int)pos[4] << 32) | ((long long int)pos[5] << 24) | ((long long int)pos[6] << 16) | ((long long int)pos[7] << 8) | pos[8];
|
result = ((long long int)pos[1] << 56) | ((long long int)pos[2] << 48) | ((long long int)pos[3] << 40) | ((long long int)pos[4] << 32) | ((long long int)pos[5] << 24) | ((long long int)pos[6] << 16) | ((long long int)pos[7] << 8) | pos[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as an integer
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\result The requested parameter as an integer
|
||||||
int Packet::getInt(const char * identifier) {
|
int Packet::getInt(const char * identifier) {
|
||||||
int result;
|
int result;
|
||||||
getInt(identifier, result);
|
getInt(identifier, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as a boolean
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\param result The result is stored in this boolean
|
||||||
void Packet::getFlag(const char * identifier, bool & result) {
|
void Packet::getFlag(const char * identifier, bool & result) {
|
||||||
int result_;
|
int result_;
|
||||||
getInt(identifier, result_);
|
getInt(identifier, result_);
|
||||||
result = (bool)result_;
|
result = (bool)result_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retrieves a single parameter as a boolean
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\result The requested parameter as a boolean
|
||||||
bool Packet::getFlag(const char * identifier) {
|
bool Packet::getFlag(const char * identifier) {
|
||||||
bool result;
|
bool result;
|
||||||
getFlag(identifier, result);
|
getFlag(identifier, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Checks whether a parameter exists
|
||||||
|
///\param identifier The name of the parameter
|
||||||
|
///\result Whether the parameter exists or not
|
||||||
bool Packet::hasMember(const char * identifier) {
|
bool Packet::hasMember(const char * identifier) {
|
||||||
return findIdentifier(identifier) > (char*)2;
|
return findIdentifier(identifier) > (char*)2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the timestamp of the packet.
|
||||||
|
///\return The timestamp of this packet.
|
||||||
long long unsigned int Packet::getTime() {
|
long long unsigned int Packet::getTime() {
|
||||||
if (version != DTSC_V2){
|
if (version != DTSC_V2){
|
||||||
if (!data){return 0;}
|
if (!data){return 0;}
|
||||||
|
@ -317,6 +349,8 @@ namespace DTSC {
|
||||||
return ((long long int)ntohl(((int *)(data + 12))[0]) << 32) | ntohl(((int *)(data + 12))[1]);
|
return ((long long int)ntohl(((int *)(data + 12))[0]) << 32) | ntohl(((int *)(data + 12))[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the track id of the packet.
|
||||||
|
///\return The track id of this packet.
|
||||||
long int Packet::getTrackId() {
|
long int Packet::getTrackId() {
|
||||||
if (version != DTSC_V2){
|
if (version != DTSC_V2){
|
||||||
return getInt("trackid");
|
return getInt("trackid");
|
||||||
|
@ -324,15 +358,21 @@ namespace DTSC {
|
||||||
return ntohl(((int *)data)[2]);
|
return ntohl(((int *)data)[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns a pointer to the payload of this packet.
|
||||||
|
///\return A pointer to the payload of this packet.
|
||||||
char * Packet::getData() {
|
char * Packet::getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the size of the payload of this packet.
|
||||||
|
///\return The size of the payload of this packet.
|
||||||
int Packet::getDataLen() {
|
int Packet::getDataLen() {
|
||||||
return dataLen;
|
return dataLen;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts the packet into a JSON value
|
||||||
|
///\return A JSON::Value representation of this packet.
|
||||||
JSON::Value Packet::toJSON(){
|
JSON::Value Packet::toJSON(){
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
unsigned int i = 8;
|
unsigned int i = 8;
|
||||||
|
@ -346,44 +386,56 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///\brief Returns the payloadsize of a part
|
||||||
long Part::getSize() {
|
long Part::getSize() {
|
||||||
return ((long)data[0] << 16) | ((long)data[1] << 8) | data[2];
|
return ((long)data[0] << 16) | ((long)data[1] << 8) | data[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the payloadsize of a part
|
||||||
void Part::setSize(long newSize) {
|
void Part::setSize(long newSize) {
|
||||||
data[0] = (newSize & 0xFF0000) >> 16;
|
data[0] = (newSize & 0xFF0000) >> 16;
|
||||||
data[1] = (newSize & 0x00FF00) >> 8;
|
data[1] = (newSize & 0x00FF00) >> 8;
|
||||||
data[2] = (newSize & 0x0000FF);
|
data[2] = (newSize & 0x0000FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Retruns the duration of a part
|
||||||
short Part::getDuration() {
|
short Part::getDuration() {
|
||||||
return btohs(data + 3);
|
return btohs(data + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the duration of a part
|
||||||
void Part::setDuration(short newDuration) {
|
void Part::setDuration(short newDuration) {
|
||||||
htobs(data + 3, newDuration);
|
htobs(data + 3, newDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief returns the offset of a part
|
||||||
long Part::getOffset() {
|
long Part::getOffset() {
|
||||||
return btohl(data + 5);
|
return btohl(data + 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the offset of a part
|
||||||
void Part::setOffset(long newOffset) {
|
void Part::setOffset(long newOffset) {
|
||||||
htobl(data + 5, newOffset);
|
htobl(data + 5, newOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the data of a part
|
||||||
char * Part::getData() {
|
char * Part::getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a part to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
void Part::toPrettyString(std::ostream & str, int indent){
|
void Part::toPrettyString(std::ostream & str, int indent){
|
||||||
str << std::string(indent, ' ') << "Part: Size(" << getSize() << "), Dur(" << getDuration() << "), Offset(" << getOffset() << ")" << std::endl;
|
str << std::string(indent, ' ') << "Part: Size(" << getSize() << "), Dur(" << getDuration() << "), Offset(" << getOffset() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the byteposition of a keyframe
|
||||||
long long unsigned int Key::getBpos() {
|
long long unsigned int Key::getBpos() {
|
||||||
return (((long long unsigned int)data[0] << 32) | (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]);
|
return (((long long unsigned int)data[0] << 32) | (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the byteposition of a keyframe
|
||||||
void Key::setBpos(long long unsigned int newBpos) {
|
void Key::setBpos(long long unsigned int newBpos) {
|
||||||
data[4] = newBpos & 0xFF;
|
data[4] = newBpos & 0xFF;
|
||||||
data[3] = (newBpos >> 8) & 0xFF;
|
data[3] = (newBpos >> 8) & 0xFF;
|
||||||
|
@ -392,88 +444,113 @@ namespace DTSC {
|
||||||
data[0] = (newBpos >> 32) & 0xFF;
|
data[0] = (newBpos >> 32) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the byteposition of a keyframe
|
||||||
long Key::getLength() {
|
long Key::getLength() {
|
||||||
return ((data[5] << 16) | (data[6] << 8) | data[7]);
|
return ((data[5] << 16) | (data[6] << 8) | data[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the byteposition of a keyframe
|
||||||
void Key::setLength(long newLength) {
|
void Key::setLength(long newLength) {
|
||||||
data[7] = newLength & 0xFF;
|
data[7] = newLength & 0xFF;
|
||||||
data[6] = (newLength >> 8) & 0xFF;
|
data[6] = (newLength >> 8) & 0xFF;
|
||||||
data[5] = (newLength >> 16) & 0xFF;
|
data[5] = (newLength >> 16) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the number of a keyframe
|
||||||
unsigned short Key::getNumber() {
|
unsigned short Key::getNumber() {
|
||||||
return btohs(data + 8);
|
return btohs(data + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the number of a keyframe
|
||||||
void Key::setNumber(unsigned short newNumber) {
|
void Key::setNumber(unsigned short newNumber) {
|
||||||
htobs(data + 8, newNumber);
|
htobs(data + 8, newNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the number of parts of a keyframe
|
||||||
short Key::getParts() {
|
short Key::getParts() {
|
||||||
return btohs(data + 10);
|
return btohs(data + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the number of parts of a keyframe
|
||||||
void Key::setParts(short newParts) {
|
void Key::setParts(short newParts) {
|
||||||
htobs(data + 10, newParts);
|
htobs(data + 10, newParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the timestamp of a keyframe
|
||||||
long Key::getTime() {
|
long Key::getTime() {
|
||||||
return btohl(data + 12);
|
return btohl(data + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the timestamp of a keyframe
|
||||||
void Key::setTime(long newTime) {
|
void Key::setTime(long newTime) {
|
||||||
htobl(data + 12, newTime);
|
htobl(data + 12, newTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the data of this keyframe struct
|
||||||
char * Key::getData() {
|
char * Key::getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a keyframe to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
void Key::toPrettyString(std::ostream & str, int indent){
|
void Key::toPrettyString(std::ostream & str, int indent){
|
||||||
str << std::string(indent, ' ') << "Key " << getNumber() << ": Pos(" << getBpos() << "), Dur(" << getLength() << "), Parts(" << getParts() << "), Time(" << getTime() << ")" << std::endl;
|
str << std::string(indent, ' ') << "Key " << getNumber() << ": Pos(" << getBpos() << "), Dur(" << getLength() << "), Parts(" << getParts() << "), Time(" << getTime() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the duration of this fragment
|
||||||
long Fragment::getDuration() {
|
long Fragment::getDuration() {
|
||||||
return btohl(data);
|
return btohl(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the duration of this fragment
|
||||||
void Fragment::setDuration(long newDuration) {
|
void Fragment::setDuration(long newDuration) {
|
||||||
htobl(data, newDuration);
|
htobl(data, newDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the length of this fragment
|
||||||
char Fragment::getLength() {
|
char Fragment::getLength() {
|
||||||
return data[4];
|
return data[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the length of this fragment
|
||||||
void Fragment::setLength(char newLength) {
|
void Fragment::setLength(char newLength) {
|
||||||
data[4] = newLength;
|
data[4] = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the number of the first keyframe in this fragment
|
||||||
short Fragment::getNumber() {
|
short Fragment::getNumber() {
|
||||||
return btohs(data + 5);
|
return btohs(data + 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the number of the first keyframe in this fragment
|
||||||
void Fragment::setNumber(short newNumber) {
|
void Fragment::setNumber(short newNumber) {
|
||||||
htobs(data + 5, newNumber);
|
htobs(data + 5, newNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns the size of a fragment
|
||||||
long Fragment::getSize() {
|
long Fragment::getSize() {
|
||||||
return btohl(data + 7);
|
return btohl(data + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Sets the size of a fragement
|
||||||
void Fragment::setSize(long newSize) {
|
void Fragment::setSize(long newSize) {
|
||||||
htobl(data + 7, newSize);
|
htobl(data + 7, newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns thte data of this fragment structure
|
||||||
char * Fragment::getData() {
|
char * Fragment::getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a fragment to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
void Fragment::toPrettyString(std::ostream & str, int indent){
|
void Fragment::toPrettyString(std::ostream & str, int indent){
|
||||||
str << std::string(indent, ' ') << "Fragment " << getNumber() << ": Dur(" << getDuration() << "), Len(" << (int)getLength() << "), Size(" << getSize() << ")" << std::endl;
|
str << std::string(indent, ' ') << "Fragment " << getNumber() << ": Dur(" << getDuration() << "), Len(" << (int)getLength() << "), Size(" << getSize() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Constructs an empty readOnlyTrack
|
||||||
readOnlyTrack::readOnlyTrack() {
|
readOnlyTrack::readOnlyTrack() {
|
||||||
fragments = NULL;
|
fragments = NULL;
|
||||||
fragLen = 0;
|
fragLen = 0;
|
||||||
|
@ -493,6 +570,7 @@ namespace DTSC {
|
||||||
fpks = 0;
|
fpks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Constructs a readOnlyTrack from a JSON::Value
|
||||||
readOnlyTrack::readOnlyTrack(JSON::Value & trackRef) {
|
readOnlyTrack::readOnlyTrack(JSON::Value & trackRef) {
|
||||||
if (trackRef.isMember("fragments") && trackRef["fragments"].isString()) {
|
if (trackRef.isMember("fragments") && trackRef["fragments"].isString()) {
|
||||||
fragments = (Fragment *)trackRef["fragments"].asStringRef().data();
|
fragments = (Fragment *)trackRef["fragments"].asStringRef().data();
|
||||||
|
@ -539,6 +617,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Constructs an empty track
|
||||||
Track::Track() {
|
Track::Track() {
|
||||||
trackID = 0;
|
trackID = 0;
|
||||||
firstms = 0;
|
firstms = 0;
|
||||||
|
@ -553,6 +632,7 @@ namespace DTSC {
|
||||||
fpks = 0;
|
fpks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Constructs a track from a readOnlyTrack
|
||||||
Track::Track(const readOnlyTrack & rhs) {
|
Track::Track(const readOnlyTrack & rhs) {
|
||||||
trackID = rhs.trackID;
|
trackID = rhs.trackID;
|
||||||
firstms = rhs.firstms;
|
firstms = rhs.firstms;
|
||||||
|
@ -581,6 +661,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Constructs a track from a JSON::Value
|
||||||
Track::Track(JSON::Value & trackRef) {
|
Track::Track(JSON::Value & trackRef) {
|
||||||
if (trackRef.isMember("fragments") && trackRef["fragments"].isString()) {
|
if (trackRef.isMember("fragments") && trackRef["fragments"].isString()) {
|
||||||
Fragment * tmp = (Fragment *)trackRef["fragments"].asStringRef().data();
|
Fragment * tmp = (Fragment *)trackRef["fragments"].asStringRef().data();
|
||||||
|
@ -618,6 +699,9 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Updates a track and its metadata given a DTSC::Packet.
|
||||||
|
///
|
||||||
|
///Will also insert keyframes on non-video tracks, and creates fragments
|
||||||
void Track::update(DTSC::Packet & pack) {
|
void Track::update(DTSC::Packet & pack) {
|
||||||
if (pack.getTime() < lastms) {
|
if (pack.getTime() < lastms) {
|
||||||
DEBUG_MSG(DLVL_WARN, "Received packets for track %d in wrong order (%d < %d) - ignoring!", (int)trackID, (int)pack.getTime(), (int)lastms);
|
DEBUG_MSG(DLVL_WARN, "Received packets for track %d in wrong order (%d < %d) - ignoring!", (int)trackID, (int)pack.getTime(), (int)lastms);
|
||||||
|
@ -679,6 +763,9 @@ namespace DTSC {
|
||||||
fragments.rbegin()->setSize(fragments.rbegin()->getSize() + dataLen);
|
fragments.rbegin()->setSize(fragments.rbegin()->getSize() + dataLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Updates a track and its metadata given a JSON::Value
|
||||||
|
///
|
||||||
|
///Will also insert keyframes on non-video tracks, and creates fragments
|
||||||
void Track::update(JSON::Value & pack) {
|
void Track::update(JSON::Value & pack) {
|
||||||
if (pack["time"].asInt() < lastms) {
|
if (pack["time"].asInt() < lastms) {
|
||||||
DEBUG_MSG(DLVL_WARN, "Received packets for track %d in wrong order (%d < %d) - ignoring!", (int)trackID, (int)pack["time"].asInt(), (int)lastms);
|
DEBUG_MSG(DLVL_WARN, "Received packets for track %d in wrong order (%d < %d) - ignoring!", (int)trackID, (int)pack["time"].asInt(), (int)lastms);
|
||||||
|
@ -737,6 +824,7 @@ namespace DTSC {
|
||||||
fragments.rbegin()->setSize(fragments.rbegin()->getSize() + pack["data"].asStringRef().size());
|
fragments.rbegin()->setSize(fragments.rbegin()->getSize() + pack["data"].asStringRef().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns a key given its number, or an empty key if the number is out of bounds
|
||||||
Key & Track::getKey(unsigned int keyNum) {
|
Key & Track::getKey(unsigned int keyNum) {
|
||||||
static Key empty;
|
static Key empty;
|
||||||
if (keyNum < keys[0].getNumber()) {
|
if (keyNum < keys[0].getNumber()) {
|
||||||
|
@ -748,6 +836,7 @@ namespace DTSC {
|
||||||
return keys[keyNum - keys[0].getNumber()];
|
return keys[keyNum - keys[0].getNumber()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns a unique identifier for a track
|
||||||
std::string readOnlyTrack::getIdentifier() {
|
std::string readOnlyTrack::getIdentifier() {
|
||||||
std::stringstream result;
|
std::stringstream result;
|
||||||
if (type == "") {
|
if (type == "") {
|
||||||
|
@ -766,12 +855,14 @@ namespace DTSC {
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns a writable identifier for a track, to prevent overwrites on readout
|
||||||
std::string readOnlyTrack::getWritableIdentifier() {
|
std::string readOnlyTrack::getWritableIdentifier() {
|
||||||
std::stringstream result;
|
std::stringstream result;
|
||||||
result << getIdentifier() << "_" << trackID;
|
result << getIdentifier() << "_" << trackID;
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Resets a track, clears all meta values
|
||||||
void Track::reset() {
|
void Track::reset() {
|
||||||
fragments.clear();
|
fragments.clear();
|
||||||
parts.clear();
|
parts.clear();
|
||||||
|
@ -781,6 +872,7 @@ namespace DTSC {
|
||||||
lastms = 0;
|
lastms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Creates an empty read-only meta object
|
||||||
readOnlyMeta::readOnlyMeta() {
|
readOnlyMeta::readOnlyMeta() {
|
||||||
vod = false;
|
vod = false;
|
||||||
live = false;
|
live = false;
|
||||||
|
@ -790,6 +882,7 @@ namespace DTSC {
|
||||||
bufferWindow = 0;
|
bufferWindow = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Creates a read-only meta object from a given JSON::Value
|
||||||
readOnlyMeta::readOnlyMeta(JSON::Value & meta) {
|
readOnlyMeta::readOnlyMeta(JSON::Value & meta) {
|
||||||
vod = meta.isMember("vod") && meta["vod"];
|
vod = meta.isMember("vod") && meta["vod"];
|
||||||
live = meta.isMember("live") && meta["live"];
|
live = meta.isMember("live") && meta["live"];
|
||||||
|
@ -810,6 +903,10 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a read-only track to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
|
///\param verbosity How verbose the output needs to be
|
||||||
void readOnlyTrack::toPrettyString(std::ostream & str, int indent, int verbosity){
|
void readOnlyTrack::toPrettyString(std::ostream & str, int indent, int verbosity){
|
||||||
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
|
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
|
||||||
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
|
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
|
||||||
|
@ -859,6 +956,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Creates an empty meta object
|
||||||
Meta::Meta() {
|
Meta::Meta() {
|
||||||
vod = false;
|
vod = false;
|
||||||
live = false;
|
live = false;
|
||||||
|
@ -867,6 +965,7 @@ namespace DTSC {
|
||||||
bufferWindow = 0;
|
bufferWindow = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Creates a meta object from a read-only meta object
|
||||||
Meta::Meta(const readOnlyMeta & rhs) {
|
Meta::Meta(const readOnlyMeta & rhs) {
|
||||||
vod = rhs.vod;
|
vod = rhs.vod;
|
||||||
live = rhs.live;
|
live = rhs.live;
|
||||||
|
@ -878,6 +977,7 @@ namespace DTSC {
|
||||||
moreheader = rhs.moreheader;
|
moreheader = rhs.moreheader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Creates a meta object from a JSON::Value
|
||||||
Meta::Meta(JSON::Value & meta) {
|
Meta::Meta(JSON::Value & meta) {
|
||||||
vod = meta.isMember("vod") && meta["vod"];
|
vod = meta.isMember("vod") && meta["vod"];
|
||||||
live = meta.isMember("live") && meta["live"];
|
live = meta.isMember("live") && meta["live"];
|
||||||
|
@ -898,6 +998,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Updates a meta object given a JSON::Value
|
||||||
void Meta::update(JSON::Value & pack) {
|
void Meta::update(JSON::Value & pack) {
|
||||||
vod = pack.isMember("bpos");
|
vod = pack.isMember("bpos");
|
||||||
live = !vod;
|
live = !vod;
|
||||||
|
@ -906,6 +1007,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Updates a meta object given a DTSC::Packet
|
||||||
void Meta::update(DTSC::Packet & pack) {
|
void Meta::update(DTSC::Packet & pack) {
|
||||||
vod = pack.hasMember("bpos");
|
vod = pack.hasMember("bpos");
|
||||||
live = !vod;
|
live = !vod;
|
||||||
|
@ -914,6 +1016,10 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a track to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
|
///\param verbosity How verbose the output needs to be
|
||||||
void Track::toPrettyString(std::ostream & str, int indent, int verbosity){
|
void Track::toPrettyString(std::ostream & str, int indent, int verbosity){
|
||||||
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
|
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
|
||||||
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
|
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
|
||||||
|
@ -963,6 +1069,7 @@ namespace DTSC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a short to a char*
|
||||||
char * convertShort(short input) {
|
char * convertShort(short input) {
|
||||||
static char result[2];
|
static char result[2];
|
||||||
result[0] = (input >> 8) & 0xFF;
|
result[0] = (input >> 8) & 0xFF;
|
||||||
|
@ -970,6 +1077,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts an integer to a char*
|
||||||
char * convertInt(int input) {
|
char * convertInt(int input) {
|
||||||
static char result[4];
|
static char result[4];
|
||||||
result[0] = (input >> 24) & 0xFF;
|
result[0] = (input >> 24) & 0xFF;
|
||||||
|
@ -979,6 +1087,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a long long to a char*
|
||||||
char * convertLongLong(long long int input) {
|
char * convertLongLong(long long int input) {
|
||||||
static char result[8];
|
static char result[8];
|
||||||
result[0] = (input >> 56) & 0xFF;
|
result[0] = (input >> 56) & 0xFF;
|
||||||
|
@ -992,6 +1101,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Determines the "packed" size of a read-only track
|
||||||
int readOnlyTrack::getSendLen() {
|
int readOnlyTrack::getSendLen() {
|
||||||
int result = 146 + init.size() + codec.size() + type.size() + getWritableIdentifier().size();
|
int result = 146 + init.size() + codec.size() + type.size() + getWritableIdentifier().size();
|
||||||
result += fragLen * 11;
|
result += fragLen * 11;
|
||||||
|
@ -1012,6 +1122,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Determines the "packed" size of a track
|
||||||
int Track::getSendLen() {
|
int Track::getSendLen() {
|
||||||
int result = 146 + init.size() + codec.size() + type.size() + getWritableIdentifier().size();
|
int result = 146 + init.size() + codec.size() + type.size() + getWritableIdentifier().size();
|
||||||
result += fragments.size() * 11;
|
result += fragments.size() * 11;
|
||||||
|
@ -1032,15 +1143,22 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a pointer to the specified destination
|
||||||
|
///
|
||||||
|
///Does a memcpy and increases the destination pointer accordingly
|
||||||
static void writePointer(char *& p, const char * src, unsigned int len){
|
static void writePointer(char *& p, const char * src, unsigned int len){
|
||||||
memcpy(p, src, len);
|
memcpy(p, src, len);
|
||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a pointer to the specified destination
|
||||||
|
///
|
||||||
|
///Does a memcpy and increases the destination pointer accordingly
|
||||||
static void writePointer(char *& p, const std::string & src){
|
static void writePointer(char *& p, const std::string & src){
|
||||||
writePointer(p, src.data(), src.size());
|
writePointer(p, src.data(), src.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a read-only track to a pointer
|
||||||
void readOnlyTrack::writeTo(char *& p){
|
void readOnlyTrack::writeTo(char *& p){
|
||||||
std::string iden = getWritableIdentifier();
|
std::string iden = getWritableIdentifier();
|
||||||
writePointer(p, convertShort(iden.size()), 2);
|
writePointer(p, convertShort(iden.size()), 2);
|
||||||
|
@ -1102,6 +1220,7 @@ namespace DTSC {
|
||||||
writePointer(p, "\000\000\356", 3);//End this track Object
|
writePointer(p, "\000\000\356", 3);//End this track Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a read-only track to a socket
|
||||||
void readOnlyTrack::send(Socket::Connection & conn) {
|
void readOnlyTrack::send(Socket::Connection & conn) {
|
||||||
conn.SendNow(convertShort(getWritableIdentifier().size()), 2);
|
conn.SendNow(convertShort(getWritableIdentifier().size()), 2);
|
||||||
conn.SendNow(getWritableIdentifier());
|
conn.SendNow(getWritableIdentifier());
|
||||||
|
@ -1162,6 +1281,7 @@ namespace DTSC {
|
||||||
conn.SendNow("\000\000\356", 3);//End this track Object
|
conn.SendNow("\000\000\356", 3);//End this track Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a track to a pointer
|
||||||
void Track::writeTo(char *& p){
|
void Track::writeTo(char *& p){
|
||||||
writePointer(p, convertShort(getWritableIdentifier().size()), 2);
|
writePointer(p, convertShort(getWritableIdentifier().size()), 2);
|
||||||
writePointer(p, getWritableIdentifier());
|
writePointer(p, getWritableIdentifier());
|
||||||
|
@ -1228,6 +1348,7 @@ namespace DTSC {
|
||||||
writePointer(p, "\000\000\356", 3);//End this track Object
|
writePointer(p, "\000\000\356", 3);//End this track Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a track to a socket
|
||||||
void Track::send(Socket::Connection & conn) {
|
void Track::send(Socket::Connection & conn) {
|
||||||
conn.SendNow(convertShort(getWritableIdentifier().size()), 2);
|
conn.SendNow(convertShort(getWritableIdentifier().size()), 2);
|
||||||
conn.SendNow(getWritableIdentifier());
|
conn.SendNow(getWritableIdentifier());
|
||||||
|
@ -1294,6 +1415,7 @@ namespace DTSC {
|
||||||
conn.SendNow("\000\000\356", 3);//End this track Object
|
conn.SendNow("\000\000\356", 3);//End this track Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Determines the "packed" size of a read-only meta object
|
||||||
unsigned int readOnlyMeta::getSendLen(){
|
unsigned int readOnlyMeta::getSendLen(){
|
||||||
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
|
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
|
||||||
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
|
@ -1302,6 +1424,7 @@ namespace DTSC {
|
||||||
return dataLen;
|
return dataLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a read-only meta object to a pointer
|
||||||
void readOnlyMeta::writeTo(char * p){
|
void readOnlyMeta::writeTo(char * p){
|
||||||
int dataLen = getSendLen();
|
int dataLen = getSendLen();
|
||||||
writePointer(p, DTSC::Magic_Header, 4);
|
writePointer(p, DTSC::Magic_Header, 4);
|
||||||
|
@ -1332,6 +1455,7 @@ namespace DTSC {
|
||||||
writePointer(p, "\000\000\356", 3);//End global object
|
writePointer(p, "\000\000\356", 3);//End global object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a read-only meta object to a socket
|
||||||
void readOnlyMeta::send(Socket::Connection & conn) {
|
void readOnlyMeta::send(Socket::Connection & conn) {
|
||||||
int dataLen = getSendLen();
|
int dataLen = getSendLen();
|
||||||
conn.SendNow(DTSC::Magic_Header, 4);
|
conn.SendNow(DTSC::Magic_Header, 4);
|
||||||
|
@ -1362,6 +1486,7 @@ namespace DTSC {
|
||||||
conn.SendNow("\000\000\356", 3);//End global object
|
conn.SendNow("\000\000\356", 3);//End global object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Determines the "packed" size of a meta object
|
||||||
unsigned int Meta::getSendLen(){
|
unsigned int Meta::getSendLen(){
|
||||||
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
|
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
|
||||||
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
|
@ -1370,6 +1495,7 @@ namespace DTSC {
|
||||||
return dataLen;
|
return dataLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a meta object to a pointer
|
||||||
void Meta::writeTo(char * p){
|
void Meta::writeTo(char * p){
|
||||||
int dataLen = getSendLen();
|
int dataLen = getSendLen();
|
||||||
writePointer(p, DTSC::Magic_Header, 4);
|
writePointer(p, DTSC::Magic_Header, 4);
|
||||||
|
@ -1400,6 +1526,7 @@ namespace DTSC {
|
||||||
writePointer(p, "\000\000\356", 3);//End global object
|
writePointer(p, "\000\000\356", 3);//End global object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Writes a meta object to a socket
|
||||||
void Meta::send(Socket::Connection & conn) {
|
void Meta::send(Socket::Connection & conn) {
|
||||||
int dataLen = getSendLen();
|
int dataLen = getSendLen();
|
||||||
conn.SendNow(DTSC::Magic_Header, 4);
|
conn.SendNow(DTSC::Magic_Header, 4);
|
||||||
|
@ -1430,6 +1557,7 @@ namespace DTSC {
|
||||||
conn.SendNow("\000\000\356", 3);//End global object
|
conn.SendNow("\000\000\356", 3);//End global object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a read-only track to a JSON::Value
|
||||||
JSON::Value readOnlyTrack::toJSON() {
|
JSON::Value readOnlyTrack::toJSON() {
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
if (fragments) {
|
if (fragments) {
|
||||||
|
@ -1467,6 +1595,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a track to a JSON::Value
|
||||||
JSON::Value Track::toJSON() {
|
JSON::Value Track::toJSON() {
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
@ -1513,6 +1642,7 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a meta object to a JSON::Value
|
||||||
JSON::Value Meta::toJSON() {
|
JSON::Value Meta::toJSON() {
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
|
@ -1534,6 +1664,10 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a read-only meta object to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
|
///\param verbosity How verbose the output needs to be
|
||||||
void readOnlyMeta::toPrettyString(std::ostream & str, int indent, int verbosity){
|
void readOnlyMeta::toPrettyString(std::ostream & str, int indent, int verbosity){
|
||||||
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
it->second.toPrettyString(str, indent, verbosity);
|
it->second.toPrettyString(str, indent, verbosity);
|
||||||
|
@ -1553,6 +1687,10 @@ namespace DTSC {
|
||||||
str << std::string(indent, ' ') << "More Header: " << moreheader << std::endl;
|
str << std::string(indent, ' ') << "More Header: " << moreheader << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a meta object to a human readable string
|
||||||
|
///\param str The stringstream to append to
|
||||||
|
///\param indent the amount of indentation needed
|
||||||
|
///\param verbosity How verbose the output needs to be
|
||||||
void Meta::toPrettyString(std::ostream & str, int indent, int verbosity){
|
void Meta::toPrettyString(std::ostream & str, int indent, int verbosity){
|
||||||
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
it->second.toPrettyString(str, indent, verbosity);
|
it->second.toPrettyString(str, indent, verbosity);
|
||||||
|
@ -1572,6 +1710,7 @@ namespace DTSC {
|
||||||
str << std::string(indent, ' ') << "More Header: " << moreheader << std::endl;
|
str << std::string(indent, ' ') << "More Header: " << moreheader << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Converts a read-only meta object to a JSON::Value
|
||||||
JSON::Value readOnlyMeta::toJSON() {
|
JSON::Value readOnlyMeta::toJSON() {
|
||||||
JSON::Value result;
|
JSON::Value result;
|
||||||
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
|
@ -1593,12 +1732,14 @@ namespace DTSC {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Resets a meta object, removes all unimportant meta values
|
||||||
void Meta::reset() {
|
void Meta::reset() {
|
||||||
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
it->second.reset();
|
it->second.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns whether a read-only meta object is fixed or not
|
||||||
bool readOnlyMeta::isFixed() {
|
bool readOnlyMeta::isFixed() {
|
||||||
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
if (!it->second.keyLen || !(it->second.keys[it->second.keyLen - 1].getBpos())) {
|
if (!it->second.keyLen || !(it->second.keys[it->second.keyLen - 1].getBpos())) {
|
||||||
|
@ -1608,6 +1749,7 @@ namespace DTSC {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Returns whether a meta object is fixed or not
|
||||||
bool Meta::isFixed() {
|
bool Meta::isFixed() {
|
||||||
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
|
||||||
if (it->second.type == "meta" || it->second.type == "") {
|
if (it->second.type == "meta" || it->second.type == "") {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,12 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <semaphore.h>
|
|
||||||
|
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <semaphore.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
|
///\brief A class used for the exchange of statistics over shared memory.
|
||||||
class statExchange {
|
class statExchange {
|
||||||
public:
|
public:
|
||||||
statExchange(char * _data);
|
statExchange(char * _data);
|
||||||
|
@ -27,18 +33,53 @@ namespace IPC {
|
||||||
void connector(std::string name);
|
void connector(std::string name);
|
||||||
std::string connector();
|
std::string connector();
|
||||||
private:
|
private:
|
||||||
|
///\brief The payload for the stat exchange
|
||||||
|
/// - 8 byte - now (timestamp of last statistics)
|
||||||
|
/// - 4 byte - time (duration of the current connection)
|
||||||
|
/// - 4 byte - lastSecond (last second of content viewed)
|
||||||
|
/// - 8 byte - down (Number of bytes received from peer)
|
||||||
|
/// - 8 byte - up (Number of bytes sent to peer)
|
||||||
|
/// - 16 byte - host (ip address of the peer)
|
||||||
|
/// - 20 byte - streamName (name of the stream peer is viewing)
|
||||||
|
/// - 20 byte - connector (name of the connector the peer is using)
|
||||||
char * data;
|
char * data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class semGuard {
|
///\brief A class used for the abstraction of semaphores
|
||||||
|
class semaphore {
|
||||||
public:
|
public:
|
||||||
semGuard(sem_t * semaphore);
|
semaphore();
|
||||||
~semGuard();
|
semaphore(const char * name, int oflag, mode_t mode, unsigned int value);
|
||||||
|
~semaphore();
|
||||||
|
operator bool() const;
|
||||||
|
void open(const char * name, int oflag, mode_t mode = 0, unsigned int value = 0);
|
||||||
|
int getVal() const;
|
||||||
|
void post();
|
||||||
|
void wait();
|
||||||
|
bool tryWait();
|
||||||
|
void close();
|
||||||
|
void unlink();
|
||||||
private:
|
private:
|
||||||
sem_t * mySemaphore;
|
#ifdef __CYGWIN__
|
||||||
|
HANDLE mySem;
|
||||||
|
#else
|
||||||
|
sem_t * mySem;
|
||||||
|
#endif
|
||||||
|
char * myName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined __APPLE__ && !defined __CYGWIN__
|
///\brief A class used as a semaphore guard
|
||||||
|
class semGuard {
|
||||||
|
public:
|
||||||
|
semGuard(semaphore thisSemaphore);
|
||||||
|
~semGuard();
|
||||||
|
private:
|
||||||
|
///\brief The semaphore to guard.
|
||||||
|
semaphore mySemaphore;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined __APPLE__
|
||||||
|
///\brief A class for managing shared memory pages.
|
||||||
class sharedPage{
|
class sharedPage{
|
||||||
public:
|
public:
|
||||||
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
||||||
|
@ -50,20 +91,37 @@ namespace IPC {
|
||||||
bool operator < (const sharedPage & rhs) const {
|
bool operator < (const sharedPage & rhs) const {
|
||||||
return name < rhs.name;
|
return name < rhs.name;
|
||||||
}
|
}
|
||||||
|
void unmap();
|
||||||
|
void close();
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
///\brief The handle of the opened shared memory page
|
||||||
|
HANDLE handle;
|
||||||
|
#else
|
||||||
|
///\brief The fd handle of the opened shared memory page
|
||||||
int handle;
|
int handle;
|
||||||
|
#endif
|
||||||
|
///\brief The name of the opened shared memory page
|
||||||
std::string name;
|
std::string name;
|
||||||
|
///\brief The size in bytes of the opened shared memory page
|
||||||
long long int len;
|
long long int len;
|
||||||
|
///\brief Whether this class should unlink the shared memory upon deletion or not
|
||||||
bool master;
|
bool master;
|
||||||
|
///\brief A pointer to the payload of the page
|
||||||
char * mapped;
|
char * mapped;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
class sharedPage;
|
class sharedPage;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined __APPLE__
|
||||||
|
///\brief A class for managing shared files in the same form as shared memory pages
|
||||||
|
#else
|
||||||
|
///\brief A class for managing shared files.
|
||||||
|
#endif
|
||||||
class sharedFile{
|
class sharedFile{
|
||||||
public:
|
public:
|
||||||
sharedFile(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
sharedFile(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
||||||
sharedFile(const sharedPage & rhs);
|
sharedFile(const sharedFile & rhs);
|
||||||
~sharedFile();
|
~sharedFile();
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
void init(std::string name_, unsigned int len_, bool master_ = false, bool autoBackoff = true);
|
void init(std::string name_, unsigned int len_, bool master_ = false, bool autoBackoff = true);
|
||||||
|
@ -71,14 +129,23 @@ namespace IPC {
|
||||||
bool operator < (const sharedFile & rhs) const {
|
bool operator < (const sharedFile & rhs) const {
|
||||||
return name < rhs.name;
|
return name < rhs.name;
|
||||||
}
|
}
|
||||||
|
void unmap();
|
||||||
|
///\brief The fd handle of the opened shared file
|
||||||
int handle;
|
int handle;
|
||||||
|
///\brief The name of the opened shared file
|
||||||
std::string name;
|
std::string name;
|
||||||
|
///\brief The size in bytes of the opened shared file
|
||||||
long long int len;
|
long long int len;
|
||||||
|
///\brief Whether this class should unlink the shared file upon deletion or not
|
||||||
bool master;
|
bool master;
|
||||||
|
///\brief A pointer to the payload of the file file
|
||||||
char * mapped;
|
char * mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined __APPLE__ || defined __CYGWIN__
|
#ifdef __APPLE__
|
||||||
|
///\brief A class for handling shared memory pages.
|
||||||
|
///
|
||||||
|
///Uses shared files at its backbone, defined for portability
|
||||||
class sharedPage: public sharedFile{
|
class sharedPage: public sharedFile{
|
||||||
public:
|
public:
|
||||||
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
|
||||||
|
@ -87,6 +154,15 @@ namespace IPC {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///\brief The server part of a server/client model for shared memory.
|
||||||
|
///
|
||||||
|
///The server manages the shared memory pages, and allocates new pages when needed.
|
||||||
|
///
|
||||||
|
///Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
|
||||||
|
///Each time a page is nearly full, the next page is created with a size double to the previous one.
|
||||||
|
///
|
||||||
|
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
|
||||||
|
///If no such length can be allocated, the next page should be tried, and so on.
|
||||||
class sharedServer{
|
class sharedServer{
|
||||||
public:
|
public:
|
||||||
sharedServer();
|
sharedServer();
|
||||||
|
@ -95,18 +171,33 @@ namespace IPC {
|
||||||
~sharedServer();
|
~sharedServer();
|
||||||
void parseEach(void (*callback)(char * data, size_t len, unsigned int id));
|
void parseEach(void (*callback)(char * data, size_t len, unsigned int id));
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
///\brief The amount of connected clients
|
||||||
unsigned int amount;
|
unsigned int amount;
|
||||||
private:
|
private:
|
||||||
bool isInUse(unsigned int id);
|
bool isInUse(unsigned int id);
|
||||||
void newPage();
|
void newPage();
|
||||||
void deletePage();
|
void deletePage();
|
||||||
|
///\brief The basename of the shared pages.
|
||||||
std::string baseName;
|
std::string baseName;
|
||||||
|
///\brief The length of each consecutive piece of payload
|
||||||
unsigned int payLen;
|
unsigned int payLen;
|
||||||
|
///\brief The set of sharedPage structures to manage the actual memory
|
||||||
std::set<sharedPage> myPages;
|
std::set<sharedPage> myPages;
|
||||||
sem_t * mySemaphore;
|
///\brief A semaphore that is locked upon creation and deletion of the page, to ensure no new data is allocated during this step.
|
||||||
|
semaphore mySemaphore;
|
||||||
|
///\brief Whether the payload has a counter, if so, it is added in front of the payload
|
||||||
bool hasCounter;
|
bool hasCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///\brief The client part of a server/client model for shared memory.
|
||||||
|
///
|
||||||
|
///The server manages the shared memory pages, and allocates new pages when needed.
|
||||||
|
///
|
||||||
|
///Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
|
||||||
|
///Each time a page is nearly full, the next page is created with a size double to the previous one.
|
||||||
|
///
|
||||||
|
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
|
||||||
|
///If no such length can be allocated, the next page should be tried, and so on.
|
||||||
class sharedClient{
|
class sharedClient{
|
||||||
public:
|
public:
|
||||||
sharedClient();
|
sharedClient();
|
||||||
|
@ -119,11 +210,17 @@ namespace IPC {
|
||||||
void keepAlive();
|
void keepAlive();
|
||||||
char * getData();
|
char * getData();
|
||||||
private:
|
private:
|
||||||
|
///\brief The basename of the shared pages.
|
||||||
std::string baseName;
|
std::string baseName;
|
||||||
|
///\brief The shared page this client has reserved a space on.
|
||||||
sharedPage myPage;
|
sharedPage myPage;
|
||||||
sem_t * mySemaphore;
|
///\brief A semaphore that is locked upon trying to allocate space on a page
|
||||||
|
semaphore mySemaphore;
|
||||||
|
///\brief The size in bytes of the opened page
|
||||||
int payLen;
|
int payLen;
|
||||||
|
///\brief The offset of the payload reserved for this client within the opened page
|
||||||
int offsetOnPage;
|
int offsetOnPage;
|
||||||
|
///\brief Whether the payload has a counter, if so, it is added in front of the payload
|
||||||
bool hasCounter;
|
bool hasCounter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
#include "shared_memory.h"
|
||||||
|
|
||||||
std::string Util::getTmpFolder(){
|
std::string Util::getTmpFolder(){
|
||||||
std::string dir;
|
std::string dir;
|
||||||
|
@ -119,14 +120,14 @@ bool Util::Stream::getStream(std::string streamname){
|
||||||
JSON::Value ServConf = JSON::fromFile(getTmpFolder() + "streamlist");
|
JSON::Value ServConf = JSON::fromFile(getTmpFolder() + "streamlist");
|
||||||
if (ServConf["streams"].isMember(streamname)){
|
if (ServConf["streams"].isMember(streamname)){
|
||||||
//check if the stream is already active, if yes, don't re-activate
|
//check if the stream is already active, if yes, don't re-activate
|
||||||
sem_t * playerLock = sem_open(std::string("/lock_" + streamname).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
IPC::semaphore playerLock(std::string("/lock_" + streamname).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
||||||
if (sem_trywait(playerLock) == -1){
|
if (!playerLock.tryWait()){
|
||||||
sem_close(playerLock);
|
playerLock.close();
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Playerlock for %s already active - not re-activating stream", streamname.c_str());
|
DEBUG_MSG(DLVL_MEDIUM, "Playerlock for %s already active - not re-activating stream", streamname.c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
sem_post(playerLock);
|
playerLock.post();
|
||||||
sem_close(playerLock);
|
playerLock.close();
|
||||||
if (ServConf["streams"][streamname]["source"].asString()[0] == '/'){
|
if (ServConf["streams"][streamname]["source"].asString()[0] == '/'){
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Activating VoD stream %s", streamname.c_str());
|
DEBUG_MSG(DLVL_MEDIUM, "Activating VoD stream %s", streamname.c_str());
|
||||||
return getVod(ServConf["streams"][streamname]["source"].asString(), streamname);
|
return getVod(ServConf["streams"][streamname]["source"].asString(), streamname);
|
||||||
|
|
Loading…
Add table
Reference in a new issue