| Index: remoting/codec/video_encoder_verbatim.cc
|
| diff --git a/remoting/codec/video_encoder_verbatim.cc b/remoting/codec/video_encoder_verbatim.cc
|
| index 4680362a02d20eb75094e2ab7b91ca90d3f6a2a5..424221bfe6b6330b40585d092402f954c101fdc3 100644
|
| --- a/remoting/codec/video_encoder_verbatim.cc
|
| +++ b/remoting/codec/video_encoder_verbatim.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "base/logging.h"
|
| #include "base/stl_util.h"
|
| +#include "base/time/time.h"
|
| #include "remoting/base/util.h"
|
| #include "remoting/proto/video.pb.h"
|
| #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
|
| @@ -14,119 +15,71 @@ namespace remoting {
|
|
|
| static const int kPacketSize = 1024 * 1024;
|
|
|
| -VideoEncoderVerbatim::VideoEncoderVerbatim()
|
| - : max_packet_size_(kPacketSize) {
|
| -}
|
| +VideoEncoderVerbatim::VideoEncoderVerbatim() {}
|
| +VideoEncoderVerbatim::~VideoEncoderVerbatim() {}
|
|
|
| -void VideoEncoderVerbatim::SetMaxPacketSize(int size) {
|
| - max_packet_size_ = size;
|
| -}
|
| +scoped_ptr<VideoPacket> VideoEncoderVerbatim::Encode(
|
| + const webrtc::DesktopFrame& frame) {
|
| + CHECK(frame.data());
|
|
|
| -VideoEncoderVerbatim::~VideoEncoderVerbatim() {
|
| -}
|
| + base::Time encode_start_time = base::Time::Now();
|
| + scoped_ptr<VideoPacket> packet(new VideoPacket());
|
|
|
| -void VideoEncoderVerbatim::Encode(
|
| - const webrtc::DesktopFrame* frame,
|
| - const DataAvailableCallback& data_available_callback) {
|
| - callback_ = data_available_callback;
|
| - encode_start_time_ = base::Time::Now();
|
| + VideoPacketFormat* format = packet->mutable_format();
|
| + format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM);
|
| + if (!frame.size().equals(screen_size_)) {
|
| + screen_size_ = frame.size();
|
| + format->set_screen_width(screen_size_.width());
|
| + format->set_screen_height(screen_size_.height());
|
| + }
|
|
|
| - webrtc::DesktopRegion::Iterator iter(frame->updated_region());
|
| - while (!iter.IsAtEnd()) {
|
| + // Calculate output size.
|
| + size_t output_size = 0;
|
| + for (webrtc::DesktopRegion::Iterator iter(frame.updated_region());
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| const webrtc::DesktopRect& rect = iter.rect();
|
| - iter.Advance();
|
| - EncodeRect(frame, rect, iter.IsAtEnd());
|
| + output_size += rect.width() * rect.height() *
|
| + webrtc::DesktopFrame::kBytesPerPixel;
|
| }
|
|
|
| - callback_.Reset();
|
| -}
|
| -
|
| -void VideoEncoderVerbatim::EncodeRect(const webrtc::DesktopFrame* frame,
|
| - const webrtc::DesktopRect& rect,
|
| - bool last) {
|
| - CHECK(frame->data());
|
| - const int stride = frame->stride();
|
| - const int bytes_per_pixel = 4;
|
| - const int row_size = bytes_per_pixel * rect.width();
|
| + uint8_t* out = GetOutputBuffer(packet.get(), output_size);
|
| + const int in_stride = frame.stride();
|
|
|
| - scoped_ptr<VideoPacket> packet(new VideoPacket());
|
| - PrepareUpdateStart(frame, rect, packet.get());
|
| - const uint8* in = frame->data() +
|
| - rect.top() * stride + rect.left() * bytes_per_pixel;
|
| - // TODO(hclam): Fill in the sequence number.
|
| - uint8* out = GetOutputBuffer(packet.get(), max_packet_size_);
|
| - int filled = 0;
|
| - int row_pos = 0; // Position in the current row in bytes.
|
| - int row_y = 0; // Current row.
|
| - while (row_y < rect.height()) {
|
| - // Prepare a message for sending out.
|
| - if (!packet.get()) {
|
| - packet.reset(new VideoPacket());
|
| - out = GetOutputBuffer(packet.get(), max_packet_size_);
|
| - filled = 0;
|
| - }
|
| -
|
| - if (row_y < rect.height()) {
|
| - int bytes_to_copy =
|
| - std::min(row_size - row_pos, max_packet_size_ - filled);
|
| - memcpy(out + filled, in + row_pos, bytes_to_copy);
|
| - row_pos += bytes_to_copy;
|
| - filled += bytes_to_copy;
|
| -
|
| - // Jump to the next row when we've reached the end of the current row.
|
| - if (row_pos == row_size) {
|
| - row_pos = 0;
|
| - in += stride;
|
| - ++row_y;
|
| - }
|
| - }
|
| -
|
| - if (row_y == rect.height()) {
|
| - DCHECK_EQ(row_pos, 0);
|
| -
|
| - packet->mutable_data()->resize(filled);
|
| - packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET);
|
| -
|
| - packet->set_capture_time_ms(frame->capture_time_ms());
|
| - packet->set_encode_time_ms(
|
| - (base::Time::Now() - encode_start_time_).InMillisecondsRoundedUp());
|
| - if (!frame->dpi().is_zero()) {
|
| - packet->mutable_format()->set_x_dpi(frame->dpi().x());
|
| - packet->mutable_format()->set_y_dpi(frame->dpi().y());
|
| - }
|
| - if (last)
|
| - packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION);
|
| + // Store all changed rectangles in the packet.
|
| + for (webrtc::DesktopRegion::Iterator iter(frame.updated_region());
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| + const webrtc::DesktopRect& rect = iter.rect();
|
| + const int row_size = webrtc::DesktopFrame::kBytesPerPixel * rect.width();
|
| + const uint8_t* in = frame.data() + rect.top() * in_stride +
|
| + rect.left() * webrtc::DesktopFrame::kBytesPerPixel;
|
| + for (int y = rect.top(); y < rect.top() + rect.height(); ++y) {
|
| + memcpy(out, in, row_size);
|
| + out += row_size;
|
| + in += in_stride;
|
| }
|
|
|
| - // If we have filled the current packet, then send it.
|
| - if (filled == max_packet_size_ || row_y == rect.height()) {
|
| - packet->mutable_data()->resize(filled);
|
| - callback_.Run(packet.Pass());
|
| - }
|
| + Rect* dirty_rect = packet->add_dirty_rects();
|
| + dirty_rect->set_x(rect.left());
|
| + dirty_rect->set_y(rect.top());
|
| + dirty_rect->set_width(rect.width());
|
| + dirty_rect->set_height(rect.height());
|
| }
|
| -}
|
|
|
| -void VideoEncoderVerbatim::PrepareUpdateStart(const webrtc::DesktopFrame* frame,
|
| - const webrtc::DesktopRect& rect,
|
| - VideoPacket* packet) {
|
| - packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET);
|
| -
|
| - VideoPacketFormat* format = packet->mutable_format();
|
| - format->set_x(rect.left());
|
| - format->set_y(rect.top());
|
| - format->set_width(rect.width());
|
| - format->set_height(rect.height());
|
| - format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM);
|
| - if (frame->size().equals(screen_size_)) {
|
| - screen_size_ = frame->size();
|
| - format->set_screen_width(screen_size_.width());
|
| - format->set_screen_height(screen_size_.height());
|
| + packet->set_capture_time_ms(frame.capture_time_ms());
|
| + packet->set_encode_time_ms(
|
| + (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
|
| + if (!frame.dpi().is_zero()) {
|
| + packet->mutable_format()->set_x_dpi(frame.dpi().x());
|
| + packet->mutable_format()->set_y_dpi(frame.dpi().y());
|
| }
|
| +
|
| + return packet.Pass();
|
| }
|
|
|
| -uint8* VideoEncoderVerbatim::GetOutputBuffer(VideoPacket* packet, size_t size) {
|
| +uint8_t* VideoEncoderVerbatim::GetOutputBuffer(VideoPacket* packet,
|
| + size_t size) {
|
| packet->mutable_data()->resize(size);
|
| - return reinterpret_cast<uint8*>(string_as_array(packet->mutable_data()));
|
| + return reinterpret_cast<uint8_t*>(string_as_array(packet->mutable_data()));
|
| }
|
|
|
| } // namespace remoting
|
|
|