1 // Copyright 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.
5 #include "media/filters/fake_video_decoder.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "media/base/bind_to_current_loop.h"
12 #include "media/base/test_helpers.h"
16 FakeVideoDecoder::FakeVideoDecoder(int decoding_delay
)
17 : task_runner_(base::MessageLoopProxy::current()),
19 decoding_delay_(decoding_delay
),
20 state_(UNINITIALIZED
),
21 total_bytes_decoded_(0) {
22 DCHECK_GE(decoding_delay
, 0);
25 FakeVideoDecoder::~FakeVideoDecoder() {
26 DCHECK_EQ(state_
, UNINITIALIZED
);
29 void FakeVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
30 const PipelineStatusCB
& status_cb
) {
31 DCHECK(task_runner_
->BelongsToCurrentThread());
32 DCHECK(config
.IsValidConfig());
33 DCHECK(decode_cb_
.IsNull()) << "No reinitialization during pending decode.";
34 DCHECK(reset_cb_
.IsNull()) << "No reinitialization during pending reset.";
36 weak_this_
= weak_factory_
.GetWeakPtr();
38 current_config_
= config
;
39 init_cb_
.SetCallback(BindToCurrentLoop(status_cb
));
41 if (!decoded_frames_
.empty()) {
42 DVLOG(1) << "Decoded frames dropped during reinitialization.";
43 decoded_frames_
.clear();
47 init_cb_
.RunOrHold(PIPELINE_OK
);
50 void FakeVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
51 const DecodeCB
& decode_cb
) {
52 DCHECK(task_runner_
->BelongsToCurrentThread());
53 DCHECK(decode_cb_
.IsNull()) << "Overlapping decodes are not supported.";
54 DCHECK(reset_cb_
.IsNull());
55 DCHECK_LE(decoded_frames_
.size(), static_cast<size_t>(decoding_delay_
));
57 int buffer_size
= buffer
->end_of_stream() ? 0 : buffer
->data_size();
58 decode_cb_
.SetCallback(BindToCurrentLoop(base::Bind(
59 &FakeVideoDecoder::OnFrameDecoded
, weak_this_
, buffer_size
, decode_cb
)));
61 if (buffer
->end_of_stream() && decoded_frames_
.empty()) {
62 decode_cb_
.RunOrHold(kOk
, VideoFrame::CreateEOSFrame());
66 if (!buffer
->end_of_stream()) {
67 DCHECK(VerifyFakeVideoBufferForTest(buffer
, current_config_
));
68 scoped_refptr
<VideoFrame
> video_frame
= VideoFrame::CreateColorFrame(
69 current_config_
.coded_size(), 0, 0, 0, buffer
->timestamp());
70 decoded_frames_
.push_back(video_frame
);
72 if (decoded_frames_
.size() <= static_cast<size_t>(decoding_delay_
)) {
73 decode_cb_
.RunOrHold(kNotEnoughData
, scoped_refptr
<VideoFrame
>());
78 scoped_refptr
<VideoFrame
> frame
= decoded_frames_
.front();
79 decoded_frames_
.pop_front();
80 decode_cb_
.RunOrHold(kOk
, frame
);
83 void FakeVideoDecoder::Reset(const base::Closure
& closure
) {
84 DCHECK(task_runner_
->BelongsToCurrentThread());
85 DCHECK(reset_cb_
.IsNull());
86 reset_cb_
.SetCallback(BindToCurrentLoop(closure
));
88 // Defer the reset if a decode is pending.
89 if (!decode_cb_
.IsNull())
95 void FakeVideoDecoder::Stop(const base::Closure
& closure
) {
96 DCHECK(task_runner_
->BelongsToCurrentThread());
97 stop_cb_
.SetCallback(BindToCurrentLoop(closure
));
99 // Defer the stop if an init, a decode or a reset is pending.
100 if (!init_cb_
.IsNull() || !decode_cb_
.IsNull() || !reset_cb_
.IsNull())
106 void FakeVideoDecoder::HoldNextInit() {
107 DCHECK(task_runner_
->BelongsToCurrentThread());
108 init_cb_
.HoldCallback();
111 void FakeVideoDecoder::HoldNextRead() {
112 DCHECK(task_runner_
->BelongsToCurrentThread());
113 decode_cb_
.HoldCallback();
116 void FakeVideoDecoder::HoldNextReset() {
117 DCHECK(task_runner_
->BelongsToCurrentThread());
118 reset_cb_
.HoldCallback();
121 void FakeVideoDecoder::HoldNextStop() {
122 DCHECK(task_runner_
->BelongsToCurrentThread());
123 stop_cb_
.HoldCallback();
126 void FakeVideoDecoder::SatisfyInit() {
127 DCHECK(task_runner_
->BelongsToCurrentThread());
128 DCHECK(decode_cb_
.IsNull());
129 DCHECK(reset_cb_
.IsNull());
131 init_cb_
.RunHeldCallback();
133 if (!stop_cb_
.IsNull())
137 void FakeVideoDecoder::SatisfyRead() {
138 DCHECK(task_runner_
->BelongsToCurrentThread());
139 decode_cb_
.RunHeldCallback();
141 if (!reset_cb_
.IsNull())
144 if (reset_cb_
.IsNull() && !stop_cb_
.IsNull())
148 void FakeVideoDecoder::SatisfyReset() {
149 DCHECK(task_runner_
->BelongsToCurrentThread());
150 DCHECK(decode_cb_
.IsNull());
151 reset_cb_
.RunHeldCallback();
153 if (!stop_cb_
.IsNull())
157 void FakeVideoDecoder::SatisfyStop() {
158 DCHECK(task_runner_
->BelongsToCurrentThread());
159 DCHECK(decode_cb_
.IsNull());
160 DCHECK(reset_cb_
.IsNull());
161 stop_cb_
.RunHeldCallback();
164 void FakeVideoDecoder::DoReset() {
165 DCHECK(task_runner_
->BelongsToCurrentThread());
166 DCHECK(decode_cb_
.IsNull());
167 DCHECK(!reset_cb_
.IsNull());
169 decoded_frames_
.clear();
170 reset_cb_
.RunOrHold();
173 void FakeVideoDecoder::DoStop() {
174 DCHECK(task_runner_
->BelongsToCurrentThread());
175 DCHECK(decode_cb_
.IsNull());
176 DCHECK(reset_cb_
.IsNull());
177 DCHECK(!stop_cb_
.IsNull());
179 state_
= UNINITIALIZED
;
180 decoded_frames_
.clear();
181 stop_cb_
.RunOrHold();
184 void FakeVideoDecoder::OnFrameDecoded(
186 const DecodeCB
& decode_cb
,
188 const scoped_refptr
<VideoFrame
>& video_frame
) {
189 if (status
== kOk
|| status
== kNotEnoughData
)
190 total_bytes_decoded_
+= buffer_size
;
191 decode_cb
.Run(status
, video_frame
);