| Index: media/filters/gpu_video_decoder.cc
|
| diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
|
| index 8ea4fc68e179e7e819630686061479fb6eced39f..a76a714b399a39211895dcf2f9372e9555f8de92 100644
|
| --- a/media/filters/gpu_video_decoder.cc
|
| +++ b/media/filters/gpu_video_decoder.cc
|
| @@ -12,7 +12,6 @@
|
| #include "base/task_runner_util.h"
|
| #include "media/base/bind_to_loop.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"
|
| @@ -160,19 +159,18 @@ GpuVideoDecoder::BufferData::~BufferData() {}
|
| GpuVideoDecoder::GpuVideoDecoder(
|
| const scoped_refptr<base::MessageLoopProxy>& message_loop,
|
| const scoped_refptr<Factories>& factories)
|
| - : demuxer_stream_(NULL),
|
| - needs_bitstream_conversion_(false),
|
| + : needs_bitstream_conversion_(false),
|
| gvd_loop_proxy_(message_loop),
|
| weak_factory_(this),
|
| vda_loop_proxy_(factories->GetMessageLoop()),
|
| factories_(factories),
|
| state_(kNormal),
|
| - demuxer_read_in_progress_(false),
|
| decoder_texture_target_(0),
|
| next_picture_buffer_id_(0),
|
| next_bitstream_buffer_id_(0),
|
| available_pictures_(-1) {
|
| DCHECK(factories_);
|
| + DCHECK(!config_.IsValidConfig());
|
| }
|
|
|
| void GpuVideoDecoder::Reset(const base::Closure& closure) {
|
| @@ -214,7 +212,6 @@ void GpuVideoDecoder::Stop(const base::Closure& closure) {
|
| EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
|
| if (!pending_reset_cb_.is_null())
|
| base::ResetAndReturn(&pending_reset_cb_).Run();
|
| - demuxer_stream_ = NULL;
|
| BindToCurrentLoop(closure).Run();
|
| }
|
|
|
| @@ -234,11 +231,12 @@ static bool IsCodedSizeSupported(const gfx::Size& coded_size) {
|
| return os_large_video_support && hw_large_video_support;
|
| }
|
|
|
| -void GpuVideoDecoder::Initialize(DemuxerStream* stream,
|
| +void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
|
| const PipelineStatusCB& orig_status_cb,
|
| const StatisticsCB& statistics_cb) {
|
| DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
|
| - DCHECK(stream);
|
| + DCHECK(config.IsValidConfig());
|
| + DCHECK(!config.is_encrypted());
|
|
|
| weak_this_ = weak_factory_.GetWeakPtr();
|
|
|
| @@ -246,7 +244,7 @@ void GpuVideoDecoder::Initialize(DemuxerStream* stream,
|
| "Media.GpuVideoDecoderInitializeStatus",
|
| BindToCurrentLoop(orig_status_cb));
|
|
|
| - if (demuxer_stream_) {
|
| + if (config_.IsValidConfig()) {
|
| // TODO(xhwang): Make GpuVideoDecoder reinitializable.
|
| // See http://crbug.com/233608
|
| DVLOG(1) << "GpuVideoDecoder reinitialization not supported.";
|
| @@ -254,10 +252,6 @@ void GpuVideoDecoder::Initialize(DemuxerStream* stream,
|
| return;
|
| }
|
|
|
| - const VideoDecoderConfig& config = stream->video_decoder_config();
|
| - DCHECK(config.IsValidConfig());
|
| - DCHECK(!config.is_encrypted());
|
| -
|
| if (!IsCodedSizeSupported(config.coded_size())) {
|
| status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
|
| return;
|
| @@ -271,7 +265,6 @@ void GpuVideoDecoder::Initialize(DemuxerStream* stream,
|
| return;
|
| }
|
|
|
| - demuxer_stream_ = stream;
|
| statistics_cb_ = statistics_cb;
|
| needs_bitstream_conversion_ = (config.codec() == kCodecH264);
|
|
|
| @@ -295,8 +288,9 @@ void GpuVideoDecoder::SetVDA(
|
|
|
| void GpuVideoDecoder::DestroyTextures() {
|
| for (std::map<int32, PictureBuffer>::iterator it =
|
| - picture_buffers_in_decoder_.begin();
|
| - it != picture_buffers_in_decoder_.end(); ++it) {
|
| + picture_buffers_in_decoder_.begin();
|
| + it != picture_buffers_in_decoder_.end();
|
| + ++it) {
|
| factories_->DeleteTexture(it->second.texture_id());
|
| }
|
| picture_buffers_in_decoder_.clear();
|
| @@ -325,10 +319,12 @@ void GpuVideoDecoder::DestroyVDA() {
|
| DestroyTextures();
|
| }
|
|
|
| -void GpuVideoDecoder::Read(const ReadCB& read_cb) {
|
| +void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
|
| + const ReadCB& read_cb) {
|
| DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
|
| DCHECK(pending_reset_cb_.is_null());
|
| DCHECK(pending_read_cb_.is_null());
|
| +
|
| pending_read_cb_ = BindToCurrentLoop(read_cb);
|
|
|
| if (state_ == kError) {
|
| @@ -336,19 +332,50 @@ void GpuVideoDecoder::Read(const ReadCB& read_cb) {
|
| return;
|
| }
|
|
|
| - // TODO(xhwang): It's odd that we return kOk after VDA has been released.
|
| - // Fix this and simplify cases.
|
| if (!vda_) {
|
| base::ResetAndReturn(&pending_read_cb_).Run(
|
| - kOk, VideoFrame::CreateEmptyFrame());
|
| + kDecodeError, VideoFrame::CreateEmptyFrame());
|
| return;
|
| }
|
|
|
| - if (!ready_video_frames_.empty()) {
|
| + if (!ready_video_frames_.empty())
|
| EnqueueFrameAndTriggerFrameDelivery(NULL);
|
| - return;
|
| +
|
| + if (buffer->IsEndOfStream()) {
|
| + if (state_ == kNormal) {
|
| + state_ = kDrainingDecoder;
|
| + vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
|
| + &VideoDecodeAccelerator::Flush, weak_vda_));
|
| + }
|
| + } else {
|
| + size_t size = buffer->GetDataSize();
|
| + SHMBuffer* shm_buffer = GetSHM(size);
|
| + if (!shm_buffer) {
|
| + state_ = kError;
|
| + return;
|
| + }
|
| +
|
| + memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
|
| + BitstreamBuffer bitstream_buffer(
|
| + next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
|
| + // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
|
| + next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
|
| + bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
|
| + bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
|
| + DCHECK(inserted);
|
| + RecordBufferData(bitstream_buffer, *buffer);
|
| +
|
| + vda_loop_proxy_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
|
| + }
|
| +
|
| + if (CanMoreDecodeWorkBeDone()) {
|
| + base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
|
| }
|
|
|
| +/*
|
| switch (state_) {
|
| case kDecoderDrained:
|
| state_ = kNormal;
|
| @@ -364,78 +391,19 @@ void GpuVideoDecoder::Read(const ReadCB& read_cb) {
|
| NOTREACHED();
|
| break;
|
| }
|
| +*/
|
| }
|
|
|
| bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
|
| return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
|
| }
|
|
|
| -void GpuVideoDecoder::RequestBufferDecode(
|
| - DemuxerStream::Status status,
|
| - const scoped_refptr<DecoderBuffer>& buffer) {
|
| - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
|
| - DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
|
| -
|
| - demuxer_read_in_progress_ = false;
|
| -
|
| - if (status == DemuxerStream::kAborted) {
|
| - if (pending_read_cb_.is_null())
|
| - return;
|
| - base::ResetAndReturn(&pending_read_cb_).Run(kOk, NULL);
|
| - return;
|
| - }
|
| -
|
| - // VideoFrameStream ensures no kConfigChanged is passed to VideoDecoders.
|
| - DCHECK_EQ(status, DemuxerStream::kOk) << status;
|
| -
|
| - if (!vda_) {
|
| - EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
|
| - return;
|
| - }
|
| -
|
| - if (buffer->IsEndOfStream()) {
|
| - if (state_ == kNormal) {
|
| - state_ = kDrainingDecoder;
|
| - vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
|
| - &VideoDecodeAccelerator::Flush, weak_vda_));
|
| - }
|
| - return;
|
| - }
|
| -
|
| - if (!pending_reset_cb_.is_null())
|
| - return;
|
| -
|
| - size_t size = buffer->GetDataSize();
|
| - SHMBuffer* shm_buffer = GetSHM(size);
|
| - if (!shm_buffer)
|
| - return;
|
| -
|
| - memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
|
| - BitstreamBuffer bitstream_buffer(
|
| - next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
|
| - // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
|
| - next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
|
| - bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
|
| - bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
|
| - DCHECK(inserted);
|
| - RecordBufferData(bitstream_buffer, *buffer);
|
| -
|
| - vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
|
| - &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
|
| -
|
| - if (CanMoreDecodeWorkBeDone()) {
|
| - // Force post here to prevent reentrancy into DemuxerStream.
|
| - gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
|
| - &GpuVideoDecoder::EnsureDemuxOrDecode, weak_this_));
|
| - }
|
| -}
|
| -
|
| -void GpuVideoDecoder::RecordBufferData(
|
| - const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) {
|
| - input_buffer_data_.push_front(BufferData(
|
| - bitstream_buffer.id(), buffer.GetTimestamp(),
|
| - demuxer_stream_->video_decoder_config().visible_rect(),
|
| - demuxer_stream_->video_decoder_config().natural_size()));
|
| +void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
|
| + const DecoderBuffer& buffer) {
|
| + input_buffer_data_.push_front(BufferData(bitstream_buffer.id(),
|
| + buffer.GetTimestamp(),
|
| + config_.visible_rect(),
|
| + config_.natural_size()));
|
| // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
|
| // that's too small for some pathological B-frame test videos. The cost of
|
| // using too-high a value is low (192 bits per extra slot).
|
| @@ -449,8 +417,8 @@ void GpuVideoDecoder::RecordBufferData(
|
| void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
|
| gfx::Rect* visible_rect,
|
| gfx::Size* natural_size) {
|
| - for (std::list<BufferData>::const_iterator it =
|
| - input_buffer_data_.begin(); it != input_buffer_data_.end();
|
| + for (std::list<BufferData>::const_iterator it = input_buffer_data_.begin();
|
| + it != input_buffer_data_.end();
|
| ++it) {
|
| if (it->bitstream_buffer_id != id)
|
| continue;
|
| @@ -659,21 +627,6 @@ GpuVideoDecoder::~GpuVideoDecoder() {
|
| DestroyTextures();
|
| }
|
|
|
| -void GpuVideoDecoder::EnsureDemuxOrDecode() {
|
| - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
|
| -
|
| - // The second condition can happen during the tear-down process.
|
| - // GpuVideoDecoder::Stop() returns the |pending_read_cb_| immediately without
|
| - // waiting for the demuxer read to be returned. Therefore, this function could
|
| - // be called even after the decoder has been stopped.
|
| - if (demuxer_read_in_progress_ || !demuxer_stream_)
|
| - return;
|
| -
|
| - demuxer_read_in_progress_ = true;
|
| - demuxer_stream_->Read(base::Bind(
|
| - &GpuVideoDecoder::RequestBufferDecode, weak_this_));
|
| -}
|
| -
|
| void GpuVideoDecoder::NotifyFlushDone() {
|
| DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
|
| DCHECK_EQ(state_, kDrainingDecoder);
|
|
|