From a8ed7baa34843a7390b1797a5d12497721910d6d Mon Sep 17 00:00:00 2001 From: "s.kamath" Date: Thu, 19 Feb 2015 18:35:04 +0530 Subject: [PATCH] [MM][WebRTC] OMX codec integration on m0 target. 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 --- .../tizen/tizen_video_decode_accelerator.cc | 26 +++++- .../tizen/tizen_video_encode_accelerator.cc | 89 ++++++++----------- 2 files changed, 58 insertions(+), 57 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 1cfce5ca9244..d83aa96b0acb 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 @@ -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 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(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; } diff --git a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_encode_accelerator.cc b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_encode_accelerator.cc index acec12e89301..2db7941b9fd6 100644 --- a/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_encode_accelerator.cc +++ b/tizen_src/impl/content/common/gpu/media/tizen/tizen_video_encode_accelerator.cc @@ -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(shm->memory()), map.data, gstBufferSize); + memcpy(static_cast(shm->memory()), map.data, gst_buffer_size); + gst_buffer_unmap(buffer, &map); #else - memcpy(static_cast(shm->memory()), buffer->data, gstBufferSize); + memcpy(static_cast(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(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( - bufref->frame_->data(VideoFrame::kYPlane)), + static_cast(bufref->frame_->data(VideoFrame::kYPlane)), bufref->size_, 0, bufref->size_, reinterpret_cast(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 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 -- 2.34.1