Enumeration is added as below.
- WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_UNDERFLOW
- WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_OVERFLOW
Functions are added as below.
- webrtc_media_packet_source_set_format()
- webrtc_media_packet_source_push_packet()
- webrtc_media_packet_source_set_buffer_state_changed_cb()
- webrtc_media_packet_source_unset_buffer_state_changed_cb()
[Version] 0.1.76
[Issue Type] API
Change-Id: Idca077c8f1e933ef1a79828a0cf00a8f07c936ae
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
#define __TIZEN_MEDIA_WEBRTC_H__
#include <tizen.h>
+#include <media_format.h>
+#include <media_packet.h>
#ifdef __cplusplus
extern "C" {
WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET /**< Media packet */
} webrtc_media_source_type_e;
+/**
+ * @brief Enumeration for buffer state type of media packet source.
+ * @since_tizen 6.5
+ */
+typedef enum {
+ WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_UNDERFLOW, /**< Buffer underflow */
+ WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_OVERFLOW, /**< Buffer overflow */
+} webrtc_media_packet_source_buffer_state_e;
+
/**
* @brief Enumeration for WebRTC media type.
* @since_tizen 6.5
*/
typedef void (*webrtc_state_changed_cb)(webrtc_h webrtc, webrtc_state_e previous, webrtc_state_e current, void *user_data);
+/**
+ * @brief Called when the buffer state of media packet source is changed.
+ * @since_tizen 6.5
+ * @param[in] source_id The media source id
+ * @param[in] state The buffer state (underflow or overflow)
+ * @param[in] user_data The user data passed from the callback registration function
+ * @see webrtc_media_packet_source_set_buffer_state_changed_cb()
+ * @see webrtc_media_packet_source_unset_buffer_state_changed_cb()
+ */
+typedef void (*webrtc_media_packet_source_buffer_state_changed_cb)(unsigned int source_id, webrtc_media_packet_source_buffer_state_e state, void *user_data);
+
/**
* @brief Called when the WebRTC needs session negotiation.
* @since_tizen 6.5
* @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
* @retval #WEBRTC_ERROR_INVALID_STATE Invalid state
* @pre webrtc_ice_candidate_cb() must be set by calling webrtc_set_ice_candidate_cb().
+ * @pre webrtc_media_packet_source_set_format() must be set by calling webrtc_set_ice_candidate_cb().
* @pre @a webrtc state must be set to #WEBRTC_STATE_IDLE.
* @post @a webrtc state will be #WEBRTC_STATE_NEGOTIATING.
* @see webrtc_create()
*/
int webrtc_remove_media_source(webrtc_h webrtc, unsigned int source_id);
+/**
+ * @brief Sets a callback function to be invoked when the buffer state of media packet source is changed.
+ * @since_tizen 6.5
+ * @param[in] webrtc WebRTC handle
+ * @param[in] source_id The media packet source id
+ * @param[in] callback Callback function pointer
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Add media packet source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @post webrtc_media_packet_source_buffer_state_changed_cb() will be invoked.
+ * @see webrtc_media_packet_source_push_packet()
+ * @see webrtc_media_packet_source_unset_buffer_state_changed_cb()
+ * @see webrtc_media_packet_source_buffer_state_changed_cb()
+ */
+int webrtc_media_packet_source_set_buffer_state_changed_cb(webrtc_h webrtc, unsigned int source_id, webrtc_media_packet_source_buffer_state_changed_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the buffer state changed callback function.
+ * @since_tizen 6.5
+ * @param[in] webrtc WebRTC handle
+ * @param[in] source_id The media packet source id
+ * @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 packet source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @see webrtc_media_packet_source_set_buffer_state_changed_cb()
+ */
+int webrtc_media_packet_source_unset_buffer_state_changed_cb(webrtc_h webrtc, unsigned int source_id);
+
+/**
+ * @brief Sets media format to the media packet source.
+ * @since_tizen 6.5
+ * @param[in] webrtc WebRTC handle
+ * @param[in] source_id The media packet source id
+ * @param[in] format The media format
+ * @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
+ * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state
+ * @pre Add media packet source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @pre @a webrtc state must be set to #WEBRTC_STATE_IDLE.
+ * @see webrtc_media_packet_source_push_packet()
+ * @see webrtc_media_packet_source_set_buffer_state_changed_cb()
+ */
+int webrtc_media_packet_source_set_format(webrtc_h webrtc, unsigned int source_id, media_format_h format);
+
+/**
+ * @brief Pushes media packet to the media packet source.
+ * @since_tizen 6.5
+ * @param[in] webrtc WebRTC handle
+ * @param[in] source_id The media packet source id
+ * @param[in] packet The media packet
+ * @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
+ * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state
+ * @pre Add media packet source to @a webrtc to get @a source_id by calling webrtc_add_media_source().
+ * @pre @a webrtc state must be set to #WEBRTC_STATE_NEGOTIATING or #WEBRTC_STATE_PLAYING.
+ * @see webrtc_media_packet_source_set_format()
+ * @see webrtc_media_packet_source_set_buffer_state_changed_cb()
+ */
+int webrtc_media_packet_source_push_packet(webrtc_h webrtc, unsigned int source_id, media_packet_h packet);
+
/**
* @brief Gets the transceiver direction of the media source with specified media type.
* @since_tizen 6.5
int media_types; /* values of media_type_e combined with bitwise 'or' */
int mlines[2]; /* index 0 for audio, 1 for video */
media_format_h media_format;
+ webrtc_callbacks_s buffer_state_changed_cb;
webrtc_display_s *display;
} webrtc_gst_slot_s;
int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigned int *source_id);
int _remove_media_source(webrtc_s *webrtc, unsigned int source_id);
int _set_media_format(webrtc_s *webrtc, unsigned int source_id, media_format_h format);
+bool _check_if_format_is_set_to_packet_sources(webrtc_s *webrtc);
+int _push_media_packet(webrtc_s *webrtc, unsigned int source_id, media_packet_h packet);
int _get_transceiver_direction(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_direction_e *direction);
int _set_transceiver_direction(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_direction_e direction);
void _post_state_in_idle(webrtc_s *webrtc, webrtc_state_e new_state);
Name: capi-media-webrtc
Summary: A WebRTC library in Tizen Native API
-Version: 0.1.75
+Version: 0.1.76
Release: 0
Group: Multimedia/API
License: Apache-2.0
RET_VAL_WITH_UNLOCK_IF(_webrtc->ice_candidate_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_webrtc->mutex, "the ice candidate callback should be set");
RET_VAL_WITH_UNLOCK_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should be IDLE");
RET_VAL_WITH_UNLOCK_IF(_webrtc->gst.webrtcbin == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_webrtc->mutex, "webrtcbin is NULL");
+ RET_VAL_WITH_UNLOCK_IF(!_check_if_format_is_set_to_packet_sources(_webrtc), WEBRTC_ERROR_INVALID_OPERATION, &_webrtc->mutex, "the media format should be set");
_gst_pipeline_set_state(webrtc, GST_STATE_PLAYING);
_webrtc->pend_state = WEBRTC_STATE_NEGOTIATING;
g_mutex_lock(&_webrtc->mutex);
- RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should not be IDLE");
+ RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should NOT be IDLE");
_gst_pipeline_set_state(_webrtc, GST_STATE_NULL);
return ret;
}
+int webrtc_media_packet_source_set_buffer_state_changed_cb(webrtc_h webrtc, unsigned int source_id, webrtc_media_packet_source_buffer_state_changed_cb callback, void *user_data)
+{
+ webrtc_s *_webrtc = (webrtc_s*)webrtc;
+ 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(callback == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ g_mutex_lock(&_webrtc->mutex);
+
+ RET_VAL_WITH_UNLOCK_IF((source = _get_slot_by_id(_webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER,
+ &_webrtc->mutex, "source is NULL");
+ RET_VAL_WITH_UNLOCK_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET, WEBRTC_ERROR_INVALID_PARAMETER, &_webrtc->mutex,
+ "source is not media packet type");
+
+ source->buffer_state_changed_cb.callback = callback;
+ source->buffer_state_changed_cb.user_data = user_data;
+
+ LOG_INFO("callback[%p] user_data[%p]", callback, user_data);
+
+ g_mutex_unlock(&_webrtc->mutex);
+
+ return WEBRTC_ERROR_NONE;
+}
+
+int webrtc_media_packet_source_unset_buffer_state_changed_cb(webrtc_h webrtc, unsigned int source_id)
+{
+ webrtc_s *_webrtc = (webrtc_s*)webrtc;
+ 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");
+
+ g_mutex_lock(&_webrtc->mutex);
+
+ RET_VAL_WITH_UNLOCK_IF((source = _get_slot_by_id(_webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER,
+ &_webrtc->mutex, "source is NULL");
+ RET_VAL_WITH_UNLOCK_IF(source->type != WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET, WEBRTC_ERROR_INVALID_PARAMETER, &_webrtc->mutex,
+ "source is not media packet type");
+ RET_VAL_WITH_UNLOCK_IF(source->buffer_state_changed_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_webrtc->mutex,\
+ "callback was not set");
+
+ LOG_INFO("callback[%p] user_data[%p] is reset to NULL",
+ source->buffer_state_changed_cb.callback, source->buffer_state_changed_cb.user_data);
+
+ source->buffer_state_changed_cb.callback = NULL;
+ source->buffer_state_changed_cb.user_data = NULL;
+
+ g_mutex_unlock(&_webrtc->mutex);
+
+ return WEBRTC_ERROR_NONE;
+}
+
+int webrtc_media_packet_source_set_format(webrtc_h webrtc, unsigned int source_id, media_format_h format)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_s *_webrtc = (webrtc_s*)webrtc;
+
+ RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(format == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "format is NULL");
+
+ g_mutex_lock(&_webrtc->mutex);
+
+ RET_VAL_WITH_UNLOCK_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should be IDLE");
+
+ ret = _set_media_format(_webrtc, source_id, format);
+ if (ret == WEBRTC_ERROR_NONE)
+ LOG_INFO("source_id[%u] format[%p]", source_id, format);
+
+ g_mutex_unlock(&_webrtc->mutex);
+
+ return ret;
+}
+
+int webrtc_media_packet_source_push_packet(webrtc_h webrtc, unsigned int source_id, media_packet_h packet)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_s *_webrtc = (webrtc_s*)webrtc;
+
+ RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(packet == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "packet is NULL");
+
+ g_mutex_lock(&_webrtc->mutex);
+
+ RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should NOT be IDLE");
+
+ ret = _push_media_packet(webrtc, source_id, packet);
+
+ g_mutex_unlock(&_webrtc->mutex);
+
+ return ret;
+}
+
int webrtc_get_transceiver_direction(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_direction_e *direction)
{
int ret = WEBRTC_ERROR_NONE;
g_mutex_lock(&_webrtc->mutex);
- RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_PLAYING, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should not be PLAYING");
+ RET_VAL_WITH_UNLOCK_IF(_webrtc->state == WEBRTC_STATE_PLAYING, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should NOT be PLAYING");
_webrtc->track_added_cb.callback = callback;
_webrtc->track_added_cb.user_data = user_data;
#include "webrtc.h"
#include "webrtc_private.h"
+#include <tbm_surface_internal.h>
#define GST_KLASS_NAME_ENCODER_AUDIO "Codec/Encoder/Audio"
#define GST_KLASS_NAME_ENCODER_VIDEO "Codec/Encoder/Video"
RET_IF(source == NULL, "source is NULL");
LOG_INFO("appsrc[%s] size[%u] source[%p, idx:%u]", GST_ELEMENT_NAME(appsrc), size, source, source->id);
+
+ if (source->buffer_state_changed_cb.callback == NULL) {
+ LOG_DEBUG("buffer state changed callback is NULL");
+ return;
+ }
+
+ LOG_DEBUG(">>> invoke buffer_state_changed_cb[%p] for UNDERFLOW, user_data[%p]",
+ source->buffer_state_changed_cb.callback, source->buffer_state_changed_cb.user_data);
+ ((webrtc_media_packet_source_buffer_state_changed_cb)(source->buffer_state_changed_cb.callback))
+ (source->id, WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_UNDERFLOW, source->buffer_state_changed_cb.user_data);
+ LOG_DEBUG("<<< end of the callback");
}
static void _appsrc_enough_data_cb(GstElement *appsrc, gpointer data)
RET_IF(source == NULL, "source is NULL");
LOG_INFO("appsrc[%s] source[%p, idx:%u]", GST_ELEMENT_NAME(appsrc), source, source->id);
+
+ if (source->buffer_state_changed_cb.callback == NULL) {
+ LOG_DEBUG("buffer state changed callback is NULL");
+ return;
+ }
+
+ LOG_DEBUG(">>> invoke buffer_state_changed_cb[%p] for OVERFLOW, user_data[%p]",
+ source->buffer_state_changed_cb.callback, source->buffer_state_changed_cb.user_data);
+ ((webrtc_media_packet_source_buffer_state_changed_cb)(source->buffer_state_changed_cb.callback))
+ (source->id, WEBRTC_MEDIA_PACKET_SOURCE_BUFFER_STATE_OVERFLOW, source->buffer_state_changed_cb.user_data);
+ LOG_DEBUG("<<< end of the callback");
}
static int __build_mediapacketsrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
LOG_ERROR("failed to create appsrc");
return WEBRTC_ERROR_INVALID_OPERATION;
}
- g_object_set(G_OBJECT(appsrc), "emit-signals", TRUE, "is-live", TRUE, NULL);
+
+ g_object_set(G_OBJECT(appsrc), "emit-signals", TRUE, "is-live", TRUE, "format", 3, NULL); /* format 3 for time format of the segment events and seek */
_connect_and_append_signal(&source->signals, G_OBJECT(appsrc), "need-data", G_CALLBACK(_appsrc_need_data_cb), source);
_connect_and_append_signal(&source->signals, G_OBJECT(appsrc), "enough-data", G_CALLBACK(_appsrc_enough_data_cb), source);
return ret;
}
+ return WEBRTC_ERROR_NONE;
+}
+
+static gboolean __check_format_is_not_set_cb(gpointer key, gpointer value, gpointer user_data)
+{
+ webrtc_gst_slot_s *source = value;
+
+ if (source->type == GPOINTER_TO_UINT(user_data)) {
+ LOG_INFO("found media packet source[%p, id:%u, media_format:%p]", source, source->id, source->media_format);
+ if (!source->media_format)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool _check_if_format_is_set_to_packet_sources(webrtc_s *webrtc)
+{
+ webrtc_gst_slot_s *source;
+
+ RET_VAL_IF(webrtc == NULL, false, "webrtc is NULL");
+
+ source = g_hash_table_find(webrtc->gst.source_slots, __check_format_is_not_set_cb, GUINT_TO_POINTER(WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET));
+ if (source) {
+ LOG_ERROR("media format is not set to the media packet source[%u]", source->id);
+ return false;
+ }
+
+ return true;
+}
+
+static int __fill_gst_buffer_mapped_data_from_packet(GstBuffer *buffer, media_packet_h packet)
+{
+ bool has_tbm_surface = false;
+ tbm_surface_info_s ts_info;
+ guint64 size = 0;
+ GstMapInfo buff_info = GST_MAP_INFO_INIT;
+
+ RET_VAL_IF(buffer == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "buffer is NULL");
+ RET_VAL_IF(packet == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "packet is NULL");
+
+ media_packet_get_buffer_size(packet, &size);
+ media_packet_has_tbm_surface_buffer(packet, &has_tbm_surface);
+
+ if (has_tbm_surface) {
+ int ret = TBM_SURFACE_ERROR_NONE;
+ tbm_surface_h ts;
+
+ media_packet_get_tbm_surface(packet, &ts);
+ ret = tbm_surface_get_info(ts, &ts_info);
+ if (ret != TBM_SURFACE_ERROR_NONE) {
+ LOG_ERROR("failed to tbm_surface_get_info()");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ LOG_DEBUG("tbm surface[%p, %ux%u, size:%u, format:%u, num_planes:%u] found",
+ ts, ts_info.width, ts_info.height, ts_info.size, ts_info.format, ts_info.num_planes);
+ }
+
+ if (gst_buffer_map(buffer, &buff_info, GST_MAP_READWRITE)) {
+ if (has_tbm_surface) {
+ int i;
+ guint8 *ptr = buff_info.data;
+ for (i = 0; i < ts_info.num_planes; i++) {
+ LOG_DEBUG("plane[%d][ptr:%p size:%u]", i, ts_info.planes[i].ptr, ts_info.planes[i].size);
+ memcpy(ptr, ts_info.planes[i].ptr, ts_info.planes[i].size);
+ ptr += ts_info.planes[i].size;
+ }
+
+ } else {
+ guchar *data_ptr;
+ media_packet_get_buffer_data_ptr(packet, (void **)&data_ptr);
+ if (data_ptr == NULL) {
+ LOG_ERROR("invalid packet, data_ptr is NULL");
+ gst_buffer_unmap(buffer, &buff_info);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ memcpy(buff_info.data, data_ptr, size);
+ }
+
+ buff_info.size = size;
+
+ LOG_DEBUG("buffer[%p], buff_info[data:%p, size:%u]", buffer, buff_info.data, buff_info.size);
+
+ gst_buffer_unmap(buffer, &buff_info);
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+int _push_media_packet(webrtc_s *webrtc, unsigned int source_id, media_packet_h packet)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_gst_slot_s *source;
+ guchar *data_ptr;
+ GstElement *appsrc;
+ GstBuffer *new_buffer;
+ guint64 pts = 0;
+ guint64 duration = 0;
+ guint64 size = 0;
+ GstFlowReturn gst_ret = GST_FLOW_OK;
+
+ 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->media_format == NULL, WEBRTC_ERROR_INVALID_OPERATION, "media_format is NULL");
+
+ appsrc = __find_element_in_bin(source->bin, "appsrc");
+ if (appsrc == NULL) {
+ LOG_ERROR("source_id[%u] is not for media packet source", source_id);
+ return WEBRTC_ERROR_INVALID_PARAMETER;
+ }
+
+ if (packet == NULL) {
+ LOG_INFO("packet is NULL, emit EOS signal");
+ g_signal_emit_by_name(G_OBJECT(appsrc), "end-of-stream", &gst_ret, NULL);
+ if (gst_ret != GST_FLOW_OK) {
+ LOG_ERROR("failed to 'end-of-stream', gst_ret[0x%x]", gst_ret);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ return WEBRTC_ERROR_NONE;
+ }
+
+ media_packet_get_buffer_data_ptr(packet, (void **)&data_ptr);
+ if (data_ptr == NULL) {
+ LOG_ERROR("invalid packet, data_ptr is NULL");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ media_packet_get_buffer_size(packet, &size);
+
+ new_buffer = gst_buffer_new_and_alloc(size);
+ if (!new_buffer) {
+ LOG_ERROR("failed to gst_buffer_new_and_alloc()");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+ ret = __fill_gst_buffer_mapped_data_from_packet(new_buffer, packet);
+ if (ret != WEBRTC_ERROR_NONE) {
+ LOG_ERROR("failed to __fill_gst_buffer_mapped_data_from_packet()");
+ return ret;
+ }
+
+ media_packet_get_pts(packet, &pts);
+ GST_BUFFER_PTS(new_buffer) = pts;
+
+ media_packet_get_duration(packet, &duration);
+ GST_BUFFER_DURATION(new_buffer) = duration;
+
+ LOG_DEBUG("new gst buffer[%p, pts:%llu, duration:%llu]", new_buffer, pts, duration);
+
+ g_signal_emit_by_name(G_OBJECT(appsrc), "push-buffer", new_buffer, &gst_ret, NULL);
+ gst_buffer_unref(new_buffer);
+
+ if (gst_ret != GST_FLOW_OK) {
+ LOG_ERROR("failed to 'push-buffer', gst_ret[0x%x]", gst_ret);
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
return WEBRTC_ERROR_NONE;
}
\ No newline at end of file