From f1ac571695d19a2b14de22113ee128226e391765 Mon Sep 17 00:00:00 2001
From: Piotr Kosko
Date: Thu, 1 Oct 2020 10:10:30 +0200
Subject: [PATCH] [Metadata] Aded getFrameAtTime method of MetadataFileHandle
[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-271
[Verification] Code compiles without errors.
Works well for mp4 video.
var path = "videos/sample_video.mp4";
function showBlob(bbb) {
var elem = document.getElementById("blobImage") || document.createElement("img");
elem.setAttribute("id", "blobImage");
elem.setAttribute("height", "240");
elem.setAttribute("width", "240");
elem.setAttribute("alt", "invalid frame");
document.getElementById("test").appendChild(elem)
var objectURL = URL.createObjectURL(bbb);
elem.src = objectURL;
}
var fileHandle = tizen.metadata.createFileHandle(path);
var frame = fileHandle.getFrameAtTime(2000, true);
console.log(frame);
showBlob(frame)
Change-Id: Ib39c32566fe1d63711d7ce5ce991f216d7a84389
---
src/metadata/metadata_api.js | 22 +++++++
src/metadata/metadata_file_handle.cc | 93 +++++++++++++++++++++-------
src/metadata/metadata_file_handle.h | 11 +++-
src/metadata/metadata_instance.cc | 38 ++++++++++++
src/metadata/metadata_instance.h | 1 +
5 files changed, 142 insertions(+), 23 deletions(-)
diff --git a/src/metadata/metadata_api.js b/src/metadata/metadata_api.js
index 8e78bdb9..236b758e 100755
--- a/src/metadata/metadata_api.js
+++ b/src/metadata/metadata_api.js
@@ -173,5 +173,27 @@ MetadataFileHandle.prototype.getThumbnailFrame = function() {
return new Blob([encodedData]);
};
+MetadataFileHandle.prototype.getFrameAtTime = function() {
+ var args = validator_.validateArgs(arguments, [
+ { name: 'timestamp', type: types_.UNSIGNED_LONG },
+ { name: 'isAccurate', type: types_.BOOLEAN, optional: true }
+ ]);
+
+ var data = {
+ uri: this.uri,
+ id: this._id,
+ timestamp: args.timestamp,
+ isAccurate: args.isAccurate
+ };
+
+ var result = native_.callSync('MetadataFileHandleGetFrameAtTime', data);
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+ var encodedData = StringToArray(native_.getResultObject(result), Uint8Array);
+
+ return new Blob([encodedData]);
+};
+
// Exports
exports = new MetadataManager();
diff --git a/src/metadata/metadata_file_handle.cc b/src/metadata/metadata_file_handle.cc
index 9a0ce85e..b3d97613 100644
--- a/src/metadata/metadata_file_handle.cc
+++ b/src/metadata/metadata_file_handle.cc
@@ -107,13 +107,13 @@ std::string convertUriToPath(const std::string& str) {
}
}
-MetadataFileHandle::MetadataFileHandle(int id) : handle_(nullptr), id_(id) {
+MetadataFileHandle::MetadataFileHandle(int id) : handle_(nullptr), id_(id), width_(0), height_(0) {
ScopeLogger();
}
// 'this' owns a handle_, and uri_ and invalidates 'o'
MetadataFileHandle::MetadataFileHandle(MetadataFileHandle&& o)
- : handle_(nullptr), id_(o.id_), uri_(std::move(o.uri_)) {
+ : handle_(nullptr), id_(o.id_), uri_(std::move(o.uri_)), width_(0), height_(0) {
ScopeLogger();
handle_ = o.handle_;
o.handle_ = nullptr;
@@ -126,6 +126,8 @@ MetadataFileHandle& MetadataFileHandle::operator=(MetadataFileHandle&& o) {
o.handle_ = nullptr;
id_ = o.id_;
uri_ = std::move(o.uri_);
+ width_ = o.width_;
+ height_ = o.height_;
return *this;
}
@@ -223,22 +225,10 @@ PlatformResult MetadataFileHandle::GetArtwork(std::vector* artwork
return PlatformResult(ErrorCode::NO_ERROR);
}
-// convert frame buffer from raw RGB888 to JPG encoding
-PlatformResult MetadataFileHandle::EncodeJPEG(unsigned char* frame, size_t frame_size,
- std::uint8_t** uint8_frame, size_t* buffer_size) {
- ScopeLogger();
- image_util_type_e encoder_type = IMAGE_UTIL_JPEG;
- image_util_encode_h encode_handle = nullptr;
- image_util_image_h image = nullptr;
- SCOPE_EXIT {
- image_util_encode_destroy(encode_handle);
- image_util_destroy_image(image);
- };
-
- int ret = image_util_encode_create(encoder_type, &encode_handle);
- if (IMAGE_UTIL_ERROR_NONE != ret) {
- LoggerE("Error during jpg encoding: %d", ret);
- return convertErrorCode(ret);
+PlatformResult MetadataFileHandle::InitWidthHeight() {
+ if (width_ != 0 && height_ != 0) {
+ LoggerD("Size already initialized");
+ return PlatformResult(ErrorCode::NO_ERROR);
}
char* value = nullptr;
@@ -247,7 +237,7 @@ PlatformResult MetadataFileHandle::EncodeJPEG(unsigned char* frame, size_t frame
LoggerE("Error during getting metadata: %d", native_res);
return convertErrorCode(native_res);
}
- unsigned int width = (unsigned long)atoi(value);
+ width_ = (unsigned long)atoi(value);
free(value);
value = nullptr;
@@ -256,11 +246,37 @@ PlatformResult MetadataFileHandle::EncodeJPEG(unsigned char* frame, size_t frame
LoggerE("Error during getting metadata: %d", native_res);
return convertErrorCode(native_res);
}
- unsigned int height = (unsigned long)atoi(value);
+ height_ = (unsigned long)atoi(value);
free(value);
value = nullptr;
- ret = image_util_create_image(width, height, IMAGE_UTIL_COLORSPACE_RGB888, frame, frame_size,
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+// convert frame buffer from raw RGB888 to JPG encoding
+PlatformResult MetadataFileHandle::EncodeJPEG(unsigned char* frame, size_t frame_size,
+ std::uint8_t** uint8_frame, size_t* buffer_size) {
+ ScopeLogger();
+ image_util_type_e encoder_type = IMAGE_UTIL_JPEG;
+ image_util_encode_h encode_handle = nullptr;
+ image_util_image_h image = nullptr;
+ SCOPE_EXIT {
+ image_util_encode_destroy(encode_handle);
+ image_util_destroy_image(image);
+ };
+
+ PlatformResult res = InitWidthHeight();
+ if (!res) {
+ return res;
+ }
+
+ int ret = image_util_encode_create(encoder_type, &encode_handle);
+ if (IMAGE_UTIL_ERROR_NONE != ret) {
+ LoggerE("Error during jpg encoding: %d", ret);
+ return convertErrorCode(ret);
+ }
+
+ ret = image_util_create_image(width_, height_, IMAGE_UTIL_COLORSPACE_RGB888, frame, frame_size,
&image);
if (IMAGE_UTIL_ERROR_NONE != ret) {
LoggerE("Error during jpg encoding: %d", ret);
@@ -312,5 +328,40 @@ PlatformResult MetadataFileHandle::GetFrame(std::vector* frame_arr
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult MetadataFileHandle::GetFrame(const unsigned long timestamp, const bool is_accurate,
+ std::vector* frame_array) {
+ ScopeLogger();
+ int size = 0;
+ size_t buffer_size = 0;
+ void* frame = nullptr;
+ char* mime_type = nullptr;
+ std::uint8_t* uint8_frame = nullptr;
+ SCOPE_EXIT {
+ free(frame);
+ free(mime_type);
+ free(uint8_frame);
+ };
+
+ int native_res =
+ metadata_extractor_get_frame_at_time(handle_, timestamp, is_accurate, &frame, &size);
+ if (METADATA_EXTRACTOR_ERROR_NONE != native_res) {
+ LoggerE("Error during getting metadata: %d", native_res);
+ return convertErrorCode(native_res);
+ }
+ LoggerD("Frame size %d", size);
+
+ // encode as JPEG
+ auto ret = EncodeJPEG((unsigned char*)frame, (size_t)size, &uint8_frame, &buffer_size);
+ if (!ret) {
+ return ret;
+ }
+
+ // convert frame to vector
+ std::vector out_buf(uint8_frame, uint8_frame + buffer_size);
+
+ *frame_array = std::move(out_buf);
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
} // namespace metadata
} // namespace extension
diff --git a/src/metadata/metadata_file_handle.h b/src/metadata/metadata_file_handle.h
index e7bcca86..2bcd8d03 100644
--- a/src/metadata/metadata_file_handle.h
+++ b/src/metadata/metadata_file_handle.h
@@ -39,14 +39,21 @@ class MetadataFileHandle {
common::PlatformResult Get(const std::string& type, std::string* result);
common::PlatformResult GetArtwork(std::vector* data, std::string* mime_type);
- common::PlatformResult EncodeJPEG(unsigned char* frame, size_t frame_size,
- std::uint8_t** uint8_frame, size_t* buffer_size);
common::PlatformResult GetFrame(std::vector* frame_array);
+ common::PlatformResult GetFrame(const unsigned long timestamp, const bool is_accurate,
+ std::vector* frame_array);
private:
+ common::PlatformResult InitWidthHeight();
+ common::PlatformResult EncodeJPEG(unsigned char* frame, size_t frame_size,
+ std::uint8_t** uint8_frame, size_t* buffer_size);
+
metadata_extractor_h handle_;
int id_;
std::string uri_;
+
+ unsigned int width_;
+ unsigned int height_;
};
} // namespace metadata
diff --git a/src/metadata/metadata_instance.cc b/src/metadata/metadata_instance.cc
index 449b9fcb..49e1cd62 100644
--- a/src/metadata/metadata_instance.cc
+++ b/src/metadata/metadata_instance.cc
@@ -36,6 +36,7 @@ MetadataInstance::MetadataInstance() : next_handle_id_(1) {
REGISTER_METHOD(MetadataFileHandleGet);
REGISTER_METHOD(MetadataFileHandleGetArtwork);
REGISTER_METHOD(MetadataFileHandleGetThumbnailFrame);
+ REGISTER_METHOD(MetadataFileHandleGetFrameAtTime);
REGISTER_METHOD(MetadataFileHandleRelease);
#undef REGISTER_METHOD
}
@@ -204,6 +205,43 @@ void MetadataInstance::MetadataFileHandleGetThumbnailFrame(const picojson::value
ReportSuccess(picojson::value(result_artwork), out);
}
+void MetadataInstance::MetadataFileHandleGetFrameAtTime(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ const std::string& uri = args.get("uri").get();
+ const int id = static_cast(args.get("id").get());
+ const unsigned long timestamp = static_cast(args.get("timestamp").get());
+ const bool is_accurate = args.get("isAccurate").get();
+
+ auto res = InitializeHandleIfNeeded(uri, id);
+ if (!res) {
+ LogAndReportError(res, &out);
+ return;
+ }
+
+ std::vector data;
+ std::string mime_type;
+ try {
+ MetadataFileHandle& m = handles_map_.at(id);
+
+ auto res = m.GetFrame(timestamp, is_accurate, &data);
+ if (!res) {
+ LogAndReportError(res, &out);
+ return;
+ }
+ } catch (...) {
+ // this should never happen
+ LogAndReportError(
+ PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out);
+ return;
+ }
+
+ std::string result_frame;
+ encode_binary_in_string(data, result_frame);
+
+ ReportSuccess(picojson::value(result_frame), out);
+}
+
void MetadataInstance::MetadataFileHandleRelease(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
diff --git a/src/metadata/metadata_instance.h b/src/metadata/metadata_instance.h
index 14e65358..26a3f499 100644
--- a/src/metadata/metadata_instance.h
+++ b/src/metadata/metadata_instance.h
@@ -34,6 +34,7 @@ class MetadataInstance : public common::ParsedInstance {
void MetadataFileHandleGet(const picojson::value& args, picojson::object& out);
void MetadataFileHandleGetArtwork(const picojson::value& args, picojson::object& out);
void MetadataFileHandleGetThumbnailFrame(const picojson::value& args, picojson::object& out);
+ void MetadataFileHandleGetFrameAtTime(const picojson::value& args, picojson::object& out);
void MetadataFileHandleRelease(const picojson::value& args, picojson::object& out);
std::map handles_map_;
--
2.34.1