[MM][WebRTC] OMX codec integration on m0 target.
authors.kamath <s.kamath@samsung.com>
Thu, 19 Feb 2015 13:05:04 +0000 (18:35 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
Added support for accelarated encoding/decoding with WebRTC.
Uses omxh264 encoder & decoder for accelaration.

Avoiding usage of convertor as camera output is in I420 format.
h264parser needed at decoder pipeline as omxh264dec take
parsed frames at src pad.
Reviewed by: Min-Soo Koo, Venugopal S M

Change-Id: I28708efeb48427125c3ba708c454cd556fb205c3
Signed-off-by: s.kamath <s.kamath@samsung.com>
tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.cc
tizen_src/impl/content/common/gpu/media/tizen/tizen_video_encode_accelerator.cc

index 1cfce5c..d83aa96 100644 (file)
@@ -235,6 +235,7 @@ bool TizenVideoDecodeAccelerator::Initialize(
   GError* error = NULL;
   GstCaps* video_caps = NULL;
   GstElement* gst_decoder = NULL;
+  GstElement* gst_parser = NULL;
   GstBus* gst_bus = NULL;
   GstPad* video_sink_pad = NULL;
   scoped_ptr<GstElement, GstElementDeleter> gst_pipeline;
@@ -301,13 +302,25 @@ bool TizenVideoDecodeAccelerator::Initialize(
   if (!(video_caps = gst_caps_from_string("video/x-h264,framerate=30/1"))) {
     return false;
   }
-  g_object_set(G_OBJECT(impl_->appsrc_), "caps", video_caps, NULL);
+  gst_app_src_set_caps(GST_APP_SRC(impl_->appsrc_), video_caps);
   gst_caps_unref(video_caps);
 
 #if defined(OS_TIZEN)
   DVLOG(1) << "######################################";
   DVLOG(1) << "      USING omx_h264dec DECODER " << (unsigned int)this;
   DVLOG(1) << "######################################";
+
+  // parser initialization
+  if (!(gst_parser = gst_element_factory_make("h264parse", "h264parse"))) {
+    LOG(ERROR) << " cannot create h264parse.";
+    return false;
+  }
+  if(!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_parser)) {
+    LOG(ERROR) << " cannot add h264parse into decoder pipeline.";
+    gst_object_unref(gst_parser);
+    return false;
+  }
+
   // decoder initialization.
   if (!(gst_decoder = gst_element_factory_make(kDecoderGstElement, kDecoderName))) {
     LOG(ERROR) << " cannot create " << kDecoderGstElement << ".";
@@ -341,8 +354,13 @@ bool TizenVideoDecodeAccelerator::Initialize(
 #endif
 
   // linking the elements.
-  if (!gst_element_link(impl_->appsrc_, gst_decoder)) {
-    LOG(ERROR) << __FUNCTION__ << " Source and Decoder could not be linked";
+  if (!gst_element_link(impl_->appsrc_, gst_parser)) {
+    LOG(ERROR) << " Source and gst_parser could not be linked";
+    return false;
+  }
+
+  if (!gst_element_link(gst_parser, gst_decoder)) {
+    LOG(ERROR) << " gst_parser and Decoder could not be linked";
     return false;
   }
   if (!gst_element_link(gst_decoder, impl_->sink_)) {
@@ -632,7 +650,7 @@ void TizenVideoDecodeAccelerator::OnDecode(
                                   buffer_ref->size_,
                                   reinterpret_cast<guint8*>(buffer_ref.get()),
                                   BitstreamBufferRef::Destruct);
-  if (!buffer_ref->gst_buffer_) {
+  if (!buffer_ref->gst_buffer_ || !GST_IS_BUFFER(buffer_ref->gst_buffer_)) {
     LOG(ERROR) << " gst_buffer_new_wrapped_full failed to allocate memory.!";
     return;
   }
index acec12e..2db7941 100644 (file)
@@ -152,7 +152,7 @@ void TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame() {
   media::BitstreamBuffer* bs_buffer = NULL;
   GstBuffer* buffer = NULL;
   bool key_frame = false;
-  gsize gstBufferSize = 0;
+  gsize gst_buffer_size = 0;
 #if GST_VERSION_MAJOR == 1
   GstMapInfo map;
 #endif
@@ -206,24 +206,25 @@ void TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame() {
       LOG (ERROR) << "Encoded Buffer contains invalid or no info.!";
       return;
   }
-  gstBufferSize = map.size;
+  gst_buffer_size = map.size;
 #else
-  gstBufferSize = buffer->size;
+  gst_buffer_size = buffer->size;
 #endif
 
 
-  if (gstBufferSize > shm->mapped_size()) {
+  if (gst_buffer_size > shm->mapped_size()) {
     LOG(ERROR) << "Encoded buff too large: "
-               << gstBufferSize << ">" << shm->mapped_size();
+               << gst_buffer_size << ">" << shm->mapped_size();
     io_client_weak_factory_.GetWeakPtr()->NotifyError(
         media::VideoEncodeAccelerator::kPlatformFailureError);
     gst_buffer_unref(buffer);
   }
   //copying data to shared memory.
 #if GST_VERSION_MAJOR == 1
-  memcpy(static_cast<uint8*>(shm->memory()), map.data, gstBufferSize);
+  memcpy(static_cast<uint8*>(shm->memory()), map.data, gst_buffer_size);
+  gst_buffer_unmap(buffer, &map);
 #else
-  memcpy(static_cast<uint8*>(shm->memory()), buffer->data, gstBufferSize);
+  memcpy(static_cast<uint8*>(shm->memory()), buffer->data, gst_buffer_size);
 #endif
 
   child_message_loop_proxy_->PostTask(
@@ -231,7 +232,7 @@ void TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame() {
       base::Bind(&media::VideoEncodeAccelerator::Client::BitstreamBufferReady,
                  io_client_weak_factory_.GetWeakPtr(),
                  bs_buffer->id(),
-                 gstBufferSize,
+                 gst_buffer_size,
                  key_frame));
 }
 
@@ -267,7 +268,9 @@ GstFlowReturn TizenVideoEncodeAccelerator::Impl::OnEncoded(
   } else {
     LOG(ERROR) << __FUNCTION__ << " ENCODING FRAME FAILED";
   }
-
+#if GST_VERSION_MAJOR == 1
+  gst_buffer_unmap(gst_output_buf, &map);
+#endif
   return GST_FLOW_OK;
 }
 
@@ -398,7 +401,11 @@ void TizenVideoEncodeAccelerator::RequestEncodingParametersChange(
     // Information can be gained by gst-inspect
 #if defined(OS_TIZEN)
     g_object_set(G_OBJECT(impl_->encoder_),
+#if GST_VERSION_MAJOR == 1
+                 "target-bitrate",
+#else
                  "bitrate",
+#endif
                  std::min(bitrate, static_cast<uint32>(MAX_BITRATE)),
                  NULL);
 #else
@@ -455,7 +462,7 @@ void TizenVideoEncodeAccelerator::OnEncode(
     return;
   }
 
-#if defined(OS_TIZEN)
+#if defined(OS_TIZEN) && GST_VERSION_MAJOR != 1
   g_object_set(impl_->encoder_,
                "force-i-frame",
                (force_keyframe || impl_->enable_framedrop_) ? TRUE : FALSE,
@@ -465,15 +472,14 @@ void TizenVideoEncodeAccelerator::OnEncode(
 #if GST_VERSION_MAJOR == 1
   bufref->gst_buffer_ =
       gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY,
-                                  static_cast<guint8*>(
-                                  bufref->frame_->data(VideoFrame::kYPlane)),
+                                  static_cast<guint8*>(bufref->frame_->data(VideoFrame::kYPlane)),
                                   bufref->size_,
                                   0,
                                   bufref->size_,
                                   reinterpret_cast<uint8*>(bufref),
                                   BitstreamBufferRef::Destruct);
-  if (!bufref->gst_buffer_) {
-      LOG(ERROR) << " gst_buffer_new_wrapped_full failed to allocate memory.";
+  if (!bufref->gst_buffer_ || !GST_IS_BUFFER(bufref->gst_buffer_)) {
+      LOG(INFO) << " gst_buffer_new_wrapped_full failed to allocate memory.";
       return;
   }
 #else
@@ -510,8 +516,8 @@ void TizenVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
 
 bool TizenVideoEncodeAccelerator::StartEncoder() {
   GError* error = NULL;
-  GstCaps* appsrc_caps = NULL, *converter_caps = NULL;
-  GstElement* gst_converter = NULL, *gst_appsink = NULL;
+  GstCaps* appsrc_caps = NULL;
+  GstElement* gst_appsink = NULL;
   gboolean retval = FALSE;
   scoped_ptr<GstElement, GstElementDeleter> gst_pipeline;
 
@@ -554,15 +560,17 @@ bool TizenVideoEncodeAccelerator::StartEncoder() {
     return false;
   }
   appsrc_caps = gst_caps_new_simple(
-      "video/x-raw-yuv",
 #if GST_VERSION_MAJOR == 1
+      "video/x-raw",
       "format", G_TYPE_STRING, gst_video_format_to_string(GST_VIDEO_FORMAT_I420),
 #else
+      "video/x-raw-yuv",
       "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I', '4', '2', '0'),
 #endif
       "width", G_TYPE_INT, impl_->view_size_.width(),
       "height", G_TYPE_INT, impl_->view_size_.height(),
       "framerate", GST_TYPE_FRACTION, 30, 1,
+      "rotate", G_TYPE_INT, 0,
       NULL);
   if (!appsrc_caps) {
     LOG(ERROR) << __FUNCTION__ << " cannot create appsrc caps";
@@ -575,11 +583,11 @@ bool TizenVideoEncodeAccelerator::StartEncoder() {
 
   // appsink initialization
   if (!(gst_appsink = gst_element_factory_make("appsink", "sink"))) {
-    LOG(ERROR) << __FUNCTION__ << " cannot create appsink";
+    LOG(ERROR) << "cannot create appsink for encoder pipeline.";
     return false;
   }
   if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_appsink)) {
-    LOG(ERROR) << __FUNCTION__ << "cannot add gst appsink into encoder pipeline.";
+    LOG(ERROR) << "cannot add gst appsink into encoder pipeline.";
     gst_object_unref(gst_appsink);
     return false;
   }
@@ -604,23 +612,16 @@ bool TizenVideoEncodeAccelerator::StartEncoder() {
     return false;
   }
   g_object_set(impl_->encoder_,
-               "byte-stream", TRUE,
                "control-rate", 2, // 1:VBR_CFR  2:CBR_CFR  3:VBR_VFR  4:CBR_VFR
+#if GST_VERSION_MAJOR == 1
+               "target-bitrate", impl_->gst_bitrate_,
+#else
                "encoder-profile", 1, // BASELINE_PROFILE
+               "byte-stream", TRUE,
                "bitrate", impl_->gst_bitrate_,
+#endif
                NULL);
 
-  // converter initialization
-  if (!(gst_converter = gst_element_factory_make(kConvertorGstElement, kConvertorName))) {
-    LOG(ERROR) << __FUNCTION__ << " cannot create " << kConvertorGstElement << ".";
-    return false;
-  }
-  if(!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_converter)) {
-    LOG(ERROR) << __FUNCTION__ << " cannot add " << kConvertorGstElement << " into encoder pipeline.";
-    gst_object_unref(gst_converter);
-    return false;
-  }
-
   g_object_set(G_OBJECT(impl_->appsrc_),
                "is-live", TRUE,
                "block", FALSE,
@@ -634,31 +635,13 @@ bool TizenVideoEncodeAccelerator::StartEncoder() {
 
   g_object_set(gst_appsink, "sync", FALSE, NULL);
 
-  converter_caps = gst_caps_new_simple(
-      "video/x-raw-yuv",
-#if GST_VERSION_MAJOR == 1
-      "format", G_TYPE_STRING, gst_video_format_to_string(GST_VIDEO_FORMAT_I420),
-#else
-      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
-#endif
-      "width", G_TYPE_INT, impl_->view_size_.width(),
-      "height", G_TYPE_INT, impl_->view_size_.height(),
-      "framerate", GST_TYPE_FRACTION, 30, 1,
-      NULL);
-  if (!converter_caps) {
-    LOG(ERROR) << __FUNCTION__ << " cannot create converter_caps.";
-    return false;
-  }
-  retval = gst_element_link_filtered(impl_->appsrc_, gst_converter,
-                                     converter_caps);
-  if (retval == FALSE) {
-    LOG(ERROR) << __FUNCTION__ << " cannot link appsrc_ with converter_.";
+  if (!gst_element_link(impl_->appsrc_, impl_->encoder_)) {
+    LOG(ERROR) << " cannot link impl_->appsrc_ with encoder_.";
     return false;
   }
 
-  if (!gst_element_link_many(gst_converter, impl_->encoder_,
-                             gst_appsink, NULL)) {
-    LOG(ERROR) << __FUNCTION__ << " cannot link converter_ with encoder_.";
+  if (!gst_element_link(impl_->encoder_, gst_appsink)) {
+    LOG(ERROR) << " cannot link encoder_ to sink.";
     return false;
   }
 #else