88
99let quicChannel = null ;
1010let bidirectionalStream = null ;
11- let writeTask , mediaStream , mediaWorker , conferenceId , myId ;
11+ let writeTask , mediaStream , mediaWorker , conferenceId , myId , mixedStream , generatorWriter ;
12+
13+ window . Module = { } ;
1214
1315const conference = new Owt . Conference . ConferenceClient ( {
1416 webTransportConfiguration : {
1517 serverCertificateFingerprints : [ {
1618 value :
17- 'DD:A8:11:FD:A1:08:17:41:36:CD:1A:33:1E:CF:AE:0D:46:3D:15:16:2C:67:C5:A2:06:35:C2:0E:88:A1:9E:C6' ,
19+ '59:74:C6:C5:2C:D8:E8:18:A9:D2:14:77:ED:94:89:87:DF:83:BA:B3:96:4C:4C:0B:B8:D3:22:58:11:55:67:1A' ,
20+ algorithm : 'sha-256' ,
21+ } ] ,
22+ serverCertificateHashes : [ {
23+ value : new Uint8Array ( [
24+ 0x59 , 0x74 , 0xC6 , 0xC5 , 0x2C , 0xD8 , 0xE8 , 0x18 , 0xA9 , 0xD2 , 0x14 ,
25+ 0x77 , 0xED , 0x94 , 0x89 , 0x87 , 0xDF , 0x83 , 0xBA , 0xB3 , 0x96 , 0x4C ,
26+ 0x4C , 0x0B , 0xB8 , 0xD3 , 0x22 , 0x58 , 0x11 , 0x55 , 0x67 , 0x1A
27+ ] ) ,
1828 algorithm : 'sha-256' ,
19- } ]
29+ } ] ,
2030 }
2131} ) ;
2232conference . addEventListener ( 'streamadded' , async ( event ) => {
@@ -26,35 +36,51 @@ conference.addEventListener('streamadded', async (event) => {
2636 conferenceId , event . stream . id , 'common' ,
2737 'http://jianjunz-nuc-ubuntu.sh.intel.com:3001' ) ;
2838 }
29- if ( event . stream . source . data || event . stream . source . video ) {
30- const subscription = await conference . subscribe (
31- event . stream ,
32- { audio : false , video : { codecs : [ 'h264' ] } , transport : { type : 'quic' } } ) ;
33- const reader = subscription . stream . readable . getReader ( ) ;
34- while ( true ) {
35- const { value, done} = await reader . read ( ) ;
36- if ( done ) {
37- console . log ( 'Subscription ends.' ) ;
38- break ;
39- }
40- console . log ( 'Received data: ' + value ) ;
41- }
42- }
39+ // if (event.stream.source.data) {
40+ // const subscription = await conference.subscribe(
41+ // event.stream,
42+ // // {transport:{type: 'quic'}});
43+ // {audio: false, video: {codecs: ['h264']}, transport: {type: 'quic'} });
44+ // const reader = subscription.stream.readable.getReader();
45+ // while (true) {
46+ // const {value, done} = await reader.read();
47+ // if (done) {
48+ // console.log('Subscription ends.');
49+ // break;
50+ // }
51+ // //console.log('Received data: ' + value);
52+ // }
53+ // }
4354} ) ;
4455
4556function updateConferenceStatus ( message ) {
4657 document . getElementById ( 'conference-status' ) . innerHTML +=
4758 ( '<p>' + message + '</p>' ) ;
4859}
4960
61+ function initWorker ( ) {
62+ mediaWorker = new Worker ( './scripts/media-worker.js' ) ;
63+ mediaWorker . onmessage = ( ( e ) => {
64+ if ( e . data [ 0 ] === 'video-frame' ) {
65+ generatorWriter . write ( e . data [ 1 ] ) ;
66+ //console.log(e.data[1]);
67+ }
68+ } ) ;
69+ }
5070
5171function joinConference ( ) {
5272 return new Promise ( ( resolve , reject ) => {
5373 createToken ( undefined , 'user' , 'presenter' , token => {
5474 conference . join ( token ) . then ( ( info ) => {
5575 conferenceId = info . id ;
5676 myId = info . self . id ;
77+ for ( const stream of info . remoteStreams ) {
78+ if ( stream . source . video === 'mixed' ) {
79+ mixedStream = stream ;
80+ }
81+ }
5782 updateConferenceStatus ( 'Connected to conference server.' ) ;
83+ initWorker ( ) ;
5884 resolve ( ) ;
5985 } ) ;
6086 } , 'http://jianjunz-nuc-ubuntu.sh.intel.com:3001' ) ;
@@ -89,17 +115,17 @@ async function attachReader(stream) {
89115
90116async function createSendChannel ( ) {
91117 bidirectionalStream = await conference . createSendStream ( ) ;
92- const localStream = new Owt . Base . LocalStream (
93- bidirectionalStream ,
94- new Owt . Base . StreamSourceInfo ( undefined , 'camera' , undefined ) ) ;
95- attachReader ( bidirectionalStream ) ;
96- const publication = await conference . publish (
97- localStream , { video : { codec : 'h264' } , transport : { type : 'quic' } } ) ;
98118 // const localStream = new Owt.Base.LocalStream(
99119 // bidirectionalStream,
100- // new Owt.Base.StreamSourceInfo(undefined, undefined, true));
120+ // new Owt.Base.StreamSourceInfo(undefined, 'camera', undefined));
121+ // attachReader(bidirectionalStream);
101122 // const publication = await conference.publish(
102- // localStream, {transport: {type: 'quic'}});
123+ // localStream, {video: {codec: 'h264'}, transport: {type: 'quic'}});
124+ const localStream = new Owt . Base . LocalStream (
125+ bidirectionalStream ,
126+ new Owt . Base . StreamSourceInfo ( undefined , undefined , true ) ) ;
127+ const publication = await conference . publish (
128+ localStream , { transport : { type : 'quic' } } ) ;
103129 console . log ( publication ) ;
104130 updateConferenceStatus ( 'Created send channel.' ) ;
105131}
@@ -123,7 +149,6 @@ async function writeUuid() {
123149async function writeVideoData ( ) {
124150 mediaStream = await navigator . mediaDevices . getUserMedia ( { video : true } ) ;
125151 const track = new MediaStreamTrackProcessor ( mediaStream . getVideoTracks ( ) [ 0 ] ) ;
126- mediaWorker = new Worker ( './scripts/media-worker.js' ) ;
127152 mediaWorker . postMessage ( [ 'video-source' , track . readable ] , [ track . readable ] ) ;
128153 mediaWorker . postMessage (
129154 [ 'send-stream' , bidirectionalStream . writable ] ,
@@ -135,26 +160,87 @@ async function writeData() {
135160 const encoded = encoder . encode ( 'message' , { stream : true } ) ;
136161 const writer = bidirectionalStream . writable . getWriter ( ) ;
137162 await writer . ready ;
138- await writer . write ( new ArrayBuffer ( 2 ) ) ;
163+ const ab = new Uint8Array ( 10000 ) ;
164+ ab . fill ( 1 , 0 ) ;
165+ await writer . write ( ab ) ;
139166 writer . releaseLock ( ) ;
140167 return ;
141168}
142169
143170window . addEventListener ( 'load' , ( ) => {
144171 windowOnLoad ( ) ;
172+ fetchWasm ( ) ;
145173} ) ;
146174
147175document . getElementById ( 'start-sending' ) . addEventListener ( 'click' , async ( ) => {
148176 if ( ! bidirectionalStream ) {
149177 updateConferenceStatus ( 'Stream is not created.' ) ;
150178 return ;
151179 }
152- writeVideoData ( ) ;
153- // writeTask = setInterval(writeData, 2000 );
180+ // writeVideoData();
181+ writeTask = setInterval ( writeData , 200 ) ;
154182 updateConferenceStatus ( 'Started sending.' ) ;
155183} ) ;
156184
157185document . getElementById ( 'stop-sending' ) . addEventListener ( 'click' , ( ) => {
158186 clearInterval ( writeTask ) ;
159187 updateConferenceStatus ( 'Stopped sending.' ) ;
160188} ) ;
189+
190+ document . getElementById ( 'start-receiving' )
191+ . addEventListener ( 'click' , async ( ) => {
192+ const video = document . getElementById ( 'remote-video' ) ;
193+ const generator = new MediaStreamTrackGenerator ( { kind : 'video' } ) ;
194+ generatorWriter = generator . writable . getWriter ( ) ;
195+ video . srcObject = new MediaStream ( [ generator ] ) ;
196+ const reader = conference . datagramReader ( ) ;
197+ const ms = new Module . MediaSession ( ) ;
198+ const receiver = ms . createRtpVideoReceiver ( ) ;
199+ receiver . setCompleteFrameCallback ( ( frame ) => {
200+ const copiedFrame = frame . slice ( 0 ) ;
201+ mediaWorker . postMessage (
202+ [ 'encoded-video-frame' , copiedFrame ] , [ copiedFrame . buffer ] ) ;
203+ } ) ;
204+ subscribeMixedStream ( ) ;
205+ while ( true ) {
206+ const received = await reader . read ( ) ;
207+ const buffer = Module . _malloc ( received . value . byteLength ) ;
208+ Module . writeArrayToMemory ( received . value , buffer ) ;
209+ receiver . onRtpPacket ( buffer , received . value . byteLength ) ;
210+ }
211+ } ) ;
212+
213+ async function fetchWasm ( ) {
214+ Module [ 'instantiateWasm' ] = async ( imports , successCallback ) => {
215+ const response = await fetch ( 'scripts/owt.wasm' ) ;
216+ const buffer = await response . arrayBuffer ( ) ;
217+ const module = await WebAssembly . compile ( buffer ) ;
218+ const instance = await WebAssembly . instantiate ( module , imports ) ;
219+ successCallback ( instance , module ) ;
220+ return { } ;
221+ } ;
222+ const scriptPromise = new Promise ( ( resolve , reject ) => {
223+ const script = document . createElement ( 'script' ) ;
224+ document . body . appendChild ( script ) ;
225+ script . onload = resolve ;
226+ script . onerror = reject ;
227+ script . async = true ;
228+ script . src = 'scripts/owt.js' ;
229+ } ) ;
230+ await scriptPromise ;
231+ }
232+
233+ async function subscribeMixedStream ( ) {
234+ const subscription = await conference . subscribe (
235+ mixedStream ,
236+ { audio : false , video : { codecs : [ 'h264' ] } , transport : { type : 'quic' } } ) ;
237+ const reader = subscription . stream . readable . getReader ( ) ;
238+ while ( true ) {
239+ const { value, done} = await reader . read ( ) ;
240+ if ( done ) {
241+ console . log ( 'Subscription ends.' ) ;
242+ break ;
243+ }
244+ // console.log('Received data: ' + value);
245+ }
246+ }
0 commit comments