Index: remoting/protocol/host_video_dispatcher.cc |
diff --git a/remoting/protocol/host_video_dispatcher.cc b/remoting/protocol/host_video_dispatcher.cc |
index b9a12c0294f28ac8e95d65ca52c8e6c000e8334f..95778e13eeb90cc8537d80cd7641db6b62c14edd 100644 |
--- a/remoting/protocol/host_video_dispatcher.cc |
+++ b/remoting/protocol/host_video_dispatcher.cc |
@@ -5,24 +5,84 @@ |
#include "remoting/protocol/host_video_dispatcher.h" |
#include "base/bind.h" |
+#include "base/callback_helpers.h" |
#include "net/socket/stream_socket.h" |
#include "remoting/base/constants.h" |
-#include "remoting/proto/video.pb.h" |
+#include "remoting/protocol/errors.h" |
#include "remoting/protocol/message_serialization.h" |
namespace remoting { |
namespace protocol { |
+HostVideoDispatcher::PendingFrame::PendingFrame( |
+ int frame_id, |
+ const ProgressCallback& progress_callback) |
+ : frame_id(frame_id), progress_callback(progress_callback) { |
+} |
+ |
HostVideoDispatcher::HostVideoDispatcher() |
- : ChannelDispatcherBase(kVideoChannelName) { |
+ : ChannelDispatcherBase(kVideoChannelName), |
+ frame_id_(0), |
+ parser_( |
+ base::Bind(&HostVideoDispatcher::OnVideoAck, base::Unretained(this)), |
+ reader()) { |
} |
HostVideoDispatcher::~HostVideoDispatcher() { |
} |
-void HostVideoDispatcher::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
- const base::Closure& done) { |
- writer()->Write(SerializeAndFrameMessage(*packet), done); |
+void HostVideoDispatcher::ProcessVideoPacket( |
+ scoped_ptr<VideoPacket> packet, |
+ const ProgressCallback& progress_callback) { |
+ if (SupportsAcks()) { |
+ packet->set_frame_id(frame_id_); |
+ pending_frames_.push_back(PendingFrame(frame_id_, progress_callback)); |
+ frame_id_++; |
+ } |
+ |
+ writer()->Write( |
+ SerializeAndFrameMessage(*packet), |
+ base::Bind(&HostVideoDispatcher::OnPacketSent, base::Unretained(this), |
+ progress_callback)); |
+} |
+ |
+bool HostVideoDispatcher::SupportsAcks() { |
+ return channel_config().version > kVideoStreamVersionNoAck; |
+} |
+ |
+void HostVideoDispatcher::OnPacketSent( |
+ const ProgressCallback& progress_callback) { |
+ progress_callback.Run(PacketProgress::SENT); |
+ |
+ // For older clients that don't send explicit video Ack message call notify |
+ // DONE state as soon as the frame is pushed to the channel. |
+ if (!SupportsAcks()) |
+ progress_callback.Run(PacketProgress::DONE); |
+} |
+ |
+void HostVideoDispatcher::OnVideoAck(scoped_ptr<VideoAck> ack, |
+ const base::Closure& done) { |
+ base::ScopedClosureRunner done_runner(done); |
+ |
+ if (!SupportsAcks()) { |
+ LOG(ERROR) << "Unexpected VideoAck message received."; |
+ return; |
+ } |
+ |
+ if (pending_frames_.empty() || |
+ pending_frames_.front().frame_id != ack->frame_id()) { |
+ NotifyError(INCOMPATIBLE_PROTOCOL); |
+ return; |
+ } |
+ |
+ // TODO(sergeyu): Currently the latency information in |ack| is ignored. |
+ // Expose it from this class so that CaptureScheduler can utilize it somehow. |
+ // See crbug.com/453177 . |
+ |
+ ProgressCallback progress_callback = |
+ pending_frames_.front().progress_callback; |
+ pending_frames_.pop_front(); |
+ progress_callback.Run(PacketProgress::DONE); |
} |
} // namespace protocol |