From: Piotr Kosko Date: Thu, 1 Oct 2020 06:02:45 +0000 (+0200) Subject: [Metadata] Aded getFrame method of MetadataFileHandle X-Git-Tag: submit/tizen/20201209.085808~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=26015ab14532cb05b28ce8bff912e27151ddf06a;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Metadata] Aded getFrame method of MetadataFileHandle [ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-271 [Verification] Code compiles withotu 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.getFrame(); console.log(frame); showBlob(frame) Change-Id: I2d5e81b19d7f11ff2c08a0096a0b58fb7e3bfc48 --- diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index dbad03bd..cebe7f4b 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -421,6 +421,9 @@ BuildRequires: pkgconfig(capi-appfw-app-manager) BuildRequires: pkgconfig(capi-appfw-package-manager) BuildRequires: pkgconfig(capi-content-media-content) BuildRequires: pkgconfig(capi-media-metadata-extractor) +# TODO check support on TV +BuildRequires: pkgconfig(capi-media-image-util) + BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(appsvc) diff --git a/src/metadata/metadata.gyp b/src/metadata/metadata.gyp index 0f43bf8b..2b999a7d 100644 --- a/src/metadata/metadata.gyp +++ b/src/metadata/metadata.gyp @@ -26,6 +26,8 @@ 'variables': { 'packages': [ 'capi-media-metadata-extractor', + # TODO check support on TV + 'capi-media-image-util', ] }, }], diff --git a/src/metadata/metadata_api.js b/src/metadata/metadata_api.js index 66a1fa65..8e78bdb9 100755 --- a/src/metadata/metadata_api.js +++ b/src/metadata/metadata_api.js @@ -158,5 +158,20 @@ MetadataFileHandle.prototype.getArtwork = function() { return new Blob([encodedData], { type: resultData.mimeType }); }; +MetadataFileHandle.prototype.getThumbnailFrame = function() { + var data = { + uri: this.uri, + id: this._id + }; + + var result = native_.callSync('MetadataFileHandleGetThumbnailFrame', 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 1e40e4e5..9a0ce85e 100644 --- a/src/metadata/metadata_file_handle.cc +++ b/src/metadata/metadata_file_handle.cc @@ -16,6 +16,8 @@ #include "metadata/metadata_file_handle.h" +#include + #include "common/logger.h" #include "common/platform_enum.h" #include "common/platform_exception.h" @@ -221,5 +223,94 @@ 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); + } + + char* value = nullptr; + int native_res = metadata_extractor_get_metadata(handle_, METADATA_VIDEO_WIDTH, &value); + if (METADATA_EXTRACTOR_ERROR_NONE != native_res) { + LoggerE("Error during getting metadata: %d", native_res); + return convertErrorCode(native_res); + } + unsigned int width = (unsigned long)atoi(value); + free(value); + value = nullptr; + + native_res = metadata_extractor_get_metadata(handle_, METADATA_VIDEO_HEIGHT, &value); + if (METADATA_EXTRACTOR_ERROR_NONE != native_res) { + LoggerE("Error during getting metadata: %d", native_res); + return convertErrorCode(native_res); + } + unsigned int height = (unsigned long)atoi(value); + free(value); + value = nullptr; + + 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); + return convertErrorCode(ret); + } + + unsigned char* jpg_buffer = nullptr; + ret = image_util_encode_run_to_buffer(encode_handle, image, &jpg_buffer, buffer_size); + if (IMAGE_UTIL_ERROR_NONE != ret) { + LoggerE("Error during jpg encoding: %d", ret); + return convertErrorCode(ret); + } + + // jpg_buffer is passed outside function and need to be released after usage + *uint8_frame = (std::uint8_t*)jpg_buffer; + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MetadataFileHandle::GetFrame(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(handle_, &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 67d31c54..e7bcca86 100644 --- a/src/metadata/metadata_file_handle.h +++ b/src/metadata/metadata_file_handle.h @@ -39,6 +39,9 @@ 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); private: metadata_extractor_h handle_; diff --git a/src/metadata/metadata_instance.cc b/src/metadata/metadata_instance.cc index 5e1db6b8..449b9fcb 100644 --- a/src/metadata/metadata_instance.cc +++ b/src/metadata/metadata_instance.cc @@ -35,6 +35,7 @@ MetadataInstance::MetadataInstance() : next_handle_id_(1) { REGISTER_METHOD(MetadataManagerCreateFileHandle); REGISTER_METHOD(MetadataFileHandleGet); REGISTER_METHOD(MetadataFileHandleGetArtwork); + REGISTER_METHOD(MetadataFileHandleGetThumbnailFrame); REGISTER_METHOD(MetadataFileHandleRelease); #undef REGISTER_METHOD } @@ -168,6 +169,41 @@ void MetadataInstance::MetadataFileHandleGetArtwork(const picojson::value& args, ReportSuccess(result_artwork, out); } +void MetadataInstance::MetadataFileHandleGetThumbnailFrame(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()); + + 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(&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_artwork; + encode_binary_in_string(data, result_artwork); + + ReportSuccess(picojson::value(result_artwork), 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 68eeddc4..14e65358 100644 --- a/src/metadata/metadata_instance.h +++ b/src/metadata/metadata_instance.h @@ -33,6 +33,7 @@ class MetadataInstance : public common::ParsedInstance { common::PlatformResult InitializeHandleIfNeeded(const std::string& uri, const int id); 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 MetadataFileHandleRelease(const picojson::value& args, picojson::object& out); std::map handles_map_;