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 #define HST_LOG_TAG "DashSidxBoxParser"
17 
18 #include "sidx_box_parser.h"
19 #include "common/log.h"
20 
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_STREAM_SOURCE, "HiStreamer" };
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Plugins {
28 namespace HttpPlugin {
29 namespace {
30     constexpr unsigned int SHIFT_NUM_2 = 2;
31     constexpr unsigned int SHIFT_NUM_4 = 4;
32     constexpr unsigned int SHIFT_NUM_8 = 8;
33     constexpr unsigned int SHIFT_NUM_16 = 16;
34     constexpr unsigned int SHIFT_NUM_24 = 24;
35     constexpr unsigned int SHIFT_NUM_31 = 31;
36     constexpr unsigned int SHIFT_NUM_32 = 32;
37     constexpr unsigned int BUFF_INDEX_0 = 0;
38     constexpr unsigned int BUFF_INDEX_1 = 1;
39     constexpr unsigned int BUFF_INDEX_2 = 2;
40     constexpr unsigned int BUFF_INDEX_3 = 3;
41     constexpr unsigned int SIDX_REFERENCE_ITEM_SIZE = 12; // bytes of one referenced item
42 }
43 
44 static inline unsigned short Get2Bytes(char *buffer, uint32_t &currPos);
45 static inline uint32_t Get4Bytes(char *buffer, uint32_t &currPos);
46 static inline int64_t Get8Bytes(char *buffer, uint32_t &currPos);
47 static inline uint32_t GetVersion(uint32_t vflag);
48 static inline uint32_t GetReferenceType(uint32_t typeAndSize);
49 static inline uint32_t GetReferenceSize(uint32_t typeAndSize);
50 static inline void ForwardBytes(uint32_t &currPos, uint32_t skipSize);
51 static inline uint32_t BemSource(char s, char i, char d, char x);
52 
~SidxBoxParser()53 SidxBoxParser::~SidxBoxParser()
54 {
55     MEDIA_LOG_D("SidxBoxParser deleter was called!!!!");
56 }
57 
ParseSidxBox(char * bitStream,uint32_t streamSize,int64_t sidxEndOffset,DashList<std::shared_ptr<SubSegmentIndex>> & subSegIndexTable)58 int32_t SidxBoxParser::ParseSidxBox(char *bitStream, uint32_t streamSize, int64_t sidxEndOffset,
59                                     DashList<std::shared_ptr<SubSegmentIndex>> &subSegIndexTable)
60 {
61     const uint32_t BEM_SIDX = BemSource('s', 'i', 'd', 'x');
62     uint32_t currPos = 0;
63 
64     while (streamSize > currPos && BASE_BOX_HEAD_SIZE < streamSize - currPos) {
65         Get4Bytes(bitStream, currPos);
66         uint32_t boxType = Get4Bytes(bitStream, currPos);
67         if (boxType == BEM_SIDX) {
68             MEDIA_LOG_D("it is a sidx box");
69             if (!BuildSubSegmentIndexes(bitStream, streamSize, sidxEndOffset, subSegIndexTable, currPos)) {
70                 return -1;
71             }
72         } else {
73             MEDIA_LOG_W("sdix box error box=(%c %c %c %c), typeSize="
74                 PUBLIC_LOG_D32, (boxType >> SHIFT_NUM_24) & 0x000000ff, (boxType >> SHIFT_NUM_16) & 0x000000ff,
75                 (boxType >> SHIFT_NUM_8) & 0x000000ff, boxType & 0x000000ff, currPos);
76             return -1;
77         }
78     }
79 
80     return 0;
81 }
82 
BuildSubSegmentIndexes(char * bitStream,uint32_t streamSize,int64_t sidxEndOffset,DashList<std::shared_ptr<SubSegmentIndex>> & subSegIndexTable,uint32_t & currPos)83 bool SidxBoxParser::BuildSubSegmentIndexes(char *bitStream, uint32_t streamSize, int64_t sidxEndOffset,
84                                            DashList<std::shared_ptr<SubSegmentIndex>> &subSegIndexTable,
85                                            uint32_t &currPos)
86 {
87     uint32_t vFlag = Get4Bytes(bitStream, currPos);
88     uint32_t version = GetVersion(vFlag);
89 
90     Get4Bytes(bitStream, currPos);
91     uint32_t timescale = Get4Bytes(bitStream, currPos);
92 
93     int64_t firstOffset;
94 
95     if (version == 0) {
96         // skip earliestPresentationTime
97         Get4Bytes(bitStream, currPos);
98         firstOffset = Get4Bytes(bitStream, currPos);
99     } else {
100         // skip earliestPresentationTime
101         Get8Bytes(bitStream, currPos);
102         firstOffset = Get8Bytes(bitStream, currPos);
103     }
104 
105     // In the file containing the Segment Index box, the anchor point for a Segment Index box is the first byte
106     // after that box
107     int64_t mediaSegOffset = firstOffset + sidxEndOffset + 1;
108 
109     // skip reserved
110     ForwardBytes(currPos, SHIFT_NUM_2);
111 
112     uint32_t referenceCount = Get2Bytes(bitStream, currPos);
113     if ((referenceCount * SIDX_REFERENCE_ITEM_SIZE + currPos) > streamSize) {
114         MEDIA_LOG_W("sidx box reference count error: " PUBLIC_LOG_U32 ", currPos:" PUBLIC_LOG_U32 ", streamSize:"
115             PUBLIC_LOG_U32, referenceCount, currPos, streamSize);
116         return false;
117     }
118 
119     MEDIA_LOG_D("sidx box reference count " PUBLIC_LOG_U32, referenceCount);
120     for (uint32_t i = 0; i < referenceCount; i++) {
121         std::shared_ptr<SubSegmentIndex> subSegIndex = std::make_shared<SubSegmentIndex>();
122         uint32_t typeAndSize = Get4Bytes(bitStream, currPos);
123         subSegIndex->referenceType_ = static_cast<int32_t>(GetReferenceType(typeAndSize));
124         subSegIndex->referencedSize_ = static_cast<int32_t>(GetReferenceSize(typeAndSize));
125         subSegIndex->startPos_ = mediaSegOffset;
126         subSegIndex->endPos_ = mediaSegOffset + subSegIndex->referencedSize_ - 1;
127         mediaSegOffset = subSegIndex->endPos_ + 1;
128         subSegIndex->duration_ = Get4Bytes(bitStream, currPos);
129         subSegIndex->timeScale_ = timescale;
130         Get4Bytes(bitStream, currPos); // uint32_t sapInfo
131         subSegIndexTable.push_back(subSegIndex);
132     }
133     return true;
134 }
135 
Get2Bytes(char * buffer,uint32_t & currPos)136 unsigned short Get2Bytes(char *buffer, uint32_t &currPos)
137 {
138     unsigned char *tmpBuff = reinterpret_cast<unsigned char *>(buffer + currPos);
139     currPos += SHIFT_NUM_2;
140     return (tmpBuff[BUFF_INDEX_0] << SHIFT_NUM_8) | tmpBuff[BUFF_INDEX_1];
141 }
142 
Get4Bytes(char * buffer,uint32_t & currPos)143 uint32_t Get4Bytes(char *buffer, uint32_t &currPos)
144 {
145     unsigned char *tmpBuff = reinterpret_cast<unsigned char *>(buffer + currPos);
146     currPos += SHIFT_NUM_4;
147     return (tmpBuff[BUFF_INDEX_0] << SHIFT_NUM_24) | (tmpBuff[BUFF_INDEX_1] << SHIFT_NUM_16) |
148            (tmpBuff[BUFF_INDEX_2] << SHIFT_NUM_8) | tmpBuff[BUFF_INDEX_3];
149 }
150 
Get8Bytes(char * buffer,uint32_t & currPos)151 int64_t Get8Bytes(char *buffer, uint32_t &currPos)
152 {
153     uint64_t tmp = Get4Bytes(buffer, currPos);
154     tmp = (tmp << SHIFT_NUM_32) | Get4Bytes(buffer, currPos);
155     return static_cast<int64_t>(tmp);
156 }
157 
GetVersion(uint32_t vflag)158 uint32_t GetVersion(uint32_t vflag)
159 {
160     return (vflag >> SHIFT_NUM_24) & 0xff;
161 }
162 
GetReferenceType(uint32_t typeAndSize)163 uint32_t GetReferenceType(uint32_t typeAndSize)
164 {
165     return (typeAndSize >> SHIFT_NUM_31) & 0xff;
166 }
167 
GetReferenceSize(uint32_t typeAndSize)168 uint32_t GetReferenceSize(uint32_t typeAndSize)
169 {
170     return typeAndSize & 0x7fffffff;
171 }
172 
ForwardBytes(uint32_t & currPos,uint32_t skipSize)173 void ForwardBytes(uint32_t &currPos, uint32_t skipSize)
174 {
175     currPos += skipSize;
176 }
177 
BemSource(char s,char i,char d,char x)178 uint32_t BemSource(char s, char i, char d, char x)
179 {
180     return (x) | ((d) << SHIFT_NUM_8) | ((i) << SHIFT_NUM_16) | ((s) << SHIFT_NUM_24);
181 }
182 } // namespace HttpPluginLite
183 } // namespace Plugin
184 } // namespace Media
185 } // namespace OHOS