OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/base/encoder_verbatim.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "gfx/rect.h" | |
9 #include "net/base/io_buffer.h" | |
10 #include "remoting/base/capture_data.h" | |
11 #include "remoting/base/util.h" | |
12 #include "remoting/proto/video.pb.h" | |
13 | |
14 namespace remoting { | |
15 | |
16 // TODO(garykac): Move up into shared location. Share value with encoder_zlib. | |
17 // TODO(garykac): 10* is added to ensure that rects fit in a single packet. | |
18 // Add support for splitting across packets and remove the 10*. | |
19 static const int kPacketSize = 10 * 1024 * 1024; | |
20 | |
21 EncoderVerbatim::EncoderVerbatim() | |
22 : packet_size_(kPacketSize) { | |
23 } | |
24 | |
25 EncoderVerbatim::EncoderVerbatim(int packet_size) | |
26 : packet_size_(packet_size) { | |
27 } | |
28 | |
29 void EncoderVerbatim::Encode(scoped_refptr<CaptureData> capture_data, | |
30 bool key_frame, | |
31 DataAvailableCallback* data_available_callback) { | |
32 capture_data_ = capture_data; | |
33 callback_.reset(data_available_callback); | |
34 | |
35 const InvalidRects& rects = capture_data->dirty_rects(); | |
36 int index = 0; | |
37 for (InvalidRects::const_iterator r = rects.begin(); | |
38 r != rects.end(); ++r, ++index) { | |
39 EncodeRect(*r, index); | |
40 } | |
41 | |
42 capture_data_ = NULL; | |
43 callback_.reset(); | |
44 } | |
45 | |
46 // TODO(garykac): This assumes that the rect fits into a single packet. | |
47 // Fix this by modeling after code in encoder_zlib.cc | |
48 void EncoderVerbatim::EncodeRect(const gfx::Rect& rect, size_t rect_index) { | |
49 CHECK(capture_data_->data_planes().data[0]); | |
50 const int stride = capture_data_->data_planes().strides[0]; | |
51 const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); | |
52 const int row_size = bytes_per_pixel * rect.width(); | |
53 | |
54 VideoPacket* packet = new VideoPacket(); | |
55 PrepareUpdateStart(rect, packet); | |
56 | |
57 const uint8* in = capture_data_->data_planes().data[0] + | |
58 rect.y() * stride + | |
59 rect.x() * bytes_per_pixel; | |
60 // TODO(hclam): Fill in the sequence number. | |
61 uint8* out = GetOutputBuffer(packet, packet_size_); | |
62 int total_bytes = 0; | |
63 for (int y = 0; y < rect.height(); y++) { | |
64 memcpy(out, in, row_size); | |
65 out += row_size; | |
66 in += stride; | |
67 total_bytes += row_size; | |
68 } | |
69 | |
70 // We have reached the end of stream. | |
71 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); | |
72 | |
73 // If we have filled the message or we have reached the end of stream. | |
74 packet->mutable_data()->resize(total_bytes); | |
75 SubmitMessage(packet, rect_index); | |
76 } | |
77 | |
78 void EncoderVerbatim::PrepareUpdateStart(const gfx::Rect& rect, | |
79 VideoPacket* packet) { | |
80 | |
81 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); | |
82 VideoPacketFormat* format = packet->mutable_format(); | |
83 | |
84 format->set_x(rect.x()); | |
85 format->set_y(rect.y()); | |
86 format->set_width(rect.width()); | |
87 format->set_height(rect.height()); | |
88 format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM); | |
89 } | |
90 | |
91 uint8* EncoderVerbatim::GetOutputBuffer(VideoPacket* packet, size_t size) { | |
92 packet->mutable_data()->resize(size); | |
93 // TODO(ajwong): Is there a better way to do this at all??? | |
94 return const_cast<uint8*>(reinterpret_cast<const uint8*>( | |
95 packet->mutable_data()->data())); | |
96 } | |
97 | |
98 void EncoderVerbatim::SubmitMessage(VideoPacket* packet, size_t rect_index) { | |
99 callback_->Run(packet); | |
100 } | |
101 | |
102 } // namespace remoting | |
OLD | NEW |