support stream capture 67/264267/1
authorJunkyeong, Kim <jk0430.kim@samsung.com>
Wed, 15 Sep 2021 07:56:15 +0000 (16:56 +0900)
committerJunkyeong, Kim <jk0430.kim@samsung.com>
Wed, 15 Sep 2021 07:56:24 +0000 (16:56 +0900)
Use timerfd APIs for capture scheduling.
Create timerfd when backend init. Close this fd when module exit.
Only one stream capture is supported at the same time.

Change-Id: I46c1ff34ca0820c758deb0e1041e23c3d2d85b4e
Signed-off-by: Junkyeong, Kim <jk0430.kim@samsung.com>
src/libhal-backend-tdm-sprd/tdm_backend_sprd.c
src/libhal-backend-tdm-sprd/tdm_backend_sprd.h
src/libhal-backend-tdm-sprd/tdm_backend_sprd_types.h
src/libhal-backend-tdm-sprd/tdm_sprd_capture.c

index d56b861..c6c2193 100644 (file)
@@ -93,6 +93,18 @@ _tdm_find_primary_gpu(void)
 }
 #endif
 
+static hal_tdm_error
+_tdm_sprd_timer_fd_handler(int fd, hal_tdm_event_loop_mask mask, void *user_data)
+{
+       tdm_sprd_display *display_data = (tdm_sprd_display *)user_data;
+
+       TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
+
+       tdm_sprd_capture_timer_cb(display_data);
+
+       return HAL_TDM_ERROR_NONE;
+}
+
 static int
 _tdm_sprd_open_drm(void)
 {
@@ -137,6 +149,7 @@ close_l:
 static void
 _tdm_sprd_display_deinitialize(tdm_sprd_display *display_data)
 {
+       tdm_sprd_capture_deinit(display_data);
        tdm_sprd_display_destroy_output_list(display_data);
        tdm_sprd_display_destroy_buffer_list(display_data);
 
@@ -172,7 +185,7 @@ failed:
 static hal_tdm_error
 _tdm_sprd_master_drm_fd_handler(hal_tdm_fd master_drm_fd, void *user_data)
 {
-       tdm_sprd_display *display_data = (tdm_sprd_display *) user_data;
+       tdm_sprd_display *display_data = (tdm_sprd_display *)user_data;
        hal_tdm_error ret;
 
        TDM_BACKEND_RETURN_VAL_IF_FAIL(display_data != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
@@ -231,6 +244,9 @@ hal_backend_tdm_sprd_exit(void *data)
 
        _tdm_sprd_display_deinitialize(display_data);
 
+       if (display_data->timer_fd >= 0)
+               close(display_data->timer_fd);
+
        if (display_data->drm_fd >= 0)
                close(display_data->drm_fd);
 
@@ -253,6 +269,8 @@ hal_backend_tdm_sprd_init(void **data)
        tdm_sprd_display *display_data = NULL;
        hal_tdm_error ret;
        int drm_fd;
+       int timer_fd;
+       hal_tdm_event_source *timer_event_source;
 
        /* allocate a hal_tdm_backend_data */
        backend_data = calloc(1, sizeof(struct _hal_tdm_backend_data));
@@ -310,6 +328,31 @@ hal_backend_tdm_sprd_init(void **data)
                TDM_BACKEND_INFO("A backend requests an master drm_fd.\n");
        }
 
+       /* create timer fd */
+       timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
+       if (timer_fd > 0) {
+               timer_event_source = calloc(1, sizeof(struct _hal_tdm_event_source));
+               if (!timer_event_source) {
+                       TDM_BACKEND_ERR("fail to alloc udev_event_source!\n");
+                       goto failed;
+               }
+               timer_event_source->event_fd = timer_fd;
+               timer_event_source->func = _tdm_sprd_timer_fd_handler;
+               timer_event_source->user_data = display_data;
+               display_data->timer_fd = timer_fd;
+
+               backend_data->event_sources[0] = timer_event_source;
+               backend_data->num_event_sources++;
+
+               TDM_BACKEND_INFO("make timer_fd.%d\n", display_data->timer_fd);
+       } else {
+               TDM_BACKEND_ERR("fail to timerfd_create!\n");
+               display_data->timer_fd = -1;
+       }
+       ret = tdm_sprd_capture_init(display_data);
+       if (ret != HAL_TDM_ERROR_NONE)
+               goto failed;
+
        /* alloc and register display_funcs */
        display_funcs = calloc(1, sizeof(struct _hal_tdm_display_funcs));
        if (!display_funcs) {
index 0f16e63..044c629 100644 (file)
@@ -134,6 +134,11 @@ hal_tdm_error   tdm_sprd_pp_get_capability(tdm_sprd_display *display_data, hal_t
 hal_tdm_pp     *tdm_sprd_pp_create(tdm_sprd_display *display_data, hal_tdm_error *error);
 void            tdm_sprd_pp_handler(struct drm_sprd_ipp_event *hw_ipp_p);
 
+/* sprd capture */
+hal_tdm_error   tdm_sprd_capture_init(tdm_sprd_display *display_data);
+void            tdm_sprd_capture_deinit(tdm_sprd_display *display_data);
+void            tdm_sprd_capture_timer_cb(tdm_sprd_display *display_data);
+
 /* sprd buffer */
 tdm_sprd_display_buffer *tdm_sprd_display_buffer_create(tdm_sprd_display *display_data, tbm_surface_h surface, hal_tdm_error *err);
 tdm_sprd_display_buffer *tdm_sprd_display_buffer_find(tdm_sprd_display *display_data, tbm_surface_h buffer);
index 4ef1fc4..b1a888c 100644 (file)
@@ -41,6 +41,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/timerfd.h>
 #include <fcntl.h>
 #include <drm.h>
 #include <drm_fourcc.h>
@@ -112,6 +113,7 @@ struct _tdm_sprd_display {
        drmEventContext evctx;
 
        int drm_fd;
+       int timer_fd;
        int output_count;
 
        struct list_head output_list;
index 2d660c8..0017fb9 100644 (file)
@@ -72,16 +72,21 @@ typedef struct _tdm_sprd_capture_data {
        struct list_head pending_buffer_list;
        struct list_head pp_convert_list;
        struct list_head composite_list;
-#if 0
-       struct {
-               tdm_event_loop_source *timer_source;
-       } stream;
-#endif
+
        hal_tdm_capture_done_handler done_func;
        void *done_user_data;
        struct list_head link;
 } tdm_sprd_capture_data;
 
+typedef struct _tdm_sprd_capture_internal {
+       tdm_sprd_capture_data *stream_data;
+       int timer_fd;
+       int removing;
+       int timer_running;
+} tdm_sprd_capture_internal;
+
+static tdm_sprd_capture_internal *g_capture_data;
+
 static tbm_format capture_client_formats[] = {
        TBM_FORMAT_XRGB8888,
        TBM_FORMAT_ARGB8888,
@@ -827,6 +832,49 @@ fail:
        return tdm_err;
 }
 
+static hal_tdm_error
+_tdm_sprd_capture_set_timer(tdm_sprd_capture_data *capture_data)
+{
+       struct itimerspec timeout;
+       int ret = 0;
+
+       timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
+       timeout.it_value.tv_nsec = 30000000;
+       timeout.it_interval.tv_nsec = 30000000; /* 30ms interval */
+//     timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = (1000000000.0 / capture_data->info.frequency) + 1000000;
+
+       ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
+       if (ret) {
+               TDM_BACKEND_ERR("timerfd_settime fail : %d", errno);
+               return HAL_TDM_ERROR_OPERATION_FAILED;
+       }
+
+       TDM_BACKEND_DBG("set timer %llu", timeout.it_interval.tv_nsec);
+
+       return HAL_TDM_ERROR_NONE;
+}
+
+static hal_tdm_error
+_tdm_sprd_capture_stop_timer(void)
+{
+       struct itimerspec timeout;
+       int ret = 0;
+
+       timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
+       timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = 0;
+
+       ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
+       if (ret) {
+               TDM_BACKEND_ERR("timerfd_settime stop fail : %d", errno);
+               return HAL_TDM_ERROR_OPERATION_FAILED;
+       }
+
+       TDM_BACKEND_DBG("stop timer");
+
+       return HAL_TDM_ERROR_NONE;
+}
+
+
 void
 sprd_capture_destroy(hal_tdm_capture *capture)
 {
@@ -877,76 +925,54 @@ sprd_capture_destroy(hal_tdm_capture *capture)
                }
                free(b);
        }
-#if 0
-       if (capture_data->stream.timer_source) {
-               TDM_BACKEND_DBG("capture %p removing postponed", capture_data);
-               return;
+
+       if (g_capture_data->stream_data == capture_data) {
+               if (g_capture_data->timer_running == 1) {
+                       TDM_BACKEND_DBG("capture %p removing postponed", capture_data);
+                       return;
+               }
+               g_capture_data->stream_data = NULL;
+               g_capture_data->timer_running = 0;
+               _tdm_sprd_capture_stop_timer();
        }
-#endif
+
        LIST_DEL(&capture_data->link);
        capture_data->stamp = 0;
        tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
        free(capture_data);
 }
-#if 0
+
 static hal_tdm_error
-_tdm_sprd_capture_stream_timer_handler(void *user_data)
+_tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
 {
-       tdm_sprd_capture_data *capture_data = user_data;
-       if (!_tdm_sprd_capture_check_struct(user_data)) {
-               return HAL_TDM_ERROR_NONE;
-       }
+       hal_tdm_error ret;
 
-       if (capture_data->removing) {
-               TDM_BACKEND_DBG("Capture %p Postponded removing", capture_data);
-               tdm_event_loop_source_remove(capture_data->stream.timer_source);
-               LIST_DEL(&capture_data->link);
-               capture_data->stamp = 0;
-               tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
-               free(capture_data);
-               return HAL_TDM_ERROR_NONE;
+       if (g_capture_data->timer_fd == -1) {
+               TDM_BACKEND_ERR("cannot support stream capture");
+               return HAL_TDM_ERROR_BAD_REQUEST;
        }
-       unsigned int ms = 1000 / capture_data->info.frequency;
-       tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
-       tbm_surface_h current_buffer = NULL;
-       hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
-       if (!capture_data->stream.timer_source) {
-               TDM_BACKEND_ERR("Timer removed");
-               return HAL_TDM_ERROR_NONE;
+
+       if ((g_capture_data->stream_data != NULL) && (g_capture_data->stream_data != capture_data)) {
+               TDM_BACKEND_ERR("previous stream capture is working. cannot execute.");
+               return HAL_TDM_ERROR_BUSY;
        }
-       tdm_event_loop_source_timer_update(capture_data->stream.timer_source, ms);
-       if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
-               TDM_BACKEND_DBG("Converter is busy");
+
+       if (g_capture_data->timer_running) {
+               TDM_BACKEND_DBG("stream capture is working");
                return HAL_TDM_ERROR_NONE;
        }
-       LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
-               LIST_DEL(&b->link);
-               current_buffer = tbm_surface_internal_ref(b->buffer);
-               free(b);
-               tdm_err = _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
-               tbm_surface_internal_unref(current_buffer);
-               break;
+
+       ret = _tdm_sprd_capture_set_timer(capture_data);
+       if (ret != HAL_TDM_ERROR_NONE) {
+               TDM_BACKEND_ERR("timerfd_settime fail: %d", ret);
+               return HAL_TDM_ERROR_OPERATION_FAILED;
        }
-       return tdm_err;
-}
-#endif
 
-static hal_tdm_error
-_tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
-{
-#if 0
-       unsigned int ms = 1000 / capture_data->info.frequency;
+       g_capture_data->timer_running = 1;
+       g_capture_data->stream_data = capture_data;
 
-       if (!capture_data->stream.timer_source) {
-               capture_data->stream.timer_source =
-                       tdm_event_loop_add_timer_handler(capture_data->display_data->dpy,
-                                                                                        _tdm_sprd_capture_stream_timer_handler,
-                                                                                        capture_data, NULL);
-                       TDM_BACKEND_RETURN_VAL_IF_FAIL(capture_data->stream.timer_source != NULL, HAL_TDM_ERROR_OUT_OF_MEMORY);
-       }
+       TDM_BACKEND_INFO("stream capture start");
 
-       tdm_event_loop_source_timer_update(capture_data->stream.timer_source, ms);
-#endif
        return HAL_TDM_ERROR_NONE;
 }
 
@@ -975,15 +1001,19 @@ hal_tdm_error
 sprd_display_get_capture_capability(hal_tdm_display *display, hal_tdm_caps_capture *caps)
 {
        int i;
+       tdm_sprd_display *display_data = NULL;
 
        if (!caps || !display) {
                TDM_BACKEND_ERR("invalid params");
                return HAL_TDM_ERROR_INVALID_PARAMETER;
        }
 
+       display_data = (tdm_sprd_display *)display;
+
        caps->capabilities = HAL_TDM_CAPTURE_CAPABILITY_OUTPUT|
                                                 HAL_TDM_CAPTURE_CAPABILITY_ONESHOT;
-//                                              HAL_TDM_CAPTURE_CAPABILITY_STREAM;
+       if (display_data->timer_fd != -1)
+               caps->capabilities |= HAL_TDM_CAPTURE_CAPABILITY_STREAM;
 
        caps->format_count = NUM_CAPTURE_FORMAT;
        caps->formats = NULL;
@@ -1143,3 +1173,74 @@ sprd_capture_set_done_handler(hal_tdm_capture *capture, hal_tdm_capture_done_han
        TDM_BACKEND_DBG("capture %p set done handler func %p", capture, func);
        return HAL_TDM_ERROR_NONE;
 }
+
+hal_tdm_error
+tdm_sprd_capture_init(tdm_sprd_display *display_data)
+{
+       tdm_sprd_capture_internal *capture_data_internal = calloc(1, sizeof(tdm_sprd_capture_internal));
+       if (!capture_data_internal) {
+               TDM_BACKEND_ERR("alloc failed");
+
+               return HAL_TDM_ERROR_OUT_OF_MEMORY;
+       }
+       capture_data_internal->timer_fd = display_data->timer_fd;
+
+       g_capture_data = capture_data_internal;
+
+       return HAL_TDM_ERROR_NONE;
+}
+
+void
+tdm_sprd_capture_deinit(tdm_sprd_display *display_data)
+{
+       if (g_capture_data == NULL)
+               return;
+
+       free(g_capture_data);
+       g_capture_data = NULL;
+}
+
+void
+tdm_sprd_capture_timer_cb(tdm_sprd_display *display_data)
+{
+       tdm_sprd_capture_data *capture_data = NULL;
+       tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
+       tbm_surface_h current_buffer = NULL;
+       uint64_t buf;
+       int expired = read(display_data->timer_fd, &buf, sizeof(uint64_t));
+       if (expired < 0)
+               TDM_BACKEND_ERR("read fail");
+
+       if (g_capture_data == NULL || g_capture_data->stream_data == NULL)
+               return;
+
+       capture_data = g_capture_data->stream_data;
+       if (!_tdm_sprd_capture_check_struct(capture_data))
+               return;
+
+       if (capture_data->removing) {
+               TDM_BACKEND_INFO("Capture %p Postponded removing", capture_data);
+               _tdm_sprd_capture_stop_timer();
+               g_capture_data->timer_running = 0;
+               g_capture_data->stream_data = NULL;
+               LIST_DEL(&capture_data->link);
+               capture_data->stamp = 0;
+               tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
+               free(capture_data);
+               return;
+       }
+
+       if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
+               TDM_BACKEND_DBG("Converter is busy");
+               return;
+       }
+       LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
+               LIST_DEL(&b->link);
+               current_buffer = b->buffer;
+               tbm_surface_internal_ref(current_buffer);
+               free(b);
+               _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
+               tbm_surface_internal_unref(current_buffer);
+               break;
+       }
+}