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