Home | History | Annotate | Download | only in codec
      1 // Copyright (c) 2012 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/codec/video_encoder_verbatim.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "base/time/time.h"
     10 #include "remoting/base/util.h"
     11 #include "remoting/proto/video.pb.h"
     12 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
     13 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
     14 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
     15 
     16 namespace remoting {
     17 
     18 static uint8_t* GetPacketOutputBuffer(VideoPacket* packet, size_t size) {
     19   packet->mutable_data()->resize(size);
     20   return reinterpret_cast<uint8_t*>(string_as_array(packet->mutable_data()));
     21 }
     22 
     23 VideoEncoderVerbatim::VideoEncoderVerbatim() {}
     24 VideoEncoderVerbatim::~VideoEncoderVerbatim() {}
     25 
     26 scoped_ptr<VideoPacket> VideoEncoderVerbatim::Encode(
     27     const webrtc::DesktopFrame& frame) {
     28   CHECK(frame.data());
     29 
     30   base::Time encode_start_time = base::Time::Now();
     31 
     32   // Create a VideoPacket with common fields (e.g. DPI, rects, shape) set.
     33   scoped_ptr<VideoPacket> packet(helper_.CreateVideoPacket(frame));
     34   packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VERBATIM);
     35 
     36   // Calculate output size.
     37   size_t output_size = 0;
     38   for (webrtc::DesktopRegion::Iterator iter(frame.updated_region());
     39        !iter.IsAtEnd(); iter.Advance()) {
     40     const webrtc::DesktopRect& rect = iter.rect();
     41     output_size += rect.width() * rect.height() *
     42         webrtc::DesktopFrame::kBytesPerPixel;
     43   }
     44 
     45   uint8_t* out = GetPacketOutputBuffer(packet.get(), output_size);
     46   const int in_stride = frame.stride();
     47 
     48   // Encode pixel data for all changed rectangles into the packet.
     49   for (webrtc::DesktopRegion::Iterator iter(frame.updated_region());
     50        !iter.IsAtEnd(); iter.Advance()) {
     51     const webrtc::DesktopRect& rect = iter.rect();
     52     const int row_size = webrtc::DesktopFrame::kBytesPerPixel * rect.width();
     53     const uint8_t* in = frame.data() + rect.top() * in_stride +
     54                         rect.left() * webrtc::DesktopFrame::kBytesPerPixel;
     55     for (int y = rect.top(); y < rect.top() + rect.height(); ++y) {
     56       memcpy(out, in, row_size);
     57       out += row_size;
     58       in += in_stride;
     59     }
     60   }
     61 
     62   // Note the time taken to encode the pixel data.
     63   packet->set_encode_time_ms(
     64       (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
     65 
     66   return packet.Pass();
     67 }
     68 
     69 }  // namespace remoting
     70