Index: remoting/client/rectangle_update_decoder.cc |
diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc |
index af123e85b84941ef09de9a68831e403caa13d0e0..3ff2be15815e7240403e698e6e93f6b12778c9fb 100644 |
--- a/remoting/client/rectangle_update_decoder.cc |
+++ b/remoting/client/rectangle_update_decoder.cc |
@@ -16,6 +16,7 @@ |
#include "remoting/codec/video_decoder_vp8.h" |
#include "remoting/client/frame_consumer.h" |
#include "remoting/protocol/session_config.h" |
+#include "third_party/libyuv/include/libyuv/convert_argb.h" |
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
using base::Passed; |
@@ -24,6 +25,55 @@ using remoting::protocol::SessionConfig; |
namespace remoting { |
+// This class wraps a VideoDecoder and byte-swaps the pixels for compatibility |
+// with the android.graphics.Bitmap class. |
+// TODO(lambroslambrou): Refactor so that the VideoDecoder produces data |
+// in the right byte-order, instead of swapping it here. |
+class RgbToBgrVideoDecoderFilter : public VideoDecoder { |
+ public: |
+ RgbToBgrVideoDecoderFilter(scoped_ptr<VideoDecoder> parent) |
+ : parent_(parent.Pass()) { |
+ } |
+ |
+ virtual void Initialize(const webrtc::DesktopSize& screen_size) OVERRIDE { |
+ parent_->Initialize(screen_size); |
+ } |
+ |
+ virtual bool DecodePacket(const VideoPacket& packet) OVERRIDE { |
+ return parent_->DecodePacket(packet); |
+ } |
+ |
+ virtual void Invalidate(const webrtc::DesktopSize& view_size, |
+ const webrtc::DesktopRegion& region) OVERRIDE { |
+ return parent_->Invalidate(view_size, region); |
+ } |
+ |
+ virtual void RenderFrame(const webrtc::DesktopSize& view_size, |
+ const webrtc::DesktopRect& clip_area, |
+ uint8* image_buffer, |
+ int image_stride, |
+ webrtc::DesktopRegion* output_region) OVERRIDE { |
+ parent_->RenderFrame(view_size, clip_area, image_buffer, image_stride, |
+ output_region); |
+ |
+ for (webrtc::DesktopRegion::Iterator i(*output_region); !i.IsAtEnd(); |
+ i.Advance()) { |
+ webrtc::DesktopRect rect = i.rect(); |
+ uint8* pixels = image_buffer + (rect.top() * image_stride) + |
+ (rect.left() * kBytesPerPixel); |
+ libyuv::ABGRToARGB(pixels, image_stride, pixels, image_stride, |
+ rect.width(), rect.height()); |
+ } |
+ } |
+ |
+ virtual const webrtc::DesktopRegion* GetImageShape() OVERRIDE { |
+ return parent_->GetImageShape(); |
+ } |
+ |
+ private: |
+ scoped_ptr<VideoDecoder> parent_; |
+}; |
+ |
RectangleUpdateDecoder::RectangleUpdateDecoder( |
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
@@ -39,6 +89,13 @@ RectangleUpdateDecoder::~RectangleUpdateDecoder() { |
} |
void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
+ if (!decode_task_runner_->BelongsToCurrentThread()) { |
+ decode_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::Initialize, this, |
+ config)); |
+ return; |
+ } |
+ |
// Initialize decoder based on the selected codec. |
ChannelConfig::Codec codec = config.video_config().codec; |
if (codec == ChannelConfig::CODEC_VERBATIM) { |
@@ -48,6 +105,12 @@ void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
} else { |
NOTREACHED() << "Invalid Encoding found: " << codec; |
} |
+ |
+ if (consumer_->GetPixelFormat() == FrameConsumer::FORMAT_RGBA) { |
+ scoped_ptr<VideoDecoder> wrapper( |
+ new RgbToBgrVideoDecoderFilter(decoder_.Pass())); |
+ decoder_ = wrapper.Pass(); |
+ } |
} |
void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, |