OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/rtp_video_reader.h" | 5 #include "remoting/protocol/rtp_video_reader.h" |
6 | 6 |
7 #include "base/task.h" | 7 #include "base/task.h" |
8 #include "remoting/proto/video.pb.h" | 8 #include "remoting/proto/video.pb.h" |
9 #include "remoting/protocol/session.h" | 9 #include "remoting/protocol/session.h" |
10 | 10 |
11 namespace remoting { | 11 namespace remoting { |
12 namespace protocol { | 12 namespace protocol { |
13 | 13 |
14 RtpVideoReader::RtpVideoReader() { } | 14 namespace { |
15 RtpVideoReader::~RtpVideoReader() { } | 15 const int kMaxPacketsInQueue = 1024; |
| 16 } // namespace |
| 17 |
| 18 RtpVideoReader::RtpVideoReader() |
| 19 : last_sequence_number_(0) { |
| 20 } |
| 21 |
| 22 RtpVideoReader::~RtpVideoReader() { |
| 23 ResetQueue(); |
| 24 } |
16 | 25 |
17 void RtpVideoReader::Init(protocol::Session* session, VideoStub* video_stub) { | 26 void RtpVideoReader::Init(protocol::Session* session, VideoStub* video_stub) { |
18 rtp_reader_.Init(session->video_rtp_channel(), | 27 rtp_reader_.Init(session->video_rtp_channel(), |
19 NewCallback(this, &RtpVideoReader::OnRtpPacket)); | 28 NewCallback(this, &RtpVideoReader::OnRtpPacket)); |
20 video_stub_ = video_stub; | 29 video_stub_ = video_stub; |
21 } | 30 } |
22 | 31 |
23 void RtpVideoReader::Close() { | 32 void RtpVideoReader::Close() { |
24 rtp_reader_.Close(); | 33 rtp_reader_.Close(); |
25 } | 34 } |
26 | 35 |
27 void RtpVideoReader::OnRtpPacket(const RtpPacket& rtp_packet) { | 36 void RtpVideoReader::ResetQueue() { |
| 37 for (PacketsQueue::iterator it = packets_queue_.begin(); |
| 38 it != packets_queue_.end(); ++it) { |
| 39 delete *it; |
| 40 } |
| 41 packets_queue_.clear(); |
| 42 } |
| 43 |
| 44 void RtpVideoReader::OnRtpPacket(const RtpPacket* rtp_packet) { |
| 45 uint32 sequence_number = rtp_packet->header().sequence_number; |
| 46 int32 relative_number = sequence_number - last_sequence_number_; |
| 47 int packet_index; |
| 48 if (relative_number > 0) { |
| 49 if (relative_number > kMaxPacketsInQueue) { |
| 50 // Sequence number jumped too much for some reason. Reset the queue. |
| 51 ResetQueue(); |
| 52 packets_queue_.resize(1); |
| 53 } else { |
| 54 packets_queue_.resize(packets_queue_.size() + relative_number); |
| 55 // Cleanup old packets, so that we don't have more than |
| 56 // |kMaxPacketsInQueue| packets. |
| 57 while (static_cast<int>(packets_queue_.size()) > kMaxPacketsInQueue) { |
| 58 delete packets_queue_.front(); |
| 59 packets_queue_.pop_front(); |
| 60 } |
| 61 } |
| 62 last_sequence_number_ = sequence_number; |
| 63 packet_index = packets_queue_.size() - 1; |
| 64 } else { |
| 65 packet_index = packets_queue_.size() - 1 + relative_number; |
| 66 if (packet_index < 0) { |
| 67 // The packet is too old. Just drop it. |
| 68 delete rtp_packet; |
| 69 return; |
| 70 } |
| 71 } |
| 72 |
| 73 CHECK_LT(packet_index, static_cast<int>(packets_queue_.size())); |
| 74 if (packets_queue_[packet_index]) { |
| 75 LOG(WARNING) << "Received duplicate packet with sequence number " |
| 76 << sequence_number; |
| 77 delete packets_queue_[packet_index]; |
| 78 } |
| 79 packets_queue_[packet_index] = rtp_packet; |
| 80 |
| 81 CheckFullPacket(packets_queue_.begin() + packet_index); |
| 82 } |
| 83 |
| 84 void RtpVideoReader::CheckFullPacket(PacketsQueue::iterator pos) { |
| 85 if ((*pos)->vp8_descriptor().fragmentation_info == |
| 86 Vp8Descriptor::NOT_FRAGMENTED) { |
| 87 // The packet is not fragmented. |
| 88 RebuildVideoPacket(pos, pos); |
| 89 return; |
| 90 } |
| 91 |
| 92 PacketsQueue::iterator first = pos; |
| 93 while (first > packets_queue_.begin() && (*first) && |
| 94 (*first)->vp8_descriptor().fragmentation_info != |
| 95 Vp8Descriptor::FIRST_FRAGMENT) { |
| 96 first--; |
| 97 } |
| 98 if (!(*first) || (*first)->vp8_descriptor().fragmentation_info != |
| 99 Vp8Descriptor::FIRST_FRAGMENT) { |
| 100 // We don't have first fragment. |
| 101 return; |
| 102 } |
| 103 |
| 104 PacketsQueue::iterator last = pos; |
| 105 while (last < (packets_queue_.end() - 1) && (*last) && |
| 106 (*last)->vp8_descriptor().fragmentation_info != |
| 107 Vp8Descriptor::LAST_FRAGMENT) { |
| 108 last++; |
| 109 } |
| 110 if (!(*last) || (*last)->vp8_descriptor().fragmentation_info != |
| 111 Vp8Descriptor::LAST_FRAGMENT) { |
| 112 // We don't have last fragment. |
| 113 return; |
| 114 } |
| 115 |
| 116 // We've found first and last fragments, and we have all fragments in the |
| 117 // middle, so we can rebuild fill packet. |
| 118 RebuildVideoPacket(first, last); |
| 119 } |
| 120 |
| 121 void RtpVideoReader::RebuildVideoPacket(PacketsQueue::iterator first, |
| 122 PacketsQueue::iterator last) { |
28 VideoPacket* packet = new VideoPacket(); | 123 VideoPacket* packet = new VideoPacket(); |
29 | 124 |
30 packet->mutable_data()->resize(rtp_packet.payload().total_bytes()); | 125 // Set flags. |
31 rtp_packet.payload().CopyTo( | 126 if ((*first)->vp8_descriptor().frame_beginning) |
32 const_cast<char*>(packet->mutable_data()->data()), | 127 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); |
33 packet->data().size()); | |
34 | 128 |
| 129 if ((*last)->header().marker) |
| 130 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); |
| 131 |
| 132 // Rebuild packet content from the fragments. |
| 133 // TODO(sergeyu): Use CompoundBuffer inside of VideoPacket, so that we don't |
| 134 // need to memcopy any data. |
| 135 CompoundBuffer content; |
| 136 for (PacketsQueue::iterator it = first; it <= last; ++it) { |
| 137 content.Append((*it)->payload()); |
| 138 |
| 139 // Delete packet because we don't need it anymore. |
| 140 delete *it; |
| 141 *it = NULL; |
| 142 } |
| 143 |
| 144 packet->mutable_data()->resize(content.total_bytes()); |
| 145 content.CopyTo(const_cast<char*>(packet->mutable_data()->data()), |
| 146 packet->data().size()); |
| 147 |
| 148 // Set format. |
35 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); | 149 packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); |
36 packet->set_flags(rtp_packet.header().marker ? VideoPacket::LAST_PACKET : 0); | |
37 | 150 |
38 video_stub_->ProcessVideoPacket(packet, new DeleteTask<VideoPacket>(packet)); | 151 video_stub_->ProcessVideoPacket(packet, new DeleteTask<VideoPacket>(packet)); |
39 } | 152 } |
40 | 153 |
41 } // namespace protocol | 154 } // namespace protocol |
42 } // namespace remoting | 155 } // namespace remoting |
OLD | NEW |