Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(874)

Side by Side Diff: remoting/client/rectangle_update_decoder.cc

Issue 4476003: Add VideoPacket struct for video packets. Refactor Decode interface to use it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/client/rectangle_update_decoder.h ('k') | remoting/host/capturer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/client/rectangle_update_decoder.h" 5 #include "remoting/client/rectangle_update_decoder.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "media/base/callback.h" 9 #include "media/base/callback.h"
10 #include "remoting/base/decoder.h" 10 #include "remoting/base/decoder.h"
11 #include "remoting/base/decoder_row_based.h" 11 #include "remoting/base/decoder_row_based.h"
12 #include "remoting/base/decoder_vp8.h" 12 #include "remoting/base/decoder_vp8.h"
13 #include "remoting/base/tracer.h" 13 #include "remoting/base/tracer.h"
14 #include "remoting/base/util.h" 14 #include "remoting/base/util.h"
15 #include "remoting/client/frame_consumer.h" 15 #include "remoting/client/frame_consumer.h"
16 #include "remoting/protocol/session_config.h"
16 17
17 using media::AutoTaskRunner; 18 using media::AutoTaskRunner;
19 using remoting::protocol::ChannelConfig;
20 using remoting::protocol::SessionConfig;
18 21
19 namespace remoting { 22 namespace remoting {
20 23
21 namespace { 24 namespace {
22 25
23 class PartialFrameCleanup : public Task { 26 class PartialFrameCleanup : public Task {
24 public: 27 public:
25 PartialFrameCleanup(media::VideoFrame* frame, UpdatedRects* rects) 28 PartialFrameCleanup(media::VideoFrame* frame, UpdatedRects* rects)
26 : frame_(frame), rects_(rects) { 29 : frame_(frame), rects_(rects) {
27 } 30 }
(...skipping 12 matching lines...) Expand all
40 43
41 RectangleUpdateDecoder::RectangleUpdateDecoder(MessageLoop* message_loop, 44 RectangleUpdateDecoder::RectangleUpdateDecoder(MessageLoop* message_loop,
42 FrameConsumer* consumer) 45 FrameConsumer* consumer)
43 : message_loop_(message_loop), 46 : message_loop_(message_loop),
44 consumer_(consumer) { 47 consumer_(consumer) {
45 } 48 }
46 49
47 RectangleUpdateDecoder::~RectangleUpdateDecoder() { 50 RectangleUpdateDecoder::~RectangleUpdateDecoder() {
48 } 51 }
49 52
50 void RectangleUpdateDecoder::DecodePacket(const VideoPacket& packet, 53 void RectangleUpdateDecoder::Initialize(const SessionConfig* config) {
54 screen_size_ = gfx::Size(config->initial_resolution().width,
55 config->initial_resolution().height);
56
57 // Initialize decoder based on the selected codec.
58 ChannelConfig::Codec codec = config->video_config().codec;
59 if (codec == ChannelConfig::CODEC_VERBATIM) {
60 TraceContext::tracer()->PrintString("Creating Verbatim decoder.");
61 decoder_.reset(DecoderRowBased::CreateVerbatimDecoder());
62 } else if (codec == ChannelConfig::CODEC_ZIP) {
63 TraceContext::tracer()->PrintString("Creating Zlib decoder");
64 decoder_.reset(DecoderRowBased::CreateZlibDecoder());
65 // TODO(sergeyu): Enable VP8 on ARM builds.
66 #if !defined(ARCH_CPU_ARM_FAMILY)
67 } else if (codec == ChannelConfig::CODEC_VP8) {
68 TraceContext::tracer()->PrintString("Creating VP8 decoder");
69 decoder_.reset(new DecoderVp8());
70 #endif
71 } else {
72 NOTREACHED() << "Invalid Encoding found: " << codec;
73 }
74 }
75
76 void RectangleUpdateDecoder::DecodePacket(const VideoPacket* packet,
51 Task* done) { 77 Task* done) {
52 if (message_loop_ != MessageLoop::current()) { 78 if (message_loop_ != MessageLoop::current()) {
53 message_loop_->PostTask( 79 message_loop_->PostTask(
54 FROM_HERE, 80 FROM_HERE,
55 NewTracedMethod(this, 81 NewTracedMethod(this,
56 &RectangleUpdateDecoder::DecodePacket, packet, 82 &RectangleUpdateDecoder::DecodePacket, packet,
57 done)); 83 done));
58 return; 84 return;
59 } 85 }
60 AutoTaskRunner done_runner(done); 86 AutoTaskRunner done_runner(done);
61 87
62 TraceContext::tracer()->PrintString("Decode Packet called."); 88 TraceContext::tracer()->PrintString("Decode Packet called.");
63 89
64 if (!IsValidPacket(packet)) { 90 if (!decoder_->IsReadyForData()) {
65 LOG(ERROR) << "Received invalid packet."; 91 InitializeDecoder(
66 return; 92 NewTracedMethod(this,
67 } 93 &RectangleUpdateDecoder::ProcessPacketData,
68 94 packet, done_runner.release()));
69 Task* process_packet_data =
70 NewTracedMethod(this,
71 &RectangleUpdateDecoder::ProcessPacketData,
72 packet, done_runner.release());
73
74 if (packet.flags() | VideoPacket::FIRST_PACKET) {
75 const VideoPacketFormat& format = packet.format();
76
77 InitializeDecoder(format, process_packet_data);
78 } else { 95 } else {
79 process_packet_data->Run(); 96 ProcessPacketData(packet, done_runner.release());
80 delete process_packet_data;
81 } 97 }
82 } 98 }
83 99
84 void RectangleUpdateDecoder::ProcessPacketData( 100 void RectangleUpdateDecoder::ProcessPacketData(
85 const VideoPacket& packet, Task* done) { 101 const VideoPacket* packet, Task* done) {
86 AutoTaskRunner done_runner(done); 102 AutoTaskRunner done_runner(done);
87 103
88 if (!decoder_->IsReadyForData()) { 104 if (!decoder_->IsReadyForData()) {
89 // TODO(ajwong): This whole thing should move into an invalid state. 105 // TODO(ajwong): This whole thing should move into an invalid state.
90 LOG(ERROR) << "Decoder is unable to process data. Dropping packet."; 106 LOG(ERROR) << "Decoder is unable to process data. Dropping packet.";
91 return; 107 return;
92 } 108 }
93 109
94 TraceContext::tracer()->PrintString("Executing Decode."); 110 TraceContext::tracer()->PrintString("Executing Decode.");
95 decoder_->DecodeBytes(packet.data());
96 111
97 if (packet.flags() | VideoPacket::LAST_PACKET) { 112 Decoder::DecodeResult result = decoder_->DecodePacket(packet);
98 decoder_->Reset();
99 113
114 if (result == Decoder::DECODE_DONE) {
100 UpdatedRects* rects = new UpdatedRects(); 115 UpdatedRects* rects = new UpdatedRects();
101 116 decoder_->GetUpdatedRects(rects);
102 // Empty out the list of current updated rects so the decoder can keep
103 // writing new ones while these are processed.
104 rects->swap(updated_rects_);
105
106 consumer_->OnPartialFrameOutput(frame_, rects, 117 consumer_->OnPartialFrameOutput(frame_, rects,
107 new PartialFrameCleanup(frame_, rects)); 118 new PartialFrameCleanup(frame_, rects));
108 } 119 }
109 } 120 }
110 121
111 // static 122 void RectangleUpdateDecoder::InitializeDecoder(Task* done) {
112 bool RectangleUpdateDecoder::IsValidPacket(const VideoPacket& packet) {
113 if (!packet.IsInitialized()) {
114 LOG(WARNING) << "Protobuf consistency checks fail.";
115 return false;
116 }
117
118 // First packet must have a format.
119 if (packet.flags() | VideoPacket::FIRST_PACKET) {
120 if (!packet.has_format()) {
121 LOG(WARNING) << "First packet must have format.";
122 return false;
123 }
124
125 // TODO(ajwong): Verify that we don't need to whitelist encodings.
126 const VideoPacketFormat& format = packet.format();
127 if (!format.has_encoding() ||
128 format.encoding() == VideoPacketFormat::ENCODING_INVALID) {
129 LOG(WARNING) << "Invalid encoding specified.";
130 return false;
131 }
132 }
133
134 // We shouldn't generate null packets.
135 if (!packet.has_data()) {
136 LOG(WARNING) << "Packet w/o data received.";
137 return false;
138 }
139
140 return true;
141 }
142
143 void RectangleUpdateDecoder::InitializeDecoder(const VideoPacketFormat& format,
144 Task* done) {
145 if (message_loop_ != MessageLoop::current()) { 123 if (message_loop_ != MessageLoop::current()) {
146 message_loop_->PostTask( 124 message_loop_->PostTask(
147 FROM_HERE, 125 FROM_HERE,
148 NewTracedMethod(this, 126 NewTracedMethod(this,
149 &RectangleUpdateDecoder::InitializeDecoder, 127 &RectangleUpdateDecoder::InitializeDecoder, done));
150 format, done));
151 return; 128 return;
152 } 129 }
153 AutoTaskRunner done_runner(done); 130 AutoTaskRunner done_runner(done);
154 131
155 // Check if we need to request a new frame. 132 // Check if we need to request a new frame.
156 if (!frame_ || 133 if (!frame_ ||
157 frame_->width() < static_cast<size_t>(format.width()) || 134 frame_->width() != static_cast<size_t>(screen_size_.width()) ||
158 frame_->height() < static_cast<size_t>(format.height())) { 135 frame_->height() != static_cast<size_t>(screen_size_.height())) {
159 if (frame_) { 136 if (frame_) {
160 TraceContext::tracer()->PrintString("Releasing old frame."); 137 TraceContext::tracer()->PrintString("Releasing old frame.");
161 consumer_->ReleaseFrame(frame_); 138 consumer_->ReleaseFrame(frame_);
162 frame_ = NULL; 139 frame_ = NULL;
163 } 140 }
164 TraceContext::tracer()->PrintString("Requesting new frame."); 141 TraceContext::tracer()->PrintString("Requesting new frame.");
165 consumer_->AllocateFrame(media::VideoFrame::RGB32, 142 consumer_->AllocateFrame(media::VideoFrame::RGB32,
166 format.width(), format.height(), 143 screen_size_.width(), screen_size_.height(),
167 base::TimeDelta(), base::TimeDelta(), 144 base::TimeDelta(), base::TimeDelta(),
168 &frame_, 145 &frame_,
169 NewTracedMethod( 146 NewTracedMethod(
170 this, 147 this,
171 &RectangleUpdateDecoder::InitializeDecoder, 148 &RectangleUpdateDecoder::InitializeDecoder,
172 format,
173 done_runner.release())); 149 done_runner.release()));
174 return; 150 return;
175 } 151 }
176 152
177 // TODO(ajwong): We need to handle the allocator failing to create a frame 153 // TODO(ajwong): We need to handle the allocator failing to create a frame
178 // and properly disable this class. 154 // and properly disable this class.
179 CHECK(frame_); 155 CHECK(frame_);
180 156
181 if (decoder_.get()) { 157 decoder_->Reset();
182 // TODO(ajwong): We need to handle changing decoders midstream correctly 158 decoder_->Initialize(frame_);
183 // since someone may feed us a corrupt stream, or manually create a
184 // stream that changes decoders. At the very leask, we should not
185 // crash the process.
186 //
187 // For now though, assume that only one encoding is used throughout.
188 //
189 // Note, this may be as simple as just deleting the current decoder.
190 // However, we need to verify the flushing semantics of the decoder first.
191 CHECK(decoder_->Encoding() == format.encoding());
192 } else {
193 // Initialize a new decoder based on this message encoding.
194 if (format.encoding() == VideoPacketFormat::ENCODING_VERBATIM) {
195 TraceContext::tracer()->PrintString("Creating Verbatim decoder.");
196 decoder_.reset(DecoderRowBased::CreateVerbatimDecoder());
197 } else if (format.encoding() == VideoPacketFormat::ENCODING_ZLIB) {
198 TraceContext::tracer()->PrintString("Creating Zlib decoder");
199 decoder_.reset(DecoderRowBased::CreateZlibDecoder());
200 // TODO(sergeyu): Enable VP8 on ARM builds.
201 #if !defined(ARCH_CPU_ARM_FAMILY)
202 } else if (format.encoding() == VideoPacketFormat::ENCODING_VP8) {
203 TraceContext::tracer()->PrintString("Creating VP8 decoder");
204 decoder_.reset(new DecoderVp8());
205 #endif
206 } else {
207 NOTREACHED() << "Invalid Encoding found: " << format.encoding();
208 }
209 }
210 159
211 // TODO(ajwong): This can happen in the face of corrupt input data. Figure
212 // out the right behavior and make this more resilient.
213 CHECK(updated_rects_.empty());
214
215 gfx::Rect rectangle_size(format.x(), format.y(),
216 format.width(), format.height());
217 updated_rects_.push_back(rectangle_size);
218 decoder_->Initialize(frame_, rectangle_size,
219 GetBytesPerPixel(format.pixel_format()));
220 TraceContext::tracer()->PrintString("Decoder is Initialized"); 160 TraceContext::tracer()->PrintString("Decoder is Initialized");
221 } 161 }
222 162
223 } // namespace remoting 163 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/rectangle_update_decoder.h ('k') | remoting/host/capturer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698