// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package livekit.proto;
option csharp_namespace = "LiveKit.Proto";

import "handle.proto";
import "track.proto";

// Create a new VideoStream
// VideoStream is used to receive video frames from a track
message NewVideoStreamRequest {
  uint64 track_handle = 1;
  VideoStreamType type = 2;
  // Get the frame on a specific format
  optional VideoBufferType format = 3;
  bool normalize_stride = 4; // if true, stride will be set to width/chroma_width
}
message NewVideoStreamResponse { OwnedVideoStream stream = 1; }

// Request a video stream from a participant
message VideoStreamFromParticipantRequest {
  uint64 participant_handle = 1;
  VideoStreamType type = 2;
  TrackSource track_source = 3;
  optional VideoBufferType format = 4;
  bool normalize_stride = 5;
}

message VideoStreamFromParticipantResponse { OwnedVideoStream stream = 1;}

// Create a new VideoSource
// VideoSource is used to send video frame to a track
message NewVideoSourceRequest { 
  VideoSourceType type = 1; 
  // Used to determine which encodings to use + simulcast layers
  // Most of the time it corresponds to the source resolution 
  VideoSourceResolution resolution = 2;
}
message NewVideoSourceResponse { OwnedVideoSource source = 1; }

// Push a frame to a VideoSource
message CaptureVideoFrameRequest {
  uint64 source_handle = 1;
  VideoBufferInfo buffer = 2;
  int64 timestamp_us = 3; // In microseconds
  VideoRotation rotation = 4;
}

message CaptureVideoFrameResponse {}

message VideoConvertRequest {
  bool flip_y = 1;
  VideoBufferInfo buffer = 2;
  VideoBufferType dst_type = 3;
}
message VideoConvertResponse { 
  optional string error = 1;
  OwnedVideoBuffer buffer = 2; 
}

//
// VideoFrame buffers
//

message VideoResolution {
  uint32 width = 1;
  uint32 height = 2;
  double frame_rate = 3;
}

enum VideoCodec {
  VP8 = 0;
  H264 = 1;
  AV1 = 2;
  VP9 = 3;
}

enum VideoRotation {
  VIDEO_ROTATION_0 = 0;
  VIDEO_ROTATION_90 = 1;
  VIDEO_ROTATION_180 = 2;
  VIDEO_ROTATION_270 = 3;
}

enum VideoBufferType {
  RGBA = 0;
  ABGR = 1;
  ARGB = 2;
  BGRA = 3;
  RGB24 = 4;
  I420 = 5;
  I420A = 6;
  I422 = 7;
  I444 = 8;
  I010 = 9;
  NV12 = 10;
}

message VideoBufferInfo {
  message ComponentInfo {
    uint64 data_ptr = 1;
    uint32 stride = 2;
    uint32 size = 3;
  }
  VideoBufferType type = 1;
  uint32 width = 2;
  uint32 height = 3;
  uint64 data_ptr = 4;
  uint32 stride = 6; // only for packed formats
  repeated ComponentInfo components = 7;
}

message OwnedVideoBuffer {
  FfiOwnedHandle handle = 1;
  VideoBufferInfo info = 2;
}

//
// VideoStream
//

enum VideoStreamType {
  VIDEO_STREAM_NATIVE = 0;
  VIDEO_STREAM_WEBGL = 1;
  VIDEO_STREAM_HTML = 2;
}

message VideoStreamInfo {
  VideoStreamType type = 1;
}

message OwnedVideoStream {
  FfiOwnedHandle handle = 1;
  VideoStreamInfo info = 2;
}

message VideoStreamEvent {
  uint64 stream_handle = 1;
  oneof message { 
    VideoFrameReceived frame_received = 2;
    VideoStreamEOS eos = 3;
  }
}

message VideoFrameReceived {
  OwnedVideoBuffer buffer = 1;
  int64 timestamp_us = 2; // In microseconds
  VideoRotation rotation = 3;
}

message VideoStreamEOS {}

//
// VideoSource
//

message VideoSourceResolution {
  uint32 width = 1;
  uint32 height = 2;
}

enum VideoSourceType {
  VIDEO_SOURCE_NATIVE = 0;
}

message VideoSourceInfo {
  VideoSourceType type = 1;
}

message OwnedVideoSource {
  FfiOwnedHandle handle = 1;
  VideoSourceInfo info = 2;
}
