summaryrefslogtreecommitdiffstats
path: root/chromecast/media/cma/pipeline/video_pipeline_impl.cc
blob: 1888776248d39c372422760280f1e6f5e43738fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"

#include "base/bind.h"
#include "chromecast/media/cdm/browser_cdm_cast.h"
#include "chromecast/media/cma/base/buffering_defs.h"
#include "chromecast/media/cma/base/cma_logging.h"
#include "chromecast/media/cma/base/coded_frame_provider.h"
#include "chromecast/media/cma/base/decoder_config_adapter.h"
#include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
#include "chromecast/public/graphics_types.h"
#include "chromecast/public/media/decoder_config.h"
#include "media/base/video_decoder_config.h"

namespace chromecast {
namespace media {

namespace {
const size_t kMaxVideoFrameSize = 1024 * 1024;
}

VideoPipelineImpl::VideoPipelineImpl(
    MediaPipelineBackend::VideoDecoder* decoder,
    const VideoPipelineClient& client)
    : AvPipelineImpl(decoder, client.av_pipeline_client),
      video_decoder_(decoder),
      natural_size_changed_cb_(client.natural_size_changed_cb) {
  DCHECK(video_decoder_);
}

VideoPipelineImpl::~VideoPipelineImpl() {
}

void VideoPipelineImpl::Initialize(
    const std::vector<::media::VideoDecoderConfig>& configs,
    scoped_ptr<CodedFrameProvider> frame_provider,
    const ::media::PipelineStatusCB& status_cb) {
  DCHECK_GT(configs.size(), 0u);
  for (const auto& config : configs) {
    CMALOG(kLogControl) << __FUNCTION__ << " "
                        << config.AsHumanReadableString();
  }

  if (frame_provider) {
    SetCodedFrameProvider(frame_provider.Pass(), kAppVideoBufferSize,
                          kMaxVideoFrameSize);
  }

  if (configs.empty()) {
     status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
     return;
  }
  DCHECK(configs.size() <= 2);
  DCHECK(configs[0].IsValidConfig());
  VideoConfig video_config =
      DecoderConfigAdapter::ToCastVideoConfig(kPrimary, configs[0]);
  VideoConfig secondary_config;
  if (configs.size() == 2) {
    DCHECK(configs[1].IsValidConfig());
    secondary_config = DecoderConfigAdapter::ToCastVideoConfig(kSecondary,
                                                               configs[1]);
    video_config.additional_config = &secondary_config;
  }

  if (!video_decoder_->SetConfig(video_config)) {
    status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
    return;
  }
  TransitionToState(kFlushed);
  status_cb.Run(::media::PIPELINE_OK);
}

void VideoPipelineImpl::OnVideoResolutionChanged(const Size& size) {
  if (state() != kPlaying)
    return;

  if (!natural_size_changed_cb_.is_null()) {
    natural_size_changed_cb_.Run(gfx::Size(size.width, size.height));
  }
}

void VideoPipelineImpl::OnUpdateConfig(
    StreamId id,
    const ::media::AudioDecoderConfig& audio_config,
    const ::media::VideoDecoderConfig& video_config) {
  if (video_config.IsValidConfig()) {
    CMALOG(kLogControl) << __FUNCTION__ << " id:" << id << " "
                        << video_config.AsHumanReadableString();

    bool success = video_decoder_->SetConfig(
        DecoderConfigAdapter::ToCastVideoConfig(id, video_config));
    if (!success && !client().playback_error_cb.is_null())
      client().playback_error_cb.Run(::media::PIPELINE_ERROR_DECODE);
  }
}

void VideoPipelineImpl::UpdateStatistics() {
  if (client().statistics_cb.is_null())
    return;

  MediaPipelineBackend::VideoDecoder::Statistics video_stats;
  video_decoder_->GetStatistics(&video_stats);

  ::media::PipelineStatistics current_stats;
  current_stats.video_bytes_decoded = video_stats.decoded_bytes;
  current_stats.video_frames_decoded = video_stats.decoded_frames;
  current_stats.video_frames_dropped = video_stats.dropped_frames;

  ::media::PipelineStatistics delta_stats;
  delta_stats.video_bytes_decoded =
      current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded;
  delta_stats.video_frames_decoded =
      current_stats.video_frames_decoded - previous_stats_.video_frames_decoded;
  delta_stats.video_frames_dropped =
      current_stats.video_frames_dropped - previous_stats_.video_frames_dropped;

  previous_stats_ = current_stats;

  client().statistics_cb.Run(delta_stats);
}

}  // namespace media
}  // namespace chromecast