pipeline.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "pipeline.h"
  2. #include <gtk/gtk.h>
  3. #include <glib-unix.h>
  4. #include <assert.h>
  5. struct _MPPipeline {
  6. GMainContext *main_context;
  7. GMainLoop *main_loop;
  8. pthread_t thread;
  9. };
  10. static void *thread_main_loop(void *arg)
  11. {
  12. MPPipeline *pipeline = arg;
  13. g_main_loop_run(pipeline->main_loop);
  14. return NULL;
  15. }
  16. MPPipeline *mp_pipeline_new()
  17. {
  18. MPPipeline *pipeline = malloc(sizeof(MPPipeline));
  19. pipeline->main_context = g_main_context_new();
  20. pipeline->main_loop = g_main_loop_new(pipeline->main_context, false);
  21. int res = pthread_create(
  22. &pipeline->thread, NULL, thread_main_loop, pipeline);
  23. assert(res == 0);
  24. return pipeline;
  25. }
  26. struct invoke_args {
  27. MPPipeline *pipeline;
  28. MPPipelineCallback callback;
  29. };
  30. static bool invoke_impl(struct invoke_args *args)
  31. {
  32. args->callback(args->pipeline, args + 1);
  33. return false;
  34. }
  35. void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, const void *data, size_t size)
  36. {
  37. if (pthread_self() != pipeline->thread) {
  38. struct invoke_args *args = malloc(sizeof(struct invoke_args) + size);
  39. args->pipeline = pipeline;
  40. args->callback = callback;
  41. if (size > 0) {
  42. memcpy(args + 1, data, size);
  43. }
  44. g_main_context_invoke_full(
  45. pipeline->main_context,
  46. G_PRIORITY_DEFAULT,
  47. (GSourceFunc)invoke_impl,
  48. args,
  49. free);
  50. } else {
  51. callback(pipeline, data);
  52. }
  53. }
  54. void mp_pipeline_free(MPPipeline *pipeline)
  55. {
  56. g_main_loop_quit(pipeline->main_loop);
  57. // Force the main thread loop to wake up, otherwise we might not exit
  58. g_main_context_wakeup(pipeline->main_context);
  59. void *r;
  60. pthread_join(pipeline->thread, &r);
  61. free(pipeline);
  62. }
  63. struct capture_source_args
  64. {
  65. MPCamera *camera;
  66. void (*callback)(MPImage, void *);
  67. void *user_data;
  68. };
  69. static bool on_capture(int fd, GIOCondition condition, struct capture_source_args *args)
  70. {
  71. mp_camera_capture_image(args->camera, args->callback, args->user_data);
  72. return true;
  73. }
  74. // Not thread safe
  75. GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data)
  76. {
  77. int video_fd = mp_camera_get_video_fd(camera);
  78. GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN);
  79. struct capture_source_args *args = malloc(sizeof(struct capture_source_args));
  80. args->camera = camera;
  81. args->callback = callback;
  82. args->user_data = user_data;
  83. g_source_set_callback(
  84. video_source,
  85. (GSourceFunc)on_capture,
  86. args,
  87. free);
  88. g_source_attach(video_source, pipeline->main_context);
  89. return video_source;
  90. }