[ACR-1598] Add new APIs for set param maximum lateness and RTP latency 07/244007/7
authorHyunil <hyunil46.park@samsung.com>
Mon, 14 Sep 2020 03:09:25 +0000 (12:09 +0900)
committerHyunil <hyunil46.park@samsung.com>
Tue, 15 Sep 2020 05:17:14 +0000 (14:17 +0900)
- MEDIA_STREAMER_PARAM_SINK_MAX_LATENESS
- Video frame drop occurs when the PTS(presentation time stamp) of segment received as RTP streaming
  exceeds the boundary of the base clock.
- If the frame is later than max-lateness, the sink will drop the buffer without calling the render method.

- MEDIA_STREAMER_RARAM_RTP_LATENCY
- Default amount of ms to buffer in the jitterbuffer of RTPbin

- Minor change
  1) Add audio clock rate for OPUS
  2) Change Default Video RTP format from VP8 to H264

[Version] 0.1.119
[Issue Type] New features

Change-Id: Iddfd098a897d1ff5bd3db291b4046d558a0d159a
Signed-off-by: Hyunil <hyunil46.park@samsung.com>
include/media_streamer.h
include/media_streamer_priv.h
include/media_streamer_util.h
packaging/capi-media-streamer.spec
src/media_streamer_gst.c
src/media_streamer_gst_webrtc.c
src/media_streamer_node.c

index aeef5d4..de679b4 100644 (file)
@@ -249,6 +249,15 @@ typedef enum {
 #define MEDIA_STREAMER_PARAM_PORT "port"
 
 /**
+ * @brief Definition for RTP packet latency of jitterbuffers of rtpbin or WebRTC node.
+ * @details Default amount of ms to buffer in the jitterbuffers.\n
+ *          Data type is string and default value is "200".
+ * @since_tizen 6.0
+ * @see media_streamer_node_get_params()
+ */
+#define MEDIA_STREAMER_PARAM_RTP_LATENCY "rtp-latency"
+
+/**
  * @brief Definition for video port parameter of source node.
  * @details The port to receive the video packets from.\n
  *          Data type is integer.
@@ -480,6 +489,16 @@ typedef enum {
 #define MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION "playlist-location"
 
 /**
+ * @brief Definition for maximum lateness of sink node.
+ * @details The maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited).\n
+ *          The range is from "-1" to "9223372036854775807".\n
+ *          Data type is string and default value is "5000000".
+ * @since_tizen 6.0
+ * @see media_streamer_node_get_params()
+ */
+#define MEDIA_STREAMER_PARAM_SINK_MAX_LATENESS "max-lateness"
+
+/**
  * @brief Definition for the name of the sink pad that receives video data.
  * @since_tizen 6.0
  * @remarks A node of #MEDIA_STREAMER_NODE_TYPE_RTP or #MEDIA_STREAMER_NODE_TYPE_WEBRTC type has this pad.
index 8a1bcf7..96148b1 100644 (file)
@@ -66,6 +66,7 @@ typedef enum {
        PROP_NAME_USER_AGENT,
        PROP_NAME_STREAM_TYPE,
        PROP_NAME_PORT,
+       PROP_NAME_RTP_LATENCY,
        PROP_NAME_VIDEO_IN_PORT,
        PROP_NAME_AUDIO_IN_PORT,
        PROP_NAME_VIDEO_OUT_PORT,
@@ -88,6 +89,7 @@ typedef enum {
        PROP_NAME_HOST,
        PROP_NAME_SEGMENT_LOCATION,
        PROP_NAME_PLAYLIST_LOCATION,
+       PROP_NAME_MAX_LATENESS,
        PROP_NAME_MAX
 } prop_name_e;
 
index b7da60b..7e8f4c1 100644 (file)
@@ -167,6 +167,9 @@ typedef struct _media_streamer_wl_info_s {
 #define DEFAULT_AUDIO_RESAMPLE              "audioresample"
 #define DEFAULT_APP_SINK                    "appsink"
 
+/* RTP */
+#define DEFAULT_MEDIA_STREAMER_RTP_LATENCY 200
+
 /* udp streaming */
 #define DEFAULT_UDP_SOURCE                  "udpsrc"
 #define DEFAULT_FILE_SOURCE                 "filesrc"
@@ -204,8 +207,8 @@ typedef struct _media_streamer_wl_info_s {
 #define WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE    "inactive"
 #define WEBRTC_RTP_TRANSCEIVER_DIRECTION_UNKNOWN     "unknown"
 #define DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION     WEBRTC_RTP_TRANSCEIVER_DIRECTION_UNKNOWN
-#define WEBRTC_DEFAULT_VIDEO_RTP_FORMAT    "application/x-rtp,media=video,clock-rate=90000,encoding-name=VP8,payload=96"
-#define WEBRTC_DEFAULT_AUDIO_RTP_FORMAT    "application/x-rtp,media=audio,encoding-name=OPUS,payload=97"
+#define WEBRTC_DEFAULT_VIDEO_RTP_FORMAT    "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264,payload=96"
+#define WEBRTC_DEFAULT_AUDIO_RTP_FORMAT    "application/x-rtp,media=audio,clock-rate=48000,encoding-name=OPUS,payload=97"
 
 #define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=352,height=288"
 #define MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT "audio/x-raw,channels=1,rate=8000,format=S16LE"
index 1e8c910..006d47d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-streamer
 Summary:    A Media Streamer API
-Version:    0.1.118
+Version:    0.1.119
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index c663490..b706958 100644 (file)
@@ -1877,6 +1877,7 @@ GstElement *ms_rtp_element_create(void)
        MS_SET_INT_STATIC_STRING_PARAM(rtp_container, MEDIA_STREAMER_PARAM_HOST, "localhost");
        MS_SET_INT_CAPS_PARAM(rtp_container, MS_PARAM_VIDEO_IN_FORMAT, gst_caps_new_any());
        MS_SET_INT_CAPS_PARAM(rtp_container, MS_PARAM_AUDIO_IN_FORMAT, gst_caps_new_any());
+       MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_RTP_LATENCY, DEFAULT_MEDIA_STREAMER_RTP_LATENCY);
 
        ms_debug_fleave();
 
index bce1f6b..b8c3e57 100644 (file)
@@ -730,6 +730,7 @@ GstElement *ms_webrtc_element_create(void)
        MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, NULL);
        MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO, DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION);
        MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO, DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION);
