• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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