vmolsa / webrtc-native

WebRTC for NodeJS
MIT License
169 stars 96 forks source link

Cross compiling for ARM #20

Open footniko opened 9 years ago

footniko commented 9 years ago

Webrtc-native works well on Ubuntu 14.04 including video and audio capturing with some modifications. Now i'm trying to cross compile it to my arm based computer (it also has Ubuntu 14.04 OS). Any hints about how can i do it properly?

vmolsa commented 9 years ago

Is streaming to browser working also? On Mac and windows it's not working.. But first install arm dependencies by running script.

# sudo ./third_party/webrtc/src/build/install-build-deps.sh --arm

After that set gyp variable and you can try to build it with npm

export GYP_CROSSCOMPILE=1
export BUILD_WEBRTC=true
npm install --arch=arm # <-- should fail

If it's failing change line 19 @ scripts/build.js

var ARCH = process.argv[2].substring(14);

to

var ARCH = 'arm';

and re-run npm install

export GYP_CROSSCOMPILE=1
export BUILD_WEBRTC=true
npm install

Did it work?

https://code.google.com/p/chromium/wiki/LinuxChromiumArm

footniko commented 9 years ago

Yes, streaming to browser also works. I tried node2browser but there are errors in the code. I just rewrote it to my requirements: index.js:

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var WebRTC = require('webrtc-native');

app.use(express.static(__dirname));

var iceServers = {
    iceServers: [
        {url: 'stun:stun.l.google.com:19302'},
    ],
};

var optionalArgument = {
    optional: [{
        DtlsSrtpKeyAgreement: true
    }]
};
var sdpConstraints = {
    optional: [],
    mandatory: {
        OfferToReceiveAudio: true,
        OfferToReceiveVideo: true
    }
};
var MediaConstraints = {audio: true, video: true};
var peer; // Uses for PeerConnection
var localStream; // Uses for saving local stream

io.on('connection', function(socket) {
    console.log('Peer Connected');

    function captureUserMedia(offerSDP) {

        WebRTC.getUserMedia(MediaConstraints, OnMediaSuccess, OnMediaError);

        function OnMediaSuccess(mediaStream) {
            localStream = mediaStream;
            createAnswer(offerSDP);
        }

        function OnMediaError(e) {
            console.error(e);
        }
    }

    function gotRemoteStream(event){
        //console.log('Getting remote video...');
    }

    function gotIceCandidate(event){
        if (event.candidate) {
            var iceData = {
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate
            };
            socket.emit('gotIceCandidate', iceData);
        }
    }

    function createAnswer(offerSDP) {
        peer = new WebRTC.RTCPeerConnection(iceServers, optionalArgument);
        peer.addStream(localStream); // establish robot's video for client
        peer.onaddstream = gotRemoteStream; // audio/video data from client
        peer.onicecandidate = gotIceCandidate;
        // remote-descriptions should be set earlier
        // using offer-sdp provided by the offerer
        var remoteDescription = new WebRTC.RTCSessionDescription(offerSDP);
        peer.setRemoteDescription(remoteDescription);

        peer.createAnswer(function(answerSDP) {
            peer.setLocalDescription(answerSDP);
            socket.emit('gotAnswer', answerSDP);
        }, onfailure, sdpConstraints);
    };
    function onfailure(error){console.log(error);}  

    socket.on('gotOffer', function(offerSDP){
        captureUserMedia(offerSDP);
    });
    socket.on('gotIceCandidateToRobot', function(iceData) {
        if (typeof peer !== 'undefined') {
            var candidate = new WebRTC.RTCIceCandidate({sdpMid: iceData.id, sdpMLineIndex: iceData.label, candidate: iceData.candidate});
            peer.addIceCandidate(candidate);
        }
    });  
    socket.on('disconnect', function () {
        console.log('Peer Disconnected');
        //peer.close();
    });

});

server.listen(3000, function() {
  console.log('Open in browser: http://localhost:3000');
});

index.html:

<html>
<head>
    <title>Node WebRTC native</title>
    <script src="/socket.io/socket.io.js"></script>
</head>
<body>
    <video id="remotevideo"></video>

<script>
var socket = io.connect();

window.onload = function(){
    initPeer();
}

/* WebRTC stuff */
var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.RTCPeerConnection;
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;

