15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/gpu_video_decoder.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <algorithm>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cpu.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/histogram.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/task_runner_util.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox_holder.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/bind_to_current_loop.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decoder_buffer.h"
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/media_log.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/base/media_switches.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline_status.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_decoder_config.h"
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/filters/gpu_video_accelerator_factories.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum number of concurrent VDA::Decode() operations GVD will maintain.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Higher values allow better pipelining in the GPU, but also require more
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resources.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kMaxInFlightDecodes = 4 };
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size of shared-memory segments we allocate.  Since we reuse them we let them
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be on the beefy side.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kSharedMemorySegmentBytes = 100 << 10;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : shm(m), size(s) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::SHMBuffer::~SHMBuffer() {}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer(
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SHMBuffer* s,
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const scoped_refptr<DecoderBuffer>& b,
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const DecodeCB& done_cb)
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : shm_buffer(s), buffer(b), done_cb(done_cb) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)GpuVideoDecoder::PendingDecoderBuffer::~PendingDecoderBuffer() {}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::BufferData::BufferData(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      natural_size(ns) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::BufferData::~BufferData() {}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::GpuVideoDecoder(
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const scoped_refptr<GpuVideoAcceleratorFactories>& factories,
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const scoped_refptr<MediaLog>& media_log)
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : needs_bitstream_conversion_(false),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factories_(factories),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(kNormal),
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      media_log_(media_log),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      decoder_texture_target_(0),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_picture_buffer_id_(0),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_bitstream_buffer_id_(0),
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      available_pictures_(0),
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      weak_factory_(this) {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(factories_.get());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::Reset(const base::Closure& closure)  {
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "Reset()";
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (state_ == kDrainingDecoder) {
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        FROM_HERE,
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::Bind(
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!vda_) {
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE, closure);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(pending_reset_cb_.is_null());
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_reset_cb_ = BindToCurrentLoop(closure);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  vda_->Reset();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid GpuVideoDecoder::Stop() {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (vda_)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DestroyVDA();
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(bitstream_buffers_in_decoder_.empty());
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!pending_reset_cb_.is_null())
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ResetAndReturn(&pending_reset_cb_).Run();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static bool IsCodedSizeSupported(const gfx::Size& coded_size) {
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Windows Media Foundation H.264 decoding does not support decoding videos
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // with any dimension smaller than 48 pixels:
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (coded_size.width() < 48 || coded_size.height() < 48)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080.
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We test against 1088 to account for 16x16 macroblocks.
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (coded_size.width() <= 1920 && coded_size.height() <= 1088)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // NOTE: additional autodetection logic may require updating input buffer size
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // selection in platform-specific implementations, such as
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // V4L2VideoDecodeAccelerator.
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::CPU cpu;
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool hw_large_video_support =
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode) ||
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ((cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 55);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool os_large_video_support = true;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  os_large_video_support = false;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return os_large_video_support && hw_large_video_support;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Report |status| to UMA and run |cb| with it.  This is super-specific to the
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// UMA stat reported because the UMA_HISTOGRAM_ENUMERATION API requires a
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// callsite to always be called with the same stat name (can't parameterize it).
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB(
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const PipelineStatusCB& cb,
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PipelineStatus status) {
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "Media.GpuVideoDecoderInitializeStatus", status, PIPELINE_STATUS_MAX + 1);
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  cb.Run(status);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                 bool /* low_delay */,
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 const PipelineStatusCB& orig_status_cb,
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 const OutputCB& output_cb) {
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "Initialize()";
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(config.IsValidConfig());
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!config.is_encrypted());
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PipelineStatusCB status_cb =
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB,
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 BindToCurrentLoop(orig_status_cb));
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool previously_initialized = config_.IsValidConfig();
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DVLOG(1) << "(Re)initializing GVD with config: "
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << config.AsHumanReadableString();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // TODO(posciak): destroy and create a new VDA on codec/profile change
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // (http://crbug.com/260224).
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (previously_initialized && (config_.profile() != config.profile())) {
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DVLOG(1) << "Codec or profile changed, cannot reinitialize.";
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!IsCodedSizeSupported(config.coded_size())) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  config_ = config;
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  needs_bitstream_conversion_ = (config.codec() == kCodecH264);
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  output_cb_ = BindToCurrentLoop(output_cb);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (previously_initialized) {
185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Reinitialization with a different config (but same codec and profile).
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // VDA should handle it by detecting this in-stream by itself,
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // no need to notify it.
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    status_cb.Run(PIPELINE_OK);
189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  vda_ = factories_->CreateVideoDecodeAccelerator().Pass();
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!vda_ || !vda_->Initialize(config.profile(), this)) {
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded.";
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_log_->SetStringProperty("video_decoder", "gpu");
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  status_cb.Run(PIPELINE_OK);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (PictureBufferMap::iterator it = buffers->begin(); it != buffers->end();
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++it) {
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    factories_->DeleteTexture(it->second.texture_id());
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffers->clear();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::DestroyVDA() {
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  vda_.reset();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // their textures may still be in use by the user of this GpuVideoDecoder.
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (PictureBufferTextureMap::iterator it =
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)           picture_buffers_at_display_.begin();
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       it != picture_buffers_at_display_.end();
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       ++it) {
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    assigned_picture_buffers_.erase(it->first);
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DestroyPictureBuffers(&assigned_picture_buffers_);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
230558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                             const DecodeCB& decode_cb) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(pending_reset_cb_.is_null());
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state_ == kError || !vda_) {
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bound_decode_cb.Run(kDecodeError);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kDecoderDrained:
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = kNormal;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Fall-through.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kNormal:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kDrainingDecoder:
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kError:
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_EQ(state_, kNormal);
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (buffer->end_of_stream()) {
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    state_ = kDrainingDecoder;
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    eos_decode_cb_ = bound_decode_cb;
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    vda_->Flush();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  size_t size = buffer->data_size();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHMBuffer* shm_buffer = GetSHM(size);
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!shm_buffer) {
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bound_decode_cb.Run(kDecodeError);
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  memcpy(shm_buffer->shm->memory(), buffer->data(), size);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BitstreamBuffer bitstream_buffer(
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!ContainsKey(bitstream_buffers_in_decoder_, bitstream_buffer.id()));
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bitstream_buffers_in_decoder_.insert(
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      std::make_pair(bitstream_buffer.id(),
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     PendingDecoderBuffer(shm_buffer, buffer, decode_cb)));
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_LE(static_cast<int>(bitstream_buffers_in_decoder_.size()),
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            kMaxInFlightDecodes);
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RecordBufferData(bitstream_buffer, *buffer.get());
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  vda_->Decode(bitstream_buffer);
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       const DecoderBuffer& buffer) {
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  input_buffer_data_.push_front(BufferData(bitstream_buffer.id(),
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                           buffer.timestamp(),
2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           config_.visible_rect(),
2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           config_.natural_size()));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Why this value?  Because why not.  avformat.h:MAX_REORDER_DELAY is 16, but
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that's too small for some pathological B-frame test videos.  The cost of
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using too-high a value is low (192 bits per extra slot).
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kMaxInputBufferDataSize = 128;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pop from the back of the list, because that's the oldest and least likely
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be useful in the future data.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (input_buffer_data_.size() > kMaxInputBufferDataSize)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_buffer_data_.pop_back();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    gfx::Rect* visible_rect,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    gfx::Size* natural_size) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::list<BufferData>::const_iterator it =
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           input_buffer_data_.begin(); it != input_buffer_data_.end();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->bitstream_buffer_id != id)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *timestamp = it->timestamp;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *visible_rect = it->visible_rect;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *natural_size = it->natural_size;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Missing bitstreambuffer id: " << id;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool GpuVideoDecoder::NeedsBitstreamConversion() const {
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return needs_bitstream_conversion_;
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool GpuVideoDecoder::CanReadWithoutStalling() const {
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      next_picture_buffer_id_ == 0 ||  // Decode() will ProvidePictureBuffers().
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      available_pictures_ > 0;
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int GpuVideoDecoder::GetMaxDecodeRequests() const {
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return kMaxInFlightDecodes;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const gfx::Size& size,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            uint32 texture_target) {
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "ProvidePictureBuffers(" << count << ", "
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           << size.width() << "x" << size.height() << ")";
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint32> texture_ids;
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<gpu::Mailbox> texture_mailboxes;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_texture_target_ = texture_target;
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!factories_->CreateTextures(count,
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  size,
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  &texture_ids,
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  &texture_mailboxes,
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  decoder_texture_target_)) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(count, texture_ids.size());
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_EQ(count, texture_mailboxes.size());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!vda_)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PictureBuffer> picture_buffers;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < texture_ids.size(); ++i) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture_buffers.push_back(PictureBuffer(
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i]));
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool inserted = assigned_picture_buffers_.insert(std::make_pair(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        picture_buffers.back().id(), picture_buffers.back())).second;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(inserted);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  available_pictures_ += count;
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
368bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  vda_->AssignPictureBuffers(picture_buffers);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "DismissPictureBuffer(" << id << ")";
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PictureBufferMap::iterator it = assigned_picture_buffers_.find(id);
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == assigned_picture_buffers_.end()) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Missing picture buffer: " << id;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PictureBuffer buffer_to_dismiss = it->second;
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  assigned_picture_buffers_.erase(it);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
38423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!picture_buffers_at_display_.count(id)) {
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // We can delete the texture immediately as it's not being displayed.
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    factories_->DeleteTexture(buffer_to_dismiss.texture_id());
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CHECK_GT(available_pictures_, 0);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    --available_pictures_;
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
39023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Not destroying a texture in display in |picture_buffers_at_display_|.
39123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Postpone deletion until after it's returned to us.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void ReadPixelsSyncInner(
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint32 texture_id,
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Rect& visible_rect,
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const SkBitmap& pixels,
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::WaitableEvent* event) {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories->ReadPixels(texture_id, visible_rect, pixels);
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  event->Signal();
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void ReadPixelsSync(
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint32 texture_id,
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Rect& visible_rect,
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const SkBitmap& pixels) {
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WaitableEvent event(true, false);
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!factories->GetTaskRunner()->PostTask(FROM_HERE,
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            base::Bind(&ReadPixelsSyncInner,
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       factories,
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       texture_id,
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       visible_rect,
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       pixels,
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       &event)))
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  event.Wait();
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "PictureReady()";
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PictureBufferMap::iterator it =
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      assigned_picture_buffers_.find(picture.picture_buffer_id());
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == assigned_picture_buffers_.end()) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PictureBuffer& pb = it->second;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update frame's timestamp.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta timestamp;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect visible_rect;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size natural_size;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &natural_size);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(decoder_texture_target_);
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
442a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture(
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      make_scoped_ptr(new gpu::MailboxHolder(
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          pb.texture_mailbox(), decoder_texture_target_, 0 /* sync_point */)),
44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReleaseMailbox,
44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   weak_factory_.GetWeakPtr(),
44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   factories_,
44823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   picture.picture_buffer_id(),
44923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   pb.texture_id())),
450a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      pb.size(),
451a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      visible_rect,
452a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      natural_size,
453a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      timestamp,
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)));
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_GT(available_pictures_, 0);
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  --available_pictures_;
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool inserted =
45823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      picture_buffers_at_display_.insert(std::make_pair(
45923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                             picture.picture_buffer_id(),
46023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                             pb.texture_id())).second;
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(inserted);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DeliverFrame(frame);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuVideoDecoder::DeliverFrame(
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<VideoFrame>& frame) {
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // During a pending vda->Reset(), we don't accumulate frames.  Drop it on the
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // floor and return.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_reset_cb_.is_null())
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  output_cb_.Run(frame);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
47923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void GpuVideoDecoder::ReleaseMailbox(
48023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::WeakPtr<GpuVideoDecoder> decoder,
48123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 picture_buffer_id,
48323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    uint32 texture_id,
4845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::vector<uint32>& release_sync_points) {
48523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
4865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < release_sync_points.size(); i++)
4885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    factories->WaitSyncPoint(release_sync_points[i]);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (decoder) {
49123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    decoder->ReusePictureBuffer(picture_buffer_id);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
49323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
49423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // It's the last chance to delete the texture after display,
49523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // because GpuVideoDecoder was destructed.
49623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  factories->DeleteTexture(texture_id);
49723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
49923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
50023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")";
50123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
50323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!picture_buffers_at_display_.empty());
50423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  PictureBufferTextureMap::iterator display_iterator =
50523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      picture_buffers_at_display_.find(picture_buffer_id);
50623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  uint32 texture_id = display_iterator->second;
50723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(display_iterator != picture_buffers_at_display_.end());
50823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  picture_buffers_at_display_.erase(display_iterator);
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!assigned_picture_buffers_.count(picture_buffer_id)) {
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // This picture was dismissed while in display, so we postponed deletion.
51223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    factories_->DeleteTexture(texture_id);
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ++available_pictures_;
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // DestroyVDA() might already have been called.
51923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (vda_)
52023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    vda_->ReusePictureBuffer(picture_buffer_id);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) {
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (available_shm_segments_.empty() ||
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      available_shm_segments_.back()->size < min_size) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate);
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // CreateSharedMemory() can return NULL during Shutdown.
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!shm)
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return NULL;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new SHMBuffer(shm, size_to_allocate);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHMBuffer* ret = available_shm_segments_.back();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  available_shm_segments_.pop_back();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) {
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  available_shm_segments_.push_back(shm_buffer);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")";
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::map<int32, PendingDecoderBuffer>::iterator it =
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitstream_buffers_in_decoder_.find(id);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == bitstream_buffers_in_decoder_.end()) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Missing bitstream buffer: " << id;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PutSHM(it->second.shm_buffer);
557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  it->second.done_cb.Run(state_ == kError ? kDecodeError : kOk);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffers_in_decoder_.erase(it);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecoder::~GpuVideoDecoder() {
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
56323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Stop should have been already called.
56423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!vda_.get() && assigned_picture_buffers_.empty());
565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(bitstream_buffers_in_decoder_.empty());
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < available_shm_segments_.size(); ++i) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    available_shm_segments_[i]->shm->Close();
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete available_shm_segments_[i];
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  available_shm_segments_.clear();
571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (std::map<int32, PendingDecoderBuffer>::iterator it =
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           bitstream_buffers_in_decoder_.begin();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != bitstream_buffers_in_decoder_.end(); ++it) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second.shm_buffer->shm->Close();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitstream_buffers_in_decoder_.clear();
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::NotifyFlushDone() {
5807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "NotifyFlushDone()";
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, kDrainingDecoder);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kDecoderDrained;
584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::ResetAndReturn(&eos_decode_cb_).Run(kOk);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::NotifyResetDone() {
5887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(3) << "NotifyResetDone()";
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(bitstream_buffers_in_decoder_.empty());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This needs to happen after the Reset() on vda_ is done to ensure pictures
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delivered during the reset can find their time data.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  input_buffer_data_.clear();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_reset_cb_.is_null())
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ResetAndReturn(&pending_reset_cb_).Run();
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!vda_)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_ = kError;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DLOG(ERROR) << "VDA Error: " << error;
608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DestroyVDA();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const {
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
617