Add API to set/get encoder bitrate 52/278852/8
authorSangchul Lee <sc11.lee@samsung.com>
Wed, 27 Jul 2022 03:06:46 +0000 (12:06 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 3 Aug 2022 06:17:33 +0000 (15:17 +0900)
Functions are added as below.
 - webrtc_media_source_set_encoder_bitrate()
 - webrtc_media_source_get_encoder_bitrate()

[Version] 0.3.191
[Issue Type] API

Change-Id: I038da91a4ea00e4acac3f92d52a33b8c81ad6e29
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/webrtc.h
include/webrtc_private.h
include/webrtc_source_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_source.c
src/webrtc_source_private.c

index 18b4cb851751b0252fe32cd1ac45cfff0d34d014..0cb403a3d43d159c16f6e44208bde46a2384bdda 100644 (file)
@@ -1247,6 +1247,46 @@ int webrtc_media_source_set_mute(webrtc_h webrtc, unsigned int source_id, webrtc
  */
 int webrtc_media_source_get_mute(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *muted);
 
+/**
+ * @brief Sets an encoder target bitrate(in bits/sec) to the media source.
+ * @details If @a source_id is a media source of #WEBRTC_MEDIA_SOURCE_TYPE_FILE or #WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET or #WEBRTC_MEDIA_SOURCE_TYPE_NULL,
+ *          this function will return #WEBRTC_ERROR_INVALID_PARAMETER.
+ * @since_tizen 7.0
+ * @param[in] webrtc         WebRTC handle
+ * @param[in] source_id      The media source id
+ * @param[in] media_type     The media type
+ * @param[in] target_bitrate The target bitrate of the encoder
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE    Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Add media source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @see webrtc_add_media_source()
+ * @see webrtc_media_source_get_encoder_bitrate()
+ */
+int webrtc_media_source_set_encoder_bitrate(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, int target_bitrate);
+
+/**
+ * @brief Gets the encoder target bitrate(in bits/sec) of the media source.
+ * @details If @a source_id is a media source of #WEBRTC_MEDIA_SOURCE_TYPE_FILE or #WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET or #WEBRTC_MEDIA_SOURCE_TYPE_NULL,
+ *          this function will return #WEBRTC_ERROR_INVALID_PARAMETER.
+ * @since_tizen 7.0
+ * @param[in] webrtc          WebRTC handle
+ * @param[in] source_id       The media source id
+ * @param[in] media_type      The media type
+ * @param[out] target_bitrate The target bitrate of the encoder
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE    Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Add media source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @see webrtc_add_media_source()
+ * @see webrtc_media_source_set_encoder_bitrate()
+ */
+int webrtc_media_source_get_encoder_bitrate(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, int *target_bitrate);
+
 /**
  * @brief Sets a video resolution to the media source.
  * @details The following media source types contain video:\n
index ccba09ffacd9a0f35b0f82ef2408d63f1c0b6727..f0fdbb221dd5794779fbdf789666f9c15ead4955 100644 (file)
@@ -528,6 +528,7 @@ typedef struct _webrtc_gst_slot_s {
                GstPad *src_pad;
                gulong src_pad_probe_id;
                gchar *raw_format;
+               int target_bitrate;
                bool pause;
                bool mute;
                bool inbandfec;
@@ -687,6 +688,8 @@ int _set_audio_mute(webrtc_s *webrtc, unsigned int source_id, bool mute);
 int _get_audio_mute(webrtc_s *webrtc, unsigned int source_id, bool *muted);
 int _set_video_mute(webrtc_s *webrtc, unsigned int source_id, bool mute);
 int _get_video_mute(webrtc_s *webrtc, unsigned int source_id, bool *muted);
+int _set_encoder_bitrate(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, int target_bitrate);
+int _get_encoder_bitrate(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, int *target_bitrate);
 int _set_video_resolution(webrtc_s *webrtc, unsigned int source_id, int width, int height);
 int _get_video_resolution(webrtc_s *webrtc, unsigned int source_id, int *width, int *height);
 int _set_video_framerate(webrtc_s *webrtc, unsigned int source_id, int framerate);
index f6031747addaf6a05894d836ad55bdf983a819ea..c06e0e0f8e7ce846745afa100d2a64dff34b92e6 100644 (file)
@@ -106,5 +106,7 @@ rtp_payload_info_s * _get_payload_info_by_encoding_name(const char *encoding_nam
 int _add_transceiver(webrtc_gst_slot_s *source, webrtc_media_type_e media_type, rtp_payload_info_s *payload_info);
 int _link_source_with_webrtcbin(webrtc_gst_slot_s *source, GstElement *webrtcbin);
 int _create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool need_capsfilter, GList **element_list, bool is_audio);
+int _set_encoder_element_bitrate(GstElement *encoder, int target_bitrate);
+int _get_encoder_element_bitrate(GstElement *encoder, int *target_bitrate);
 
 #endif /* __TIZEN_MEDIA_WEBRTC_SOURCE_COMMON_H__ */
index feda5900258cf4241368e1fe5625d5e28b4146b3..7f2038eb8ca3e46040f86f36738d911d61c2041b 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.3.190
+Version:    0.3.191
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 828969090f7dc90cf2b3e1254f36264bf9d176a0..04bfd9daae3161f4109c3d9d389f33d774e39d1c 100644 (file)
@@ -441,6 +441,30 @@ int webrtc_media_source_get_mute(webrtc_h webrtc, unsigned int source_id, webrtc
                _get_video_mute(_webrtc, source_id, muted);
 }
 
+int webrtc_media_source_set_encoder_bitrate(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, int target_bitrate)
+{
+       g_autoptr(GMutexLocker) locker = NULL;
+       webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+
+       locker = g_mutex_locker_new(&_webrtc->mutex);
+
+       return _set_encoder_bitrate(webrtc, source_id, media_type, target_bitrate);
+}
+
+int webrtc_media_source_get_encoder_bitrate(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, int *target_bitrate)
+{
+       g_autoptr(GMutexLocker) locker = NULL;
+       webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+
+       locker = g_mutex_locker_new(&_webrtc->mutex);
+
+       return _get_encoder_bitrate(webrtc, source_id, media_type, target_bitrate);
+}
+
 int webrtc_media_source_set_video_resolution(webrtc_h webrtc, unsigned int source_id, int width, int height)
 {
        g_autoptr(GMutexLocker) locker = NULL;
index ac82a0209021c9a3c1cea8e202e0ae83d7f23d0c..7dc34a1909112c097ce9b3526b491b89f7d94934 100644 (file)
@@ -1956,6 +1956,108 @@ int _get_audio_mute(webrtc_s *webrtc, unsigned int source_id, bool *muted)
        return WEBRTC_ERROR_NONE;
 }
 
+static int __validate_source_for_encoder_bitrate(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_gst_slot_s **source)
+{
+       webrtc_gst_slot_s *_source;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       RET_VAL_IF((_source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "could not find source");
+       RET_VAL_IF(_source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE || _source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
+               _source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type");
+
+       if (_source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE ||
+               _source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
+               _source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL) {
+               LOG_ERROR("invalid type(%d)", _source->type);
+               return WEBRTC_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!(_source->media_types &
+               (media_type == WEBRTC_MEDIA_TYPE_AUDIO ? MEDIA_TYPE_AUDIO : MEDIA_TYPE_VIDEO))) {
+               LOG_ERROR("invalid media_type for source[media_types:0x%x, id:%u]", _source->media_types, source_id);
+               return WEBRTC_ERROR_INVALID_PARAMETER;
+       }
+
+       if (source)
+               *source = _source;
+
+       return WEBRTC_ERROR_NONE;
+}
+
+int _set_encoder_bitrate(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, int target_bitrate)
+{
+       int ret;
+       int av_idx;
+       webrtc_gst_slot_s *source;
+       GstElement *encoder;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       RET_VAL_IF(target_bitrate <= 0, WEBRTC_ERROR_INVALID_PARAMETER, "target_bitrate <= 0");
+       if ((ret = __validate_source_for_encoder_bitrate(webrtc, source_id, media_type, &source)) != WEBRTC_ERROR_NONE)
+               return ret;
+
+       if (media_type == WEBRTC_MEDIA_TYPE_AUDIO && source->media_types & MEDIA_TYPE_AUDIO) {
+               av_idx = AV_IDX_AUDIO;
+
+       } else if (media_type == WEBRTC_MEDIA_TYPE_VIDEO && source->media_types & MEDIA_TYPE_VIDEO) {
+               av_idx = AV_IDX_VIDEO;
+
+       } else {
+               LOG_ERROR_IF_REACHED("invalid media_type[%d] for source[media_types:0x%x, id:%u]", media_type, source->media_types, source_id);
+               return WEBRTC_ERROR_INVALID_PARAMETER;
+       }
+
+       if ((encoder = gst_bin_get_by_name(source->bin, (av_idx == AV_IDX_AUDIO) ? ELEMENT_NAME_AUDIO_ENCODER : ELEMENT_NAME_VIDEO_ENCODER)))
+               if ((ret = _set_encoder_element_bitrate(encoder, target_bitrate)) != WEBRTC_ERROR_NONE)
+                       return ret;
+
+       source->av[av_idx].target_bitrate = target_bitrate;
+
+       LOG_INFO("webrtc[%p] source_id[%u] media_type[%u] target_bitrate[%d]", webrtc, source_id, media_type, target_bitrate);
+
+       return WEBRTC_ERROR_NONE;
+}
+
+int _get_encoder_bitrate(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, int *target_bitrate)
+{
+       int ret;
+       int av_idx;
+       webrtc_gst_slot_s *source;
+       GstElement *encoder;
+       int bitrate;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       RET_VAL_IF(target_bitrate == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "target_bitrate is NULL");
+       if ((ret = __validate_source_for_encoder_bitrate(webrtc, source_id, media_type, &source)) != WEBRTC_ERROR_NONE)
+               return ret;
+
+       if (media_type == WEBRTC_MEDIA_TYPE_AUDIO && source->media_types & MEDIA_TYPE_AUDIO) {
+               av_idx = AV_IDX_AUDIO;
+
+       } else if (media_type == WEBRTC_MEDIA_TYPE_VIDEO && source->media_types & MEDIA_TYPE_VIDEO) {
+               av_idx = AV_IDX_VIDEO;
+
+       } else {
+               LOG_ERROR_IF_REACHED("invalid media_type[%d] for source[media_types:0x%x, id:%u]", media_type, source->media_types, source_id);
+               return WEBRTC_ERROR_INVALID_PARAMETER;
+       }
+
+       if ((encoder = gst_bin_get_by_name(source->bin, (av_idx == AV_IDX_AUDIO) ? ELEMENT_NAME_AUDIO_ENCODER : ELEMENT_NAME_VIDEO_ENCODER))) {
+               if ((ret = _get_encoder_element_bitrate(encoder, &bitrate)) != WEBRTC_ERROR_NONE)
+                       return ret;
+               *target_bitrate = source->av[av_idx].target_bitrate = bitrate;
+       } else {
+               *target_bitrate = source->av[av_idx].target_bitrate;
+       }
+
+       LOG_INFO("webrtc[%p] source_id[%u] media_type[%u] target_bitrate[%d]", webrtc, source_id, media_type, *target_bitrate);
+
+       return WEBRTC_ERROR_NONE;
+}
+
 static int __build_loopback_audiosink(webrtc_gst_slot_s *source, GstElement *link_with)
 {
        webrtc_s *webrtc;
index cb576d8e981333fb89849af34c11e8c64e4f3fdb..6b50d3d72d64b56da005ee27414370e91e055a73 100644 (file)
@@ -899,6 +899,53 @@ static GstElement *__get_hw_encoder_element(webrtc_s *webrtc, webrtc_gst_slot_s
 }
 //LCOV_EXCL_STOP
 
+static const char *__bitrate_properties[] = {
+       "bitrate",
+       "target-bitrate",
+       NULL,
+};
+
+int _set_encoder_element_bitrate(GstElement *encoder, int target_bitrate)
+{
+       int i;
+
+       RET_VAL_IF(encoder == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "encoder is NULL");
+
+       for (i = 0; __bitrate_properties[i] != NULL; i++) {
+               if (!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(encoder)), __bitrate_properties[i]))
+                       continue;
+
+               g_object_set(G_OBJECT(encoder),  __bitrate_properties[i], target_bitrate, NULL);
+               LOG_INFO("[%s] %s:%d", GST_OBJECT_NAME(gst_element_get_factory(encoder)), __bitrate_properties[i], target_bitrate);
+               return WEBRTC_ERROR_NONE;
+       }
+
+       LOG_ERROR("unknown bitrate property name");
+       return WEBRTC_ERROR_INVALID_OPERATION;
+}
+
+int _get_encoder_element_bitrate(GstElement *encoder, int *target_bitrate)
+{
+       int i;
+       int bitrate;
+
+       RET_VAL_IF(encoder == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "encoder is NULL");
+       RET_VAL_IF(target_bitrate == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "target_bitrate is NULL");
+
+       for (i = 0; __bitrate_properties[i] != NULL; i++) {
+               if (!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(encoder)), __bitrate_properties[i]))
+                       continue;
+
+               g_object_get(G_OBJECT(encoder),  __bitrate_properties[i], &bitrate, NULL);
+               LOG_INFO("[%s] %s:%d", GST_OBJECT_NAME(gst_element_get_factory(encoder)), __bitrate_properties[i], bitrate);
+               *target_bitrate = bitrate;
+               return WEBRTC_ERROR_NONE;
+       }
+
+       LOG_ERROR("unknown bitrate property name");
+       return WEBRTC_ERROR_INVALID_OPERATION;
+}
+
 static GstElement * __prepare_encoder(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool is_audio)
 {
        GstElement *encoder = NULL;
@@ -952,6 +999,9 @@ static GstElement * __prepare_encoder(webrtc_s *webrtc, webrtc_gst_slot_s *sourc
                }
        }
 
+       if (source->av[is_audio ? AV_IDX_AUDIO : AV_IDX_VIDEO].target_bitrate > 0)
+               _set_encoder_element_bitrate(encoder, source->av[is_audio ? AV_IDX_AUDIO : AV_IDX_VIDEO].target_bitrate);
+
        return encoder;
 }