createAnswer method

dynamic createAnswer (
  1. int handleId,
  2. dynamic media,
  3. dynamic callbacks,
  4. dynamic customizedSdp
)

Implementation

createAnswer(int handleId, media, callbacks, customizedSdp) {
  Plugin pluginHandle = this.pluginHandles[handleId.toString()];
  if (pluginHandle == null) {
    Janus.warn("Invalid handle");
    callbacks.error("Invalid handle");
    return;
  }
  bool simulcast = callbacks.simulcast == true;
  if (!simulcast) {
    Janus.log(
        "Creating answer (iceDone=" + pluginHandle.iceDone.toString() + ")");
  } else {
    Janus.log("Creating answer (iceDone=" +
        pluginHandle.iceDone.toString() +
        ", simulcast=" +
        simulcast.toString() +
        ")");
  }
  var mediaConstraints;
  if (Janus.unifiedPlan) {
    // We can use Transceivers
    mediaConstraints = {};
    var audioTransceiver;
    var videoTransceiver;
    // FIX ME no equivalent call
    // var transceivers = pluginHandle.pc.getTransceivers();
    // if (transceivers != null && transceivers.length > 0) {
    //   for (var t in transceivers) {
    //     if ((t['sender'] &&
    //             t['sender'].track &&
    //             t['sender'].track.kind == "audio") ||
    //         (t['receiver'] &&
    //             t['receiver'].track &&
    //             t['receiver'].track.kind == "audio")) {
    //       if (!audioTransceiver) audioTransceiver = t;
    //       continue;
    //     }
    //     if ((t['sender'] &&
    //             t['sender'].track &&
    //             t['sender'].track.kind == "video") ||
    //         (t['receiver'] &&
    //             t['receiver'].track &&
    //             t['receiver'].track.kind == "video")) {
    //       if (!videoTransceiver) videoTransceiver = t;
    //       continue;
    //     }
    //   }
    // }
    // Handle audio (and related changes, if any)
    var audioSend = isAudioSendEnabled(media);
    var audioRecv = isAudioRecvEnabled(media);
    if (!audioSend && !audioRecv) {
      // Audio disabled: have we removed it?
      if (media['removeAudio'] && audioTransceiver) {
        try {
          if (audioTransceiver.setDirection != null) {
            audioTransceiver.setDirection("inactive");
          } else {
            audioTransceiver.direction = "inactive";
          }
          Janus.log(
              "Setting audio transceiver to inactive:", audioTransceiver);
        } catch (e) {
          Janus.error(e);
        }
      }
    } else {
      // Take care of audio m-line
      if (audioSend && audioRecv) {
        if (audioTransceiver != null) {
          try {
            if (audioTransceiver.setDirection != null) {
              audioTransceiver.setDirection("sendrecv");
            } else {
              audioTransceiver.direction = "sendrecv";
            }
            Janus.log(
                "Setting audio transceiver to sendrecv:", audioTransceiver);
          } catch (e) {
            Janus.error(e);
          }
        }
      } else if (audioSend && !audioRecv) {
        try {
          if (audioTransceiver != null) {
            if (audioTransceiver.setDirection != null) {
              audioTransceiver.setDirection("sendonly");
            } else {
              audioTransceiver.direction = "sendonly";
            }
            Janus.log(
                "Setting audio transceiver to sendonly:", audioTransceiver);
          }
        } catch (e) {
          Janus.error(e);
        }
      } else if (!audioSend && audioRecv) {
        if (audioTransceiver != null) {
          try {
            if (audioTransceiver.setDirection != null) {
              audioTransceiver.setDirection("recvonly");
            } else {
              audioTransceiver.direction = "recvonly";
            }
            Janus.log(
                "Setting audio transceiver to recvonly:", audioTransceiver);
          } catch (e) {
            Janus.error(e);
          }
        } else {
          // In theory, this is the only case where we might not have a transceiver yet
          // FIX ME no addTransceiver call
          // audioTransceiver =
          //     pc.addTransceiver("audio", {'direction': "recvonly"});
          // Janus.log("Adding recvonly audio transceiver:", audioTransceiver);
          Janus.log("No addTransceiver call");
        }
      }
    }
    // Handle video (and related changes, if any)
    var videoSend = isVideoSendEnabled(media);
    var videoRecv = isVideoRecvEnabled(media);
    if (!videoSend && !videoRecv) {
      // Video disabled: have we removed it?
      if (media['removeVideo'] && videoTransceiver != null) {
        try {
          if (videoTransceiver.setDirection != null) {
            videoTransceiver.setDirection("inactive");
          } else {
            videoTransceiver.direction = "inactive";
          }
          Janus.log(
              "Setting video transceiver to inactive:", videoTransceiver);
        } catch (e) {
          Janus.error(e);
        }
      }
    } else {
      // Take care of video m-line
      if (videoSend && videoRecv) {
        if (videoTransceiver != null) {
          try {
            if (videoTransceiver.setDirection != null) {
              videoTransceiver.setDirection("sendrecv");
            } else {
              videoTransceiver.direction = "sendrecv";
            }
            Janus.log(
                "Setting video transceiver to sendrecv:", videoTransceiver);
          } catch (e) {
            Janus.error(e);
          }
        }
      } else if (videoSend && !videoRecv) {
        if (videoTransceiver != null) {
          try {
            if (videoTransceiver.setDirection != null) {
              videoTransceiver.setDirection("sendonly");
            } else {
              videoTransceiver.direction = "sendonly";
            }
            Janus.log(
                "Setting video transceiver to sendonly:", videoTransceiver);
          } catch (e) {
            Janus.error(e);
          }
        }
      } else if (!videoSend && videoRecv) {
        if (videoTransceiver != null) {
          try {
            if (videoTransceiver.setDirection != null) {
              videoTransceiver.setDirection("recvonly");
            } else {
              videoTransceiver.direction = "recvonly";
            }
            Janus.log(
                "Setting video transceiver to recvonly:", videoTransceiver);
          } catch (e) {
            Janus.error(e);
          }
        } else {
          // In theory, this is the only case where we might not have a transceiver yet
          // FIX ME
          // videoTransceiver =
          //     pc.addTransceiver("video", {'direction': "recvonly"});
          // Janus.log("Adding recvonly video transceiver:", videoTransceiver);
          Janus.log("No addTransciever call");
        }
      }
    }
  } else {
    if (Janus.webRTCAdapter['browserDetails']['browser'] == "firefox" ||
        Janus.webRTCAdapter['browserDetails']['browser'] == "edge") {
      mediaConstraints = {
        'offerToReceiveAudio': isAudioRecvEnabled(media),
        'offerToReceiveVideo': isVideoRecvEnabled(media)
      };
    } else {
      mediaConstraints = {
        'mandatory': {
          'OfferToReceiveAudio': isAudioRecvEnabled(media),
          'OfferToReceiveVideo': isVideoRecvEnabled(media)
        }
      };
    }
  }
  Janus.debug(mediaConstraints);
  // Check if this is Firefox and we've been asked to do simulcasting
  var sendVideo = isVideoSendEnabled(media);
  if (sendVideo &&
      simulcast &&
      Janus.webRTCAdapter['browserDetails']['browser'] == "firefox") {
    // FIXME Based on https://gist.github.com/voluntas/088bc3cc62094730647b
    Janus.log("Enabling Simulcasting for Firefox (RID)");
    // FIX ME no equivalent call
    // var sender = pc.getSenders()[1];
    // Janus.log(sender);
    // var parameters = sender.getParameters();
    // Janus.log(parameters);

    // var maxBitrates = getMaxBitrates(callbacks.simulcastMaxBitrates);
    // sender.setParameters({
    //   'encodings': [
    //     {
    //       'rid': "high",
    //       'active': true,
    //       'priority': "high",
    //       'maxBitrate': maxBitrates['high']
    //     },
    //     {
    //       'rid': "medium",
    //       'active': true,
    //       'priority': "medium",
    //       'maxBitrate': maxBitrates['medium']
    //     },
    //     {
    //       'rid': "low",
    //       'active': true,
    //       'priority': "low",
    //       'maxBitrate': maxBitrates['low']
    //     }
    //   ]
    // });
  }
  pluginHandle.pc
      .createAnswer(mediaConstraints)
      .then((RTCSessionDescription answer) {
    Janus.debug(answer.toString());
    // JSON.stringify doesn't work on some WebRTC objects anymore
    // See https://code.google.com/p/chromium/issues/detail?id=467366
    RTCSessionDescription jsep =
        RTCSessionDescription(answer.sdp, answer.type);
    // FIX ME
    // if (callbacks.customizeSdp != null && callbacks.customizeSdp is Function)
    // callbacks.customizeSdp(jsep);
    answer.sdp = jsep.sdp;
    Janus.log("Setting local description");
    if (sendVideo && simulcast) {
      // This SDP munging only works with Chrome
      if (Janus.webRTCAdapter['browserDetails']['browser'] == "chrome") {
        // FIXME Apparently trying to simulcast when answering breaks video in Chrome...
        //~ Janus.log("Enabling Simulcasting for Chrome (SDP munging)");
        //~ answer.sdp = mungeSdpForSimulcasting(answer.sdp);
        Janus.warn(
            "simulcast=true, but this is an answer, and video breaks in Chrome if we enable it");
      } else if (Janus.webRTCAdapter['browserDetails']['browser'] !=
          "firefox") {
        Janus.warn(
            "simulcast=true, but this is not Chrome nor Firefox, ignoring");
      }
    }
    pluginHandle.mySdp = answer.sdp;
    pluginHandle.pc.setLocalDescription(answer).catchError(callbacks.error);
    pluginHandle.mediaConstraints = mediaConstraints;
    if (pluginHandle.iceDone == null && pluginHandle.trickle == null) {
      // Don't do anything until we have all candidates
      Janus.log("Waiting for all candidates...");
      return;
    }
    callbacks.success(answer);
  }).catchError((error, StackTrace stackTrace) {
    callbacks.error(error);
  });
}