OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h" | 5 #include "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 // Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO | 24 // Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO |
25 // thread. This does very similar what MessageFilter usually does. It is not | 25 // thread. This does very similar what MessageFilter usually does. It is not |
26 // MessageFilter because GpuChannelHost doesn't support AddFilter. | 26 // MessageFilter because GpuChannelHost doesn't support AddFilter. |
27 class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener, | 27 class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener, |
28 public base::NonThreadSafe { | 28 public base::NonThreadSafe { |
29 public: | 29 public: |
30 Receiver(Client* client, | 30 Receiver(Client* client, |
31 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | 31 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
32 : client_(client), | 32 : client_(client), |
33 io_task_runner_(io_task_runner), | 33 io_task_runner_(io_task_runner), |
34 weak_factory_for_io_(this) { | 34 weak_factory_for_io_( |
| 35 base::MakeUnique<base::WeakPtrFactory<Receiver>>(this)), |
| 36 weak_ptr_for_io_(weak_factory_for_io_->GetWeakPtr()) { |
35 DCHECK(CalledOnValidThread()); | 37 DCHECK(CalledOnValidThread()); |
36 } | 38 } |
37 | 39 |
38 ~Receiver() override { DCHECK(CalledOnValidThread()); } | 40 ~Receiver() override { |
| 41 DCHECK(CalledOnValidThread()); |
| 42 // If |io_task_runner_| no longer accepts tasks, |weak_factory_for_io_| |
| 43 // will leak. This is acceptable, because that should only happen on |
| 44 // Browser shutdown. |
| 45 io_task_runner_->DeleteSoon(FROM_HERE, weak_factory_for_io_.release()); |
| 46 } |
39 | 47 |
40 void InvalidateWeakPtr(base::WaitableEvent* event) { | 48 void InvalidateWeakPtrOnIOThread(base::WaitableEvent* event) { |
41 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 49 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
42 weak_factory_for_io_.InvalidateWeakPtrs(); | 50 weak_factory_for_io_->InvalidateWeakPtrs(); |
43 event->Signal(); | 51 event->Signal(); |
44 } | 52 } |
45 | 53 |
46 // IPC::Listener implementation. | 54 // IPC::Listener implementation. |
47 void OnChannelError() override { | 55 void OnChannelError() override { |
48 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 56 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
49 | 57 |
50 OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE); | 58 OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE); |
51 } | 59 } |
52 | 60 |
53 bool OnMessageReceived(const IPC::Message& msg) override { | 61 bool OnMessageReceived(const IPC::Message& msg) override { |
54 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 62 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
55 | 63 |
56 bool handled = true; | 64 bool handled = true; |
57 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg) | 65 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg) |
58 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck) | 66 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck) |
59 IPC_MESSAGE_UNHANDLED(handled = false) | 67 IPC_MESSAGE_UNHANDLED(handled = false) |
60 IPC_END_MESSAGE_MAP() | 68 IPC_END_MESSAGE_MAP() |
61 DCHECK(handled); | 69 DCHECK(handled); |
62 return handled; | 70 return handled; |
63 } | 71 } |
64 | 72 |
65 base::WeakPtr<IPC::Listener> AsWeakPtrForIO() { | 73 base::WeakPtr<IPC::Listener> AsWeakPtrForIO() { return weak_ptr_for_io_; } |
66 return weak_factory_for_io_.GetWeakPtr(); | |
67 } | |
68 | 74 |
69 private: | 75 private: |
70 void OnDecodeAck(int32_t bitstream_buffer_id, Error error) { | 76 void OnDecodeAck(int32_t bitstream_buffer_id, Error error) { |
71 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 77 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
72 | 78 |
73 if (!client_) | 79 if (!client_) |
74 return; | 80 return; |
75 | 81 |
76 if (error == JpegDecodeAccelerator::NO_ERRORS) { | 82 if (error == JpegDecodeAccelerator::NO_ERRORS) { |
77 client_->VideoFrameReady(bitstream_buffer_id); | 83 client_->VideoFrameReady(bitstream_buffer_id); |
78 } else { | 84 } else { |
79 // Only NotifyError once. | 85 // Only NotifyError once. |
80 // Client::NotifyError() may trigger deletion of |this| (on another | 86 // Client::NotifyError() may trigger deletion of |this| (on another |
81 // thread), so calling it needs to be the last thing done on this stack! | 87 // thread), so calling it needs to be the last thing done on this stack! |
82 JpegDecodeAccelerator::Client* client = nullptr; | 88 JpegDecodeAccelerator::Client* client = nullptr; |
83 std::swap(client, client_); | 89 std::swap(client, client_); |
84 client->NotifyError(bitstream_buffer_id, error); | 90 client->NotifyError(bitstream_buffer_id, error); |
85 } | 91 } |
86 } | 92 } |
87 | 93 |
88 Client* client_; | 94 Client* client_; |
89 | 95 |
90 // GPU IO task runner. | 96 // GPU IO task runner. |
91 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | 97 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
92 | 98 |
93 // Weak pointers will be invalidated on IO thread. | 99 // Weak pointers will be invalidated on IO thread. |
94 base::WeakPtrFactory<Receiver> weak_factory_for_io_; | 100 std::unique_ptr<base::WeakPtrFactory<Receiver>> weak_factory_for_io_; |
| 101 base::WeakPtr<Receiver> weak_ptr_for_io_; |
95 | 102 |
96 DISALLOW_COPY_AND_ASSIGN(Receiver); | 103 DISALLOW_COPY_AND_ASSIGN(Receiver); |
97 }; | 104 }; |
98 | 105 |
99 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost( | 106 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost( |
100 scoped_refptr<gpu::GpuChannelHost> channel, | 107 scoped_refptr<gpu::GpuChannelHost> channel, |
101 int32_t route_id, | 108 int32_t route_id, |
102 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | 109 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
103 : channel_(std::move(channel)), | 110 : channel_(std::move(channel)), |
104 decoder_route_id_(route_id), | 111 decoder_route_id_(route_id), |
105 io_task_runner_(io_task_runner) { | 112 io_task_runner_(io_task_runner) { |
106 DCHECK(channel_); | 113 DCHECK(channel_); |
107 DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE); | 114 DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE); |
108 } | 115 } |
109 | 116 |
110 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() { | 117 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() { |
111 DCHECK(CalledOnValidThread()); | 118 DCHECK(CalledOnValidThread()); |
112 Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_)); | 119 Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_)); |
113 | 120 |
114 if (receiver_) { | 121 if (receiver_) { |
115 channel_->RemoveRoute(decoder_route_id_); | 122 channel_->RemoveRoute(decoder_route_id_); |
116 | 123 |
117 // Invalidate weak ptr of |receiver_|. After that, no more messages will be | 124 // Invalidate weak ptr of |receiver_|. After that, no more messages will be |
118 // routed to |receiver_| on IO thread. | 125 // routed to |receiver_| on IO thread. |
119 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 126 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
120 base::WaitableEvent::InitialState::NOT_SIGNALED); | 127 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 128 // Use of Unretained() is safe, because if the task executes, we block |
| 129 // until it is finished by waiting on |event| below. |
121 bool task_expected_to_run = io_task_runner_->PostTask( | 130 bool task_expected_to_run = io_task_runner_->PostTask( |
122 FROM_HERE, base::Bind(&Receiver::InvalidateWeakPtr, | 131 FROM_HERE, base::Bind(&Receiver::InvalidateWeakPtrOnIOThread, |
123 base::Unretained(receiver_.get()), | 132 base::Unretained(receiver_.get()), |
124 base::Unretained(&event))); | 133 base::Unretained(&event))); |
125 // If the current call is happening during the browser shutdown, the | 134 // If the current call is happening during the browser shutdown, the |
126 // |io_task_runner_| may no longer be accepting tasks. | 135 // |io_task_runner_| may no longer be accepting tasks. |
127 if (task_expected_to_run) | 136 if (task_expected_to_run) |
128 event.Wait(); | 137 event.Wait(); |
129 } | 138 } |
130 } | 139 } |
131 | 140 |
132 bool GpuJpegDecodeAcceleratorHost::Initialize( | 141 bool GpuJpegDecodeAcceleratorHost::Initialize( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 if (!channel_->Send(message)) { | 208 if (!channel_->Send(message)) { |
200 DLOG(ERROR) << "Send(" << message->type() << ") failed"; | 209 DLOG(ERROR) << "Send(" << message->type() << ") failed"; |
201 } | 210 } |
202 } | 211 } |
203 | 212 |
204 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() { | 213 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() { |
205 return receiver_->AsWeakPtrForIO(); | 214 return receiver_->AsWeakPtrForIO(); |
206 } | 215 } |
207 | 216 |
208 } // namespace media | 217 } // namespace media |
OLD | NEW |