Skip to content

Commit

Permalink
Feature/h265 (#90)
Browse files Browse the repository at this point in the history
<!--
Thank you for your contribution to the Kurento project.
Please provide enough information so that others can review your Pull
Request.

For more information, see the Contribution Guidelines:
https://github.com/Kurento/kurento/blob/main/.github/CONTRIBUTING.md
-->


## What is the current behavior you want to change?
This change provide H.265 video codec support to Kurento including
WebRTC and RTP services


## What is the new behavior provided by this change?
It adds H,.265 support using x265 gstreamer codecs

## How has this been tested?
Using standard Kurento tutorials


## Types of changes
<!--
What types of changes does your code introduce?
Put an 'x' in all the boxes that apply:
-->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature / enhancement (non-breaking change which improves the
project)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] My change requires a change to the documentation
- [ ] My change requires a change in other repository <!-- Explain which
one -->


## Checklist
<!--
Go over all the following points, and put an 'x' in all the boxes that
apply.
If you're unsure about any of these, don't hesitate to ask. We're here
to help!
-->
- [X] I have read the [Contribution
Guidelines](https://github.com/Kurento/kurento/blob/main/.github/CONTRIBUTING.md)
- [X] I have added an explanation of what the changes do and why they
should be included
- [X] I have written new tests for the changes, as applicable, and have
successfully run them locally
  • Loading branch information
slabajo authored Nov 12, 2024
2 parents 63d3515 + 7c4921e commit 3dcbcd4
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 9 deletions.
3 changes: 2 additions & 1 deletion server/media-server/sdp_pattern.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ m=audio 0 RTP/AVP 98 99 0
a=rtpmap:98 OPUS/48000/2
a=rtpmap:99 AMR/8000/1
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 96 97 101 98 100 102
m=video 0 RTP/AVP 96 97 101 98 100 102 103
a=rtpmap:96 H263-1998/90000
a=rtpmap:97 VP8/90000
a=rtpmap:101 H264/90000
a=rtpmap:98 VP9/90000
a=rtpmap:100 MP4V-ES/90000
a=rtpmap:102 AV1/90000
a=rtpmap:103 H265/90000


Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
"video/x-theora;" \
"video/x-h264;" \
"video/x-gst_ff-libxvid;" \
"video/x-h264;" \
"video/x-h265;" \
"video/x-xvid;" \
"video/mpeg,mpegversion=[1, 2];" \
"video/x-theora;" \
Expand Down
33 changes: 31 additions & 2 deletions server/module-core/src/gst-plugins/commons/kmsenctreebin.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ G_DEFINE_TYPE (KmsEncTreeBin, kms_enc_tree_bin, KMS_TYPE_TREE_BIN);

typedef enum
{
X265,
AV1,
VP9,
VP8,
Expand Down Expand Up @@ -70,6 +71,8 @@ static const gchar *
kms_enc_tree_bin_get_name_from_type (EncoderType enc_type)
{
switch (enc_type) {
case X265:
return "x265";
case AV1:
return "av1";
case VP9:
Expand Down Expand Up @@ -145,6 +148,17 @@ configure_encoder (GstElement * encoder, EncoderType type,
{
GST_DEBUG ("Configure encoder: %" GST_PTR_FORMAT, encoder);
switch (type) {
case X265:
{
/* *INDENT-OFF* */
g_object_set (G_OBJECT (encoder),
"speed-preset", /* veryfast */ 3,
"key-int-max", 60,
"tune", /* zero-latency */ 4,
NULL);
/* *INDENT-ON* */
break;
}
case AV1:
{
/* *INDENT-OFF* */
Expand Down Expand Up @@ -229,7 +243,9 @@ kms_enc_tree_bin_set_encoder_type (KmsEncTreeBin * self)

g_object_get (self->priv->enc, "name", &name, NULL);

if (g_str_has_prefix (name, "vp8enc")) {
if (g_str_has_prefix (name, "x265enc")) {
self->priv->enc_type = X265;
} else if (g_str_has_prefix (name, "vp8enc")) {
self->priv->enc_type = VP8;
} else if (g_str_has_prefix (name, "vp9enc")) {
self->priv->enc_type = VP9;
Expand Down Expand Up @@ -321,16 +337,25 @@ kms_enc_tree_bin_set_target_bitrate (KmsEncTreeBin *self)
{
const gchar *vpx_property_name = "target-bitrate";
const gchar *h264_property_name = "bitrate";
const gchar *h265_property_name = "bitrate";
const gchar *property_name;

gint new_bitrate = kms_enc_tree_bin_get_bitrate (self);
gint kbps_div;
guint min_bitrate = 0;
guint br;

if (new_bitrate <= 0) {
return;
}

switch (self->priv->enc_type) {
case X265:
property_name = h265_property_name;
kbps_div = 1;
new_bitrate /= 1000;
min_bitrate = 1;
break;
case VP9:
property_name = vpx_property_name;
kbps_div = 1000;
Expand Down Expand Up @@ -365,7 +390,11 @@ kms_enc_tree_bin_set_target_bitrate (KmsEncTreeBin *self)
return;
}

g_object_set (self->priv->enc, property_name, new_bitrate * kbps_div / 1000, NULL);
br = new_bitrate * kbps_div / 1000;
if (br < min_bitrate) {
br = min_bitrate;
}
g_object_set (self->priv->enc, property_name, br, NULL);

GST_DEBUG_OBJECT (self->priv->enc, "\"%s\" set: %d", property_name,
new_bitrate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ static gchar *video_rtcp_fb_enc[] = {
"AV1",
"VP9",
"VP8",
"H264"
"H264",
"H265"
};

#define KMS_SDP_RTP_AVPF_MEDIA_HANDLER_GET_PRIVATE(obj) ( \
Expand Down
1 change: 1 addition & 0 deletions server/module-core/src/server/config/SdpEndpoint.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
{ "name": "AMR/8000" }
],
"videoCodecs": [
{ "name": "H265/90000" },
{ "name": "AV1/90000" },
{ "name": "VP9/90000" },
{ "name": "VP8/90000" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,10 @@ void MediaElementImpl::setVideoFormat (std::shared_ptr<VideoCaps> caps)
fraction = caps->getFramerate();

switch (codec->getValue() ) {
case VideoCodec::H265:
str_caps = "video/x-h265";
break;

case VideoCodec::AV1:
str_caps = "video/x-av1";
break;
Expand Down
1 change: 1 addition & 0 deletions server/module-core/src/server/interface/core.kmd.json
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,7 @@ Pipeline, towards the associated producer. Only valid for video consumers.
{
"typeFormat": "ENUM",
"values": [
"H265",
"AV1",
"VP9",
"VP8",
Expand Down
59 changes: 58 additions & 1 deletion server/module-core/tests/check/element/agnosticbin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,45 @@ GST_START_TEST (test_raw_to_rtp_h264)

GST_END_TEST;

GST_START_TEST (test_raw_to_rtp_h265)
{
GstElement *fakesink;
GstElement *pipeline =
gst_parse_launch
("videotestsrc is-live=true"
" ! agnosticbin ! application/x-rtp,media=(string)video,"
" encoding-name=(string)H265,clock-rate=(int)90000"
" ! fakesink async=true sync=true name=sink signal-handoffs=true",
NULL);
GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));

loop = g_main_loop_new (NULL, TRUE);

gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message", G_CALLBACK (bus_msg), pipeline);

fakesink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");

g_signal_connect (G_OBJECT (fakesink), "handoff",
G_CALLBACK (fakesink_hand_off), loop);

g_object_unref (fakesink);

gst_element_set_state (pipeline, GST_STATE_PLAYING);

mark_point ();
g_main_loop_run (loop);
mark_point ();

gst_element_set_state (pipeline, GST_STATE_NULL);
gst_bus_remove_signal_watch (bus);
g_object_unref (bus);
g_object_unref (pipeline);
g_main_loop_unref (loop);
}

GST_END_TEST;

GST_START_TEST (test_raw_to_rtp_av1)
{
GstElement *fakesink;
Expand Down Expand Up @@ -1707,6 +1746,22 @@ GST_START_TEST (test_codec_config_av1)

GST_END_TEST;

GST_START_TEST (test_codec_config_x265)
{
const gchar *pipeline_str =
"videotestsrc is-live=true"
" ! agnosticbin name=ag ! capsfilter caps=video/x-h265"
" ! fakesink async=true sync=true name=sink signal-handoffs=true";
const gchar *config_str =
"x265,speed-preset=faster,tune=zerolatency";
const gchar *codec_name = "x264";
const gchar *agnostic_name = "ag";

test_codec_config (pipeline_str, config_str, codec_name, agnostic_name);
}

GST_END_TEST;

GST_START_TEST (test_codec_config_vp8)
{
const gchar *pipeline_str =
Expand Down Expand Up @@ -1788,10 +1843,12 @@ agnostic2_suite (void)
tcase_add_test (tc_chain, test_codec_config_openh264);
tcase_add_test (tc_chain, test_codec_config_vp9);
tcase_add_test (tc_chain, test_codec_config_av1);

tcase_add_test (tc_chain, test_codec_config_x265);

tcase_add_test (tc_chain, test_raw_to_rtp);
tcase_add_test (tc_chain, test_raw_to_rtp_vp9);
tcase_add_test (tc_chain, test_raw_to_rtp_h264);
tcase_add_test (tc_chain, test_raw_to_rtp_h265);
tcase_add_test (tc_chain, test_raw_to_rtp_av1);
tcase_add_test (tc_chain, test_raw_to_rtp_opus);
tcase_add_test (tc_chain, test_raw_to_rtp_pcmu);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,9 @@
;; requested on client, unfortunately for traffic on the other direction, this must be requested to the
;; browser or client. On browser, the client application needs to use the following API
;; https://www.w3.org/TR/webrtc-priority/
;qos-dscp=AUDIO_HIGH
;qos-dscp=AUDIO_HIGH

; Enable/Diable H265 support. It is disabled by default, enabling it implies that the user or administrator is responsible
; for H265 royalties that may be needed to use this codec. Kurento team will never be responsible for any unatuorhized use of
; patent protected codecs
;enable-h265=false
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

#define PARAM_QOS_DSCP "qos-dscp"

#define PARAM_ENABLE_H265 "enable-h265"

namespace kurento
{

Expand Down Expand Up @@ -133,6 +135,12 @@ remove_not_supported_codecs (GstElement *element)
g_array_unref (codecs);
}

static void
add_support_for_h265 ()
{
supported_codecs.emplace_back("H265");
}

static void
check_support_for_h264 ()
{
Expand Down Expand Up @@ -631,6 +639,15 @@ WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
std::call_once (certificates_flag,
std::bind (&WebRtcEndpointImpl::generateDefaultCertificates, this) );

std::string enableH265;

if (getConfigValue<std::string,WebRtcEndpoint>(&enableH265, PARAM_ENABLE_H265)) {
GST_INFO ("ENABLE-H265 configured value is %s", enableH265.c_str());
if (enableH265 == "true") {
add_support_for_h265 ();
}
}

this->qosDscp = qosDscp;
if (qosDscp->getValue () == DSCPValue::NO_VALUE) {
std::string cfg_dscp_value;
Expand Down
Loading

0 comments on commit 3dcbcd4

Please sign in to comment.