// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_CAST_CAST_CONFIG_H_
#define MEDIA_CAST_CAST_CONFIG_H_

#include <stddef.h>
#include <stdint.h>

#include <string>

#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"

namespace media {
class VideoEncodeAccelerator;

namespace cast {

enum Codec {
  CODEC_UNKNOWN,
  CODEC_AUDIO_OPUS,
  CODEC_AUDIO_PCM16,
  CODEC_AUDIO_AAC,
  CODEC_AUDIO_REMOTE,
  CODEC_VIDEO_FAKE,
  CODEC_VIDEO_VP8,
  CODEC_VIDEO_H264,
  CODEC_VIDEO_REMOTE,
  CODEC_LAST = CODEC_VIDEO_REMOTE
};

// Describes the content being transported over RTP streams.
enum class RtpPayloadType {
  UNKNOWN = -1,

  // Cast Streaming will encode raw audio frames using one of its available
  // codec implementations, and transport encoded data in the RTP stream.
  FIRST = 96,
  AUDIO_OPUS = 96,
  AUDIO_AAC = 97,
  AUDIO_PCM16 = 98,

  // Audio frame data is not modified, and should be transported reliably and
  // in-sequence. No assumptions about the data can be made.
  REMOTE_AUDIO = 99,

  AUDIO_LAST = REMOTE_AUDIO,

  // Cast Streaming will encode raw video frames using one of its available
  // codec implementations, and transport encoded data in the RTP stream.
  VIDEO_VP8 = 100,
  VIDEO_H264 = 101,

  // Video frame data is not modified, and should be transported reliably and
  // in-sequence. No assumptions about the data can be made.
  REMOTE_VIDEO = 102,

  LAST = REMOTE_VIDEO
};

// TODO(miu): Eliminate these after moving "default config" into the top-level
// media/cast directory.  http://crbug.com/530839
enum SuggestedDefaults {
  // Audio encoder bitrate.  Zero means "auto," which asks the encoder to select
  // a bitrate that dynamically adjusts to the content.  Otherwise, a constant
  // bitrate is used.
  kDefaultAudioEncoderBitrate = 0,

  // Suggested default audio sampling rate.
  kDefaultAudioSamplingRate = 48000,

  // RTP timebase for media remoting RTP streams.
  kRemotingRtpTimebase = 90000,

  // Suggested default maximum video frame rate.
  kDefaultMaxFrameRate = 30,

  // End-to-end latency in milliseconds.
  //
  // DO NOT USE THIS (400 ms is proven as ideal for general-purpose use).
  //
  // TODO(miu): Change to 400, and confirm nothing has broken in later change.
  // http://crbug.com/530839
  kDefaultRtpMaxDelayMs = 100,

  // Suggested minimum and maximum video bitrates for general-purpose use (up to
  // 1080p, 30 FPS).
  kDefaultMinVideoBitrate = 300000,
  kDefaultMaxVideoBitrate = 5000000,

  // Minimum and Maximum VP8 quantizer in default configuration.
  kDefaultMaxQp = 63,
  kDefaultMinQp = 4,

  kDefaultMaxCpuSaverQp = 25,

  // Number of video buffers in default configuration (applies only to certain
  // external codecs).
  kDefaultNumberOfVideoBuffers = 1,
};

// These parameters are only for video encoders.
struct VideoCodecParams {
  VideoCodecParams();
  VideoCodecParams(const VideoCodecParams& other);
  ~VideoCodecParams();

  int max_qp;
  int min_qp;

  // The maximum |min_quantizer| set to the encoder when CPU is constrained.
  // This is a trade-off between higher resolution with lower encoding quality
  // and lower resolution with higher encoding quality. The set value indicates
  // the maximum quantizer that the encoder might produce better quality video
  // at this resolution than lowering resolution with similar CPU usage and
  // smaller quantizer. The set value has to be between |min_qp| and |max_qp|.
  // Suggested value range: [4, 30]. It is only used by software VP8 codec.
  int max_cpu_saver_qp;

  // This field is used differently by various encoders.
  //
  // It defaults to 1.
  //
  // For VP8, this field is ignored.
  //
  // For H.264 on Mac or iOS, it controls the max number of frames the encoder
  // may hold before emitting a frame. A larger window may allow higher encoding
  // efficiency at the cost of latency and memory. Set to 0 to let the encoder
  // choose a suitable value for the platform and other encoding settings.
  int max_number_of_video_buffers_used;

  int number_of_encode_threads;
};

struct FrameSenderConfig {
  FrameSenderConfig();
  FrameSenderConfig(const FrameSenderConfig& other);
  ~FrameSenderConfig();

