summaryrefslogtreecommitdiffstats
path: root/remoting/client/rectangle_update_decoder.cc
diff options
context:
space:
mode:
authorkxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-24 21:55:06 +0000
committerkxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-24 21:55:06 +0000
commit0cc246139d02e266ce81f6c8895f295ccf1c5438 (patch)
treebe4d09c200d210d8b8b00045c19dff8dcab31f77 /remoting/client/rectangle_update_decoder.cc
parente28bcda6365ef544a123fc91d22420a775886cde (diff)
downloadchromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.zip
chromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.tar.gz
chromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.tar.bz2
Moved video stub implementation to RectangleUpdateDecoder.
Review URL: https://chromiumcodereview.appspot.com/10867039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@153305 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/client/rectangle_update_decoder.cc')
-rw-r--r--remoting/client/rectangle_update_decoder.cc154
1 files changed, 135 insertions, 19 deletions
diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc
index 0fb253b..c7a1404 100644
--- a/remoting/client/rectangle_update_decoder.cc
+++ b/remoting/client/rectangle_update_decoder.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
@@ -24,16 +23,30 @@ using remoting::protocol::SessionConfig;
namespace remoting {
+RectangleUpdateDecoder::QueuedVideoPacket::QueuedVideoPacket(
+ scoped_ptr<VideoPacket> packet,
+ const base::Closure& done)
+ : packet(packet.release()),
+ done(done) {
+}
+
+RectangleUpdateDecoder::QueuedVideoPacket::~QueuedVideoPacket() {
+}
+
RectangleUpdateDecoder::RectangleUpdateDecoder(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner,
scoped_refptr<FrameConsumerProxy> consumer)
- : task_runner_(task_runner),
+ : main_task_runner_(main_task_runner),
+ decode_task_runner_(decode_task_runner),
consumer_(consumer),
source_size_(SkISize::Make(0, 0)),
source_dpi_(SkIPoint::Make(0, 0)),
view_size_(SkISize::Make(0, 0)),
clip_area_(SkIRect::MakeEmpty()),
- paint_scheduled_(false) {
+ paint_scheduled_(false),
+ packet_being_processed_(false),
+ latest_sequence_number_(0) {
}
RectangleUpdateDecoder::~RectangleUpdateDecoder() {
@@ -55,12 +68,7 @@ void RectangleUpdateDecoder::Initialize(const SessionConfig& config) {
void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet,
const base::Closure& done) {
- if (!task_runner_->BelongsToCurrentThread()) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::DecodePacket,
- this, base::Passed(&packet), done));
- return;
- }
+ DCHECK(decode_task_runner_->BelongsToCurrentThread());
base::ScopedClosureRunner done_runner(done);
bool decoder_needs_reset = false;
@@ -109,7 +117,7 @@ void RectangleUpdateDecoder::SchedulePaint() {
if (paint_scheduled_)
return;
paint_scheduled_ = true;
- task_runner_->PostTask(
+ decode_task_runner_->PostTask(
FROM_HERE, base::Bind(&RectangleUpdateDecoder::DoPaint, this));
}
@@ -141,8 +149,8 @@ void RectangleUpdateDecoder::DoPaint() {
}
void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) {
- if (!task_runner_->BelongsToCurrentThread()) {
- task_runner_->PostTask(
+ if (!decode_task_runner_->BelongsToCurrentThread()) {
+ decode_task_runner_->PostTask(
FROM_HERE, base::Bind(&RectangleUpdateDecoder::RequestReturnBuffers,
this, done));
return;
@@ -158,8 +166,8 @@ void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) {
}
void RectangleUpdateDecoder::DrawBuffer(pp::ImageData* buffer) {
- if (!task_runner_->BelongsToCurrentThread()) {
- task_runner_->PostTask(
+ if (!decode_task_runner_->BelongsToCurrentThread()) {
+ decode_task_runner_->PostTask(
FROM_HERE, base::Bind(&RectangleUpdateDecoder::DrawBuffer,
this, buffer));
return;
@@ -173,8 +181,8 @@ void RectangleUpdateDecoder::DrawBuffer(pp::ImageData* buffer) {
}
void RectangleUpdateDecoder::InvalidateRegion(const SkRegion& region) {
- if (!task_runner_->BelongsToCurrentThread()) {
- task_runner_->PostTask(
+ if (!decode_task_runner_->BelongsToCurrentThread()) {
+ decode_task_runner_->PostTask(
FROM_HERE, base::Bind(&RectangleUpdateDecoder::InvalidateRegion,
this, region));
return;
@@ -188,8 +196,8 @@ void RectangleUpdateDecoder::InvalidateRegion(const SkRegion& region) {
void RectangleUpdateDecoder::SetOutputSizeAndClip(const SkISize& view_size,
const SkIRect& clip_area) {
- if (!task_runner_->BelongsToCurrentThread()) {
- task_runner_->PostTask(
+ if (!decode_task_runner_->BelongsToCurrentThread()) {
+ decode_task_runner_->PostTask(
FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSizeAndClip,
this, view_size, clip_area));
return;
@@ -225,4 +233,112 @@ void RectangleUpdateDecoder::SetOutputSizeAndClip(const SkISize& view_size,
}
}
+void RectangleUpdateDecoder::ProcessVideoPacket(scoped_ptr<VideoPacket> packet,
+ const base::Closure& done) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // If the video packet is empty then drop it. Empty packets are used to
+ // maintain activity on the network.
+ if (!packet->has_data() || packet->data().size() == 0) {
+ done.Run();
+ return;
+ }
+
+ // Add one frame to the counter.
+ stats_.video_frame_rate()->Record(1);
+
+ // Record other statistics received from host.
+ stats_.video_bandwidth()->Record(packet->data().size());
+ if (packet->has_capture_time_ms())
+ stats_.video_capture_ms()->Record(packet->capture_time_ms());
+ if (packet->has_encode_time_ms())
+ stats_.video_encode_ms()->Record(packet->encode_time_ms());
+ if (packet->has_client_sequence_number() &&
+ packet->client_sequence_number() > latest_sequence_number_) {
+ latest_sequence_number_ = packet->client_sequence_number();
+ base::TimeDelta round_trip_latency =
+ base::Time::Now() -
+ base::Time::FromInternalValue(packet->client_sequence_number());
+ stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds());
+ }
+
+ received_packets_.push_back(QueuedVideoPacket(packet.Pass(), done));
+ if (!packet_being_processed_)
+ ProcessNextPacket();
+}
+
+int RectangleUpdateDecoder::GetPendingVideoPackets() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return received_packets_.size();
+}
+
+void RectangleUpdateDecoder::DropAllPackets() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ while(!received_packets_.empty()) {
+ delete received_packets_.front().packet;
+ received_packets_.front().done.Run();
+ received_packets_.pop_front();
+ }
+}
+
+void RectangleUpdateDecoder::ProcessNextPacket() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ CHECK(!packet_being_processed_);
+
+ if (received_packets_.empty()) {
+ // Nothing to do!
+ return;
+ }
+
+ scoped_ptr<VideoPacket> packet(received_packets_.front().packet);
+ received_packets_.front().packet = NULL;
+ packet_being_processed_ = true;
+
+ // Measure the latency between the last packet being received and presented.
+ bool last_packet = (packet->flags() & VideoPacket::LAST_PACKET) != 0;
+ base::Time decode_start;
+ if (last_packet)
+ decode_start = base::Time::Now();
+
+ base::Closure callback = base::Bind(&RectangleUpdateDecoder::OnPacketDone,
+ this,
+ last_packet,
+ decode_start);
+
+ decode_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &RectangleUpdateDecoder::DecodePacket, this,
+ base::Passed(&packet), callback));
+}
+
+void RectangleUpdateDecoder::OnPacketDone(bool last_packet,
+ base::Time decode_start) {
+ if (!main_task_runner_->BelongsToCurrentThread()) {
+ main_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &RectangleUpdateDecoder::OnPacketDone, this,
+ last_packet, decode_start));
+ return;
+ }
+
+ // Record the latency between the final packet being received and
+ // presented.
+ if (last_packet) {
+ stats_.video_decode_ms()->Record(
+ (base::Time::Now() - decode_start).InMilliseconds());
+ }
+
+ received_packets_.front().done.Run();
+ received_packets_.pop_front();
+
+ packet_being_processed_ = false;
+
+ // Process the next video packet.
+ ProcessNextPacket();
+}
+
+ChromotingStats* RectangleUpdateDecoder::GetStats() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return &stats_;
+}
+
} // namespace remoting