Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: media/filters/gpu_video_decoder.cc

Issue 16274005: Separate DemuxerStream and VideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: VideoFrameStream ready for review. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/cpu.h" 9 #include "base/cpu.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/task_runner_util.h" 12 #include "base/task_runner_util.h"
13 #include "media/base/bind_to_loop.h" 13 #include "media/base/bind_to_loop.h"
14 #include "media/base/decoder_buffer.h" 14 #include "media/base/decoder_buffer.h"
15 #include "media/base/demuxer_stream.h"
16 #include "media/base/pipeline.h" 15 #include "media/base/pipeline.h"
17 #include "media/base/pipeline_status.h" 16 #include "media/base/pipeline_status.h"
18 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
19 18
20 namespace media { 19 namespace media {
21 20
22 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to 21 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to
23 // the client's thread. 22 // the client's thread.
24 // 23 //
25 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories 24 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) 152 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns)
154 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), 153 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr),
155 natural_size(ns) { 154 natural_size(ns) {
156 } 155 }
157 156
158 GpuVideoDecoder::BufferData::~BufferData() {} 157 GpuVideoDecoder::BufferData::~BufferData() {}
159 158
160 GpuVideoDecoder::GpuVideoDecoder( 159 GpuVideoDecoder::GpuVideoDecoder(
161 const scoped_refptr<base::MessageLoopProxy>& message_loop, 160 const scoped_refptr<base::MessageLoopProxy>& message_loop,
162 const scoped_refptr<Factories>& factories) 161 const scoped_refptr<Factories>& factories)
163 : demuxer_stream_(NULL), 162 : needs_bitstream_conversion_(false),
164 needs_bitstream_conversion_(false),
165 gvd_loop_proxy_(message_loop), 163 gvd_loop_proxy_(message_loop),
166 weak_factory_(this), 164 weak_factory_(this),
167 vda_loop_proxy_(factories->GetMessageLoop()), 165 vda_loop_proxy_(factories->GetMessageLoop()),
168 factories_(factories), 166 factories_(factories),
169 state_(kNormal), 167 state_(kNormal),
170 demuxer_read_in_progress_(false),
171 decoder_texture_target_(0), 168 decoder_texture_target_(0),
172 next_picture_buffer_id_(0), 169 next_picture_buffer_id_(0),
173 next_bitstream_buffer_id_(0), 170 next_bitstream_buffer_id_(0),
174 available_pictures_(-1) { 171 available_pictures_(-1) {
175 DCHECK(factories_); 172 DCHECK(factories_);
173 DCHECK(!config_.IsValidConfig());
176 } 174 }
177 175
178 void GpuVideoDecoder::Reset(const base::Closure& closure) { 176 void GpuVideoDecoder::Reset(const base::Closure& closure) {
179 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 177 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
180 178
181 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { 179 if (state_ == kDrainingDecoder && !factories_->IsAborted()) {
182 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 180 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
183 &GpuVideoDecoder::Reset, weak_this_, closure)); 181 &GpuVideoDecoder::Reset, weak_this_, closure));
184 // NOTE: if we're deferring Reset() until a Flush() completes, return 182 // NOTE: if we're deferring Reset() until a Flush() completes, return
185 // queued pictures to the VDA so they can be used to finish that Flush(). 183 // queued pictures to the VDA so they can be used to finish that Flush().
(...skipping 21 matching lines...) Expand all
207 } 205 }
208 206
209 void GpuVideoDecoder::Stop(const base::Closure& closure) { 207 void GpuVideoDecoder::Stop(const base::Closure& closure) {
210 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 208 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
211 if (vda_) 209 if (vda_)
212 DestroyVDA(); 210 DestroyVDA();
213 if (!pending_read_cb_.is_null()) 211 if (!pending_read_cb_.is_null())
214 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 212 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
215 if (!pending_reset_cb_.is_null()) 213 if (!pending_reset_cb_.is_null())
216 base::ResetAndReturn(&pending_reset_cb_).Run(); 214 base::ResetAndReturn(&pending_reset_cb_).Run();
217 demuxer_stream_ = NULL;
218 BindToCurrentLoop(closure).Run(); 215 BindToCurrentLoop(closure).Run();
219 } 216 }
220 217
221 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { 218 static bool IsCodedSizeSupported(const gfx::Size& coded_size) {
222 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. 219 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080.
223 // We test against 1088 to account for 16x16 macroblocks. 220 // We test against 1088 to account for 16x16 macroblocks.
224 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) 221 if (coded_size.width() <= 1920 && coded_size.height() <= 1088)
225 return true; 222 return true;
226 223
227 base::CPU cpu; 224 base::CPU cpu;
228 bool hw_large_video_support = 225 bool hw_large_video_support =
229 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58; 226 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58;
230 bool os_large_video_support = true; 227 bool os_large_video_support = true;
231 #if defined(OS_WIN) 228 #if defined(OS_WIN)
232 os_large_video_support = false; 229 os_large_video_support = false;
233 #endif 230 #endif
234 return os_large_video_support && hw_large_video_support; 231 return os_large_video_support && hw_large_video_support;
235 } 232 }
236 233
237 void GpuVideoDecoder::Initialize(DemuxerStream* stream, 234 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
238 const PipelineStatusCB& orig_status_cb, 235 const PipelineStatusCB& orig_status_cb,
239 const StatisticsCB& statistics_cb) { 236 const StatisticsCB& statistics_cb) {
240 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 237 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
241 DCHECK(stream); 238 DCHECK(config.IsValidConfig());
239 DCHECK(!config.is_encrypted());
242 240
243 weak_this_ = weak_factory_.GetWeakPtr(); 241 weak_this_ = weak_factory_.GetWeakPtr();
244 242
245 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( 243 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
246 "Media.GpuVideoDecoderInitializeStatus", 244 "Media.GpuVideoDecoderInitializeStatus",
247 BindToCurrentLoop(orig_status_cb)); 245 BindToCurrentLoop(orig_status_cb));
248 246
249 if (demuxer_stream_) { 247 if (config_.IsValidConfig()) {
250 // TODO(xhwang): Make GpuVideoDecoder reinitializable. 248 // TODO(xhwang): Make GpuVideoDecoder reinitializable.
251 // See http://crbug.com/233608 249 // See http://crbug.com/233608
252 DVLOG(1) << "GpuVideoDecoder reinitialization not supported."; 250 DVLOG(1) << "GpuVideoDecoder reinitialization not supported.";
253 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 251 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
254 return; 252 return;
255 } 253 }
256 254
257 const VideoDecoderConfig& config = stream->video_decoder_config();
258 DCHECK(config.IsValidConfig());
259 DCHECK(!config.is_encrypted());
260
261 if (!IsCodedSizeSupported(config.coded_size())) { 255 if (!IsCodedSizeSupported(config.coded_size())) {
262 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 256 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
263 return; 257 return;
264 } 258 }
265 259
266 client_proxy_ = new VDAClientProxy(this); 260 client_proxy_ = new VDAClientProxy(this);
267 VideoDecodeAccelerator* vda = 261 VideoDecodeAccelerator* vda =
268 factories_->CreateVideoDecodeAccelerator(config.profile(), client_proxy_); 262 factories_->CreateVideoDecodeAccelerator(config.profile(), client_proxy_);
269 if (!vda) { 263 if (!vda) {
270 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 264 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
271 return; 265 return;
272 } 266 }
273 267
274 demuxer_stream_ = stream;
275 statistics_cb_ = statistics_cb; 268 statistics_cb_ = statistics_cb;
276 needs_bitstream_conversion_ = (config.codec() == kCodecH264); 269 needs_bitstream_conversion_ = (config.codec() == kCodecH264);
277 270
278 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; 271 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
279 PostTaskAndReplyWithResult( 272 PostTaskAndReplyWithResult(
280 vda_loop_proxy_, FROM_HERE, 273 vda_loop_proxy_, FROM_HERE,
281 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)), 274 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)),
282 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda)); 275 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda));
283 } 276 }
284 277
285 void GpuVideoDecoder::SetVDA( 278 void GpuVideoDecoder::SetVDA(
286 const PipelineStatusCB& status_cb, 279 const PipelineStatusCB& status_cb,
287 VideoDecodeAccelerator* vda, 280 VideoDecodeAccelerator* vda,
288 base::WeakPtr<VideoDecodeAccelerator> weak_vda) { 281 base::WeakPtr<VideoDecodeAccelerator> weak_vda) {
289 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 282 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
290 DCHECK(!vda_.get()); 283 DCHECK(!vda_.get());
291 vda_.reset(vda); 284 vda_.reset(vda);
292 weak_vda_ = weak_vda; 285 weak_vda_ = weak_vda;
293 status_cb.Run(PIPELINE_OK); 286 status_cb.Run(PIPELINE_OK);
294 } 287 }
295 288
296 void GpuVideoDecoder::DestroyTextures() { 289 void GpuVideoDecoder::DestroyTextures() {
297 for (std::map<int32, PictureBuffer>::iterator it = 290 for (std::map<int32, PictureBuffer>::iterator it =
298 picture_buffers_in_decoder_.begin(); 291 picture_buffers_in_decoder_.begin();
299 it != picture_buffers_in_decoder_.end(); ++it) { 292 it != picture_buffers_in_decoder_.end();
293 ++it) {
300 factories_->DeleteTexture(it->second.texture_id()); 294 factories_->DeleteTexture(it->second.texture_id());
301 } 295 }
302 picture_buffers_in_decoder_.clear(); 296 picture_buffers_in_decoder_.clear();
303 } 297 }
304 298
305 static void DestroyVDAWithClientProxy( 299 static void DestroyVDAWithClientProxy(
306 const scoped_refptr<VDAClientProxy>& client_proxy, 300 const scoped_refptr<VDAClientProxy>& client_proxy,
307 base::WeakPtr<VideoDecodeAccelerator> weak_vda) { 301 base::WeakPtr<VideoDecodeAccelerator> weak_vda) {
308 if (weak_vda) { 302 if (weak_vda) {
309 weak_vda->Destroy(); 303 weak_vda->Destroy();
310 DCHECK(!weak_vda); // Check VDA::Destroy() contract. 304 DCHECK(!weak_vda); // Check VDA::Destroy() contract.
311 } 305 }
312 } 306 }
313 307
314 void GpuVideoDecoder::DestroyVDA() { 308 void GpuVideoDecoder::DestroyVDA() {
315 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 309 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
316 310
317 // |client_proxy| must stay alive until |weak_vda_| has been destroyed. 311 // |client_proxy| must stay alive until |weak_vda_| has been destroyed.
318 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 312 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
319 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_)); 313 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_));
320 314
321 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); 315 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
322 client_proxy_->Detach(); 316 client_proxy_->Detach();
323 client_proxy_ = NULL; 317 client_proxy_ = NULL;
324 318
325 DestroyTextures(); 319 DestroyTextures();
326 } 320 }
327 321
328 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 322 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
323 const ReadCB& read_cb) {
329 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 324 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
330 DCHECK(pending_reset_cb_.is_null()); 325 DCHECK(pending_reset_cb_.is_null());
331 DCHECK(pending_read_cb_.is_null()); 326 DCHECK(pending_read_cb_.is_null());
327
332 pending_read_cb_ = BindToCurrentLoop(read_cb); 328 pending_read_cb_ = BindToCurrentLoop(read_cb);
333 329
334 if (state_ == kError) { 330 if (state_ == kError) {
335 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 331 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
336 return; 332 return;
337 } 333 }
338 334
339 // TODO(xhwang): It's odd that we return kOk after VDA has been released.
340 // Fix this and simplify cases.
341 if (!vda_) { 335 if (!vda_) {
342 base::ResetAndReturn(&pending_read_cb_).Run( 336 base::ResetAndReturn(&pending_read_cb_).Run(
343 kOk, VideoFrame::CreateEmptyFrame()); 337 kDecodeError, VideoFrame::CreateEmptyFrame());
344 return; 338 return;
345 } 339 }
346 340
347 if (!ready_video_frames_.empty()) { 341 if (!ready_video_frames_.empty())
348 EnqueueFrameAndTriggerFrameDelivery(NULL); 342 EnqueueFrameAndTriggerFrameDelivery(NULL);
349 return; 343
344 if (buffer->IsEndOfStream()) {
345 if (state_ == kNormal) {
346 state_ = kDrainingDecoder;
347 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
348 &VideoDecodeAccelerator::Flush, weak_vda_));
349 }
350 } else {
351 size_t size = buffer->GetDataSize();
352 SHMBuffer* shm_buffer = GetSHM(size);
353 if (!shm_buffer) {
354 state_ = kError;
355 return;
356 }
357
358 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
359 BitstreamBuffer bitstream_buffer(
360 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
361 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
362 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
363 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
364 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
365 DCHECK(inserted);
366 RecordBufferData(bitstream_buffer, *buffer);
367
368 vda_loop_proxy_->PostTask(
369 FROM_HERE,
370 base::Bind(
371 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
350 } 372 }
351 373
374 if (CanMoreDecodeWorkBeDone()) {
375 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
376 }
377
378 /*
352 switch (state_) { 379 switch (state_) {
353 case kDecoderDrained: 380 case kDecoderDrained:
354 state_ = kNormal; 381 state_ = kNormal;
355 // Fall-through. 382 // Fall-through.
356 case kNormal: 383 case kNormal:
357 EnsureDemuxOrDecode(); 384 EnsureDemuxOrDecode();
358 break; 385 break;
359 case kDrainingDecoder: 386 case kDrainingDecoder:
360 // Do nothing. Will be satisfied either by a PictureReady or 387 // Do nothing. Will be satisfied either by a PictureReady or
361 // NotifyFlushDone below. 388 // NotifyFlushDone below.
362 break; 389 break;
363 case kError: 390 case kError:
364 NOTREACHED(); 391 NOTREACHED();
365 break; 392 break;
366 } 393 }
394 */
367 } 395 }
368 396
369 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { 397 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
370 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; 398 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
371 } 399 }
372 400
373 void GpuVideoDecoder::RequestBufferDecode( 401 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
374 DemuxerStream::Status status, 402 const DecoderBuffer& buffer) {
375 const scoped_refptr<DecoderBuffer>& buffer) { 403 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(),
376 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 404 buffer.GetTimestamp(),
377 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; 405 config_.visible_rect(),
378 406 config_.natural_size()));
379 demuxer_read_in_progress_ = false;
380
381 if (status == DemuxerStream::kAborted) {
382 if (pending_read_cb_.is_null())
383 return;
384 base::ResetAndReturn(&pending_read_cb_).Run(kOk, NULL);
385 return;
386 }
387
388 // VideoFrameStream ensures no kConfigChanged is passed to VideoDecoders.
389 DCHECK_EQ(status, DemuxerStream::kOk) << status;
390
391 if (!vda_) {
392 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
393 return;
394 }
395
396 if (buffer->IsEndOfStream()) {
397 if (state_ == kNormal) {
398 state_ = kDrainingDecoder;
399 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
400 &VideoDecodeAccelerator::Flush, weak_vda_));
401 }
402 return;
403 }
404
405 if (!pending_reset_cb_.is_null())
406 return;
407
408 size_t size = buffer->GetDataSize();
409 SHMBuffer* shm_buffer = GetSHM(size);
410 if (!shm_buffer)
411 return;
412
413 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
414 BitstreamBuffer bitstream_buffer(
415 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
416 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
417 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
418 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
419 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
420 DCHECK(inserted);
421 RecordBufferData(bitstream_buffer, *buffer);
422
423 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
424 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
425
426 if (CanMoreDecodeWorkBeDone()) {
427 // Force post here to prevent reentrancy into DemuxerStream.
428 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
429 &GpuVideoDecoder::EnsureDemuxOrDecode, weak_this_));
430 }
431 }
432
433 void GpuVideoDecoder::RecordBufferData(
434 const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) {
435 input_buffer_data_.push_front(BufferData(
436 bitstream_buffer.id(), buffer.GetTimestamp(),
437 demuxer_stream_->video_decoder_config().visible_rect(),
438 demuxer_stream_->video_decoder_config().natural_size()));
439 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but 407 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
440 // that's too small for some pathological B-frame test videos. The cost of 408 // that's too small for some pathological B-frame test videos. The cost of
441 // using too-high a value is low (192 bits per extra slot). 409 // using too-high a value is low (192 bits per extra slot).
442 static const size_t kMaxInputBufferDataSize = 128; 410 static const size_t kMaxInputBufferDataSize = 128;
443 // Pop from the back of the list, because that's the oldest and least likely 411 // Pop from the back of the list, because that's the oldest and least likely
444 // to be useful in the future data. 412 // to be useful in the future data.
445 if (input_buffer_data_.size() > kMaxInputBufferDataSize) 413 if (input_buffer_data_.size() > kMaxInputBufferDataSize)
446 input_buffer_data_.pop_back(); 414 input_buffer_data_.pop_back();
447 } 415 }
448 416
449 void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp, 417 void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
450 gfx::Rect* visible_rect, 418 gfx::Rect* visible_rect,
451 gfx::Size* natural_size) { 419 gfx::Size* natural_size) {
452 for (std::list<BufferData>::const_iterator it = 420 for (std::list<BufferData>::const_iterator it = input_buffer_data_.begin();
453 input_buffer_data_.begin(); it != input_buffer_data_.end(); 421 it != input_buffer_data_.end();
454 ++it) { 422 ++it) {
455 if (it->bitstream_buffer_id != id) 423 if (it->bitstream_buffer_id != id)
456 continue; 424 continue;
457 *timestamp = it->timestamp; 425 *timestamp = it->timestamp;
458 *visible_rect = it->visible_rect; 426 *visible_rect = it->visible_rect;
459 *natural_size = it->natural_size; 427 *natural_size = it->natural_size;
460 return; 428 return;
461 } 429 }
462 NOTREACHED() << "Missing bitstreambuffer id: " << id; 430 NOTREACHED() << "Missing bitstreambuffer id: " << id;
463 } 431 }
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 for (std::map<int32, BufferPair>::iterator it = 620 for (std::map<int32, BufferPair>::iterator it =
653 bitstream_buffers_in_decoder_.begin(); 621 bitstream_buffers_in_decoder_.begin();
654 it != bitstream_buffers_in_decoder_.end(); ++it) { 622 it != bitstream_buffers_in_decoder_.end(); ++it) {
655 it->second.shm_buffer->shm->Close(); 623 it->second.shm_buffer->shm->Close();
656 } 624 }
657 bitstream_buffers_in_decoder_.clear(); 625 bitstream_buffers_in_decoder_.clear();
658 626
659 DestroyTextures(); 627 DestroyTextures();
660 } 628 }
661 629
662 void GpuVideoDecoder::EnsureDemuxOrDecode() {
663 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
664
665 // The second condition can happen during the tear-down process.
666 // GpuVideoDecoder::Stop() returns the |pending_read_cb_| immediately without
667 // waiting for the demuxer read to be returned. Therefore, this function could
668 // be called even after the decoder has been stopped.
669 if (demuxer_read_in_progress_ || !demuxer_stream_)
670 return;
671
672 demuxer_read_in_progress_ = true;
673 demuxer_stream_->Read(base::Bind(
674 &GpuVideoDecoder::RequestBufferDecode, weak_this_));
675 }
676
677 void GpuVideoDecoder::NotifyFlushDone() { 630 void GpuVideoDecoder::NotifyFlushDone() {
678 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 631 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
679 DCHECK_EQ(state_, kDrainingDecoder); 632 DCHECK_EQ(state_, kDrainingDecoder);
680 state_ = kDecoderDrained; 633 state_ = kDecoderDrained;
681 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 634 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
682 } 635 }
683 636
684 void GpuVideoDecoder::NotifyResetDone() { 637 void GpuVideoDecoder::NotifyResetDone() {
685 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 638 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
686 DCHECK(ready_video_frames_.empty()); 639 DCHECK(ready_video_frames_.empty());
(...skipping 19 matching lines...) Expand all
706 659
707 state_ = kError; 660 state_ = kError;
708 661
709 if (!pending_read_cb_.is_null()) { 662 if (!pending_read_cb_.is_null()) {
710 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 663 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
711 return; 664 return;
712 } 665 }
713 } 666 }
714 667
715 } // namespace media 668 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698