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
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204

media / base / mime_util_internal.h [blame]

// Copyright 2012 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_BASE_MIME_UTIL_INTERNAL_H_
#define MEDIA_BASE_MIME_UTIL_INTERNAL_H_

#include <string>
#include <string_view>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "build/build_config.h"
#include "media/base/media_export.h"
#include "media/base/media_types.h"
#include "media/base/mime_util.h"
#include "media/base/video_color_space.h"

namespace media::internal {

// Internal utility class for handling mime types.  Should only be invoked by
// tests and the functions within mime_util.cc -- NOT for direct use by others.
class MEDIA_EXPORT MimeUtil {
 public:
  MimeUtil();

  MimeUtil(const MimeUtil&) = delete;
  MimeUtil& operator=(const MimeUtil&) = delete;

  ~MimeUtil();

  enum Codec {
    INVALID_CODEC,
    PCM,
    MP3,
    AC3,
    EAC3,
    MPEG2_AAC,
    MPEG4_AAC,
    MPEG4_XHE_AAC,
    VORBIS,
    OPUS,
    FLAC,
    H264,
    HEVC,
    VP8,
    VP9,
    THEORA,
    DOLBY_VISION,
    AV1,
    MPEG_H_AUDIO,
    DTS,
    DTSXP2,
    DTSE,
    AC4,
    IAMF,
    LAST_CODEC = IAMF
  };

  // Platform configuration structure.  Controls which codecs are supported at
  // runtime.  Also used by tests to simulate platform differences.
  struct PlatformInfo {
#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
    bool has_platform_dv_decoder = false;
#endif
    bool has_platform_vp8_decoder = false;
    bool has_platform_vp9_decoder = false;
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
    bool has_platform_hevc_decoder = false;
#endif
    bool has_platform_opus_decoder = false;
  };

  struct ParsedCodecResult {
    Codec codec;
    bool is_ambiguous;
    std::optional<VideoType> video;
  };

  // See mime_util.h for more information on these methods.
  bool IsSupportedMediaMimeType(std::string_view mime_type) const;
  void SplitCodecs(std::string_view codecs,
                   std::vector<std::string>* codecs_out) const;
  void StripCodecs(std::vector<std::string>* codecs) const;
  std::optional<VideoType> ParseVideoCodecString(
      std::string_view mime_type,
      std::string_view codec_id,
      bool allow_ambiguous_matches) const;
  bool ParseAudioCodecString(std::string_view mime_type,
                             std::string_view codec_id,
                             bool* out_is_ambiguous,
                             AudioCodec* out_codec) const;
  SupportsType IsSupportedMediaFormat(std::string_view mime_type,
                                      const std::vector<std::string>& codecs,
                                      bool is_encrypted) const;

  // Checks android platform specific codec restrictions. Returns true if
  // |codec| is supported when contained in |mime_type_lower_case|.
  // |is_encrypted| means the codec will be used with encrypted blocks.
  // |platform_info| describes the availability of various platform features;
  // see PlatformInfo for more details.
  static bool IsCodecSupportedOnAndroid(Codec codec,
                                        std::string_view mime_type_lower_case,
                                        bool is_encrypted,
                                        VideoCodecProfile video_profile,
                                        const PlatformInfo& platform_info);

 private:
  typedef base::flat_set<int> CodecSet;
  typedef base::flat_map<std::string, CodecSet> MediaFormatMappings;

  // Initializes the supported media types into hash sets for faster lookup.
  void InitializeMimeTypeMaps();

  // Initializes the supported media formats (|media_format_map_|).
  void AddSupportedMediaFormats();

  // Adds |mime_type| with the specified codecs to |media_format_map_|.
  void AddContainerWithCodecs(std::string mime_type, CodecSet codecs_list);

  // Returns SupportsType::kSupported if all codec IDs in |codecs| are
  // unambiguous and are supported in |mime_type_lower_case|. kMaybeSupported is
  // returned if at least one codec ID in |codecs| is ambiguous but all the
  // codecs are supported. kNotSupported is returned if |mime_type_lower_case|
  // is not supported or at least one is not supported in
  // |mime_type_lower_case|. |is_encrypted| means the codec will be used with
  // encrypted blocks.
  SupportsType AreSupportedCodecs(
      const std::vector<ParsedCodecResult>& parsed_codecs,
      std::string_view mime_type_lower_case,
      bool is_encrypted) const;

  // Parse the combination of |mime_type_lower_case| and |codecs|. Returns true
  // when parsing succeeds and output is written to |out_results|. Returns false
  // when parsing fails. Failure may be caused by
  //  - invalid/unrecognized codec strings and mime_types
  //  - invalid combinations of codec strings and mime_types (e.g. H264 in WebM)
  // See comment for ParseCodecHelper().
  bool ParseCodecStrings(std::string_view mime_type_lower_case,
                         const std::vector<std::string>& codecs,
                         std::vector<ParsedCodecResult>* out_results) const;

  // Helper to ParseCodecStrings(). Parses a single |codec_id| with
  // |mime_type_lower_case| to populate the fields of |out_result|. This helper
  // method does not validate the combination of |mime_type_lower_case| and
  // |codec_id|, nor does it handle empty/unprovided codecs; See caller
  // ParseCodecStrings().
  //
  // |out_result| is only valid when this method returns true (parsing success).
  // |out_result->is_ambiguous| will be set to true when the codec string
  // matches one of a fixed number of *non-RFC compliant* strings (e.g. "avc").
  // Ambiguous video codec strings may fail to provide video profile and/or
  // level info. In these cases, we use the following values to indicate
  // "unspecified":
  //  - out_result->video_profile = VIDEO_CODEC_PROFILE_UNKNOWN
  //  - out_result->video_level = 0
  //
  // For unambiguous video codecs, |video_profile| and |video_level| will be
  // set in |out_result|.
  //
  // |out_result|'s |video_color_space| will report the codec strings color
  // space when provided. Most codec strings do not yet describe color, so this
  // will often be set to the default of REC709.
  bool ParseCodecHelper(std::string_view mime_type_lower_case,
                        std::string_view codec_id,
                        ParsedCodecResult* out_result) const;

  // Returns kSupported if |codec| when platform supports codec contained in
  // |mime_type_lower_case|. Returns kMaybeSupported when platform support is
  // unclear. Otherwise returns NotSupported. Note: This method will always
  // return NotSupported for proprietary codecs if |allow_proprietary_codecs_|
  // is set to false. |is_encrypted| means the codec will be used with encrypted
  // blocks.
  // TODO(chcunningham): Make this method return a bool. Platform support should
  // always be knowable for a fully specified codec.
  SupportsType IsCodecSupported(std::string_view mime_type_lower_case,
                                Codec codec,
                                VideoCodecProfile video_profile,
                                VideoCodecLevel video_level,
                                const VideoColorSpace& eotf,
                                bool is_encrypted) const;

  // Returns true if |codec| refers to a proprietary codec.
  bool IsCodecProprietary(Codec codec) const;

  // Returns true and sets |*default_codec| if |mime_type_lower_case| has a
  // default codec associated with it. Returns false otherwise and the value of
  // |*default_codec| is undefined.
  bool GetDefaultCodec(std::string_view mime_type_lower_case,
                       Codec* default_codec) const;

#if BUILDFLAG(IS_ANDROID)
  // Indicates the support of various codecs within the platform.
  PlatformInfo platform_info_;
#endif

  // A map of mime_types and hash map of the supported codecs for the mime_type.
  MediaFormatMappings media_format_map_;
};

}  // namespace media::internal

#endif  // MEDIA_BASE_MIME_UTIL_INTERNAL_H_