1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
#include "common.hh"
#include "strutil.hh"
#include "timezone.hh"
#include "video.hh"
#if HAVE_MEDIAINFO
#include <MediaInfo/MediaInfo.h>
#endif
namespace {
class VideoImpl : public Video {
public:
VideoImpl(uint64_t width, uint64_t height)
: width_(width), height_(height) {}
uint64_t width() const override {
return width_;
}
uint64_t height() const override {
return height_;
}
double length() const override {
return length_;
}
Location location() const override {
return location_;
}
Date date() const override {
return date_;
}
void set_length(double length) {
length_ = length;
}
void set_location(Location location) {
location_ = location;
}
void set_date(Date date) {
date_ = date;
}
private:
uint64_t width_;
uint64_t height_;
double length_{0.0};
Location location_;
Date date_;
};
#if HAVE_MEDIAINFO
bool parse_location(std::string const& str, Location* location) {
auto end = str.find('/');
if (end == std::string::npos)
return false;
char* latend = nullptr;
location->lat = strtod(str.c_str(), &latend);
if (!latend)
return false;
char* lngend = nullptr;
location->lng = strtod(latend, &lngend);
if (!lngend)
return false;
if (lngend != str.c_str() + end)
return false;
return true;
}
#endif
} // namespace
std::unique_ptr<Video> Video::load(std::filesystem::path const& path,
Timezone const* timezone) {
#if HAVE_MEDIAINFO
MediaInfoLib::MediaInfo info;
#if defined(UNICODE) || defined (_UNICODE)
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
if (info.Open(convert.from_bytes(path))) {
auto width = str::parse_uint64(
convert.to_bytes(info.Get(MediaInfoLib::Stream_Video, 0, L"Width")));
auto height = str::parse_uint64(
convert.to_bytes(info.Get(MediaInfoLib::Stream_Video, 0, L"Height")));
if (width && height) {
std::optional<Location> location;
auto video = std::make_unique<VideoImpl>(*width, *height);
auto duration = str::parse_uint64(
convert.to_bytes(
info.Get(MediaInfoLib::Stream_Video, 0, L"Duration")));
if (duration)
video->set_length(*duration / 1000.0);
{
Location tmp;
if (parse_location(
convert.to_bytes(
info.Get(MediaInfoLib::Stream_General, 0, L"xyz")),
&tmp)) {
location = tmp;
video->set_location(tmp);
}
}
{
auto date = Date::from_format(
"UTC %Y-%m-%d %H:%M:%S",
convert.to_bytes(
info.Get(MediaInfoLib::Stream_General, 0, L"Encoded_Date")),
false);
if (!date.empty()) {
video->set_date(date.value());
if (location) {
auto local_time = timezone->get_local_time(location->lat,
location->lng,
date.value());
if (local_time)
video->set_date(local_time.value());
}
}
}
return video;
}
}
#else // UNICODE || _UNICODE
if (info.Open(path)) {
auto width = str::parse_uint64(
info.Get(MediaInfoLib::Stream_Video, 0, "Width"));
auto height = str::parse_uint64(
info.Get(MediaInfoLib::Stream_Video, 0, "Height"));
if (width && height) {
auto video = std::make_unique<VideoImpl>(*width, *height);
auto duration = str::parse_uint64(
info.Get(MediaInfoLib::Stream_Video, 0, "Duration"));
if (duration)
video->set_length(*duration / 1000.0);
std::optional<Location> location;
{
Location tmp;
if (parse_location(info.Get(MediaInfoLib::Stream_General, 0, "xyz"),
&tmp)) {
location = tmp;
video->set_location(tmp);
}
}
{
auto date = Date::from_format(
"UTC %Y-%m-%d %H:%M:%S",
info.Get(MediaInfoLib::Stream_General, 0, "Encoded_Date"),
false);
if (!date.empty()) {
video->set_date(date.value());
if (location) {
auto local_time = timezone->get_local_time(location->lat,
location->lng,
date.value());
if (local_time)
video->set_date(local_time.value());
}
}
}
return video;
}
}
#endif // UNICODE || _UNICODE
#endif // HAVE_MEDIAINFO
return nullptr;
}
|