OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/codec/video_encoder_verbatim.h" | 5 #include "remoting/codec/video_encoder_verbatim.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/video/capture/screen/screen_capture_data.h" | 8 #include "base/stl_util.h" |
9 #include "remoting/base/util.h" | 9 #include "remoting/base/util.h" |
10 #include "remoting/proto/video.pb.h" | 10 #include "remoting/proto/video.pb.h" |
| 11 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
11 | 12 |
12 namespace remoting { | 13 namespace remoting { |
13 | 14 |
14 static const int kPacketSize = 1024 * 1024; | 15 static const int kPacketSize = 1024 * 1024; |
15 | 16 |
16 VideoEncoderVerbatim::VideoEncoderVerbatim() | 17 VideoEncoderVerbatim::VideoEncoderVerbatim() |
17 : screen_size_(SkISize::Make(0,0)), | 18 : max_packet_size_(kPacketSize) { |
18 max_packet_size_(kPacketSize) { | |
19 } | 19 } |
20 | 20 |
21 void VideoEncoderVerbatim::SetMaxPacketSize(int size) { | 21 void VideoEncoderVerbatim::SetMaxPacketSize(int size) { |
22 max_packet_size_ = size; | 22 max_packet_size_ = size; |
23 } | 23 } |
24 | 24 |
25 VideoEncoderVerbatim::~VideoEncoderVerbatim() { | 25 VideoEncoderVerbatim::~VideoEncoderVerbatim() { |
26 } | 26 } |
27 | 27 |
28 void VideoEncoderVerbatim::Encode( | 28 void VideoEncoderVerbatim::Encode( |
29 scoped_refptr<media::ScreenCaptureData> capture_data, | 29 const webrtc::DesktopFrame* frame, |
30 bool key_frame, | |
31 const DataAvailableCallback& data_available_callback) { | 30 const DataAvailableCallback& data_available_callback) { |
32 capture_data_ = capture_data; | |
33 callback_ = data_available_callback; | 31 callback_ = data_available_callback; |
34 encode_start_time_ = base::Time::Now(); | 32 encode_start_time_ = base::Time::Now(); |
35 | 33 |
36 const SkRegion& region = capture_data->dirty_region(); | 34 webrtc::DesktopRegion::Iterator iter(frame->updated_region()); |
37 SkRegion::Iterator iter(region); | 35 while (!iter.IsAtEnd()) { |
38 while (!iter.done()) { | 36 const webrtc::DesktopRect& rect = iter.rect(); |
39 SkIRect rect = iter.rect(); | 37 iter.Advance(); |
40 iter.next(); | 38 EncodeRect(frame, rect, iter.IsAtEnd()); |
41 EncodeRect(rect, iter.done()); | |
42 } | 39 } |
43 | 40 |
44 capture_data_ = NULL; | |
45 callback_.Reset(); | 41 callback_.Reset(); |
46 } | 42 } |
47 | 43 |
48 void VideoEncoderVerbatim::EncodeRect(const SkIRect& rect, bool last) { | 44 void VideoEncoderVerbatim::EncodeRect(const webrtc::DesktopFrame* frame, |
49 CHECK(capture_data_->data()); | 45 const webrtc::DesktopRect& rect, |
50 const int stride = capture_data_->stride(); | 46 bool last) { |
| 47 CHECK(frame->data()); |
| 48 const int stride = frame->stride(); |
51 const int bytes_per_pixel = 4; | 49 const int bytes_per_pixel = 4; |
52 const int row_size = bytes_per_pixel * rect.width(); | 50 const int row_size = bytes_per_pixel * rect.width(); |
53 | 51 |
54 scoped_ptr<VideoPacket> packet(new VideoPacket()); | 52 scoped_ptr<VideoPacket> packet(new VideoPacket()); |
55 PrepareUpdateStart(rect, packet.get()); | 53 PrepareUpdateStart(frame, rect, packet.get()); |
56 const uint8* in = capture_data_->data() + | 54 const uint8* in = frame->data() + |
57 rect.fTop * stride + rect.fLeft * bytes_per_pixel; | 55 rect.top() * stride + rect.left() * bytes_per_pixel; |
58 // TODO(hclam): Fill in the sequence number. | 56 // TODO(hclam): Fill in the sequence number. |
59 uint8* out = GetOutputBuffer(packet.get(), max_packet_size_); | 57 uint8* out = GetOutputBuffer(packet.get(), max_packet_size_); |
60 int filled = 0; | 58 int filled = 0; |
61 int row_pos = 0; // Position in the current row in bytes. | 59 int row_pos = 0; // Position in the current row in bytes. |
62 int row_y = 0; // Current row. | 60 int row_y = 0; // Current row. |
63 while (row_y < rect.height()) { | 61 while (row_y < rect.height()) { |
64 // Prepare a message for sending out. | 62 // Prepare a message for sending out. |
65 if (!packet.get()) { | 63 if (!packet.get()) { |
66 packet.reset(new VideoPacket()); | 64 packet.reset(new VideoPacket()); |
67 out = GetOutputBuffer(packet.get(), max_packet_size_); | 65 out = GetOutputBuffer(packet.get(), max_packet_size_); |
(...skipping 13 matching lines...) Expand all Loading... |
81 in += stride; | 79 in += stride; |
82 ++row_y; | 80 ++row_y; |
83 } | 81 } |
84 } | 82 } |
85 | 83 |
86 if (row_y == rect.height()) { | 84 if (row_y == rect.height()) { |
87 DCHECK_EQ(row_pos, 0); | 85 DCHECK_EQ(row_pos, 0); |
88 | 86 |
89 packet->mutable_data()->resize(filled); | 87 packet->mutable_data()->resize(filled); |
90 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); | 88 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); |
91 packet->set_capture_time_ms(capture_data_->capture_time_ms()); | 89 |
| 90 packet->set_capture_time_ms(frame->capture_time_ms()); |
92 packet->set_encode_time_ms( | 91 packet->set_encode_time_ms( |
93 (base::Time::Now() - encode_start_time_).InMillisecondsRoundedUp()); | 92 (base::Time::Now() - encode_start_time_).InMillisecondsRoundedUp()); |
94 packet->set_client_sequence_number( | 93 if (!frame->dpi().is_zero()) { |
95 capture_data_->client_sequence_number()); | 94 packet->mutable_format()->set_x_dpi(frame->dpi().x()); |
96 SkIPoint dpi(capture_data_->dpi()); | 95 packet->mutable_format()->set_y_dpi(frame->dpi().y()); |
97 if (dpi.x()) | 96 } |
98 packet->mutable_format()->set_x_dpi(dpi.x()); | |
99 if (dpi.y()) | |
100 packet->mutable_format()->set_y_dpi(dpi.y()); | |
101 if (last) | 97 if (last) |
102 packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION); | 98 packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION); |
103 } | 99 } |
104 | 100 |
105 // If we have filled the current packet, then send it. | 101 // If we have filled the current packet, then send it. |
106 if (filled == max_packet_size_ || row_y == rect.height()) { | 102 if (filled == max_packet_size_ || row_y == rect.height()) { |
107 packet->mutable_data()->resize(filled); | 103 packet->mutable_data()->resize(filled); |
108 callback_.Run(packet.Pass()); | 104 callback_.Run(packet.Pass()); |
109 } | 105 } |
110 } | 106 } |
111 } | 107 } |
112 | 108 |
113 void VideoEncoderVerbatim::PrepareUpdateStart(const SkIRect& rect, | 109 void VideoEncoderVerbatim::PrepareUpdateStart(const webrtc::DesktopFrame* frame, |
| 110 const webrtc::DesktopRect& rect, |
114 VideoPacket* packet) { | 111 VideoPacket* packet) { |
115 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); | 112 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); |
116 | 113 |
117 VideoPacketFormat* format = packet->mutable_format(); | 114 VideoPacketFormat* format = packet->mutable_format(); |
118 format->set_x(rect.fLeft); | 115 format->set_x(rect.left()); |
119 format->set_y(rect.fTop); | 116 format->set_y(rect.top()); |
120 format->set_width(rect.width()); | 117 format->set_width(rect.width()); |
121 format->set_height(rect.height()); | 118 format->set_height(rect.height()); |
122 format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM); | 119 format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM); |
123 if (capture_data_->size() != screen_size_) { | 120 if (frame->size().equals(screen_size_)) { |
124 screen_size_ = capture_data_->size(); | 121 screen_size_ = frame->size(); |
125 format->set_screen_width(screen_size_.width()); | 122 format->set_screen_width(screen_size_.width()); |
126 format->set_screen_height(screen_size_.height()); | 123 format->set_screen_height(screen_size_.height()); |
127 } | 124 } |
128 } | 125 } |
129 | 126 |
130 uint8* VideoEncoderVerbatim::GetOutputBuffer(VideoPacket* packet, size_t size) { | 127 uint8* VideoEncoderVerbatim::GetOutputBuffer(VideoPacket* packet, size_t size) { |
131 packet->mutable_data()->resize(size); | 128 packet->mutable_data()->resize(size); |
132 // TODO(ajwong): Is there a better way to do this at all??? | 129 return reinterpret_cast<uint8*>(string_as_array(packet->mutable_data())); |
133 return const_cast<uint8*>(reinterpret_cast<const uint8*>( | |
134 packet->mutable_data()->data())); | |
135 } | 130 } |
136 | 131 |
137 } // namespace remoting | 132 } // namespace remoting |
OLD | NEW |