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