var iceServers = {
    iceServers: [
        {url: 'stun:stun.l.google.com:19302'},
    ],
};
var optionalArgument = {
    optional: [{
        DtlsSrtpKeyAgreement: true
    }]
};
var sdpConstraints = {
    optional: [],
    mandatory: {
        OfferToReceiveAudio: true,
        OfferToReceiveVideo: true
    }
};

var peer; // Uses for PeerConnection

function initPeer() {
    peer = new PeerConnection(iceServers, optionalArgument);
    peer.onaddstream = gotRemoteStream; // get robot's stream
    peer.onicecandidate = gotIceCandidate;

    peer.createOffer(function(offerSDP) {
        peer.setLocalDescription(offerSDP);
        socket.emit('gotOffer', offerSDP);
     }, onOfferFailure, sdpConstraints);

    function gotIceCandidate(event){
        if (event.candidate) {
            var iceData = {
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate
            };
            socket.emit('gotIceCandidateToRobot', iceData);
        }
    }

    function gotRemoteStream(event){
        //alert('Getting video from robot...');
        var video = document.getElementById('remotevideo');
        //video.autoplay = true;
        video.src = URL.createObjectURL(event.stream);
        video.play();

    }
    function onOfferFailure(error){console.log(error);}
}
/* --WebRTC stuff */

socket.on('message', function(data){
    console.log('Message from server: ' + data);
});
socket.on('gotAnswer', function(answerSDP){
    var remoteDescription = new SessionDescription(answerSDP);
    peer.setRemoteDescription(remoteDescription);
});
socket.on('gotIceCandidate', function(iceData) {
    if (typeof peer !== 'undefined') {
        var candidate = new IceCandidate({sdpMLineIndex: iceData.label, candidate: iceData.candidate});
        peer.addIceCandidate(candidate);
    }
});

</script>
</body>
</html>

However, after i get stream first time, i always getting this message: WARNING: no real random source present! And i can't receive stream again (for exapmle if i want to receive it in a new tab).

Thank you for your cross compiling guide. I'll try it soon.

vmolsa commented 9 years ago

Nice! :)

The message "WARNING: no real random source present!" comes from libsrtp and it's "hard" coded to it. And it means that there is no secure RNG method enabled. Basically this means that it could be possible to hack self signed webrtc certificates...

footniko commented 9 years ago

Stuck with this error while trying to crosscompile:

AssertionError: make_global_settings needs to be the same for all targets. [] vs. [['CC', '/home/footniko/my/nodejs/odroid-sdk/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin//arm-linux-gnueabihf-gcc'], ['CXX', '/home/footniko/my/nodejs/odroid-sdk/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin//arm-linux-gnueabihf-g++'], ['CC.host', 'third_party/llvm-build/Release+Asserts/bin/clang'], ['CXX.host', 'third_party/llvm-build/Release+Asserts/bin/clang++']]
vmolsa commented 9 years ago

It seems that pangyp is configured to using target_arch = "x64" you can check it from build/config.gypi where line "target_arch" is "x64"?

change line 20 @ package.json

"install": "pangyp rebuild",

to

"install": "pangyp rebuild --arch=arm",

now "target_arch" in build/config.gypi should be "arm" after "npm install"

footniko commented 9 years ago

Thanks! It helped but now i got error at another level:

