chromium/media/filters/hls_media_player_tag_recorder.h

// Copyright 2024 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_HLS_MEDIA_PLAYER_TAG_RECORDER_H_
#define MEDIA_FILTERS_HLS_MEDIA_PLAYER_TAG_RECORDER_H_

#include "base/threading/sequence_bound.h"
#include "media/base/media_export.h"
#include "media/filters/hls_data_source_provider.h"
#include "media/filters/hls_demuxer_status.h"
#include "media/filters/hls_network_access.h"
#include "media/formats/hls/media_segment.h"
#include "media/formats/hls/playlist.h"
#include "media/formats/hls/tag_recorder.h"

namespace media {

// A stripped down implementation of the HLS Manifest parser which can record
// statistics for playlists which are passed to Android's MediaPlayer.
class MEDIA_EXPORT HlsMediaPlayerTagRecorder : public hls::TagRecorder {
 public:
  explicit HlsMediaPlayerTagRecorder(
      std::unique_ptr<HlsNetworkAccess> network_access);

  ~HlsMediaPlayerTagRecorder() override;

  void Start(GURL root_playlist_uri);
  void AllowRecording();

  // TagRecorder implementation
  void SetMetric(Metric metric) override;
  void RecordError(uint32_t err_code) override;

 private:
  // Recorded in the AdvancedFeatureTagType histogram.
  // These values are persisted to logs. Entries should not be renumbered
  // and numeric values should never be reused.
  enum class AdvancedFeatureTagType : uint32_t {
    kContentSteering = 0,        // Multivariant
    kDiscontinuity = 1,          // Media
    kDiscontinuitySequence = 2,  // Media
    kGap = 3,                    // Media
    kKey = 4,                    // Media
    kPart = 5,                   // Media
    kSessionKey = 6,             // Multivariant
    kSkip = 7,                   // Media
    kXNonStandard = 8,           // Media,Multivariant
    kMaxValue = kXNonStandard,
  };

  // Recorded in the PlaylistSegmentType histogram.
  // These values are persisted to logs. Entries should not be renumbered
  // and numeric values should never be reused.
  enum class PlaylistSegmentType : uint32_t {
    kTS = 0,
    kMP4 = 1,
    kAAC = 2,
    kUnexpected = 3,
    kMaxValue = kUnexpected,
  };

  // Recorded in the SegmentEncryptionMode histogram.
  // These values are persisted to logs. Entries should not be renumbered
  // and numeric values should never be reused.
  enum class SegmentEncryptionMode : uint32_t {
    kNone = 0,
    kSegmentAES = 1,
    kSampleAES = 2,
    kSampleAESCTR = 3,
    kSampleAESCENC = 4,
    kISO230017 = 5,
    kMaxValue = kISO230017,
  };

  void OnPlaylistFetch(GURL root_playlist_uri,
                       HlsDataSourceProvider::ReadResult result);

  // Data recording methods
  void SetTopLevelPlaylistType(hls::Playlist::Kind kind);
  void SetAdvancedFeaturePresent(AdvancedFeatureTagType type);
  void SetSegmentTypePresent(PlaylistSegmentType type);
  void SetEncryptionModePresent(SegmentEncryptionMode mode);

  // Data saved, to be logged only if media player successfully can play.
  std::optional<uint32_t> advanced_feature_bitfield_
      GUARDED_BY_CONTEXT(sequence_checker_);
  std::optional<uint32_t> playlist_segment_bitfield_
      GUARDED_BY_CONTEXT(sequence_checker_);
  std::optional<uint32_t> segment_encryption_bitfield_
      GUARDED_BY_CONTEXT(sequence_checker_);
  std::optional<uint32_t> playlist_invalid_errorcode_
      GUARDED_BY_CONTEXT(sequence_checker_);
  std::optional<hls::Playlist::Kind> root_playlist_type_
      GUARDED_BY_CONTEXT(sequence_checker_);

  // Network access structure.
  std::unique_ptr<HlsNetworkAccess> network_access_
      GUARDED_BY_CONTEXT(sequence_checker_);

  bool recording_enabled_ GUARDED_BY_CONTEXT(sequence_checker_) = false;

  // Ensure that safe member fields are only accessed on the media sequence.
  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<HlsMediaPlayerTagRecorder> weak_factory_{this};
};

}  // namespace media

#endif  // MEDIA_FILTERS_HLS_MEDIA_PLAYER_TAG_RECORDER_H_