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/base/encoder_zlib.h" | 5 #include "remoting/base/encoder_row_based.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "gfx/rect.h" | 8 #include "gfx/rect.h" |
9 #include "remoting/base/capture_data.h" | 9 #include "remoting/base/capture_data.h" |
10 #include "remoting/base/compressor_verbatim.h" | |
10 #include "remoting/base/compressor_zlib.h" | 11 #include "remoting/base/compressor_zlib.h" |
11 #include "remoting/base/util.h" | 12 #include "remoting/base/util.h" |
12 #include "remoting/proto/video.pb.h" | 13 #include "remoting/proto/video.pb.h" |
13 | 14 |
14 namespace remoting { | 15 namespace remoting { |
15 | 16 |
16 static const int kPacketSize = 1024 * 1024; | 17 static const int kPacketSize = 1024 * 1024; |
17 | 18 |
18 EncoderZlib::EncoderZlib() : packet_size_(kPacketSize) { | 19 EncoderRowBased* EncoderRowBased::CreateZlibEncoder() { |
20 return new EncoderRowBased(new CompressorZlib(), | |
21 VideoPacketFormat::ENCODING_ZLIB); | |
19 } | 22 } |
20 | 23 |
21 EncoderZlib::EncoderZlib(int packet_size) : packet_size_(packet_size) { | 24 EncoderRowBased* EncoderRowBased::CreateVerbatimEncoder() { |
25 return new EncoderRowBased(new CompressorVerbatim(), | |
26 VideoPacketFormat::ENCODING_VERBATIM); | |
22 } | 27 } |
23 | 28 |
24 EncoderZlib::~EncoderZlib() {} | 29 EncoderRowBased::EncoderRowBased(Compressor* compressor, |
30 VideoPacketFormat::Encoding encoding) | |
31 : encoding_(encoding), | |
32 compressor_(compressor), | |
33 packet_size_(kPacketSize) { | |
34 } | |
25 | 35 |
26 void EncoderZlib::Encode(scoped_refptr<CaptureData> capture_data, | 36 EncoderRowBased::EncoderRowBased(Compressor* compressor, |
27 bool key_frame, | 37 VideoPacketFormat::Encoding encoding, |
28 DataAvailableCallback* data_available_callback) { | 38 int packet_size) |
39 : encoding_(encoding), | |
40 compressor_(compressor), | |
41 packet_size_(packet_size) { | |
42 } | |
43 | |
44 EncoderRowBased::~EncoderRowBased() {} | |
45 | |
46 void EncoderRowBased::Encode(scoped_refptr<CaptureData> capture_data, | |
47 bool key_frame, | |
48 DataAvailableCallback* data_available_callback) { | |
29 CHECK(capture_data->pixel_format() == media::VideoFrame::RGB32) | 49 CHECK(capture_data->pixel_format() == media::VideoFrame::RGB32) |
30 << "Zlib Encoder only works with RGB32. Got " | 50 << "RowBased Encoder only works with RGB32. Got " |
31 << capture_data->pixel_format(); | 51 << capture_data->pixel_format(); |
32 capture_data_ = capture_data; | 52 capture_data_ = capture_data; |
33 callback_.reset(data_available_callback); | 53 callback_.reset(data_available_callback); |
34 | 54 |
35 CompressorZlib compressor; | |
36 const InvalidRects& rects = capture_data->dirty_rects(); | 55 const InvalidRects& rects = capture_data->dirty_rects(); |
37 int index = 0; | 56 int index = 0; |
38 for (InvalidRects::const_iterator r = rects.begin(); | 57 for (InvalidRects::const_iterator r = rects.begin(); |
39 r != rects.end(); ++r, ++index) { | 58 r != rects.end(); ++r, ++index) { |
40 EncodeRect(&compressor, *r, index); | 59 EncodeRect(*r, index); |
41 } | 60 } |
42 | 61 |
43 capture_data_ = NULL; | 62 capture_data_ = NULL; |
44 callback_.reset(); | 63 callback_.reset(); |
45 } | 64 } |
46 | 65 |
47 void EncoderZlib::EncodeRect(CompressorZlib* compressor, | 66 void EncoderRowBased::EncodeRect(const gfx::Rect& rect, size_t rect_index) { |
48 const gfx::Rect& rect, size_t rect_index) { | |
49 CHECK(capture_data_->data_planes().data[0]); | 67 CHECK(capture_data_->data_planes().data[0]); |
50 const int strides = capture_data_->data_planes().strides[0]; | 68 const int strides = capture_data_->data_planes().strides[0]; |
51 const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); | 69 const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); |
52 const int row_size = bytes_per_pixel * rect.width(); | 70 const int row_size = bytes_per_pixel * rect.width(); |
53 | 71 |
72 compressor_->Reset(); | |
73 | |
54 VideoPacket* packet = new VideoPacket(); | 74 VideoPacket* packet = new VideoPacket(); |
55 PrepareUpdateStart(rect, packet); | 75 PrepareUpdateStart(rect, packet); |
56 const uint8* in = capture_data_->data_planes().data[0] + | 76 const uint8* in = capture_data_->data_planes().data[0] + |
57 rect.y() * strides + | 77 rect.y() * strides + rect.x() * bytes_per_pixel; |
58 rect.x() * bytes_per_pixel; | |
59 // TODO(hclam): Fill in the sequence number. | 78 // TODO(hclam): Fill in the sequence number. |
60 uint8* out = GetOutputBuffer(packet, packet_size_); | 79 uint8* out = GetOutputBuffer(packet, packet_size_); |
61 int filled = 0; | 80 int filled = 0; |
62 int row_x = 0; | 81 int row_pos = 0; // Position in the current row in bytes. |
63 int row_y = 0; | 82 int row_y = 0; // Current row. |
64 bool compress_again = true; | 83 bool compress_again = true; |
65 while (compress_again) { | 84 while (compress_again) { |
66 // Prepare a message for sending out. | 85 // Prepare a message for sending out. |
67 if (!packet) { | 86 if (!packet) { |
68 packet = new VideoPacket(); | 87 packet = new VideoPacket(); |
69 out = GetOutputBuffer(packet, packet_size_); | 88 out = GetOutputBuffer(packet, packet_size_); |
70 filled = 0; | 89 filled = 0; |
71 } | 90 } |
72 | 91 |
73 Compressor::CompressorFlush flush = Compressor::CompressorNoFlush; | 92 Compressor::CompressorFlush flush = Compressor::CompressorNoFlush; |
74 if (row_y == rect.height() - 1) { | 93 if (row_y == rect.height() - 1) { |
75 if (rect_index == capture_data_->dirty_rects().size() - 1) { | 94 flush = Compressor::CompressorFinish; |
76 flush = Compressor::CompressorFinish; | |
77 } else { | |
78 flush = Compressor::CompressorSyncFlush; | |
Alpha Left Google
2010/12/02 19:39:55
It is fine that we don't use sync flush but we nee
Sergey Ulanov
2010/12/03 00:17:21
Added comments about it in the header.
| |
79 } | |
80 } | 95 } |
81 | 96 |
82 int consumed = 0; | 97 int consumed = 0; |
83 int written = 0; | 98 int written = 0; |
84 compress_again = compressor->Process(in + row_x, row_size - row_x, | 99 compress_again = compressor_->Process(in + row_pos, row_size - row_pos, |
85 out + filled, packet_size_ - filled, | 100 out + filled, packet_size_ - filled, |
86 flush, &consumed, &written); | 101 flush, &consumed, &written); |
87 row_x += consumed; | 102 row_pos += consumed; |
88 filled += written; | 103 filled += written; |
89 | 104 |
90 // We have reached the end of stream. | 105 // We have reached the end of stream. |
91 if (!compress_again) { | 106 if (!compress_again) { |
92 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); | 107 packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); |
108 DCHECK(row_pos == row_size); | |
109 DCHECK(row_y == rect.height() - 1); | |
93 } | 110 } |
94 | 111 |
95 // If we have filled the message or we have reached the end of stream. | 112 // If we have filled the message or we have reached the end of stream. |
96 if (filled == packet_size_ || !compress_again) { | 113 if (filled == packet_size_ || !compress_again) { |
97 packet->mutable_data()->resize(filled); | 114 packet->mutable_data()->resize(filled); |
98 SubmitMessage(packet, rect_index); | 115 callback_->Run(packet); |
99 packet = NULL; | 116 packet = NULL; |
100 } | 117 } |
101 | 118 |
102 // Reached the end of input row and we're not at the last row. | 119 // Reached the end of input row and we're not at the last row. |
103 if (row_x == row_size && row_y < rect.height() - 1) { | 120 if (row_pos == row_size && row_y < rect.height() - 1) { |
104 row_x = 0; | 121 row_pos = 0; |
105 in += strides; | 122 in += strides; |
106 ++row_y; | 123 ++row_y; |
107 } | 124 } |
108 } | 125 } |
109 } | 126 } |
110 | 127 |
111 void EncoderZlib::PrepareUpdateStart(const gfx::Rect& rect, | 128 void EncoderRowBased::PrepareUpdateStart(const gfx::Rect& rect, |
112 VideoPacket* packet) { | 129 VideoPacket* packet) { |
113 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); | 130 packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); |
131 | |
114 VideoPacketFormat* format = packet->mutable_format(); | 132 VideoPacketFormat* format = packet->mutable_format(); |
115 | |
116 format->set_x(rect.x()); | 133 format->set_x(rect.x()); |
117 format->set_y(rect.y()); | 134 format->set_y(rect.y()); |
118 format->set_width(rect.width()); | 135 format->set_width(rect.width()); |
119 format->set_height(rect.height()); | 136 format->set_height(rect.height()); |
120 format->set_encoding(VideoPacketFormat::ENCODING_ZLIB); | 137 format->set_encoding(encoding_); |
121 } | 138 } |
122 | 139 |
123 uint8* EncoderZlib::GetOutputBuffer(VideoPacket* packet, size_t size) { | 140 uint8* EncoderRowBased::GetOutputBuffer(VideoPacket* packet, size_t size) { |
124 packet->mutable_data()->resize(size); | 141 packet->mutable_data()->resize(size); |
125 // TODO(ajwong): Is there a better way to do this at all??? | 142 // TODO(ajwong): Is there a better way to do this at all??? |
126 return const_cast<uint8*>(reinterpret_cast<const uint8*>( | 143 return const_cast<uint8*>(reinterpret_cast<const uint8*>( |
127 packet->mutable_data()->data())); | 144 packet->mutable_data()->data())); |
128 } | 145 } |
129 | 146 |
130 void EncoderZlib::SubmitMessage(VideoPacket* packet, size_t rect_index) { | |
131 callback_->Run(packet); | |
132 } | |
133 | 147 |
134 } // namespace remoting | 148 } // namespace remoting |
OLD | NEW |