190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/filters/fake_video_decoder.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback_helpers.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/location.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/base/bind_to_loop.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "media/base/test_helpers.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace media {
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)FakeVideoDecoder::FakeVideoDecoder(int decoding_delay)
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : message_loop_(base::MessageLoopProxy::current()),
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      weak_factory_(this),
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      decoding_delay_(decoding_delay),
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      state_(UNINITIALIZED),
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      total_bytes_decoded_(0) {
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(decoding_delay, 0);
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)FakeVideoDecoder::~FakeVideoDecoder() {
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(state_, UNINITIALIZED);
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FakeVideoDecoder::Initialize(const VideoDecoderConfig& config,
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  const PipelineStatusCB& status_cb) {
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(config.IsValidConfig());
33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull()) << "No reinitialization during pending decode.";
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull()) << "No reinitialization during pending reset.";
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  weak_this_ = weak_factory_.GetWeakPtr();
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  current_config_ = config;
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  init_cb_.SetCallback(BindToCurrentLoop(status_cb));
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!decoded_frames_.empty()) {
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DVLOG(1) << "Decoded frames dropped during reinitialization.";
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    decoded_frames_.clear();
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  state_ = NORMAL;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  init_cb_.RunOrHold(PIPELINE_OK);
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FakeVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
51558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                              const DecodeCB& decode_cb) {
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
53558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull()) << "Overlapping decodes are not supported.";
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull());
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(decoded_frames_.size(), static_cast<size_t>(decoding_delay_));
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
58558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb_.SetCallback(BindToCurrentLoop(base::Bind(
59558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      &FakeVideoDecoder::OnFrameDecoded, weak_this_, buffer_size, decode_cb)));
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (buffer->end_of_stream() && decoded_frames_.empty()) {
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    decode_cb_.RunOrHold(kOk, VideoFrame::CreateEOSFrame());
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!buffer->end_of_stream()) {
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(VerifyFakeVideoBufferForTest(buffer, current_config_));
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateColorFrame(
69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        current_config_.coded_size(), 0, 0, 0, buffer->timestamp());
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    decoded_frames_.push_back(video_frame);
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (decoded_frames_.size() <= static_cast<size_t>(decoding_delay_)) {
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      decode_cb_.RunOrHold(kNotEnoughData, scoped_refptr<VideoFrame>());
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<VideoFrame> frame = decoded_frames_.front();
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  decoded_frames_.pop_front();
80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb_.RunOrHold(kOk, frame);
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::Reset(const base::Closure& closure) {
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull());
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reset_cb_.SetCallback(BindToCurrentLoop(closure));
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Defer the reset if a decode is pending.
89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!decode_cb_.IsNull())
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DoReset();
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::Stop(const base::Closure& closure) {
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stop_cb_.SetCallback(BindToCurrentLoop(closure));
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Defer the stop if an init, a decode or a reset is pending.
100558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!init_cb_.IsNull() || !decode_cb_.IsNull() || !reset_cb_.IsNull())
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DoStop();
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::HoldNextInit() {
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  init_cb_.HoldCallback();
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::HoldNextRead() {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb_.HoldCallback();
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::HoldNextReset() {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reset_cb_.HoldCallback();
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::HoldNextStop() {
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stop_cb_.HoldCallback();
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::SatisfyInit() {
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
128558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull());
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull());
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  init_cb_.RunHeldCallback();
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!stop_cb_.IsNull())
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DoStop();
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::SatisfyRead() {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
139558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb_.RunHeldCallback();
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!reset_cb_.IsNull())
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DoReset();
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (reset_cb_.IsNull() && !stop_cb_.IsNull())
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DoStop();
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::SatisfyReset() {
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull());
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reset_cb_.RunHeldCallback();
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!stop_cb_.IsNull())
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DoStop();
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::SatisfyStop() {
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull());
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull());
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stop_cb_.RunHeldCallback();
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::DoReset() {
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
166558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull());
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!reset_cb_.IsNull());
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoded_frames_.clear();
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reset_cb_.RunOrHold();
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FakeVideoDecoder::DoStop() {
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.IsNull());
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(reset_cb_.IsNull());
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!stop_cb_.IsNull());
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  state_ = UNINITIALIZED;
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoded_frames_.clear();
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stop_cb_.RunOrHold();
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FakeVideoDecoder::OnFrameDecoded(
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int buffer_size,
186558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const DecodeCB& decode_cb,
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Status status,
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const scoped_refptr<VideoFrame>& video_frame) {
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status == kOk || status == kNotEnoughData)
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    total_bytes_decoded_ += buffer_size;
191558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb.Run(status, video_frame);
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace media
195