<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/filters/gpu_video_decoder.h"

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
#include "media/base/pipeline_status.h"
#include "media/base/video_decoder_config.h"
#include "media/ffmpeg/ffmpeg_common.h"

namespace media {

GpuVideoDecoder::Factories::~Factories() {}

// Size of shared-memory segments we allocate.  Since we reuse them we let them
// be on the beefy side.
static const size_t kSharedMemorySegmentBytes = 100 << 10;

GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s)
    : shm(m), size(s) {
}

GpuVideoDecoder::SHMBuffer::~SHMBuffer() {}

GpuVideoDecoder::BufferPair::BufferPair(
    SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b)
    : shm_buffer(s), buffer(b) {
}

GpuVideoDecoder::BufferPair::~BufferPair() {}

GpuVideoDecoder::BufferTimeData::BufferTimeData(
    int32 bbid, base::TimeDelta ts, base::TimeDelta dur)
    : bitstream_buffer_id(bbid), timestamp(ts), duration(dur) {
}

GpuVideoDecoder::BufferTimeData::~BufferTimeData() {}

GpuVideoDecoder::GpuVideoDecoder(
    MessageLoop* message_loop,
    MessageLoop* vda_loop,
    const scoped_refptr<Factories>& factories)
    : gvd_loop_proxy_(message_loop->message_loop_proxy()),
      vda_loop_proxy_(vda_loop->message_loop_proxy()),
      factories_(factories),
      state_(kNormal),
      demuxer_read_in_progress_(false),
      decoder_texture_target_(0),
      next_picture_buffer_id_(0),
      next_bitstream_buffer_id_(0),
      shutting_down_(false),
      error_occured_(false) {
  DCHECK(gvd_loop_proxy_ && factories_);
}

void GpuVideoDecoder::Reset(const base::Closure& closure)  {
  if (!gvd_loop_proxy_->BelongsToCurrentThread() ||
      state_ == kDrainingDecoder) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Reset, this, closure));
    return;
  }

  // Throw away any already-decoded, not-yet-delivered frames.
  ready_video_frames_.clear();

  if (!vda_.get()) {
    closure.Run();
    return;
  }

  DCHECK(pending_reset_cb_.is_null());
  DCHECK(!closure.is_null());

  // VideoRendererBase::Flush() can't complete while it has a pending read to
  // us, so we fulfill such a read here.
  if (!pending_read_cb_.is_null())
    EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());

  if (shutting_down_) {
    // Immediately fire the callback instead of waiting for the reset to
    // complete (which will happen after PipelineImpl::Stop() completes).
    gvd_loop_proxy_->PostTask(FROM_HERE, closure);
  } else {
    pending_reset_cb_ = closure;
  }

  vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
      &VideoDecodeAccelerator::Reset, weak_vda_));
}

void GpuVideoDecoder::Stop(const base::Closure& closure) {
  if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Stop, this, closure));
    return;
  }
  if (!vda_.get()) {
    closure.Run();
    return;
  }
  VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
  vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
      &VideoDecodeAccelerator::Destroy, weak_vda_));
  closure.Run();
}

void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
                                 const PipelineStatusCB& orig_status_cb,
                                 const StatisticsCB& statistics_cb) {
  if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Initialize,
        this, stream, orig_status_cb, statistics_cb));
    return;
  }

  PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
      "Media.GpuVideoDecoderInitializeStatus", orig_status_cb);<commit_msg>Delay deleting GpuVideoDecoder until after GpuVideoDecodeAcceleratorHost::Destroy() fires.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/filters/gpu_video_decoder.h"

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
#include "media/base/pipeline_status.h"
#include "media/base/video_decoder_config.h"
#include "media/ffmpeg/ffmpeg_common.h"

namespace media {

GpuVideoDecoder::Factories::~Factories() {}

// Size of shared-memory segments we allocate.  Since we reuse them we let them
// be on the beefy side.
static const size_t kSharedMemorySegmentBytes = 100 << 10;

GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s)
    : shm(m), size(s) {
}

GpuVideoDecoder::SHMBuffer::~SHMBuffer() {}

GpuVideoDecoder::BufferPair::BufferPair(
    SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b)
    : shm_buffer(s), buffer(b) {
}

GpuVideoDecoder::BufferPair::~BufferPair() {}

GpuVideoDecoder::BufferTimeData::BufferTimeData(
    int32 bbid, base::TimeDelta ts, base::TimeDelta dur)
    : bitstream_buffer_id(bbid), timestamp(ts), duration(dur) {
}

GpuVideoDecoder::BufferTimeData::~BufferTimeData() {}

GpuVideoDecoder::GpuVideoDecoder(
    MessageLoop* message_loop,
    MessageLoop* vda_loop,
    const scoped_refptr<Factories>& factories)
    : gvd_loop_proxy_(message_loop->message_loop_proxy()),
      vda_loop_proxy_(vda_loop->message_loop_proxy()),
      factories_(factories),
      state_(kNormal),
      demuxer_read_in_progress_(false),
      decoder_texture_target_(0),
      next_picture_buffer_id_(0),
      next_bitstream_buffer_id_(0),
      shutting_down_(false),
      error_occured_(false) {
  DCHECK(gvd_loop_proxy_ && factories_);
}

void GpuVideoDecoder::Reset(const base::Closure& closure)  {
  if (!gvd_loop_proxy_->BelongsToCurrentThread() ||
      state_ == kDrainingDecoder) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Reset, this, closure));
    return;
  }

  // Throw away any already-decoded, not-yet-delivered frames.
  ready_video_frames_.clear();

  if (!vda_.get()) {
    closure.Run();
    return;
  }

  DCHECK(pending_reset_cb_.is_null());
  DCHECK(!closure.is_null());

  // VideoRendererBase::Flush() can't complete while it has a pending read to
  // us, so we fulfill such a read here.
  if (!pending_read_cb_.is_null())
    EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());

  if (shutting_down_) {
    // Immediately fire the callback instead of waiting for the reset to
    // complete (which will happen after PipelineImpl::Stop() completes).
    gvd_loop_proxy_->PostTask(FROM_HERE, closure);
  } else {
    pending_reset_cb_ = closure;
  }

  vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
      &VideoDecodeAccelerator::Reset, weak_vda_));
}

void GpuVideoDecoder::Stop(const base::Closure& closure) {
  if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Stop, this, closure));
    return;
  }
  if (!vda_.get()) {
    closure.Run();
    return;
  }
  VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
  // Tricky: |this| needs to stay alive until after VDA::Destroy is actually
  // called, not just posted.  We can't simply PostTaskAndReply using |closure|
  // as the |reply| because we might be called while the renderer thread
  // (a.k.a. vda_loop_proxy_) is paused (during WebMediaPlayerImpl::Destroy()),
  // which would result in an apparent hang.  Instead, we take an artificial ref
  // to |this| and release it as |reply| after VDA::Destroy returns.
  AddRef();
  vda_loop_proxy_->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_),
      base::Bind(&GpuVideoDecoder::Release, this));
  closure.Run();
}

void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
                                 const PipelineStatusCB& orig_status_cb,
                                 const StatisticsCB& statistics_cb) {
  if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
    gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
        &GpuVideoDecoder::Initialize,
        this, stream, orig_status_cb, statistics_cb));
    return;
  }

  PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
      "Media.GpuVideoDecoderInitializeStatus", orig_status_cb);
{'fraction_non_alphanumeric': 0.12110091743119267, 'fraction_numerical': 0.003211009174311927, 'mean_word_length': 4.4608641202254224, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1667532', 'n_tokens_mistral': 2887, 'n_tokens_neox': 2852, 'n_words': 574}