/**
   * Determines the recommended streaming parameters based on the maximum bandwidth of the user's
   * internet connection. This is the recommended method if the broadcast resolution can be
   * independent of the game window resolution and will produce the best visual quality. The game
   * must submit buffers at the resolution returned in the VideoParams.
   *
   * @param maxKbps Maximum bitrate supported (this should be determined by running the ingest
   *     tester for a given ingest server).
   * @param frameRate The desired frame rate. For a given bitrate and motion factor, a higher
   *     framerate will mean a lower resolution.
   * @param bitsPerPixel The bits per pixel used in the final encoded video. A fast motion game
   *     (e.g. first person shooter) required more bits per pixel of encoded video avoid compression
   *     artifacting. Use 0.1 for an average motion game. For games without too many fast changes in
   *     the scene, you could use a value below 0.1 but not much. For fast moving games with lots of
   *     scene changes a value as high as 0.2 would be appropriate.
   * @param aspectRatio - The aspect ratio of the video which we'll use for calculating width and
   *     height.
   * @return The filled in VideoParams.
   */
  public VideoParams getRecommendedVideoParams(
      int maxKbps, int frameRate, float bitsPerPixel, float aspectRatio) {
    int[] resolution = m_Stream.getMaxResolution(maxKbps, frameRate, bitsPerPixel, aspectRatio);

    VideoParams videoParams = new VideoParams();
    videoParams.maxKbps = maxKbps;
    videoParams.encodingCpuUsage = EncodingCpuUsage.TTV_ECU_HIGH;
    videoParams.pixelFormat = determinePixelFormat();
    videoParams.targetFps = frameRate;
    videoParams.outputWidth = resolution[0];
    videoParams.outputHeight = resolution[1];
    videoParams.disableAdaptiveBitrate = false;
    videoParams.verticalFlip = false;

    return videoParams;
  }
  /**
   * Returns a fully populated VideoParams struct based on the given width, height and frame rate.
   * This function is not the advised way to setup VideoParams because it has no information about
   * the user's maximum bitrate. Use the other version of GetRecommendedVideoParams instead if
   * possible.
   *
   * @param width The broadcast width
   * @param height The broadcast height
   * @param frameRate The broadcast frames per second
   * @return The VideoParams
   */
  public VideoParams getRecommendedVideoParams(int width, int height, int frameRate) {
    VideoParams videoParams = new VideoParams();

    videoParams.outputWidth = width;
    videoParams.outputHeight = height;
    videoParams.targetFps = frameRate;
    videoParams.pixelFormat = determinePixelFormat();
    videoParams.encodingCpuUsage = EncodingCpuUsage.TTV_ECU_HIGH;
    videoParams.disableAdaptiveBitrate = false;
    videoParams.verticalFlip = false;

    // Compute the rest of the fields based on the given parameters
    ErrorCode ret = m_Stream.getDefaultParams(videoParams);
    if (ErrorCode.failed(ret)) {
      String err = ErrorCode.getString(ret);
      reportError(String.format("Error in GetDefaultParams: %s", err));
      return null;
    }

    return videoParams;
  }
  /**
   * Begins broadcast using the given VideoParams.
   *
   * @param videoParams The video params
   * @return Whether or not successfully broadcasting
   */
  public boolean startBroadcasting(VideoParams videoParams) {
    if (videoParams == null || !this.getIsReadyToBroadcast()) {
      return false;
    }

    m_VideoParams = videoParams.clone();

    // Setup the audio parameters
    m_AudioParams = new AudioParams();
    m_AudioParams.audioEnabled =
        m_EnableAudio && getIsAudioSupported(); // // only enable audio if possible

    if (!allocateBuffers()) {
      m_VideoParams = null;
      m_AudioParams = null;
      return false;
    }

    ErrorCode ret =
        m_Stream.start(videoParams, m_AudioParams, m_IngestServer, StartFlags.None, true);
    if (ErrorCode.failed(ret)) {
      cleanupBuffers();

      String err = ErrorCode.getString(ret);
      reportError(String.format("Error while starting to broadcast: %s", err));

      m_VideoParams = null;
      m_AudioParams = null;

      return false;
    }

    setBroadcastState(BroadcastState.Starting);

    return true;
  }