pthread.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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 (graph->nb_threads == 1) {
  75. graph->thread_type = 0;
  76. return 0;
  77. }
  78. graph->internal->thread = av_mallocz(sizeof(ThreadContext));
  79. if (!graph->internal->thread)
  80. return AVERROR(ENOMEM);
  81. ret = thread_init_internal(graph->internal->thread, graph->nb_threads);
  82. if (ret <= 1) {
  83. av_freep(&graph->internal->thread);
  84. graph->thread_type = 0;
  85. graph->nb_threads = 1;
  86. return (ret < 0) ? ret : 0;
  87. }
  88. graph->nb_threads = ret;
  89. graph->internal->thread_execute = thread_execute;
  90. return 0;
  91. }
  92. void ff_graph_thread_free(AVFilterGraph *graph)
  93. {
  94. if (graph->internal->thread)
  95. slice_thread_uninit(graph->internal->thread);
  96. av_freep(&graph->internal->thread);
  97. }