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 #include "reader.h"
17
18 #include "dp_utils.h"
19 #include "track_factory.h"
20
21 namespace OHOS {
22 namespace CameraStandard {
23 namespace DeferredProcessing {
24 namespace {
25 constexpr int32_t DEFAULT_INT_VAL = 0;
26 constexpr double DEFAULT_DOUBLE_VAL = 0.0;
27 constexpr int32_t FPS_30 = 30;
28 constexpr int32_t FPS_60 = 60;
29 constexpr double FACTOR = 1.1;
30 }
31
~Reader()32 Reader::~Reader()
33 {
34 source_ = nullptr;
35 sourceFormat_ = nullptr;
36 inputDemuxer_ = nullptr;
37 tracks_.clear();
38 }
39
Create(int32_t inputFd)40 MediaManagerError Reader::Create(int32_t inputFd)
41 {
42 DP_DEBUG_LOG("entered.");
43 DP_CHECK_ERROR_RETURN_RET_LOG(inputFd == INVALID_FD, ERROR_FAIL, "inputFd is invalid: %{public}d.", inputFd);
44
45 auto off = lseek(inputFd, DEFAULT_OFFSET, SEEK_END);
46 DP_CHECK_ERROR_RETURN_RET_LOG(off == static_cast<off_t>(ERROR_FAIL), ERROR_FAIL, "Reader lseek failed.");
47 source_ = MediaAVCodec::AVSourceFactory::CreateWithFD(inputFd, DEFAULT_OFFSET, off);
48 DP_CHECK_ERROR_RETURN_RET_LOG(source_ == nullptr, ERROR_FAIL, "Create avsource failed.");
49
50 auto ret = GetSourceFormat();
51 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "Get avsource format failed.");
52
53 ret = GetUserMeta();
54 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "Get user format failed.");
55
56 ret = InitTracksAndDemuxer();
57 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "Init tracks and demuxer failed.");
58 return OK;
59 }
60
GetSourceFormat()61 MediaManagerError Reader::GetSourceFormat()
62 {
63 DP_DEBUG_LOG("entered.");
64 DP_CHECK_ERROR_RETURN_RET_LOG(source_ == nullptr, ERROR_FAIL, "AVSource is nullptr.");
65
66 Format sourceFormat;
67 auto ret = source_->GetSourceFormat(sourceFormat);
68 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "Get avsource format failed.");
69 sourceFormat_ = std::make_shared<Format>(sourceFormat);
70 return OK;
71 }
72
GetUserMeta()73 MediaManagerError Reader::GetUserMeta()
74 {
75 DP_DEBUG_LOG("entered.");
76 DP_CHECK_ERROR_RETURN_RET_LOG(source_ == nullptr, ERROR_FAIL, "AVSource is nullptr.");
77
78 Format userFormat;
79 auto ret = source_->GetUserMeta(userFormat);
80 DP_CHECK_ERROR_RETURN_RET_LOG(ret != static_cast<int32_t>(OK), ERROR_FAIL, "Get user format failed.");
81 userFormat_ = std::make_shared<Format>(userFormat);
82 return OK;
83 }
84
InitTracksAndDemuxer()85 MediaManagerError Reader::InitTracksAndDemuxer()
86 {
87 DP_DEBUG_LOG("entered.");
88 DP_CHECK_ERROR_RETURN_RET_LOG(!sourceFormat_->GetIntValue(Tag::MEDIA_TRACK_COUNT, trackCount_), ERROR_FAIL,
89 "Get track count failed.");
90
91 for (int32_t index = 0; index < trackCount_; ++index) {
92 auto track = TrackFactory::GetInstance().CreateTrack(source_, index);
93 DP_LOOP_CONTINUE_LOG(track == nullptr, "Track index: %{public}d is nullptr.", index);
94 tracks_.emplace(std::pair(track->GetType(), track));
95 }
96 DP_DEBUG_LOG("TrackCount num: %{public}d, trackMap size: %{public}d",
97 trackCount_, static_cast<int32_t>(tracks_.size()));
98 inputDemuxer_ = std::make_shared<Demuxer>();
99 auto ret = inputDemuxer_->Create(source_, tracks_);
100 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "Audio demuxer init failed.");
101 return OK;
102 }
103
Read(Media::Plugins::MediaType trackType,std::shared_ptr<AVBuffer> & sample)104 MediaManagerError Reader::Read(Media::Plugins::MediaType trackType, std::shared_ptr<AVBuffer>& sample)
105 {
106 DP_CHECK_ERROR_RETURN_RET_LOG(inputDemuxer_ == nullptr, ERROR_FAIL, "Demuxer is nullptr.");
107 auto ret = inputDemuxer_->ReadStream(trackType, sample);
108 DP_CHECK_ERROR_RETURN_RET_LOG(ret == ERROR_FAIL, ERROR_FAIL,
109 "Read sample failed, track type: %{public}d", trackType);
110 DP_CHECK_RETURN_RET_LOG(ret == EOS, EOS, "Reading finished.");
111 return ret;
112 }
113
GetMediaInfo(std::shared_ptr<MediaInfo> & mediaInfo)114 MediaManagerError Reader::GetMediaInfo(std::shared_ptr<MediaInfo>& mediaInfo)
115 {
116 GetSourceMediaInfo(mediaInfo);
117 mediaInfo->streamCount = trackCount_;
118
119 auto it = tracks_.find(Media::Plugins::MediaType::VIDEO);
120 DP_CHECK_ERROR_RETURN_RET_LOG(it == tracks_.end(), ERROR_FAIL, "Not find video track.");
121
122 auto videoFormat = it->second->GetFormat();
123 GetTrackMediaInfo(videoFormat, mediaInfo);
124 return OK;
125 }
126
Reset(int64_t resetPts)127 MediaManagerError Reader::Reset(int64_t resetPts)
128 {
129 DP_DEBUG_LOG("entered.");
130 DP_CHECK_ERROR_RETURN_RET_LOG(resetPts < 0, ERROR_FAIL, "Invalid reset pts.");
131 DP_CHECK_ERROR_RETURN_RET_LOG(inputDemuxer_ == nullptr, ERROR_FAIL, "Demuxer is null.");
132
133 auto ret = inputDemuxer_->SeekToTime(resetPts);
134 DP_CHECK_ERROR_RETURN_RET_LOG(ret != OK, ERROR_FAIL, "Reset pts failed.");
135 return OK;
136 }
137
GetSourceMediaInfo(std::shared_ptr<MediaInfo> & mediaInfo) const138 void Reader::GetSourceMediaInfo(std::shared_ptr<MediaInfo>& mediaInfo) const
139 {
140 CheckAndGetValue(sourceFormat_, Tag::MEDIA_CREATION_TIME, mediaInfo->creationTime);
141 CheckAndGetValue(sourceFormat_, Tag::MEDIA_DURATION, mediaInfo->codecInfo.duration);
142 CheckAndGetValue(sourceFormat_, Tag::MEDIA_LATITUDE, mediaInfo->latitude);
143 CheckAndGetValue(sourceFormat_, Tag::MEDIA_LONGITUDE, mediaInfo->longitude);
144 CheckAndGetValue(userFormat_, LIVE_PHOTO_COVERTIME, mediaInfo->livePhotoCovertime);
145 std::string encParam;
146 CheckAndGetValue(userFormat_, STAGE_ENC_PARAM_KEY, encParam);
147 auto result = ParseKeyValue(encParam);
148 for (const auto& [tag, value] : result) {
149 if (tag == Tag::VIDEO_ENCODE_BITRATE_MODE) {
150 mediaInfo->codecInfo.bitMode = MapVideoBitrateMode(value);
151 } else if (tag == Tag::MEDIA_BITRATE) {
152 int64_t bitRate;
153 DP_CHECK_EXECUTE(StrToI64(value, bitRate), mediaInfo->codecInfo.bitRate = bitRate);
154 }
155 }
156 DP_INFO_LOG("MediaInfo creationTime: %{public}s, duration: %{public}" PRId64 ", livePhotoCovertime: %{public}f, "
157 "bitMode: %{public}d, bitRate: %{public}" PRId64,
158 mediaInfo->creationTime.c_str(), mediaInfo->codecInfo.duration, mediaInfo->livePhotoCovertime,
159 mediaInfo->codecInfo.bitMode, mediaInfo->codecInfo.bitRate);
160 }
161
GetTrackMediaInfo(const TrackFormat & trackFormat,std::shared_ptr<MediaInfo> & mediaInfo) const162 MediaManagerError Reader::GetTrackMediaInfo(const TrackFormat& trackFormat,
163 std::shared_ptr<MediaInfo>& mediaInfo) const
164 {
165 auto& format = trackFormat.format;
166 CheckAndGetValue(format, Tag::MIME_TYPE, mediaInfo->codecInfo.mimeType);
167 CheckAndGetValue(format, Tag::MEDIA_PROFILE, mediaInfo->codecInfo.profile);
168 CheckAndGetValue(format, Tag::MEDIA_LEVEL, mediaInfo->codecInfo.level);
169 CheckAndGetValue(format, Tag::VIDEO_WIDTH, mediaInfo->codecInfo.width);
170 CheckAndGetValue(format, Tag::VIDEO_HEIGHT, mediaInfo->codecInfo.height);
171 CheckAndGetValue(format, Tag::VIDEO_ROTATION, mediaInfo->codecInfo.rotation);
172 DP_CHECK_EXECUTE(mediaInfo->codecInfo.bitRate == 0,
173 CheckAndGetValue(format, Tag::MEDIA_BITRATE, mediaInfo->codecInfo.bitRate));
174
175 int32_t intVal {DEFAULT_INT_VAL};
176 if (CheckAndGetValue(format, Tag::VIDEO_COLOR_RANGE, intVal)) {
177 mediaInfo->codecInfo.colorRange = static_cast<ColorRange>(intVal);
178 }
179 if (CheckAndGetValue(format, Tag::VIDEO_PIXEL_FORMAT, intVal)) {
180 mediaInfo->codecInfo.pixelFormat = static_cast<Media::Plugins::VideoPixelFormat>(intVal);
181 }
182 if (CheckAndGetValue(format, Tag::VIDEO_COLOR_PRIMARIES, intVal)) {
183 mediaInfo->codecInfo.colorPrimary = static_cast<Media::Plugins::ColorPrimary>(intVal);
184 }
185 if (CheckAndGetValue(format, Tag::VIDEO_COLOR_TRC, intVal)) {
186 mediaInfo->codecInfo.colorTransferCharacter = static_cast<Media::Plugins::TransferCharacteristic>(intVal);
187 }
188 if (CheckAndGetValue(format, Tag::VIDEO_IS_HDR_VIVID, intVal)) {
189 mediaInfo->codecInfo.isHdrvivid = static_cast<bool>(intVal);
190 }
191
192 double doubleVal {DEFAULT_DOUBLE_VAL};
193 if (CheckAndGetValue(format, Tag::VIDEO_FRAME_RATE, doubleVal)) {
194 mediaInfo->codecInfo.fps = FixFPS(doubleVal);
195 }
196
197 DP_INFO_LOG("TrackMediaInfo colorRange: %{public}d, pixelFormat: %{public}d, colorPrimary: %{public}d, "
198 "transfer: %{public}d, profile: %{public}d, level: %{public}d, bitRate: %{public}" PRId64 ", "
199 "fps: %{public}d, rotation: %{public}d, mime: %{public}s, isHdrvivid: %{public}d",
200 mediaInfo->codecInfo.colorRange, mediaInfo->codecInfo.pixelFormat, mediaInfo->codecInfo.colorPrimary,
201 mediaInfo->codecInfo.colorTransferCharacter, mediaInfo->codecInfo.profile, mediaInfo->codecInfo.level,
202 mediaInfo->codecInfo.bitRate, mediaInfo->codecInfo.fps, mediaInfo->codecInfo.rotation,
203 mediaInfo->codecInfo.mimeType.c_str(), mediaInfo->codecInfo.isHdrvivid);
204 return OK;
205 }
206
FixFPS(const double fps)207 inline int32_t Reader::FixFPS(const double fps)
208 {
209 return fps < static_cast<double>(FPS_30) * FACTOR ? FPS_30 : FPS_60;
210 }
211
MapVideoBitrateMode(const std::string & modeName) const212 Media::Plugins::VideoEncodeBitrateMode Reader::MapVideoBitrateMode(const std::string& modeName) const
213 {
214 static const std::unordered_map<std::string, Media::Plugins::VideoEncodeBitrateMode> modeMap = {
215 {"CBR", Media::Plugins::VideoEncodeBitrateMode::CBR},
216 {"VBR", Media::Plugins::VideoEncodeBitrateMode::VBR},
217 {"CQ", Media::Plugins::VideoEncodeBitrateMode::CQ},
218 {"CRF", Media::Plugins::VideoEncodeBitrateMode::CRF},
219 {"SQR", Media::Plugins::VideoEncodeBitrateMode::SQR},
220 {"CBR_VIDEOCALL", Media::Plugins::VideoEncodeBitrateMode::CBR_VIDEOCALL}
221 };
222 auto it = modeMap.find(modeName);
223 DP_CHECK_RETURN_RET(it == modeMap.end(), Media::Plugins::VideoEncodeBitrateMode::CBR);
224 return it->second;
225 }
226 } // namespace DeferredProcessing
227 } // namespace CameraStandard
228 } // namespace OHOS
229