| 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; | |
| 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 |