/*
 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h"

#include <string.h>

#include <optional>

#include "api/video/video_codec_constants.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "modules/video_coding/codecs/interface/common_constants.h"
#include "rtc_base/bitstream_reader.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace {

// Picture ID:
//
//      +-+-+-+-+-+-+-+-+
// I:   |M| PICTURE ID  |   M:0 => picture id is 7 bits.
//      +-+-+-+-+-+-+-+-+   M:1 => picture id is 15 bits.
// M:   | EXTENDED PID  |
//      +-+-+-+-+-+-+-+-+
//
void ParsePictureId(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
  if (parser.ReadBit()) {  // m_bit
    vp9->picture_id = parser.ReadBits(15);
    vp9->max_picture_id = kMaxTwoBytePictureId;
  } else {
    vp9->picture_id = parser.ReadBits(7);
    vp9->max_picture_id = kMaxOneBytePictureId;
  }
}

// Layer indices :
//
//      +-+-+-+-+-+-+-+-+
// L:   |  T  |U|  S  |D|
//      +-+-+-+-+-+-+-+-+
//      |   TL0PICIDX   |  (non-flexible mode only)
//      +-+-+-+-+-+-+-+-+
//
void ParseLayerInfo(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
  vp9->temporal_idx = parser.ReadBits(3);
  vp9->temporal_up_switch = parser.Read<bool>();
  vp9->spatial_idx = parser.ReadBits(3);
  vp9->inter_layer_predicted = parser.Read<bool>();
  if (vp9->spatial_idx >= kMaxSpatialLayers) {
    parser.Invalidate();
    return;
  }

  if (!vp9->flexible_mode) {
    vp9->tl0_pic_idx = parser.Read<uint8_t>();
  }
}

// Reference indices:
//
//      +-+-+-+-+-+-+-+-+                P=1,F=1: At least one reference index
// P,F: | P_DIFF      |N|  up to 3 times          has to be specified.
//      +-+-+-+-+-+-+-+-+                    N=1: An additional P_DIFF follows
//                                                current P_DIFF.
//
void ParseRefIndices(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
  if (vp9->picture_id == kNoPictureId) {
    parser.Invalidate();
    return;
  }

  vp9->num_ref_pics = 0;
  bool n_bit;
  do {
    if (vp9->num_ref_pics == kMaxVp9RefPics) {
      parser.Invalidate();
      return;
    }

    uint8_t p_diff = parser.ReadBits(7);
    n_bit = parser.Read<bool>();

    vp9->pid_diff[vp9->num_ref_pics] = p_diff;
    uint32_t scaled_pid = vp9->picture_id;
    if (p_diff > scaled_pid) {
      // TODO(asapersson): Max should correspond to the picture id of last wrap.
      scaled_pid += vp9->max_picture_id + 1;
    }
    vp9->ref_picture_id[vp9->num_ref_pics++] = scaled_pid - p_diff;
  } while (n_bit);
}

// Scalability structure (SS).
//
//      +-+-+-+-+-+-+-+-+
// V:   | N_S |Y|G|-|-|-|
//      +-+-+-+-+-+-+-+-+              -|
// Y:   |     WIDTH     | (OPTIONAL)    .
//      +               +               .
//      |               | (OPTIONAL)    .
//      +-+-+-+-+-+-+-+-+               . N_S + 1 times
//      |     HEIGHT    | (OPTIONAL)    .
//      +               +               .
//      |               | (OPTIONAL)    .
//      +-+-+-+-+-+-+-+-+              -|
// G:   |      N_G      | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+                           -|
// N_G: |  T  |U| R |-|-| (OPTIONAL)                 .
//      +-+-+-+-+-+-+-+-+              -|            . N_G times
//      |    P_DIFF     | (OPTIONAL)    . R times    .
//      +-+-+-+-+-+-+-+-+              -|           -|
//
void ParseSsData(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
  vp9->num_spatial_layers = parser.ReadBits(3) + 1;
  vp9->spatial_layer_resolution_present = parser.Read<bool>();
  bool g_bit = parser.Read<bool>();
  parser.ConsumeBits(3);
  vp9->gof.num_frames_in_gof = 0;

  if (vp9->spatial_layer_resolution_present) {
    for (size_t i = 0; i < vp9->num_spatial_layers; ++i) {
      vp9->width[i] = parser.Read<uint16_t>();
      vp9->height[i] = parser.Read<uint16_t>();
    }
  }
  if (g_bit) {
    vp9->gof.num_frames_in_gof = parser.Read<uint8_t>();
  }
  for (size_t i = 0; i < vp9->gof.num_frames_in_gof; ++i) {
    vp9->gof.temporal_idx[i] = parser.ReadBits(3);
    vp9->gof.temporal_up_switch[i] = parser.Read<bool>();
    vp9->gof.num_ref_pics[i] = parser.ReadBits(2);
    parser.ConsumeBits(2);

    for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) {
      vp9->gof.pid_diff[i][p] = parser.Read<uint8_t>();
    }
  }
}
}  // namespace

std::optional<VideoRtpDepacketizer::ParsedRtpPayload>
VideoRtpDepacketizerVp9::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
  std::optional<ParsedRtpPayload> result(std::in_place);
  int offset = ParseRtpPayload(rtp_payload, &result->video_header);
  if (offset == 0)
    return std::nullopt;
  RTC_DCHECK_LT(offset, rtp_payload.size());
  result->video_payload =
      rtp_payload.Slice(offset, rtp_payload.size() - offset);
  return result;
}

int VideoRtpDepacketizerVp9::ParseRtpPayload(
    rtc::ArrayView<const uint8_t> rtp_payload,
    RTPVideoHeader* video_header) {
  RTC_DCHECK(video_header);
  // Parse mandatory first byte of payload descriptor.
  BitstreamReader parser(rtp_payload);
  uint8_t first_byte = parser.Read<uint8_t>();
  bool i_bit = first_byte & 0b1000'0000;  // PictureId present .
  bool p_bit = first_byte & 0b0100'0000;  // Inter-picture predicted.
  bool l_bit = first_byte & 0b0010'0000;  // Layer indices present.
  bool f_bit = first_byte & 0b0001'0000;  // Flexible mode.
  bool b_bit = first_byte & 0b0000'1000;  // Begins frame flag.
  bool e_bit = first_byte & 0b0000'0100;  // Ends frame flag.
  bool v_bit = first_byte & 0b0000'0010;  // Scalability structure present.
  bool z_bit = first_byte & 0b0000'0001;  // Not used for inter-layer prediction

  // Parsed payload.
  video_header->width = 0;
  video_header->height = 0;
  video_header->simulcastIdx = 0;
  video_header->codec = kVideoCodecVP9;

  auto& vp9_header =
      video_header->video_type_header.emplace<RTPVideoHeaderVP9>();
  vp9_header.InitRTPVideoHeaderVP9();
  vp9_header.inter_pic_predicted = p_bit;
  vp9_header.flexible_mode = f_bit;
  vp9_header.beginning_of_frame = b_bit;
  vp9_header.end_of_frame = e_bit;
  vp9_header.ss_data_available = v_bit;
  vp9_header.non_ref_for_inter_layer_pred = z_bit;

  // Parse fields that are present.
  if (i_bit) {
    ParsePictureId(parser, &vp9_header);
  }
  if (l_bit) {
    ParseLayerInfo(parser, &vp9_header);
  }
  if (p_bit && f_bit) {
    ParseRefIndices(parser, &vp9_header);
  }
  if (v_bit) {
    ParseSsData(parser, &vp9_header);
    if (vp9_header.spatial_layer_resolution_present) {
      // TODO(asapersson): Add support for spatial layers.
      video_header->width = vp9_header.width[0];
      video_header->height = vp9_header.height[0];
    }
  }
  video_header->frame_type = p_bit || vp9_header.inter_layer_predicted
                                 ? VideoFrameType::kVideoFrameDelta
                                 : VideoFrameType::kVideoFrameKey;
  video_header->is_first_packet_in_frame = b_bit;
  video_header->is_last_packet_in_frame = e_bit;

  int num_remaining_bits = parser.RemainingBitCount();
  if (num_remaining_bits <= 0) {
    // Failed to parse or empty vp9 payload data.
    return 0;
  }
  // vp9 descriptor is byte aligned.
  RTC_DCHECK_EQ(num_remaining_bits % 8, 0);
  return rtp_payload.size() - num_remaining_bits / 8;
}
}  // namespace webrtc
