This commit is contained in:
defnax 2015-09-03 17:41:30 +02:00
commit 07c5030c36
35 changed files with 1254 additions and 388 deletions

View File

@ -27,12 +27,12 @@ addons:
project: project:
name: "RetroShare/RetroShare" name: "RetroShare/RetroShare"
description: "RetroShare Build submitted via Travis CI" description: "RetroShare Build submitted via Travis CI"
build_command_prepend: "qmake; make clean" build_command_prepend: "qmake CONFIG+=NO_SQLCIPHER; make clean"
build_command: "make -j 4" build_command: "make -j 4"
branch_pattern: coverity_scan branch_pattern: coverity_scan
before_script: before_script:
- qmake - qmake CONFIG+=NO_SQLCIPHER
#script: make #script: make
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make ; fi script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make ; fi
@ -53,6 +53,8 @@ notifications:
- "chat.freenode.net#retroshare" - "chat.freenode.net#retroshare"
template: template:
- "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}" - "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}"
- "Message: %{commit_message}"
- "Commit details: %{compare_url}"
# webhooks: # webhooks:
# urls: # urls:
# - https://webhooks.gitter.im/e/9502afd22ca6c8e85fb3 # - https://webhooks.gitter.im/e/9502afd22ca6c8e85fb3

View File

@ -37,7 +37,7 @@ Compilation on Linux
3. Compile 3. Compile
```bash ```bash
cd trunk cd trunk
qmake CONFIG=debug qmake CONFIG+=debug
make make
``` ```
@ -51,11 +51,22 @@ Compilation on Linux
/usr/bin/RetroShare06 /usr/bin/RetroShare06
/usr/bin/RetroShare06-nogui /usr/bin/RetroShare06-nogui
Compile only retroshare-nogui
-----------------------------
If you want to run RetroShare on a server and dont need the gui and plugins,
you can run the following commands to only compile/install the nogui version:
```bash
qmake
make retroshare-nogui
sudo make retroshare-nogui-install_subtargets
```
For packagers For packagers
------------- -------------
Packagers can use PREFIX and LIB\_DIR to customize the installation paths: Packagers can use PREFIX and LIB\_DIR to customize the installation paths:
```bash ```bash
qmake PREFIX=/usr LIB_DIR=/usr/lib64 qmake PREFIX=/usr LIB_DIR=/usr/lib64 "CONFIG-=debug" "CONFIG+=release"
make make
make INSTALL_ROOT=${PKGDIR} install make INSTALL_ROOT=${PKGDIR} install
``` ```

View File

@ -1,3 +1,5 @@
!include("retroshare.pri"): error("Could not include file retroshare.pri")
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += \ SUBDIRS += \
@ -24,43 +26,12 @@ pegmarkdown.file = supportlibs/pegmarkdown/pegmarkdown.pro
retroshare_gui.file = retroshare-gui/src/retroshare-gui.pro retroshare_gui.file = retroshare-gui/src/retroshare-gui.pro
retroshare_gui.depends = libretroshare libresapi pegmarkdown retroshare_gui.depends = libretroshare libresapi pegmarkdown
retroshare_gui.target = retroshare-gui
retroshare_nogui.file = retroshare-nogui/src/retroshare-nogui.pro retroshare_nogui.file = retroshare-nogui/src/retroshare-nogui.pro
retroshare_nogui.depends = libretroshare libresapi retroshare_nogui.depends = libretroshare libresapi
retroshare_nogui.target = retroshare-nogui
plugins.file = plugins/plugins.pro plugins.file = plugins/plugins.pro
plugins.depends = retroshare_gui plugins.depends = retroshare_gui
plugins.target = plugins
unix {
isEmpty(PREFIX) { PREFIX = /usr }
isEmpty(INC_DIR) { INC_DIR = "$${PREFIX}/include/retroshare06" }
isEmpty(LIB_DIR) { LIB_DIR = "$${PREFIX}/lib" }
isEmpty(DATA_DIR) { DATA_DIR = "$${PREFIX}/share/RetroShare06" }
icon_files.path = "$${PREFIX}/share/icons/hicolor"
icon_files.files = data/24x24
icon_files.files += data/48x48
icon_files.files += data/64x64
icon_files.files += data/128x128
INSTALLS += icon_files
desktop_files.path = "$${PREFIX}/share/applications"
desktop_files.files = data/retroshare06.desktop
INSTALLS += desktop_files
pixmap_files.path = "$${PREFIX}/share/pixmaps"
pixmap_files.files = data/retroshare06.xpm
INSTALLS += pixmap_files
data_files.path = "$${DATA_DIR}"
data_files.files = libbitdht/src/bitdht/bdboot.txt
INSTALLS += data_files
webui_files.path = "$${DATA_DIR}/webui"
webui_files.files = libresapi/src/webfiles/*
INSTALLS += webui_files
webui_img_files.path = "$${DATA_DIR}/webui/img"
webui_img_files.files = retroshare-gui/src/gui/images/logo/logo_splash.png
INSTALLS += webui_img_files
}

View File

@ -2,7 +2,7 @@ Source: retroshare06
Section: devel Section: devel
Priority: standard Priority: standard
Maintainer: Cyril Soler <csoler@users.sourceforge.net> Maintainer: Cyril Soler <csoler@users.sourceforge.net>
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqtmultimediakit1, qtmobility-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libcv-dev, libopencv-core-dev, libopencv-contrib-dev, libhighgui-dev, tcl8.5, libsqlcipher-dev, libmicrohttpd-dev Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqtmultimediakit1, qtmobility-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libcv-dev, libopencv-core-dev, libopencv-contrib-dev, libhighgui-dev, tcl8.5, libsqlcipher-dev, libmicrohttpd-dev, libavcodec-dev
Standards-Version: 3.9.3 Standards-Version: 3.9.3
Homepage: http://retroshare.sourceforge.net Homepage: http://retroshare.sourceforge.net

View File

@ -2,7 +2,7 @@ Source: retroshare06
Section: devel Section: devel
Priority: standard Priority: standard
Maintainer: Cyril Soler <csoler@users.sourceforge.net> Maintainer: Cyril Soler <csoler@users.sourceforge.net>
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqt4-multimedia, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libcv-dev, libcvaux-dev, libhighgui-dev, tcl8.5, libmicrohttpd-dev, libsqlite3-dev Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqt4-multimedia, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libcv-dev, libcvaux-dev, libhighgui-dev, tcl8.5, libmicrohttpd-dev, libsqlite3-dev, libavcodec-dev
Standards-Version: 3.9.3 Standards-Version: 3.9.3
Homepage: http://retroshare.sourceforge.net Homepage: http://retroshare.sourceforge.net

View File

@ -2,7 +2,7 @@ Source: retroshare
Section: devel Section: devel
Priority: standard Priority: standard
Maintainer: Cyril Soler <csoler@users.sourceforge.net> Maintainer: Cyril Soler <csoler@users.sourceforge.net>
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, libprotobuf-dev, protobuf-compiler, cmake, libcurl4-openssl-dev Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, libprotobuf-dev, protobuf-compiler, cmake, libcurl4-openssl-dev, libavcodec-dev
Standards-Version: 3.9.1 Standards-Version: 3.9.1
Homepage: http://retroshare.sourceforge.net Homepage: http://retroshare.sourceforge.net

View File

@ -2,7 +2,7 @@ Source: retroshare06
Section: devel Section: devel
Priority: standard Priority: standard
Maintainer: Cyril Soler <csoler@users.sourceforge.net> Maintainer: Cyril Soler <csoler@users.sourceforge.net>
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqtmultimediakit1, qtmobility-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libopencv-dev, tcl8.5, libsqlcipher-dev, libmicrohttpd-dev Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, qt4-dev-tools, libqt4-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libqt4-opengl-dev, libqtmultimediakit1, qtmobility-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libopencv-dev, tcl8.5, libsqlcipher-dev, libmicrohttpd-dev, libavcodec-dev
Standards-Version: 3.9.3 Standards-Version: 3.9.3
Homepage: http://retroshare.sourceforge.net Homepage: http://retroshare.sourceforge.net

View File

@ -3,7 +3,7 @@
configure: configure-stamp configure: configure-stamp
configure-stamp: configure-stamp:
dh_testdir dh_testdir
cd src && qmake-qt4 CONFIG=release PREFIX=/usr LIB_DIR=/usr/lib RetroShare.pro cd src && qmake-qt4 "CONFIG-=debug" "CONFIG+=release" PREFIX=/usr LIB_DIR=/usr/lib RetroShare.pro
touch $@ touch $@

View File

@ -56,7 +56,7 @@ cd lib/sqlcipher
make make
cd - cd -
cd src cd src
qmake-qt4 CONFIG=release PREFIX=%{_prefix} LIB_DIR=%{_libdir} RetroShare.pro qmake-qt4 "CONFIG-=debug" "CONFIG+=release" PREFIX=%{_prefix} LIB_DIR=%{_libdir} RetroShare.pro
make make
cd - cd -

View File

@ -1,3 +1,5 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = lib TEMPLATE = lib
CONFIG += staticlib CONFIG += staticlib
CONFIG -= qt CONFIG -= qt
@ -37,6 +39,13 @@ linux-g++-64 {
OBJECTS_DIR = temp/linux-g++-64/obj OBJECTS_DIR = temp/linux-g++-64/obj
} }
unix {
data_files.path = "$${DATA_DIR}"
data_files.files = bitdht/bdboot.txt
INSTALLS += data_files
}
#################### Cross compilation for windows under Linux #################### #################### Cross compilation for windows under Linux ####################
win32-x-g++ { win32-x-g++ {

View File

@ -105,7 +105,7 @@ void ForumHandler::handleWildcard(Request &req, Response &resp)
{ {
RsGxsForumGroup& grp = *vit; RsGxsForumGroup& grp = *vit;
KeyValueReference<RsGxsGroupId> id("id", grp.mMeta.mGroupId); KeyValueReference<RsGxsGroupId> id("id", grp.mMeta.mGroupId);
KeyValueReference<u_int32_t> vis_msg("visible_msg_count", grp.mMeta.mVisibleMsgCount); KeyValueReference<uint32_t> vis_msg("visible_msg_count", grp.mMeta.mVisibleMsgCount);
//KeyValueReference<RsPgpId> pgp_id("pgp_id",grp.mPgpId ); //KeyValueReference<RsPgpId> pgp_id("pgp_id",grp.mPgpId );
// not very happy about this, i think the flags should stay hidden in rsidentities // not very happy about this, i think the flags should stay hidden in rsidentities
bool own = (grp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); bool own = (grp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN);

View File

@ -1,3 +1,5 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = lib TEMPLATE = lib
CONFIG += staticlib CONFIG += staticlib
CONFIG -= qt CONFIG -= qt
@ -8,6 +10,16 @@ CONFIG += libmicrohttpd
INCLUDEPATH += ../../libretroshare/src INCLUDEPATH += ../../libretroshare/src
unix {
webui_files.path = "$${DATA_DIR}/webui"
webui_files.files = webfiles/*
INSTALLS += webui_files
webui_img_files.path = "$${DATA_DIR}/webui/img"
webui_img_files.files = ../../retroshare-gui/src/gui/images/logo/logo_splash.png
INSTALLS += webui_img_files
}
win32{ win32{
DEFINES *= WINDOWS_SYS DEFINES *= WINDOWS_SYS
INCLUDEPATH += $$PWD/../../../libs/include INCLUDEPATH += $$PWD/../../../libs/include

View File

@ -1,7 +1,11 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = lib TEMPLATE = lib
CONFIG += staticlib bitdht CONFIG += staticlib bitdht
CONFIG += create_prl
CONFIG -= qt CONFIG -= qt
TARGET = retroshare TARGET = retroshare
TARGET_PRL = libretroshare
#GXS Stuff. #GXS Stuff.
@ -80,6 +84,8 @@ SOURCES += tcponudp/udppeer.cc \
# The next line is for compliance with debian packages. Keep it! # The next line is for compliance with debian packages. Keep it!
INCLUDEPATH += ../libbitdht INCLUDEPATH += ../libbitdht
DEFINES *= RS_USE_BITDHT DEFINES *= RS_USE_BITDHT
PRE_TARGETDEPS *= ../../libbitdht/src/lib/libbitdht.a
LIBS += ../../libbitdht/src/lib/libbitdht.a
} }
@ -135,15 +141,22 @@ linux-* {
DEPENDPATH += . $${SSL_DIR} $${UPNP_DIR} DEPENDPATH += . $${SSL_DIR} $${UPNP_DIR}
INCLUDEPATH += . $${SSL_DIR} $${UPNP_DIR} INCLUDEPATH += . $${SSL_DIR} $${UPNP_DIR}
contains(CONFIG, NO_SQLCIPHER) {
DEFINES *= NO_SQLCIPHER
LIBS *= -lsqlite3
} else {
SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes)
isEmpty(SQLCIPHER_OK) { isEmpty(SQLCIPHER_OK) {
# We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database.
!exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) { exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) {
message(libsqlcipher.a not found. Compilation will not use SQLCIPER. Database will be unencrypted.) LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a
DEFINES *= NO_SQLCIPHER
} else {
DEPENDPATH += ../../../lib/ DEPENDPATH += ../../../lib/
INCLUDEPATH += ../../../lib/ INCLUDEPATH += ../../../lib/
} else {
error("libsqlcipher is not installed and libsqlcipher.a not found. SQLCIPHER is necessary for encrypted database, to build with unencrypted database, run: qmake CONFIG+=NO_SQLCIPHER")
}
} else {
LIBS *= -lsqlcipher
} }
} }
@ -165,14 +178,11 @@ linux-* {
DEFINES *= UBUNTU DEFINES *= UBUNTU
INCLUDEPATH += /usr/include/glib-2.0/ /usr/lib/glib-2.0/include INCLUDEPATH += /usr/include/glib-2.0/ /usr/lib/glib-2.0/include
LIBS *= -lgnome-keyring LIBS *= -lgnome-keyring
LIBS *= -lssl -lupnp -lixml
LIBS *= -lcrypto -lz -lpthread
} }
unix { unix {
isEmpty(PREFIX) { PREFIX = /usr }
isEmpty(INC_DIR) { INC_DIR = "$${PREFIX}/include/retroshare06" }
isEmpty(LIB_DIR) { LIB_DIR = "$${PREFIX}/lib" }
isEmpty(DATA_DIR) { DATA_DIR = "$${PREFIX}/share/RetroShare06" }
DEFINES *= LIB_DIR=\"\\\"$${LIB_DIR}\\\"\" DEFINES *= LIB_DIR=\"\\\"$${LIB_DIR}\\\"\"
DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\" DEFINES *= DATA_DIR=\"\\\"$${DATA_DIR}\\\"\"
@ -330,6 +340,10 @@ openbsd-* {
################################### COMMON stuff ################################## ################################### COMMON stuff ##################################
# openpgpsdk
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2
HEADERS += dbase/cachestrapper.h \ HEADERS += dbase/cachestrapper.h \
dbase/fimonitor.h \ dbase/fimonitor.h \
dbase/findex.h \ dbase/findex.h \

View File

@ -649,7 +649,6 @@ bool RsTlvKeySignatureSet::GetTlv(void *data, uint32_t size, uint32_t *offset)
/* get the next type */ /* get the next type */
uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) );
SignType currType;
switch(tlvsubtype) switch(tlvsubtype)
{ {
@ -659,16 +658,13 @@ bool RsTlvKeySignatureSet::GetTlv(void *data, uint32_t size, uint32_t *offset)
ok &= sign.GetTlv(data, size, offset); ok &= sign.GetTlv(data, size, offset);
if (ok) if (ok)
{ {
keySignSet[currType] = sign; keySignSet[sign_type] = sign;
} }
} }
break; break;
case TLV_TYPE_KEYSIGNATURETYPE: case TLV_TYPE_KEYSIGNATURETYPE:
{ {
ok = GetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, &sign_type); ok = GetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, &sign_type);
if(ok)
currType = sign_type;
} }
break; break;
default: default:

