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 "MediaDemuxer"
17 #define MEDIA_ATOMIC_ABILITY
18
19 #include "media_demuxer.h"
20
21 #include <algorithm>
22 #include <memory>
23 #include <map>
24
25 #include "avcodec_common.h"
26 #include "avcodec_trace.h"
27 #include "cpp_ext/type_traits_ext.h"
28 #include "buffer/avallocator.h"
29 #include "common/event.h"
30 #include "common/log.h"
31 #include "hisysevent.h"
32 #include "meta/media_types.h"
33 #include "meta/meta.h"
34 #include "osal/utils/dump_buffer.h"
35 #include "plugin/plugin_info.h"
36 #include "plugin/plugin_buffer.h"
37 #include "source/source.h"
38 #include "stream_demuxer.h"
39 #include "media_core.h"
40 #include "osal/utils/dump_buffer.h"
41 #include "demuxer_plugin_manager.h"
42
43 namespace {
44 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_DEMUXER, "MediaDemuxer" };
45 } // namespace
46
47 namespace OHOS {
48 namespace Media {
49 constexpr int64_t MAX_PTS_DIFFER_THRESHOLD_US = 10000000; // The maximum difference between Segment 10s.
50 constexpr int64_t INVALID_PTS_DATA = -1; // The invalid pts data -1.
51 constexpr int64_t PTS_MICRO_ADJUSTMENT_US = 1000;
52
HandleAutoMaintainPts(int32_t trackId,std::shared_ptr<AVBuffer> sample)53 void MediaDemuxer::HandleAutoMaintainPts(int32_t trackId, std::shared_ptr<AVBuffer> sample)
54 {
55 if (!isAutoMaintainPts_) {
56 return;
57 }
58 int64_t curPacketPts = sample->pts_;
59 std::shared_ptr<MaintainBaseInfo> baseInfo = maintainBaseInfos_[trackId];
60 if (baseInfo == nullptr) {
61 MEDIA_LOG_E("BaseInfo is nullptr, track " PUBLIC_LOG_D32, trackId);
62 return;
63 }
64 int64_t diff = 0;
65 diff = curPacketPts - baseInfo->lastPts;
66 auto oldPts = baseInfo->lastPts;
67 baseInfo->lastPts = curPacketPts;
68 if (diff < 0) {
69 diff = 0 - diff;
70 }
71
72 if (baseInfo->segmentOffset == INVALID_PTS_DATA) {
73 int64_t offset = static_cast<int64_t>(source_->GetSegmentOffset());
74 if (baseInfo->segmentOffset != offset) {
75 baseInfo->segmentOffset = offset;
76 baseInfo->basePts = curPacketPts;
77 }
78 sample->pts_ = baseInfo->segmentOffset + curPacketPts - baseInfo->basePts + mediaStartPts_;
79 } else if (diff > MAX_PTS_DIFFER_THRESHOLD_US) {
80 if (baseInfo->isLastPtsChange) {
81 int64_t offset = static_cast<int64_t>(source_->GetSegmentOffset());
82 if (baseInfo->segmentOffset != offset) {
83 baseInfo->segmentOffset = offset;
84 baseInfo->basePts = baseInfo->candidateBasePts;
85 }
86 sample->pts_ = baseInfo->segmentOffset + curPacketPts - baseInfo->basePts + mediaStartPts_;
87 baseInfo->isLastPtsChange = false;
88 } else {
89 sample->pts_ = baseInfo->lastPtsModifyedMax + PTS_MICRO_ADJUSTMENT_US;
90 baseInfo->candidateBasePts = curPacketPts;
91 baseInfo->isLastPtsChange = true;
92 baseInfo->lastPts = oldPts;
93 }
94 } else {
95 sample->pts_ = baseInfo->segmentOffset + curPacketPts - baseInfo->basePts + mediaStartPts_;
96 baseInfo->isLastPtsChange = false;
97 }
98 baseInfo->lastPtsModifyedMax = std::max(sample->pts_, baseInfo->lastPtsModifyedMax);
99
100 MEDIA_LOG_I("Success, track:" PUBLIC_LOG_D32 ", orgPts:"
101 PUBLIC_LOG_D64 ", pts:" PUBLIC_LOG_D64 ", basePts: " PUBLIC_LOG_D64, trackId,
102 curPacketPts, sample->pts_, baseInfo->basePts);
103 }
104
InitPtsInfo()105 void MediaDemuxer::InitPtsInfo()
106 {
107 if (source_ == nullptr || !source_->GetHLSDiscontinuity()) {
108 return;
109 }
110 MEDIA_LOG_I("Enable hls disContinuity auto maintain pts");
111 isAutoMaintainPts_ = true;
112 AutoLock lock(mapMutex_);
113 for (auto it = bufferQueueMap_.begin(); it != bufferQueueMap_.end(); it++) {
114 int32_t trackId = it->first;
115 if (maintainBaseInfos_[trackId] == nullptr) {
116 maintainBaseInfos_[trackId] = std::make_shared<MaintainBaseInfo>();
117 }
118 maintainBaseInfos_[trackId]->segmentOffset = INVALID_PTS_DATA;
119 maintainBaseInfos_[trackId]->basePts = INVALID_PTS_DATA;
120 maintainBaseInfos_[trackId]->isLastPtsChange = false;
121 maintainBaseInfos_[trackId]->lastPtsModifyedMax = INVALID_PTS_DATA;
122 }
123 }
124
InitMediaStartPts()125 void MediaDemuxer::InitMediaStartPts()
126 {
127 std::string mime;
128 int64_t startTime = 0;
129 for (const auto& trackInfo : mediaMetaData_.trackMetas) {
130 if (trackInfo == nullptr || !(trackInfo->GetData(Tag::MIME_TYPE, mime))) {
131 MEDIA_LOG_W("TrackInfo is null or get mime fail");
132 continue;
133 }
134 if (!(mime.find("audio/") == 0 || mime.find("video/") == 0)) {
135 continue;
136 }
137 if (trackInfo->GetData(Tag::MEDIA_START_TIME, startTime) &&
138 (mediaStartPts_ == HST_TIME_NONE || startTime < mediaStartPts_)) {
139 mediaStartPts_ = startTime;
140 }
141 }
142 }
143
TranscoderInitMediaStartPts()144 void MediaDemuxer::TranscoderInitMediaStartPts()
145 {
146 // Init media start time based on the first video track and the first audio track
147 std::string mime;
148 int64_t startTime = 0;
149 bool isInitVideoStartTime = false;
150 bool isInitAudioStartTime = false;
151 for (const auto& trackInfo : mediaMetaData_.trackMetas) {
152 if (trackInfo == nullptr || !(trackInfo->GetData(Tag::MIME_TYPE, mime))) {
153 MEDIA_LOG_W("TrackInfo is null or get mime fail");
154 continue;
155 }
156 if (!isInitVideoStartTime && (mime.find("video/") == 0)) {
157 isInitVideoStartTime = true;
158 FALSE_RETURN(trackInfo->GetData(Tag::MEDIA_START_TIME, startTime));
159 if (transcoderStartPts_ == HST_TIME_NONE || startTime < transcoderStartPts_) {
160 transcoderStartPts_ = startTime;
161 }
162 } else if (!isInitAudioStartTime && (mime.find("audio/") == 0)) {
163 isInitAudioStartTime = true;
164 FALSE_RETURN(trackInfo->GetData(Tag::MEDIA_START_TIME, startTime));
165 if (transcoderStartPts_ == HST_TIME_NONE || startTime < transcoderStartPts_) {
166 transcoderStartPts_ = startTime;
167 }
168 }
169 if (isInitAudioStartTime && isInitVideoStartTime) {
170 break;
171 }
172 }
173 }
174 } // namespace Media
175 } // namespace OHOS
176