WEBRTC_MEDIA_SOURCE_TYPE_CUSTOM_VIDEO, /**< Custom video */
} webrtc_media_source_type_internal_e;
+/**
+ * @internal
+ * @brief Enumeration for WebRTC snapshot format.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ WEBRTC_SNAPSHOT_FORMAT_RAW_RGB24 = 0x01, /**< Raw 24-bit RGB */
+ WEBRTC_SNAPSHOT_FORMAT_JPEG = 0x11, /**< JPEG */
+ WEBRTC_SNAPSHOT_FORMAT_PNG = 0x12, /**< PNG */
+} webrtc_snapshot_format_e;
+
+/**
+ * @internal
+ * @brief Definition for snapshot option.
+ * @since_tizen 7.0
+ * @see webrtc_take_snapshot()
+ */
+#define WEBRTC_SNAPSHOT_OPTION_NONE -1
+
/**
* @internal
* @brief Enumeration for WebRTC signaling message type.
SIGNALING_MESSAGE_TYPE_ERROR, /**< Error */
} webrtc_signaling_message_type_e;
+
+/**
+ * @internal
+ * @brief Called when an image is captured by webrtc_take_snapshot().
+ * @since_tizen 7.0
+ * @remarks The @a webrtc is the same object for which the callback was set.\n
+ * The @a webrtc should not be released.\n
+ * The @a data should not be released. The @a data can be used only in the callback. To use outside, make a copy.
+ * @param[in] webrtc WebRTC handle
+ * @param[in] track_id The track id
+ * @param[in] format The snapshot image format
+ * @param[in] data The snapshot image data captured from @a track_id
+ * @param[in] width The snapshot image width
+ * @param[in] height The snapshot image height
+ * @param[in] size The size of @a data
+ * @param[in] user_data The user data passed from the callback registration function
+ * @see webrtc_take_snapshot()
+ */
+typedef void (*webrtc_snapshot_cb)(webrtc_h webrtc, unsigned int track_id, webrtc_snapshot_format_e format, const char *data, int width, int height, unsigned int size, void *user_data);
+
/**
* @internal
* @brief Called when a message to be handled is sent from the remote peer or the signaling server.
*/
int webrtc_get_video_resolution(webrtc_h webrtc, unsigned int track_id, int *width, int *height);
+/**
+ * @internal
+ * @brief Takes a snapshot from the video track asynchronously.
+ * @since_tizen 7.0
+ * @remarks The registered callback will be invoked in an internal thread of the webrtc.\n
+ * If webrtc_set_encoded_video_frame_cb() has been called, it will return #WEBRTC_ERROR_INVALID_OPERATION.\n
+ * @a option only affects when @a format is #WEBRTC_SNAPSHOT_FORMAT_JPEG or #WEBRTC_SNAPSHOT_FORMAT_PNG,
+ * otherwise #WEBRTC_SNAPSHOT_OPTION_NONE can be used.\n
+ * If @a format is #WEBRTC_SNAPSHOT_FORMAT_JPEG, @a option is for quality level which range from 1 to 100.\n
+ * If @a format is #WEBRTC_SNAPSHOT_FORMAT_PNG, @a option is for compression level which range from 0 to 9.\n
+ * @param[in] webrtc WebRTC handle
+ * @param[in] track_id The track id
+ * @param[in] format The snapshot image format
+ * @param[in] option The option of @a format
+ * @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
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre webrtc_track_added_cb() must be set by calling webrtc_set_track_added_cb().
+ * @post webrtc_snapshot_cb() will be invoked.
+ */
+int webrtc_take_snapshot(webrtc_h webrtc, unsigned int track_id, webrtc_snapshot_format_e format, int option, webrtc_snapshot_cb callback, void *user_data);
+
/**
* @internal
* @brief Sets a video loopback to render the video frames of the media source to an ecore wayland display.
#include <libwebsockets.h>
#include <libsoup/soup.h>
-#include "webrtc.h"
+#include "webrtc_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
} webrtc_s;
-typedef enum snapshot_format_e {
- SNAPSHOT_FORMAT_RGB24,
- SNAPSHOT_FORMAT_JPEG,
- SNAPSHOT_FORMAT_PNG,
-} snapshot_format_e;
-
/* FIXME: divide into two slot types or use union */
typedef struct _webrtc_gst_slot_s {
unsigned int id;
GstPad *sink_pad;
gulong sink_pad_probe_id;
GMutex mutex;
- snapshot_format_e target_format;
- int option; /* quality for JPEG, compression level for PNG */
+ unsigned int track_id;
+ int target_format;
+ int option; /* quality level for JPEG, compression level for PNG */
+ void *callback;
+ void *user_data;
} snapshot;
struct {
/* sink capture video frame */
int _init_convert_thread(webrtc_s *webrtc);
void _deinit_convert_thread(webrtc_s *webrtc);
-int _capture_video_frame_from_sink(webrtc_s *webrtc, unsigned int track_id, snapshot_format_e format, int option);
+int _capture_video_frame_from_sink(webrtc_s *webrtc, unsigned int track_id, int format, int option, webrtc_snapshot_cb callback, void *user_data);
int _capture_video_frame(webrtc_gst_slot_s *sink);
/* display */
Name: capi-media-webrtc
Summary: A WebRTC library in Tizen Native API
-Version: 0.3.271
+Version: 0.3.272
Release: 0
Group: Multimedia/API
License: Apache-2.0
return _get_video_resolution_from_sink(_webrtc, track_id, width, height);
}
+int webrtc_take_snapshot(webrtc_h webrtc, unsigned int track_id, webrtc_snapshot_format_e format, int option, webrtc_snapshot_cb callback, void *user_data)
+{
+ g_autoptr(GMutexLocker) locker = NULL;
+ webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+ RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(callback == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ locker = g_mutex_locker_new(&_webrtc->mutex);
+
+ RET_VAL_IF(_webrtc->track_added_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, "track added callback was not set");
+
+ return _capture_video_frame_from_sink(_webrtc, track_id, format, option, callback, user_data);
+}
+
int webrtc_media_source_set_video_loopback_to_ecore_wl(webrtc_h webrtc, unsigned int source_id, void *ecore_wl_window, unsigned int *track_id)
{
int ret = WEBRTC_ERROR_NONE;
return WEBRTC_ERROR_NONE;
}
-int _capture_video_frame_from_sink(webrtc_s *webrtc, unsigned int track_id, snapshot_format_e format, int option)
+int _capture_video_frame_from_sink(webrtc_s *webrtc, unsigned int track_id, int format, int option, webrtc_snapshot_cb callback, void *user_data)
{
webrtc_gst_slot_s *sink;
RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
RET_VAL_IF(sink->encoded_frame_cb != NULL, WEBRTC_ERROR_INVALID_OPERATION, "it may be a forwarding sink for encoded frame callback");
RET_VAL_IF((sink->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_OPERATION, "it's not a video track");
- RET_VAL_IF(format == SNAPSHOT_FORMAT_JPEG && (option < 1 || option > 100), WEBRTC_ERROR_INVALID_PARAMETER, "invalid JPEG option value");
- RET_VAL_IF(format == SNAPSHOT_FORMAT_PNG && (option < 0 || option > 9), WEBRTC_ERROR_INVALID_PARAMETER, "invalid PNG option value");
+ RET_VAL_IF(format == WEBRTC_SNAPSHOT_FORMAT_JPEG && (option < 1 || option > 100), WEBRTC_ERROR_INVALID_PARAMETER, "invalid JPEG option value");
+ RET_VAL_IF(format == WEBRTC_SNAPSHOT_FORMAT_PNG && (option < 0 || option > 9), WEBRTC_ERROR_INVALID_PARAMETER, "invalid PNG option value");
g_mutex_lock(&sink->snapshot.mutex); /* unlock in __remove_probe_from_pad_for_snapshot() */
+ sink->snapshot.track_id = track_id;
sink->snapshot.target_format = format;
sink->snapshot.option = option;
+ sink->snapshot.callback = callback;
+ sink->snapshot.user_data = user_data;
- LOG_INFO("webrtc[%p] track_id[%u] format[%d] option[%d]", webrtc, track_id, format, option);
+ LOG_INFO("webrtc[%p] track_id[%u] format[0x%x] option[%d] callback[%p] user_data[%p]",
+ webrtc, track_id, format, option, callback, user_data);
return _capture_video_frame(sink);
}
* limitations under the License.
*/
-#include "webrtc.h"
+#include "webrtc_internal.h"
#include "webrtc_private.h"
#include <gst/video/video-info.h>
#include <mm_error.h>
mm_util_color_format_e color_format;
MMVideoBuffer *vbuffer;
bool exit;
- snapshot_format_e target_format;
+ unsigned int track_id;
+ int target_format;
int option;
+ void *callback;
+ void *user_data;
} queue_data_s;
static const char * __format_str[] = {
- [SNAPSHOT_FORMAT_RGB24] = "RGB24",
- [SNAPSHOT_FORMAT_JPEG] = "JPEG",
- [SNAPSHOT_FORMAT_PNG] = "PNG",
+ [WEBRTC_SNAPSHOT_FORMAT_RAW_RGB24] = "RGB24",
+ [WEBRTC_SNAPSHOT_FORMAT_JPEG] = "JPEG",
+ [WEBRTC_SNAPSHOT_FORMAT_PNG] = "PNG",
};
//LCOV_EXCL_START
LOG_WARNING("converted rgb24 frame is dumped to [%s]", file_path);
}
-static void __dump_encoded_result(webrtc_video_frame_s *result, snapshot_format_e target_format, int option, unsigned int idx)
+static void __dump_encoded_result(webrtc_video_frame_s *result, int target_format, int option, unsigned int idx)
{
g_autofree gchar *file_path = NULL;
g_autoptr(GError) error = NULL;
qd = g_new0(queue_data_s, 1);
qd->color_format = color_format;
qd->vbuffer = vbuffer;
+ qd->track_id = probe_data->slot->snapshot.track_id;
qd->target_format = probe_data->slot->snapshot.target_format;
qd->option = probe_data->slot->snapshot.option;
+ qd->callback = probe_data->slot->snapshot.callback;
+ qd->user_data = probe_data->slot->snapshot.user_data;
g_async_queue_push(probe_data->slot->webrtc->snapshot.queue, qd);
out:
/* check target format and encode it if needed */
switch (qd->target_format) {
- case SNAPSHOT_FORMAT_RGB24:
+ case WEBRTC_SNAPSHOT_FORMAT_RAW_RGB24:
break; /* skip encoding */
- case SNAPSHOT_FORMAT_JPEG:
- case SNAPSHOT_FORMAT_PNG:
+ case WEBRTC_SNAPSHOT_FORMAT_JPEG:
+ case WEBRTC_SNAPSHOT_FORMAT_PNG:
ret = __mm_image_encode(rgb24_frame.data, rgb24_frame.size, rgb24_frame.width, rgb24_frame.height, MM_UTIL_COLOR_RGB24,
- (qd->target_format == SNAPSHOT_FORMAT_JPEG) ? IMG_CODEC_JPEG : IMG_CODEC_PNG, qd->option, &encoded_frame);
+ (qd->target_format == WEBRTC_SNAPSHOT_FORMAT_JPEG) ? IMG_CODEC_JPEG : IMG_CODEC_PNG, qd->option, &encoded_frame);
break;
default:
- LOG_ERROR_IF_REACHED("target_format(%d)", qd->target_format);
+ LOG_ERROR_IF_REACHED("target_format(0x%x)", qd->target_format);
ret = WEBRTC_ERROR_INVALID_PARAMETER;
break;
}
- if (ret != WEBRTC_ERROR_NONE)
- LOG_ERROR("failed to encode image(), ret[0x%x]", ret);
+ if (ret == WEBRTC_ERROR_NONE) {
+ int width = (int)(encoded_frame.data ? encoded_frame.width : rgb24_frame.width);
+ int height = (int)(encoded_frame.data ? encoded_frame.height : rgb24_frame.height);
+ unsigned int size = (unsigned int)(encoded_frame.data ? encoded_frame.size : rgb24_frame.size);
#ifdef DUMP_CONVERTED_RESULT
- __dump_rgb24_result(&rgb24_frame, ++idx);
- __dump_encoded_result(&encoded_frame, qd->target_format, qd->option, idx);
+ __dump_rgb24_result(&rgb24_frame, ++idx);
+ __dump_encoded_result(&encoded_frame, qd->target_format, qd->option, idx);
#endif
- /* TODO: Append data to user callback */
+ LOG_DEBUG(">>> callback[%p] user_data[%p] track_id[%u] format[%s] %ux%u",
+ qd->callback, qd->user_data, qd->track_id, __format_str[qd->target_format], width, height);
+ ((webrtc_snapshot_cb)(qd->callback))(webrtc, qd->track_id, qd->target_format, encoded_frame.data ?
+ (const char *)encoded_frame.data : (const char *)rgb24_frame.data, width, height, size, qd->user_data);
+ LOG_DEBUG("<<< end of the callback");
+ } else {
+ LOG_ERROR("failed to encode image(), skip invoking callback, ret[0x%x]", ret);
+ }
}
__release_queue_data(qd);