View File

@ -1,8 +1,10 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = lib TEMPLATE = lib
win32 { macx {
CONFIG += staticlib
} else {
CONFIG = staticlib CONFIG = staticlib
} else {
CONFIG += staticlib
} }
DEFINES *= OPENSSL_NO_IDEA DEFINES *= OPENSSL_NO_IDEA

View File

@ -1,3 +1,5 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = lib TEMPLATE = lib
CONFIG *= plugin CONFIG *= plugin
@ -5,9 +7,6 @@ DEPENDPATH += ../../libretroshare/src/ ../../retroshare-gui/src/
INCLUDEPATH += ../../libretroshare/src/ ../../retroshare-gui/src/ INCLUDEPATH += ../../libretroshare/src/ ../../retroshare-gui/src/
unix { unix {
isEmpty(PREFIX) { PREFIX = /usr }
isEmpty(LIB_DIR) { LIB_DIR = "$${PREFIX}/lib" }
target.path = "$${LIB_DIR}/retroshare/extensions6" target.path = "$${LIB_DIR}/retroshare/extensions6"
INSTALLS += target INSTALLS += target
} }
@ -29,6 +28,9 @@ win32 {
QMAKE_CFLAGS += -Wextra QMAKE_CFLAGS += -Wextra
QMAKE_CXXFLAGS += -Wextra QMAKE_CXXFLAGS += -Wextra
# solve linker warnings because of the order of the libraries
QMAKE_LFLAGS += -Wl,--start-group
OBJECTS_DIR = temp/obj OBJECTS_DIR = temp/obj
MOC_DIR = temp/moc MOC_DIR = temp/moc
RCC_DIR = temp/qrc RCC_DIR = temp/qrc

View File

@ -92,8 +92,7 @@ linux-* {
win32 { win32 {
DEFINES += CURL_STATICLIB LIBXML_STATIC LIBXSLT_STATIC LIBEXSLT_STATIC DEFINES += CURL_STATICLIB LIBXML_STATIC LIBXSLT_STATIC LIBEXSLT_STATIC
# Change order of the libraries LIBS += -lcurl -lxml2 -lz -lxslt -lws2_32 -lwldap32 -lssl -lcrypto
LIBS = -lcurl -lxml2 -lz -lxslt -lws2_32 -lwldap32 -lssl -lcrypto -lgdi32 -lwsock32 $${LIBS}
} }
openbsd-* { openbsd-* {

View File

@ -24,6 +24,9 @@ linux-* {
} }
win32 { win32 {
# ffmpeg
QMAKE_CXXFLAGS += -D__STDC_CONSTANT_MACROS
LIBS_DIR = $$PWD/../../../libs LIBS_DIR = $$PWD/../../../libs
LIBS += -L"$$LIBS_DIR/lib/opencv" LIBS += -L"$$LIBS_DIR/lib/opencv"
@ -96,4 +99,4 @@ TRANSLATIONS += \
lang/VOIP_tr.ts \ lang/VOIP_tr.ts \
lang/VOIP_zh_CN.ts lang/VOIP_zh_CN.ts
LIBS += -lspeex -lspeexdsp LIBS += -lspeex -lspeexdsp -lavformat -lavcodec -lavutil

View File

@ -29,17 +29,15 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <QTimer>
//#include "AudioInput.h"
//#include "AudioOutput.h"
#include "AudioStats.h" #include "AudioStats.h"
#include "AudioInputConfig.h" #include "AudioInputConfig.h"
//#include "Global.h"
//#include "NetworkConfig.h"
#include "audiodevicehelper.h" #include "audiodevicehelper.h"
#include "AudioWizard.h" #include "AudioWizard.h"
#include "gui/VideoProcessor.h"
#include "gui/common/RSGraphWidget.h" #include "gui/common/RSGraphWidget.h"
#include "util/RsProtectedTimer.h"
#include <interface/rsVOIP.h> #include <interface/rsVOIP.h>
#define iroundf(x) ( static_cast<int>(x) ) #define iroundf(x) ( static_cast<int>(x) )
@ -55,9 +53,9 @@ void AudioInputDialog::showEvent(QShowEvent *) {
class voipGraphSource: public RSGraphSource class voipGraphSource: public RSGraphSource
{ {
public: public:
voipGraphSource() {} voipGraphSource() : video_input(NULL) {}
void setVideoInput(QVideoInputDevice *vid) { video_input = vid ; } void setVideoInput(const QVideoInputDevice *vid) { video_input = vid ; }
virtual QString displayName(int) const { return tr("Required bandwidth") ;} virtual QString displayName(int) const { return tr("Required bandwidth") ;}
@ -73,21 +71,14 @@ public:
virtual void getValues(std::map<std::string,float>& vals) const virtual void getValues(std::map<std::string,float>& vals) const
{ {
RsVOIPDataChunk chunk ;
uint32_t total_size = 0 ;
vals.clear() ; vals.clear() ;
while(video_input && video_input->getNextEncodedPacket(chunk)) if(video_input)
{ vals[std::string("bw")] = video_input->currentBandwidth() ;
total_size += chunk.size ;
chunk.clear() ;
}
vals[std::string("bw")] = (float)total_size ;
} }
private: private:
QVideoInputDevice *video_input ; const QVideoInputDevice *video_input ;
}; };
void voipGraph::setVoipSource(voipGraphSource *gs) void voipGraph::setVoipSource(voipGraphSource *gs)
@ -125,7 +116,13 @@ AudioInputConfig::AudioInputConfig(QWidget * parent, Qt::WindowFlags flags)
// //
videoInput = new QVideoInputDevice(this) ; videoInput = new QVideoInputDevice(this) ;
videoInput->setEchoVideoTarget(ui.videoDisplay) ; videoInput->setEchoVideoTarget(ui.videoDisplay) ;
videoInput->setVideoEncoder(new JPEGVideoEncoder()) ;
videoProcessor = new VideoProcessor() ;
videoProcessor->setDisplayTarget(NULL) ;
videoProcessor->setMaximumBandwidth(ui.availableBW_SB->value()) ;
videoInput->setVideoProcessor(videoProcessor) ;
graph_source = new voipGraphSource ; graph_source = new voipGraphSource ;
ui.voipBwGraph->setSource(graph_source); ui.voipBwGraph->setSource(graph_source);
@ -133,10 +130,35 @@ AudioInputConfig::AudioInputConfig(QWidget * parent, Qt::WindowFlags flags)
graph_source->setVideoInput(videoInput) ; graph_source->setVideoInput(videoInput) ;
graph_source->setCollectionTimeLimit(1000*300) ; graph_source->setCollectionTimeLimit(1000*300) ;
graph_source->start() ; graph_source->start() ;
QObject::connect(ui.showEncoded_CB,SIGNAL(toggled(bool)),this,SLOT(togglePreview(bool))) ;
QObject::connect(ui.availableBW_SB,SIGNAL(valueChanged(double)),this,SLOT(updateAvailableBW(double))) ;
}
void AudioInputConfig::updateAvailableBW(double r)
{
std::cerr << "Setting max bandwidth to " << r << " KB/s" << std::endl;
videoProcessor->setMaximumBandwidth((uint32_t)(r*1024)) ;
}
void AudioInputConfig::togglePreview(bool b)
{
if(b)
{
videoInput->setEchoVideoTarget(NULL) ;
videoProcessor->setDisplayTarget(ui.videoDisplay) ;
}
else
{
videoInput->setEchoVideoTarget(ui.videoDisplay) ;
videoProcessor->setDisplayTarget(NULL) ;
}
} }
AudioInputConfig::~AudioInputConfig() AudioInputConfig::~AudioInputConfig()
{ {
disconnect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) );
graph_source->stop() ; graph_source->stop() ;
graph_source->setVideoInput(NULL) ; graph_source->setVideoInput(NULL) ;
@ -166,7 +188,7 @@ void AudioInputConfig::load()
//connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) ); //connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) );
//connect( ui.allowTunnelConnectionCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) ); //connect( ui.allowTunnelConnectionCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) );
qtTick = new QTimer(this); qtTick = new RsProtectedTimer(this);
connect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) ); connect( qtTick, SIGNAL( timeout ( ) ), this, SLOT( on_Tick_timeout() ) );
qtTick->start(20); qtTick->start(20);
/*if (AudioInputRegistrar::qmNew) { /*if (AudioInputRegistrar::qmNew) {
@ -330,8 +352,10 @@ void AudioInputConfig::on_qcbTransmit_currentIndexChanged(int v) {
} }
void AudioInputConfig::on_Tick_timeout() { void AudioInputConfig::on_Tick_timeout()
if (!inputAudioProcessor) { {
if (!inputAudioProcessor)
{
inputAudioProcessor = new QtSpeex::SpeexInputProcessor(); inputAudioProcessor = new QtSpeex::SpeexInputProcessor();
inputAudioProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered); inputAudioProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
@ -352,6 +376,15 @@ void AudioInputConfig::on_Tick_timeout() {
abSpeech->iValue = iroundf(inputAudioProcessor->dVoiceAcivityLevel * 32767.0f + 0.5f); abSpeech->iValue = iroundf(inputAudioProcessor->dVoiceAcivityLevel * 32767.0f + 0.5f);
abSpeech->update(); abSpeech->update();
// also transmit encoded video
RsVOIPDataChunk chunk ;
while((!videoInput->stopped()) && videoInput->getNextEncodedPacket(chunk))
{
videoProcessor->receiveEncodedData(chunk) ;
chunk.clear() ;
}
} }
void AudioInputConfig::emptyBuffer() { void AudioInputConfig::emptyBuffer() {

View File

@ -69,6 +69,7 @@ class AudioInputConfig : public ConfigPage
//VideoDecoder *videoDecoder ; //VideoDecoder *videoDecoder ;
//VideoEncoder *videoEncoder ; //VideoEncoder *videoEncoder ;
QVideoInputDevice *videoInput ; QVideoInputDevice *videoInput ;
VideoProcessor *videoProcessor ;
bool loaded; bool loaded;
voipGraphSource *graph_source ; voipGraphSource *graph_source ;
@ -93,9 +94,11 @@ class AudioInputConfig : public ConfigPage
virtual QString pageName() const { return tr("VOIP") ; } virtual QString pageName() const { return tr("VOIP") ; }
virtual QString helpText() const { return ""; } virtual QString helpText() const { return ""; }
private slots: private slots:
void updateAvailableBW(double r);
void loadSettings(); void loadSettings();
void emptyBuffer(); void emptyBuffer();
void togglePreview(bool) ;
void on_qsTransmitHold_valueChanged(int v); void on_qsTransmitHold_valueChanged(int v);
void on_qsAmp_valueChanged(int v); void on_qsAmp_valueChanged(int v);

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1155</width> <width>1155</width>
<height>713</height> <height>832</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -391,6 +391,49 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Available bandwidth:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="availableBW_SB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use this field to simulate the maximum bandwidth available so as to preview what the encoded video will look like with the corresponding compression rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string>KB/s</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>2.000000000000000</double>
</property>
<property name="maximum">
<double>200.000000000000000</double>
</property>
<property name="value">
<double>30.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="showEncoded_CB">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Display encoded (and then decoded) frame, to check the codec's quality. If not selected, the image above only shows the frame that is grabbed from your camera.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>preview</string>
</property>
</widget>
</item>
<item> <item>
<spacer> <spacer>
<property name="orientation"> <property name="orientation">

View File

@ -11,10 +11,15 @@ QVideoInputDevice::QVideoInputDevice(QWidget *parent)
{ {
_timer = NULL ; _timer = NULL ;
_capture_device = NULL ; _capture_device = NULL ;
_video_encoder = NULL ; _video_processor = NULL ;
_echo_output_device = NULL ; _echo_output_device = NULL ;
} }
bool QVideoInputDevice::stopped()
{
return _timer == NULL ;
}
void QVideoInputDevice::stop() void QVideoInputDevice::stop()
{ {
if(_timer != NULL) if(_timer != NULL)
@ -54,6 +59,9 @@ void QVideoInputDevice::start()
void QVideoInputDevice::grabFrame() void QVideoInputDevice::grabFrame()
{ {
if(!_timer)
return ;
IplImage *img=cvQueryFrame(_capture_device); IplImage *img=cvQueryFrame(_capture_device);
if(img == NULL) if(img == NULL)
@ -73,30 +81,38 @@ void QVideoInputDevice::grabFrame()
cv::Mat img_rgb; cv::Mat img_rgb;
cv::cvtColor(cv::Mat(img), img_rgb, CV_BGR2RGB); cv::cvtColor(cv::Mat(img), img_rgb, CV_BGR2RGB);
static const int _encoded_width = 128 ; QImage image = QImage(img_rgb.data,img_rgb.cols,img_rgb.rows,QImage::Format_RGB888);
static const int _encoded_height = 128 ;
QImage image = QImage(img_rgb.data,img_rgb.cols,img_rgb.rows,QImage::Format_RGB888).scaled(QSize(_encoded_width,_encoded_height),Qt::IgnoreAspectRatio,Qt::SmoothTransformation) ; if(_video_processor != NULL)
if(_video_encoder != NULL)
{ {
_video_encoder->addImage(image) ; _video_processor->processImage(image) ;
emit networkPacketReady() ; emit networkPacketReady() ;
} }
if(_echo_output_device != NULL) _echo_output_device->showFrame(image) ; if(_echo_output_device != NULL)
_echo_output_device->showFrame(image) ;
} }
bool QVideoInputDevice::getNextEncodedPacket(RsVOIPDataChunk& chunk) bool QVideoInputDevice::getNextEncodedPacket(RsVOIPDataChunk& chunk)
{ {
if(_video_encoder) if(!_timer)
return _video_encoder->nextPacket(chunk) ; return false ;
if(_video_processor)
return _video_processor->nextEncodedPacket(chunk) ;
else else
return false ; return false ;
} }
uint32_t QVideoInputDevice::currentBandwidth() const
{
return _video_processor->currentBandwidthOut() ;
}
QVideoInputDevice::~QVideoInputDevice() QVideoInputDevice::~QVideoInputDevice()
{ {
stop() ; stop() ;
_video_processor = NULL ;
} }
@ -113,6 +129,7 @@ void QVideoOutputDevice::showFrameOff()
void QVideoOutputDevice::showFrame(const QImage& img) void QVideoOutputDevice::showFrame(const QImage& img)
{ {
setPixmap(QPixmap::fromImage(img).scaled(minimumSize(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)) ; std::cerr << "img.size = " << img.width() << " x " << img.height() << std::endl;
setPixmap(QPixmap::fromImage(img).scaled( QSize(height()*640/480,height()),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)) ;
} }

View File

@ -2,6 +2,7 @@
#include <QLabel> #include <QLabel>
#include "interface/rsVOIP.h" #include "interface/rsVOIP.h"
#include "gui/VideoProcessor.h"
class VideoEncoder ; class VideoEncoder ;
class CvCapture ; class CvCapture ;
@ -31,7 +32,7 @@ class QVideoInputDevice: public QObject
// Captured images are sent to this encoder. Can be NULL. // Captured images are sent to this encoder. Can be NULL.
// //
void setVideoEncoder(VideoEncoder *venc) { _video_encoder = venc ; } void setVideoProcessor(VideoProcessor *venc) { _video_processor = venc ; }
// All images received will be echoed to this target. We could use signal/slots, but it's // All images received will be echoed to this target. We could use signal/slots, but it's
// probably faster this way. Can be NULL. // probably faster this way. Can be NULL.
@ -42,17 +43,23 @@ class QVideoInputDevice: public QObject
// //
bool getNextEncodedPacket(RsVOIPDataChunk&) ; bool getNextEncodedPacket(RsVOIPDataChunk&) ;
// gets the estimated current bandwidth required to transmit the encoded data, in B/s
//
uint32_t currentBandwidth() const ;
// control
void start() ; void start() ;
void stop() ; void stop() ;
bool stopped();
protected slots: protected slots:
void grabFrame() ; void grabFrame() ;
signals: signals:
void networkPacketReady() ; void networkPacketReady() ;
private: private:
VideoEncoder *_video_encoder ; VideoProcessor *_video_processor ;
QTimer *_timer ; QTimer *_timer ;
CvCapture *_capture_device ; CvCapture *_capture_device ;

View File

@ -123,8 +123,7 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
inputAudioDevice = NULL ; inputAudioDevice = NULL ;
inputVideoDevice = new QVideoInputDevice(mChatWidget) ; // not started yet ;-) inputVideoDevice = new QVideoInputDevice(mChatWidget) ; // not started yet ;-)
inputVideoProcessor = new JPEGVideoEncoder ; videoProcessor = new VideoProcessor ;
outputVideoProcessor = new JPEGVideoDecoder ;
// Make a widget with two video devices, one for echo, and one for the talking peer. // Make a widget with two video devices, one for echo, and one for the talking peer.
videoWidget = new QWidget(mChatWidget) ; videoWidget = new QWidget(mChatWidget) ;
@ -144,8 +143,8 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
mChatWidget->addChatHorizontalWidget(videoWidget) ; mChatWidget->addChatHorizontalWidget(videoWidget) ;
inputVideoDevice->setEchoVideoTarget(echoVideoDevice) ; inputVideoDevice->setEchoVideoTarget(echoVideoDevice) ;
inputVideoDevice->setVideoEncoder(inputVideoProcessor) ; inputVideoDevice->setVideoProcessor(videoProcessor) ;
outputVideoProcessor->setDisplayTarget(outputVideoDevice) ; videoProcessor->setDisplayTarget(outputVideoDevice) ;
} }
VOIPChatWidgetHolder::~VOIPChatWidgetHolder() VOIPChatWidgetHolder::~VOIPChatWidgetHolder()
@ -154,8 +153,7 @@ VOIPChatWidgetHolder::~VOIPChatWidgetHolder()
inputAudioDevice->stop() ; inputAudioDevice->stop() ;
delete inputVideoDevice ; delete inputVideoDevice ;
delete inputVideoProcessor ; delete videoProcessor ;
delete outputVideoProcessor ;
button_map::iterator it = buttonMapTakeVideo.begin(); button_map::iterator it = buttonMapTakeVideo.begin();
while (it != buttonMapTakeVideo.end()) { while (it != buttonMapTakeVideo.end()) {
@ -287,7 +285,8 @@ void VOIPChatWidgetHolder::toggleVideoCapture()
void VOIPChatWidgetHolder::addVideoData(const RsPeerId &peer_id, QByteArray* array) void VOIPChatWidgetHolder::addVideoData(const RsPeerId &peer_id, QByteArray* array)
{ {
if (!videoCaptureToggleButton->isChecked()) { if (!videoCaptureToggleButton->isChecked())
{
if (mChatWidget) { if (mChatWidget) {
QString buttonName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str()); QString buttonName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
if (buttonName.isEmpty()) buttonName = "VoIP";//TODO maybe change all with GxsId if (buttonName.isEmpty()) buttonName = "VoIP";//TODO maybe change all with GxsId
@ -317,11 +316,18 @@ void VOIPChatWidgetHolder::addVideoData(const RsPeerId &peer_id, QByteArray* arr
} }
//TODO make a sound for the incoming call //TODO make a sound for the incoming call
// soundManager->play(VOIP_SOUND_INCOMING_CALL); // soundManager->play(VOIP_SOUND_INCOMING_CALL);
if (mVOIPNotify) mVOIPNotify->notifyReceivedVoipVideoCall(peer_id); if (mVOIPNotify) mVOIPNotify->notifyReceivedVoipVideoCall(peer_id);
} else { }
outputVideoProcessor->receiveEncodedData((unsigned char *)array->data(),array->size()) ; else
{
RsVOIPDataChunk chunk ;
chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
chunk.size = array->size() ;
chunk.data = array->data() ;
videoProcessor->receiveEncodedData(chunk) ;
} }
} }
@ -359,7 +365,7 @@ void VOIPChatWidgetHolder::botMouseLeave()
void VOIPChatWidgetHolder::setAcceptedBandwidth(uint32_t bytes_per_sec) void VOIPChatWidgetHolder::setAcceptedBandwidth(uint32_t bytes_per_sec)
{ {
inputVideoProcessor->setMaximumFrameRate(bytes_per_sec) ; videoProcessor->setMaximumBandwidth(bytes_per_sec) ;
} }
void VOIPChatWidgetHolder::addAudioData(const RsPeerId &peer_id, QByteArray* array) void VOIPChatWidgetHolder::addAudioData(const RsPeerId &peer_id, QByteArray* array)

View File

@ -34,8 +34,7 @@ class QAudioInput;
class QAudioOutput; class QAudioOutput;
class QVideoInputDevice ; class QVideoInputDevice ;
class QVideoOutputDevice ; class QVideoOutputDevice ;
class VideoEncoder ; class VideoProcessor ;
class VideoDecoder ;
#define VOIP_SOUND_INCOMING_CALL "VOIP_incoming_call" #define VOIP_SOUND_INCOMING_CALL "VOIP_incoming_call"
@ -82,8 +81,7 @@ protected:
QWidget *videoWidget ; // pointer to call show/hide QWidget *videoWidget ; // pointer to call show/hide
VideoEncoder *inputVideoProcessor; VideoProcessor *videoProcessor;
VideoDecoder *outputVideoProcessor;
// Additional buttons to the chat bar // Additional buttons to the chat bar
QToolButton *audioListenToggleButton ; QToolButton *audioListenToggleButton ;

View File

@ -1,4 +1,6 @@
#include <iostream> #include <iostream>
#include <assert.h>
#include <malloc.h>
#include <QByteArray> #include <QByteArray>
#include <QBuffer> #include <QBuffer>
@ -7,67 +9,677 @@
#include "VideoProcessor.h" #include "VideoProcessor.h"
#include "QVideoDevice.h" #include "QVideoDevice.h"
VideoDecoder::VideoDecoder() #include <math.h>
#include <time.h>
#if defined(__MINGW32__)
#define memalign _aligned_malloc
#endif //MINGW
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
}
//#define DEBUG_MPEG_VIDEO 1
VideoProcessor::VideoProcessor()
:_encoded_frame_size(640,480) , vpMtx("VideoProcessor")
{ {
_output_device = NULL ; _decoded_output_device = NULL ;
//_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO;
_encoding_current_codec = VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO;
_estimated_bandwidth_in = 0 ;
_estimated_bandwidth_out = 0 ;
_target_bandwidth_out = 30*1024 ; // 30 KB/s
_total_encoded_size_in = 0 ;
_total_encoded_size_out = 0 ;
_last_bw_estimate_in_TS = time(NULL) ;
_last_bw_estimate_out_TS = time(NULL) ;
} }
bool VideoEncoder::addImage(const QImage& img) VideoProcessor::~VideoProcessor()
{ {
encodeData(img) ; // clear encoding queue
return true ; RS_STACK_MUTEX(vpMtx) ;
}
bool VideoEncoder::nextPacket(RsVOIPDataChunk& chunk) while(!_encoded_out_queue.empty())
{
if(_out_queue.empty())
return false ;
chunk = _out_queue.front() ;
_out_queue.pop_front() ;
return true ;
}
void VideoDecoder::receiveEncodedData(const unsigned char *data,uint32_t size)
{
_output_device->showFrame(decodeData(data,size)) ;
}
QImage JPEGVideoDecoder::decodeData(const unsigned char *encoded_image_data,uint32_t size)
{
QByteArray qb((char*)encoded_image_data,size) ;
QImage image ;
if(image.loadFromData(qb,"JPEG"))
return image ;
else
{ {
std::cerr << "image.loadFromData(): returned an error.: " << std::endl; _encoded_out_queue.back().clear() ;
return QImage() ; _encoded_out_queue.pop_back() ;
} }
} }
void VideoEncoder::setMaximumFrameRate(uint32_t bytes_per_sec) bool VideoProcessor::processImage(const QImage& img)
{ {
std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl; VideoCodec *codec ;
switch(_encoding_current_codec)
{
case VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO: codec = &_jpeg_video_codec ;
break ;
case VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO: codec = &_mpeg_video_codec ;
break ;
default:
codec = NULL ;
}
// std::cerr << "reducing to " << _frame_size.width() << " x " << _frame_size.height() << std::endl;
if(codec)
{
RsVOIPDataChunk chunk ;
if(codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),_target_bandwidth_out,chunk) && chunk.size > 0)
{
RS_STACK_MUTEX(vpMtx) ;
_encoded_out_queue.push_back(chunk) ;
_total_encoded_size_out += chunk.size ;
}
time_t now = time(NULL) ;
if(now > _last_bw_estimate_out_TS)
{
RS_STACK_MUTEX(vpMtx) ;
_estimated_bandwidth_out = uint32_t(0.75*_estimated_bandwidth_out + 0.25 * (_total_encoded_size_out / (float)(now - _last_bw_estimate_out_TS))) ;
_total_encoded_size_out = 0 ;
_last_bw_estimate_out_TS = now ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "new bw estimate: " << _estimated_bw << std::endl;
#endif
}
return true ;
}
else
{
std::cerr << "No codec for codec ID = " << _encoding_current_codec << ". Please call VideoProcessor::setCurrentCodec()" << std::endl;
return false ;
}
} }
bool VideoProcessor::nextEncodedPacket(RsVOIPDataChunk& chunk)
void JPEGVideoEncoder::encodeData(const QImage& image)
{ {
RS_STACK_MUTEX(vpMtx) ;
if(_encoded_out_queue.empty())
return false ;
chunk = _encoded_out_queue.front() ;
_encoded_out_queue.pop_front() ;
return true ;
}
void VideoProcessor::setInternalFrameSize(QSize s)
{
_encoded_frame_size = s ;
}
void VideoProcessor::receiveEncodedData(const RsVOIPDataChunk& chunk)
{
static const int HEADER_SIZE = 4 ;
// read frame type. Use first 4 bytes to give info about content.
//
// Byte Meaning Values
// 00 Codec CODEC_ID_JPEG_VIDEO Basic Jpeg codec
// CODEC_ID_DDWT_VIDEO Differential wavelet compression
//
// 01 Unused Might be useful later
//
// 0203 Flags Codec specific flags.
//
if(chunk.size < HEADER_SIZE)
{
std::cerr << "JPEGVideoDecoder::decodeData(): Too small a data packet. size=" << chunk.size << std::endl;
return ;
}
uint32_t codid = ((unsigned char *)chunk.data)[0] + (((unsigned char *)chunk.data)[1] << 8) ;
//uint16_t flags = ((unsigned char *)chunk.data)[2] + (((unsigned char *)chunk.data)[3] << 8) ;
VideoCodec *codec ;
switch(codid)
{
case VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO: codec = &_jpeg_video_codec ;
break ;
case VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO: codec = &_mpeg_video_codec ;
break ;
default:
codec = NULL ;
}
QImage img ;
if(codec == NULL)
{
std::cerr << "Unknown decoding codec: " << codid << std::endl;
return ;
}
{
RS_STACK_MUTEX(vpMtx) ;
_total_encoded_size_in += chunk.size ;
time_t now = time(NULL) ;
if(now > _last_bw_estimate_in_TS)
{
_estimated_bandwidth_in = uint32_t(0.75*_estimated_bandwidth_in + 0.25 * (_total_encoded_size_in / (float)(now - _last_bw_estimate_in_TS))) ;
_total_encoded_size_in = 0 ;
_last_bw_estimate_in_TS = now ;
#ifdef DEBUG_VIDEO_OUTPUT_DEVICE
std::cerr << "new bw estimate (in): " << _estimated_bandwidth_in << std::endl;
#endif
}
}
if(!codec->decodeData(chunk,img))
{
std::cerr << "No image decoded. Probably in the middle of something..." << std::endl;
return ;
}
if(_decoded_output_device)
_decoded_output_device->showFrame(img) ;
}
void VideoProcessor::setMaximumBandwidth(uint32_t bytes_per_sec)
{
std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl;
_target_bandwidth_out = bytes_per_sec ;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
JPEGVideo::JPEGVideo()
: _encoded_ref_frame_max_distance(10),_encoded_ref_frame_count(10)
{
}
bool JPEGVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
{
// now see if the frame is a differential frame, or just a reference frame.
uint16_t codec = ((unsigned char *)chunk.data)[0] + (((unsigned char *)chunk.data)[1] << 8) ;
uint16_t flags = ((unsigned char *)chunk.data)[2] + (((unsigned char *)chunk.data)[3] << 8) ;
assert(codec == VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO) ;
// un-compress image data
QByteArray qb((char*)&((uint8_t*)chunk.data)[HEADER_SIZE],(int)chunk.size - HEADER_SIZE) ;
if(!image.loadFromData(qb,"JPEG"))
{
std::cerr << "image.loadFromData(): returned an error.: " << std::endl;
return false ;
}
if(flags & JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME)
{
if(_decoded_reference_frame.size() != image.size())
{
std::cerr << "Bad reference frame!" << std::endl;
return false ;
}
QImage res = _decoded_reference_frame ;
for(int i=0;i<image.byteCount();++i)
{
int new_val = (int)res.bits()[i] + ((int)image.bits()[i] - 128) ;
res.bits()[i] = std::max(0,std::min(255,new_val)) ;
}
image = res ;
}
else
_decoded_reference_frame = image ;
return true ;
}
bool JPEGVideo::encodeData(const QImage& image,uint32_t /* size_hint */,RsVOIPDataChunk& voip_chunk)
{
// check if we make a diff image, or if we use the full frame.
QImage encoded_frame ;
bool differential_frame ;
if(_encoded_ref_frame_count++ < _encoded_ref_frame_max_distance && image.size() == _encoded_reference_frame.size())
{
// compute difference with reference frame.
encoded_frame = image ;
for(int i=0;i<image.byteCount();++i)
{
// We cannot use basic modulo 256 arithmetic, because the decompressed JPeg frames do not follow the same rules (values are clamped)
// and cause color blotches when perturbated by a differential frame.
int diff = ( (int)image.bits()[i] - (int)_encoded_reference_frame.bits()[i]) + 128;
encoded_frame.bits()[i] = (unsigned char)std::max(0,std::min(255,diff)) ;
}
differential_frame = true ;
}
else
{
_encoded_ref_frame_count = 0 ;
_encoded_reference_frame = image ;
encoded_frame = image ;
differential_frame = false ;
}
QByteArray qb ; QByteArray qb ;
QBuffer buffer(&qb) ; QBuffer buffer(&qb) ;
buffer.open(QIODevice::WriteOnly) ; buffer.open(QIODevice::WriteOnly) ;
image.save(&buffer,"JPEG") ; encoded_frame.save(&buffer,"JPEG") ;
RsVOIPDataChunk voip_chunk ; voip_chunk.data = malloc(HEADER_SIZE + qb.size());
voip_chunk.data = malloc(qb.size());
memcpy(voip_chunk.data,qb.data(),qb.size()) ; // build header
voip_chunk.size = qb.size() ; uint32_t flags = differential_frame ? JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME : 0x0 ;
((unsigned char *)voip_chunk.data)[0] = VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO & 0xff ;
((unsigned char *)voip_chunk.data)[1] = (VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO >> 8) & 0xff ;
((unsigned char *)voip_chunk.data)[2] = flags & 0xff ;
((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ;
memcpy(&((unsigned char*)voip_chunk.data)[HEADER_SIZE],qb.data(),qb.size()) ;
voip_chunk.size = HEADER_SIZE + qb.size() ;
voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ; voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
_out_queue.push_back(voip_chunk) ; return true ;
}
FFmpegVideo::FFmpegVideo()
{
// Encoding
encoding_codec = NULL ;
encoding_frame_buffer = NULL ;
encoding_context = NULL ;
//AVCodecID codec_id = AV_CODEC_ID_H264 ;
//AVCodecID codec_id = AV_CODEC_ID_MPEG2VIDEO;
AVCodecID codec_id = AV_CODEC_ID_MPEG4;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
/* find the mpeg1 video encoder */
encoding_codec = avcodec_find_encoder(codec_id);
if (!encoding_codec) throw("AV codec not found for codec id ") ;
encoding_context = avcodec_alloc_context3(encoding_codec);
if (!encoding_context) throw std::runtime_error("AV: Could not allocate video codec encoding context");
/* put sample parameters */
encoding_context->bit_rate = 10*1024 ; // default bitrate is 30KB/s
encoding_context->bit_rate_tolerance = encoding_context->bit_rate ;
#ifdef USE_VARIABLE_BITRATE
encoding_context->rc_min_rate = 0;
encoding_context->rc_max_rate = 10*1024;//encoding_context->bit_rate;
encoding_context->rc_buffer_size = 10*1024*1024;
encoding_context->rc_initial_buffer_occupancy = (int) ( 0.9 * encoding_context->rc_buffer_size);
encoding_context->rc_max_available_vbv_use = 1.0;
encoding_context->rc_min_vbv_overflow_use = 0.0;
#else
encoding_context->rc_min_rate = 0;
encoding_context->rc_max_rate = 0;
encoding_context->rc_buffer_size = 0;
#endif
encoding_context->flags |= CODEC_FLAG_PSNR;
encoding_context->flags |= CODEC_FLAG_TRUNCATED;
encoding_context->flags |= CODEC_CAP_PARAM_CHANGE;
encoding_context->i_quant_factor = 0.769f;
encoding_context->b_quant_factor = 1.4f;
encoding_context->time_base.num = 1;
encoding_context->time_base.den = 15;//framesPerSecond;
encoding_context->qmin = 1;
encoding_context->qmax = 51;
encoding_context->max_qdiff = 4;
//encoding_context->me_method = ME_HEX;
//encoding_context->max_b_frames = 4;
//encoding_context->flags |= CODEC_FLAG_LOW_DELAY; // MPEG2 only
//encoding_context->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
//encoding_context->crf = 0.0f;
//encoding_context->cqp = 26;
/* resolution must be a multiple of two */
encoding_context->width = 640;//176;
encoding_context->height = 480;//144;
/* frames per second */
encoding_context->time_base = (AVRational){1,25};
/* emit one intra frame every ten frames
* check frame pict_type before passing frame
* to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
* then gop_size is ignored and the output of encoder
* will always be I frame irrespective to gop_size
*/
encoding_context->gop_size = 100;
//encoding_context->max_b_frames = 1;
encoding_context->pix_fmt = AV_PIX_FMT_YUV420P; //context->pix_fmt = AV_PIX_FMT_RGB24;
if (codec_id == AV_CODEC_ID_H264)
av_opt_set(encoding_context->priv_data, "preset", "slow", 0);
/* open it */
if (avcodec_open2(encoding_context, encoding_codec, NULL) < 0)
throw std::runtime_error( "AV: Could not open codec context. Something's wrong.");
encoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
if(!encoding_frame_buffer)
throw std::runtime_error("AV: could not allocate frame buffer.") ;
encoding_frame_buffer->format = encoding_context->pix_fmt;
encoding_frame_buffer->width = encoding_context->width;
encoding_frame_buffer->height = encoding_context->height;
/* the image can be allocated by any means and av_image_alloc() is
* just the most convenient way if av_malloc() is to be used */
int ret = av_image_alloc(encoding_frame_buffer->data, encoding_frame_buffer->linesize,
encoding_context->width, encoding_context->height, encoding_context->pix_fmt, 32);
if (ret < 0)
throw std::runtime_error("AV: Could not allocate raw picture buffer");
encoding_frame_count = 0 ;
// Decoding
decoding_codec = avcodec_find_decoder(codec_id);
if (!decoding_codec)
throw("AV codec not found for codec id ") ;
decoding_context = avcodec_alloc_context3(decoding_codec);
if(!decoding_context)
throw std::runtime_error("AV: Could not allocate video codec decoding context");
decoding_context->width = encoding_context->width;
decoding_context->height = encoding_context->height;
decoding_context->pix_fmt = AV_PIX_FMT_YUV420P;
if(decoding_codec->capabilities & CODEC_CAP_TRUNCATED)
decoding_context->flags |= CODEC_FLAG_TRUNCATED; // we do not send complete frames
if(avcodec_open2(decoding_context,decoding_codec,NULL) < 0)
throw("AV codec open action failed! ") ;
decoding_frame_buffer = avcodec_alloc_frame() ;//(AVFrame*)malloc(sizeof(AVFrame)) ;
av_init_packet(&decoding_buffer);
decoding_buffer.data = NULL ;
decoding_buffer.size = 0 ;
//ret = av_image_alloc(decoding_frame_buffer->data, decoding_frame_buffer->linesize, decoding_context->width, decoding_context->height, decoding_context->pix_fmt, 32);
//if (ret < 0)
//throw std::runtime_error("AV: Could not allocate raw picture buffer");
// debug
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Dumping captured data to file tmpvideo.mpg" << std::endl;
encoding_debug_file = fopen("tmpvideo.mpg","w") ;
#endif
}
FFmpegVideo::~FFmpegVideo()
{
avcodec_close(encoding_context);
avcodec_close(decoding_context);
av_free(encoding_context);
av_free(decoding_context);
av_freep(&encoding_frame_buffer->data[0]);
av_freep(&decoding_frame_buffer->data[0]);
free(encoding_frame_buffer);
free(decoding_frame_buffer);
}
#define MAX_FFMPEG_ENCODING_BITRATE 81920
bool FFmpegVideo::encodeData(const QImage& image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& voip_chunk)
{
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Encoding frame of size " << image.width() << "x" << image.height() << ", resized to " << encoding_frame_buffer->width << "x" << encoding_frame_buffer->height << " : ";
#endif
QImage input ;
if(target_encoding_bitrate > MAX_FFMPEG_ENCODING_BITRATE)
{
std::cerr << "Max encodign bitrate eexceeded. Capping to " << MAX_FFMPEG_ENCODING_BITRATE << std::endl;
target_encoding_bitrate = MAX_FFMPEG_ENCODING_BITRATE ;
}
//encoding_context->bit_rate = target_encoding_bitrate;
encoding_context->rc_max_rate = target_encoding_bitrate;
//encoding_context->bit_rate_tolerance = target_encoding_bitrate;
if(image.width() != encoding_frame_buffer->width || image.height() != encoding_frame_buffer->height)
input = image.scaled(QSize(encoding_frame_buffer->width,encoding_frame_buffer->height),Qt::IgnoreAspectRatio,Qt::SmoothTransformation) ;
else
input = image ;
/* prepare a dummy image */
/* Y */
for (int y = 0; y < encoding_context->height/2; y++)
for (int x = 0; x < encoding_context->width/2; x++)
{
QRgb pix00 = input.pixel(QPoint(2*x+0,2*y+0)) ;
QRgb pix01 = input.pixel(QPoint(2*x+0,2*y+1)) ;
QRgb pix10 = input.pixel(QPoint(2*x+1,2*y+0)) ;
QRgb pix11 = input.pixel(QPoint(2*x+1,2*y+1)) ;
int R00 = (pix00 >> 16) & 0xff ; int G00 = (pix00 >> 8) & 0xff ; int B00 = (pix00 >> 0) & 0xff ;
int R01 = (pix01 >> 16) & 0xff ; int G01 = (pix01 >> 8) & 0xff ; int B01 = (pix01 >> 0) & 0xff ;
int R10 = (pix10 >> 16) & 0xff ; int G10 = (pix10 >> 8) & 0xff ; int B10 = (pix10 >> 0) & 0xff ;
int R11 = (pix11 >> 16) & 0xff ; int G11 = (pix11 >> 8) & 0xff ; int B11 = (pix11 >> 0) & 0xff ;
int Y00 = (0.257 * R00) + (0.504 * G00) + (0.098 * B00) + 16 ;
int Y01 = (0.257 * R01) + (0.504 * G01) + (0.098 * B01) + 16 ;
int Y10 = (0.257 * R10) + (0.504 * G10) + (0.098 * B10) + 16 ;
int Y11 = (0.257 * R11) + (0.504 * G11) + (0.098 * B11) + 16 ;
float R = 0.25*(R00+R01+R10+R11) ;
float G = 0.25*(G00+G01+G10+G11) ;
float B = 0.25*(B00+B01+B10+B11) ;
int U = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 ;
int V = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 ;
encoding_frame_buffer->data[0][(2*y+0) * encoding_frame_buffer->linesize[0] + 2*x+0] = std::min(255,std::max(0,Y00)); // Y
encoding_frame_buffer->data[0][(2*y+0) * encoding_frame_buffer->linesize[0] + 2*x+1] = std::min(255,std::max(0,Y01)); // Y
encoding_frame_buffer->data[0][(2*y+1) * encoding_frame_buffer->linesize[0] + 2*x+0] = std::min(255,std::max(0,Y10)); // Y
encoding_frame_buffer->data[0][(2*y+1) * encoding_frame_buffer->linesize[0] + 2*x+1] = std::min(255,std::max(0,Y11)); // Y
encoding_frame_buffer->data[1][y * encoding_frame_buffer->linesize[1] + x] = std::min(255,std::max(0,U));// Cr
encoding_frame_buffer->data[2][y * encoding_frame_buffer->linesize[2] + x] = std::min(255,std::max(0,V));// Cb
}
encoding_frame_buffer->pts = encoding_frame_count++;
/* encode the image */
int got_output = 0;
AVFrame *frame = encoding_frame_buffer ;
AVPacket pkt ;
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
// do
// {
int ret = avcodec_encode_video2(encoding_context, &pkt, frame, &got_output) ;
if (ret < 0)
{
std::cerr << "Error encoding frame!" << std::endl;
return false ;
}
// frame = NULL ; // next attempts: do not encode anything. Do this to just flush the buffer
//
// } while(got_output) ;
if(got_output)
{
voip_chunk.data = malloc(pkt.size + HEADER_SIZE) ;
uint32_t flags = 0;
((unsigned char *)voip_chunk.data)[0] = VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO & 0xff ;
((unsigned char *)voip_chunk.data)[1] = (VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO >> 8) & 0xff ;
((unsigned char *)voip_chunk.data)[2] = flags & 0xff ;
((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ;
memcpy(&((unsigned char*)voip_chunk.data)[HEADER_SIZE],pkt.data,pkt.size) ;
voip_chunk.size = pkt.size + HEADER_SIZE;
voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Output : " << pkt.size << " bytes." << std::endl;
fwrite(pkt.data,1,pkt.size,encoding_debug_file) ;
fflush(encoding_debug_file) ;
#endif
av_free_packet(&pkt);
return true ;
}
else
{
voip_chunk.data = NULL;
voip_chunk.size = 0;
voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
std::cerr << "No output produced." << std::endl;
return false ;
}
}
bool FFmpegVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image)
{
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Decoding data of size " << chunk.size << std::endl;
#endif
unsigned char *buff ;
if(decoding_buffer.data != NULL)
{
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Completing buffer with size " << chunk.size - HEADER_SIZE + decoding_buffer.size << ": copying existing "
<< decoding_buffer.size << " bytes. Adding new " << chunk.size - HEADER_SIZE<< " bytes " << std::endl;
#endif
uint32_t s = chunk.size - HEADER_SIZE + decoding_buffer.size ;
unsigned char *tmp = (unsigned char*)memalign(16,s + FF_INPUT_BUFFER_PADDING_SIZE) ;
memset(tmp,0,s+FF_INPUT_BUFFER_PADDING_SIZE) ;
memcpy(tmp,decoding_buffer.data,decoding_buffer.size) ;
free(decoding_buffer.data) ;
buff = &tmp[decoding_buffer.size] ;
decoding_buffer.size = s ;
decoding_buffer.data = tmp ;
}
else
{
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Allocating new buffer of size " << chunk.size - HEADER_SIZE << std::endl;
#endif
decoding_buffer.data = (unsigned char *)memalign(16,chunk.size - HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE) ;
decoding_buffer.size = chunk.size - HEADER_SIZE ;
memset(decoding_buffer.data,0,decoding_buffer.size + FF_INPUT_BUFFER_PADDING_SIZE) ;
buff = decoding_buffer.data ;
}
memcpy(buff,&((unsigned char*)chunk.data)[HEADER_SIZE],chunk.size - HEADER_SIZE) ;
int got_frame = 0 ;
int len = avcodec_decode_video2(decoding_context,decoding_frame_buffer,&got_frame,&decoding_buffer) ;
if(len < 0)
{
std::cerr << "Error decodign frame!" << std::endl;
return false ;
}
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Used " << len << " bytes out of " << decoding_buffer.size << ". got_frame = " << got_frame << std::endl;
#endif
if(got_frame)
{
image = QImage(QSize(decoding_frame_buffer->width,decoding_frame_buffer->height),QImage::Format_ARGB32) ;
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Decoded frame. Size=" << image.width() << "x" << image.height() << std::endl;
#endif
for (int y = 0; y < decoding_frame_buffer->height; y++)
for (int x = 0; x < decoding_frame_buffer->width; x++)
{
int Y = decoding_frame_buffer->data[0][y * decoding_frame_buffer->linesize[0] + x] ;
int U = decoding_frame_buffer->data[1][(y/2) * decoding_frame_buffer->linesize[1] + x/2] ;
int V = decoding_frame_buffer->data[2][(y/2) * decoding_frame_buffer->linesize[2] + x/2] ;
int B = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 1.596*(V - 128)))) ;
int G = std::min(255,std::max(0,(int)(1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128)))) ;
int R = std::min(255,std::max(0,(int)(1.164*(Y - 16) + 2.018*(U - 128)))) ;
image.setPixel(QPoint(x,y),QRgb( 0xff000000 + (R << 16) + (G << 8) + B)) ;
}
}
if(len == decoding_buffer.size)
{
free(decoding_buffer.data) ;
decoding_buffer.data = NULL;
decoding_buffer.size = 0;
}
else if(len != 0)
{
#ifdef DEBUG_MPEG_VIDEO
std::cerr << "Moving remaining data (" << decoding_buffer.size - len << " bytes) back to 0" << std::endl;
#endif
memmove(decoding_buffer.data,decoding_buffer.data+len,decoding_buffer.size - len) ;
decoding_buffer.size -= len ;
}
return true ;
} }

