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