#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
+#include <gst/allocators/gsttizenmemory.h>
#include "gsttizenipcsink.h"
#define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0"
-#define DEFAULT_SHM_PATH "/tizenipcshm"
+#define DEFAULT_SHM_PATH "/tmp/tizenipcshm"
#define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP)
#define DEFAULT_BACKLOG 5
#define CLIENT_RESPONSE_TIMEOUT_NORMAL (G_TIME_SPAN_SECOND)
};
-
+static gboolean __init_socket(GstTizenipcSink *self);
+static gboolean __init_shared_memory(GstTizenipcSink *self, guint shm_size);
static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size);
static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *tbm_key);
static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key);
-
-static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
+static gboolean __init_socket(GstTizenipcSink *self)
{
int i = 0;
int flags = 0;
struct sockaddr_un addr_un;
struct sockaddr *address = NULL;
socklen_t address_len = 0;
- gchar shm_path[32] = {'\0',};
- if (self == NULL) {
+ if (!self) {
GST_ERROR("NULL handle");
return FALSE;
}
- GST_INFO_OBJECT(self, "start - shared memory size %u", shm_size);
-
/* open socket */
self->socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (self->socket_fd < 0) {
flags = fcntl(self->socket_fd, F_GETFL, NULL);
if (flags < 0) {
GST_ERROR_OBJECT(self, "failed to fcntl F_GETFL");
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
/* set non-block mode */
if (fcntl (self->socket_fd, F_SETFL, flags|O_NONBLOCK) < 0) {
GST_ERROR_OBJECT(self, "failed to fcntl F_SETFL");
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
memset(&addr_un, 0x0, sizeof(addr_un));
while (bind(self->socket_fd, address, address_len) < 0) {
if (errno != EADDRINUSE) {
GST_ERROR_OBJECT(self, "failed to bind. errno %d", errno);
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
if (i > 256) {
GST_ERROR_OBJECT(self, "no more free socket name");
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s.%d", self->socket_path, i);
self->socket_path_result = g_strdup(addr_un.sun_path);
if (self->socket_path_result == NULL) {
GST_ERROR_OBJECT(self, "failed to copy string %s", addr_un.sun_path);
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
if (chmod(self->socket_path_result, self->permissions) < 0) {
GST_ERROR_OBJECT(self, "failed to chmod %s - %d", addr_un.sun_path, self->permissions);
- goto _FAILED;
+ goto _SOCKET_FAILED;
}
if (listen(self->socket_fd, DEFAULT_BACKLOG) < 0) {
GST_ERROR_OBJECT(self, "failed to listen");
- goto _FAILED;
+ goto _SOCKET_FAILED;
+ }
+
+ GST_INFO_OBJECT(self, "socket fd [%d]", self->socket_fd);
+
+ return TRUE;
+
+_SOCKET_FAILED:
+ if (self->socket_fd > INIT_FD) {
+ shutdown(self->socket_fd, SHUT_RDWR);
+ close(self->socket_fd);
+ self->socket_fd = INIT_FD;
+ }
+
+ return FALSE;
+}
+
+
+static gboolean __init_shared_memory(GstTizenipcSink *self, guint shm_size)
+{
+ int i = 0;
+ gchar shm_path[32] = {'\0',};
+
+ if (shm_size == 0) {
+ GST_INFO_OBJECT(self, "shm size is 0");
+ return TRUE;
}
- /* create shared memory */
- i = 0;
do {
snprintf(shm_path, 32, "%s.%d", DEFAULT_SHM_PATH, i++);
self->shm_fd = shm_open(shm_path, O_RDWR|O_CREAT|O_EXCL, self->permissions);
if (self->shm_fd < 0) {
GST_ERROR_OBJECT(self, "failed to open shared memory [%s], errno [%d]", shm_path, errno);
- goto _FAILED;
+ goto _SHARED_MEMORY_FAILED;
}
if (self->shm_path) {
self->shm_path = g_strdup(shm_path);
if (self->shm_path == NULL) {
GST_ERROR_OBJECT(self, "failed to copy shared memory path");
- goto _FAILED;
+ goto _SHARED_MEMORY_FAILED;
}
if (ftruncate(self->shm_fd, shm_size) < 0) {
GST_ERROR_OBJECT(self, "failed to resize shm to %d", shm_size);
- goto _FAILED;
+ goto _SHARED_MEMORY_FAILED;
}
self->shm_mapped_area = (gchar *)mmap(NULL,
- shm_size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- self->shm_fd,
- 0);
+ shm_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ self->shm_fd,
+ 0);
if (self->shm_mapped_area == MAP_FAILED) {
GST_ERROR_OBJECT(self, "failed to mmap for shared memory");
- goto _FAILED;
+ goto _SHARED_MEMORY_FAILED;
}
self->shm_mapped_size = shm_size;
+ GST_INFO_OBJECT(self, "shared memory size [%d]", self->shm_mapped_size);
+
+ return TRUE;
+
+_SHARED_MEMORY_FAILED:
+ if (self->shm_fd > INIT_FD) {
+ close(self->shm_fd);
+ self->shm_fd = INIT_FD;
+ }
+
+ return FALSE;
+}
+
+
+static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
+{
+ if (self == NULL) {
+ GST_ERROR("NULL handle");
+ return FALSE;
+ }
+
+ GST_INFO_OBJECT(self, "start - socket path [%s], shared memory size [%u]",
+ self->socket_path, shm_size);
+
+ /* socket */
+ if (!__init_socket(self))
+ return FALSE;
+
+ /* shared memory */
+ if (!__init_shared_memory(self, shm_size))
+ goto _FAILED;
+
/* create gst poll and thread for poll */
self->poll = gst_poll_new(TRUE);
if (self->poll == NULL) {
GST_ERROR_OBJECT(self, "failed to create gst poll");
goto _FAILED;
}
+
gst_poll_fd_init(&self->pollfd);
self->pollfd.fd = self->socket_fd;
gst_poll_add_fd(self->poll, &self->pollfd);
self->poll = NULL;
}
- if (self->shm_fd > -1) {
+ if (self->shm_fd > INIT_FD) {
close(self->shm_fd);
- self->shm_fd = -1;
+ self->shm_fd = INIT_FD;
}
- if (self->socket_fd > -1) {
+ if (self->socket_fd > INIT_FD) {
close(self->socket_fd);
- self->socket_fd = -1;
+ self->socket_fd = INIT_FD;
}
return FALSE;
{
int i = 0;
int j = 0;
- GstTizenipcBuffer *sended_buffer = NULL;
+ GstTizenipcBuffer *buffer_list = NULL;
if (self == NULL || buf == NULL || tbm_key == NULL) {
GST_ERROR("NULL parameter %p, %p, %p", self, buf, tbm_key);
g_mutex_lock(&self->buffer_lock);
- sended_buffer = self->sended_buffer;
+ buffer_list = self->buffer_list;
- for (i = 0 ; i < GST_TIZENIPC_BUFFER_MAX ; i++) {
+ for (i = 0 ; i < IPC_BUFFER_MAX ; i++) {
/* find empty space */
- if (sended_buffer[i].gst_buf == NULL) {
- self->sended_buffer_count++;
+ if (buffer_list[i].gst_buf == NULL) {
+ self->buffer_list_count++;
GST_DEBUG_OBJECT(self, "insert buffer(key[0] %d) to index %d, count %d",
- tbm_key[0], i, self->sended_buffer_count);
+ tbm_key[0], i, self->buffer_list_count);
/* ref gst buffer and set tbm key */
gst_buffer_ref(buf);
- sended_buffer[i].gst_buf = buf;
+ buffer_list[i].gst_buf = buf;
- for (j = 0 ; j < MM_VIDEO_BUFFER_PLANE_MAX ; j++) {
+ for (j = 0 ; j < TBM_SURF_PLANE_MAX ; j++) {
if (tbm_key[j] > 0) {
- sended_buffer[i].tbm_key[j] = tbm_key[j];
+ buffer_list[i].tbm_key[j] = tbm_key[j];
} else {
break;
}
static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key)
{
int i = 0;
- GstTizenipcBuffer *sended_buffer = NULL;
+ GstTizenipcBuffer *buffer_list = NULL;
if (self == NULL || tbm_key == NULL) {
GST_ERROR("NULL parameter %p, %p", self, tbm_key);
g_mutex_lock(&self->buffer_lock);
- sended_buffer = self->sended_buffer;
+ buffer_list = self->buffer_list;
- for (i = 0 ; i < GST_TIZENIPC_BUFFER_MAX ; i++) {
+ for (i = 0 ; i < IPC_BUFFER_MAX ; i++) {
/* find matched buffer info */
- if (sended_buffer[i].tbm_key[0] == tbm_key[0] &&
- sended_buffer[i].tbm_key[1] == tbm_key[1] &&
- sended_buffer[i].tbm_key[2] == tbm_key[2] &&
- sended_buffer[i].tbm_key[3] == tbm_key[3]) {
+ if (buffer_list[i].tbm_key[0] == tbm_key[0] &&
+ buffer_list[i].tbm_key[1] == tbm_key[1] &&
+ buffer_list[i].tbm_key[2] == tbm_key[2] &&
+ buffer_list[i].tbm_key[3] == tbm_key[3]) {
/* remove buffer info and unref gst buffer */
- self->sended_buffer_count--;
+ self->buffer_list_count--;
GST_DEBUG_OBJECT(self, "gst buffer %p for key[0] %d, count %d",
- sended_buffer[i].gst_buf, tbm_key[0], self->sended_buffer_count);
+ buffer_list[i].gst_buf, tbm_key[0], self->buffer_list_count);
- if (sended_buffer[i].gst_buf) {
- gst_buffer_unref(sended_buffer[i].gst_buf);
- sended_buffer[i].gst_buf = NULL;
+ if (buffer_list[i].gst_buf) {
+ gst_buffer_unref(buffer_list[i].gst_buf);
+ buffer_list[i].gst_buf = NULL;
} else {
GST_WARNING_OBJECT(self, "no gst buffer for key[0] %d", tbm_key[0]);
}
- sended_buffer[i].tbm_key[0] = 0;
- sended_buffer[i].tbm_key[1] = 0;
- sended_buffer[i].tbm_key[2] = 0;
- sended_buffer[i].tbm_key[3] = 0;
+ buffer_list[i].tbm_key[0] = 0;
+ buffer_list[i].tbm_key[1] = 0;
+ buffer_list[i].tbm_key[2] = 0;
+ buffer_list[i].tbm_key[3] = 0;
g_cond_signal(&self->buffer_cond);
g_mutex_unlock(&self->buffer_lock);
g_mutex_init(&self->ipc_lock);
g_cond_init(&self->ipc_cond);
- self->socket_fd = -1;
- self->client_fd = -1;
- self->shm_fd = -1;
+ self->socket_fd = INIT_FD;
+ self->client_fd = INIT_FD;
+ self->shm_fd = INIT_FD;
self->shm_mapped_area = MAP_FAILED;
self->is_connected = FALSE;
self->permissions = DEFAULT_PERMISSIONS;
+
self->socket_path = g_strdup(DEFAULT_SOCKET_PATH);
- if (self->socket_path == NULL) {
+ if (self->socket_path == NULL)
GST_ERROR_OBJECT(self, "failed to dup socket path [%s]", DEFAULT_SOCKET_PATH);
- }
- self->sended_buffer = g_new0(GstTizenipcBuffer, GST_TIZENIPC_BUFFER_MAX);
- if (self->sended_buffer == NULL) {
- GST_ERROR_OBJECT(self, "failed to alloc sended_buffer");
- }
+
+ self->buffer_list = g_new0(GstTizenipcBuffer, IPC_BUFFER_MAX);
+ if (self->buffer_list == NULL)
+ GST_ERROR_OBJECT(self, "failed to alloc buffer_list");
return;
}
g_mutex_clear(&self->buffer_lock);
g_cond_clear(&self->buffer_cond);
- if (self->socket_path) {
- g_free(self->socket_path);
- self->socket_path = NULL;
- }
+ g_free(self->socket_path);
+ self->socket_path = NULL;
- if (self->socket_path_result) {
- g_free(self->socket_path_result);
- self->socket_path_result = NULL;
- }
+ g_free(self->socket_path_result);
+ self->socket_path_result = NULL;
- if (self->shm_path) {
- g_free(self->shm_path);
- self->shm_path = NULL;
+ g_free(self->shm_path);
+ self->shm_path = NULL;
+
+ if (self->caps_string) {
+ GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+ g_free(self->caps_string);
+ self->caps_string = NULL;
}
G_OBJECT_CLASS(parent_class)->finalize(object);
{
gchar *temp_string = g_value_dup_string(value);
if (temp_string) {
- if (self->socket_path) {
- g_free(self->socket_path);
- self->socket_path = NULL;
- }
+ g_free(self->socket_path);
self->socket_path = temp_string;
} else {
GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value));
/* check socket path and buffer list */
if (self->socket_path == NULL ||
- self->sended_buffer == NULL) {
- GST_ERROR_OBJECT(self, "socket path[%p] or sended buffer [%p] is NULL",
- self->socket_path, self->sended_buffer);
+ self->buffer_list == NULL) {
+ GST_ERROR_OBJECT(self, "socket path[%p] or buffer_list [%p] is NULL",
+ self->socket_path, self->buffer_list);
return FALSE;
}
return FALSE;
}
- GST_INFO_OBJECT(self, "start");
+ /* wait for buffer */
+ g_mutex_lock(&self->buffer_lock);
+
+ GST_INFO_OBJECT(self, "start - not returned buffer %d", self->buffer_list_count);
+
+ while (self->buffer_list_count > 0) {
+ wait_end_time = g_get_monotonic_time () + BUFFER_WAIT_TIMEOUT;
+ if (!g_cond_wait_until(&self->buffer_cond, &self->buffer_lock, wait_end_time)) {
+ GST_WARNING_OBJECT(self, "wait timeout - current count %d",
+ self->buffer_list_count);
+ break;
+ } else {
+ GST_WARNING_OBJECT(self, "signal received - current count %d",
+ self->buffer_list_count);
+ }
+ }
+
+ g_mutex_unlock(&self->buffer_lock);
/* stop poll thread */
self->poll_thread_run = FALSE;
GST_WARNING_OBJECT(self, "no poll thread");
}
- /* wait for sended buffer */
- g_mutex_lock(&self->buffer_lock);
-
- while (self->sended_buffer_count > 0) {
- wait_end_time = g_get_monotonic_time () + BUFFER_WAIT_TIMEOUT;
- if (!g_cond_wait_until(&self->buffer_cond, &self->buffer_lock, wait_end_time)) {
- GST_WARNING_OBJECT(self, "wait timeout - current count %d",
- self->sended_buffer_count);
- break;
- } else {
- GST_WARNING_OBJECT(self, "signal received - current count %d",
- self->sended_buffer_count);
- }
- }
-
- g_mutex_unlock(&self->buffer_lock);
-
/* close client */
if (self->client_fd >= 0) {
GST_INFO_OBJECT(self, "close client fd %d", self->client_fd);
shutdown(self->client_fd, SHUT_RDWR);
close(self->client_fd);
g_signal_emit(self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, self->client_fd);
- self->client_fd = -1;
+ self->client_fd = INIT_FD;
} else {
GST_WARNING_OBJECT(self, "no client");
}
}
close(self->shm_fd);
- self->shm_fd = -1;
+ self->shm_fd = INIT_FD;
if (self->shm_path) {
shm_unlink(self->shm_path);
shutdown(self->socket_fd, SHUT_RDWR);
close(self->socket_fd);
- self->socket_fd = -1;
+ self->socket_fd = INIT_FD;
} else {
GST_WARNING_OBJECT(self, "socket is not opened");
}
{
GstTizenipcSink *self = NULL;
GstTizenipcMessage msg = {0, };
- MMVideoBuffer *mm_buf = NULL;
GstMemory *memory = NULL;
GstMapInfo map_info = GST_MAP_INFO_INIT;
gint64 wait_end_time = 0;
- int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX] = {0, };
int i = 0;
if (bsink == NULL) {
goto _SKIP_BUFFER;
}
+ memory = gst_buffer_peek_memory(buf, 0);
+ if (!memory) {
+ GST_WARNING_OBJECT(self, "failed to peek memory 0 for %p", buf);
+ goto _SKIP_BUFFER;
+ }
+
if (self->is_normal_format) {
- memory = gst_buffer_peek_memory(buf, 0);
- if (memory == NULL) {
- GST_WARNING_OBJECT(self, "failed to peek memory 0 for %p", buf);
- goto _SKIP_BUFFER;
+ if (self->shm_mapped_area == MAP_FAILED) {
+ GST_ERROR_OBJECT(self, "no mapped area");
+ return GST_FLOW_ERROR;
}
if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) {
msg.id = TIZEN_IPC_BUFFER_NEW;
msg.size = map_info.size;
} else {
- /* get mm_buf from gst buffer */
- if (gst_buffer_n_memory(buf) <= 1) {
- GST_WARNING_OBJECT(self, "invalid memory number %d", gst_buffer_n_memory(buf));
- goto _SKIP_BUFFER;
- }
+ int num_bos = 0;
+ tbm_bo bo = NULL;
- memory = gst_buffer_peek_memory(buf, 1);
- if (memory == NULL) {
- GST_WARNING_OBJECT(self, "failed to peek memory 1 for %p", buf);
- goto _SKIP_BUFFER;
- }
+ /* set command type */
+ msg.id = TIZEN_IPC_BUFFER_NEW;
- if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) {
- GST_WARNING_OBJECT(self, "failed to map memory %p", memory);
- goto _SKIP_BUFFER;
- }
+ /* get number of bo */
+ num_bos = gst_tizen_memory_get_num_bos(memory);
- mm_buf = (MMVideoBuffer *)map_info.data;
+ GST_LOG_OBJECT(self, "Tizen memory[%p] : number of bo %d", memory, num_bos);
- gst_memory_unmap(memory, &map_info);
+ /* get bo and export to deliver to client process */
+ for (i = 0 ; i < num_bos ; i++) {
+ bo = gst_tizen_memory_get_bos(memory, i);
+ if (!bo) {
+ GST_ERROR_OBJECT(self, "failed to get bo for index %d", i);
+ continue;
+ }
- if (mm_buf == NULL) {
- GST_WARNING_OBJECT(self, "NULL mm_buf");
- goto _SKIP_BUFFER;
- }
+ msg.tbm_key[i] = tbm_bo_export(bo);
- GST_LOG_OBJECT(self, "MMVideoBuffer info - %p, num handle %d",
- mm_buf, mm_buf->handle_num);
-
- /* export bo to pass buffer to client process */
- for (i = 0 ; i < mm_buf->handle_num ; i++) {
- if (mm_buf->handle.bo[i]) {
- tbm_key[i] = tbm_bo_export(mm_buf->handle.bo[i]);
- GST_LOG_OBJECT(self, "export tbm key[index:%d] %d", i, tbm_key[i]);
- if (tbm_key[i] <= 0) {
- GST_ERROR_OBJECT(self, "failed to export bo[%d] %p", i, mm_buf->handle.bo[i]);
- goto _SKIP_BUFFER;
- }
- } else {
- break;
+ GST_LOG_OBJECT(self, "export tbm key[index:%d] %d", i, msg.tbm_key[i]);
+
+ if (msg.tbm_key[i] <= 0) {
+ GST_ERROR_OBJECT(self, "failed to export bo[%d] %p", i, bo);
+ goto _SKIP_BUFFER;
}
}
/* keep and send buffer */
- if (_add_buffer_to_list(self, buf, tbm_key) == FALSE) {
- GST_ERROR_OBJECT(self, "failed to add to list for buffer %p and key[0] %d", buf, tbm_key[0]);
+ if (_add_buffer_to_list(self, buf, msg.tbm_key) == FALSE) {
+ GST_ERROR_OBJECT(self, "failed to add to list for buffer %p and key[0] %d", buf, msg.tbm_key[0]);
goto _SKIP_BUFFER;
}
-
- /* set command type and size */
- msg.id = TIZEN_IPC_BUFFER_NEW;
- msg.size = sizeof(MMVideoBuffer) + sizeof(tbm_key);
-
- /* copy zero copy info to shared memory */
- memcpy(self->shm_mapped_area, mm_buf, sizeof(MMVideoBuffer));
- memcpy(self->shm_mapped_area + sizeof(MMVideoBuffer), tbm_key, sizeof(tbm_key));
}
/* send data */
_SKIP_BUFFER_AFTER_ADD_TO_LIST:
if (!self->is_normal_format)
- _remove_buffer_from_list(self, tbm_key);
+ _remove_buffer_from_list(self, msg.tbm_key);
_SKIP_BUFFER:
g_mutex_unlock(&self->ipc_lock);
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_EOS:
- /* wait for sended buffer */
+ /* wait for buffer */
break;
default:
break;
static gboolean gst_tizenipc_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
{
GstTizenipcSink *self = NULL;
- GstStructure *structure = NULL;
if (bsink == NULL) {
GST_ERROR("NULL object");
GST_INFO_OBJECT(self, "start - caps [%"GST_PTR_FORMAT"]", caps);
- self->is_normal_format = TRUE;
-
- structure = gst_caps_get_structure(caps, 0);
- if (structure == NULL) {
- GST_ERROR_OBJECT(self, "failed to get structure from caps [%"GST_PTR_FORMAT"]", caps);
+ /* get GstVideoInfo */
+ gst_video_info_init(&self->video_info);
+ if (!gst_video_info_from_caps(&self->video_info, caps)) {
+ GST_ERROR_OBJECT(bsink, "failed to get video info from caps[%p,%"GST_PTR_FORMAT"]",
+ caps, caps);
return FALSE;
}
- if (!gst_structure_has_name(structure, "video/x-raw")) {
- GST_ERROR_OBJECT(self, "not supported caps [%"GST_PTR_FORMAT"]", caps);
+ self->is_normal_format = TRUE;
+ self->format = GST_VIDEO_INFO_FORMAT(&self->video_info);
+ self->width = GST_VIDEO_INFO_WIDTH(&self->video_info);
+ self->height = GST_VIDEO_INFO_HEIGHT(&self->video_info);
+
+ switch (self->format) {
+ case GST_VIDEO_FORMAT_SN12:
+ case GST_VIDEO_FORMAT_SN21:
+ case GST_VIDEO_FORMAT_S420:
+ case GST_VIDEO_FORMAT_ST12:
+ case GST_VIDEO_FORMAT_SR32:
+ case GST_VIDEO_FORMAT_STV0:
+ case GST_VIDEO_FORMAT_STV1:
+ self->shm_size = 0;
+ self->is_normal_format = FALSE;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
+ self->shm_size = (self->width * self->height * 3) >> 1;
+ break;
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ self->shm_size = (self->width * self->height) << 1;
+ break;
+ default:
+ GST_ERROR_OBJECT(self, "unsupported format [%d]", self->format);
return FALSE;
}
- self->format_string = gst_structure_get_string(structure, "format");
- if (self->format_string == NULL) {
- GST_ERROR_OBJECT(self, "failed to get format from caps [%"GST_PTR_FORMAT"]", caps);
- return FALSE;
- }
+ GST_INFO_OBJECT(self, "format %d, size %dx%d, shm size %d",
+ self->format, self->width, self->height, self->shm_size);
- if (!gst_structure_get_int(structure, "width", &self->width) ||
- !gst_structure_get_int(structure, "height", &self->height)) {
- GST_ERROR_OBJECT(self, "failed to get width, height from caps [%"GST_PTR_FORMAT"]", caps);
- return FALSE;
+ if (self->caps_string) {
+ GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+ g_free(self->caps_string);
+ self->caps_string = NULL;
}
- if (!strcmp(self->format_string, "SN12") || !strcmp(self->format_string, "SN21") ||
- !strcmp(self->format_string, "SYVY") || !strcmp(self->format_string, "SUYV") ||
- !strcmp(self->format_string, "S420")) {
- self->shm_size = sizeof(MMVideoBuffer) + (sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
- self->is_normal_format = FALSE;
- } else if (!strcmp(self->format_string, "NV12") || !strcmp(self->format_string, "NV21") ||
- !strcmp(self->format_string, "I420") || !strcmp(self->format_string, "YV12")) {
- self->shm_size = (self->width * self->height * 3) >> 1;
- } else if (!strcmp(self->format_string, "YUYV") || !strcmp(self->format_string, "YUY2") ||
- !strcmp(self->format_string, "UYVY")) {
- self->shm_size = (self->width * self->height) << 1;
- } else {
- GST_ERROR_OBJECT(self, "unsupported format [%s]", self->format_string);
- return FALSE;
- }
+ /* get caps string */
+ self->caps_string = gst_caps_to_string(caps);
- GST_INFO_OBJECT(self, "format %s, size %dx%d, shm size %d",
- self->format_string, self->width, self->height, self->shm_size);
+ GST_INFO_OBJECT(self, "caps [%s]", self->caps_string);
/* create socket and shared memory for sending buffer */
if (!_prepare_tizenipc_sink(self, self->shm_size)) {
GST_INFO_OBJECT(self, "client accpeted : fd %d", self->client_fd);
- /* send shard memory size */
- msg.id = TIZEN_IPC_SHM_SIZE;
- msg.size = self->shm_mapped_size;
- if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
- GST_ERROR_OBJECT(self, "failed to send shard memory size");
- close(self->client_fd);
- self->client_fd = -1;
- g_mutex_unlock(&self->ipc_lock);
- continue;
+ if (self->shm_mapped_size > 0) {
+ /* send shard memory size */
+ msg.id = TIZEN_IPC_SHM_SIZE;
+ msg.size = self->shm_mapped_size;
+ if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+ GST_ERROR_OBJECT(self, "failed to send shard memory size");
+ close(self->client_fd);
+ self->client_fd = INIT_FD;
+ g_mutex_unlock(&self->ipc_lock);
+ continue;
+ }
+
+ /* send shard memory path */
+ msg.id = TIZEN_IPC_SHM_PATH;
+ msg.size = strlen(self->shm_path) + 1;
+ if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+ GST_ERROR_OBJECT(self, "failed to send shard memory path 1");
+ close(self->client_fd);
+ self->client_fd = INIT_FD;
+ g_mutex_unlock(&self->ipc_lock);
+ continue;
+ }
+
+ if (send(self->client_fd, self->shm_path, msg.size, MSG_NOSIGNAL) != msg.size) {
+ GST_ERROR_OBJECT(self, "failed to send shard memory path 2");
+ close(self->client_fd);
+ self->client_fd = INIT_FD;
+ g_mutex_unlock(&self->ipc_lock);
+ continue;
+ }
+
+ GST_INFO_OBJECT(self, "send shm path done - %s", self->shm_path);
}
- /* send shard memory path */
- msg.id = TIZEN_IPC_SHM_PATH;
- msg.size = strlen(self->shm_path) + 1;
+ /* send buffer type */
+ msg.id = TIZEN_IPC_BUFFER_TYPE;
+ msg.type = self->is_normal_format ? BUFFER_TYPE_NORMAL : BUFFER_TYPE_ZERO_COPY;
if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
- GST_ERROR_OBJECT(self, "failed to send shard memory path 1");
+ GST_ERROR_OBJECT(self, "failed to send buffer type");
close(self->client_fd);
- self->client_fd = -1;
+ self->client_fd = INIT_FD;
g_mutex_unlock(&self->ipc_lock);
continue;
}
- if (send(self->client_fd, self->shm_path, strlen(self->shm_path) + 1, MSG_NOSIGNAL) != (strlen(self->shm_path) + 1)) {
- GST_ERROR_OBJECT(self, "failed to send shard memory path 2");
+ GST_INFO_OBJECT(self, "send buffer type done - %d", msg.type);
+
+ /* send caps string */
+ msg.id = TIZEN_IPC_BUFFER_CAPS;
+ msg.size = strlen(self->caps_string) + 1;
+ if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+ GST_ERROR_OBJECT(self, "failed to send caps string 1");
close(self->client_fd);
- self->client_fd = -1;
+ self->client_fd = INIT_FD;
g_mutex_unlock(&self->ipc_lock);
continue;
}
- GST_INFO_OBJECT(self, "send shm path done - %s", self->shm_path);
-
- /* send buffer type */
- msg.id = TIZEN_IPC_BUFFER_TYPE;
- msg.type = self->is_normal_format ? BUFFER_TYPE_NORMAL : BUFFER_TYPE_ZERO_COPY;
- if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
- GST_ERROR_OBJECT(self, "failed to send buffer type");
+ if (send(self->client_fd, self->caps_string, msg.size, MSG_NOSIGNAL) != msg.size) {
+ GST_ERROR_OBJECT(self, "failed to send caps string 2");
close(self->client_fd);
- self->client_fd = -1;
+ self->client_fd = INIT_FD;
g_mutex_unlock(&self->ipc_lock);
continue;
}
- GST_INFO_OBJECT(self, "send buffer type done - %d", msg.type);
+ GST_INFO_OBJECT(self, "send caps string done - %s", self->caps_string);
gst_poll_fd_init(&self->client_pollfd);
self->client_pollfd.fd = self->client_fd;
continue;
}
- if (self->client_fd > -1) {
+ if (self->client_fd > INIT_FD) {
if (gst_poll_fd_has_closed(self->poll, &self->client_pollfd)) {
GST_WARNING_OBJECT(self, "client is gone, closing");
goto close_client;
GST_INFO_OBJECT(self, "close client fd %d", self->client_fd);
gst_poll_remove_fd(self->poll, &self->client_pollfd);
+
+ shutdown(self->client_fd, SHUT_RDWR);
close(self->client_fd);
- self->client_fd = -1;
+ self->client_fd = INIT_FD;
g_mutex_unlock(&self->ipc_lock);
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
+#include <gst/allocators/gsttizenmemory.h>
#include "gsttizenipcsrc.h"
#define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0"
-#define DEFAULT_SHM_PATH "/tizenipcshm"
+#define DEFAULT_SHM_PATH "/tmp/tizenipcshm"
#define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP)
#define DEFAULT_BACKLOG 5
#define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000)
};
+static GstBuffer *_tizenipc_src_buffer_new(GstTizenipcSrc *self, GstTizenipcMessage *recv_msg);
+static void _tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *buffer);
+static gboolean _tizenipc_get_tbm_format(GstVideoFormat video_format, guint32 *tbm_format);
+
static void gst_tizenipc_src_finalize(GObject *object);
static void gst_tizenipc_src_set_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static gboolean gst_tizenipc_src_start(GstBaseSrc *bsrc);
static gboolean gst_tizenipc_src_stop(GstBaseSrc *bsrc);
-static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf);
static gboolean gst_tizenipc_src_unlock(GstBaseSrc *bsrc);
static gboolean gst_tizenipc_src_unlock_stop(GstBaseSrc *bsrc);
+static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf);
static GstStateChangeReturn gst_tizenipc_src_change_state(GstElement *element, GstStateChange transition);
-static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *buffer);
+static gboolean _tizenipc_get_tbm_format(GstVideoFormat video_format, guint32 *tbm_format)
+{
+ if (!tbm_format) {
+ GST_ERROR("NULL param");
+ return FALSE;
+ }
+
+ switch(video_format) {
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_S420:
+ *tbm_format = TBM_FORMAT_YUV420;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_SN12:
+ *tbm_format = TBM_FORMAT_NV12;
+ break;
+ case GST_VIDEO_FORMAT_NV21:
+ case GST_VIDEO_FORMAT_SN21:
+ *tbm_format = TBM_FORMAT_NV21;
+ break;
+ case GST_VIDEO_FORMAT_YUY2:
+ *tbm_format = TBM_FORMAT_YUYV;
+ break;
+ case GST_VIDEO_FORMAT_UYVY:
+ *tbm_format = TBM_FORMAT_UYVY;
+ break;
+ default:
+ GST_ERROR("unhandled format %d", video_format);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self)
{
struct sockaddr_un addr_un;
return FALSE;
}
- GST_INFO_OBJECT(self, "start");
+ GST_INFO_OBJECT(self, "start - socket path [%s]", self->socket_path);
/* socket connection */
self->socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
goto _PREPARE_FAILED;
}
- if (fcntl(self->socket_fd, F_SETFL, flags|FD_CLOEXEC) < 0) {
+ if (fcntl(self->socket_fd, F_SETFL, flags | FD_CLOEXEC) < 0) {
GST_ERROR_OBJECT(self, "failed to fcntl F_SETFL FD_CLOEXEC for socket fd %d", self->socket_fd);
goto _PREPARE_FAILED;
}
address_len = sizeof(addr_un);
if (connect(self->socket_fd, address, address_len) < 0) {
- GST_ERROR_OBJECT(self, "failed to connect for socket fd %d", self->socket_fd);
+ GST_ERROR_OBJECT(self, "failed to connect for socket fd %d, errno %d", self->socket_fd, errno);
goto _PREPARE_FAILED;
}
if (self->socket_fd >= 0) {
shutdown(self->socket_fd, SHUT_RDWR);
close(self->socket_fd);
- self->socket_fd = -1;
+ self->socket_fd = INIT_FD;
}
if (self->socket_path) {
shutdown(self->socket_fd, SHUT_RDWR);
close(self->socket_fd);
- self->socket_fd = -1;
+ self->socket_fd = INIT_FD;
}
- if (self->socket_path) {
- unlink(self->socket_path);
- }
-
- if (self->shm_mapped_area) {
+ if (self->shm_mapped_area != MAP_FAILED) {
munmap(self->shm_mapped_area, self->shm_mapped_size);
self->shm_mapped_area = MAP_FAILED;
}
if (self->shm_fd) {
close(self->shm_fd);
- self->shm_fd = -1;
+ self->shm_fd = INIT_FD;
}
GST_INFO_OBJECT(self, "done");
g_mutex_init(&self->buffer_lock);
g_cond_init(&self->buffer_cond);
- self->socket_fd = -1;
- self->shm_fd = -1;
+ self->socket_fd = INIT_FD;
+ self->shm_fd = INIT_FD;
self->shm_mapped_area = MAP_FAILED;
self->bufmgr = tbm_bufmgr_init(-1);
+
self->socket_path = g_strdup(DEFAULT_SOCKET_PATH);
- if (self->socket_path == NULL) {
+ if (self->socket_path == NULL)
GST_ERROR_OBJECT(self, "failed to dup socket path [%s]", DEFAULT_SOCKET_PATH);
- }
+
self->poll = gst_poll_new(TRUE);
- if (self->poll == NULL) {
+ if (self->poll == NULL)
GST_ERROR_OBJECT(self, "failed to get gst poll");
- } else {
+ else
gst_poll_fd_init(&self->pollfd);
- }
+
+ self->allocator = gst_tizen_allocator_new();
+ if (!self->allocator)
+ GST_ERROR_OBJECT(self, "tizen allocator new failed");
return;
}
g_mutex_clear(&self->buffer_lock);
g_cond_clear(&self->buffer_cond);
- if (self->socket_path) {
- g_free(self->socket_path);
- self->socket_path = NULL;
- }
+ g_free(self->socket_path);
+ self->socket_path = NULL;
- if (self->shm_path) {
- g_free(self->shm_path);
- self->shm_path = NULL;
- }
+ g_free(self->shm_path);
+ self->shm_path = NULL;
if (self->poll) {
gst_poll_free(self->poll);
self->bufmgr = NULL;
}
+ if (self->caps_string) {
+ GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+ g_free(self->caps_string);
+ self->caps_string = NULL;
+ }
+
GST_INFO_OBJECT(self, "done");
G_OBJECT_CLASS(parent_class)->finalize(object);
temp_string = g_value_dup_string(value);
if (temp_string) {
- if (self->socket_path) {
- g_free(self->socket_path);
- self->socket_path = NULL;
- }
+ g_free(self->socket_path);
self->socket_path = temp_string;
+ GST_INFO_OBJECT(object, "socket path [%s]", self->socket_path);
} else {
GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value));
}
}
-static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
+static void _tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
{
GstTizenipcSrc *self = NULL;
GstTizenipcMessage send_msg = {0,};
- MMVideoBuffer *mm_buf = NULL;
int i = 0;
int send_len = 0;
}
self = ipc_buf->self;
- mm_buf = ipc_buf->mm_buf;
-
if (self == NULL) {
GST_ERROR("NULL handle");
goto _BUFFER_FINALIZE_DONE;
}
/* send message to sink for current tbm key */
- if (self->socket_fd > -1) {
+ if (self->socket_fd > INIT_FD) {
send_msg.id = TIZEN_IPC_BUFFER_RELEASE;
- memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
+ memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * TBM_SURF_PLANE_MAX);
send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL);
if (send_len != sizeof(GstTizenipcMessage)) {
GST_ERROR_OBJECT(self, "send failed : BUFFER_RELEASE key[0] %d", send_msg.tbm_key[0]);
g_mutex_lock(&self->buffer_lock);
GST_DEBUG_OBJECT(self, "live buffer(tbm key[0] %d) count %d -> %d",
- ipc_buf->tbm_key[0], self->live_buffer_count, self->live_buffer_count-1);
+ ipc_buf->tbm_key[0], self->live_buffer_count, self->live_buffer_count - 1);
self->live_buffer_count--;
g_cond_signal(&self->buffer_cond);
self = NULL;
_BUFFER_FINALIZE_DONE:
- if (mm_buf) {
- for (i = 0 ; i < mm_buf->handle_num ; i++) {
- if (mm_buf->handle.bo[i]) {
- tbm_bo_unref(mm_buf->handle.bo[i]);
- mm_buf->handle.bo[i] = NULL;
- } else {
- break;
- }
- }
+ if (ipc_buf->t_surface) {
+ tbm_surface_destroy(ipc_buf->t_surface);
+ ipc_buf->t_surface = NULL;
+ }
- free(mm_buf);
- mm_buf = NULL;
+ for (i = 0 ; ipc_buf->bos[i] ; i++) {
+ if (ipc_buf->bos[i]) {
+ tbm_bo_unref(ipc_buf->bos[i]);
+ ipc_buf->bos[i] = NULL;
+ } else {
+ break;
+ }
}
free(ipc_buf);
}
+static GstBuffer *_tizenipc_src_buffer_new(GstTizenipcSrc *self, GstTizenipcMessage *recv_msg)
+{
+ int i = 0;
+ int num_bos = 0;
+ void *normal_buffer_data = NULL;
+
+ GstBuffer *buffer = NULL;
+ GstMemory *memory = NULL;
+
+ GstTizenipcSrcBuffer *ipc_buf = NULL;
+ GstTizenipcMessage send_msg = {0,};
+
+ if (!self || !recv_msg) {
+ GST_ERROR_OBJECT(self, "NULL param %p %p", self, recv_msg);
+ return NULL;
+ }
+
+ /* create empty buffer */
+ buffer = gst_buffer_new();
+ if (!buffer) {
+ GST_ERROR_OBJECT(self, "buffer failed");
+ return NULL;
+ }
+
+ /* get new buffer from sink */
+ if (self->is_normal_format) {
+ if (self->shm_mapped_area == MAP_FAILED) {
+ GST_ERROR_OBJECT(self, "no mapped area");
+ goto _BUFFER_NEW_FAILED;
+ }
+ /* non-zero-copy case */
+ normal_buffer_data = (void *)malloc(recv_msg->size);
+ if (!normal_buffer_data) {
+ GST_ERROR_OBJECT(self, "normal buffer[%d] failed", recv_msg->size);
+ goto _BUFFER_NEW_FAILED;
+ }
+
+ memcpy(normal_buffer_data, self->shm_mapped_area, recv_msg->size);
+
+ /* create GstMemory */
+ memory = gst_memory_new_wrapped(0,
+ normal_buffer_data, recv_msg->size, 0,
+ recv_msg->size, normal_buffer_data, free);
+ } else {
+ /* zero-copy case */
+ ipc_buf = g_new0(GstTizenipcSrcBuffer, 1);
+ if (!ipc_buf) {
+ GST_ERROR_OBJECT(self, "GstTizenipcSrcBuffer alloc failed");
+ goto _BUFFER_NEW_FAILED;
+ }
+
+ ipc_buf->gst_buf = buffer;
+ ipc_buf->self = gst_object_ref(self);
+
+ /* get tbm key from message */
+ memcpy(send_msg.tbm_key, recv_msg->tbm_key, sizeof(int) * TBM_SURF_PLANE_MAX);
+
+ /* import tbm bo */
+ for (i = 0 ; i < TBM_SURF_PLANE_MAX && send_msg.tbm_key[i] > 0 ; i++) {
+ ipc_buf->bos[i] = tbm_bo_import(self->bufmgr, send_msg.tbm_key[i]);
+ if (ipc_buf->bos[i] == NULL) {
+ GST_ERROR_OBJECT(self, "bo import failed for key [%d]", send_msg.tbm_key[i]);
+ goto _BUFFER_NEW_FAILED;
+ }
+
+ ipc_buf->tbm_key[i] = send_msg.tbm_key[i];
+
+ num_bos++;
+ }
+
+ /* create tbm surface */
+ ipc_buf->t_surface = tbm_surface_internal_create_with_bos(&self->ts_info, ipc_buf->bos, num_bos);
+ if (!ipc_buf->t_surface) {
+ GST_ERROR_OBJECT(self, "tbm surface create failed");
+ goto _BUFFER_NEW_FAILED;
+ }
+
+ /* create GstMemory */
+ memory = gst_tizen_allocator_alloc_surface(self->allocator,
+ &self->video_info,
+ ipc_buf->t_surface,
+ (gpointer)ipc_buf,
+ (GDestroyNotify)_tizenipc_src_buffer_finalize);
+
+ if (memory) {
+ g_mutex_lock(&self->buffer_lock);
+ self->live_buffer_count++;
+ GST_DEBUG_OBJECT(self, "gst buffer %p, live count %d", buffer, self->live_buffer_count);
+ g_mutex_unlock(&self->buffer_lock);
+ }
+ }
+
+ if (!memory) {
+ GST_ERROR_OBJECT(self, "gst memory create failed");
+ goto _BUFFER_NEW_FAILED;
+ }
+
+ /* append memory */
+ gst_buffer_append_memory(buffer, memory);
+
+ GST_LOG_OBJECT(self, "new buffer %p", buffer);
+
+ return buffer;
+
+_BUFFER_NEW_FAILED:
+ if (ipc_buf) {
+ for (i = 0 ; i < TBM_SURF_PLANE_MAX ; i++) {
+ if (ipc_buf->bos[i]) {
+ GST_WARNING_OBJECT(self, "release imported bo[%d] %p", i, ipc_buf->bos[i]);
+ tbm_bo_unref(ipc_buf->bos[i]);
+ ipc_buf->bos[i] = NULL;
+ }
+ }
+
+ gst_object_unref(ipc_buf->self);
+ ipc_buf->self = NULL;
+
+ g_free(ipc_buf);
+ ipc_buf = NULL;
+ }
+
+ if (normal_buffer_data) {
+ free(normal_buffer_data);
+ normal_buffer_data = NULL;
+ }
+
+ gst_buffer_unref(buffer);
+ buffer = NULL;
+
+ return NULL;
+}
+
+
static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf)
{
GstTizenipcSrc *self = NULL;
- GstTizenipcSrcBuffer *ipc_buf = NULL;
GstTizenipcMessage recv_msg = {0,};
GstTizenipcMessage send_msg = {0,};
- MMVideoBuffer *mm_buf = NULL;
GstBuffer *gst_buf = NULL;
- GstMemory *gst_memory = NULL;
- void *normal_buffer_data = NULL;
- int i = 0;
int recv_len = 0;
int send_len = 0;
/* handle message */
if (recv_msg.id == TIZEN_IPC_BUFFER_NEW) {
- /* get new buffer from sink */
- if (self->shm_mapped_area == MAP_FAILED) {
- GST_ERROR_OBJECT(self, "shared memory is not mapped");
- return GST_FLOW_ERROR;
- }
-
- if (!self->is_normal_format) {
- mm_buf = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer));
- if (mm_buf) {
- memcpy(mm_buf, self->shm_mapped_area, sizeof(MMVideoBuffer));
- memcpy(send_msg.tbm_key, self->shm_mapped_area + sizeof(MMVideoBuffer), sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
- for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
- if (send_msg.tbm_key[i] > 0) {
- tbm_bo_handle bo_handle = {0, };
-
- GST_LOG_OBJECT(self, "received tbm key[%d] %d", i, send_msg.tbm_key[i]);
-
- /* import bo from tbm key */
- mm_buf->handle.bo[i] = tbm_bo_import(self->bufmgr, send_msg.tbm_key[i]);
- if (mm_buf->handle.bo[i] == NULL) {
- GST_ERROR_OBJECT(self, "failed to import bo for tbm key %d", send_msg.tbm_key[i]);
- break;
- }
-
- /* get user address */
- bo_handle = tbm_bo_get_handle(mm_buf->handle.bo[i], TBM_DEVICE_CPU);
- if (bo_handle.ptr == NULL) {
- GST_ERROR_OBJECT(self, "failed to get user address for bo %p, key %d",
- mm_buf->handle.bo[i], send_msg.tbm_key[i]);
- break;
- }
- mm_buf->data[i] = bo_handle.ptr;
- } else {
- break;
- }
- }
- } else {
- GST_ERROR_OBJECT(self, "failed to alloc MMVideoBuffer");
- }
- } else {
- normal_buffer_data = (void *)malloc(recv_msg.size);
- if (normal_buffer_data) {
- memcpy(normal_buffer_data, self->shm_mapped_area, recv_msg.size);
- } else {
- GST_ERROR_OBJECT(self, "failed to alloc new buffer data - size %d", recv_msg.size);
- }
- }
+ gst_buf = _tizenipc_src_buffer_new(self, &recv_msg);
/* send received message */
send_msg.id = TIZEN_IPC_BUFFER_RECEIVED;
GST_OBJECT_LOCK(self);
send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL);
+ if (send_len != sizeof(GstTizenipcMessage))
+ GST_ERROR_OBJECT(self, "failed to send RECEIVED message");
GST_OBJECT_UNLOCK(self);
-
- if (send_len != sizeof(GstTizenipcMessage)) {
- GST_ERROR_OBJECT(self, "failed to send RECEIVED message");
- }
} else if (recv_msg.id == TIZEN_IPC_SHM_PATH) {
gchar shm_path[32] = {'\0',};
if (self->shm_mapped_area == MAP_FAILED) {
GST_ERROR_OBJECT(self, "failed to mmap shared memory for fd %d", self->shm_fd);
close(self->shm_fd);
- self->shm_fd = -1;
+ self->shm_fd = INIT_FD;
return GST_FLOW_ERROR;
}
self->is_normal_format = (recv_msg.type == BUFFER_TYPE_NORMAL) ? TRUE : FALSE;
GST_INFO_OBJECT(self, "is normal format? %d", self->is_normal_format);
goto again;
- } else {
- GST_WARNING_OBJECT(self, "unknown message : id %d", recv_msg.id);
- goto again;
- }
- }
+ } else if (recv_msg.id == TIZEN_IPC_BUFFER_CAPS) {
+ int tbm_ret = 0;
+ guint32 tbm_format = 0;
+ GstCaps *caps = NULL;
+ tbm_surface_h t_surface = NULL;
+
+ if (recv_msg.size <= 0) {
+ GST_ERROR_OBJECT(self, "invalid caps_string size %d", recv_msg.size);
+ return GST_FLOW_ERROR;
+ }
- if (mm_buf == NULL && normal_buffer_data == NULL) {
- GST_ERROR_OBJECT(self, "All buffers are NULL");
- return GST_FLOW_ERROR;
- }
+ g_free(self->caps_string);
+ self->caps_string = NULL;
- /* make gst buffer with mm_buf */
- gst_buf = gst_buffer_new();
- if (gst_buf == NULL) {
- GST_ERROR_OBJECT(self, "failed to create gst buffer");
- goto _CREATE_FAILED;
- }
+ self->caps_string = (gchar *)g_malloc((gsize)recv_msg.size);
+ if (!self->caps_string) {
+ GST_ERROR_OBJECT(self, "caps_string allocation failed");
+ return GST_FLOW_ERROR;
+ }
- /* default memory */
- if (mm_buf) {
- gst_memory = gst_memory_new_wrapped(0,
- mm_buf->data[0], mm_buf->size[0], 0,
- mm_buf->size[0], NULL, NULL);
- } else {
- gst_memory = gst_memory_new_wrapped(0,
- normal_buffer_data, recv_msg.size, 0,
- recv_msg.size, normal_buffer_data, free);
- }
- if (gst_memory == NULL) {
- GST_ERROR_OBJECT(self, "failed to create default gst memory");
- goto _CREATE_FAILED;
- }
-
- gst_buffer_append_memory(gst_buf, gst_memory);
- gst_memory = NULL;
-
- if (mm_buf) {
- /* mm_buf memory */
- gst_memory = gst_memory_new_wrapped(0,
- mm_buf, sizeof(MMVideoBuffer), 0,
- sizeof(MMVideoBuffer), mm_buf, NULL);
- if (gst_memory == NULL) {
- GST_ERROR_OBJECT(self, "failed to create gst memory for mm_buf");
- goto _CREATE_FAILED;
- }
+ /* get caps string */
+ recv_len = recv(self->socket_fd, self->caps_string, recv_msg.size, 0);
+ if (recv_len != recv_msg.size) {
+ GST_ERROR_OBJECT(self, "failed to receive message from sink %d : %d",
+ recv_len, recv_msg.size);
+ return GST_FLOW_ERROR;
+ }
- gst_buffer_append_memory(gst_buf, gst_memory);
- gst_memory = NULL;
+ GST_INFO_OBJECT(self, "caps string from sink [%s]", self->caps_string);
- /* ipc_buf memory */
- ipc_buf = (GstTizenipcSrcBuffer *)malloc(sizeof(GstTizenipcSrcBuffer));
- if (ipc_buf == NULL) {
- GST_ERROR_OBJECT(self, "failed to create GstTizenipcsrcBuffer");
- goto _CREATE_FAILED;
- }
+ /* get caps from string */
+ caps = gst_caps_from_string(self->caps_string);
+ if (!caps) {
+ GST_ERROR_OBJECT(self, "failed to get caps from string");
+ return GST_FLOW_ERROR;
+ }
- ipc_buf->self = gst_object_ref(self);
- ipc_buf->gst_buf = gst_buf;
- ipc_buf->mm_buf = mm_buf;
- memcpy(ipc_buf->tbm_key, send_msg.tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
- gst_memory = gst_memory_new_wrapped(0,
- ipc_buf, sizeof(GstTizenipcSrcBuffer), 0,
- sizeof(GstTizenipcSrcBuffer), ipc_buf,
- (GDestroyNotify)gst_tizenipc_src_buffer_finalize);
- if (gst_memory == NULL) {
- GST_ERROR_OBJECT(self, "failed to create gst memory for ipc_buf");
- goto _CREATE_FAILED;
- }
+ /* get video info from caps */
+ if (!gst_video_info_from_caps(&self->video_info, caps)) {
+ GST_ERROR_OBJECT(self, "get video info failed (caps[%s])", self->caps_string);
+ return GST_FLOW_ERROR;
+ }
- gst_buffer_append_memory(gst_buf, gst_memory);
- gst_memory = NULL;
+ /* get tbm format */
+ if (!_tizenipc_get_tbm_format(GST_VIDEO_INFO_FORMAT(&self->video_info), &tbm_format)) {
+ GST_ERROR_OBJECT(self, "get tbm format failed - video format %d", GST_VIDEO_INFO_FORMAT(&self->video_info));
+ return GST_FLOW_ERROR;
+ }
- g_mutex_lock(&self->buffer_lock);
- self->live_buffer_count++;
- GST_DEBUG_OBJECT(self, "gst buffer %p, live count %d", gst_buf, self->live_buffer_count);
- g_mutex_unlock(&self->buffer_lock);
- } else {
- GST_DEBUG_OBJECT(self, "normal buffer create done - size %d", recv_msg.size);
- }
+ /* get tbm surface info */
+ t_surface = tbm_surface_create(GST_VIDEO_INFO_WIDTH(&self->video_info),
+ GST_VIDEO_INFO_HEIGHT(&self->video_info), tbm_format);
+ if (!t_surface) {
+ GST_ERROR_OBJECT(self, "tbm surface failed");
+ return GST_FLOW_ERROR;
+ }
- *outbuf = gst_buf;
+ memset(&self->ts_info, 0x0, sizeof(tbm_surface_info_s));
- return GST_FLOW_OK;
+ tbm_ret = tbm_surface_get_info(t_surface, &self->ts_info);
-_CREATE_FAILED:
- if (ipc_buf) {
- free(ipc_buf);
- ipc_buf = NULL;
- }
+ tbm_surface_destroy(t_surface);
+ t_surface = NULL;
- if (mm_buf) {
- free(mm_buf);
- mm_buf = NULL;
- }
+ if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
+ GST_ERROR_OBJECT(self, "tbm_surface_get_info failed. 0x%x", tbm_ret);
+ return GST_FLOW_ERROR;
+ }
- if (gst_buf) {
- gst_buffer_unref(gst_buf);
- gst_buf = NULL;
+ GST_INFO_OBJECT(self, "video/tbm surface info done.");
+ goto again;
+ } else {
+ GST_WARNING_OBJECT(self, "unknown message : id %d", recv_msg.id);
+ goto again;
+ }
}
- if (normal_buffer_data) {
- free(normal_buffer_data);
- normal_buffer_data = NULL;
+ if (!gst_buf) {
+ GST_ERROR_OBJECT(self, "no buffer");
+ return GST_FLOW_ERROR;
}
- return GST_FLOW_ERROR;
+ *outbuf = gst_buf;
+
+ return GST_FLOW_OK;
}