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.
5 #include "remoting/base/encoder_zlib.h"
8 #include "media/base/data_buffer.h"
9 #include "remoting/base/capture_data.h"
10 #include "remoting/base/compressor_zlib.h"
11 #include "remoting/base/protocol_util.h"
12 #include "remoting/base/protocol/chromotocol.pb.h"
16 static const int kPacketSize
= 1024 * 1024;
18 EncoderZlib::EncoderZlib() : packet_size_(kPacketSize
) {
21 EncoderZlib::EncoderZlib(int packet_size
) : packet_size_(packet_size
) {
24 void EncoderZlib::Encode(scoped_refptr
<CaptureData
> capture_data
,
26 DataAvailableCallback
* data_available_callback
) {
27 CHECK(capture_data
->pixel_format() == PixelFormatRgb32
)
28 << "Zlib Encoder only works with RGB32";
29 capture_data_
= capture_data
;
30 callback_
.reset(data_available_callback
);
32 CompressorZlib compressor
;
33 const InvalidRects
& rects
= capture_data
->dirty_rects();
35 for (InvalidRects::const_iterator r
= rects
.begin();
36 r
!= rects
.end(); ++r
, ++index
) {
37 EncodeRect(&compressor
, *r
, index
);
44 void EncoderZlib::EncodeRect(CompressorZlib
* compressor
,
45 const gfx::Rect
& rect
, size_t rect_index
) {
46 CHECK(capture_data_
->data_planes().data
[0]);
47 const int strides
= capture_data_
->data_planes().strides
[0];
48 const int bytes_per_pixel
= GetBytesPerPixel(capture_data_
->pixel_format());
49 const int row_size
= bytes_per_pixel
* rect
.width();
51 HostMessage
* message
= PrepareMessage(&rect
);
52 const uint8
* in
= capture_data_
->data_planes().data
[0] +
54 rect
.x() * bytes_per_pixel
;
55 // TODO(hclam): Fill in the sequence number.
56 uint8
* out
= (uint8
*)message
->mutable_update_stream_packet()->
57 mutable_rect_data()->mutable_data()->data();
61 bool compress_again
= true;
62 while (compress_again
) {
63 // Prepare a message for sending out.
65 message
= PrepareMessage(NULL
);
66 out
= (uint8
*)(message
->mutable_update_stream_packet()->
67 mutable_rect_data()->mutable_data()->data());
71 Compressor::CompressorFlush flush
= Compressor::CompressorNoFlush
;
72 if (row_y
== rect
.height() - 1) {
73 if (rect_index
== capture_data_
->dirty_rects().size() - 1) {
74 flush
= Compressor::CompressorFinish
;
76 flush
= Compressor::CompressorSyncFlush
;
82 compress_again
= compressor
->Process(in
+ row_x
, row_size
- row_x
,
83 out
+ filled
, packet_size_
- filled
,
84 flush
, &consumed
, &written
);
88 // We have reached the end of stream.
89 if (!compress_again
) {
90 message
->mutable_update_stream_packet()->mutable_end_rect();
93 // If we have filled the message or we have reached the end of stream.
94 if (filled
== packet_size_
|| !compress_again
) {
95 message
->mutable_update_stream_packet()->mutable_rect_data()->
96 mutable_data()->resize(filled
);
97 SubmitMessage(message
, rect_index
);
101 // Reached the end of input row and we're not at the last row.
102 if (row_x
== row_size
&& row_y
< rect
.height() - 1) {
110 HostMessage
* EncoderZlib::PrepareMessage(const gfx::Rect
* rect
) {
111 HostMessage
* message
= new HostMessage();
112 UpdateStreamPacketMessage
* packet
= message
->mutable_update_stream_packet();
114 // Prepare the begin rect content.
116 packet
->mutable_begin_rect()->set_x(rect
->x());
117 packet
->mutable_begin_rect()->set_y(rect
->y());
118 packet
->mutable_begin_rect()->set_width(rect
->width());
119 packet
->mutable_begin_rect()->set_height(rect
->height());
120 packet
->mutable_begin_rect()->set_encoding(EncodingZlib
);
121 packet
->mutable_begin_rect()->set_pixel_format(
122 capture_data_
->pixel_format());
125 packet
->mutable_rect_data()->mutable_data()->resize(packet_size_
);
129 void EncoderZlib::SubmitMessage(HostMessage
* message
, size_t rect_index
) {
130 EncodingState state
= EncodingInProgress
;
131 if (rect_index
== 0 && message
->update_stream_packet().has_begin_rect())
132 state
|= EncodingStarting
;
133 if (rect_index
== capture_data_
->dirty_rects().size() - 1 &&
134 message
->update_stream_packet().has_end_rect())
135 state
|= EncodingEnded
;
136 callback_
->Run(message
, state
);
139 } // namespace remoting