* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_H__
-#define __TIZEN_MEDIA_ROSE_H__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_H__
#include <tizen.h>
#include <stdbool.h>
int rose_start(rose_h rose);
int rose_stop(rose_h rose);
int rose_pause(rose_h rose);
-int rose_set_play_position(rose_h rose, int msec, bool accurate);
+//int rose_set_play_position(rose_h rose, int msec, bool accurate);
int rose_get_play_position(rose_h rose, int *msec);
//int rose_get_state(rose_h rose, rose_state_e *state);
int rose_set_display(rose_h rose, rose_display_type_e type, void *display);
#ifdef __cplusplus
}
#endif
-#endif /* __TIZEN_MEDIA_ROSE_H__ */
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_H__ */
* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_CTLINFO_H__
-#define __TIZEN_MEDIA_ROSE_CTLINFO_H__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_CTLINFO_PARSE_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_CTLINFO_PARSE_H__
#include <glib.h>
#include <libxml/parser.h>
int rose_ctl_info_parse(xmlNode * a_node, rose_control_info ** ctl_info);
void rose_ctl_info_free(rose_control_info * ctl_info);
+/* The number of devices and information of the device are needed. */
+guint rose_ctl_get_total_delay_time(rose_control_info * ctl_info, rose_sdc_type_e type);
+
#ifdef __cplusplus
}
#endif
-#endif /* __TIZEN_MEDIA_ROSE_CTLINFO_H__ */
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_CTLINFO_PARSE_H__ */
* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_XML_H__
-#define __TIZEN_MEDIA_ROSE_XML_H__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_PARSE_XML_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_PARSE_XML_H__
#include <glib.h>
#include <libxml/parser.h>
#ifdef __cplusplus
}
#endif
-#endif /* __TIZEN_MEDIA_ROSE_XML_H__ */
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_PARSE_XML_H__ */
* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_PRIVATE_H__
-#define __TIZEN_MEDIA_ROSE_PRIVATE_H__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_PRIV_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_PRIV_H__
#include <glib.h>
#include <dlog.h>
+#include <time.h>
#include "rose_tizen.h"
#include "rose_tizen_sem_parse.h"
#include "rose_tizen_ctlinfo_parse.h"
#endif
#define LOG_TAG "TIZEN_N_ROSE"
+#define ROSE_GET_SEM(handle) ((rose_s *)handle)->sem
+#define ROSE_GET_RENDERER(handle) ((rose_s *)handle)->renderer
+#define ROSE_GET_MPLAYER_INTF(handle) ((rose_s *)handle)->mplayer_intf
+#define ROSE_GET_CTL_INFO(hanlde) ((rose_s *)handle)->ctl_info
+
#define ROSE_CHECK_CONDITION(condition, error, msg) \
do { \
- if (condition) {} else { \
- LOGE("[%s] %s(0x%08x)", __FUNCTION__, msg, error); \
+ if (!condition) { \
+ LOGE("%s return %s", msg, #error); \
return error; \
} \
} while (0)
#define ROSE_CHECK_INSTANCE(rose) \
- ROSE_CHECK_CONDITION(rose != NULL, ROSE_ERROR_INVALID_PARAMETER, \
+ ROSE_CHECK_CONDITION(rose, ROSE_ERROR_INVALID_PARAMETER, \
"ROSE_ERROR_INVALID_PARAMETER")
#define ROSE_CHECK_NULL(arg) \
return ROSE_ERROR_INVALID_STATE; \
} \
} while (0)
+
+#define ROSE_SET_STATE(x_rose, x_state) \
+do { \
+ LOGD("setting state [%s:%d]", #x_state, x_state); \
+ ((rose_s *)(x_rose))->state = x_state; \
+} while (0)
+
+#define ROSE_CHECK_NULL_GOTO(arg, error) \
+do { \
+ if (!arg) { \
+ LOGE("[%s] input arg is NULL goto %s", #arg, #error); \
+ goto error; \
+ } \
+} while (0)
+
+#define ROSE_G_FREE_IF(x) \
+do { \
+ if (x) { \
+ g_free(x); \
+ x = NULL; \
+ } \
+} while (0)
+
+#define _RENDER_MUTEX_INIT(x_render) g_mutex_init(&((rose_render *)x_render)->mutex)
+#define _RENDER_MUTEX_LOCK(x_render) g_mutex_lock(&((rose_render *)x_render)->mutex)
+#define _RENDER_MUTEX_UNLOCK(x_render) g_mutex_unlock(&((rose_render *)x_render)->mutex)
+
+#define _RENDER_PAUSE_MUTEX_INIT(x_render) g_mutex_init(&((rose_render *)x_render)->pause_mutex)
+#define _RENDER_PAUSE_MUTEX_LOCK(x_render) g_mutex_lock(&((rose_render *)x_render)->pause_mutex)
+#define _RENDER_PAUSE_MUTEX_UNLOCK(x_render) g_mutex_unlock(&((rose_render *)x_render)->pause_mutex)
+
+#define _RENDER_CLOCK_MUTEX_INIT(x_render) g_mutex_init(&((rose_render *)x_render)->clock_mutex)
+#define _RENDER_CLOCK_MUTEX_LOCK(x_render) g_mutex_lock(&((rose_render *)x_render)->clock_mutex)
+#define _RENDER_CLOCK_MUTEX_UNLOCK(x_render) g_mutex_unlock(&((rose_render *)x_render)->clock_mutex)
+
+#define _RENDER_COND_INIT(x_render) g_cond_init(&((rose_render *)x_render)->cond)
+#define _RENDER_COND_WAIT(x_render) g_cond_wait(&((rose_render *)x_render)->cond, &((rose_render *)x_render)->mutex)
+#define _RENDER_COND_SIGNAL(x_render) g_cond_signal(&((rose_render *)x_render)->cond)
+
+#define _RENDER_PAUSE_COND_INIT(x_render) g_cond_init(&((rose_render *)x_render)->pause_cond)
+#define _RENDER_PAUSE_COND_WAIT(x_render) g_cond_wait(&((rose_render *)x_render)->pause_cond, &((rose_render *)x_render)->pause_mutex)
+#define _RENDER_PAUSE_COND_SIGNAL(x_render) g_cond_signal(&((rose_render *)x_render)->pause_cond)
+
+#define DEFAULT_CHECK_TIME_MS 100
+
+typedef struct _rose_render {
+ GMutex mutex;
+ GCond cond;
+
+ GMutex pause_mutex;
+ GCond pause_cond;
+
+ GMutex clock_mutex;
+
+ gboolean thread_exit;
+ gboolean thread_pause;
+
+ gboolean mplayer_is_started;
+
+ gint64 base_clock;
+ gint64 time_offset;
+
+ guint wait_timer;
+
+ GList *cur_sem_list;
+ GList *last_sem_list;
+
+ GThread *thread;
+} rose_render;
+
typedef struct _rose_s {
rose_state_e state;
gchar *sem_path;
gchar *media_path;
+ gchar *ctl_info_path;
rose_sem *sem;
rose_control_info *ctl_info;
mplayer_interface *mplayer_intf;
+ rose_render *renderer;
} rose_s;
#ifdef __cplusplus
}
#endif
-#endif /* __TIZEN_MEDIA_ROSE_PRIVATE_H__ */
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_PRIV_H__ */
* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_SEM_H__
-#define __TIZEN_MEDIA_ROSE_SEM_H__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_SEM_PARSE_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_SEM_PARSE_H__
#include <glib.h>
#include <libxml/parser.h>
SEM_EFFECT_NONE,
SEM_EFFECT_LIGHT,
SEM_EFFECT_FLASH,
- SEM_EFFECT_TEMPERATURE,
SEM_EFFECT_WIND,
SEM_EFFECT_VIBRATION,
+ SEM_EFFECT_TEMPERATURE,
SEM_EFFECT_MAX,
} rose_sem_effect_type_e;
rose_sem_si_attr *si_attr;
/* effect_elements is rose_sem_effect_elements */
GList *effect_elements;
-
};
struct _rose_sem_si_attr {
rose_sem_base_attr *base_attr;
rose_sem_si_attr *si_attr;
+
+ guint delay_time;
};
int rose_sem_parse(xmlNode * a_node, rose_sem ** sem);
void rose_sem_free(rose_sem * sem);
+guint _rose_sem_get_pts(rose_sem_effect_elements *effect, guint time_scale);
+gint64 _rose_sem_get_render_time(rose_sem_effect_elements *effect, guint time_scale);
+void _rose_sem_sort_pts_with_delay(rose_sem *sem);
+
+#ifdef __FOR_DEBUG
+void _print_sem_data (rose_sem_effect_elements *effect, guint pts);
+#endif
+
#ifdef __cplusplus
}
#endif
-#endif /* __TIZEN_MEDIA_ROSE_SEM_H__ */
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_SEM_PARSE_H__ */
* limitations under the License.
*/
-#ifndef __TIZEN_MEDIA_ROSE_MPLAYER__
-#define __TIZEN_MEDIA_ROSE_MPLAYER__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_H__
#include <stdint.h>
#include <stdbool.h>
}
#endif /* __cplusplus */
-#endif /* __TIZEN_MEDIA_ROSE_MPLAYER__ */
\ No newline at end of file
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_H__ */
\ No newline at end of file
*/
-#ifndef __TIZEN_MEDIA_ROSE_MPLAYER_INTF__
-#define __TIZEN_MEDIA_ROSE_MPLAYER_INTF__
+#ifndef __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_INTERFACE_H__
+#define __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_INTERFACE_H__
#include <stdint.h>
#include <stdbool.h>
}
#endif /* __cplusplus */
-#endif /* __TIZEN_MEDIA_ROSE_MPLAYER_INTF__ */
\ No newline at end of file
+#endif /* __TIZEN_MEDIA_ROSE_TIZEN_MPLAYER_INTERFACE_H__ */
\ No newline at end of file
Name: capi-media-rose-tizen
Summary: For RoSE(Representation Of Sensory Effect) APIs
-Version: 0.0.5
+Version: 0.0.6
Release: 0
Group: Multimedia/API
License: Apache-2.0
#include <stdio.h>
#include <stdlib.h>
#include "rose_tizen_priv.h"
-//#include "rose_tizen_parse_xml.h"
-//#include "rose_tizen_sem_parse.h"
+
+static gpointer _rose_render_thread (gpointer data);
+static gint _wait_to_render(gpointer data);
+static gboolean _create_render_thread(rose_s *handle);
+static void _destroy_render_thread(rose_s *handle);
+static gint64 _get_running_time(rose_render *renderer);
+static void _rose_apply_delay(rose_s *handle);
+static void _start_mplayer(rose_s *handle);
+static guint _calc_wait_time(gint64 next_pts, gint64 cur_pts);
int rose_create(rose_h * rose)
{
ret = _rose_mplayer_create(&handle->mplayer_intf);
if (ret) {
LOGE("Failed to create mplayer handle %d", ret);
- g_free(handle);
- *rose = NULL;
+ ROSE_G_FREE_IF(handle);
return ROSE_ERROR_INVALID_OPERATION;
}
- handle->state = ROSE_STATE_IDLE;
+ ROSE_SET_STATE(handle, ROSE_STATE_IDLE);
*rose = (rose_h) handle;
if (ret) // need to check error handling
LOGE("Failed to destroy mplayer handle %d", ret);
- g_free(handle);
+ ROSE_G_FREE_IF(handle->sem_path);
+ ROSE_G_FREE_IF(handle->media_path);
+ ROSE_G_FREE_IF(handle->ctl_info_path);
+ ROSE_G_FREE_IF(handle);
return ROSE_ERROR_NONE;
}
SECURE_LOGD("input sem path is %s", path);
// need to check file path is valid
+ ROSE_G_FREE_IF(handle->sem_path);
+
+ handle->sem_path = g_strndup(path, strlen(path));
+
// check validate SEM
doc = xmlReadFile(path, "UTF-8", 0);
if (!doc) {
SECURE_LOGD("input control info path is %s", path);
// need to check file path is valid
+ ROSE_G_FREE_IF(handle->ctl_info_path);
+
+ handle->ctl_info_path = g_strndup(path, strlen(path));
+
// check validate ControlInfo
doc = xmlReadFile(path, "UTF-8", 0);
if (!doc) {
ROSE_CHECK_INSTANCE(handle->mplayer_intf);
ROSE_CHECK_STATE(handle, ROSE_STATE_IDLE);
+ ROSE_G_FREE_IF(handle->media_path);
+
+ handle->media_path = g_strndup(path, strlen(path));
+
ret = _rose_mplayer_set_uri(handle->mplayer_intf, path);
if (ret)
LOGE("Failed to set uri %d", ret);
ROSE_CHECK_INSTANCE(handle->mplayer_intf);
ROSE_CHECK_STATE(handle, ROSE_STATE_IDLE);
+ handle->renderer = (rose_render *) g_new0(rose_render, 1);
+ handle->renderer->thread_pause = TRUE;
+ if (!_create_render_thread(handle)) {
+ LOGE("Failed to create render thread");
+ ret = ROSE_ERROR_INVALID_OPERATION;
+ goto ERROR;
+ }
+
+ _rose_apply_delay(handle);
+
ret = _rose_mplayer_prepare(handle->mplayer_intf);
- if (ret)
+ if (ret) {
LOGE("Failed to prepare player %d", ret);
+ goto ERROR;
+ }
+
+ ROSE_SET_STATE(handle, ROSE_STATE_READY);
+
+ return ret;
+ERROR:
+ _rose_mplayer_unprepare(handle->mplayer_intf);
+ _destroy_render_thread(handle);
+ ROSE_G_FREE_IF(handle->renderer);
return ret;
}
if (ret)
LOGE("Failed to unprepare player %d", ret);
+ _destroy_render_thread(handle);
+
+ ROSE_SET_STATE(handle, ROSE_STATE_IDLE);
+
return ret;
}
ROSE_CHECK_INSTANCE(handle);
ROSE_CHECK_INSTANCE(handle->mplayer_intf);
+ ROSE_CHECK_INSTANCE(handle->renderer);
ROSE_CHECK_STATE(handle, ROSE_STATE_READY);
- ret = _rose_mplayer_start(handle->mplayer_intf);
- if (ret)
- LOGE("Failed to start player %d", ret);
+ _RENDER_PAUSE_MUTEX_LOCK(handle->renderer);
+ handle->renderer->thread_pause = FALSE;
+ _RENDER_PAUSE_COND_SIGNAL(handle->renderer);
+ _RENDER_PAUSE_MUTEX_UNLOCK(handle->renderer);
+
+ ROSE_SET_STATE(handle, ROSE_STATE_PLAYING);
return ret;
}
+
int rose_stop(rose_h rose)
{
int ret = ROSE_ERROR_NONE;
rose_s *handle = (rose_s *)rose;
+ rose_render *renderer;
ROSE_CHECK_INSTANCE(handle);
ROSE_CHECK_INSTANCE(handle->mplayer_intf);
+ ROSE_CHECK_INSTANCE(handle->renderer);
ROSE_CHECK_STATE(handle, ROSE_STATE_PLAYING);
- ret = _rose_mplayer_stop(handle->mplayer_intf);
- if (ret)
- LOGE("Failed to stop player %d", ret);
+ /* pause render thread*/
+ renderer = ROSE_GET_RENDERER(handle);
+ renderer->thread_pause = TRUE;
+ if (renderer->wait_timer != 0) {
+ g_source_remove(renderer->wait_timer);
+ renderer->wait_timer = 0;
+ }
+ renderer->cur_sem_list = NULL;
+ renderer->last_sem_list = NULL;
+ _RENDER_COND_SIGNAL(renderer);
+ if (renderer->mplayer_is_started) {
+ ret = _rose_mplayer_stop(handle->mplayer_intf);
+ if (ret) {
+ LOGE("Failed to stop player %d", ret);
+ return ret;
+ }
+ renderer->mplayer_is_started = FALSE;
+ }
+
+ ROSE_SET_STATE(handle, ROSE_STATE_READY);
return ret;
}
+
int rose_pause(rose_h rose)
{
int ret = ROSE_ERROR_NONE;
rose_s *handle = (rose_s *)rose;
+ rose_render *renderer;
ROSE_CHECK_INSTANCE(handle);
ROSE_CHECK_INSTANCE(handle->mplayer_intf);
+ ROSE_CHECK_INSTANCE(handle->renderer);
ROSE_CHECK_STATE(handle, ROSE_STATE_PLAYING);
- ret = _rose_mplayer_pause(handle->mplayer_intf);
- if (ret)
- LOGE("Failed to pause player %d", ret);
+ /* pause render thread*/
+ renderer = ROSE_GET_RENDERER(handle);
+ renderer->thread_pause = TRUE;
+ if (renderer->wait_timer != 0) {
+ g_source_remove(renderer->wait_timer);
+ renderer->wait_timer = 0;
+ }
+ _RENDER_COND_SIGNAL(renderer);
+ if (renderer->mplayer_is_started) {
+ ret = _rose_mplayer_pause(handle->mplayer_intf);
+ if (ret)
+ LOGE("Failed to pause player %d", ret);
+ renderer->mplayer_is_started = FALSE;
+ }
+
+ ROSE_SET_STATE(handle, ROSE_STATE_PAUSED);
return ret;
}
-int rose_set_play_position(rose_h rose, int msec, bool accurate)
+int rose_get_play_position(rose_h rose, int *msec)
{
int ret = ROSE_ERROR_NONE;
rose_s *handle = (rose_s *)rose;
+ int get_msec = 0;
ROSE_CHECK_INSTANCE(handle);
ROSE_CHECK_STATE(handle, ROSE_STATE_READY);
- ret = _rose_mplayer_set_position(handle->mplayer_intf, msec, accurate);
+ ret = _rose_mplayer_get_position(handle->mplayer_intf, &get_msec);
if (ret)
- LOGE("Failed to set play position %d", ret);
+ LOGE("Failed to get play position %d", ret);
+
+ *msec = get_msec;
return ret;
}
-int rose_get_play_position(rose_h rose, int *msec)
+static void _resync_base_time(rose_s *handle)
{
int ret = ROSE_ERROR_NONE;
- rose_s *handle = (rose_s *)rose;
int get_msec = 0;
+ rose_render *renderer = NULL;
+
+ ROSE_CHECK_NULL_VOID(handle);
+ ROSE_CHECK_NULL_VOID(handle->renderer);
+ ROSE_CHECK_NULL_VOID(handle->mplayer_intf);
+
+ renderer = ROSE_GET_RENDERER(handle);
+
+ if (renderer->base_clock == 0) {
+ _RENDER_CLOCK_MUTEX_LOCK(renderer);
+ renderer->base_clock = g_get_monotonic_time() + renderer->time_offset * G_GINT64_CONSTANT (1000);
+ _RENDER_CLOCK_MUTEX_UNLOCK(renderer);
+ return;
+ }
+
+ if (_get_running_time(renderer) <= 0)
+ return;
- ROSE_CHECK_INSTANCE(handle);
- ROSE_CHECK_STATE(handle, ROSE_STATE_READY);
ret = _rose_mplayer_get_position(handle->mplayer_intf, &get_msec);
- if (ret)
- LOGE("Failed to set play position %d", ret);
+ if (ret) {
+ LOGE("Failed to get play position %d", ret);
+ get_msec = 0;
+ }
- *msec = get_msec;
+ _RENDER_CLOCK_MUTEX_LOCK(renderer);
+ renderer->base_clock = g_get_monotonic_time()
+ + renderer->time_offset * G_GINT64_CONSTANT (1000)
+ - (gint64)(get_msec * G_GINT64_CONSTANT (1000));
+ _RENDER_CLOCK_MUTEX_UNLOCK(renderer);
+}
- return ret;
+static gpointer _rose_render_thread (gpointer data)
+{
+ rose_s *handle = (rose_s *)data;
+ rose_render *renderer = NULL;
+ rose_sem *sem = NULL;
+ gint64 cur_pts = 0;
+ gint64 next_pts = 0;
+ guint wait_time = 0;
+ guint time_scale = 0;
+
+ GList *cur_list = NULL;
+ GList *next_list = NULL;
+
+ ROSE_CHECK_CONDITION(handle, NULL, "handle is NULL");
+ ROSE_CHECK_CONDITION(handle->sem, NULL, "sem is NULL");
+ ROSE_CHECK_CONDITION(handle->renderer, NULL, "renderer is NULL");
+
+ sem = ROSE_GET_SEM(handle);
+ renderer = ROSE_GET_RENDERER(handle);
+
+ time_scale = sem->time_scale;
+
+ _RENDER_MUTEX_LOCK(renderer);
+ while (!renderer->thread_exit) {
+ /* need to check pause state */
+ _RENDER_PAUSE_MUTEX_LOCK(renderer);
+ while (renderer->thread_pause) {
+ LOGD("Pause render thread");
+ _RENDER_PAUSE_COND_WAIT(renderer);
+ _resync_base_time(handle);
+ LOGD("restart render thread");
+ }
+ _RENDER_PAUSE_MUTEX_UNLOCK(renderer);
+ if (renderer->thread_exit)
+ break;
+
+ /* check list */
+ if (renderer->last_sem_list) {
+ cur_list = renderer->last_sem_list;
+ next_list = cur_list->next;
+ if (!next_list)
+ break;
+
+ } else {
+ cur_list = NULL;
+ cur_pts = 0;
+ next_list = g_list_first(sem->effect_elements);
+ }
+
+ _start_mplayer(handle);
+
+ next_pts = _rose_sem_get_render_time(next_list->data, time_scale);
+ LOGD("Next render pts = %" G_GINT64_FORMAT " ms", next_pts);
+ cur_pts = _get_running_time(renderer);
+
+ if (cur_pts <= 0 && next_pts >= 0 && !renderer->mplayer_is_started) {
+ wait_time = _calc_wait_time(0, cur_pts);
+ LOGD("Need to mplayer start");
+ LOGD("add wait timer %u ms", wait_time);
+ renderer->wait_timer = g_timeout_add((guint)wait_time,
+ (GSourceFunc)_wait_to_render, handle);
+ _RENDER_COND_WAIT(renderer);
+ _start_mplayer(handle);
+ cur_pts = 0;
+ if (renderer->thread_pause || renderer->thread_exit)
+ continue;
+ }
+
+ wait_time = _calc_wait_time(next_pts, cur_pts);
+ LOGD("add wait timer %u ms", wait_time);
+ renderer->cur_sem_list = next_list;
+ renderer->wait_timer = g_timeout_add((guint)wait_time,
+ (GSourceFunc)_wait_to_render, handle);
+ _RENDER_COND_WAIT(renderer);
+ if (renderer->thread_pause || renderer->thread_exit)
+ continue;
+
+ cur_list = next_list;
+ renderer->last_sem_list = cur_list;
+
+ if (renderer->thread_exit)
+ break;
+
+ cur_list = cur_list->next;
+ }
+
+ _RENDER_MUTEX_UNLOCK(renderer);
+ LOGD("exit render thread");
+
+ return NULL;
+}
+
+static gint _wait_to_render(gpointer data)
+{
+ rose_s *handle = (rose_s *)data;
+ gint64 render_time = 0;
+ gint64 running_time = 0;
+ rose_render *renderer = NULL;
+ rose_sem *sem = NULL;
+
+ ROSE_CHECK_NULL_GOTO(handle, ERROR);
+ ROSE_CHECK_NULL_GOTO(handle->sem, ERROR);
+ ROSE_CHECK_NULL_GOTO(handle->renderer, ERROR);
+ ROSE_CHECK_NULL_GOTO(handle->renderer->cur_sem_list, ERROR);
+
+ sem = ROSE_GET_SEM(handle);
+ renderer = ROSE_GET_RENDERER(handle);
+
+ LOGD("Called wait_render timer");
+ g_usleep(1000);
+ //_resync_base_time(handle);
+
+ if (!renderer->mplayer_is_started)
+ render_time = 0;
+ else
+ render_time = _rose_sem_get_render_time(renderer->cur_sem_list->data, sem->time_scale);
+
+ while (1) {
+ running_time = _get_running_time(renderer);
+ if (running_time >= render_time)
+ break;
+ g_usleep((render_time - running_time) * G_GINT64_CONSTANT (1000));
+ }
+
+ERROR:
+ _RENDER_COND_SIGNAL(renderer);
+
+ return FALSE;
+}
+
+static gint64 _get_running_time(rose_render *renderer)
+{
+ gint64 running_time = -1;
+ ROSE_CHECK_CONDITION(renderer, -1, "Renderer is NULL");
+ _RENDER_CLOCK_MUTEX_LOCK(renderer);
+ running_time = (g_get_monotonic_time() - renderer->base_clock ) / G_GINT64_CONSTANT (1000);
+ _RENDER_CLOCK_MUTEX_UNLOCK(renderer);
+ return running_time;
+}
+
+static gboolean _create_render_thread(rose_s *handle)
+{
+ ROSE_CHECK_NULL_FALSE(handle);
+ ROSE_CHECK_NULL_FALSE(handle->renderer);
+
+ _RENDER_MUTEX_INIT(handle->renderer);
+ _RENDER_PAUSE_MUTEX_INIT(handle->renderer);
+ _RENDER_CLOCK_MUTEX_INIT(handle->renderer);
+
+ _RENDER_COND_INIT(handle->renderer);
+ _RENDER_PAUSE_COND_INIT(handle->renderer);
+
+ handle->renderer->thread = g_thread_new ("thread",
+ (GThreadFunc)_rose_render_thread, handle);
+ if (handle->renderer->thread == NULL) {
+ LOGE("Failed to create render thread");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void _destroy_render_thread(rose_s *handle)
+{
+ rose_render *renderer;
+ ROSE_CHECK_NULL_VOID(handle);
+ ROSE_CHECK_NULL_VOID(handle->renderer);
+ ROSE_CHECK_NULL_VOID(handle->renderer->thread);
+
+ renderer = ROSE_GET_RENDERER(handle);
+
+ renderer->thread_exit = TRUE;
+ renderer->thread_pause = FALSE;
+ if (renderer->wait_timer > 0) {
+ g_source_remove(renderer->wait_timer);
+ renderer->wait_timer = 0;
+ }
+ _RENDER_COND_SIGNAL(renderer);
+ _RENDER_PAUSE_COND_SIGNAL(renderer);
+ g_thread_join(renderer->thread);
+ renderer->thread = NULL;
+}
+
+static void _rose_apply_delay(rose_s *handle)
+{
+ GList *sem_node;
+ rose_sem_effect_elements *sem_element;
+ guint delay = 0;
+ rose_sem *sem;
+ rose_control_info *ctl_info;
+ guint first_pts = 0;
+ gint64 time_offset = 0;
+
+ ROSE_CHECK_NULL_VOID(handle);
+ ROSE_CHECK_NULL_VOID(handle->sem);
+ ROSE_CHECK_NULL_VOID(handle->ctl_info);
+ ROSE_CHECK_NULL_VOID(handle->renderer);
+
+ sem = handle->sem;
+ ctl_info = handle->ctl_info;
+
+ sem_node = sem->effect_elements;
+
+ for (; sem_node; sem_node = sem_node->next) {
+ sem_element = (rose_sem_effect_elements *)sem_node->data;
+ delay = rose_ctl_get_total_delay_time(ctl_info, (int) sem_element->type);
+ if (delay != G_MAXUINT)
+ sem_element->delay_time = delay;
+ }
+
+ _rose_sem_sort_pts_with_delay(sem);
+
+ sem_element = (g_list_first(sem->effect_elements))->data;
+
+ first_pts = _rose_sem_get_pts(sem_element, sem->time_scale);
+ time_offset = (gint64)first_pts - sem_element->delay_time;
+
+ if (time_offset < 0)
+ handle->renderer->time_offset = time_offset;
+
+ LOGD("Time offset = [%" G_GINT64_FORMAT "]", time_offset);
+
+}
+
+static void _start_mplayer(rose_s *handle)
+{
+ rose_render *renderer;
+ int ret;
+ ROSE_CHECK_NULL_VOID(handle);
+ ROSE_CHECK_NULL_VOID(handle->sem);
+ ROSE_CHECK_NULL_VOID(handle->renderer);
+
+ renderer = ROSE_GET_RENDERER(handle);
+
+ if (!renderer->mplayer_is_started && (_get_running_time(renderer) >= 0)) {
+ ret = _rose_mplayer_start(handle->mplayer_intf);
+ if (ret) {
+ LOGE("Failed to start player %d", ret);
+ return;
+ }
+ LOGD("Started mplayer");
+ renderer->mplayer_is_started = TRUE;
+ }
+}
+
+static guint _calc_wait_time(gint64 next_pts, gint64 cur_pts)
+{
+ guint wait_time = 0;
+
+ if ((next_pts - cur_pts - DEFAULT_CHECK_TIME_MS) > 0)
+ wait_time = next_pts - cur_pts - DEFAULT_CHECK_TIME_MS;
+
+ return wait_time;
}
\ No newline at end of file
int ret = ROSE_ERROR_NONE;
gboolean exist = FALSE;
+ ROSE_CHECK_INSTANCE(ctl_info);
+
rose_ctl_info_free(*ctl_info);
- *ctl_info = NULL;
new_ctl_info = g_slice_new0(rose_control_info);
ret = ROSE_ERROR_INVALID_OPERATION;
}
+ *ctl_info = new_ctl_info;
+
return ret;
}
if (new_sdc_element->sdc_type > SDC_TYPE_NONE) {
switch (new_sdc_element->sdc_type) {
- case SDC_TYPE_LIGHT:
- exist |= _parse_sdc_light_type(node, &new_sdc_element->light);
case SDC_TYPE_FLASH:
exist |= _parse_sdc_flash_type(node, &new_sdc_element->flash);
break;
+ case SDC_TYPE_LIGHT:
+ exist |= _parse_sdc_light_type(node, &new_sdc_element->light);
+ break;
case SDC_TYPE_WIND:
exist |= _parse_sdc_wind_type(node, &new_sdc_element->wind);
break;
gboolean exist = FALSE;
// xmlNode *cur_node;
+ ROSE_CHECK_NULL_FALSE(light);
+
new_light = g_slice_new0(rose_sdc_light);
exist |= new_light->unit_flag =
return FALSE;
}
+ _free_sdc_light_type(*light);
+ *light = new_light;
+
return TRUE;
}
rose_sdc_flash *new_flash = NULL;
gboolean exist = FALSE;
+ ROSE_CHECK_NULL_FALSE(flash);
+
new_flash = g_slice_new0(rose_sdc_flash);
exist |= new_flash->max_freq_flag
return FALSE;
}
+ _free_sdc_flash_type(*flash);
+ *flash = new_flash;
+
return TRUE;
}
rose_sdc_wind *new_wind = NULL;
gboolean exist = FALSE;
+ ROSE_CHECK_NULL_FALSE(wind);
+
new_wind = g_slice_new0(rose_sdc_wind);
exist |= new_wind->unit_flag =
return FALSE;
}
+ _free_sdc_wind_type(*wind);
+ *wind = new_wind;
+
return TRUE;
}
rose_sdc_vibration *new_vibration = NULL;
gboolean exist = FALSE;
+ ROSE_CHECK_NULL_FALSE(vibration);
+
new_vibration = g_slice_new0(rose_sdc_vibration);
exist |= new_vibration->unit_flag =
return FALSE;
}
+ _free_sdc_vibration_type(*vibration);
+ *vibration = new_vibration;
+
return TRUE;
}
g_slice_free(rose_control_info, ctl_info);
}
+static gint _compare_type(rose_sdc_element *a, rose_sdc_type_e *type)
+{
+ if (a && type) {
+ if (a->sdc_type == *type)
+ return 0;
+ }
+
+ return 1;
+}
+
+guint rose_ctl_get_total_delay_time(rose_control_info * ctl_info, rose_sdc_type_e type)
+{
+ GList *r_list = NULL;
+ rose_sdc_element *sdc_elem;
+ guint delay_time = G_MAXUINT;
+ ROSE_CHECK_CONDITION(ctl_info, G_MAXUINT, "ctl_info is NULL");
+
+ r_list = g_list_find_custom (ctl_info->sdc_elements, &type, (GCompareFunc) _compare_type);
+ if (!r_list) {
+ LOGW("[%d] type is not on the list", type);
+ return delay_time;
+ }
+
+ sdc_elem = (rose_sdc_element *)r_list->data;
+ delay_time = sdc_elem->firstorderdelaytime + sdc_elem->zerothorderdelaytime;
+ LOGD("[%d type] delay time is [%u]", type, delay_time);
+ return delay_time;
+}
\ No newline at end of file
}
+guint _rose_sem_get_pts(rose_sem_effect_elements *effect, guint time_scale)
+{
+ guint pts = 0;
+ guint apply_time_scale = time_scale;
+ ROSE_CHECK_CONDITION(effect, G_MAXUINT, "effect data is NULL");
+ ROSE_CHECK_CONDITION(effect->si_attr, G_MAXUINT, "effect si attribute is NULL");
+
+ if (effect->si_attr->time_scale_flag)
+ apply_time_scale = effect->si_attr->time_scale;
+
+ if (apply_time_scale != 0)
+ pts = effect->si_attr->pts / apply_time_scale;
+ else
+ pts = effect->si_attr->pts;
+
+ return pts * 1000;
+}
+
+gint64 _rose_sem_get_render_time(rose_sem_effect_elements *effect, guint time_scale)
+{
+ gint64 time_with_delay = G_MAXINT64;
+ guint time_pts = 0;
+ time_pts = _rose_sem_get_pts(effect, time_scale);
+ if (time_pts != G_MAXUINT) {
+ time_with_delay = (gint64)time_pts - effect->delay_time;
+ LOGD("pts with delay = %" G_GINT64_FORMAT "ms", time_with_delay);
+ }
+
+ return time_with_delay;
+}
+
+gint _sort_element_pts (rose_sem_effect_elements *e1, rose_sem_effect_elements *e2, rose_sem *sem)
+{
+ gint64 time1 = 0;
+ gint64 time2 = 0;
+
+ ROSE_CHECK_CONDITION(e1, 0, "1st arg is NULL");
+ ROSE_CHECK_CONDITION(e2, 0, "2nd arg is NULL");
+ ROSE_CHECK_CONDITION(sem, 0, "rose sem is NULL");
+
+ time1 = _rose_sem_get_pts(e1, sem->time_scale) - e1->delay_time;
+ time2 = _rose_sem_get_pts(e2, sem->time_scale) - e2->delay_time;
+
+ return (time1 - time2);
+}
+
+void _rose_sem_sort_pts_with_delay(rose_sem *sem)
+{
+ ROSE_CHECK_NULL_VOID(sem);
+ sem->effect_elements = g_list_sort_with_data(sem->effect_elements,
+ (GCompareDataFunc)_sort_element_pts, sem);
+ return;
+}
+
+#ifdef __FOR_DEBUG
+const char * _convert_type_to_str(rose_sem_effect_type_e type)
+{
+ const char *msg;
+ switch (type) {
+ case SEM_EFFECT_LIGHT:
+ msg = "SEM_EFFECT_LIGHT";
+ break;
+ case SEM_EFFECT_FLASH:
+ msg = "SEM_EFFECT_FLASH";
+ break;
+ case SEM_EFFECT_TEMPERATURE:
+ msg = "SEM_EFFECT_TEMPERATURE";
+ break;
+ case SEM_EFFECT_WIND:
+ msg = "SEM_EFFECT_WIND";
+ break;
+ case SEM_EFFECT_VIBRATION:
+ msg = "SEM_EFFECT_VIBRATION";
+ break;
+ default:
+ msg = "SEM_EFFECT_UNKNOWN";
+ break;
+ }
+ return msg;
+}
+
+void _print_sem_data (rose_sem_effect_elements *effect, guint time_scale)
+{
+ ROSE_CHECK_NULL_VOID(effect);
+ // GString *string = g_string_new(NULL);
+ LOGI("-----------------------------------------------------------------------");
+ LOGD("%s", _convert_type_to_str(effect->type));
+
+ if (effect->color_type_flag)
+ LOGD("color type = [%s]", effect->color_type);
+
+ if (effect->frequency_flag)
+ LOGD("frequency = [%u]", effect->frequency);
+
+ if (effect->intensity_value_flag)
+ LOGD("intensity_value = [%f]", effect->intensity_value);
+
+ if (effect->intensity_range_flag)
+ LOGD("intensity_range = [%f - %f]", effect->min_intensity, effect->max_intensity);
+
+ if (effect->base_attr) {
+ rose_sem_base_attr *base_attr = effect->base_attr;
+ if (base_attr->activate_flag)
+ LOGD("%s", base_attr->activate ? "activate" : "deactivate");
+ if (base_attr->duration_flag)
+ LOGD("duration = [%u]", base_attr->duration);
+ if (base_attr->fade_flag)
+ LOGD("fade = [%u]", base_attr->fade);
+ if (base_attr->priority_flag)
+ LOGD("priority = [%u]", base_attr->priority);
+ if (base_attr->location_flag)
+ LOGD("location = [%s]", base_attr->location);
+ }
+
+ if (effect->si_attr) {
+ rose_sem_si_attr *si_attr = effect->si_attr;
+ if (si_attr->time_scale_flag)
+ LOGD("\ntime_scale = [%u]", si_attr->time_scale);
+ if (si_attr->pts_delta_flag)
+ LOGD("pts_delta = [%u]", si_attr->pts_delta);
+ if (si_attr->abs_time_flag)
+ LOGD("abs_time = [%s]", si_attr->abs_time);
+ if (si_attr->pts_flag) {
+ LOGD("pts = [%u]", si_attr->pts);
+ if (time_scale != 0)
+ LOGD("-> with delay pts = [%d ms]", (si_attr->pts / time_scale) * 1000 - effect->delay_time);
+ }
+ }
+}
+#endif
\ No newline at end of file
CURRENT_STATUS_SEM_FILE_PATH,
CURRENT_STATUS_CTL_INFO_FILE_PATH,
CURRENT_STATUS_DISPLAY_SURFACE_CHANGE,
- CURRENT_STATUS_POSITION_TIME,
- CURRENT_STATUS_POSITION_ACCURATE,
};
/* for video display */
return;
}
- // player_state_e player_state = PLAYER_STATE_NONE;
- // ret = player_get_state(g_player[0], &player_state);
- // if (ret)
- // g_print("failed to player_get_state(), ret(0x%x)\n", ret);
-
if (surface_type == ROSE_DISPLAY_TYPE_OVERLAY) {
if (!g_win_id) {
return ret;
}
-int test_rose_set_position(int time, bool accurate)
-{
- int ret = 0;
- LOGD("test_rose_set_position");
- ret = rose_set_play_position(rose, time, accurate);
- return ret;
-}
-
int test_rose_get_position()
{
int ret = 0;
return ret;
}
-// int rose_seek(rose_h rose, int64_t nanoseconds);
-// int rose_get_state(rose_h rose, rose_state_e *state);
int rose_set_display(rose_h rose, rose_display_type_e type, void *display);
/*-----------------------------------------------------------------------
test_rose_stop();
} else if (strncmp(cmd, "e", 1) == 0) {
test_rose_pause();
- } else if (strncmp(cmd, "j", 1) == 0) {
- g_menu_state = CURRENT_STATUS_POSITION_TIME;
} else if (strncmp(cmd, "l", 1) == 0) {
test_rose_get_position();
} else if (strncmp(cmd, "q", 1) == 0) {
g_print("*** input media path.\n");
} else if (g_menu_state == CURRENT_STATUS_DISPLAY_SURFACE_CHANGE) {
g_print("*** input display surface type.(0: Wayland surface, 1: EVAS surface, 2: No use surface (e.g: audio playback)) \n");
- } else if (g_menu_state == CURRENT_STATUS_POSITION_TIME) {
- g_print("*** input position value(msec)\n");
- } else if (g_menu_state == CURRENT_STATUS_POSITION_ACCURATE) {
- g_print("*** input accurate value(0/1)\n");
} else {
g_print("*** unknown status.\n");
/* exit(0); */
reset_menu_state();
break;
}
- case CURRENT_STATUS_POSITION_TIME: {
- value1 = atoi(cmd);
- g_menu_state = CURRENT_STATUS_POSITION_ACCURATE;
- break;
- }
- case CURRENT_STATUS_POSITION_ACCURATE: {
- test_rose_set_position(value1, ((atoi(cmd) != 0) ? (true) : (false)));
- reset_menu_state();
- break;
- }
default:
break;
}