diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-09 01:34:08 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-09 01:34:08 +0000 |
commit | 5bc7183a8a86f77d79187b545f4442c02b4b5da4 (patch) | |
tree | 5e8605f948381d4ee164ad3cf6b6c79fab37676f /remoting/base | |
parent | 5484722ea6f8b25aeca90ec2c7bd85b30143ee52 (diff) | |
download | chromium_src-5bc7183a8a86f77d79187b545f4442c02b4b5da4.zip chromium_src-5bc7183a8a86f77d79187b545f4442c02b4b5da4.tar.gz chromium_src-5bc7183a8a86f77d79187b545f4442c02b4b5da4.tar.bz2 |
Simplified frame rate control in the chromoting host.
Insted of keeping semi-fixed frame rate, now capturing rate is controlled
by how fast we can send data to the client. Capturing of frame n is
started only after frame n-2 is sent (while n-1 is being encoded). This
guarantees that we don't clog the video channel buffers, and that we start
capturing only if we know that the frame will not need to wait for too long
in the buffer.
TEST=None
BUG=None
Review URL: http://codereview.chromium.org/5634002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68688 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base')
-rw-r--r-- | remoting/base/codec_test.cc | 5 | ||||
-rw-r--r-- | remoting/base/decoder_row_based.cc | 34 | ||||
-rw-r--r-- | remoting/base/decoder_row_based.h | 3 | ||||
-rw-r--r-- | remoting/base/encoder_row_based.cc | 10 | ||||
-rw-r--r-- | remoting/base/encoder_row_based.h | 2 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.cc | 4 |
6 files changed, 47 insertions, 11 deletions
diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc index 0521b52d..0c59659 100644 --- a/remoting/base/codec_test.cc +++ b/remoting/base/codec_test.cc @@ -81,6 +81,11 @@ class EncoderMessageTester { state_ = kWaitingForBeginRect; ++end_rect_; } + + if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) { + // LAST_PARTITION must always be marked with LAST_PACKET. + EXPECT_TRUE((packet->flags() & VideoPacket::LAST_PACKET) != 0); + } } } diff --git a/remoting/base/decoder_row_based.cc b/remoting/base/decoder_row_based.cc index a657331..25e738f 100644 --- a/remoting/base/decoder_row_based.cc +++ b/remoting/base/decoder_row_based.cc @@ -46,10 +46,22 @@ void DecoderRowBased::Reset() { frame_ = NULL; decompressor_->Reset(); state_ = kUninitialized; + updated_rects_.clear(); } bool DecoderRowBased::IsReadyForData() { - return state_ == kReady || state_ == kProcessing || state_ == kDone; + switch (state_) { + case kUninitialized: + case kError: + return false; + case kReady: + case kProcessing: + case kPartitionDone: + case kDone: + return true; + } + NOTREACHED(); + return false; } void DecoderRowBased::Initialize(scoped_refptr<media::VideoFrame> frame) { @@ -119,14 +131,18 @@ Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) { } } - if (state_ == kDone) { + if (state_ == kPartitionDone || state_ == kDone) { if (row_y_ < clip_.height()) { state_ = kError; LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; return DECODE_ERROR; } + updated_rects_.push_back(clip_); decompressor_->Reset(); + } + + if (state_ == kDone) { return DECODE_DONE; } else { return DECODE_IN_PROGRESS; @@ -139,7 +155,7 @@ void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) { } if (packet->flags() & VideoPacket::FIRST_PACKET) { - if (state_ != kReady && state_ != kDone) { + if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { state_ = kError; LOG(WARNING) << "Received unexpected FIRST_PACKET."; return; @@ -165,6 +181,15 @@ void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) { LOG(WARNING) << "Received unexpected LAST_PACKET."; return; } + state_ = kPartitionDone; + } + + if (packet->flags() & VideoPacket::LAST_PARTITION) { + if (state_ != kPartitionDone) { + state_ = kError; + LOG(WARNING) << "Received unexpected LAST_PARTITION."; + return; + } state_ = kDone; } @@ -172,7 +197,8 @@ void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) { } void DecoderRowBased::GetUpdatedRects(UpdatedRects* rects) { - rects->push_back(clip_); + rects->swap(updated_rects_); + updated_rects_.clear(); } VideoPacketFormat::Encoding DecoderRowBased::Encoding() { diff --git a/remoting/base/decoder_row_based.h b/remoting/base/decoder_row_based.h index da05c05..05c2e3c 100644 --- a/remoting/base/decoder_row_based.h +++ b/remoting/base/decoder_row_based.h @@ -36,6 +36,7 @@ class DecoderRowBased : public Decoder { kUninitialized, kReady, kProcessing, + kPartitionDone, kDone, kError, }; @@ -70,6 +71,8 @@ class DecoderRowBased : public Decoder { // True if we should decode the image upside down. bool reverse_rows_; + UpdatedRects updated_rects_; + DISALLOW_COPY_AND_ASSIGN(DecoderRowBased); }; diff --git a/remoting/base/encoder_row_based.cc b/remoting/base/encoder_row_based.cc index 6a797b2..d9dcb10 100644 --- a/remoting/base/encoder_row_based.cc +++ b/remoting/base/encoder_row_based.cc @@ -65,17 +65,15 @@ void EncoderRowBased::Encode(scoped_refptr<CaptureData> capture_data, callback_.reset(data_available_callback); const InvalidRects& rects = capture_data->dirty_rects(); - int index = 0; - for (InvalidRects::const_iterator r = rects.begin(); - r != rects.end(); ++r, ++index) { - EncodeRect(*r, index); + for (InvalidRects::const_iterator r = rects.begin(); r != rects.end(); ++r) { + EncodeRect(*r, r == --rects.end()); } capture_data_ = NULL; callback_.reset(); } -void EncoderRowBased::EncodeRect(const gfx::Rect& rect, size_t rect_index) { +void EncoderRowBased::EncodeRect(const gfx::Rect& rect, bool last) { CHECK(capture_data_->data_planes().data[0]); const int strides = capture_data_->data_planes().strides[0]; const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); @@ -117,6 +115,8 @@ void EncoderRowBased::EncodeRect(const gfx::Rect& rect, size_t rect_index) { // We have reached the end of stream. if (!compress_again) { packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); + if (last) + packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION); DCHECK(row_pos == row_size); DCHECK(row_y == rect.height() - 1); } diff --git a/remoting/base/encoder_row_based.h b/remoting/base/encoder_row_based.h index 1dfd916..11ebd9a 100644 --- a/remoting/base/encoder_row_based.h +++ b/remoting/base/encoder_row_based.h @@ -41,7 +41,7 @@ class EncoderRowBased : public Encoder { int packet_size); // Encode a single dirty rect using compressor. - void EncodeRect(const gfx::Rect& rect, size_t rect_index); + void EncodeRect(const gfx::Rect& rect, bool last); // Marks a packet as the first in a series of rectangle updates. void PrepareUpdateStart(const gfx::Rect& rect, VideoPacket* packet); diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc index ea02add..6d07e54 100644 --- a/remoting/base/encoder_vp8.cc +++ b/remoting/base/encoder_vp8.cc @@ -189,6 +189,7 @@ void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data, switch (packet->kind) { case VPX_CODEC_CX_FRAME_PKT: got_data = true; + // TODO(sergeyu): Split each frame into multiple partitions. message->set_data(packet->data.frame.buf, packet->data.frame.sz); break; default: @@ -197,7 +198,8 @@ void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data, } message->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); - message->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET); + message->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET | + VideoPacket::LAST_PARTITION); data_available_callback->Run(message); delete data_available_callback; |