1 /* 2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef HISTREAMER_M3U8_H 17 #define HISTREAMER_M3U8_H 18 19 #include <memory> 20 #include <string> 21 #include <list> 22 #include <unordered_map> 23 #include <functional> 24 #include <map> 25 #include "hls_tags.h" 26 #include "playlist_downloader.h" 27 #include "download/downloader.h" 28 29 namespace OHOS { 30 namespace Media { 31 namespace Plugins { 32 namespace HttpPlugin { 33 enum class M3U8MediaType : int32_t { 34 M3U8_MEDIA_TYPE_INVALID = -1, 35 M3U8_MEDIA_TYPE_AUDIO, 36 M3U8_MEDIA_TYPE_VIDEO, 37 M3U8_MEDIA_TYPE_SUBTITLES, 38 M3U8_MEDIA_TYPE_CLOSED_CAPTIONS, 39 M3U8_N_MEDIA_TYPES, 40 }; 41 42 struct M3U8InitFile { 43 std::string uri; 44 int offset; 45 int size; 46 }; 47 48 struct M3U8Fragment { 49 M3U8Fragment(std::string uri, double duration, int sequence, bool discont); 50 M3U8Fragment(const M3U8Fragment& m3u8, const uint8_t *key, const uint8_t *iv); 51 std::string uri_; 52 double duration_; 53 int64_t sequence_; 54 bool discont_ {false}; 55 uint8_t key_[16] { 0 }; 56 int iv_[16] {0}; 57 int offset_ {-1}; 58 int size_ {0}; 59 }; 60 61 struct M3U8Info { 62 std::string uri; 63 double duration = 0; 64 bool discontinuity = false; 65 bool bVod {false}; 66 }; 67 68 struct M3U8 { 69 M3U8(std::string uri, std::string name); 70 ~M3U8(); 71 void InitTagUpdaters(); 72 void InitTagUpdatersMap(); 73 bool Update(const std::string& playList, bool isNeedCleanFiles); 74 void UpdateFromTags(std::list<std::shared_ptr<Tag>>& tags); 75 void AddFile(std::shared_ptr<M3U8Fragment> fragment, size_t duration); 76 void GetExtInf(const std::shared_ptr<Tag>& tag, double& duration) const; 77 double GetDuration() const; 78 bool IsLive() const; 79 80 std::string uri_; 81 std::string name_; 82 std::unordered_map<HlsTag, std::function<void(std::shared_ptr<Tag>&, M3U8Info&)>> tagUpdatersMap_; 83 84 double targetDuration_ {0.0}; 85 bool bLive_ {}; 86 std::list<std::shared_ptr<M3U8Fragment>> files_; 87 uint64_t sequence_ {1}; // default 1 88 int discontSequence_ {0}; 89 std::string playList_; 90 void ParseKey(const std::shared_ptr<AttributesTag> &tag); 91 void DownloadKey(); 92 bool SaveData(uint8_t *data, uint32_t len); 93 static void OnDownloadStatus(DownloadStatus status, std::shared_ptr<Downloader> &, 94 std::shared_ptr<DownloadRequest> &request); 95 bool SetDrmInfo(std::multimap<std::string, std::vector<uint8_t>>& drmInfo); 96 void StoreDrmInfos(const std::multimap<std::string, std::vector<uint8_t>>& drmInfo); 97 void ProcessDrmInfos(void); 98 99 std::shared_ptr<std::string> method_; 100 std::shared_ptr<std::string> keyUri_; 101 uint8_t iv_[16] { 0 }; 102 uint8_t key_[16] { 0 }; 103 size_t keyLen_ { 0 }; 104 std::shared_ptr<Downloader> downloader_; 105 std::shared_ptr<DownloadRequest> downloadRequest_; 106 DataSaveFunc dataSave_; 107 StatusCallbackFunc statusCallback_; 108 PlayListChangeCallback *callback_ { nullptr }; 109 bool startedDownloadStatus_ { false }; 110 bool isDecryptAble_ { false }; 111 bool isDecryptKeyReady_ { false }; 112 std::multimap<std::string, std::vector<uint8_t>> localDrmInfos_; 113 M3U8Info firstFragment_; 114 std::atomic<bool> isFirstFragmentReady_ {false}; 115 std::atomic<bool> isPlayTypeFound_ {false}; 116 bool hasDiscontinuity_ {false}; 117 std::vector<size_t> segmentOffsets_; 118 std::map<std::string, std::string> httpHeader_ {}; 119 }; 120 121 struct M3U8Media { 122 M3U8MediaType type_; 123 std::string groupID_; 124 std::string name_; 125 std::string lang_; 126 std::string uri_; 127 bool isDefault_; 128 bool autoSelect_; 129 bool forced_; 130 std::shared_ptr<M3U8> m3u8_; 131 }; 132 133 struct M3U8VariantStream { 134 M3U8VariantStream(std::string name, std::string uri, std::shared_ptr<M3U8> m3u8); 135 std::string name_; 136 std::string uri_; 137 std::string codecs_; 138 uint64_t bandWidth_ {}; 139 int programID_ {}; 140 int width_ {}; 141 int height_ {}; 142 bool iframe_ {false}; 143 std::shared_ptr<M3U8> m3u8_; 144 std::list<M3U8Media> media_; 145 }; 146 147 struct M3U8MasterPlaylist { 148 M3U8MasterPlaylist(const std::string& playList, const std::string& uri, uint32_t initResolution = 0, 149 const std::map<std::string, std::string>& httpHeader = std::map<std::string, std::string>()); 150 void UpdateMediaPlaylist(); 151 void UpdateMasterPlaylist(); 152 void DownloadSessionKey(std::shared_ptr<Tag>& tag); 153 void ChooseStreamByResolution(); 154 bool IsNearToInitResolution(const std::shared_ptr<M3U8VariantStream> &choosedStream, 155 const std::shared_ptr<M3U8VariantStream> ¤tStream); 156 uint32_t GetResolutionDelta(uint32_t width, uint32_t height); 157 std::list<std::shared_ptr<M3U8VariantStream>> variants_; 158 std::shared_ptr<M3U8VariantStream> defaultVariant_; 159 std::string uri_; 160 std::string playList_; 161 double duration_ {0}; 162 std::atomic<bool> isSimple_ {false}; 163 std::atomic<bool> bLive_ {false}; 164 bool isDecryptAble_ { false }; 165 bool isDecryptKeyReady_ { false }; 166 uint8_t iv_[16] { 0 }; 167 uint8_t key_[16] { 0 }; 168 size_t keyLen_ { 0 }; 169 std::atomic<bool> isParseSuccess_ {true}; 170 std::vector<size_t> segmentOffsets_; 171 bool hasDiscontinuity_ {false}; 172 std::map<std::string, std::string> httpHeader_ {}; 173 uint32_t initResolution_ {0}; 174 }; 175 } 176 } 177 } 178 } 179 #endif 180