View File

@ -4,87 +4,149 @@
#include <QImage> #include <QImage>
#include "interface/rsVOIP.h" #include "interface/rsVOIP.h"
extern "C" {
#include <libavcodec/avcodec.h>
}
class QVideoOutputDevice ; class QVideoOutputDevice ;
// This class decodes video from a stream. It keeps a queue of class VideoCodec
// decoded frame that needs to be retrieved using the getNextImage() method.
//
class VideoDecoder
{ {
public: public:
VideoDecoder() ; virtual bool encodeData(const QImage& Image, uint32_t size_hint, RsVOIPDataChunk& chunk) = 0;
virtual ~VideoDecoder() {} virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) = 0;
// Gets the next image to be displayed. Once returned, the image should protected:
// be cleared from the incoming queue. static const uint32_t HEADER_SIZE = 0x04 ;
//
void setDisplayTarget(QVideoOutputDevice *odev) { _output_device = odev ; }
virtual void receiveEncodedData(const unsigned char *data,uint32_t size) ;
// returns the current (measured) frame rate in bytes per second.
//
uint32_t currentFrameRate() const;
private:
QVideoOutputDevice *_output_device ;
std::list<QImage> _image_queue ;
// Incoming data is processed by a video codec and converted into images.
//
virtual QImage decodeData(const unsigned char *encoded_image,uint32_t encoded_image_size) = 0 ;
// // This buffer accumulated incoming encoded data, until a full packet is obtained,
// // since the stream might not send images at once. When incoming images are decoded, the
// // data is removed from the buffer.
// //
// unsigned char *buffer ;
// uint32_t buffer_size ;
};
// This class encodes video using a video codec (possibly homemade, or based on existing codecs)
// and produces a data stream that is sent to the network transfer service (e.g. p3VOIP).
//
class VideoEncoder
{
public:
VideoEncoder() {}
virtual ~VideoEncoder() {}
// Takes the next image to be encoded.
//
bool addImage(const QImage& Image) ;
bool packetReady() const { return !_out_queue.empty() ; }
bool nextPacket(RsVOIPDataChunk& ) ;
// Used to tweak the compression ratio so that the video can stream ok.
//
void setMaximumFrameRate(uint32_t bytes_per_second) ;
protected:
//virtual bool sendEncodedData(unsigned char *mem,uint32_t size) = 0 ;
virtual void encodeData(const QImage& image) = 0 ;
std::list<RsVOIPDataChunk> _out_queue ;
}; };
// Now derive various image encoding/decoding algorithms. // Now derive various image encoding/decoding algorithms.
// //
class JPEGVideoDecoder: public VideoDecoder class JPEGVideo: public VideoCodec
{ {
protected: public:
virtual QImage decodeData(const unsigned char *encoded_image,uint32_t encoded_image_size) ; JPEGVideo() ;
protected:
virtual bool encodeData(const QImage& Image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& chunk) ;
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
static const uint32_t JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME = 0x0001 ;
private:
QImage _decoded_reference_frame ;
QImage _encoded_reference_frame ;
uint32_t _encoded_ref_frame_max_distance ; // max distance between two reference frames.
uint32_t _encoded_ref_frame_count ;
}; };
class JPEGVideoEncoder: public VideoEncoder struct AVCodec ;
struct AVCodecContext ;
struct AVFrame ;
struct AVPacket ;
class FFmpegVideo: public VideoCodec
{
public:
FFmpegVideo() ;
~FFmpegVideo() ;
protected:
virtual bool encodeData(const QImage& Image, uint32_t target_encoding_bitrate, RsVOIPDataChunk& chunk) ;
virtual bool decodeData(const RsVOIPDataChunk& chunk,QImage& image) ;
private:
AVCodec *encoding_codec;
AVCodec *decoding_codec;
AVCodecContext *encoding_context;
AVCodecContext *decoding_context;
AVFrame *encoding_frame_buffer ;
AVFrame *decoding_frame_buffer ;
AVPacket decoding_buffer;
uint64_t encoding_frame_count ;
FILE *encoding_debug_file ;
};
// This class decodes video from a stream. It keeps a queue of
// decoded frame that needs to be retrieved using the getNextImage() method.
//
class VideoProcessor
{ {
public: public:
JPEGVideoEncoder() {} VideoProcessor() ;
virtual ~VideoProcessor() ;
enum CodecId {
VIDEO_PROCESSOR_CODEC_ID_UNKNOWN = 0x0000,
VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO = 0x0001,
VIDEO_PROCESSOR_CODEC_ID_DDWT_VIDEO = 0x0002,
VIDEO_PROCESSOR_CODEC_ID_MPEG_VIDEO = 0x0003
};
// =====================================================================================
// =------------------------------------ DECODING -------------------------------------=
// =====================================================================================
// Gets the next image to be displayed. Once returned, the image should
// be cleared from the incoming queue.
//
void setDisplayTarget(QVideoOutputDevice *odev) { _decoded_output_device = odev ; }
virtual void receiveEncodedData(const RsVOIPDataChunk& chunk) ;
// returns the current (measured) frame rate in bytes per second.
//
uint32_t currentBandwidthIn() const { return _estimated_bandwidth_in ; }
private:
QVideoOutputDevice *_decoded_output_device ;
std::list<QImage> _decoded_image_queue ;
// =====================================================================================
// =------------------------------------ ENCODING -------------------------------------=
// =====================================================================================
public:
// Takes the next image to be encoded.
//
bool processImage(const QImage& Image) ;
bool encodedPacketReady() const { return !_encoded_out_queue.empty() ; }
bool nextEncodedPacket(RsVOIPDataChunk& ) ;
// Used to tweak the compression ratio so that the video can stream ok.
//
void setMaximumBandwidth(uint32_t bytes_per_second) ;
void setInternalFrameSize(QSize) ;
// returns the current encoding frame rate in bytes per second.
//
uint32_t currentBandwidthOut() const { return _estimated_bandwidth_out ; }
protected: protected:
virtual void encodeData(const QImage& Image) ; std::list<RsVOIPDataChunk> _encoded_out_queue ;
QSize _encoded_frame_size ;
// =====================================================================================
// =------------------------------------- Codecs --------------------------------------=
// =====================================================================================
JPEGVideo _jpeg_video_codec ;
FFmpegVideo _mpeg_video_codec ;
uint16_t _encoding_current_codec ;
time_t _last_bw_estimate_in_TS;
time_t _last_bw_estimate_out_TS;
uint32_t _total_encoded_size_in ;
uint32_t _total_encoded_size_out ;
float _estimated_bandwidth_in ;
float _estimated_bandwidth_out ;
float _target_bandwidth_out ;
RsMutex vpMtx ;
}; };

