You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.1KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /**
  19. * @file
  20. * Libavfilter multithreading support
  21. */
  22. #include "config.h"
  23. #include "libavutil/common.h"
  24. #include "libavutil/cpu.h"
  25. #include "libavutil/mem.h"
  26. #include "libavutil/thread.h"
  27. #include "libavutil/slicethread.h"
  28. #include "avfilter.h"
  29. #include "internal.h"
  30. #include "thread.h"
  31. typedef struct ThreadContext {
  32. AVFilterGraph *graph;
  33. AVSliceThread *thread;
  34. avfilter_action_func *func;
  35. /* per-execute parameters */
  36. AVFilterContext *ctx;
  37. void *arg;
  38. int *rets;
  39. } ThreadContext;
  40. static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
  41. {
  42. ThreadContext *c = priv;
  43. int ret = c->func(c->ctx, c->arg, jobnr, nb_jobs);
  44. if (c->rets)
  45. c->rets[jobnr] = ret;
  46. }
  47. static void slice_thread_uninit(ThreadContext *c)
  48. {
  49. avpriv_slicethread_free(&c->thread);
  50. }
  51. static int thread_execute(AVFilterContext *ctx, avfilter_action_func *func,
  52. void *arg, int *ret, int nb_jobs)
  53. {
  54. ThreadContext *c = ctx->graph->internal->thread;
  55. if (nb_jobs <= 0)
  56. return 0;
  57. c->ctx = ctx;
  58. c->arg = arg;
  59. c->func = func;
  60. c->rets = ret;
  61. avpriv_slicethread_execute(c->thread, nb_jobs, 0);
  62. return 0;
  63. }
  64. static int thread_init_internal(ThreadContext *c, int nb_threads)
  65. {
  66. nb_threads = avpriv_slicethread_create(&c->thread, c, worker_func, NULL, nb_threads);
  67. if (nb_threads <= 1)
  68. avpriv_slicethread_free(&c->thread);
  69. return FFMAX(nb_threads, 1);
  70. }
  71. int ff_graph_thread_init(AVFilterGraph *graph)
  72. {
  73. int ret;
  74. #if HAVE_W32THREADS
  75. w32thread_init();
  76. #endif
  77. if (graph->nb_threads == 1) {
  78. graph->thread_type = 0;
  79. return 0;
  80. }
  81. graph->internal->thread = av_mallocz(sizeof(ThreadContext));
  82. if (!graph->internal->thread)
  83. return AVERROR(ENOMEM);
  84. ret = thread_init_internal(graph->internal->thread, graph->nb_threads);
  85. if (ret <= 1) {
  86. av_freep(&graph->internal->thread);
  87. graph->thread_type = 0;
  88. graph->nb_threads = 1;
  89. return (ret < 0) ? ret : 0;
  90. }
  91. graph->nb_threads = ret;
  92. graph->internal->thread_execute = thread_execute;
  93. return 0;
  94. }
  95. void ff_graph_thread_free(AVFilterGraph *graph)
  96. {
  97. if (graph->internal->thread)
  98. slice_thread_uninit(graph->internal->thread);
  99. av_freep(&graph->internal->thread);
  100. }