Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(675)

Side by Side Diff: remoting/protocol/rtp_video_reader.cc

Issue 4925001: Packetizer/Depacketizer for RTP. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/protocol/rtp_video_reader.h ('k') | remoting/protocol/rtp_video_writer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
OLDNEW
« no previous file with comments | « remoting/protocol/rtp_video_reader.h ('k') | remoting/protocol/rtp_video_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698