  // The sender's SSRC identifier.
  uint32_t sender_ssrc;

  // The receiver's SSRC identifier.
  uint32_t receiver_ssrc;

  // The total amount of time between a frame's capture/recording on the sender
  // and its playback on the receiver (i.e., shown to a user).  This should be
  // set to a value large enough to give the system sufficient time to encode,
  // transmit/retransmit, receive, decode, and render; given its run-time
  // environment (sender/receiver hardware performance, network conditions,
  // etc.).
  base::TimeDelta min_playout_delay;
  base::TimeDelta max_playout_delay;

  // Starting playout delay when streaming animated content.
  base::TimeDelta animated_playout_delay;

  // RTP payload type enum: Specifies the type/encoding of frame data.
  RtpPayloadType rtp_payload_type;

  // If true, use an external HW encoder rather than the built-in
  // software-based one.
  bool use_external_encoder;

  // RTP timebase: The number of RTP units advanced per one second.  For audio,
  // this is the sampling rate.  For video, by convention, this is 90 kHz.
  int rtp_timebase;

  // Number of channels.  For audio, this is normally 2.  For video, this must
  // be 1 as Cast does not have support for stereoscopic video.
  int channels;

  // For now, only fixed bitrate is used for audio encoding. So for audio,
  // |max_bitrate| is used, and the other two will be overriden if they are not
  // equal to |max_bitrate|.
  int max_bitrate;
  int min_bitrate;
  int start_bitrate;

  double max_frame_rate;

  // Codec used for the compression of signal data.
  Codec codec;

  // The AES crypto key and initialization vector.  Each of these strings
  // contains the data in binary form, of size kAesKeySize.  If they are empty
  // strings, crypto is not being used.
  std::string aes_key;
  std::string aes_iv_mask;

  // These are codec specific parameters for video streams only.
  VideoCodecParams video_codec_params;
};

// TODO(miu): Naming and minor type changes are badly needed in a later CL.
struct FrameReceiverConfig {
  FrameReceiverConfig();
  FrameReceiverConfig(const FrameReceiverConfig& other);
  ~FrameReceiverConfig();

  // The receiver's SSRC identifier.
  uint32_t receiver_ssrc;

  // The sender's SSRC identifier.
  uint32_t sender_ssrc;

  // The total amount of time between a frame's capture/recording on the sender
  // and its playback on the receiver (i.e., shown to a user).  This is fixed as
  // a value large enough to give the system sufficient time to encode,
  // transmit/retransmit, receive, decode, and render; given its run-time
  // environment (sender/receiver hardware performance, network conditions,
  // etc.).
  int rtp_max_delay_ms;  // TODO(miu): Change to TimeDelta target_playout_delay.

  // RTP payload type enum: Specifies the type/encoding of frame data.
  RtpPayloadType rtp_payload_type;

  // RTP timebase: The number of RTP units advanced per one second.  For audio,
  // this is the sampling rate.  For video, by convention, this is 90 kHz.
  int rtp_timebase;

  // Number of channels.  For audio, this is normally 2.  For video, this must
  // be 1 as Cast does not have support for stereoscopic video.
  int channels;

  // The target frame rate.  For audio, this is normally 100 (i.e., frames have
  // a duration of 10ms each).  For video, this is normally 30, but any frame
  // rate is supported.
  double target_frame_rate;

  // Codec used for the compression of signal data.
  // TODO(miu): Merge the AudioCodec and VideoCodec enums into one so this union
  // is not necessary.
  Codec codec;

  // The AES crypto key and initialization vector.  Each of these strings
  // contains the data in binary form, of size kAesKeySize.  If they are empty
  // strings, crypto is not being used.
  std::string aes_key;
  std::string aes_iv_mask;
};

// TODO(miu): Remove the CreateVEA callbacks.  http://crbug.com/454029
typedef base::Callback<void(scoped_refptr<base::SingleThreadTaskRunner>,
                            std::unique_ptr<media::VideoEncodeAccelerator>)>
    ReceiveVideoEncodeAcceleratorCallback;
typedef base::Callback<void(const ReceiveVideoEncodeAcceleratorCallback&)>
    CreateVideoEncodeAcceleratorCallback;
typedef base::Callback<void(std::unique_ptr<base::SharedMemory>)>
    ReceiveVideoEncodeMemoryCallback;
typedef base::Callback<void(size_t size,
                            const ReceiveVideoEncodeMemoryCallback&)>
    CreateVideoEncodeMemoryCallback;

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_CAST_CONFIG_H_
