video_decoder_verbatim.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_decoder_verbatim.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace remoting {
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Both input and output data are assumed to be RGBA32.
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kBytesPerPixel = 4;
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)VideoDecoderVerbatim::VideoDecoderVerbatim() {}
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)VideoDecoderVerbatim::~VideoDecoderVerbatim() {}
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool VideoDecoderVerbatim::IsReadyForData() {
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoDecoderVerbatim::Initialize(const webrtc::DesktopSize& screen_size) {
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  updated_region_.Clear();
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  screen_buffer_.reset();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  screen_size_ = screen_size;
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Allocate the screen buffer, if necessary.
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!screen_size_.is_empty()) {
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    screen_buffer_.reset(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new uint8
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            [screen_size_.width() * screen_size_.height() * kBytesPerPixel]);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuVideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket(
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const VideoPacket* packet) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  webrtc::DesktopRegion region;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* in = packet->data().data();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int stride = kBytesPerPixel * screen_size_.width();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < packet->dirty_rects_size(); ++i) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Rect proto_rect = packet->dirty_rects(i);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    webrtc::DesktopRect rect =
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        webrtc::DesktopRect::MakeXYWH(proto_rect.x(), proto_rect.y(),
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      proto_rect.width(), proto_rect.height());
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    region.AddRect(rect);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!DoesRectContain(webrtc::DesktopRect::MakeSize(screen_size_), rect)) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Invalid packet received";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return DECODE_ERROR;
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rect_row_size = kBytesPerPixel * rect.width();
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    uint8_t* out = screen_buffer_.get() + rect.top() * stride +
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   rect.left() * kBytesPerPixel;
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (int y = rect.top(); y < rect.top() + rect.height(); ++y) {
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (in + rect_row_size > packet->data().data() + packet->data().size()) {
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        LOG(ERROR) << "Invalid packet received";
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return DECODE_ERROR;
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      memcpy(out, in, rect_row_size);
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      in += rect_row_size;
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      out += stride;
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (in != packet->data().data() + packet->data().size()) {
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Invalid packet received";
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return DECODE_ERROR;
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  updated_region_.AddRegion(region);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return DECODE_DONE;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return VideoPacketFormat::ENCODING_VERBATIM;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoDecoderVerbatim::Invalidate(const webrtc::DesktopSize& view_size,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const webrtc::DesktopRegion& region) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  updated_region_.AddRegion(region);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoDecoderVerbatim::RenderFrame(const webrtc::DesktopSize& view_size,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       const webrtc::DesktopRect& clip_area,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       uint8* image_buffer,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int image_stride,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       webrtc::DesktopRegion* output_region) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_region->Clear();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96  // TODO(alexeypa): scaling is not implemented.
97  webrtc::DesktopRect clip_rect = webrtc::DesktopRect::MakeSize(screen_size_);
98  clip_rect.IntersectWith(clip_area);
99  if (clip_rect.is_empty())
100    return;
101
102  int screen_stride = screen_size_.width() * kBytesPerPixel;
103
104  for (webrtc::DesktopRegion::Iterator i(updated_region_);
105       !i.IsAtEnd(); i.Advance()) {
106    webrtc::DesktopRect rect(i.rect());
107    rect.IntersectWith(clip_rect);
108    if (rect.is_empty())
109      continue;
110
111    CopyRGB32Rect(screen_buffer_.get(), screen_stride,
112                  clip_rect,
113                  image_buffer, image_stride,
114                  clip_area,
115                  rect);
116    output_region->AddRect(rect);
117  }
118
119  updated_region_.Clear();
120}
121
122const webrtc::DesktopRegion* VideoDecoderVerbatim::GetImageShape() {
123  return NULL;
124}
125
126}  // namespace remoting
127