+       MS_SET_INT_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_RTP_LATENCY, DEFAULT_MEDIA_STREAMER_RTP_LATENCY);
 
        if (!(webrtcbin = ms_element_create("webrtcbin", NULL))) {
                ms_error("Failed to create webrtcbin element");
index 8a7cd72..8d4b175 100644 (file)
@@ -99,6 +99,12 @@ static param_s param_table[] = {
                PARAM_DATA_TYPE_NUMBER
        },
        {
+               MEDIA_STREAMER_PARAM_RTP_LATENCY,
+               "rtp-latency",
+               PROP_NAME_RTP_LATENCY,
+               PARAM_DATA_TYPE_NUMBER
+       },
+       {
                MEDIA_STREAMER_PARAM_VIDEO_IN_PORT,
                "video_in_port",
                PROP_NAME_VIDEO_IN_PORT,
@@ -231,6 +237,12 @@ static param_s param_table[] = {
                PARAM_DATA_TYPE_STRING
        },
        {
+               MEDIA_STREAMER_PARAM_SINK_MAX_LATENESS,
+               "max-lateness",
+               PROP_NAME_MAX_LATENESS,
+               PARAM_DATA_TYPE_NUMBER
+       },
+       {
                NULL,
                NULL,
                PROP_NAME_MAX,
@@ -467,6 +479,31 @@ static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *para
 }
 
 //LCOV_EXCL_START
+static int __ms_node_get_rtp_latency(media_streamer_node_s *node, int *latency)
+{
+       GValue *val = NULL;
+
+       ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is null");
+       ms_retvm_if(!latency, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "latency is null");
+       ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC &&
+                               node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
+
+       val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_RTP_LATENCY);
+       if (!val) {
+               ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_RTP_LATENCY, GST_ELEMENT_NAME(node->gst_element));
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       if (!(*latency = g_value_get_int(val))) {
+               ms_error("Failed to g_value_get_int()");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       ms_info("RTP latency is [%d]", *latency);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
 static int __ms_webrtc_node_check_transceiver_direction_param_value(media_streamer_node_s *node, param_s *param, const gchar *param_value)
 {
        GstWebRTCRTPTransceiverDirection direction;
@@ -601,6 +638,10 @@ static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *p
                ret = __ms_param_value_set(val, param->data_type, param_value);
                break;
 
+       case PROP_NAME_RTP_LATENCY:
+               ret = __ms_param_value_set(val, param->data_type, param_value);
+               break;
+
        default:
                ms_error("failed to set property, undefined param name[%s]", param->param_name);
                return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
@@ -1680,6 +1721,7 @@ int ms_rtp_node_prepare(media_streamer_node_s *node)
        GstGhostPad *ghost_pad = NULL;
        GstElement *audio_filter = NULL;
        GstCaps *audio_caps = NULL;
+       gint latency = DEFAULT_MEDIA_STREAMER_RTP_LATENCY;
 
        ms_debug_fenter();
 
@@ -1695,6 +1737,12 @@ int ms_rtp_node_prepare(media_streamer_node_s *node)
 
        ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
 
+       if (__ms_node_get_rtp_latency(node, &latency) != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to get rtp latency");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+       g_object_set(G_OBJECT(rtpbin), "latency", latency, NULL);
+
        val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
        host = g_value_get_string(val);
 
@@ -2056,8 +2104,10 @@ int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
        GstElement *webrtcbin = NULL;
+       GstElement *rtpbin = NULL;
        GObject *send_channel = NULL;
        gboolean is_offerer = FALSE;
+       gint latency = DEFAULT_MEDIA_STREAMER_RTP_LATENCY;
        media_streamer_webrtc_callbacks_s *_callbacks = NULL;
 
        ms_debug_fenter();
@@ -2114,6 +2164,15 @@ int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s
        ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
        ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
 
+       if (__ms_node_get_rtp_latency(node, &latency) != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to get rtp latency");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       rtpbin = gst_bin_get_by_name(GST_BIN(webrtcbin), "rtpbin");
+       g_object_set(G_OBJECT(rtpbin), "latency", latency, NULL);
+       gst_object_unref(rtpbin);
+
        ms_generate_dots(node->gst_element, "webrtc_prepared");
 
        ms_debug_fleave();
@@ -2227,6 +2286,7 @@ int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const c
        case PROP_NAME_ROTATE:
        case PROP_NAME_FLIP:
        case PROP_NAME_DISPLAY_GEOMETRY_METHOD:
+       case PROP_NAME_MAX_LATENESS:
                g_object_set(node->gst_element, param->prop_name, ms_get_number_from_string(param_value), NULL);
                break;
 
@@ -2789,4 +2849,4 @@ int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
 
        return MEDIA_STREAMER_ERROR_NONE;
 }
-//LCOV_EXCL_STOP
\ No newline at end of file
+//LCOV_EXCL_STOP