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
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169

media / filters / decoder_stream_traits.h [blame]

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_FILTERS_DECODER_STREAM_TRAITS_H_
#define MEDIA_FILTERS_DECODER_STREAM_TRAITS_H_

#include <memory>
#include <string>

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/moving_window.h"
#include "base/time/time.h"
#include "media/base/audio_decoder.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/channel_layout.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_log_properties.h"
#include "media/base/pipeline_status.h"
#include "media/base/sample_format.h"
#include "media/base/video_decoder.h"
#include "media/filters/audio_timestamp_validator.h"

namespace media {

class AudioBuffer;
class CdmContext;
class DemuxerStream;
class VideoDecoderConfig;
class VideoFrame;

template <DemuxerStream::Type StreamType>
class DecoderStreamTraits {};

enum class PostDecodeAction { DELIVER, DROP };

template <>
class MEDIA_EXPORT DecoderStreamTraits<DemuxerStream::AUDIO> {
 public:
  using OutputType = AudioBuffer;
  using DecoderType = AudioDecoder;
  using DecoderConfigType = AudioDecoderConfig;
  using InitCB = AudioDecoder::InitCB;
  using OutputCB = AudioDecoder::OutputCB;

  static const MediaLogProperty kDecoderName =
      MediaLogProperty::kAudioDecoderName;
  static const MediaLogProperty kIsPlatformDecoder =
      MediaLogProperty::kIsPlatformAudioDecoder;
  static const MediaLogProperty kIsDecryptingDemuxerStream =
      MediaLogProperty::kIsAudioDecryptingDemuxerStream;

  static std::string ToString();
  static bool NeedsBitstreamConversion(DecoderType* decoder);
  static scoped_refptr<OutputType> CreateEOSOutput();

  DecoderStreamTraits(MediaLog* media_log,
                      ChannelLayout initial_hw_layout,
                      SampleFormat initial_hw_sample_format);

  void ReportStatistics(const StatisticsCB& statistics_cb, int bytes_decoded);
  void SetIsPlatformDecoder(bool is_platform_decoder);
  void SetIsDecryptingDemuxerStream(bool is_dds);
  void SetEncryptionType(EncryptionType decryption_type);
  void InitializeDecoder(DecoderType* decoder,
                         const DecoderConfigType& config,
                         bool low_delay,
                         CdmContext* cdm_context,
                         InitCB init_cb,
                         const OutputCB& output_cb,
                         const WaitingCB& waiting_cb);
  void OnDecoderInitialized(DecoderType* decoder,
                            InitCB cb,
                            DecoderStatus status);
  DecoderConfigType GetDecoderConfig(DemuxerStream* stream);
  void OnDecode(const DecoderBuffer& buffer);
  PostDecodeAction OnDecodeDone(OutputType* buffer);
  void OnStreamReset(DemuxerStream* stream);
  void OnOutputReady(OutputType* output);

 private:
  void OnConfigChanged(const AudioDecoderConfig& config);

  // Validates encoded timestamps match decoded output duration. MEDIA_LOG warns
  // if timestamp gaps are detected. Sufficiently large gaps can lead to AV sync
  // drift.
  std::unique_ptr<AudioTimestampValidator> audio_ts_validator_;
  raw_ptr<MediaLog> media_log_;
  // HW layout at the time pipeline was started. Will not reflect possible
  // device changes.
  ChannelLayout initial_hw_layout_;
  // HW sample format at the time pipeline was started. Will not reflect
  // possible device changes.
  SampleFormat initial_hw_sample_format_;
  PipelineStatistics stats_;
  AudioDecoderConfig config_;

  base::WeakPtr<DecoderStreamTraits<DemuxerStream::AUDIO>> weak_this_;
  base::WeakPtrFactory<DecoderStreamTraits<DemuxerStream::AUDIO>> weak_factory_{
      this};
};

template <>
class MEDIA_EXPORT DecoderStreamTraits<DemuxerStream::VIDEO> {
 public:
  using OutputType = VideoFrame;
  using DecoderType = VideoDecoder;
  using DecoderConfigType = VideoDecoderConfig;
  using InitCB = VideoDecoder::InitCB;
  using OutputCB = VideoDecoder::OutputCB;
  static const MediaLogProperty kDecoderName =
      MediaLogProperty::kVideoDecoderName;
  static const MediaLogProperty kIsPlatformDecoder =
      MediaLogProperty::kIsPlatformVideoDecoder;
  static const MediaLogProperty kIsDecryptingDemuxerStream =
      MediaLogProperty::kIsVideoDecryptingDemuxerStream;

  static std::string ToString();
  static bool NeedsBitstreamConversion(DecoderType* decoder);
  static scoped_refptr<OutputType> CreateEOSOutput();

  explicit DecoderStreamTraits(MediaLog* media_log);

  DecoderConfigType GetDecoderConfig(DemuxerStream* stream);
  void ReportStatistics(const StatisticsCB& statistics_cb, int bytes_decoded);
  void SetIsPlatformDecoder(bool is_platform_decoder);
  void SetIsDecryptingDemuxerStream(bool is_dds);
  void SetEncryptionType(EncryptionType decryption_type);
  void InitializeDecoder(DecoderType* decoder,
                         const DecoderConfigType& config,
                         bool low_delay,
                         CdmContext* cdm_context,
                         InitCB init_cb,
                         const OutputCB& output_cb,
                         const WaitingCB& waiting_cb);
  void OnDecoderInitialized(DecoderType* decoder,
                            InitCB cb,
                            DecoderStatus status);
  void OnDecode(const DecoderBuffer& buffer);
  PostDecodeAction OnDecodeDone(OutputType* buffer);
  void OnStreamReset(DemuxerStream* stream);
  void OnOutputReady(OutputType* output);

 private:
  base::TimeDelta last_keyframe_timestamp_;
  base::MovingAverage<base::TimeDelta, base::TimeDelta>
      keyframe_distance_average_;

  // Tracks the duration of incoming packets over time.
  struct FrameMetadata {
    bool should_drop = false;
    base::TimeDelta duration = kNoTimestamp;
    base::TimeTicks decode_begin_time;
  };
  base::flat_map<base::TimeDelta, FrameMetadata> frame_metadata_;

  PipelineStatistics stats_;

  VideoTransformation transform_ = kNoTransformation;

  base::WeakPtr<DecoderStreamTraits<DemuxerStream::VIDEO>> weak_this_;
  base::WeakPtrFactory<DecoderStreamTraits<DemuxerStream::VIDEO>> weak_factory_{
      this};
};

}  // namespace media

#endif  // MEDIA_FILTERS_DECODER_STREAM_TRAITS_H_