File: decoder_selector.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (153 lines) | stat: -rw-r--r-- 5,616 bytes parent folder | download | duplicates (6)
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/webcodecs/decoder_selector.h"

#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "media/base/channel_layout.h"
#include "media/base/demuxer_stream.h"
#include "media/base/sample_format.h"
#include "media/filters/decrypting_demuxer_stream.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

// Demuxing isn't part of WebCodecs. This shim allows us to reuse decoder
// selection logic from <video>.
// TODO(chcunningham): Maybe refactor DecoderSelector to separate dependency on
// media::DemuxerStream. DecoderSelection doesn't conceptually require a
// Demuxer. The tough part is re-working Decryptingmedia::DemuxerStream.
template <media::DemuxerStream::Type StreamType>
class NullDemuxerStream : public media::DemuxerStream {
 public:
  using DecoderConfigType =
      typename media::DecoderStreamTraits<StreamType>::DecoderConfigType;

  ~NullDemuxerStream() override = default;

  void Read(uint32_t count, ReadCB read_cb) override { NOTREACHED(); }

  void Configure(DecoderConfigType config);

  media::AudioDecoderConfig audio_decoder_config() override {
    DCHECK_EQ(type(), media::DemuxerStream::AUDIO);
    return audio_decoder_config_;
  }

  media::VideoDecoderConfig video_decoder_config() override {
    DCHECK_EQ(type(), media::DemuxerStream::VIDEO);
    return video_decoder_config_;
  }

  Type type() const override { return stream_type; }

  bool SupportsConfigChanges() override { NOTREACHED(); }

  void set_low_delay(bool low_delay) { low_delay_ = low_delay; }
  media::StreamLiveness liveness() const override {
    return low_delay_ ? media::StreamLiveness::kLive
                      : media::StreamLiveness::kUnknown;
  }

 private:
  static const media::DemuxerStream::Type stream_type = StreamType;

  media::AudioDecoderConfig audio_decoder_config_;
  media::VideoDecoderConfig video_decoder_config_;
  bool low_delay_ = false;
};

template <>
void NullDemuxerStream<media::DemuxerStream::AUDIO>::Configure(
    DecoderConfigType config) {
  audio_decoder_config_ = config;
}

template <>
void NullDemuxerStream<media::DemuxerStream::VIDEO>::Configure(
    DecoderConfigType config) {
  video_decoder_config_ = config;
}

// TODO(crbug.com/368085608): Flip `enable_priority_based_selection` to true.
template <media::DemuxerStream::Type StreamType>
DecoderSelector<StreamType>::DecoderSelector(
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    CreateDecodersCB create_decoders_cb,
    typename Decoder::OutputCB output_cb)
    : impl_(std::move(task_runner),
            std::move(create_decoders_cb),
            &null_media_log_,
            /*enable_priority_based_selection=*/false),
      demuxer_stream_(new NullDemuxerStream<StreamType>()),
      stream_traits_(CreateStreamTraits()),
      output_cb_(output_cb) {
  impl_.Initialize(stream_traits_.get(), demuxer_stream_.get(),
                   nullptr /*CdmContext*/, media::WaitingCB());
}

template <media::DemuxerStream::Type StreamType>
DecoderSelector<StreamType>::~DecoderSelector() = default;

template <media::DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::SelectDecoder(
    const DecoderConfig& config,
    bool low_delay,
    SelectDecoderCB select_decoder_cb) {
  // |impl_| will internally use this the |config| from our NullDemuxerStream.
  demuxer_stream_->Configure(config);
  demuxer_stream_->set_low_delay(low_delay);

  // media::DecoderSelector will call back with a DecoderStatus if selection is
  // in progress when it is destructed.
  impl_.BeginDecoderSelection(
      WTF::BindOnce(&DecoderSelector<StreamType>::OnDecoderSelected,
                    weak_factory_.GetWeakPtr(), std::move(select_decoder_cb)),
      output_cb_);
}

template <>
std::unique_ptr<WebCodecsAudioDecoderSelector::StreamTraits>
DecoderSelector<media::DemuxerStream::AUDIO>::CreateStreamTraits() {
  // TODO(chcunningham): Consider plumbing real hw channel layout.
  return std::make_unique<DecoderSelector::StreamTraits>(
      &null_media_log_, media::CHANNEL_LAYOUT_NONE,
      media::kUnknownSampleFormat);
}

template <>
std::unique_ptr<WebCodecsVideoDecoderSelector::StreamTraits>
DecoderSelector<media::DemuxerStream::VIDEO>::CreateStreamTraits() {
  return std::make_unique<DecoderSelector::StreamTraits>(&null_media_log_);
}

template <media::DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::OnDecoderSelected(
    SelectDecoderCB select_decoder_cb,
    DecoderOrError decoder_or_error,
    std::unique_ptr<media::DecryptingDemuxerStream> decrypting_demuxer_stream) {
  DCHECK(!decrypting_demuxer_stream);

  // We immediately finalize decoder selection.
  // TODO(chcunningham): Rework this to do finalize after first frame
  // successfully decoded. This updates to match latest plans for spec
  // (configure() no longer takes a promise).
  impl_.FinalizeDecoderSelection();

  if (!decoder_or_error.has_value()) {
    std::move(select_decoder_cb).Run(nullptr);
  } else {
    std::move(select_decoder_cb).Run(std::move(decoder_or_error).value());
  }
}

template class MODULES_EXPORT DecoderSelector<media::DemuxerStream::VIDEO>;
template class MODULES_EXPORT DecoderSelector<media::DemuxerStream::AUDIO>;

}  // namespace blink