PageSourceSearch

https://www.creativexchange.io/source/wowza/lib/WowzaPeerConnectionPublish.js

js creativexchange.io collected 2026-10-05 02:21:49 UTC 8,112 bytes, 320 lines download raw bytes

1/*
2 * This code and all components (c) Copyright 2019-2020, Wowza Media Systems, LLC. All rights reserved.
3 * This code is licensed pursuant to the BSD 3-Clause License.
4 */
5
6let browserDetails = window.adapter.browserDetails;
7
8// munge plug-in
9let mungeSDP = undefined;
10
11// callbacks
12let onconnectionstatechange = undefined;
13let onstop = undefined;
14let onerror = undefined;
15
16// local state
17let localStream = undefined;
18let streamInfo = undefined;
19let mediaInfo = {
20  videoBitrate: "",
21  audioBitrate: "",
22  videoFrameRate: "30",
23  videoCodec: "42e01f",
24  audioCodec: "opus"
25}
26let userData = undefined;
27let statsInterval = undefined;
28
29let wsConnection = undefined;
30let peerConnection = undefined;
31let peerConnectionConfig = { 'iceServers': [] };
32peerConnectionConfig = null;
33let videoSender = undefined;
34let audioSender = undefined;
35
36
37function gotIceCandidate(event) {
38  if (event.candidate != null) {
39    console.log('WowzaPeerConnectionPublish.gotIceCandidate: ' + JSON.stringify({ 'ice': event.candidate }));
40  }
41}
42
43function gotDescription(description) {
44  console.log("WowzaPeerConnectionPublish.gotDescription: SDP:");
45  console.log(description.sdp+'');
46
47  let mungeData = new Object();
48
49  if (mediaInfo.audioBitrate != null)
50    mungeData.audioBitrate = mediaInfo.audioBitrate;
51  if (mediaInfo.videoBitrate != null)
52    mungeData.videoBitrate = mediaInfo.videoBitrate;
53  if (mediaInfo.videoFrameRate != null)
54    mungeData.videoFrameRate = mediaInfo.videoFrameRate;
55  if (mediaInfo.videoCodec != null)
56    mungeData.videoCodec = mediaInfo.videoCodec;
57  if (mediaInfo.audioCodec != null)
58    mungeData.audioCodec = mediaInfo.audioCodec;
59
60  if (mungeSDP != null)
61  {
62    description.sdp = mungeSDP(description.sdp, mungeData);
63  }
64
65  console.log("WowzaPeerConnectionPublish.gotDescription: Setting local description SDP: ");
66  console.log(description.sdp);
67
68
69  peerConnection
70    .setLocalDescription(description)
71    .then(() => wsConnection.send('{"direction":"publish", "command":"sendOffer", "streamInfo":' + JSON.stringify(streamInfo) + ', "sdp":' + JSON.stringify(description) + ', "userData":' + JSON.stringify(userData) + '}'))
72    .catch((error)=>{
73      let newError = {message:"Peer connection failed",...error};
74      errorHandler(newError);
75    });
76}
77
78function createOnStats(onStats) {
79  return () => {
80    if (peerConnection != null)
81    {
82      peerConnection.getStats(null)
83      .then(onStats, err => console.log(err));
84    }
85  }
86}
87
88function wsConnect(url) {
89  try
90  {
91    wsConnection = new WebSocket(url);
92  }
93  catch(e)
94  {
95    errorHandler(e);
96    return;
97  }
98
99  wsConnection.binaryType = 'arraybuffer';
100
101  wsConnection.onopen = function () {
102    console.log("WowzaPeerConnectionPublish.wsConnection.onopen");
103
104    peerConnection = new RTCPeerConnection(peerConnectionConfig);
105    videoSender = undefined;
106    audioSender = undefined;
107
108    peerConnection.onicecandidate = (event) => {
109      if (event.candidate != null) {
110        console.log('WowzaPeerConnectionPublish.gotIceCandidate: ' + JSON.stringify({ 'ice': event.candidate }));
111      }
112    }
113
114    peerConnection.onconnectionstatechange = (event) => {
115      if (onconnectionstatechange != null)
116      {
117        onconnectionstatechange(event);
118      }
119    }
120
121    peerConnection.onnegotiationneeded = (event) => {
122      peerConnection.createOffer(gotDescription, errorHandler);
123    }
124
125    let localTracks = localStream.getTracks();
126    for (let localTrack in localTracks) {
127      let sender = peerConnection.addTrack(localTracks[localTrack], localStream);
128      if (localTracks[localTrack].type === 'audio')
129      {
130        audioSender = sender;
131      }
132      else if (localTracks[localTrack].type === 'video')
133      {
134        videoSender = sender;
135      }
136    }
137  }
138
139  wsConnection.onmessage = function (evt) {
140    console.log("WowzaPeerConnectionPublish.wsConnection.onmessage: " + evt.data);
141
142    var msgJSON = JSON.parse(evt.data);
143
144    var msgStatus = Number(msgJSON['status']);
145    var msgCommand = msgJSON['command'];
146
147    if (msgStatus != 200) {
148      stop();
149      errorHandler({message:msgJSON['statusDescription']});
150    }
151    else {
152      var sdpData = msgJSON['sdp'];
153      if (sdpData !== undefined) {
154
155        var mungeData = new Object();
156
157        if (mediaInfo.audioBitrate !== undefined)
158          mungeData.audioBitrate = mediaInfo.audioBitrate;
159        if (mediaInfo.videoBitrate !== undefined)
160          mungeData.videoBitrate = mediaInfo.videoBitrate;
161
162        console.log("WowzaPeerConnectionPublish.wsConnection.onmessage: Setting remote description SDP:");
163        console.log(sdpData.sdp);
164
165        peerConnection
166          .setRemoteDescription(new RTCSessionDescription(sdpData),
167            () => { },
168            errorHandler
169          );
170      }
171
172      var iceCandidates = msgJSON['iceCandidates'];
173      if (iceCandidates !== undefined) {
174        for (var index in iceCandidates) {
175          console.log('WowzaPeerConnectionPublish.wsConnection.iceCandidates: ' + iceCandidates[index]);
176          peerConnection.addIceCandidate(new RTCIceCandidate(iceCandidates[index]));
177        }
178      }
179    }
180  }
181
182  wsConnection.onclose = function () {
183    console.log("WowzaPeerConnectionPublish.wsConnection.onclose");
184  }
185
186  wsConnection.onerror = function (error) {
187    console.log('wsConnection.onerror');
188    console.log(error);
189    let message = "Websocket connection failed: " + url;
190    console.log(message);
191    let newError = {message:message,...error};
192    stop();
193    errorHandler(newError);
194  }
195}
196
197function replaceTrack (type, newTrack)
198{
199  if (peerConnection != null)
200  {
201    console.log(peerConnection);
202    if (type === 'audio')
203    {
204      if (audioSender != null)
205      {
206        audioSender.replaceTrack(newTrack);
207      }
208      else
209      {
210        audioSender = peerConnection.addTrack(newTrack);
211      }
212    }
213    else if (type === 'video')
214    {
215      if (videoSender != null)
216      {
217        videoSender.replaceTrack(newTrack);
218      }
219      else
220      {
221        videoSender = peerConnection.addTrack(newTrack);
222      }
223    }
224  }
225}
226
227// startProps:
228//   wsURL: string
229//   localStream: MediaStream
230//   streamInfo: { applicationName, streamName }
231//   mediaInfo: { videoBitrate, audioBitrate, videoFrameRate, videoCodec, audioCodec }
232//   userData: any
233//   mungeSDP: function (sdpStr, mungeData)
234//   onconnectionstatechange: function
235//   onerror: function 
236
237function start (props)
238{
239  let wsURL = props.wsURL;
240  localStream = props.localStream;
241  if (props.streamInfo != null)
242    streamInfo = props.streamInfo;
243  if (props.mediaInfo != null)
244    mediaInfo = props.mediaInfo;
245  if (props.userData != null)
246    userData = props.userData;
247
248  if (props.mungeSDP != null)
249    mungeSDP = props.mungeSDP;
250
251  if (props.onconnectionstatechange != null)
252    onconnectionstatechange = props.onconnectionstatechange;
253  if (props.onstop != null)
254    onstop = props.onstop;
255  if (props.onerror != null)
256    onerror = props.onerror;
257
258  if (props.onstats != null)
259  {
260    statsInterval = setInterval(createOnStats(props.onstats),5000);
261  }
262
263  if (peerConnection == null)
264  {
265    if (wsConnection != null)
266      wsConnection.close();
267    wsConnection = null;
268
269    console.log("WowzaPeerConnectionPublish.start: wsURL:" + wsURL + " streamInfo:" + JSON.stringify(streamInfo));
270    wsConnect(wsURL);
271  }
272  else
273  {
274    console.log('WowzaPeerConnectionPublish.start: peerConnection already in use, not starting');
275  }
276}
277
278function stop ()
279{
280  if (peerConnection != null)
281    peerConnection.close();
282  peerConnection = undefined;
283  videoSender = undefined;
284  audioSender = undefined;
285  
286  if (wsConnection != null)
287    wsConnection.close();
288  wsConnection = undefined;
289
290  if (statsInterval != null)
291  {
292    clearInterval(statsInterval);
293    statsInterval = undefined;
294  }
295  if (onstop != null)
296  {
297    onstop();
298  }
299}
300
301function isStarted()
302{
303  return (peerConnection != null);
304}
305
306function errorHandler(error) {
307  console.trace();
308  if (onerror != null)
309  {
310    onerror(error);
311  }
312}
313
314export default {
315  connect: wsConnect,
316  start: start,
317  stop: stop,
318  isStarted: isStarted,
319  replaceTrack: replaceTrack
320};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.