[1108/2001] CXX obj/webrtc/libjingle/xmpp/rtc_xmpp.presencestatus.o
FAILED: /home/footniko/my/nodejs/odroid-sdk/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-g++ -MMD -MF obj/webrtc/libjingle/xmpp/rtc_xmpp.presencestatus.o.d -DV8_DEPRECATION_WARNINGS -D_FILE_OFFSET_BITS=64 -DCHROMIUM_BUILD -DCR_CLANG_REVISION=239765-1 -DUI_COMPOSITOR_IMAGE_TRANSPORT -DUSE_AURA=1 -DUSE_ASH=1 -DUSE_PANGO=1 -DUSE_CAIRO=1 -DUSE_DEFAULT_RENDER_THEME=1 -DUSE_LIBJPEG_TURBO=1 -DUSE_X11=1 -DUSE_CLIPBOARD_AURAX11=1 -DENABLE_ONE_CLICK_SIGNIN -DENABLE_PRE_SYNC_BACKUP -DENABLE_REMOTING=1 -DENABLE_WEBRTC=1 -DENABLE_MEDIA_ROUTER=1 -DENABLE_PEPPER_CDMS -DENABLE_CONFIGURATION_POLICY -DENABLE_NOTIFICATIONS -DENABLE_HIDPI=1 -DENABLE_TOPCHROME_MD=1 -DUSE_UDEV -DDONT_EMBED_BUILD_METADATA -DENABLE_TASK_MANAGER=1 -DENABLE_EXTENSIONS=1 -DENABLE_PLUGINS=1 -DENABLE_SESSION_SERVICE=1 -DENABLE_THEMES=1 -DENABLE_AUTOFILL_DIALOG=1 -DENABLE_BACKGROUND=1 -DENABLE_GOOGLE_NOW=1 -DCLD_VERSION=2 -DENABLE_PRINTING=1 -DENABLE_BASIC_PRINTING=1 -DENABLE_PRINT_PREVIEW=1 -DENABLE_SPELLCHECK=1 -DENABLE_CAPTIVE_PORTAL_DETECTION=1 -DENABLE_APP_LIST=1 -DENABLE_SETTINGS_APP=1 -DENABLE_SUPERVISED_USERS=1 -DENABLE_MDNS=1 -DENABLE_SERVICE_DISCOVERY=1 -DV8_USE_EXTERNAL_STARTUP_DATA -DFULL_SAFE_BROWSING -DSAFE_BROWSING_CSD -DSAFE_BROWSING_DB_LOCAL -DSAFE_BROWSING_SERVICE -DEXPAT_RELATIVE_PATH -DWEBRTC_ARCH_ARM -DWEBRTC_ARCH_ARM_V7 -DWEBRTC_HAS_NEON -DWEBRTC_POSIX -DWEBRTC_LINUX -DWEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DFEATURE_ENABLE_PSTN -DSSL_USE_NSS -DHAVE_NSS_SSL_H -DSSL_USE_NSS_RNG -DUSE_LIBPCI=1 -DUSE_GLIB=1 -DUSE_NSS_CERTS=1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -D_FORTIFY_SOURCE=2 -Igen -I../.. -fstack-protector --param=ssp-buffer-size=4 -Werror -pthread -fno-strict-aliasing -Wall -Wno-unused-parameter -Wno-missing-field-initializers -fvisibility=hidden -pipe -fPIC -Wno-unused-local-typedefs -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-strict-overflow -march=armv7-a -mtune=generic-armv7-a -mfpu=neon -mfloat-abi=hard -mthumb --sysroot=/home/footniko/my/nodejs/node-webrtc-arm/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot -O2 -fno-ident -fdata-sections -ffunction-sections -funwind-tables -fno-exceptions -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden -Wsign-compare -Woverloaded-virtual -Wno-abi -std=gnu++11 -Wno-narrowing -Wno-literal-suffix  -c ../../webrtc/libjingle/xmpp/presencestatus.cc -o obj/webrtc/libjingle/xmpp/rtc_xmpp.presencestatus.o
In file included from ../../webrtc/libjingle/xmpp/presencestatus.cc:11:0:
../../webrtc/libjingle/xmpp/presencestatus.h: In static member function ‘static std::string buzz::PresenceStatus::TrimStatus(const string&)’:
../../webrtc/libjingle/xmpp/presencestatus.h:135:31: error: comparison is always true due to limited range of data type [-Werror=type-limits]
       if (s[i] <= ' ' && s[i] >= 0) {
                               ^
cc1plus: all warnings being treated as errors
[1108/2001] CXX obj/webrtc/libjingle/xmpp/rtc_xmpp.hangoutpubsubclient.o
ninja: build stopped: subcommand failed.

I guess i need to turn off -Werror flag but where?

UPDATE I remove all mentions of -Werror in this files

./third_party/webrtc/src/chromium/src/build/config/compiler/BUILD.gn on line 822
./third_party/webrtc/src/chromium/src/build/nocompile.gypi on line 84
./third_party/webrtc/src/chromium/src/build/common.gypi

But now i got another error. It seems like i don't have all files. Will try it tomorrow anew

footniko commented 9 years ago

Still the same error:

In file included from ../../talk/media/devices/linuxdeviceinfo.cc:30:0:
../../talk/media/devices/libudevsymboltable.h:31:21: fatal error: libudev.h: No such file or directory
 #include <libudev.h>
                     ^
compilation terminated.
[995/1036] CXX obj/talk/media/webrtc/libjingle_media.webrtcvideoengine2.o
ninja: build stopped: subcommand failed.

Seems like my toolchain doesn't have this library:(

UPDATE Took needed library from my arm device. Now i got many [-Wnon-virtual-dtor] warnings and npm building failed.

UPDATE2 I removed all mentions of -Wnon-virtual-dtor from ./third_party/webrtc/src/webrtc/build/common.gypi but building still fails. Well... the only way i can see now is to compile directly on my arm...

vmolsa commented 9 years ago

Easiest way to build the module is from device but you need almost 10GB disk space to build it and time.. :/

footniko commented 9 years ago

So i tried to build it from my arm device but still no success :( What i did: git clone https://github.com/vmolsa/webrtc-native . export BUILD_WEBRTC=true npm install The procedure taked 3 hours on my device and failed with errors:

...
[3:07:19] Resolving deltas:  93% (2786209/2990269)   
[3:07:21] Resolving deltas:  93% (2791790/2990269)   
[3:07:23] Resolving deltas:  93% (2794577/2990269)   
[3:07:23] fatal: Out of memory, malloc failed (tried to allocate 106589184 bytes)
[3:07:23] fatal: index-pack failed
Traceback (most recent call last):
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_scm.py", line 920, in _Clone
    self._Run(clone_cmd, options, cwd=self._root_dir, retry=True)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_scm.py", line 1174, in _Run
    gclient_utils.CheckCallAndFilterAndHeader(cmd, env=env, **kwargs)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_utils.py", line 293, in CheckCallAndFilterAndHeader
    return CheckCallAndFilter(args, **kwargs)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_utils.py", line 538, in CheckCallAndFilter
    rv, args, kwargs.get('cwd', None), None, None)
CalledProcessError: Command 'git -c core.deltaBaseCacheLimit=512m clone --no-checkout --progress --verbose https://chromium.googlesource.com/chromium/src.git /home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj' returned non-zero exit status 128 in /home/user/webrtc-native/third_party/webrtc/src/chromium
----------------------------------------
solutions = [{
  'name': 'src',
  'url': 'https://chromium.googlesource.com/chromium/src.git',
  'deps_file': '.DEPS.git',
  'managed': False,
  'custom_deps': {
    # Skip syncing some large dependencies WebRTC will never need.
    'src/chrome/tools/test/reference_build/chrome_linux': None,
    'src/chrome/tools/test/reference_build/chrome_mac': None,
    'src/chrome/tools/test/reference_build/chrome_win': None,
    'src/native_client': None,
    'src/third_party/cld_2/src': None,
    'src/third_party/ffmpeg': None,
    'src/third_party/hunspell_dictionaries': None,
    'src/third_party/liblouis/src': None,
    'src/third_party/pdfium': None,
    'src/third_party/skia': None,
    'src/third_party/trace-viewer': None,
    'src/third_party/webrtc': None,
    'src/third_party/WebKit': None,
  },
  'safesync_url': ''
}]

cache_dir = None
WARNING: subprocess '"git" "-c" "core.deltaBaseCacheLimit=512m" "clone" "--no-checkout" "--progress" "--verbose" "https://chromium.googlesource.com/chromium/src.git" "/home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj"' in /home/user/webrtc-native/third_party/webrtc/src/chromium failed; will retry after a short nap...
WARNING: subprocess '"git" "-c" "core.deltaBaseCacheLimit=512m" "clone" "--no-checkout" "--progress" "--verbose" "https://chromium.googlesource.com/chromium/src.git" "/home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj"' in /home/user/webrtc-native/third_party/webrtc/src/chromium failed; will retry after a short nap...
WARNING: subprocess '"git" "-c" "core.deltaBaseCacheLimit=512m" "clone" "--no-checkout" "--progress" "--verbose" "https://chromium.googlesource.com/chromium/src.git" "/home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj"' in /home/user/webrtc-native/third_party/webrtc/src/chromium failed; will retry after a short nap...
WARNING: subprocess '"git" "-c" "core.deltaBaseCacheLimit=512m" "clone" "--no-checkout" "--progress" "--verbose" "https://chromium.googlesource.com/chromium/src.git" "/home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj"' in /home/user/webrtc-native/third_party/webrtc/src/chromium failed; will retry after a short nap...
Traceback (most recent call last):
  File "/home/user/webrtc-native/third_party/depot_tools/gclient.py", line 2313, in <module>
    sys.exit(main(sys.argv[1:]))
  File "/home/user/webrtc-native/third_party/depot_tools/gclient.py", line 2299, in main
    return dispatcher.execute(OptionParser(), argv)
  File "/home/user/webrtc-native/third_party/depot_tools/subcommand.py", line 252, in execute
    return command(parser, args[1:])
  File "/home/user/webrtc-native/third_party/depot_tools/gclient.py", line 2056, in CMDsync
    ret = client.RunOnDeps('update', args)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient.py", line 1520, in RunOnDeps
    work_queue.flush(revision_overrides, command, args, options=self._options)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_utils.py", line 896, in flush
    self._run_one_task(self.queued.pop(i), args, kwargs)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_utils.py", line 988, in _run_one_task
    task_item.run(*args, **kwargs)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient.py", line 832, in run
    file_list)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_scm.py", line 166, in RunCommand
    return getattr(self, command)(options, args, file_list)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_scm.py", line 418, in update
    self._Clone(revision, url, options)
  File "/home/user/webrtc-native/third_party/depot_tools/gclient_scm.py", line 928, in _Clone
    if os.listdir(tmp_dir):
