/*
 *  Copyright (c) 2011 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 "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"

#include <assert.h>  // assert
#include <string.h>  // memcpy

#include <limits>
#include <utility>
#include <vector>

#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "webrtc/rtc_base/logging.h"

namespace webrtc {
namespace {
int ParseVP8PictureID(RTPVideoHeaderVP8* vp8,
                      const uint8_t** data,
                      size_t* data_length,
                      size_t* parsed_bytes) {
  assert(vp8 != NULL);
  if (*data_length == 0)
    return -1;

  vp8->pictureId = (**data & 0x7F);
  if (**data & 0x80) {
    (*data)++;
    (*parsed_bytes)++;
    if (--(*data_length) == 0)
      return -1;
    // PictureId is 15 bits
    vp8->pictureId = (vp8->pictureId << 8) + **data;
  }
  (*data)++;
  (*parsed_bytes)++;
  (*data_length)--;
  return 0;
}

int ParseVP8Tl0PicIdx(RTPVideoHeaderVP8* vp8,
                      const uint8_t** data,
                      size_t* data_length,
                      size_t* parsed_bytes) {
  assert(vp8 != NULL);
  if (*data_length == 0)
    return -1;

  vp8->tl0PicIdx = **data;
  (*data)++;
  (*parsed_bytes)++;
  (*data_length)--;
  return 0;
}

int ParseVP8TIDAndKeyIdx(RTPVideoHeaderVP8* vp8,
                         const uint8_t** data,
                         size_t* data_length,
                         size_t* parsed_bytes,
                         bool has_tid,
                         bool has_key_idx) {
  assert(vp8 != NULL);
  if (*data_length == 0)
    return -1;

  if (has_tid) {
    vp8->temporalIdx = ((**data >> 6) & 0x03);
    vp8->layerSync = (**data & 0x20) ? true : false;  // Y bit
  }
  if (has_key_idx) {
    vp8->keyIdx = (**data & 0x1F);
  }
  (*data)++;
  (*parsed_bytes)++;
  (*data_length)--;
  return 0;
}

int ParseVP8Extension(RTPVideoHeaderVP8* vp8,
                      const uint8_t* data,
                      size_t data_length) {
  assert(vp8 != NULL);
  assert(data_length > 0);
  size_t parsed_bytes = 0;
  // Optional X field is present.
  bool has_picture_id = (*data & 0x80) ? true : false;   // I bit
  bool has_tl0_pic_idx = (*data & 0x40) ? true : false;  // L bit
  bool has_tid = (*data & 0x20) ? true : false;          // T bit
  bool has_key_idx = (*data & 0x10) ? true : false;      // K bit

  // Advance data and decrease remaining payload size.
  data++;
  parsed_bytes++;
  data_length--;

  if (has_picture_id) {
    if (ParseVP8PictureID(vp8, &data, &data_length, &parsed_bytes) != 0) {
      return -1;
    }
  }

  if (has_tl0_pic_idx) {
    if (ParseVP8Tl0PicIdx(vp8, &data, &data_length, &parsed_bytes) != 0) {
      return -1;
    }
  }

  if (has_tid || has_key_idx) {
    if (ParseVP8TIDAndKeyIdx(
            vp8, &data, &data_length, &parsed_bytes, has_tid, has_key_idx) !=
        0) {
      return -1;
    }
  }
  return static_cast<int>(parsed_bytes);
}

int ParseVP8FrameSize(RtpDepacketizer::ParsedPayload* parsed_payload,
                      const uint8_t* data,
                      size_t data_length) {
  assert(parsed_payload != NULL);
  if (parsed_payload->frame_type != kVideoFrameKey) {
    // Included in payload header for I-frames.
    return 0;
  }
  if (data_length < 10) {
    // For an I-frame we should always have the uncompressed VP8 header
    // in the beginning of the partition.
    return -1;
  }
  parsed_payload->type.Video.width = ((data[7] << 8) + data[6]) & 0x3FFF;
  parsed_payload->type.Video.height = ((data[9] << 8) + data[8]) & 0x3FFF;
  return 0;
}
}  // namespace

RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
                                   size_t max_payload_len,
                                   size_t last_packet_reduction_len,
                                   VP8PacketizerMode mode)
    : payload_data_(NULL),
      payload_size_(0),
      vp8_fixed_payload_descriptor_bytes_(1),
      mode_(mode),
      hdr_info_(hdr_info),
      num_partitions_(0),
      max_payload_len_(max_payload_len),
      last_packet_reduction_len_(last_packet_reduction_len) {}

RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
                                   size_t max_payload_len,
                                   size_t last_packet_reduction_len)
    : payload_data_(NULL),
      payload_size_(0),
      part_info_(),
      vp8_fixed_payload_descriptor_bytes_(1),
      mode_(kEqualSize),
      hdr_info_(hdr_info),
      num_partitions_(0),
      max_payload_len_(max_payload_len),
      last_packet_reduction_len_(last_packet_reduction_len) {}

RtpPacketizerVp8::~RtpPacketizerVp8() {
}

size_t RtpPacketizerVp8::SetPayloadData(
    const uint8_t* payload_data,
    size_t payload_size,
    const RTPFragmentationHeader* fragmentation) {
  payload_data_ = payload_data;
  payload_size_ = payload_size;
  if (fragmentation) {
    part_info_.CopyFrom(*fragmentation);
    num_partitions_ = fragmentation->fragmentationVectorSize;
  } else {
    part_info_.VerifyAndAllocateFragmentationHeader(1);
    part_info_.fragmentationLength[0] = payload_size;
    part_info_.fragmentationOffset[0] = 0;
    num_partitions_ = part_info_.fragmentationVectorSize;
  }
  if (GeneratePackets() < 0) {
    return 0;
  }
  return packets_.size();
}

bool RtpPacketizerVp8::NextPacket(RtpPacketToSend* packet) {
  RTC_DCHECK(packet);
  if (packets_.empty()) {
    return false;
  }
  InfoStruct packet_info = packets_.front();
  packets_.pop();

  uint8_t* buffer = packet->AllocatePayload(
      packets_.empty() ? max_payload_len_ - last_packet_reduction_len_
                       : max_payload_len_);
  int bytes = WriteHeaderAndPayload(packet_info, buffer, max_payload_len_);
  if (bytes < 0) {
    return false;
  }
  packet->SetPayloadSize(bytes);
  packet->SetMarker(packets_.empty());
  return true;
}

std::string RtpPacketizerVp8::ToString() {
  return "RtpPacketizerVp8";
}

int RtpPacketizerVp8::GeneratePackets() {
  if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ +
                             PayloadDescriptorExtraLength() + 1 +
                             last_packet_reduction_len_) {
    // The provided payload length is not long enough for the payload
    // descriptor and one payload byte in the last packet.
    // Return an error.
    return -1;
  }

  size_t per_packet_capacity =
      max_payload_len_ -
      (vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength());

  if (mode_ == kEqualSize) {
    GeneratePacketsSplitPayloadBalanced(0, payload_size_, per_packet_capacity,
                                        true, 0);
    return 0;
  }
  size_t part_idx = 0;
  while (part_idx < num_partitions_) {
    size_t current_packet_capacity = per_packet_capacity;
    bool last_partition = (part_idx + 1) == num_partitions_;
    if (last_partition)
      current_packet_capacity -= last_packet_reduction_len_;
    // Check if the next partition fits in to single packet with some space
    // left to aggregate some partitions together.
    if (mode_ == kAggregate &&
        part_info_.fragmentationLength[part_idx] < current_packet_capacity) {
      part_idx =
          GeneratePacketsAggregatePartitions(part_idx, per_packet_capacity);
    } else {
      GeneratePacketsSplitPayloadBalanced(
          part_info_.fragmentationOffset[part_idx],
          part_info_.fragmentationLength[part_idx], per_packet_capacity,
          last_partition, part_idx);
      ++part_idx;
    }
  }
  return 0;
}

void RtpPacketizerVp8::GeneratePacketsSplitPayloadBalanced(size_t payload_start,
                                                           size_t payload_len,
                                                           size_t capacity,
                                                           bool last_partition,
                                                           size_t part_idx) {
  // Last packet of the last partition is smaller. Pretend that it's the same
  // size, but we must write more payload to it.
  size_t total_bytes = payload_len;
  if (last_partition)
    total_bytes += last_packet_reduction_len_;
  // Integer divisions with rounding up.
  size_t num_packets_left = (total_bytes + capacity - 1) / capacity;
  size_t bytes_per_packet = total_bytes / num_packets_left;
  size_t num_larger_packets = total_bytes % num_packets_left;
  size_t remaining_data = payload_len;
  while (remaining_data > 0) {
    // Last num_larger_packets are 1 byte wider than the rest. Increase
    // per-packet payload size when needed.
    if (num_packets_left == num_larger_packets)
      ++bytes_per_packet;
    size_t current_packet_bytes = bytes_per_packet;
    if (current_packet_bytes > remaining_data) {
      current_packet_bytes = remaining_data;
    }
    // This is not the last packet in the whole payload, but there's no data
    // left for the last packet. Leave at least one byte for the last packet.
    if (num_packets_left == 2 && current_packet_bytes == remaining_data &&
        last_partition) {
      --current_packet_bytes;
    }
    QueuePacket(payload_start + payload_len - remaining_data,
                current_packet_bytes, part_idx, remaining_data == payload_len);
    remaining_data -= current_packet_bytes;
    --num_packets_left;
  }
}

size_t RtpPacketizerVp8::GeneratePacketsAggregatePartitions(size_t part_idx,
                                                            size_t capacity) {
  // Bloat the last partition by the reduction of the last packet. As it always
  // will be in the last packet we can pretend that the last packet is the same
  // size as the rest of the packets. Done temporary to simplify calculations.
  part_info_.fragmentationLength[num_partitions_ - 1] +=
      last_packet_reduction_len_;
  // Current partition should fit into the packet.
  RTC_CHECK_LE(part_info_.fragmentationLength[part_idx], capacity);
  // Find all partitions, shorter than capacity.
  size_t end_part = part_idx + 1;
  while (end_part < num_partitions_ &&
         part_info_.fragmentationLength[end_part] <= capacity) {
    ++end_part;
  }
  size_t total_partitions = end_part - part_idx;

  // Aggregate partitions |part_idx|..|end_part-1| to blocks of size at most
  // |capacity| minimizing the number of packets and then size of a largest
  // block using dynamic programming. |scores[i]| stores best score in the form
  // <number of packets, largest packet> for last i partitions. Maximum index is
  // |total_partitions|, minimum index is 0, hence the length is
  // |total_partitions|+1.

  struct PartitionScore {
    size_t num_packets = std::numeric_limits<size_t>::max();
    size_t largest_packet_len = std::numeric_limits<size_t>::max();
    // Compare num_packets first then largest_packet_len
    bool operator <(const PartitionScore& other) const {
      if (num_packets < other.num_packets) return true;
      if (num_packets > other.num_packets) return false;
      return largest_packet_len < other.largest_packet_len;
    }
  };

  std::vector<PartitionScore> scores(total_partitions + 1);
  // 0 partitions can be split into 0 packets with largest of size 0.
  scores[0].num_packets = 0;
  scores[0].largest_packet_len = 0;

  // best_block_size[i] stores optimal number of partitions to be aggregated
  // in the first packet if only last i partitions are considered.
  std::vector<size_t> best_block_size(total_partitions + 1, 0);
  // Calculate scores and best_block_size iteratively.
  for (size_t partitions_left = 0; partitions_left < total_partitions;
       ++partitions_left) {
    // Here scores[paritions_left] is already calculated correctly. Update
    // possible score for every possible new_paritions_left > partitions_left by
    // aggregating all partitions in between into a single packet.
    size_t current_payload_len = 0;
    PartitionScore current_score = scores[partitions_left];
    // Some next partitions are aggregated into one packet.
    current_score.num_packets += 1;
    // Calculate new score for last |new_partitions_left| partitions given
    // best score for |partitions_left| partitions.
    for (size_t new_partitions_left = partitions_left + 1;
         new_partitions_left <= total_partitions; ++new_partitions_left) {
      current_payload_len +=
          part_info_.fragmentationLength[end_part - new_partitions_left];
      if (current_payload_len > capacity)
        break;
      // Update maximum packet size.
      if (current_payload_len > current_score.largest_packet_len)
        current_score.largest_packet_len = current_payload_len;
      // Score with less num_packets is better. If equal, minimum largest packet
      // size is better.
      if (current_score < scores[new_partitions_left]) {
        scores[new_partitions_left] = current_score;
        best_block_size[new_partitions_left] =
            new_partitions_left - partitions_left;
      }
    }
  }
  // Undo temporary change.
  part_info_.fragmentationLength[num_partitions_ - 1] -=
      last_packet_reduction_len_;
  // Restore answer given sizes of aggregated blocks in |best_block_size| for
  // each possible left number of partitions.
  size_t partitions_left = total_partitions;
  while (partitions_left > 0) {
    size_t cur_parts = best_block_size[partitions_left];
    size_t first_partition = end_part - partitions_left;
    size_t start_offset = part_info_.fragmentationOffset[first_partition];
    size_t post_last_partition = first_partition + cur_parts;
    size_t finish_offset =
        (post_last_partition < num_partitions_)
            ? part_info_.fragmentationOffset[post_last_partition]
            : payload_size_;
    size_t current_payload_len = finish_offset - start_offset;
    QueuePacket(start_offset, current_payload_len, first_partition, true);
    // Go to next packet.
    partitions_left -= cur_parts;
  }
  return end_part;
}

void RtpPacketizerVp8::QueuePacket(size_t start_pos,
                                   size_t packet_size,
                                   size_t first_partition_in_packet,
                                   bool start_on_new_fragment) {
  // Write info to packet info struct and store in packet info queue.
  InfoStruct packet_info;
  packet_info.payload_start_pos = start_pos;
  packet_info.size = packet_size;
  packet_info.first_partition_ix = first_partition_in_packet;
  packet_info.first_fragment = start_on_new_fragment;
  packets_.push(packet_info);
}

int RtpPacketizerVp8::WriteHeaderAndPayload(const InfoStruct& packet_info,
                                            uint8_t* buffer,
                                            size_t buffer_length) const {
  // Write the VP8 payload descriptor.
  //       0
  //       0 1 2 3 4 5 6 7 8
  //      +-+-+-+-+-+-+-+-+-+
  //      |X| |N|S| PART_ID |
  //      +-+-+-+-+-+-+-+-+-+
  // X:   |I|L|T|K|         | (mandatory if any of the below are used)
  //      +-+-+-+-+-+-+-+-+-+
  // I:   |PictureID (8/16b)| (optional)
  //      +-+-+-+-+-+-+-+-+-+
  // L:   |   TL0PIC_IDX    | (optional)
  //      +-+-+-+-+-+-+-+-+-+
  // T/K: |TID:Y|  KEYIDX   | (optional)
  //      +-+-+-+-+-+-+-+-+-+

  assert(packet_info.size > 0);
  buffer[0] = 0;
  if (XFieldPresent())
    buffer[0] |= kXBit;
  if (hdr_info_.nonReference)
    buffer[0] |= kNBit;
  if (packet_info.first_fragment)
    buffer[0] |= kSBit;
  buffer[0] |= (packet_info.first_partition_ix & kPartIdField);

  const int extension_length = WriteExtensionFields(buffer, buffer_length);
  if (extension_length < 0)
    return -1;

  memcpy(&buffer[vp8_fixed_payload_descriptor_bytes_ + extension_length],
         &payload_data_[packet_info.payload_start_pos],
         packet_info.size);

  // Return total length of written data.
  return packet_info.size + vp8_fixed_payload_descriptor_bytes_ +
         extension_length;
}

int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer,
                                           size_t buffer_length) const {
  size_t extension_length = 0;
  if (XFieldPresent()) {
    uint8_t* x_field = buffer + vp8_fixed_payload_descriptor_bytes_;
    *x_field = 0;
    extension_length = 1;  // One octet for the X field.
    if (PictureIdPresent()) {
      if (WritePictureIDFields(
              x_field, buffer, buffer_length, &extension_length) < 0) {
        return -1;
      }
    }
    if (TL0PicIdxFieldPresent()) {
      if (WriteTl0PicIdxFields(
              x_field, buffer, buffer_length, &extension_length) < 0) {
        return -1;
      }
    }
    if (TIDFieldPresent() || KeyIdxFieldPresent()) {
      if (WriteTIDAndKeyIdxFields(
              x_field, buffer, buffer_length, &extension_length) < 0) {
        return -1;
      }
    }
    assert(extension_length == PayloadDescriptorExtraLength());
  }
  return static_cast<int>(extension_length);
}

int RtpPacketizerVp8::WritePictureIDFields(uint8_t* x_field,
                                           uint8_t* buffer,
                                           size_t buffer_length,
                                           size_t* extension_length) const {
  *x_field |= kIBit;
  assert(buffer_length >=
      vp8_fixed_payload_descriptor_bytes_ + *extension_length);
  const int pic_id_length = WritePictureID(
      buffer + vp8_fixed_payload_descriptor_bytes_ + *extension_length,
      buffer_length - vp8_fixed_payload_descriptor_bytes_ - *extension_length);
  if (pic_id_length < 0)
    return -1;
  *extension_length += pic_id_length;
  return 0;
}

int RtpPacketizerVp8::WritePictureID(uint8_t* buffer,
                                     size_t buffer_length) const {
  const uint16_t pic_id = static_cast<uint16_t>(hdr_info_.pictureId);
  size_t picture_id_len = PictureIdLength();
  if (picture_id_len > buffer_length)
    return -1;
  if (picture_id_len == 2) {
    buffer[0] = 0x80 | ((pic_id >> 8) & 0x7F);
    buffer[1] = pic_id & 0xFF;
  } else if (picture_id_len == 1) {
    buffer[0] = pic_id & 0x7F;
  }
  return static_cast<int>(picture_id_len);
}

int RtpPacketizerVp8::WriteTl0PicIdxFields(uint8_t* x_field,
                                           uint8_t* buffer,
                                           size_t buffer_length,
                                           size_t* extension_length) const {
  if (buffer_length <
      vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) {
    return -1;
  }
  *x_field |= kLBit;
  buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length] =
      hdr_info_.tl0PicIdx;
  ++*extension_length;
  return 0;
}

int RtpPacketizerVp8::WriteTIDAndKeyIdxFields(uint8_t* x_field,
                                              uint8_t* buffer,
                                              size_t buffer_length,
                                              size_t* extension_length) const {
  if (buffer_length <
      vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) {
    return -1;
  }
  uint8_t* data_field =
      &buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length];
  *data_field = 0;
  if (TIDFieldPresent()) {
    *x_field |= kTBit;
    assert(hdr_info_.temporalIdx <= 3);
    *data_field |= hdr_info_.temporalIdx << 6;
    *data_field |= hdr_info_.layerSync ? kYBit : 0;
  }
  if (KeyIdxFieldPresent()) {
    *x_field |= kKBit;
    *data_field |= (hdr_info_.keyIdx & kKeyIdxField);
  }
  ++*extension_length;
  return 0;
}

size_t RtpPacketizerVp8::PayloadDescriptorExtraLength() const {
  size_t length_bytes = PictureIdLength();
  if (TL0PicIdxFieldPresent())
    ++length_bytes;
  if (TIDFieldPresent() || KeyIdxFieldPresent())
    ++length_bytes;
  if (length_bytes > 0)
    ++length_bytes;  // Include the extension field.
  return length_bytes;
}

size_t RtpPacketizerVp8::PictureIdLength() const {
  if (hdr_info_.pictureId == kNoPictureId) {
    return 0;
  }
  return 2;
}

bool RtpPacketizerVp8::XFieldPresent() const {
  return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent() ||
          KeyIdxFieldPresent());
}

bool RtpPacketizerVp8::TIDFieldPresent() const {
  assert((hdr_info_.layerSync == false) ||
         (hdr_info_.temporalIdx != kNoTemporalIdx));
  return (hdr_info_.temporalIdx != kNoTemporalIdx);
}

bool RtpPacketizerVp8::KeyIdxFieldPresent() const {
  return (hdr_info_.keyIdx != kNoKeyIdx);
}

bool RtpPacketizerVp8::TL0PicIdxFieldPresent() const {
  return (hdr_info_.tl0PicIdx != kNoTl0PicIdx);
}

//
// VP8 format:
//
// Payload descriptor
//       0 1 2 3 4 5 6 7
//      +-+-+-+-+-+-+-+-+
//      |X|R|N|S|PartID | (REQUIRED)
//      +-+-+-+-+-+-+-+-+
// X:   |I|L|T|K|  RSV  | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// I:   |   PictureID   | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// L:   |   TL0PICIDX   | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
// T/K: |TID:Y| KEYIDX  | (OPTIONAL)
//      +-+-+-+-+-+-+-+-+
//
// Payload header (considered part of the actual payload, sent to decoder)
//       0 1 2 3 4 5 6 7
//      +-+-+-+-+-+-+-+-+
//      |Size0|H| VER |P|
//      +-+-+-+-+-+-+-+-+
//      |      ...      |
//      +               +
bool RtpDepacketizerVp8::Parse(ParsedPayload* parsed_payload,
                               const uint8_t* payload_data,
                               size_t payload_data_length) {
  assert(parsed_payload != NULL);
  if (payload_data_length == 0) {
    LOG(LS_ERROR) << "Empty payload.";
    return false;
  }

  // Parse mandatory first byte of payload descriptor.
  bool extension = (*payload_data & 0x80) ? true : false;               // X bit
  bool beginning_of_partition = (*payload_data & 0x10) ? true : false;  // S bit
  int partition_id = (*payload_data & 0x0F);  // PartID field

  parsed_payload->type.Video.width = 0;
  parsed_payload->type.Video.height = 0;
  parsed_payload->type.Video.is_first_packet_in_frame =
      beginning_of_partition && (partition_id == 0);
  parsed_payload->type.Video.simulcastIdx = 0;
  parsed_payload->type.Video.codec = kRtpVideoVp8;
  parsed_payload->type.Video.codecHeader.VP8.nonReference =
      (*payload_data & 0x20) ? true : false;  // N bit
  parsed_payload->type.Video.codecHeader.VP8.partitionId = partition_id;
  parsed_payload->type.Video.codecHeader.VP8.beginningOfPartition =
      beginning_of_partition;
  parsed_payload->type.Video.codecHeader.VP8.pictureId = kNoPictureId;
  parsed_payload->type.Video.codecHeader.VP8.tl0PicIdx = kNoTl0PicIdx;
  parsed_payload->type.Video.codecHeader.VP8.temporalIdx = kNoTemporalIdx;
  parsed_payload->type.Video.codecHeader.VP8.layerSync = false;
  parsed_payload->type.Video.codecHeader.VP8.keyIdx = kNoKeyIdx;

  if (partition_id > 8) {
    // Weak check for corrupt payload_data: PartID MUST NOT be larger than 8.
    return false;
  }

  // Advance payload_data and decrease remaining payload size.
  payload_data++;
  if (payload_data_length <= 1) {
    LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
    return false;
  }
  payload_data_length--;

  if (extension) {
    const int parsed_bytes =
        ParseVP8Extension(&parsed_payload->type.Video.codecHeader.VP8,
                          payload_data,
                          payload_data_length);
    if (parsed_bytes < 0)
      return false;
    payload_data += parsed_bytes;
    payload_data_length -= parsed_bytes;
    if (payload_data_length == 0) {
      LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
      return false;
    }
  }

  // Read P bit from payload header (only at beginning of first partition).
  if (beginning_of_partition && partition_id == 0) {
    parsed_payload->frame_type =
        (*payload_data & 0x01) ? kVideoFrameDelta : kVideoFrameKey;
  } else {
    parsed_payload->frame_type = kVideoFrameDelta;
  }

  if (ParseVP8FrameSize(parsed_payload, payload_data, payload_data_length) !=
      0) {
    return false;
  }

  parsed_payload->payload = payload_data;
  parsed_payload->payload_length = payload_data_length;
  return true;
}
}  // namespace webrtc
