| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/jni/jni_frame_consumer.h" | 5 #include "remoting/client/jni/jni_frame_consumer.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
| 10 #include "base/android/scoped_java_ref.h" | 10 #include "base/android/scoped_java_ref.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "remoting/base/util.h" | 13 #include "remoting/base/util.h" |
| 14 #include "remoting/client/jni/chromoting_jni_instance.h" | 14 #include "remoting/client/jni/chromoting_jni_instance.h" |
| 15 #include "remoting/client/jni/chromoting_jni_runtime.h" | 15 #include "remoting/client/jni/chromoting_jni_runtime.h" |
| 16 #include "remoting/client/jni/jni_client.h" | 16 #include "remoting/client/jni/jni_client.h" |
| 17 #include "remoting/client/jni/jni_display_handler.h" |
| 17 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 18 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 18 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" | 19 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h" |
| 19 #include "ui/gfx/android/java_bitmap.h" | 20 #include "ui/gfx/android/java_bitmap.h" |
| 20 | 21 |
| 21 namespace remoting { | 22 namespace remoting { |
| 22 | 23 |
| 23 class JniFrameConsumer::Renderer { | 24 class JniFrameConsumer::Renderer { |
| 24 public: | 25 public: |
| 25 Renderer(ChromotingJniRuntime* jni_runtime, JniClient* jni_client) : | 26 Renderer(ChromotingJniRuntime* jni_runtime, |
| 26 jni_runtime_(jni_runtime), | 27 base::WeakPtr<JniDisplayHandler> display) |
| 27 jni_client_(jni_client) {} | 28 : jni_runtime_(jni_runtime), display_handler_(display) {} |
| 28 ~Renderer() { | 29 ~Renderer() { |
| 29 DCHECK(jni_runtime_->display_task_runner()->BelongsToCurrentThread()); | 30 DCHECK(jni_runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 30 } | 31 } |
| 31 | 32 |
| 32 void RenderFrame(std::unique_ptr<webrtc::DesktopFrame> frame); | 33 void RenderFrame(std::unique_ptr<webrtc::DesktopFrame> frame); |
| 33 | 34 |
| 34 private: | 35 private: |
| 35 // Used to obtain task runner references and make calls to Java methods. | 36 // Used to obtain task runner references and make calls to Java methods. |
| 36 ChromotingJniRuntime* jni_runtime_; | 37 ChromotingJniRuntime* jni_runtime_; |
| 37 | 38 |
| 38 JniClient* jni_client_; | 39 base::WeakPtr<JniDisplayHandler> display_handler_; |
| 39 | 40 |
| 40 // This global reference is required, instead of a local reference, so it | 41 // This global reference is required, instead of a local reference, so it |
| 41 // remains valid for the lifetime of |bitmap_| - gfx::JavaBitmap does not | 42 // remains valid for the lifetime of |bitmap_| - gfx::JavaBitmap does not |
| 42 // create its own global reference internally. And this global ref must be | 43 // create its own global reference internally. And this global ref must be |
| 43 // destroyed (released) after |bitmap_| is destroyed. | 44 // destroyed (released) after |bitmap_| is destroyed. |
| 44 base::android::ScopedJavaGlobalRef<jobject> bitmap_global_ref_; | 45 base::android::ScopedJavaGlobalRef<jobject> bitmap_global_ref_; |
| 45 | 46 |
| 46 // Reference to the frame bitmap that is passed to Java when the frame is | 47 // Reference to the frame bitmap that is passed to Java when the frame is |
| 47 // allocated. This provides easy access to the underlying pixels. | 48 // allocated. This provides easy access to the underlying pixels. |
| 48 std::unique_ptr<gfx::JavaBitmap> bitmap_; | 49 std::unique_ptr<gfx::JavaBitmap> bitmap_; |
| 49 }; | 50 }; |
| 50 | 51 |
| 51 // Function called on the display thread to render the frame. | 52 // Function called on the display thread to render the frame. |
| 52 void JniFrameConsumer::Renderer::RenderFrame( | 53 void JniFrameConsumer::Renderer::RenderFrame( |
| 53 std::unique_ptr<webrtc::DesktopFrame> frame) { | 54 std::unique_ptr<webrtc::DesktopFrame> frame) { |
| 54 DCHECK(jni_runtime_->display_task_runner()->BelongsToCurrentThread()); | 55 DCHECK(jni_runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 56 if (!display_handler_) { |
| 57 return; |
| 58 } |
| 55 | 59 |
| 56 if (!bitmap_ || bitmap_->size().width() != frame->size().width() || | 60 if (!bitmap_ || bitmap_->size().width() != frame->size().width() || |
| 57 bitmap_->size().height() != frame->size().height()) { | 61 bitmap_->size().height() != frame->size().height()) { |
| 58 // Allocate a new Bitmap, store references here, and pass it to Java. | 62 // Allocate a new Bitmap, store references here, and pass it to Java. |
| 59 JNIEnv* env = base::android::AttachCurrentThread(); | 63 JNIEnv* env = base::android::AttachCurrentThread(); |
| 60 | 64 |
| 61 // |bitmap_| must be deleted before |bitmap_global_ref_| is released. | 65 // |bitmap_| must be deleted before |bitmap_global_ref_| is released. |
| 62 bitmap_.reset(); | 66 bitmap_.reset(); |
| 63 bitmap_global_ref_.Reset( | 67 bitmap_global_ref_.Reset( |
| 64 env, | 68 env, display_handler_ |
| 65 jni_client_->NewBitmap(frame->size().width(), frame->size().height()) | 69 ->NewBitmap(frame->size().width(), frame->size().height()) |
| 66 .obj()); | 70 .obj()); |
| 67 bitmap_.reset(new gfx::JavaBitmap(bitmap_global_ref_.obj())); | 71 bitmap_.reset(new gfx::JavaBitmap(bitmap_global_ref_.obj())); |
| 68 jni_client_->UpdateFrameBitmap(bitmap_global_ref_.obj()); | 72 display_handler_->UpdateFrameBitmap(bitmap_global_ref_); |
| 69 } | 73 } |
| 70 | 74 |
| 71 // Copy pixels from |frame| into the Java Bitmap. | 75 // Copy pixels from |frame| into the Java Bitmap. |
| 72 // TODO(lambroslambrou): Optimize away this copy by having the VideoDecoder | 76 // TODO(lambroslambrou): Optimize away this copy by having the VideoDecoder |
| 73 // decode directly into the Bitmap's pixel memory. This currently doesn't | 77 // decode directly into the Bitmap's pixel memory. This currently doesn't |
| 74 // work very well because the VideoDecoder writes the decoded data in BGRA, | 78 // work very well because the VideoDecoder writes the decoded data in BGRA, |
| 75 // and then the R/B channels are swapped in place (on the decoding thread). | 79 // and then the R/B channels are swapped in place (on the decoding thread). |
| 76 // If a repaint is triggered from a Java event handler, the unswapped pixels | 80 // If a repaint is triggered from a Java event handler, the unswapped pixels |
| 77 // can sometimes appear on the display. | 81 // can sometimes appear on the display. |
| 78 uint8_t* dest_buffer = static_cast<uint8_t*>(bitmap_->pixels()); | 82 uint8_t* dest_buffer = static_cast<uint8_t*>(bitmap_->pixels()); |
| 79 webrtc::DesktopRect buffer_rect = | 83 webrtc::DesktopRect buffer_rect = |
| 80 webrtc::DesktopRect::MakeSize(frame->size()); | 84 webrtc::DesktopRect::MakeSize(frame->size()); |
| 81 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); !i.IsAtEnd(); | 85 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); !i.IsAtEnd(); |
| 82 i.Advance()) { | 86 i.Advance()) { |
| 83 CopyRGB32Rect(frame->data(), frame->stride(), buffer_rect, dest_buffer, | 87 CopyRGB32Rect(frame->data(), frame->stride(), buffer_rect, dest_buffer, |
| 84 bitmap_->stride(), buffer_rect, i.rect()); | 88 bitmap_->stride(), buffer_rect, i.rect()); |
| 85 } | 89 } |
| 86 | 90 |
| 87 jni_client_->RedrawCanvas(); | 91 display_handler_->RedrawCanvas(); |
| 88 } | 92 } |
| 89 | 93 |
| 90 JniFrameConsumer::JniFrameConsumer(ChromotingJniRuntime* jni_runtime, | 94 JniFrameConsumer::JniFrameConsumer(ChromotingJniRuntime* jni_runtime, |
| 91 JniClient* jni_client) | 95 base::WeakPtr<JniDisplayHandler> display) |
| 92 : jni_runtime_(jni_runtime), | 96 : jni_runtime_(jni_runtime), |
| 93 renderer_(new Renderer(jni_runtime, jni_client)), | 97 renderer_(new Renderer(jni_runtime, display)), |
| 94 weak_factory_(this) {} | 98 weak_factory_(this) {} |
| 95 | 99 |
| 96 JniFrameConsumer::~JniFrameConsumer() { | 100 JniFrameConsumer::~JniFrameConsumer() { |
| 97 jni_runtime_->display_task_runner()->DeleteSoon(FROM_HERE, | 101 jni_runtime_->display_task_runner()->DeleteSoon(FROM_HERE, |
| 98 renderer_.release()); | 102 renderer_.release()); |
| 99 } | 103 } |
| 100 | 104 |
| 101 std::unique_ptr<webrtc::DesktopFrame> JniFrameConsumer::AllocateFrame( | 105 std::unique_ptr<webrtc::DesktopFrame> JniFrameConsumer::AllocateFrame( |
| 102 const webrtc::DesktopSize& size) { | 106 const webrtc::DesktopSize& size) { |
| 103 return base::WrapUnique(new webrtc::BasicDesktopFrame(size)); | 107 return base::WrapUnique(new webrtc::BasicDesktopFrame(size)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 120 | 124 |
| 121 if (!done.is_null()) | 125 if (!done.is_null()) |
| 122 done.Run(); | 126 done.Run(); |
| 123 } | 127 } |
| 124 | 128 |
| 125 protocol::FrameConsumer::PixelFormat JniFrameConsumer::GetPixelFormat() { | 129 protocol::FrameConsumer::PixelFormat JniFrameConsumer::GetPixelFormat() { |
| 126 return FORMAT_RGBA; | 130 return FORMAT_RGBA; |
| 127 } | 131 } |
| 128 | 132 |
| 129 } // namespace remoting | 133 } // namespace remoting |
| OLD | NEW |