View File

@ -51,7 +51,9 @@ class RsVOIPPongResult
struct RsVOIPDataChunk struct RsVOIPDataChunk
{ {
typedef enum { RS_VOIP_DATA_TYPE_AUDIO, RS_VOIP_DATA_TYPE_VIDEO } RsVOIPDataType ; typedef enum { RS_VOIP_DATA_TYPE_UNKNOWN = 0x00,
RS_VOIP_DATA_TYPE_AUDIO = 0x01,
RS_VOIP_DATA_TYPE_VIDEO = 0x02 } RsVOIPDataType ;
void *data ; // create/delete using malloc/free. void *data ; // create/delete using malloc/free.
uint32_t size ; uint32_t size ;

View File

@ -76,6 +76,19 @@ std::ostream& RsVOIPProtocolItem::print(std::ostream &out, uint16_t indent)
printRsItemEnd(out, "RsVOIPProtocolItem", indent); printRsItemEnd(out, "RsVOIPProtocolItem", indent);
return out; return out;
} }
std::ostream& RsVOIPBandwidthItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsVOIPBandwidthItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << "flags: " << std::hex << flags << std::dec << std::endl;
printIndent(out, int_Indent);
out << "speed: " << bytes_per_sec << std::endl;
printRsItemEnd(out, "RsVOIPBandwidthItem", indent);
return out;
}
std::ostream& RsVOIPDataItem::print(std::ostream &out, uint16_t indent) std::ostream& RsVOIPDataItem::print(std::ostream &out, uint16_t indent)
{ {
printRsItemBase(out, "RsVOIPDataItem", indent); printRsItemBase(out, "RsVOIPDataItem", indent);
@ -100,6 +113,14 @@ uint32_t RsVOIPDataItem::serial_size() const
return s; return s;
} }
uint32_t RsVOIPBandwidthItem::serial_size() const
{
uint32_t s = 8; /* header */
s += 4; /* flags */
s += 4; /* bandwidth */
return s;
}
uint32_t RsVOIPProtocolItem::serial_size() const uint32_t RsVOIPProtocolItem::serial_size() const
{ {
uint32_t s = 8; /* header */ uint32_t s = 8; /* header */
@ -150,6 +171,40 @@ bool RsVOIPProtocolItem::serialise(void *data, uint32_t& pktsize)
return ok; return ok;
} }
bool RsVOIPBandwidthItem::serialise(void *data, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
#ifdef RSSERIAL_DEBUG
std::cerr << "RsVOIPSerialiser::serialiseVOIPBandwidthItem() Header: " << ok << std::endl;
std::cerr << "RsVOIPSerialiser::serialiseVOIPBandwidthItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, flags);
ok &= setRawUInt32(data, tlvsize, &offset, bytes_per_sec);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsVOIPSerialiser::serialiseVOIPBandwidthItem() Size Error! " << std::endl;
}
return ok;
}
/* serialise the data to the buffer */ /* serialise the data to the buffer */
bool RsVOIPDataItem::serialise(void *data, uint32_t& pktsize) bool RsVOIPDataItem::serialise(void *data, uint32_t& pktsize)
{ {
@ -254,6 +309,36 @@ RsVOIPProtocolItem::RsVOIPProtocolItem(void *data, uint32_t pktsize)
if (!ok) if (!ok)
throw std::runtime_error("Deserialisation error!") ; throw std::runtime_error("Deserialisation error!") ;
} }
RsVOIPBandwidthItem::RsVOIPBandwidthItem(void *data, uint32_t pktsize)
: RsVOIPItem(RS_PKT_SUBTYPE_VOIP_BANDWIDTH)
{
/* get the type and size */
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
uint32_t offset = 0;
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_VOIP_PLUGIN != getRsItemService(rstype)) || (RS_PKT_SUBTYPE_VOIP_BANDWIDTH != getRsItemSubType(rstype)))
throw std::runtime_error("Wrong packet type!") ;
if (pktsize < rssize) /* check size */
throw std::runtime_error("Not enough size!") ;
bool ok = true;
/* skip the header */
offset += 8;
/* get mandatory parts first */
ok &= getRawUInt32(data, rssize, &offset, &flags);
ok &= getRawUInt32(data, rssize, &offset, &bytes_per_sec);
if (offset != rssize)
throw std::runtime_error("Deserialisation error!") ;
if (!ok)
throw std::runtime_error("Deserialisation error!") ;
}
RsVOIPPingItem::RsVOIPPingItem(void *data, uint32_t pktsize) RsVOIPPingItem::RsVOIPPingItem(void *data, uint32_t pktsize)
: RsVOIPItem(RS_PKT_SUBTYPE_VOIP_PING) : RsVOIPItem(RS_PKT_SUBTYPE_VOIP_PING)
{ {

View File

@ -58,8 +58,9 @@ const uint16_t RS_SERVICE_TYPE_VOIP_PLUGIN = 0xa021;
const uint8_t RS_PKT_SUBTYPE_VOIP_PING = 0x01; const uint8_t RS_PKT_SUBTYPE_VOIP_PING = 0x01;
const uint8_t RS_PKT_SUBTYPE_VOIP_PONG = 0x02; const uint8_t RS_PKT_SUBTYPE_VOIP_PONG = 0x02;
const uint8_t RS_PKT_SUBTYPE_VOIP_PROTOCOL = 0x03 ; const uint8_t RS_PKT_SUBTYPE_VOIP_PROTOCOL = 0x03 ;
// 0x04 is unused because of a change in the protocol // 0x04,0x05 is unused because of a change in the protocol
const uint8_t RS_PKT_SUBTYPE_VOIP_DATA = 0x05 ; const uint8_t RS_PKT_SUBTYPE_VOIP_BANDWIDTH = 0x06 ;
const uint8_t RS_PKT_SUBTYPE_VOIP_DATA = 0x07 ;
const uint8_t QOS_PRIORITY_RS_VOIP = 9 ; const uint8_t QOS_PRIORITY_RS_VOIP = 9 ;
@ -117,9 +118,27 @@ class RsVOIPDataItem: public RsVOIPItem
uint32_t flags ; uint32_t flags ;
uint32_t data_size ; uint32_t data_size ;
void *voip_data ; void *voip_data ;
}; };
class RsVOIPBandwidthItem: public RsVOIPItem
{
public:
RsVOIPBandwidthItem() :RsVOIPItem(RS_PKT_SUBTYPE_VOIP_BANDWIDTH) {}
RsVOIPBandwidthItem(void *data,uint32_t size) ; // de-serialization
virtual bool serialise(void *data,uint32_t& size) ;
virtual uint32_t serial_size() const ;
virtual ~RsVOIPBandwidthItem() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
uint32_t flags ; // is that incoming or expected bandwidth?
uint32_t bytes_per_sec ; // bandwidth in bytes per sec.
};
class RsVOIPProtocolItem: public RsVOIPItem class RsVOIPProtocolItem: public RsVOIPItem
{ {
public: public:

View File

@ -19,6 +19,8 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
****************************************************************/ ****************************************************************/
#include <QApplication>
#include <QClipboard>
#include <QMimeData> #include <QMimeData>
#include <QTextDocumentFragment> #include <QTextDocumentFragment>
#include <QCompleter> #include <QCompleter>
@ -228,6 +230,7 @@ void MimeTextEdit::contextMenuEvent(QContextMenuEvent *e)
QMenu *contextMenu = createStandardContextMenu(e->pos()); QMenu *contextMenu = createStandardContextMenu(e->pos());
/* Add actions for pasting links */ /* Add actions for pasting links */
contextMenu->addAction( tr("Paste as plain text"), this, SLOT(pastePlainText()));
contextMenu->addSeparator(); contextMenu->addSeparator();
QAction *pasteLinkAction = contextMenu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); QAction *pasteLinkAction = contextMenu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink()));
contextMenu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste my certificate link"), this, SLOT(pasteOwnCertificateLink())); contextMenu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste my certificate link"), this, SLOT(pasteOwnCertificateLink()));
@ -260,3 +263,8 @@ void MimeTextEdit::pasteOwnCertificateLink()
insertHtml(link.toHtml() + " "); insertHtml(link.toHtml() + " ");
} }
} }
void MimeTextEdit::pastePlainText()
{
insertPlainText(QApplication::clipboard()->text());
}