OSError: [Errno 2] No such file or directory: '/home/user/webrtc-native/third_party/webrtc/src/chromium/_gclient_src_MfctJj'
Error: Command '/usr/bin/python -u src/sync_chromium.py --target-revision f8d6ba9efdddfb3aa0dfc01cd579f500a2de0b8d' returned non-zero exit status 1 in /home/user/webrtc-native/third_party/webrtc
Hook '/usr/bin/python -u src/sync_chromium.py --target-revision f8d6ba9efdddfb3aa0dfc01cd579f500a2de0b8d' took 11255.51 secs
make: *** [.] Error 1
make: Leaving directory `/home/user/webrtc-native/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/home/user/webrtc-native/node_modules/pangyp/lib/build.js:271:23)
gyp ERR! stack     at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:797:12)
gyp ERR! System Linux 3.10.80-121
gyp ERR! command "node" "/home/user/webrtc-native/node_modules/.bin/pangyp" "rebuild"
gyp ERR! cwd /home/user/webrtc-native
gyp ERR! node -v v0.10.25
gyp ERR! pangyp -v v2.3.0
gyp ERR! not ok 
npm ERR! weird error 1
npm WARN This failure might be due to the use of legacy binary "node"
npm WARN For further explanations, please read
/usr/share/doc/nodejs/README.Debian

npm ERR! not ok code 0

Googling for this error didn't give me smooth solution. I've tried to repeat the procedure but with no success. Any ideas? I've also tried to build webrtc separately but also with no success.

vmolsa commented 9 years ago

git is running out of memory.

fatal: Out of memory, malloc failed (tried to allocate 106589184 bytes)
toussi commented 8 years ago

Getting stuck with compiling for armhf , with this :

Compile host: Ubuntu 16.04 and15.10 amd64 - same error on both versions. Did :
build-deps.sh --arm npm install --arch=arm

arm-linux-gnueabihf-g++-5 -Wl,-z,now -Wl,-z,relro -Wl,--fatal-warnings -Wl,-z,defs -pthread -Wl,-z,noexecstack -fPIC -B/home/daniel/webrtc-native/third_party/webrtc/src/third_party/binutils/Linux_x64/Release/bin -Wl,--disable-new-dtags --sysroot=/home/daniel/webrtc-native/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot -L/home/daniel/webrtc-native/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot/lib/arm-linux-gnueabihf -Wl,-rpath-link=/home/daniel/webrtc-native/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot/lib/arm-linux-gnueabihf -L/home/daniel/webrtc-native/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot/usr/lib/arm-linux-gnueabihf -Wl,-rpath-link=/home/daniel/webrtc-native/third_party/webrtc/src/build/linux/debian_wheezy_arm-sysroot/usr/lib/arm-linux-gnueabihf -Wl,-O1 -Wl,--as-needed -Wl,--gc-sections -o frame_analyzer -Wl,--start-group obj/webrtc/tools/frame_analyzer/frame_analyzer.frame_analyzer.o obj/webrtc/tools/libcommand_line_parser.a obj/webrtc/tools/libvideo_quality_analysis.a obj/webrtc/common_video/libcommon_video.a obj/webrtc/libwebrtc_common.a obj/webrtc/system_wrappers/libsystem_wrappers.a obj/webrtc/base/librtc_base_approved.a libyuv.a obj/chromium/src/third_party/libjpeg_turbo/libjpeg_turbo.a -Wl,--end-group -lrt /usr/lib/gcc-cross/arm-linux-gnueabihf/5/libstdc++.so: error: undefined reference to 'clock_gettime', version 'GLIBC_2.17'