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