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

Unified 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: fix win64 Created 7 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/video_decoder_selector.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/gpu_video_decoder.cc
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index 8cf51ad101a76c7a78aaec78ca20b916dd43b8a5..fcb837d005fd167089447a6dc070505b01945709 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -4,6 +4,8 @@
#include "media/filters/gpu_video_decoder.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/cpu.h"
@@ -12,7 +14,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,14 +161,12 @@ 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),
@@ -176,6 +175,7 @@ GpuVideoDecoder::GpuVideoDecoder(
}
void GpuVideoDecoder::Reset(const base::Closure& closure) {
+ DVLOG(3) << "Reset()";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
if (state_ == kDrainingDecoder && !factories_->IsAborted()) {
@@ -214,7 +214,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 +233,13 @@ 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) {
+ DVLOG(3) << "Initialize()";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
- DCHECK(stream);
+ DCHECK(config.IsValidConfig());
+ DCHECK(!config.is_encrypted());
weak_this_ = weak_factory_.GetWeakPtr();
@@ -246,7 +247,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 +255,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,11 +268,11 @@ void GpuVideoDecoder::Initialize(DemuxerStream* stream,
return;
}
- demuxer_stream_ = stream;
+ config_ = config;
statistics_cb_ = statistics_cb;
needs_bitstream_conversion_ = (config.codec() == kCodecH264);
- DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
+ DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded.";
PostTaskAndReplyWithResult(
vda_loop_proxy_.get(),
FROM_HERE,
@@ -333,72 +330,37 @@ 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) {
+ if (state_ == kError || !vda_) {
base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
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());
- return;
- }
-
- if (!ready_video_frames_.empty()) {
- EnqueueFrameAndTriggerFrameDelivery(NULL);
- return;
- }
-
switch (state_) {
case kDecoderDrained:
+ if (!ready_video_frames_.empty()) {
+ EnqueueFrameAndTriggerFrameDelivery(NULL);
+ return;
+ }
state_ = kNormal;
// Fall-through.
case kNormal:
- EnsureDemuxOrDecode();
break;
case kDrainingDecoder:
+ DCHECK(buffer->IsEndOfStream());
// Do nothing. Will be satisfied either by a PictureReady or
// NotifyFlushDone below.
- break;
+ return;
case kError:
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.get()) << 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()) {
@@ -410,13 +372,12 @@ void GpuVideoDecoder::RequestBufferDecode(
return;
}
- if (!pending_reset_cb_.is_null())
- return;
-
size_t size = buffer->GetDataSize();
SHMBuffer* shm_buffer = GetSHM(size);
- if (!shm_buffer)
+ if (!shm_buffer) {
+ base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
return;
+ }
memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
BitstreamBuffer bitstream_buffer(
@@ -431,19 +392,25 @@ void GpuVideoDecoder::RequestBufferDecode(
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_));
+ if (!ready_video_frames_.empty()) {
+ EnqueueFrameAndTriggerFrameDelivery(NULL);
+ return;
}
+
+ if (CanMoreDecodeWorkBeDone())
+ base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
+}
+
+bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
+ return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
}
-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).
@@ -492,6 +459,8 @@ void GpuVideoDecoder::NotifyInitializeDone() {
void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
const gfx::Size& size,
uint32 texture_target) {
+ DVLOG(3) << "ProvidePictureBuffers(" << count << ", "
+ << size.width() << "x" << size.height() << ")";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
std::vector<uint32> texture_ids;
@@ -530,6 +499,7 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
}
void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
+ DVLOG(3) << "DismissPictureBuffer(" << id << ")";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
std::map<int32, PictureBuffer>::iterator it =
@@ -559,6 +529,7 @@ void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
}
void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
+ DVLOG(3) << "PictureReady()";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
std::map<int32, PictureBuffer>::iterator it =
@@ -625,6 +596,7 @@ void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery(
void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
uint32 sync_point) {
+ DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
if (!vda_)
@@ -648,7 +620,6 @@ void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
}
factories_->WaitSyncPoint(sync_point);
-
++available_pictures_;
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
@@ -678,6 +649,7 @@ void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) {
}
void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
+ DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
std::map<int32, BufferPair>::iterator it =
@@ -698,8 +670,8 @@ void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
bitstream_buffers_in_decoder_.erase(it);
if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder &&
- CanMoreDecodeWorkBeDone()) {
- EnsureDemuxOrDecode();
+ CanMoreDecodeWorkBeDone() && !pending_read_cb_.is_null()) {
+ base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
}
}
@@ -721,22 +693,8 @@ 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() {
+ DVLOG(3) << "NotifyFlushDone()";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
DCHECK_EQ(state_, kDrainingDecoder);
state_ = kDecoderDrained;
@@ -744,6 +702,7 @@ void GpuVideoDecoder::NotifyFlushDone() {
}
void GpuVideoDecoder::NotifyResetDone() {
+ DVLOG(3) << "NotifyResetDone()";
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
DCHECK(ready_video_frames_.empty());
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/video_decoder_selector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698