summaryrefslogtreecommitdiff
path: root/src/video.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2021-11-17 22:34:57 +0100
committerJoel Klinghed <the_jk@spawned.biz>2021-11-17 22:34:57 +0100
commit6232d13f5321b87ddf12a1aa36b4545da45f173d (patch)
tree23f3316470a14136debd9d02f9e920ca2b06f4cc /src/video.cc
Travel3: Simple image and video display site
Reads the images and videos from filesystem and builds a site in memroy.
Diffstat (limited to 'src/video.cc')
-rw-r--r--src/video.cc171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/video.cc b/src/video.cc
new file mode 100644
index 0000000..110bd4a
--- /dev/null
+++ b/src/video.cc
@@ -0,0 +1,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;
+}