#include <mm_util_type.h>
#include <mm_util_image.h>
#include <mm_util_imgp.h>
+#include <mm_util_jpeg.h>
typedef struct {
unsigned char *data;
mm_util_color_format_e color_format;
MMVideoBuffer *vbuffer;
bool exit;
+ snapshot_format_e target_format;
+ int quality;
} queue_data_s;
+static const char * __format_str[] = {
+ [SNAPSHOT_FORMAT_RGB24] = "RGB24",
+ [SNAPSHOT_FORMAT_JPEG] = "JPEG",
+};
+
//LCOV_EXCL_START
static void __add_probe_to_pad_for_snapshot(webrtc_gst_slot_s *sink, GstElement *videosink, void *probe_cb)
{
RET_IF(videosink == NULL, "videosink is NULL");
RET_IF(probe_cb == NULL, "probe_cb is NULL");
- g_mutex_lock(&sink->snapshot.mutex); /* unlock in __remove_probe_from_pad_for_snapshot() */
-
pad = gst_element_get_static_pad(videosink, "sink");
media_type = _get_mime_type_from_pad(pad);
return vbuffer;
}
-static int __convert_colorspace(unsigned char *src_data, size_t src_size, int src_w, int src_h, mm_util_color_format_e src_fmt, mm_util_color_format_e dst_fmt, webrtc_video_frame_s *result)
+static int __mm_image_convert_colorspace(unsigned char *src_data, size_t src_size, int src_w, int src_h, mm_util_color_format_e src_fmt, mm_util_color_format_e dst_fmt, webrtc_video_frame_s *result)
{
int ret;
mm_util_image_h src_image;
return WEBRTC_ERROR_NONE;
}
+static int __mm_image_encode(unsigned char *src_data, size_t src_size, int src_w, int src_h, mm_util_color_format_e src_fmt, mm_util_img_codec_type codec, int quality, webrtc_video_frame_s *result)
+{
+ int ret;
+ mm_util_image_h src_image;
+
+ RET_VAL_IF(src_data == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_data is NULL");
+ RET_VAL_IF(result == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "result is NULL");
+
+ LOG_DEBUG_ENTER();
+
+ ret = mm_image_create_image(src_w, src_h, src_fmt, src_data, src_size, &src_image);
+ RET_VAL_IF(ret != MM_UTIL_ERROR_NONE, WEBRTC_ERROR_INVALID_OPERATION, "failed to mm_image_create_image()");
+
+ result->width = src_w;
+ result->height = src_h;
+
+ switch (codec) {
+ case IMG_CODEC_JPEG:
+ ret = mm_util_encode_to_jpeg_memory(src_image, quality, (void **)&result->data, &result->size);
+ mm_image_destroy_image(src_image);
+ RET_VAL_IF(ret != MM_UTIL_ERROR_NONE, WEBRTC_ERROR_INVALID_OPERATION, "failed to mm_util_encode_to_jpeg_memory()");
+
+ LOG_INFO("src[data:%p, size:%zu, %dx%d, fmt:%d] -> dst[data:%p, size:%zu, %ux%u, codec:JPEG, quality:%d]",
+ src_data, src_size, src_w, src_h, src_fmt,
+ result->data, result->size, result->width, result->height, quality);
+ return WEBRTC_ERROR_NONE;
+
+ default:
+ LOG_ERROR_IF_REACHED("codec(%d)", codec);
+ mm_image_destroy_image(src_image);
+ return WEBRTC_ERROR_INVALID_PARAMETER;
+ }
+}
+
static int __get_src_size(MMVideoBuffer *vbuffer, mm_util_color_format_e color_format)
{
RET_VAL_IF(vbuffer == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "vbuffer is NULL");
return WEBRTC_ERROR_INVALID_PARAMETER;
}
- return __convert_colorspace(dst_buffer, src_size, vbuffer->width[0], vbuffer->height[0], color_format,
+ return __mm_image_convert_colorspace(dst_buffer, src_size, vbuffer->width[0], vbuffer->height[0], color_format,
MM_UTIL_COLOR_RGB24, result_video_frame);
}
#ifdef DUMP_CONVERTED_RESULT
-static void __dump_converted_result(webrtc_video_frame_s *result)
+static void __dump_rgb24_result(webrtc_video_frame_s *result, unsigned int idx)
{
g_autofree gchar *file_path = NULL;
g_autoptr(GError) error = NULL;
- static unsigned int count = 1;
RET_IF(result == NULL, "result is NULL");
- LOG_DEBUG_ENTER();
+ if (!result->data)
+ return;
+
+ file_path = g_strdup_printf("/tmp/snapshot_%03u_%ux%u_RGB24.dump", idx, result->width, result->height);
+
+ if (!g_file_set_contents(file_path, (char *)result->data, result->size, &error)) {
+ LOG_ERROR("failed to g_file_set_contents() for %s, error:%s", file_path, error->message);
+ return;
+ }
+
+ 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, unsigned int idx)
+{
+ g_autofree gchar *file_path = NULL;
+ g_autoptr(GError) error = NULL;
+
+ RET_IF(result == NULL, "result is NULL");
if (!result->data)
return;
- file_path = g_strdup_printf("/tmp/snapshot_%03u_%ux%u_RGB24.dump", count++, result->width, result->height);
+ file_path = g_strdup_printf("/tmp/snapshot_%03u_%ux%u_%s.dump", idx, result->width, result->height, __format_str[target_format]);
if (!g_file_set_contents(file_path, (char *)result->data, result->size, &error)) {
LOG_ERROR("failed to g_file_set_contents() for %s, error:%s", file_path, error->message);
return;
}
- LOG_DEBUG("converted rgb24 frame is dumped to [%s]", file_path);
+ LOG_WARNING("encoded %s frame is dumped to [%s]", __format_str[target_format], file_path);
}
#endif
qd = g_new0(queue_data_s, 1);
qd->color_format = color_format;
qd->vbuffer = vbuffer;
+ qd->target_format = probe_data->slot->snapshot.target_format;
+ qd->quality = probe_data->slot->snapshot.quality;
g_async_queue_push(probe_data->slot->webrtc->snapshot.queue, qd);
out:
static gpointer __convert_thread(gpointer data)
{
webrtc_s *webrtc = (webrtc_s *)data;
+#ifdef DUMP_CONVERTED_RESULT
+ unsigned int idx = 0;
+#endif
while (1) {
- webrtc_video_frame_s result_frame = { NULL, 0, 0, 0 };
+ webrtc_video_frame_s rgb24_frame = { NULL, 0, 0, 0 };
+ webrtc_video_frame_s encoded_frame = { NULL, 0, 0, 0 };
queue_data_s *qd;
LOG_DEBUG("wait for data...");
qd = g_async_queue_pop(webrtc->snapshot.queue);
- LOG_INFO("process qd[%p, vbuffer:%p, exit:%d]", qd, qd->vbuffer, qd->exit);
+ LOG_INFO("process qd[%p, vbuffer:%p, target_format:%s, exit:%d]",
+ qd, qd->vbuffer, __format_str[qd->target_format], qd->exit);
if (qd->exit) {
__release_queue_data(qd);
break;
}
- /* convert and dump */
- if (__change_colorspace_to_rgb24(qd->vbuffer, qd->color_format, &result_frame) == WEBRTC_ERROR_NONE) {
+ /* FIXME: skip this conversion if encoder supports other input formats */
+ if (__change_colorspace_to_rgb24(qd->vbuffer, qd->color_format, &rgb24_frame) == WEBRTC_ERROR_NONE) {
+ int ret = WEBRTC_ERROR_NONE;
+
+ /* check target format and encode it if needed */
+ switch (qd->target_format) {
+ case SNAPSHOT_FORMAT_RGB24:
+ break; /* skip encoding */
+ case SNAPSHOT_FORMAT_JPEG:
+ ret = __mm_image_encode(rgb24_frame.data, rgb24_frame.size, rgb24_frame.width, rgb24_frame.height, MM_UTIL_COLOR_RGB24,
+ IMG_CODEC_JPEG, qd->quality, &encoded_frame);
+ if (ret != WEBRTC_ERROR_NONE)
+ LOG_ERROR("failed to __mm_image_encode() for %s", __format_str[qd->target_format]);
+ break;
+ default:
+ LOG_ERROR_IF_REACHED("target_format(%d)", qd->target_format);
+ break;
+ }
#ifdef DUMP_CONVERTED_RESULT
- __dump_converted_result(&result_frame);
+ __dump_rgb24_result(&rgb24_frame, ++idx);
+ __dump_encoded_result(&encoded_frame, qd->target_format, idx);
#endif
/* TODO: Append data to user callback */
}
__release_queue_data(qd);
- g_free(result_frame.data);
+ g_free(rgb24_frame.data);
+ g_free(encoded_frame.data);
}
LOG_DEBUG("exit");