#include "webrtc.h"
#include "webrtc_private.h"
#include <mm_error.h>
+#include <gst/video/video-info.h>
+#include <tbm_surface_internal.h>
+#include <media_packet.h>
+#include <media_format.h>
-int _apply_display(webrtc_s *webrtc, webrtc_display_s *display)
+#define BUFFER_MAX_PLANE_NUM 4
+
+typedef struct _video_decoded_data_s {
+ MMPixelFormatType format; /**< image format */
+ int width; /**< width of video buffer */
+ int height; /**< height of video buffer */
+ unsigned int timestamp; /**< timestamp of buffer (msec)*/
+ unsigned int length_total; /**< total length of buffer (in byte)*/
+ void *data[BUFFER_MAX_PLANE_NUM];
+ void *bo[BUFFER_MAX_PLANE_NUM]; /**< TBM buffer object */
+ int stride[BUFFER_MAX_PLANE_NUM]; /**< stride of plane */
+ int elevation[BUFFER_MAX_PLANE_NUM]; /**< elevation of plane */
+ int orientation; /**< orientation */
+ int bo_size; /**< TBM buffer object size */
+ int plane_num; /**< number of Plane */
+} video_decoded_data_info_s;
+
+typedef struct _media_packet_finalize_data_s {
+ webrtc_tbm_s *tbm;
+ video_decoded_data_info_s *info;
+} media_packet_finalize_data_s;
+
+static guint32 __convert_fourcc_string_to_value(const gchar *format_name)
+{
+ return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
+}
+
+static int __get_pixel_format(unsigned int fourcc)
+{
+ switch (fourcc) {
+ case GST_MAKE_FOURCC('S', 'N', '1', '2'):
+ case GST_MAKE_FOURCC('N', 'V', '1', '2'):
+ return MM_PIXEL_FORMAT_NV12;
+ case GST_MAKE_FOURCC('S', 'T', '1', '2'):
+ return MM_PIXEL_FORMAT_NV12T;
+ case GST_MAKE_FOURCC('S', 'N', '2', '1'):
+ case GST_MAKE_FOURCC('N', 'V', '2', '1'):
+ return MM_PIXEL_FORMAT_NV21;
+ case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
+ case GST_MAKE_FOURCC('Y', 'U', 'Y', 'V'):
+ case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
+ return MM_PIXEL_FORMAT_YUYV;
+ case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
+ case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'):
+ return MM_PIXEL_FORMAT_UYVY;
+ case GST_MAKE_FOURCC('S', '4', '2', '0'):
+ case GST_MAKE_FOURCC('I', '4', '2', '0'):
+ return MM_PIXEL_FORMAT_I420;
+ case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
+ return MM_PIXEL_FORMAT_YV12;
+ case GST_MAKE_FOURCC('4', '2', '2', 'P'):
+ return MM_PIXEL_FORMAT_422P;
+ case GST_MAKE_FOURCC('R', 'G', 'B', 'P'):
+ return MM_PIXEL_FORMAT_RGB565;
+ case GST_MAKE_FOURCC('R', 'G', 'B', '3'):
+ return MM_PIXEL_FORMAT_RGB888;
+ case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
+ case GST_MAKE_FOURCC('x', 'R', 'G', 'B'):
+ return MM_PIXEL_FORMAT_ARGB;
+ case GST_MAKE_FOURCC('B', 'G', 'R', 'A'):
+ case GST_MAKE_FOURCC('B', 'G', 'R', 'x'):
+ case GST_MAKE_FOURCC('S', 'R', '3', '2'):
+ return MM_PIXEL_FORMAT_RGBA;
+ default:
+ LOG_ERROR("not supported fourcc type(%c%c%c%c)", fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24);
+ return MM_PIXEL_FORMAT_INVALID;
+ }
+}
+
+static int __get_tbm_surface_format(int pixel_format, uint32_t *tbm_format)
+{
+ RET_VAL_IF(pixel_format <= MM_PIXEL_FORMAT_INVALID, WEBRTC_ERROR_INVALID_PARAMETER, "invalid pixel_format(%d)", pixel_format);
+ RET_VAL_IF(pixel_format >= MM_PIXEL_FORMAT_NUM, WEBRTC_ERROR_INVALID_PARAMETER, "invalid pixel_format(%d)", pixel_format);
+ RET_VAL_IF(tbm_format == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "tbm_format is NULL");
+
+ switch (pixel_format) {
+ case MM_PIXEL_FORMAT_NV12:
+ *tbm_format = TBM_FORMAT_NV12;
+ break;
+ case MM_PIXEL_FORMAT_NV12T:
+ *tbm_format = TBM_FORMAT_NV12MT;
+ break;
+ case MM_PIXEL_FORMAT_NV16:
+ *tbm_format = TBM_FORMAT_NV16;
+ break;
+ case MM_PIXEL_FORMAT_NV21:
+ *tbm_format = TBM_FORMAT_NV21;
+ break;
+ case MM_PIXEL_FORMAT_YUYV:
+ *tbm_format = TBM_FORMAT_YUYV;
+ break;
+ case MM_PIXEL_FORMAT_UYVY:
+ case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
+ *tbm_format = TBM_FORMAT_UYVY;
+ break;
+ case MM_PIXEL_FORMAT_422P:
+ *tbm_format = TBM_FORMAT_YUV422;
+ break;
+ case MM_PIXEL_FORMAT_I420:
+ *tbm_format = TBM_FORMAT_YUV420;
+ break;
+ case MM_PIXEL_FORMAT_YV12:
+ *tbm_format = TBM_FORMAT_YVU420;
+ break;
+ case MM_PIXEL_FORMAT_RGB565:
+ *tbm_format = TBM_FORMAT_RGB565;
+ break;
+ case MM_PIXEL_FORMAT_RGB888:
+ *tbm_format = TBM_FORMAT_RGB888;
+ break;
+ case MM_PIXEL_FORMAT_RGBA:
+ *tbm_format = TBM_FORMAT_ARGB8888;
+ break;
+ case MM_PIXEL_FORMAT_ARGB:
+ *tbm_format = TBM_FORMAT_ARGB8888;
+ break;
+ default:
+ LOGE("not suppported pixel_format(%d)", pixel_format);
+ return WEBRTC_ERROR_INVALID_PARAMETER;
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+/* These values are based on media_format.h */
+static const char *__get_format_string_from_mime_type(media_format_mimetype_e mimetype)
+{
+ if (mimetype & 0x2510)
+ return "I420";
+ if (mimetype & 0x2520)
+ return "NV12";
+ if (mimetype & 0x2530)
+ return "NV12T";
+ if (mimetype & 0x2540)
+ return "YV12";
+ if (mimetype & 0x2550)
+ return "NV21";
+ if (mimetype & 0x2560)
+ return "NV16";
+ if (mimetype & 0x2570)
+ return "YUYV";
+ if (mimetype & 0x2580)
+ return "UYVY";
+ if (mimetype & 0x2590)
+ return "422P";
+ if (mimetype & 0x25a0)
+ return "RGB565";
+ if (mimetype & 0x25b0)
+ return "RGB888";
+ if (mimetype & 0x25c0)
+ return "RGBA";
+ if (mimetype & 0x25d0)
+ return "ARGB";
+ if (mimetype & 0x25e0)
+ return "BGRA";
+ if (mimetype & 0x25f0)
+ return "Y8";
+
+ return "UNKNOWN";
+}
+
+static int __get_media_packet_mimetype(int pixel_format, media_format_mimetype_e *mimetype)
+{
+ RET_VAL_IF(pixel_format <= MM_PIXEL_FORMAT_INVALID, WEBRTC_ERROR_INVALID_PARAMETER, "invalid pixel_format(%d)", pixel_format);
+ RET_VAL_IF(pixel_format >= MM_PIXEL_FORMAT_NUM, WEBRTC_ERROR_INVALID_PARAMETER, "invalid pixel_format(%d)", pixel_format);
+ RET_VAL_IF(mimetype == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "mimetype is NULL");
+
+ switch (pixel_format) {
+ case MM_PIXEL_FORMAT_NV12:
+ *mimetype = MEDIA_FORMAT_NV12;
+ break;
+ case MM_PIXEL_FORMAT_NV12T:
+ *mimetype = MEDIA_FORMAT_NV12T;
+ break;
+ case MM_PIXEL_FORMAT_NV16:
+ *mimetype = MEDIA_FORMAT_NV16;
+ break;
+ case MM_PIXEL_FORMAT_NV21:
+ *mimetype = MEDIA_FORMAT_NV21;
+ break;
+ case MM_PIXEL_FORMAT_YUYV:
+ *mimetype = MEDIA_FORMAT_YUYV;
+ break;
+ case MM_PIXEL_FORMAT_UYVY:
+ case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
+ *mimetype = MEDIA_FORMAT_UYVY;
+ break;
+ case MM_PIXEL_FORMAT_422P:
+ *mimetype = MEDIA_FORMAT_422P;
+ break;
+ case MM_PIXEL_FORMAT_I420:
+ *mimetype = MEDIA_FORMAT_I420;
+ break;
+ case MM_PIXEL_FORMAT_YV12:
+ *mimetype = MEDIA_FORMAT_YV12;
+ break;
+ case MM_PIXEL_FORMAT_RGB565:
+ *mimetype = MEDIA_FORMAT_RGB565;
+ break;
+ case MM_PIXEL_FORMAT_RGB888:
+ *mimetype = MEDIA_FORMAT_RGB888;
+ break;
+ case MM_PIXEL_FORMAT_RGBA:
+ *mimetype = MEDIA_FORMAT_RGBA;
+ break;
+ case MM_PIXEL_FORMAT_ARGB:
+ *mimetype = MEDIA_FORMAT_ARGB;
+ break;
+ default:
+ LOGE("not suppported pixel_format(%d)", pixel_format);
+ return WEBRTC_ERROR_INVALID_PARAMETER;
+ }
+
+ return WEBRTC_ERROR_NONE;
+}
+
+static media_packet_rotate_method_e __convert_packet_orient_info(int orientation)
+{
+ media_packet_rotate_method_e rotate = MEDIA_PACKET_ROTATE_IDENTITY;
+
+ switch (orientation) {
+ case 90:
+ rotate = MEDIA_PACKET_ROTATE_90;
+ break;
+ case 180:
+ rotate = MEDIA_PACKET_ROTATE_180;
+ break;
+ case 270:
+ rotate = MEDIA_PACKET_ROTATE_270;
+ break;
+ default:
+ rotate = MEDIA_PACKET_ROTATE_IDENTITY;
+ break;
+ }
+
+ return rotate;
+}
+
+static video_decoded_data_info_s *__get_decoded_data_info_from_pad(GstPad *pad)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+ unsigned int fourcc = 0;
+ const gchar *string_format;
+ video_decoded_data_info_s *info;
+ gint width, height;
+ MMPixelFormatType format;
+ GstVideoInfo vinfo;
+
+ caps = gst_pad_get_current_caps(pad);
+ RET_VAL_IF(caps == NULL, NULL, "caps is NULL");
+
+ structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(structure, "width", &width);
+ gst_structure_get_int(structure, "height", &height);
+ string_format = gst_structure_get_string(structure, "format");
+ if (string_format)
+ fourcc = __convert_fourcc_string_to_value(string_format);
+ format = __get_pixel_format(fourcc);
+ gst_video_info_from_caps(&vinfo, caps);
+ gst_caps_unref(caps);
+
+ RET_VAL_IF(width == 0, NULL, "width is 0");
+ RET_VAL_IF(height == 0, NULL, "height is 0");
+ RET_VAL_IF(format == MM_PIXEL_FORMAT_INVALID, NULL, "pixel format is invalid");
+
+ info = g_new0(video_decoded_data_info_s, 1);
+
+ info->width = width;
+ info->height = height;
+ info->format = format;
+ info->plane_num = GST_VIDEO_INFO_N_PLANES(&vinfo);
+
+ return info;
+}
+
+static bool __swcodec_set_stride_elevation(video_decoded_data_info_s *info)
+{
+ RET_VAL_IF(info == NULL, false, "info is NULL");
+
+ if (info->format == MM_PIXEL_FORMAT_I420) {
+ int ret = TBM_SURFACE_ERROR_NONE;
+ tbm_surface_h ts;
+ tbm_surface_info_s ts_info;
+ int i;
+
+ ts = tbm_surface_create(info->width, info->height, TBM_FORMAT_YUV420);
+ ret = tbm_surface_get_info(ts, &ts_info);
+ tbm_surface_destroy(ts);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ return false;
+
+ for (i = 0; i < ts_info.num_planes; i++) {
+ info->stride[i] = ts_info.planes[i].stride;
+ info->elevation[i] = ts_info.planes[i].size / ts_info.planes[i].stride;
+ }
+ info->bo_size = ts_info.size;
+
+ } else if (info->format == MM_PIXEL_FORMAT_RGBA) {
+ info->stride[0] = info->width * 4;
+ info->elevation[0] = info->height;
+ info->bo_size = info->stride[0] * info->height;
+
+ } else {
+ LOGE("not supported format(%d)", info->format);
+ return false;
+ }
+
+ return true;
+}
+
+static bool __swcodec_set_bo(webrtc_display_s *display, video_decoded_data_info_s *info, GstMemory *mem)
+{
+ tbm_bo_handle thandle;
+ gboolean is_mapped;
+ int src_stride[BUFFER_MAX_PLANE_NUM] = { 0, };
+ int src_offset[BUFFER_MAX_PLANE_NUM] = { 0, };
+ int dest_offset[BUFFER_MAX_PLANE_NUM] = { 0, };
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ unsigned char *src = NULL;
+ unsigned char *dest = NULL;
+ GstMapInfo mapinfo = GST_MAP_INFO_INIT;
+
+ RET_VAL_IF(display == NULL, false, "display is NULL");
+ RET_VAL_IF(display->tbm == NULL, false, "display->tbm is NULL");
+
+ is_mapped = gst_memory_map(mem, &mapinfo, GST_MAP_READWRITE);
+ RET_VAL_IF(is_mapped == FALSE, false, "is_mapped is FALSE");
+
+ if (mapinfo.data == NULL) {
+ LOG_ERROR("mapinfo.data is NULL");
+ goto ERROR;
+ }
+
+ if (display->tbm->bo_list == NULL)
+ _create_tbm_bo_list(display->tbm, info->bo_size, 10); /* FIXME: use ini file to get list length */
+
+ info->bo[0] = _get_unused_tbm_bo(display->tbm, 10); /* FIXME: use ini file to get timeout sec */
+ if (info->bo[0] == NULL) {
+ LOG_ERROR("failed to _get_unused_tbm_bo()");
+ goto ERROR;
+ }
+
+ thandle = tbm_bo_map(info->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+ if (thandle.ptr == NULL) {
+ LOG_ERROR("thandle pointer is NULL");
+ goto ERROR;
+ }
+
+ if (info->format == MM_PIXEL_FORMAT_I420) {
+ src_stride[0] = GST_ROUND_UP_4(info->width);
+ src_stride[1] = src_stride[2] = GST_ROUND_UP_4(info->width >> 1);
+ src_offset[1] = src_stride[0] * GST_ROUND_UP_2(info->height);
+ src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(info->height) >> 1));
+
+ dest_offset[0] = 0;
+ dest_offset[1] = info->stride[0] * info->elevation[0];
+ dest_offset[2] = dest_offset[1] + info->stride[1] * info->elevation[1];
+
+ for (i = 0; i < 3; i++) {
+ src = mapinfo.data + src_offset[i];
+ dest = thandle.ptr + dest_offset[i];
+
+ if (i > 0)
+ k = 1;
+
+ for (j = 0; j < info->height >> k; j++) {
+ memcpy(dest, src, info->width>>k);
+ src += src_stride[i];
+ dest += info->stride[i];
+ }
+ }
+
+ } else if (info->format == MM_PIXEL_FORMAT_RGBA) {
+ memcpy(thandle.ptr, mapinfo.data, info->bo_size);
+
+ } else {
+ LOG_ERROR("not support format %d", info->format);
+ goto ERROR;
+ }
+
+ tbm_bo_unmap(info->bo[0]);
+ gst_memory_unmap(mem, &mapinfo);
+
+ return true;
+
+ERROR:
+ if (info->bo[0])
+ tbm_bo_unmap(info->bo[0]);
+
+ if (is_mapped)
+ gst_memory_unmap(mem, &mapinfo);
+
+ return false;
+}
+
+static int __media_packet_finalize_cb(media_packet_h m_packet, int error_code, void *user_data)
+{
+ tbm_surface_h ts;
+ media_packet_finalize_data_s *finalize_data = (media_packet_finalize_data_s *)user_data;
+
+ RET_VAL_IF(m_packet == NULL, MEDIA_PACKET_FINALIZE, "m_packet is NULL");
+ RET_VAL_IF(finalize_data == NULL, MEDIA_PACKET_FINALIZE, "finalize_data is NULL");
+
+ if (media_packet_get_tbm_surface(m_packet, &ts) != MEDIA_PACKET_ERROR_NONE)
+ LOG_ERROR("failed to media_packet_get_tbm_surface()");
+
+ if (ts) {
+ LOG_DEBUG("tbm surface[%p] is destroyed", ts);
+ tbm_surface_destroy(ts);
+ }
+
+ if (finalize_data->info->bo[0])
+ _release_tbm_bo(finalize_data->tbm, finalize_data->info->bo[0]);
+
+ g_free(finalize_data->info);
+ g_free(finalize_data);
+
+ return MEDIA_PACKET_FINALIZE;
+}
+
+static media_packet_h __get_media_packet(webrtc_tbm_s *tbm, video_decoded_data_info_s *info, tbm_surface_h ts)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ int m_ret = MEDIA_FORMAT_ERROR_NONE;
+ media_format_h m_format;
+ media_format_mimetype_e mimetype = MEDIA_FORMAT_NV12;
+ media_packet_h m_packet = NULL;
+ media_packet_finalize_data_s *finalize_data = NULL;
+
+ RET_VAL_IF(tbm == NULL, NULL, "tbm is NULL");
+ RET_VAL_IF(info == NULL, NULL, "info is NULL");
+ RET_VAL_IF(ts == NULL, NULL, "ts is NULL");
+
+ ret = __get_media_packet_mimetype(info->format, &mimetype);
+ RET_VAL_IF(ret != WEBRTC_ERROR_NONE, NULL, "failed to __get_media_packet_mimetype()");
+
+ LOG_DEBUG("mimetype[0x%x, %s], resolution[%dx%d], orientation[%d], timestamp[%u]",
+ mimetype, __get_format_string_from_mime_type(mimetype), info->width, info->height, info->orientation, info->timestamp);
+
+ m_ret = media_format_create(&m_format);
+ RET_VAL_IF(m_ret != MEDIA_FORMAT_ERROR_NONE, NULL, "failed to media_format_create()");
+
+ m_ret = media_format_set_video_mime(m_format, mimetype);
+ if (m_ret != MEDIA_FORMAT_ERROR_NONE) {
+ LOG_ERROR("failed to media_format_set_video_mime(), m_ret[0x%x]", m_ret);
+ goto ERROR;
+ }
+
+ m_ret = media_format_set_video_width(m_format, info->width);
+ if (m_ret != MEDIA_FORMAT_ERROR_NONE) {
+ LOG_ERROR("failed to media_format_set_video_width(), m_ret[0x%x]", m_ret);
+ goto ERROR;
+ }
+
+ m_ret = media_format_set_video_height(m_format, info->height);
+ if (m_ret != MEDIA_FORMAT_ERROR_NONE) {
+ LOG_ERROR("failed to media_format_set_video_height(), m_ret[0x%x]", m_ret);
+ goto ERROR;
+ }
+
+ finalize_data = g_new0(media_packet_finalize_data_s, 1);
+ finalize_data->tbm = tbm;
+ finalize_data->info = info;
+
+ m_ret = media_packet_create_from_tbm_surface(m_format, ts, (media_packet_finalize_cb)__media_packet_finalize_cb, (void *)finalize_data, &m_packet);
+ if (m_ret != MEDIA_PACKET_ERROR_NONE) {
+ LOG_ERROR("failed to media_packet_create_from_tbm_surface(), m_ret[0x%x]", m_ret);
+ goto ERROR;
+ }
+
+ if (info->timestamp != 0) {
+ m_ret = media_packet_set_pts(m_packet, (uint64_t)info->timestamp * 1000000);
+ if (m_ret != MEDIA_PACKET_ERROR_NONE)
+ LOG_ERROR("failed to media_packet_set_pts(), m_ret[0x%x]", m_ret);
+ }
+
+ m_ret = media_packet_set_rotate_method(m_packet, __convert_packet_orient_info(info->orientation));
+ if (m_ret != MEDIA_PACKET_ERROR_NONE)
+ LOG_ERROR("failed to media_packet_set_rotate_method(), m_ret[0x%x]", m_ret);
+
+ media_format_unref(m_format);
+
+ LOG_DEBUG("media packet[%p]", m_packet);
+
+ return m_packet;
+
+ERROR:
+ if (m_format)
+ media_format_unref(m_format);
+
+ if (m_packet)
+ media_packet_destroy(m_packet);
+
+ if (finalize_data)
+ g_free(finalize_data);
+
+ return NULL;
+}
+
+static tbm_surface_h __get_tbm_surface(video_decoded_data_info_s *info)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ tbm_surface_h ts;
+ tbm_surface_info_s ts_info;
+ uint32_t bo_format;
+ int i;
+ int bo_num = 1; /* always 1 for none zerocopy format */
+
+ RET_VAL_IF(info == NULL, NULL, "info is NULL");
+
+ memset(&ts_info, 0, sizeof(tbm_surface_info_s));
+
+ ret = __get_tbm_surface_format(info->format, &bo_format);
+ RET_VAL_IF(ret != WEBRTC_ERROR_NONE, NULL, "failed to __get_tbm_surface_format()");
+
+ ts_info.width = info->width;
+ ts_info.height = info->height;
+ ts_info.format = bo_format;
+ ts_info.bpp = tbm_surface_internal_get_bpp(bo_format);
+ ts_info.num_planes = tbm_surface_internal_get_num_planes(bo_format);
+ ts_info.size = 0;
+
+ for (i = 0; i < ts_info.num_planes; i++) {
+ ts_info.planes[i].stride = info->stride[i];
+ ts_info.planes[i].size = info->stride[i] * info->elevation[i];
+ if (i < bo_num)
+ ts_info.planes[i].offset = 0;
+ else
+ ts_info.planes[i].offset = ts_info.planes[i - 1].offset + ts_info.planes[i - 1].size;
+ ts_info.size += ts_info.planes[i].size;
+ if (info->format == MM_PIXEL_FORMAT_RGBA)
+ ts_info.size = info->stride[0] * info->height;
+ }
+
+ ts = tbm_surface_internal_create_with_bos(&ts_info, (tbm_bo *)info->bo, bo_num);
+ if (ts == NULL) {
+ LOG_ERROR("failed to tbm_surface_internal_create_with_bos()");
+ return NULL;
+ }
+
+ LOG_DEBUG("tbm surface[%p] is created", ts);
+
+ return ts;
+}
+
+static media_packet_h __get_media_packet_from_buffer(webrtc_display_s *display, GstBuffer *buffer, GstPad *pad)
+{
+ video_decoded_data_info_s *info;
+ GstMemory *mem;
+ tbm_surface_h ts;
+ media_packet_h m_packet;
+
+ RET_VAL_IF(display == NULL, NULL, "sink is NULL");
+ RET_VAL_IF(buffer == NULL, NULL, "buffer is NULL");
+ RET_VAL_IF(pad == NULL, NULL, "pad is NULL");
+
+ info = __get_decoded_data_info_from_pad(pad);
+ RET_VAL_IF(info == NULL, NULL, "info is NULL");
+
+ mem = gst_buffer_peek_memory(buffer, 0);
+ info->length_total = gst_memory_get_sizes(mem, NULL, NULL);
+ info->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> milli sec */
+
+ if (!__swcodec_set_stride_elevation(info) || !__swcodec_set_bo(display, info, mem))
+ goto ERROR;
+
+ ts = __get_tbm_surface(info);
+ if (ts == NULL) {
+ LOG_ERROR("failed to __get_tbm_surface()");
+ goto ERROR;
+ }
+
+ m_packet = __get_media_packet(display->tbm, info, ts);
+ if (m_packet == NULL) {
+ LOG_ERROR("failed to __get_media_packet()");
+ goto ERROR;
+ }
+
+ return m_packet;
+
+ERROR:
+ LOG_ERROR("release video data resource");
+
+ if (info->bo[0])
+ _release_tbm_bo(display->tbm, info->bo[0]);
+ g_free(info);
+
+ return NULL;
+}
+
+/* handoff signal handler */
+void _video_stream_decoded_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
+{
+ webrtc_display_s *display = (webrtc_display_s*)data;
+ media_packet_h packet;
+
+ RET_IF(display == NULL, "sink is NULL");
+
+ LOG_DEBUG("object[%p] buffer[%p] pad[%p] display[%p]", object, buffer, pad, display);
+
+ packet = __get_media_packet_from_buffer(display, buffer, pad);
+ if (packet == NULL) {
+ LOG_ERROR("could not get a media packet");
+ return;
+ }
+
+ mm_display_interface_evas_render(display->mm_display, packet);
+}
+
+static gboolean __set_evas_display_idle_cb(gpointer user_data)
+{
+ int ret = MM_ERROR_NONE;
+ int surface_id;
+ webrtc_display_s *display = (webrtc_display_s*)user_data;
+
+ RET_VAL_IF(display == NULL, G_SOURCE_REMOVE, "display is NULL");
+
+ g_mutex_lock(&display->mutex);
+
+ ret = mm_display_interface_set_display(display->mm_display, MM_DISPLAY_TYPE_EVAS, display->object, &surface_id);
+ if (ret != MM_ERROR_NONE) {
+ LOG_ERROR("failed to mm_display_interface_set_display(), ret[0x%x]", ret);
+ g_mutex_unlock(&display->mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ LOG_DEBUG("surface id[%d]", surface_id);
+
+ /* FIXE: get mode and rotation value from handle */
+ ret = mm_display_interface_evas_set_mode(display->mm_display, 0); /* 0: letter box, 1: origin size, 2: full screen */
+ RET_VAL_WITH_UNLOCK_IF(ret != MM_ERROR_NONE, G_SOURCE_REMOVE, &display->mutex, "failed to mm_display_interface_evas_set_mode()");
+
+ ret = mm_display_interface_evas_set_rotation(display->mm_display, 0); /* 0: not rotate, 1: 90 degree, 2, 180 degree, 3, 270 degree */
+ RET_VAL_WITH_UNLOCK_IF(ret != MM_ERROR_NONE, G_SOURCE_REMOVE, &display->mutex, "failed to mm_display_interface_evas_set_rotation()");
+
+ ret = mm_display_interface_evas_set_visible(display->mm_display, true);
+ RET_VAL_WITH_UNLOCK_IF(ret != MM_ERROR_NONE, G_SOURCE_REMOVE, &display->mutex, "failed to mm_display_interface_evas_set_visible()");
+
+ g_mutex_unlock(&display->mutex);
+
+ return G_SOURCE_REMOVE;
+}
+
+int _apply_display(webrtc_display_s *display)
{
- RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
RET_VAL_IF(display == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "sink is NULL");
switch (display->type) {
break;
case WEBRTC_DISPLAY_TYPE_EVAS:
- /* TODO: Implemenation */
LOG_DEBUG("it's EVAS type");
+
+ if (display->tbm == NULL)
+ display->tbm = _alloc_tbm();
+
+ g_idle_add(__set_evas_display_idle_cb, display);
break;
default:
return WEBRTC_ERROR_NONE;
}
-void _init_display(webrtc_s *webrtc)
+webrtc_display_s *_alloc_display(void)
{
- RET_IF(webrtc == NULL, "webrtc is NULL");
+ webrtc_display_s *display = g_new0(webrtc_display_s, 1);
- if (mm_display_interface_init(&webrtc->mm_display) != MM_ERROR_NONE)
+ g_mutex_init(&display->mutex);
+
+ if (mm_display_interface_init(&display->mm_display) != MM_ERROR_NONE)
LOG_WARNING("failed to mm_display_interface_init()");
+ else
+ LOG_DEBUG("init mm_display[%p]", display->mm_display);
+
+ LOG_DEBUG("alloc display[%p]", display);
+
+ return display;
}
-void _deinit_display(webrtc_s *webrtc)
+void _release_display(webrtc_display_s *display)
{
- RET_IF(webrtc == NULL, "webrtc is NULL");
+ RET_IF(display == NULL, "webrtc is NULL");
- if (webrtc->mm_display) {
- mm_display_interface_deinit(webrtc->mm_display);
- webrtc->mm_display = NULL;
+ g_mutex_lock(&display->mutex);
+
+ if (display->mm_display) {
+ LOG_DEBUG("deinit display->mm_display[%p]", display->mm_display);
+ mm_display_interface_deinit(display->mm_display);
+ display->mm_display = NULL;
+ }
+
+ if (display->tbm) {
+ _release_tbm(display->tbm);
+ display->tbm = NULL;
}
+
+ g_mutex_unlock(&display->mutex);
+ g_mutex_clear(&display->mutex);
+
+ LOG_DEBUG("free display[%p]", display);
+
+ g_free(display);
}
\ No newline at end of file