From 3247ccd59a6ba89329d22d6965d0be50ef736958 Mon Sep 17 00:00:00 2001 From: "sonal.g1@samsung.com" Date: Mon, 19 Jan 2015 20:26:14 +0530 Subject: [PATCH] [Tizen][WebRTC] Pixmap implementation for video decode accelerator Implementation of Rendering through pixmap surface. Together with: I325093df8aac31fc0eab155da08cd87de2ab58f7 Reviewed by: Min-Soo Koo, SeungSeop Park, Venugopal S M Change-Id: I80a06a4fa0fa65106061a32f0a57b4e2b8a3635b Signed-off-by: sonal.g1@samsung.com --- .../tizen/tizen_video_decode_accelerator.cc | 214 +++++++++++++++++- .../tizen/tizen_video_decode_accelerator.h | 7 + 2 files changed, 219 insertions(+), 2 deletions(-) diff --git a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.cc b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.cc index 26a5ad5d1398..1cfce5ca9244 100644 --- a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.cc +++ b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.cc @@ -15,6 +15,9 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) +#include "ui/gl/efl_pixmap.h" +#endif #if GST_VERSION_MAJOR == 1 #include @@ -41,6 +44,10 @@ const char* kDecoderGstElement = "omxh264dec"; const char* kDecoderGstElement = "omx_h264dec"; #endif +// Generating Unique Key from given width and height. +int32 ConvertWidthAndHeightToKey(int width, int height) { + return ((width << 16) | height); +} } // namespace namespace content { @@ -48,6 +55,9 @@ namespace content { enum { MAX_BITRATE = 2000000, // bps. INPUT_BUFFER_SIZE = MAX_BITRATE / 8, // bytes. 1 sec for H.264 HD video. +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + ID_LAST = 0x3FFFFFFF, // wrap round ID after this +#endif }; media::VideoDecodeAccelerator* CreateTizenVideoDecodeAccelerator() { @@ -103,7 +113,21 @@ struct TizenVideoDecodeAccelerator::Impl { sink_(NULL), appsrc_(NULL), io_message_loop_proxy_(base::MessageLoopProxy::current()), - gst_thread_("TizenDecoderThreadGst") {} + gst_thread_("TizenDecoderThreadGst") +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + ,bitstream_buffer_id_(0), + pixmap_id_(0), + gst_width_(0), + gst_height_(0), + damage_(0), + damage_handler_(NULL), + is_x_window_handle_set_(false) +#endif +{ +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + xpixmap_buffer_map_.clear(); +#endif +} static GstBusSyncReply OnBusMessage( GstBus* bus, GstMessage* msg, gpointer data) { @@ -123,7 +147,30 @@ struct TizenVideoDecodeAccelerator::Impl { g_free(debug); break; } - default: NOTREACHED(); +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + case GST_MESSAGE_ELEMENT: { + TizenVideoDecodeAccelerator::Impl* obj_impl = + static_cast(data); + if (obj_impl) { + if (obj_impl->IsXWindowHandleSet()) { +#if GST_VERSION_MAJOR == 1 + if (gst_is_video_overlay_prepare_window_handle_message(msg)) { +#else + if (gst_structure_has_name(msg->structure, "prepare-xid")) { +#endif + obj_impl->OnXWindowIdPrepared(msg); + gst_message_unref(msg); + return GST_BUS_PASS; + } + } + } else { + LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; + } + break; + } +#endif + default: + break; } return GST_BUS_PASS; } @@ -142,6 +189,17 @@ struct TizenVideoDecodeAccelerator::Impl { impl->can_feed_ = false; } +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + bool IsXWindowHandleSet() const {return is_x_window_handle_set_;} + void OnXWindowIdPrepared(GstMessage* message); + void SetXWindowHandle(bool handle_set); + void SetPixmap(const int32& gst_width, const int32& gst_height); + void DeregisterDamageHandler(); + static Eina_Bool OnSurfaceChanged(void* ptr_acc, int type, void* event); + static void OnSinkCapChanged( + GstPad* sink_pad, GParamSpec* gparamspec, void* user_data); +#endif + volatile bool can_feed_; volatile bool is_destroying_; GstElement* pipeline_; @@ -150,6 +208,18 @@ struct TizenVideoDecodeAccelerator::Impl { scoped_refptr io_message_loop_proxy_; scoped_ptr > io_client_weak_factory_; base::Thread gst_thread_; +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + int bitstream_buffer_id_; + scoped_refptr pixmap_surface_; + int pixmap_id_; + gint gst_width_; + gint gst_height_; + Ecore_X_Damage damage_; + Ecore_Event_Handler* damage_handler_; + bool is_x_window_handle_set_; + typedef std::map > PixmapSurfaceTizenMap; + PixmapSurfaceTizenMap xpixmap_buffer_map_; +#endif }; TizenVideoDecodeAccelerator::TizenVideoDecodeAccelerator() @@ -166,6 +236,7 @@ bool TizenVideoDecodeAccelerator::Initialize( GstCaps* video_caps = NULL; GstElement* gst_decoder = NULL; GstBus* gst_bus = NULL; + GstPad* video_sink_pad = NULL; scoped_ptr gst_pipeline; static GstAppSrcCallbacks appsrc_callbacks = {&Impl::StartFeed, &Impl::StopFeed, NULL}; @@ -259,6 +330,15 @@ bool TizenVideoDecodeAccelerator::Initialize( return false; } g_object_set(impl_->sink_, "rotate", 0, NULL); +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + if (!(video_sink_pad = gst_element_get_static_pad(impl_->sink_, "sink"))) { + return false; + } + g_signal_connect( + video_sink_pad, "notify::caps", G_CALLBACK(impl_->OnSinkCapChanged), impl_); + impl_->SetXWindowHandle(false); + gst_object_unref(video_sink_pad); +#endif // linking the elements. if (!gst_element_link(impl_->appsrc_, gst_decoder)) { @@ -385,6 +465,11 @@ void TizenVideoDecodeAccelerator::Reset() { void TizenVideoDecodeAccelerator::Destroy() { if (impl_ != NULL) { +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + impl_->SetXWindowHandle(false); + impl_->DeregisterDamageHandler(); + impl_->xpixmap_buffer_map_.clear(); +#endif if (impl_->gst_thread_.IsRunning()) { impl_->gst_thread_.Stop(); } @@ -408,6 +493,131 @@ void TizenVideoDecodeAccelerator::StartDecoder() { gst_element_set_state(impl_->pipeline_, GST_STATE_PLAYING); }; +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) +void TizenVideoDecodeAccelerator::Impl::OnXWindowIdPrepared( + GstMessage* message) { +#if GST_VERSION_MAJOR == 1 + const GstStructure* structure = gst_message_get_structure(message); + gst_structure_get_int(structure, "video-width", &gst_width_); + gst_structure_get_int(structure, "video-height", &gst_height_); +#else + gst_structure_get_int(message->structure, "video-width", &gst_width_); + gst_structure_get_int(message->structure, "video-height", &gst_height_); +#endif + SetPixmap(gst_width_, gst_height_); + SetXWindowHandle(true); +} + +void TizenVideoDecodeAccelerator::Impl::SetXWindowHandle( + bool handle_set) { + is_x_window_handle_set_ = handle_set; +} + +void TizenVideoDecodeAccelerator::Impl::SetPixmap( + const int32& gst_width, const int32& gst_height) { + int32 key_wh = ConvertWidthAndHeightToKey(gst_width, gst_height); + PixmapSurfaceTizenMap::iterator it = xpixmap_buffer_map_.find(key_wh); + if (it != xpixmap_buffer_map_.end()) { + pixmap_surface_ = it->second; + pixmap_id_ = pixmap_surface_->GetId(); + } else { + pixmap_surface_ = + gfx::EflPixmap::Create(gfx::EflPixmapBase::UsageType::SURFACE, + gfx::Size(gst_width, gst_height)); + if (pixmap_surface_.get() == NULL) { + LOG(ERROR) << __FUNCTION__ << "Failed to create pixmap Surface"; + return; + } + pixmap_id_ = pixmap_surface_->GetId(); + xpixmap_buffer_map_[key_wh] = pixmap_surface_; + } + gst_width_ = gst_width; + gst_height_ = gst_height; + DeregisterDamageHandler(); + + // Register to get notification from ecore for damage updates. + damage_ = ecore_x_damage_new(pixmap_id_, + ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); + damage_handler_ = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, + OnSurfaceChanged, + this); +#if GST_VERSION_MAJOR == 1 + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink_), pixmap_id_); +#else + gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink_), pixmap_id_); +#endif +} + +void TizenVideoDecodeAccelerator::Impl::DeregisterDamageHandler() { + if (damage_) { + ecore_x_damage_free(damage_); + damage_ = 0; + } + if (damage_handler_) { + ecore_event_handler_del(damage_handler_); + damage_handler_ = NULL; + } +} + +// Callback received when pixmap surface is changed/damaged +Eina_Bool TizenVideoDecodeAccelerator::Impl::OnSurfaceChanged(void* ptr_acc, + int type, + void* event) { + TizenVideoDecodeAccelerator::Impl* self = + static_cast(ptr_acc); + + if (self) { + media::Picture picture(self->pixmap_id_, + self->bitstream_buffer_id_, + gfx::Rect(self->gst_width_, self->gst_height_)); + + self->io_message_loop_proxy_->PostTask( + FROM_HERE, + base::Bind(&media::VideoDecodeAccelerator::Client::PictureReady, + self->io_client_weak_factory_->GetWeakPtr(), + picture) ); + self->bitstream_buffer_id_ = (self->bitstream_buffer_id_ + 1) & ID_LAST; + } else { + LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; + return ECORE_CALLBACK_CANCEL; + } + return ECORE_CALLBACK_PASS_ON; +} + +void TizenVideoDecodeAccelerator::Impl::OnSinkCapChanged( + GstPad* sink_pad, GParamSpec* gparamspec,void* user_data) { + TizenVideoDecodeAccelerator::Impl* self = + static_cast(user_data); + if (!self) { + LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; + return; + } + + int width = 0, height = 0; +#if GST_VERSION_MAJOR == 1 + GstCaps* caps = gst_pad_get_current_caps(GST_PAD(sink_pad)); + if (caps) { + GstVideoInfo info; + gst_video_info_init(&info); + + if (gst_video_info_from_caps(&info, caps)) { + width = info.width; + height = info.height; + if ((self->gst_width_ != width) || (self->gst_height_ != height)) { + self->SetPixmap(width, height); + } + } + } +#else + if (gst_video_get_size(sink_pad, &width, &height)) { + if ((self->gst_width_ != width) || (self->gst_height_ != height)) { + self->SetPixmap(width, height); + } + } +#endif +} +#endif + void TizenVideoDecodeAccelerator::OnDecode( scoped_ptr buffer_ref) { if (!buffer_ref) { diff --git a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.h b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.h index 10a42f5e8528..c312e5e589b4 100644 --- a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.h +++ b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_decode_accelerator.h @@ -5,6 +5,13 @@ #ifndef CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ #define CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ +#include +#include +#include +#include +#include +#include + #include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "content/common/content_export.h" -- 2.34.1