View File

@ -58,7 +58,7 @@ private slots:
void insertCompletion(const QString &completion); void insertCompletion(const QString &completion);
void pasteLink(); void pasteLink();
void pasteOwnCertificateLink(); void pasteOwnCertificateLink();
void pastePlainText();
private: private:
QString textUnderCursor() const; QString textUnderCursor() const;

View File

@ -1,5 +1,8 @@
QT += network xml script !include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
QT += network xml
CONFIG += qt gui uic qrc resources idle bitdht CONFIG += qt gui uic qrc resources idle bitdht
CONFIG += link_prl
# Plz never commit the .pro with these flags enabled. # Plz never commit the .pro with these flags enabled.
# Use this flag when developping new features only. # Use this flag when developping new features only.
@ -73,47 +76,20 @@ linux-* {
QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 LIBS *= -lX11 -lXss
LIBS += -lssl -lupnp -lixml -lXss -lgnome-keyring
LIBS *= -lcrypto -ldl -lX11 -lz
LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) #LIBS *= -lglib-2.0
isEmpty(SQLCIPHER_OK) { LIBS *= -rdynamic -ldl
# We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database.
exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) {
LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a
DEPENDPATH += ../../../lib/sqlcipher/src/
INCLUDEPATH += ../../../lib/sqlcipher/src/
DEPENDPATH += ../../../lib/sqlcipher/tsrc/
INCLUDEPATH += ../../../lib/sqlcipher/tsrc/
} else {
message(libsqlcipher.a not found. Compilation will not use SQLCIPHER. Database will be unencrypted.)
DEFINES *= NO_SQLCIPHER
LIBS *= -lsqlite3
}
} else {
LIBS += -lsqlcipher
}
LIBS *= -lglib-2.0
LIBS *= -rdynamic
DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions
DEFINES *= UBUNTU DEFINES *= UBUNTU
} }
unix { unix {
isEmpty(PREFIX) { PREFIX = /usr } target.path = "$${BIN_DIR}"
isEmpty(DATA_DIR) { DATA_DIR = "$${PREFIX}/share/RetroShare06" }
target.path = "$${PREFIX}/bin"
INSTALLS += target INSTALLS += target
data_files.path="$${DATA_DIR}/" data_files.path="$${DATA_DIR}/"
@ -123,6 +99,22 @@ unix {
style_files.path="$${DATA_DIR}/stylesheets" style_files.path="$${DATA_DIR}/stylesheets"
style_files.files=gui/qss/chat/Bubble gui/qss/chat/Bubble_Compact style_files.files=gui/qss/chat/Bubble gui/qss/chat/Bubble_Compact
INSTALLS += style_files INSTALLS += style_files
icon_files.path = "$${PREFIX}/share/icons/hicolor"
icon_files.files = ../../data/24x24
icon_files.files += ../../data/48x48
icon_files.files += ../../data/64x64
icon_files.files += ../../data/128x128
INSTALLS += icon_files
desktop_files.path = "$${PREFIX}/share/applications"
desktop_files.files = ../../data/retroshare06.desktop
INSTALLS += desktop_files
pixmap_files.path = "$${PREFIX}/share/pixmaps"
pixmap_files.files = ../../data/retroshare06.xpm
INSTALLS += pixmap_files
} }
linux-g++ { linux-g++ {
@ -183,6 +175,9 @@ win32 {
QMAKE_CFLAGS += -Wextra QMAKE_CFLAGS += -Wextra
QMAKE_CXXFLAGS += -Wextra QMAKE_CXXFLAGS += -Wextra
# solve linker warnings because of the order of the libraries
QMAKE_LFLAGS += -Wl,--start-group
# Switch off optimization for release version # Switch off optimization for release version
QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -O0 QMAKE_CXXFLAGS_RELEASE += -O0
@ -198,20 +193,16 @@ win32 {
#QTPLUGIN += qjpeg #QTPLUGIN += qjpeg
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS_DIR = $$PWD/../../../libs LIBS_DIR = $$PWD/../../../libs
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -L"$$LIBS_DIR/lib" LIBS += -L"$$LIBS_DIR/lib"
LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
LIBS += -lsqlcipher LIBS += -lsqlcipher
LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz -lws2_32
# added after bitdht
# LIBS += -lws2_32
LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32
LIBS += -lole32 -lwinmm LIBS += -lole32 -lwinmm
RC_FILE = gui/images/retroshare_win.rc RC_FILE = gui/images/retroshare_win.rc
@ -248,7 +239,6 @@ macx {
CONFIG += version_detail_bash_script CONFIG += version_detail_bash_script
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -lssl -lcrypto -lz LIBS += -lssl -lcrypto -lz
#LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan #LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan
LIBS += ../../../miniupnpc-1.0/libminiupnpc.a LIBS += ../../../miniupnpc-1.0/libminiupnpc.a
@ -286,10 +276,8 @@ openbsd-* {
INCLUDEPATH *= /usr/local/include INCLUDEPATH *= /usr/local/include
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS *= ../../libretroshare/src/lib/libretroshare.a LIBS *= ../../libretroshare/src/lib/libretroshare.a
LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS *= -lssl -lcrypto LIBS *= -lssl -lcrypto
LIBS *= -lgpgme LIBS *= -lgpgme
LIBS *= -lupnp LIBS *= -lupnp
@ -311,11 +299,6 @@ openbsd-* {
# ########################################### # ###########################################
bitdht {
LIBS += ../../libbitdht/src/lib/libbitdht.a
PRE_TARGETDEPS *= ../../libbitdht/src/lib/libbitdht.a
}
DEPENDPATH += . ../../libretroshare/src/ DEPENDPATH += . ../../libretroshare/src/
INCLUDEPATH += ../../libretroshare/src/ INCLUDEPATH += ../../libretroshare/src/
@ -325,11 +308,6 @@ INCLUDEPATH += ../../libresapi/src
PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a
LIBS += ../../libresapi/src/lib/libresapi.a -lmicrohttpd LIBS += ../../libresapi/src/lib/libresapi.a -lmicrohttpd
win32 {
# must be added after bitdht
LIBS += -lws2_32
}
# Input # Input
HEADERS += rshare.h \ HEADERS += rshare.h \
retroshare-gui/configpage.h \ retroshare-gui/configpage.h \

View File

@ -1,3 +1,5 @@
!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri")
TEMPLATE = app TEMPLATE = app
TARGET = RetroShare06-nogui TARGET = RetroShare06-nogui
CONFIG += bitdht CONFIG += bitdht
@ -6,6 +8,7 @@ CONFIG += bitdht
# webinterface, requires libmicrohttpd # webinterface, requires libmicrohttpd
CONFIG += webui CONFIG += webui
CONFIG -= qt xml gui CONFIG -= qt xml gui
CONFIG += link_prl
# if you are linking against the libretroshare with gxs. # if you are linking against the libretroshare with gxs.
# this option links against the required sqlite library. # this option links against the required sqlite library.
@ -28,37 +31,11 @@ linux-* {
QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 LIBS *= -rdynamic -ldl
LIBS += -lssl -lupnp -lixml -lgnome-keyring
LIBS *= -lcrypto -ldl -lz -lpthread
LIBS *= -rdynamic
gxs {
SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes)
isEmpty(SQLCIPHER_OK) {
# We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database.
exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) {
LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a
DEPENDPATH += ../../../lib/sqlcipher/src/
INCLUDEPATH += ../../../lib/sqlcipher/src/
} else {
message(libsqlcipher.a not found. Compilation will not use SQLCIPHER. Database will be unencrypted.)
DEFINES *= NO_SQLCIPHER
LIBS *= -lsqlite3
}
} else {
LIBS *= -lsqlcipher
}
}
} }
unix { unix {
isEmpty(PREFIX) { PREFIX = /usr } target.path = "$${BIN_DIR}"
target.path = "$${PREFIX}/bin"
INSTALLS += target INSTALLS += target
} }
@ -98,17 +75,17 @@ win32 {
UI_DIR = temp/ui UI_DIR = temp/ui
MOC_DIR = temp/moc MOC_DIR = temp/moc
# solve linker warnings because of the order of the libraries
QMAKE_LFLAGS += -Wl,--start-group
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS_DIR = $$PWD/../../../libs LIBS_DIR = $$PWD/../../../libs
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -L"$$LIBS_DIR/lib" LIBS += -L"$$LIBS_DIR/lib"
LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz
# added after bitdht LIBS += -lcrypto -lws2_32 -lgdi32
# LIBS += -lcrypto -lws2_32 -lgdi32
LIBS += -luuid -lole32 -liphlpapi -lcrypt32 LIBS += -luuid -lole32 -liphlpapi -lcrypt32
LIBS += -lole32 -lwinmm LIBS += -lole32 -lwinmm
@ -134,7 +111,6 @@ macx {
LIBS += -Wl,-search_paths_first LIBS += -Wl,-search_paths_first
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -lssl -lcrypto -lz LIBS += -lssl -lcrypto -lz
LIBS += ../../../miniupnpc-1.0/libminiupnpc.a LIBS += ../../../miniupnpc-1.0/libminiupnpc.a
LIBS += -framework CoreFoundation LIBS += -framework CoreFoundation
@ -173,24 +149,17 @@ openbsd-* {
INCLUDEPATH *= /usr/local/include INCLUDEPATH *= /usr/local/include
QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen
LIBS *= ../../libretroshare/src/lib/libretroshare.a LIBS *= ../../libretroshare/src/lib/libretroshare.a
LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS *= -lssl -lcrypto LIBS *= -lssl -lcrypto
LIBS *= -lgpgme LIBS *= -lgpgme
LIBS *= -lupnp LIBS *= -lupnp
LIBS *= -lgnome-keyring LIBS *= -lgnome-keyring
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS *= -rdynamic LIBS *= -rdynamic
} }
############################## Common stuff ###################################### ############################## Common stuff ######################################
# bitdht config
bitdht {
LIBS += ../../libbitdht/src/lib/libbitdht.a
}
DEPENDPATH += . ../../libretroshare/src DEPENDPATH += . ../../libretroshare/src
INCLUDEPATH += . ../../libretroshare/src INCLUDEPATH += . ../../libretroshare/src
@ -386,7 +355,3 @@ protorpc {
INCLUDEPATH += $${PROTOPATH}/src INCLUDEPATH += $${PROTOPATH}/src
} }
} }
win32 {
# must be added after ssh
LIBS += -lcrypto -lws2_32 -lgdi32
}

7
retroshare.pri Normal file
View File

@ -0,0 +1,7 @@
unix {
isEmpty(PREFIX) { PREFIX = "/usr" }
isEmpty(BIN_DIR) { BIN_DIR = "$${PREFIX}/bin" }
isEmpty(INC_DIR) { INC_DIR = "$${PREFIX}/include/retroshare06" }
isEmpty(LIB_DIR) { LIB_DIR = "$${PREFIX}/lib" }
isEmpty(DATA_DIR) { DATA_DIR = "$${PREFIX}/share/RetroShare06" }
}