OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/cpu.h" | 11 #include "base/cpu.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/task_runner_util.h" | 14 #include "base/task_runner_util.h" |
15 #include "media/base/bind_to_loop.h" | 15 #include "media/base/bind_to_loop.h" |
16 #include "media/base/decoder_buffer.h" | 16 #include "media/base/decoder_buffer.h" |
17 #include "media/base/pipeline.h" | 17 #include "media/base/pipeline.h" |
18 #include "media/base/pipeline_status.h" | 18 #include "media/base/pipeline_status.h" |
19 #include "media/base/video_decoder_config.h" | 19 #include "media/base/video_decoder_config.h" |
20 | 20 |
21 namespace media { | 21 namespace media { |
22 | 22 |
23 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to | |
24 // the client's thread. | |
25 // | |
26 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories | |
27 // and take care of some of the work that GpuVideoDecoder does to minimize | |
28 // thread hopping. See following for discussion: | |
29 // | |
30 // https://codereview.chromium.org/12989009/diff/27035/media/filters/gpu_video_d
ecoder.cc#newcode23 | |
31 class VDAClientProxy | |
32 : public base::RefCountedThreadSafe<VDAClientProxy>, | |
33 public VideoDecodeAccelerator::Client { | |
34 public: | |
35 explicit VDAClientProxy(VideoDecodeAccelerator::Client* client); | |
36 | |
37 // Detaches the proxy. |weak_client_| will no longer be called and can be | |
38 // safely deleted. Any pending/future calls will be discarded. | |
39 // | |
40 // Must be called on |client_loop_|. | |
41 void Detach(); | |
42 | |
43 // VideoDecodeAccelerator::Client implementation. | |
44 virtual void NotifyInitializeDone() OVERRIDE; | |
45 virtual void ProvidePictureBuffers(uint32 count, | |
46 const gfx::Size& size, | |
47 uint32 texture_target) OVERRIDE; | |
48 virtual void DismissPictureBuffer(int32 id) OVERRIDE; | |
49 virtual void PictureReady(const media::Picture& picture) OVERRIDE; | |
50 virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE; | |
51 virtual void NotifyFlushDone() OVERRIDE; | |
52 virtual void NotifyResetDone() OVERRIDE; | |
53 virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE; | |
54 | |
55 private: | |
56 friend class base::RefCountedThreadSafe<VDAClientProxy>; | |
57 virtual ~VDAClientProxy(); | |
58 | |
59 scoped_refptr<base::MessageLoopProxy> client_loop_; | |
60 | |
61 // Weak pointers are used to invalidate tasks posted to |client_loop_| after | |
62 // Detach() has been called. | |
63 base::WeakPtrFactory<VideoDecodeAccelerator::Client> weak_client_factory_; | |
64 base::WeakPtr<VideoDecodeAccelerator::Client> weak_client_; | |
65 | |
66 DISALLOW_COPY_AND_ASSIGN(VDAClientProxy); | |
67 }; | |
68 | |
69 VDAClientProxy::VDAClientProxy(VideoDecodeAccelerator::Client* client) | |
70 : client_loop_(base::MessageLoopProxy::current()), | |
71 weak_client_factory_(client), | |
72 weak_client_(weak_client_factory_.GetWeakPtr()) { | |
73 DCHECK(weak_client_.get()); | |
74 } | |
75 | |
76 VDAClientProxy::~VDAClientProxy() {} | |
77 | |
78 void VDAClientProxy::Detach() { | |
79 DCHECK(client_loop_->BelongsToCurrentThread()); | |
80 DCHECK(weak_client_.get()) << "Detach() already called"; | |
81 weak_client_factory_.InvalidateWeakPtrs(); | |
82 } | |
83 | |
84 void VDAClientProxy::NotifyInitializeDone() { | |
85 client_loop_->PostTask(FROM_HERE, base::Bind( | |
86 &VideoDecodeAccelerator::Client::NotifyInitializeDone, weak_client_)); | |
87 } | |
88 | |
89 void VDAClientProxy::ProvidePictureBuffers(uint32 count, | |
90 const gfx::Size& size, | |
91 uint32 texture_target) { | |
92 client_loop_->PostTask(FROM_HERE, base::Bind( | |
93 &VideoDecodeAccelerator::Client::ProvidePictureBuffers, weak_client_, | |
94 count, size, texture_target)); | |
95 } | |
96 | |
97 void VDAClientProxy::DismissPictureBuffer(int32 id) { | |
98 client_loop_->PostTask(FROM_HERE, base::Bind( | |
99 &VideoDecodeAccelerator::Client::DismissPictureBuffer, weak_client_, id)); | |
100 } | |
101 | |
102 void VDAClientProxy::PictureReady(const media::Picture& picture) { | |
103 client_loop_->PostTask(FROM_HERE, base::Bind( | |
104 &VideoDecodeAccelerator::Client::PictureReady, weak_client_, picture)); | |
105 } | |
106 | |
107 void VDAClientProxy::NotifyEndOfBitstreamBuffer(int32 id) { | |
108 client_loop_->PostTask(FROM_HERE, base::Bind( | |
109 &VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, weak_client_, | |
110 id)); | |
111 } | |
112 | |
113 void VDAClientProxy::NotifyFlushDone() { | |
114 client_loop_->PostTask(FROM_HERE, base::Bind( | |
115 &VideoDecodeAccelerator::Client::NotifyFlushDone, weak_client_)); | |
116 } | |
117 | |
118 void VDAClientProxy::NotifyResetDone() { | |
119 client_loop_->PostTask(FROM_HERE, base::Bind( | |
120 &VideoDecodeAccelerator::Client::NotifyResetDone, weak_client_)); | |
121 } | |
122 | |
123 void VDAClientProxy::NotifyError(media::VideoDecodeAccelerator::Error error) { | |
124 client_loop_->PostTask(FROM_HERE, base::Bind( | |
125 &VideoDecodeAccelerator::Client::NotifyError, weak_client_, error)); | |
126 } | |
127 | |
128 | |
129 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 23 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
130 // Higher values allow better pipelining in the GPU, but also require more | 24 // Higher values allow better pipelining in the GPU, but also require more |
131 // resources. | 25 // resources. |
132 enum { kMaxInFlightDecodes = 4 }; | 26 enum { kMaxInFlightDecodes = 4 }; |
133 | 27 |
134 GpuVideoDecoder::Factories::~Factories() {} | 28 GpuVideoDecoder::Factories::~Factories() {} |
135 | 29 |
136 // Size of shared-memory segments we allocate. Since we reuse them we let them | 30 // Size of shared-memory segments we allocate. Since we reuse them we let them |
137 // be on the beefy side. | 31 // be on the beefy side. |
138 static const size_t kSharedMemorySegmentBytes = 100 << 10; | 32 static const size_t kSharedMemorySegmentBytes = 100 << 10; |
(...skipping 18 matching lines...) Expand all Loading... |
157 } | 51 } |
158 | 52 |
159 GpuVideoDecoder::BufferData::~BufferData() {} | 53 GpuVideoDecoder::BufferData::~BufferData() {} |
160 | 54 |
161 GpuVideoDecoder::GpuVideoDecoder( | 55 GpuVideoDecoder::GpuVideoDecoder( |
162 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 56 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
163 const scoped_refptr<Factories>& factories) | 57 const scoped_refptr<Factories>& factories) |
164 : needs_bitstream_conversion_(false), | 58 : needs_bitstream_conversion_(false), |
165 gvd_loop_proxy_(message_loop), | 59 gvd_loop_proxy_(message_loop), |
166 weak_factory_(this), | 60 weak_factory_(this), |
167 vda_loop_proxy_(factories->GetMessageLoop()), | |
168 factories_(factories), | 61 factories_(factories), |
169 state_(kNormal), | 62 state_(kNormal), |
170 decoder_texture_target_(0), | 63 decoder_texture_target_(0), |
171 next_picture_buffer_id_(0), | 64 next_picture_buffer_id_(0), |
172 next_bitstream_buffer_id_(0), | 65 next_bitstream_buffer_id_(0), |
173 available_pictures_(0) { | 66 available_pictures_(0) { |
174 DCHECK(factories_.get()); | 67 DCHECK(factories_.get()); |
| 68 DCHECK_EQ(message_loop.get(), factories->GetMessageLoop().get()); |
175 } | 69 } |
176 | 70 |
177 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 71 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
178 DVLOG(3) << "Reset()"; | 72 DVLOG(3) << "Reset()"; |
179 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 73 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
180 | 74 |
181 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { | 75 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { |
182 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 76 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
183 &GpuVideoDecoder::Reset, weak_this_, closure)); | 77 &GpuVideoDecoder::Reset, weak_this_, closure)); |
184 // NOTE: if we're deferring Reset() until a Flush() completes, return | 78 // NOTE: if we're deferring Reset() until a Flush() completes, return |
(...skipping 10 matching lines...) Expand all Loading... |
195 gvd_loop_proxy_->PostTask(FROM_HERE, closure); | 89 gvd_loop_proxy_->PostTask(FROM_HERE, closure); |
196 return; | 90 return; |
197 } | 91 } |
198 | 92 |
199 if (!pending_read_cb_.is_null()) | 93 if (!pending_read_cb_.is_null()) |
200 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 94 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
201 | 95 |
202 DCHECK(pending_reset_cb_.is_null()); | 96 DCHECK(pending_reset_cb_.is_null()); |
203 pending_reset_cb_ = BindToCurrentLoop(closure); | 97 pending_reset_cb_ = BindToCurrentLoop(closure); |
204 | 98 |
205 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 99 vda_->Reset(); |
206 &VideoDecodeAccelerator::Reset, weak_vda_)); | |
207 } | 100 } |
208 | 101 |
209 void GpuVideoDecoder::Stop(const base::Closure& closure) { | 102 void GpuVideoDecoder::Stop(const base::Closure& closure) { |
210 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 103 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
211 if (vda_) | 104 if (vda_) |
212 DestroyVDA(); | 105 DestroyVDA(); |
213 if (!pending_read_cb_.is_null()) | 106 if (!pending_read_cb_.is_null()) |
214 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 107 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
215 if (!pending_reset_cb_.is_null()) | 108 if (!pending_reset_cb_.is_null()) |
216 base::ResetAndReturn(&pending_reset_cb_).Run(); | 109 base::ResetAndReturn(&pending_reset_cb_).Run(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 DVLOG(1) << "GpuVideoDecoder reinitialization not supported."; | 145 DVLOG(1) << "GpuVideoDecoder reinitialization not supported."; |
253 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 146 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
254 return; | 147 return; |
255 } | 148 } |
256 | 149 |
257 if (!IsCodedSizeSupported(config.coded_size())) { | 150 if (!IsCodedSizeSupported(config.coded_size())) { |
258 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 151 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
259 return; | 152 return; |
260 } | 153 } |
261 | 154 |
262 client_proxy_ = new VDAClientProxy(this); | 155 VideoDecodeAccelerator* vda = |
263 VideoDecodeAccelerator* vda = factories_->CreateVideoDecodeAccelerator( | 156 factories_->CreateVideoDecodeAccelerator(config.profile(), this); |
264 config.profile(), client_proxy_.get()); | |
265 if (!vda) { | 157 if (!vda) { |
266 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 158 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
267 return; | 159 return; |
268 } | 160 } |
269 | 161 |
270 config_ = config; | 162 config_ = config; |
271 needs_bitstream_conversion_ = (config.codec() == kCodecH264); | 163 needs_bitstream_conversion_ = (config.codec() == kCodecH264); |
272 | 164 |
273 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded."; | 165 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded."; |
274 PostTaskAndReplyWithResult( | |
275 vda_loop_proxy_.get(), | |
276 FROM_HERE, | |
277 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)), | |
278 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda)); | |
279 } | |
280 | |
281 void GpuVideoDecoder::SetVDA( | |
282 const PipelineStatusCB& status_cb, | |
283 VideoDecodeAccelerator* vda, | |
284 base::WeakPtr<VideoDecodeAccelerator> weak_vda) { | |
285 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | |
286 DCHECK(!vda_.get()); | |
287 vda_.reset(vda); | 166 vda_.reset(vda); |
288 weak_vda_ = weak_vda; | |
289 status_cb.Run(PIPELINE_OK); | 167 status_cb.Run(PIPELINE_OK); |
290 } | 168 } |
291 | 169 |
292 void GpuVideoDecoder::DestroyTextures() { | 170 void GpuVideoDecoder::DestroyTextures() { |
293 std::map<int32, PictureBuffer>::iterator it; | 171 std::map<int32, PictureBuffer>::iterator it; |
294 | 172 |
295 for (it = assigned_picture_buffers_.begin(); | 173 for (it = assigned_picture_buffers_.begin(); |
296 it != assigned_picture_buffers_.end(); ++it) { | 174 it != assigned_picture_buffers_.end(); ++it) { |
297 factories_->DeleteTexture(it->second.texture_id()); | 175 factories_->DeleteTexture(it->second.texture_id()); |
298 } | 176 } |
299 assigned_picture_buffers_.clear(); | 177 assigned_picture_buffers_.clear(); |
300 | 178 |
301 for (it = dismissed_picture_buffers_.begin(); | 179 for (it = dismissed_picture_buffers_.begin(); |
302 it != dismissed_picture_buffers_.end(); ++it) { | 180 it != dismissed_picture_buffers_.end(); ++it) { |
303 factories_->DeleteTexture(it->second.texture_id()); | 181 factories_->DeleteTexture(it->second.texture_id()); |
304 } | 182 } |
305 dismissed_picture_buffers_.clear(); | 183 dismissed_picture_buffers_.clear(); |
306 } | 184 } |
307 | 185 |
308 static void DestroyVDAWithClientProxy( | |
309 const scoped_refptr<VDAClientProxy>& client_proxy, | |
310 base::WeakPtr<VideoDecodeAccelerator> weak_vda) { | |
311 if (weak_vda.get()) { | |
312 weak_vda->Destroy(); | |
313 DCHECK(!weak_vda.get()); // Check VDA::Destroy() contract. | |
314 } | |
315 } | |
316 | |
317 void GpuVideoDecoder::DestroyVDA() { | 186 void GpuVideoDecoder::DestroyVDA() { |
318 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 187 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
319 | 188 |
320 // |client_proxy| must stay alive until |weak_vda_| has been destroyed. | 189 if (vda_) |
321 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 190 vda_.release()->Destroy(); |
322 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_)); | |
323 | |
324 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); | |
325 client_proxy_->Detach(); | |
326 client_proxy_ = NULL; | |
327 | 191 |
328 DestroyTextures(); | 192 DestroyTextures(); |
329 } | 193 } |
330 | 194 |
331 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 195 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
332 const ReadCB& read_cb) { | 196 const ReadCB& read_cb) { |
333 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 197 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
334 DCHECK(pending_reset_cb_.is_null()); | 198 DCHECK(pending_reset_cb_.is_null()); |
335 DCHECK(pending_read_cb_.is_null()); | 199 DCHECK(pending_read_cb_.is_null()); |
336 | 200 |
(...skipping 20 matching lines...) Expand all Loading... |
357 // NotifyFlushDone below. | 221 // NotifyFlushDone below. |
358 return; | 222 return; |
359 case kError: | 223 case kError: |
360 NOTREACHED(); | 224 NOTREACHED(); |
361 return; | 225 return; |
362 } | 226 } |
363 | 227 |
364 if (buffer->IsEndOfStream()) { | 228 if (buffer->IsEndOfStream()) { |
365 if (state_ == kNormal) { | 229 if (state_ == kNormal) { |
366 state_ = kDrainingDecoder; | 230 state_ = kDrainingDecoder; |
367 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 231 vda_->Flush(); |
368 &VideoDecodeAccelerator::Flush, weak_vda_)); | |
369 } | 232 } |
370 return; | 233 return; |
371 } | 234 } |
372 | 235 |
373 size_t size = buffer->GetDataSize(); | 236 size_t size = buffer->GetDataSize(); |
374 SHMBuffer* shm_buffer = GetSHM(size); | 237 SHMBuffer* shm_buffer = GetSHM(size); |
375 if (!shm_buffer) { | 238 if (!shm_buffer) { |
376 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 239 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
377 return; | 240 return; |
378 } | 241 } |
379 | 242 |
380 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); | 243 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); |
381 BitstreamBuffer bitstream_buffer( | 244 BitstreamBuffer bitstream_buffer( |
382 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); | 245 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); |
383 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. | 246 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
384 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; | 247 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; |
385 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 248 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
386 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 249 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
387 DCHECK(inserted); | 250 DCHECK(inserted); |
388 RecordBufferData(bitstream_buffer, *buffer.get()); | 251 RecordBufferData(bitstream_buffer, *buffer.get()); |
389 | 252 |
390 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 253 vda_->Decode(bitstream_buffer); |
391 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); | |
392 | 254 |
393 if (!ready_video_frames_.empty()) { | 255 if (!ready_video_frames_.empty()) { |
394 EnqueueFrameAndTriggerFrameDelivery(NULL); | 256 EnqueueFrameAndTriggerFrameDelivery(NULL); |
395 return; | 257 return; |
396 } | 258 } |
397 | 259 |
398 if (CanMoreDecodeWorkBeDone()) | 260 if (CanMoreDecodeWorkBeDone()) |
399 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL); | 261 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL); |
400 } | 262 } |
401 | 263 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 for (size_t i = 0; i < texture_ids.size(); ++i) { | 346 for (size_t i = 0; i < texture_ids.size(); ++i) { |
485 picture_buffers.push_back(PictureBuffer( | 347 picture_buffers.push_back(PictureBuffer( |
486 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); | 348 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); |
487 bool inserted = assigned_picture_buffers_.insert(std::make_pair( | 349 bool inserted = assigned_picture_buffers_.insert(std::make_pair( |
488 picture_buffers.back().id(), picture_buffers.back())).second; | 350 picture_buffers.back().id(), picture_buffers.back())).second; |
489 DCHECK(inserted); | 351 DCHECK(inserted); |
490 } | 352 } |
491 | 353 |
492 available_pictures_ += count; | 354 available_pictures_ += count; |
493 | 355 |
494 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 356 vda_->AssignPictureBuffers(picture_buffers); |
495 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, | |
496 picture_buffers)); | |
497 } | 357 } |
498 | 358 |
499 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 359 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
500 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; | 360 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; |
501 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 361 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
502 | 362 |
503 std::map<int32, PictureBuffer>::iterator it = | 363 std::map<int32, PictureBuffer>::iterator it = |
504 assigned_picture_buffers_.find(id); | 364 assigned_picture_buffers_.find(id); |
505 if (it == assigned_picture_buffers_.end()) { | 365 if (it == assigned_picture_buffers_.end()) { |
506 NOTREACHED() << "Missing picture buffer: " << id; | 366 NOTREACHED() << "Missing picture buffer: " << id; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 it = dismissed_picture_buffers_.find(picture_buffer_id); | 473 it = dismissed_picture_buffers_.find(picture_buffer_id); |
614 DCHECK(it != dismissed_picture_buffers_.end()); | 474 DCHECK(it != dismissed_picture_buffers_.end()); |
615 factories_->DeleteTexture(it->second.texture_id()); | 475 factories_->DeleteTexture(it->second.texture_id()); |
616 dismissed_picture_buffers_.erase(it); | 476 dismissed_picture_buffers_.erase(it); |
617 return; | 477 return; |
618 } | 478 } |
619 | 479 |
620 factories_->WaitSyncPoint(sync_point); | 480 factories_->WaitSyncPoint(sync_point); |
621 ++available_pictures_; | 481 ++available_pictures_; |
622 | 482 |
623 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 483 vda_->ReusePictureBuffer(picture_buffer_id); |
624 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, | |
625 picture_buffer_id)); | |
626 } | 484 } |
627 | 485 |
628 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 486 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
629 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 487 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
630 if (available_shm_segments_.empty() || | 488 if (available_shm_segments_.empty() || |
631 available_shm_segments_.back()->size < min_size) { | 489 available_shm_segments_.back()->size < min_size) { |
632 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 490 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
633 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 491 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
634 // CreateSharedMemory() can return NULL during Shutdown. | 492 // CreateSharedMemory() can return NULL during Shutdown. |
635 if (!shm) | 493 if (!shm) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 | 577 |
720 state_ = kError; | 578 state_ = kError; |
721 | 579 |
722 if (!pending_read_cb_.is_null()) { | 580 if (!pending_read_cb_.is_null()) { |
723 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 581 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
724 return; | 582 return; |
725 } | 583 } |
726 } | 584 } |
727 | 585 |
728 } // namespace media | 586 } // namespace media |
OLD | NEW |