8
8
9
9
let quicChannel = null ;
10
10
let bidirectionalStream = null ;
11
- let writeTask , mediaStream , mediaWorker , conferenceId , myId ;
11
+ let writeTask , mediaStream , mediaWorker , conferenceId , myId , mixedStream , generatorWriter ;
12
+
13
+ window . Module = { } ;
12
14
13
15
const conference = new Owt . Conference . ConferenceClient ( {
14
16
webTransportConfiguration : {
15
17
serverCertificateFingerprints : [ {
16
18
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
+ ] ) ,
18
28
algorithm : 'sha-256' ,
19
- } ]
29
+ } ] ,
20
30
}
21
31
} ) ;
22
32
conference . addEventListener ( 'streamadded' , async ( event ) => {
@@ -26,35 +36,51 @@ conference.addEventListener('streamadded', async (event) => {
26
36
conferenceId , event . stream . id , 'common' ,
27
37
'http://jianjunz-nuc-ubuntu.sh.intel.com:3001' ) ;
28
38
}
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
+ // }
43
54
} ) ;
44
55
45
56
function updateConferenceStatus ( message ) {
46
57
document . getElementById ( 'conference-status' ) . innerHTML +=
47
58
( '<p>' + message + '</p>' ) ;
48
59
}
49
60
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
+ }
50
70
51
71
function joinConference ( ) {
52
72
return new Promise ( ( resolve , reject ) => {
53
73
createToken ( undefined , 'user' , 'presenter' , token => {
54
74
conference . join ( token ) . then ( ( info ) => {
55
75
conferenceId = info . id ;
56
76
myId = info . self . id ;
77
+ for ( const stream of info . remoteStreams ) {
78
+ if ( stream . source . video === 'mixed' ) {
79
+ mixedStream = stream ;
80
+ }
81
+ }
57
82
updateConferenceStatus ( 'Connected to conference server.' ) ;
83
+ initWorker ( ) ;
58
84
resolve ( ) ;
59
85
} ) ;
60
86
} , 'http://jianjunz-nuc-ubuntu.sh.intel.com:3001' ) ;
@@ -89,17 +115,17 @@ async function attachReader(stream) {
89
115
90
116
async function createSendChannel ( ) {
91
117
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' } } ) ;
98
118
// const localStream = new Owt.Base.LocalStream(
99
119
// bidirectionalStream,
100
- // new Owt.Base.StreamSourceInfo(undefined, undefined, true));
120
+ // new Owt.Base.StreamSourceInfo(undefined, 'camera', undefined));
121
+ // attachReader(bidirectionalStream);
101
122
// 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' } } ) ;
103
129
console . log ( publication ) ;
104
130
updateConferenceStatus ( 'Created send channel.' ) ;
105
131
}
@@ -123,7 +149,6 @@ async function writeUuid() {
123
149
async function writeVideoData ( ) {
124
150
mediaStream = await navigator . mediaDevices . getUserMedia ( { video : true } ) ;
125
151
const track = new MediaStreamTrackProcessor ( mediaStream . getVideoTracks ( ) [ 0 ] ) ;
126
- mediaWorker = new Worker ( './scripts/media-worker.js' ) ;
127
152
mediaWorker . postMessage ( [ 'video-source' , track . readable ] , [ track . readable ] ) ;
128
153
mediaWorker . postMessage (
129
154
[ 'send-stream' , bidirectionalStream . writable ] ,
@@ -135,26 +160,87 @@ async function writeData() {
135
160
const encoded = encoder . encode ( 'message' , { stream : true } ) ;
136
161
const writer = bidirectionalStream . writable . getWriter ( ) ;
137
162
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 ) ;
139
166
writer . releaseLock ( ) ;
140
167
return ;
141
168
}
142
169
143
170
window . addEventListener ( 'load' , ( ) => {
144
171
windowOnLoad ( ) ;
172
+ fetchWasm ( ) ;
145
173
} ) ;
146
174
147
175
document . getElementById ( 'start-sending' ) . addEventListener ( 'click' , async ( ) => {
148
176
if ( ! bidirectionalStream ) {
149
177
updateConferenceStatus ( 'Stream is not created.' ) ;
150
178
return ;
151
179
}
152
- writeVideoData ( ) ;
153
- // writeTask = setInterval(writeData, 2000 );
180
+ // writeVideoData();
181
+ writeTask = setInterval ( writeData , 200 ) ;
154
182
updateConferenceStatus ( 'Started sending.' ) ;
155
183
} ) ;
156
184
157
185
document . getElementById ( 'stop-sending' ) . addEventListener ( 'click' , ( ) => {
158
186
clearInterval ( writeTask ) ;
159
187
updateConferenceStatus ( 'Stopped sending.' ) ;
160
188
} ) ;
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