1 /*
2  * Copyright (c) 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 #ifndef PTS_AND_INDEX_CONVERSION_H
16 #define PTS_AND_INDEX_CONVERSION_H
17 
18 #include "securec.h"
19 #include <vector>
20 #include <map>
21 #include <queue>
22 #include <list>
23 #include "meta/meta.h"
24 #include "buffer/avbuffer.h"
25 #include "plugin/plugin_buffer.h"
26 #include "plugin/plugin_definition.h"
27 #include "common/media_source.h"
28 #include "stream_demuxer.h"
29 
30 #define BOX_TYPE_FTYP "ftyp"
31 #define BOX_TYPE_MOOV "moov"
32 #define BOX_TYPE_MVHD "mvhd"
33 #define BOX_TYPE_TRAK "trak"
34 #define BOX_TYPE_MDIA "mdia"
35 #define BOX_TYPE_MINF "minf"
36 #define BOX_TYPE_STBL "stbl"
37 #define BOX_TYPE_STTS "stts"
38 #define BOX_TYPE_CTTS "ctts"
39 #define BOX_TYPE_HDLR "hdlr"
40 #define BOX_TYPE_MDHD "mdhd"
41 
42 namespace OHOS {
43 namespace Media {
44 using MediaSource = OHOS::Media::Plugins::MediaSource;
45 using Buffer = OHOS::Media::Plugins::Buffer;
46 class Source;
47 
48 class TimeAndIndexConversion {
49 public:
50     TimeAndIndexConversion();
51     ~TimeAndIndexConversion() ;
52     Status SetDataSource(const std::shared_ptr<MediaSource>& source);
53     Status GetFirstVideoTrackIndex(uint32_t &trackIndex);
54     Status GetIndexByRelativePresentationTimeUs(const uint32_t trackIndex,
55         const uint64_t relativePresentationTimeUs, uint32_t &index);
56     Status GetRelativePresentationTimeUsByIndex(const uint32_t trackIndex,
57         const uint32_t index, uint64_t &relativePresentationTimeUs);
58 private:
59     enum IndexAndPTSConvertMode : unsigned int {
60         GET_FIRST_PTS,
61         INDEX_TO_RELATIVEPTS,
62         RELATIVEPTS_TO_INDEX,
63     };
64 
65     enum TrakType : unsigned int {
66         TRAK_OTHER,
67         TRAK_AUDIO,
68         TRAK_VIDIO,
69     };
70 
71     struct BoxHeader {
72         uint32_t size;
73         char type[5];
74     };
75 
76     struct STTSEntry {
77         uint32_t sampleCount;
78         uint32_t sampleDelta;
79     };
80 
81     struct CTTSEntry {
82         uint32_t sampleCount;
83         int32_t sampleOffset;
84     };
85 
86     struct TrakInfo {
87         uint32_t trakId;
88         TrakType trakType;
89         uint32_t timeScale;
90         std::vector<STTSEntry> sttsEntries;
91         std::vector<CTTSEntry> cttsEntries;
92     };
93 
94     std::shared_ptr<Source> source_{nullptr};
95     uint64_t mediaDataSize_ = 0;
96     uint64_t offset_ = 0;
97     uint64_t fileSize_ = 0;
98 
99     TrakInfo curTrakInfo_{0};
100     uint32_t curTrakInfoIndex_ = 0;
101     std::vector<TrakInfo> trakInfoVec_;
102 
103     std::map<std::string, void(TimeAndIndexConversion::*)(uint32_t)> boxParsers = {
104         {BOX_TYPE_STTS, &TimeAndIndexConversion::ParseStts},
105         {BOX_TYPE_CTTS, &TimeAndIndexConversion::ParseCtts},
106         {BOX_TYPE_HDLR, &TimeAndIndexConversion::ParseHdlr},
107         {BOX_TYPE_MDHD, &TimeAndIndexConversion::ParseMdhd},
108         {BOX_TYPE_STBL, &TimeAndIndexConversion::ParseBox},
109         {BOX_TYPE_MINF, &TimeAndIndexConversion::ParseBox},
110         {BOX_TYPE_MDIA, &TimeAndIndexConversion::ParseBox},
111     };
112 
113     void StartParse();
114     void ReadLargeSize(std::shared_ptr<Buffer> buffer, uint64_t &largeSize);
115     void ReadBufferFromDataSource(size_t bufSize, std::shared_ptr<Buffer> &buffer);
116     void ReadBoxHeader(std::shared_ptr<Buffer> buffer, BoxHeader &header);
117     bool IsMP4orMOV();
118     void ParseMoov(uint32_t boxSize);
119     void ParseTrak(uint32_t boxSize);
120     void ParseBox(uint32_t boxSize);
121     void ParseCtts(uint32_t boxSize);
122     void ParseStts(uint32_t boxSize);
123     void ParseHdlr(uint32_t boxSize);
124     void ParseMdhd(uint32_t boxSize);
125 
126     Status GetPresentationTimeUsFromFfmpegMOV(IndexAndPTSConvertMode mode,
127         uint32_t trackIndex, int64_t absolutePTS, uint32_t index);
128     Status PTSAndIndexConvertSttsAndCttsProcess(IndexAndPTSConvertMode mode,
129         int64_t absolutePTS, uint32_t index);
130     Status PTSAndIndexConvertOnlySttsProcess(IndexAndPTSConvertMode mode,
131         int64_t absolutePTS, uint32_t index);
132     void InitPTSandIndexConvert();
133     bool IsWithinPTSAndIndexConversionMaxFrames(uint32_t trackIndex);
134     void IndexToRelativePTSProcess(int64_t pts, uint32_t index);
135     void RelativePTSToIndexProcess(int64_t pts, int64_t absolutePTS);
136     void PTSAndIndexConvertSwitchProcess(IndexAndPTSConvertMode mode,
137         int64_t pts, int64_t absolutePTS, uint32_t index);
138     int64_t absolutePTSIndexZero_ = INT64_MAX;
139     std::priority_queue<int64_t> indexToRelativePTSMaxHeap_;
140     uint32_t indexToRelativePTSFrameCount_ = 0;
141     uint32_t relativePTSToIndexPosition_ = 0;
142     int64_t relativePTSToIndexPTSMin_ = INT64_MAX;
143     int64_t relativePTSToIndexPTSMax_ = INT64_MIN;
144     int64_t relativePTSToIndexRightDiff_ = INT64_MAX;
145     int64_t relativePTSToIndexLeftDiff_ = INT64_MAX;
146     int64_t relativePTSToIndexTempDiff_ = INT64_MAX;
147     uint32_t curConvertTrakInfoIndex_ = 0;
148 };
149 } // namespace Media
150 } // namespace OHOS
151 #endif // PTS_AND_INDEX_CONVERSION_H