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(RtpPacket* rtp_packet) { | |
Alpha Left Google
2010/11/15 23:46:35
Looks like this can be const *, you can still dele
Sergey Ulanov
2010/11/16 00:22:55
Agree. Changed this to const
| |
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())); | |
Alpha Left Google
2010/11/15 23:46:35
can we not use CHECK but return failure so that we
Sergey Ulanov
2010/11/16 00:22:55
The code above guarantees that packet_index < stat
| |
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 |