1 /*
2 * Copyright (C) 2025 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 "media_player_framework_utils.h"
17
18 #include "directory_ex.h"
19 #include <fcntl.h>
20 #include "string_ex.h"
21 #include <sys/stat.h>
22
23 #include "unique_fd.h"
24
25 #include "medialibrary_errno.h"
26 #include "medialibrary_tracer.h"
27 #include "media_file_utils.h"
28 #include "media_log.h"
29
30 using namespace std;
31
32 namespace OHOS {
33 namespace Media {
34
35 uint32_t INT32_MAX_LENGTH = 11;
36
StrToInt32(const std::string & str,int32_t & ret)37 static bool StrToInt32(const std::string &str, int32_t &ret)
38 {
39 CHECK_AND_RETURN_RET_LOG((!str.empty()) && str.length() <= INT32_MAX_LENGTH,
40 false, "Convert failed, str = %{public}s", str.c_str());
41 CHECK_AND_RETURN_RET_LOG(IsNumericStr(str), false,
42 "Convert failed, input is not number, str = %{public}s", str.c_str());
43
44 int64_t numberValue = std::stoll(str);
45 CHECK_AND_RETURN_RET_LOG(numberValue >= INT32_MIN && numberValue <= INT32_MAX, false,
46 "Convert failed, number out of int32 range, str = %{public}s", str.c_str());
47
48 ret = static_cast<int32_t>(numberValue);
49 return true;
50 }
51
GetAVMetadataHelper(const std::string & path,AVMetadataUsage usage)52 std::shared_ptr<AVMetadataHelper> MediaPlayerFrameWorkUtils::GetAVMetadataHelper(
53 const std::string &path, AVMetadataUsage usage)
54 {
55 CHECK_AND_RETURN_RET_LOG((!path.empty()), nullptr, "Path is empty");
56
57 string absFilePath;
58 CHECK_AND_RETURN_RET_LOG(PathToRealPath(path, absFilePath), nullptr,
59 "Failed to open a nullptr path, errno=%{public}d, path:%{public}s",
60 errno, MediaFileUtils::DesensitizePath(path).c_str());
61
62 UniqueFd uniqueFd(open(absFilePath.c_str(), O_RDONLY));
63 CHECK_AND_RETURN_RET_LOG(uniqueFd.Get() >= 0, nullptr,
64 "Open file failed, errno:%{public}d, fd:%{public}d", errno, uniqueFd.Get());
65
66 struct stat64 st;
67 CHECK_AND_RETURN_RET_LOG(fstat64(uniqueFd.Get(), &st) == 0, nullptr,
68 "Get file state failed, err %{public}d", errno);
69
70 shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
71 CHECK_AND_RETURN_RET_LOG(avMetadataHelper != nullptr, nullptr, "AvMetadataHelper is nullptr");
72
73 int64_t length = static_cast<int64_t>(st.st_size);
74 int32_t ret = avMetadataHelper->SetSource(uniqueFd.Get(), 0, length, usage);
75 CHECK_AND_RETURN_RET_LOG(ret == E_OK, nullptr, "Set source failed, err:%{public}d", ret);
76 return avMetadataHelper;
77 }
78
GetExifRotate(const std::string & path,int32_t & exifRotate)79 int32_t MediaPlayerFrameWorkUtils::GetExifRotate(const std::string &path, int32_t &exifRotate)
80 {
81 shared_ptr<AVMetadataHelper> avMetadataHelper = GetAVMetadataHelper(path, AV_META_USAGE_META_ONLY);
82 CHECK_AND_RETURN_RET_LOG(avMetadataHelper != nullptr, E_ERR, "AvMetadataHelper is nullptr");
83
84 auto resultMap = avMetadataHelper->ResolveMetadata();
85 CHECK_AND_RETURN_RET_LOG(resultMap.count(AVMetadataCode::AV_KEY_VIDEO_ROTATE_ORIENTATION) != 0,
86 E_ERR, "Map does not have exif rotate");
87
88 std::string strOfExifRotate = resultMap.at(AVMetadataCode::AV_KEY_VIDEO_ROTATE_ORIENTATION);
89 return StrToInt32(strOfExifRotate, exifRotate) ? E_OK : E_ERR;
90 }
91 } // namespace Media
92 } // namespace OHOS