Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/codec/video_decoder_verbatim.h" | 5 #include "remoting/codec/video_decoder_verbatim.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "remoting/base/util.h" | 8 #include "remoting/base/util.h" |
| 9 | 9 |
| 10 namespace remoting { | 10 namespace remoting { |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 // Both input and output data are assumed to be RGBA32. | 13 // Both input and output data are assumed to be RGBA32. |
| 14 const int kBytesPerPixel = 4; | 14 const int kBytesPerPixel = 4; |
| 15 } // namespace | 15 } // namespace |
| 16 | 16 |
| 17 VideoDecoderVerbatim::VideoDecoderVerbatim() | |
| 18 : screen_size_(SkISize::Make(0, 0)) {} | |
| 17 | 19 |
| 18 VideoDecoderVerbatim::VideoDecoderVerbatim() | 20 VideoDecoderVerbatim::~VideoDecoderVerbatim() {} |
| 19 : state_(kUninitialized), | |
| 20 clip_(SkIRect::MakeEmpty()), | |
| 21 row_pos_(0), | |
| 22 row_y_(0), | |
| 23 screen_size_(SkISize::Make(0, 0)) { | |
| 24 } | |
| 25 | |
| 26 VideoDecoderVerbatim::~VideoDecoderVerbatim() { | |
| 27 } | |
| 28 | 21 |
| 29 bool VideoDecoderVerbatim::IsReadyForData() { | 22 bool VideoDecoderVerbatim::IsReadyForData() { |
| 30 switch (state_) { | 23 return true; |
| 31 case kUninitialized: | |
| 32 case kError: | |
| 33 return false; | |
| 34 case kReady: | |
| 35 case kProcessing: | |
| 36 case kPartitionDone: | |
| 37 case kDone: | |
| 38 return true; | |
| 39 } | |
| 40 NOTREACHED(); | |
| 41 return false; | |
| 42 } | 24 } |
| 43 | 25 |
| 44 void VideoDecoderVerbatim::Initialize(const SkISize& screen_size) { | 26 void VideoDecoderVerbatim::Initialize(const SkISize& screen_size) { |
| 45 updated_region_.setEmpty(); | 27 updated_region_.setEmpty(); |
| 46 screen_buffer_.reset(); | 28 screen_buffer_.reset(); |
| 47 | 29 |
| 48 screen_size_ = screen_size; | 30 screen_size_ = screen_size; |
| 49 // Allocate the screen buffer, if necessary. | 31 // Allocate the screen buffer, if necessary. |
| 50 if (!screen_size_.isEmpty()) { | 32 if (!screen_size_.isEmpty()) { |
| 51 screen_buffer_.reset(new uint8[ | 33 screen_buffer_.reset( |
| 52 screen_size_.width() * screen_size_.height() * kBytesPerPixel]); | 34 new uint8 |
| 35 [screen_size_.width() * screen_size_.height() * kBytesPerPixel]); | |
| 53 } | 36 } |
| 54 | |
| 55 state_ = kReady; | |
| 56 } | 37 } |
| 57 | 38 |
| 58 VideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket( | 39 VideoDecoder::DecodeResult VideoDecoderVerbatim::DecodePacket( |
| 59 const VideoPacket* packet) { | 40 const VideoPacket* packet) { |
| 60 UpdateStateForPacket(packet); | 41 SkRegion region; |
| 61 | 42 for (int i = 0; i < packet->dirty_rects_size(); ++i) { |
| 62 if (state_ == kError) { | 43 Rect remoting_rect = packet->dirty_rects(i); |
| 63 return DECODE_ERROR; | 44 SkIRect rect = |
| 45 SkIRect::MakeXYWH(remoting_rect.x(), remoting_rect.y(), | |
| 46 remoting_rect.width(), remoting_rect.height()); | |
| 47 region.op(rect, SkRegion::kUnion_Op); | |
| 64 } | 48 } |
| 65 | 49 |
| 66 const uint8* in = reinterpret_cast<const uint8*>(packet->data().data()); | 50 updated_region_.op(region, SkRegion::kUnion_Op); |
| 67 const int in_size = packet->data().size(); | |
| 68 const int row_size = clip_.width() * kBytesPerPixel; | |
| 69 | 51 |
| 70 int out_stride = screen_size_.width() * kBytesPerPixel; | 52 const char* in = packet->data().data(); |
| 71 uint8* out = screen_buffer_.get() + out_stride * (clip_.top() + row_y_) + | 53 int stride = kBytesPerPixel * screen_size_.width(); |
|
Wez
2013/09/12 14:20:15
nit: buffer_row_bytes or buffer_stride?
Sergey Ulanov
2013/09/12 19:18:45
They are the same for the frames generated by this
| |
| 72 kBytesPerPixel * clip_.left(); | 54 for (SkRegion::Iterator iter(region); !iter.done(); iter.next()) { |
| 73 | 55 const SkIRect& rect = iter.rect(); |
|
Wez
2013/09/12 14:20:15
Need to check that |rect| is contained within |scr
Sergey Ulanov
2013/09/12 19:18:45
Done.
| |
| 74 // Consume all the data in the message. | 56 int row_size = kBytesPerPixel * rect.width(); |
|
Wez
2013/09/12 14:20:15
nit: row_bytes or source_stride or packet[_data]_s
Sergey Ulanov
2013/09/12 19:18:45
size of a single raw in the rect being decoded.
| |
| 75 int used = 0; | 57 uint8_t* out = screen_buffer_.get() + rect.top() * stride + |
| 76 while (used < in_size) { | 58 rect.left() * kBytesPerPixel; |
| 77 if (row_y_ >= clip_.height()) { | 59 for (int y = rect.y(); y < rect.y() + rect.height(); ++y) { |
| 78 state_ = kError; | 60 memcpy(out, in, row_size); |
| 79 LOG(WARNING) << "Too much data is received for the given rectangle."; | 61 in += row_size; |
| 80 return DECODE_ERROR; | 62 if (in > packet->data().data() + packet->data().size()) { |
| 81 } | 63 LOG(ERROR) << "Invalid packet received"; |
| 82 | 64 return DECODE_ERROR; |
| 83 int bytes_to_copy = std::min(in_size - used, row_size - row_pos_); | 65 } |
| 84 memcpy(out + row_pos_, in + used, bytes_to_copy); | 66 out += stride; |
| 85 | |
| 86 used += bytes_to_copy; | |
| 87 row_pos_ += bytes_to_copy; | |
| 88 | |
| 89 // If this row is completely filled then move onto the next row. | |
| 90 if (row_pos_ == row_size) { | |
| 91 ++row_y_; | |
| 92 row_pos_ = 0; | |
| 93 out += out_stride; | |
| 94 } | 67 } |
| 95 } | 68 } |
| 96 | 69 |
| 97 if (state_ == kPartitionDone || state_ == kDone) { | 70 return DECODE_DONE; |
| 98 if (row_y_ < clip_.height()) { | |
| 99 state_ = kError; | |
| 100 LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; | |
| 101 return DECODE_ERROR; | |
| 102 } | |
| 103 | |
| 104 updated_region_.op(clip_, SkRegion::kUnion_Op); | |
| 105 } | |
| 106 | |
| 107 if (state_ == kDone) { | |
| 108 return DECODE_DONE; | |
| 109 } else { | |
| 110 return DECODE_IN_PROGRESS; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void VideoDecoderVerbatim::UpdateStateForPacket(const VideoPacket* packet) { | |
| 115 if (state_ == kError) { | |
| 116 return; | |
| 117 } | |
| 118 | |
| 119 if (packet->flags() & VideoPacket::FIRST_PACKET) { | |
| 120 if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { | |
| 121 state_ = kError; | |
| 122 LOG(WARNING) << "Received unexpected FIRST_PACKET."; | |
| 123 return; | |
| 124 } | |
| 125 | |
| 126 // Reset the buffer location status variables on the first packet. | |
| 127 clip_.setXYWH(packet->format().x(), packet->format().y(), | |
| 128 packet->format().width(), packet->format().height()); | |
| 129 if (!SkIRect::MakeSize(screen_size_).contains(clip_)) { | |
| 130 state_ = kError; | |
| 131 LOG(WARNING) << "Invalid clipping area received."; | |
| 132 return; | |
| 133 } | |
| 134 | |
| 135 state_ = kProcessing; | |
| 136 row_pos_ = 0; | |
| 137 row_y_ = 0; | |
| 138 } | |
| 139 | |
| 140 if (state_ != kProcessing) { | |
| 141 state_ = kError; | |
| 142 LOG(WARNING) << "Received unexpected packet."; | |
| 143 return; | |
| 144 } | |
| 145 | |
| 146 if (packet->flags() & VideoPacket::LAST_PACKET) { | |
| 147 if (state_ != kProcessing) { | |
| 148 state_ = kError; | |
| 149 LOG(WARNING) << "Received unexpected LAST_PACKET."; | |
| 150 return; | |
| 151 } | |
| 152 state_ = kPartitionDone; | |
| 153 } | |
| 154 | |
| 155 if (packet->flags() & VideoPacket::LAST_PARTITION) { | |
| 156 if (state_ != kPartitionDone) { | |
| 157 state_ = kError; | |
| 158 LOG(WARNING) << "Received unexpected LAST_PARTITION."; | |
| 159 return; | |
| 160 } | |
| 161 state_ = kDone; | |
| 162 } | |
| 163 | |
| 164 return; | |
| 165 } | 71 } |
| 166 | 72 |
| 167 VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() { | 73 VideoPacketFormat::Encoding VideoDecoderVerbatim::Encoding() { |
| 168 return VideoPacketFormat::ENCODING_VERBATIM; | 74 return VideoPacketFormat::ENCODING_VERBATIM; |
| 169 } | 75 } |
| 170 | 76 |
| 171 void VideoDecoderVerbatim::Invalidate(const SkISize& view_size, | 77 void VideoDecoderVerbatim::Invalidate(const SkISize& view_size, |
| 172 const SkRegion& region) { | 78 const SkRegion& region) { |
| 173 updated_region_.op(region, SkRegion::kUnion_Op); | 79 updated_region_.op(region, SkRegion::kUnion_Op); |
| 174 } | 80 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 201 } | 107 } |
| 202 | 108 |
| 203 updated_region_.setEmpty(); | 109 updated_region_.setEmpty(); |
| 204 } | 110 } |
| 205 | 111 |
| 206 const SkRegion* VideoDecoderVerbatim::GetImageShape() { | 112 const SkRegion* VideoDecoderVerbatim::GetImageShape() { |
| 207 return NULL; | 113 return NULL; |
| 208 } | 114 } |
| 209 | 115 |
| 210 } // namespace remoting | 116 } // namespace remoting |
| OLD | NEW |