/**
   * If the user is logged in and ready to broadcast this will kick off an asynchronous test of
   * bandwidth to all ingest servers. This will in turn fill in the bitrate fields in the ingest
   * list.
   *
   * @return The IngestTester instance that is valid during the test.
   */
  public IngestTester startIngestTest() {
    if (!getIsReadyToBroadcast() || m_IngestList == null) {
      return null;
    }

    if (getIsIngestTesting()) {
      return null;
    }

    m_IngestTester = new IngestTester(m_Stream, m_IngestList);
    m_IngestTester.Start();

    setBroadcastState(BroadcastState.IngestTesting);

    return m_IngestTester;
  }
 /** Asynchronously cancels a currently underway ingest test. */
 public void cancelIngestTest() {
   if (getIsIngestTesting()) {
     m_IngestTester.Cancel();
   }
 }
  /**
   * Updates the internals of the controller. This should be called at least as frequently as the
   * desired broadcast framerate. Asynchronous results will be fired from inside this function.
   */
  public void update() {
    if (m_Stream == null || !m_SdkInitialized) {
      return;
    }

    ErrorCode ret = m_Stream.pollTasks();
    checkError(ret);

    // update the ingest tester
    if (getIsIngestTesting()) {
      m_IngestTester.update();

      // all done testing
      if (m_IngestTester.getIsDone()) {
        m_IngestTester = null;
        setBroadcastState(BroadcastState.ReadyToBroadcast);
      }
    }

    switch (m_BroadcastState) {
        // Kick off an authentication request
      case Authenticated:
        {
          setBroadcastState(BroadcastState.LoggingIn);

          ret = m_Stream.login(m_AuthToken);
          if (ErrorCode.failed(ret)) {
            String err = ErrorCode.getString(ret);
            reportError(String.format("Error in TTV_Login: %s\n", err));
          }
          break;
        }
        // Login
      case LoggedIn:
        {
          setBroadcastState(BroadcastState.FindingIngestServer);

          ret = m_Stream.getIngestServers(m_AuthToken);
          if (ErrorCode.failed(ret)) {
            setBroadcastState(BroadcastState.LoggedIn);

            String err = ErrorCode.getString(ret);
            reportError(String.format("Error in TTV_GetIngestServers: %s\n", err));
          }
          break;
        }
        // Ready to stream
      case ReceivedIngestServers:
        {
          setBroadcastState(BroadcastState.ReadyToBroadcast);

          // Kick off requests for the user and stream information that aren't 100% essential to be
          // ready before streaming starts
          ret = m_Stream.getUserInfo(m_AuthToken);
          if (ErrorCode.failed(ret)) {
            String err = ErrorCode.getString(ret);
            reportError(String.format("Error in TTV_GetUserInfo: %s\n", err));
          }

          updateStreamInfo();

          ret = m_Stream.getArchivingState(m_AuthToken);
          if (ErrorCode.failed(ret)) {
            String err = ErrorCode.getString(ret);
            reportError(String.format("Error in TTV_GetArchivingState: %s\n", err));
          }

          break;
        }
        // Waiting for the start/stop callback
      case Starting:
      case Stopping:
        {
          break;
        }
        // No action required
      case FindingIngestServer:
      case Authenticating:
      case Initialized:
      case Uninitialized:
      case IngestTesting:
        {
          break;
        }
      case Paused:
      case Broadcasting:
        {
          updateStreamInfo();
          break;
        }
      default:
        {
          break;
        }
    }
  }