[Metadata] Aded getFrameAtTime method of MetadataFileHandle 90/245090/4
authorPiotr Kosko <p.kosko@samsung.com>
Thu, 1 Oct 2020 08:10:30 +0000 (10:10 +0200)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Wed, 9 Dec 2020 06:00:07 +0000 (07:00 +0100)
[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
src/metadata/metadata_file_handle.cc
src/metadata/metadata_file_handle.h
src/metadata/metadata_instance.cc
src/metadata/metadata_instance.h

index 8e78bdb9695afc6bcb6a7e1bfc8fb9aaa40bd8ab..236b758e5951c504ed6e3b04fd2f68459b4beb42 100755 (executable)
@@ -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();
index 9a0ce85eac146fadd0bd282abe0d6253194e6570..b3d97613a458f23d39a97fb955f0be2890b9b9f5 100644 (file)
@@ -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<std::uint8_t>* 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<std::uint8_t>* frame_arr
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+PlatformResult MetadataFileHandle::GetFrame(const unsigned long timestamp, const bool is_accurate,
+                                            std::vector<std::uint8_t>* 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<std::uint8_t> out_buf(uint8_frame, uint8_frame + buffer_size);
+
+  *frame_array = std::move(out_buf);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace metadata
 }  // namespace extension
index e7bcca865ad5c2e4195f071f901db7a39c39662c..2bcd8d03497f3f3cd5efcbcc41e600d527071d05 100644 (file)
@@ -39,14 +39,21 @@ class MetadataFileHandle {
   common::PlatformResult Get(const std::string& type, std::string* result);
 
   common::PlatformResult GetArtwork(std::vector<std::uint8_t>* 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<std::uint8_t>* frame_array);
+  common::PlatformResult GetFrame(const unsigned long timestamp, const bool is_accurate,
+                                  std::vector<std::uint8_t>* 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
index 449b9fcb200a315429b703d2e67a5c4fa232ac47..49e1cd62e822cc10555f733946eb1f1316fc1d35 100644 (file)
@@ -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<std::string>();
+  const int id = static_cast<int>(args.get("id").get<double>());
+  const unsigned long timestamp = static_cast<unsigned long>(args.get("timestamp").get<double>());
+  const bool is_accurate = args.get("isAccurate").get<bool>();
+
+  auto res = InitializeHandleIfNeeded(uri, id);
+  if (!res) {
+    LogAndReportError(res, &out);
+    return;
+  }
+
+  std::vector<std::uint8_t> 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();
index 14e653584d9f91140699279426a46e3544127e07..26a3f4997fb7ac01b92fc28e5a18843dfed17740 100644 (file)
@@ -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<int, MetadataFileHandle> handles_map_;