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

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

Issue 15085011: Add FakeVideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/fake_video_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/message_loop_proxy.h"
11 #include "media/base/bind_to_loop.h"
12 #include "media/base/demuxer_stream.h"
13
14 namespace media {
15
16 FakeVideoDecoder::FakeVideoDecoder(int decoding_delay)
17 : message_loop_(base::MessageLoopProxy::current()),
18 weak_factory_(this),
19 decoding_delay_(decoding_delay),
20 state_(UNINITIALIZED),
21 demuxer_stream_(NULL) {
22 DCHECK_GE(decoding_delay, 0);
23 }
24
25 FakeVideoDecoder::~FakeVideoDecoder() {
26 DCHECK_EQ(state_, UNINITIALIZED);
27 }
28
29 void FakeVideoDecoder::Initialize(DemuxerStream* stream,
30 const PipelineStatusCB& status_cb,
31 const StatisticsCB& statistics_cb) {
32 DCHECK(message_loop_->BelongsToCurrentThread());
33 DCHECK(stream);
34 DCHECK(stream->video_decoder_config().IsValidConfig());
35 DCHECK(read_cb_.is_null()) << "No reinitialization during pending read.";
36 DCHECK(reset_cb_.is_null()) << "No reinitialization during pending reset.";
37
38 weak_this_ = weak_factory_.GetWeakPtr();
39
40 demuxer_stream_ = stream;
41 statistics_cb_ = statistics_cb;
42 current_config_ = stream->video_decoder_config();
43
44 if (!decoded_frames_.empty()) {
45 LOG(INFO) << "Decoded frames dropped during reinitialization.";
scherkus (not reviewing) 2013/05/09 20:07:09 does this have to be LOG(INFO)?
xhwang 2013/05/22 04:29:42 Done.
46 decoded_frames_.clear();
47 }
48
49 state_ = NORMAL;
50 // TODO(xhwang): Make initialization callback holdable using CallbackHolder.
51 message_loop_->PostTask(FROM_HERE, base::Bind(status_cb, PIPELINE_OK));
52 }
53
54 void FakeVideoDecoder::Read(const ReadCB& read_cb) {
55 DCHECK(message_loop_->BelongsToCurrentThread());
56 DCHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
57 DCHECK(reset_cb_.is_null());
58 DCHECK_LE(decoded_frames_.size(), static_cast<size_t>(decoding_delay_));
59
60 read_cb_.SetCallback(BindToCurrentLoop(read_cb));
61 ReadFromDemuxerStream();
62 }
63
64 void FakeVideoDecoder::Reset(const base::Closure& closure) {
65 DCHECK(message_loop_->BelongsToCurrentThread());
66 DCHECK(reset_cb_.is_null());
67 reset_cb_.SetCallback(BindToCurrentLoop(closure));
68
69 // Defer the reset if a read is pending.
70 if (!read_cb_.is_null())
71 return;
72
73 DoReset();
74 }
75
76 void FakeVideoDecoder::Stop(const base::Closure& closure) {
77 DCHECK(message_loop_->BelongsToCurrentThread());
78 stop_cb_.SetCallback(BindToCurrentLoop(closure));
79
80 // Defer the reset if a read and/or a reset is pending.
81 if (!read_cb_.is_null() || !reset_cb_.is_null())
82 return;
83
84 DoStop();
85 }
86
87 void FakeVideoDecoder::HoldNextRead() {
88 DCHECK(message_loop_->BelongsToCurrentThread());
89 read_cb_.HoldCallback();
90 }
91
92 void FakeVideoDecoder::HoldNextReset() {
93 DCHECK(message_loop_->BelongsToCurrentThread());
94 reset_cb_.HoldCallback();
95 }
96
97 void FakeVideoDecoder::HoldNextStop() {
98 DCHECK(message_loop_->BelongsToCurrentThread());
99 stop_cb_.HoldCallback();
100 }
101
102 void FakeVideoDecoder::SatisfyRead() {
103 DCHECK(message_loop_->BelongsToCurrentThread());
104 read_cb_.Release();
105
106 if (!reset_cb_.is_null())
107 DoReset();
108
109 if (reset_cb_.is_null() && !stop_cb_.is_null())
110 DoStop();
111 }
112
113 void FakeVideoDecoder::SatisfyReset() {
114 DCHECK(message_loop_->BelongsToCurrentThread());
115 DCHECK(read_cb_.is_null());
116 reset_cb_.Release();
117
118 if (!stop_cb_.is_null())
119 DoStop();
120 }
121
122 void FakeVideoDecoder::SatisfyStop() {
123 DCHECK(message_loop_->BelongsToCurrentThread());
124 DCHECK(read_cb_.is_null());
125 DCHECK(reset_cb_.is_null());
126 stop_cb_.Release();
127 }
128
129 void FakeVideoDecoder::ReadFromDemuxerStream() {
130 DCHECK_EQ(state_, NORMAL);
131 DCHECK(!read_cb_.is_null());
132 demuxer_stream_->Read(base::Bind(&FakeVideoDecoder::BufferReady, weak_this_));
133 }
134
135 void FakeVideoDecoder::BufferReady(DemuxerStream::Status status,
136 const scoped_refptr<DecoderBuffer>& buffer) {
137 DCHECK(message_loop_->BelongsToCurrentThread());
138 DCHECK_EQ(state_, NORMAL);
139 DCHECK(!read_cb_.is_null());
140 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
141
142 if (!stop_cb_.is_null()) {
143 read_cb_.Run(kOk, scoped_refptr<VideoFrame>());
144 if (!reset_cb_.is_null()) {
145 DoReset();
146 }
147 DoStop();
148 return;
149 }
150
151 if (status == DemuxerStream::kConfigChanged) {
152 DCHECK(demuxer_stream_->video_decoder_config().IsValidConfig());
153 current_config_ = demuxer_stream_->video_decoder_config();
154
155 if (reset_cb_.is_null()) {
156 ReadFromDemuxerStream();
157 return;
158 }
159 }
160
161 if (!reset_cb_.is_null()) {
162 read_cb_.Run(kOk, scoped_refptr<VideoFrame>());
163 DoReset();
164 return;
165 }
166
167 if (status == DemuxerStream::kAborted) {
168 read_cb_.Run(kOk, scoped_refptr<VideoFrame>());
169 return;
170 }
171
172 DCHECK_EQ(status, DemuxerStream::kOk);
173
174 if (buffer->IsEndOfStream() && decoded_frames_.empty()) {
175 read_cb_.Run(kOk, VideoFrame::CreateEmptyFrame());
176 return;
177 }
178
179 if (!buffer->IsEndOfStream()) {
180 scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateColorFrame(
181 current_config_.coded_size(), 0, 0, 0, buffer->GetTimestamp());
182 decoded_frames_.push_back(video_frame);
183
184 if (decoded_frames_.size() <= static_cast<size_t>(decoding_delay_)) {
185 ReadFromDemuxerStream();
186 return;
187 }
188 }
189
190 scoped_refptr<VideoFrame> frame = decoded_frames_.front();
191 decoded_frames_.pop_front();
192 read_cb_.Run(kOk, frame);
193 }
194
195 void FakeVideoDecoder::DoReset() {
196 DCHECK(message_loop_->BelongsToCurrentThread());
197 DCHECK(read_cb_.is_null());
198 DCHECK(!reset_cb_.is_null());
199
200 decoded_frames_.clear();
201 reset_cb_.Run();
202 }
203
204 void FakeVideoDecoder::DoStop() {
205 DCHECK(message_loop_->BelongsToCurrentThread());
206 DCHECK(read_cb_.is_null());
207 DCHECK(reset_cb_.is_null());
208 DCHECK(!stop_cb_.is_null());
209
210 state_ = UNINITIALIZED;
211 demuxer_stream_ = NULL;
212 decoded_frames_.clear();
213 stop_cb_.Run();
214 }
215
216 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698