1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/rtp/frame_buffer.h"
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace media {
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace cast {
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FrameBuffer::FrameBuffer()
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : frame_id_(0),
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      max_packet_id_(0),
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      num_packets_received_(0),
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      max_seen_packet_id_(0),
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new_playout_delay_ms_(0),
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      is_key_frame_(false),
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      total_data_size_(0),
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      last_referenced_frame_id_(0),
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      packets_() {}
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FrameBuffer::~FrameBuffer() {}
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool FrameBuffer::InsertPacket(const uint8* payload_data,
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               size_t payload_size,
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                               const RtpCastHeader& rtp_header) {
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Is this the first packet in the frame?
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (packets_.empty()) {
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    frame_id_ = rtp_header.frame_id;
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    max_packet_id_ = rtp_header.max_packet_id;
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    is_key_frame_ = rtp_header.is_key_frame;
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    new_playout_delay_ms_ = rtp_header.new_playout_delay_ms;
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (is_key_frame_)
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DCHECK_EQ(rtp_header.frame_id, rtp_header.reference_frame_id);
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    last_referenced_frame_id_ = rtp_header.reference_frame_id;
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    rtp_timestamp_ = rtp_header.rtp_timestamp;
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Is this the correct frame?
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (rtp_header.frame_id != frame_id_)
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Insert every packet only once.
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (packets_.find(rtp_header.packet_id) != packets_.end()) {
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::vector<uint8> data;
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::pair<PacketMap::iterator, bool> retval =
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      packets_.insert(make_pair(rtp_header.packet_id, data));
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Insert the packet.
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  retval.first->second.resize(payload_size);
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::copy(
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      payload_data, payload_data + payload_size, retval.first->second.begin());
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ++num_packets_received_;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  max_seen_packet_id_ = std::max(max_seen_packet_id_, rtp_header.packet_id);
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  total_data_size_ += payload_size;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool FrameBuffer::Complete() const {
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return num_packets_received_ - 1 == max_packet_id_;
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool FrameBuffer::AssembleEncodedFrame(EncodedFrame* frame) const {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!Complete())
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Frame is complete -> construct.
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (is_key_frame_)
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    frame->dependency = EncodedFrame::KEY;
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else if (frame_id_ == last_referenced_frame_id_)
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    frame->dependency = EncodedFrame::INDEPENDENT;
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    frame->dependency = EncodedFrame::DEPENDENT;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->frame_id = frame_id_;
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->referenced_frame_id = last_referenced_frame_id_;
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->rtp_timestamp = rtp_timestamp_;
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  frame->new_playout_delay_ms = new_playout_delay_ms_;
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Build the data vector.
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->data.clear();
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->data.reserve(total_data_size_);
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  PacketMap::const_iterator it;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (it = packets_.begin(); it != packets_.end(); ++it)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    frame->data.insert(frame->data.end(), it->second.begin(), it->second.end());
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return true;
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid FrameBuffer::GetMissingPackets(bool newest_frame,
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    PacketIdSet* missing_packets) const {
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Missing packets capped by max_seen_packet_id_.
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // (Iff it's the latest frame)
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int maximum = newest_frame ? max_seen_packet_id_ : max_packet_id_;
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int packet = 0;
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (PacketMap::const_iterator i = packets_.begin();
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       i != packets_.end() && packet <= maximum;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++i) {
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int end = std::min<int>(i->first, maximum + 1);
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    while (packet < end) {
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      missing_packets->insert(packet);
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      packet++;
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    packet++;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (packet <= maximum) {
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    missing_packets->insert(packet);
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    packet++;
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace cast
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace media
117