1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/protocol/rtp_writer.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "remoting/protocol/rtp_utils.h"
namespace remoting {
namespace {
const int kMtu = 1200;
const uint8 kRtpPayloadTypePrivate = 96;
}
RtpWriter::RtpWriter()
: rtp_socket_(NULL),
rtcp_socket_(NULL),
last_packet_number_(0) {
}
RtpWriter::~RtpWriter() { }
// Initializes the writer. Must be called on the thread the sockets belong
// to.
void RtpWriter::Init(net::Socket* rtp_socket, net::Socket* rtcp_socket) {
buffered_rtp_writer_ = new BufferedDatagramWriter();
buffered_rtp_writer_->Init(rtp_socket, NULL);
rtp_socket_ = rtp_socket;
rtcp_socket_ = rtcp_socket;
}
void RtpWriter::SendPacket(const char* payload, int payload_size,
uint32 timestamp) {
RtpHeader header;
header.padding = false;
header.extension = false;
header.sources = 0;
header.payload_type = kRtpPayloadTypePrivate;
header.timestamp = timestamp;
// TODO(sergeyu): RTP requires that SSRC is chosen randomly by each
// participant. There are only two participants in chromoting session,
// so SSRC isn't useful. Implement it in future if neccessary.
header.sync_source_id = 0;
// TODO(sergeyu): Add VP8 payload header.
int position = 0;
while (position < payload_size) {
// Allocate buffer.
int size = std::min(kMtu, payload_size - position);
int header_size = GetRtpHeaderSize(header.sources);
int total_size = size + header_size;
net::IOBufferWithSize* buffer = new net::IOBufferWithSize(total_size);
// Set marker if this is the last frame.
header.marker = (position + size) == payload_size;
// TODO(sergeyu): Handle sequence number wrapping.
header.sequence_number = last_packet_number_;
++last_packet_number_;
// Generate header.
PackRtpHeader(reinterpret_cast<uint8*>(buffer->data()), buffer->size(),
header);
// Copy data to the buffer.
memcpy(buffer->data() + header_size, payload + position, size);
// Send it.
buffered_rtp_writer_->Write(buffer);
position += size;
}
DCHECK_EQ(position, payload_size);
}
int RtpWriter::GetPendingPackets() {
return buffered_rtp_writer_->GetBufferChunks();
}
// Stop writing and drop pending data. Must be called from the same thread as
// Init().
void RtpWriter::Close() {
buffered_rtp_writer_->Close();
}
} // namespace remoting
|