f_perms.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) 2013 Clément Bœsch
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/lfg.h"
  21. #include "libavutil/opt.h"
  22. #include "libavutil/random_seed.h"
  23. #include "audio.h"
  24. #include "video.h"
  25. enum mode {
  26. MODE_NONE,
  27. MODE_RO,
  28. MODE_RW,
  29. MODE_TOGGLE,
  30. MODE_RANDOM,
  31. NB_MODES
  32. };
  33. typedef struct {
  34. const AVClass *class;
  35. AVLFG lfg;
  36. int64_t random_seed;
  37. enum mode mode;
  38. } PermsContext;
  39. #define OFFSET(x) offsetof(PermsContext, x)
  40. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
  41. static const AVOption options[] = {
  42. { "mode", "select permissions mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_NONE}, MODE_NONE, NB_MODES-1, FLAGS, "mode" },
  43. { "none", "do nothing", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_NONE}, INT_MIN, INT_MAX, FLAGS, "mode" },
  44. { "ro", "set all output frames read-only", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RO}, INT_MIN, INT_MAX, FLAGS, "mode" },
  45. { "rw", "set all output frames writable", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RW}, INT_MIN, INT_MAX, FLAGS, "mode" },
  46. { "toggle", "switch permissions", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TOGGLE}, INT_MIN, INT_MAX, FLAGS, "mode" },
  47. { "random", "set permissions randomly", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RANDOM}, INT_MIN, INT_MAX, FLAGS, "mode" },
  48. { "seed", "set the seed for the random mode", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS },
  49. { NULL }
  50. };
  51. static av_cold int init(AVFilterContext *ctx)
  52. {
  53. PermsContext *perms = ctx->priv;
  54. if (perms->mode == MODE_RANDOM) {
  55. uint32_t seed;
  56. if (perms->random_seed == -1)
  57. perms->random_seed = av_get_random_seed();
  58. seed = perms->random_seed;
  59. av_log(ctx, AV_LOG_INFO, "random seed: 0x%08x\n", seed);
  60. av_lfg_init(&perms->lfg, seed);
  61. }
  62. return 0;
  63. }
  64. enum perm { RO, RW };
  65. static const char * const perm_str[2] = { "RO", "RW" };
  66. static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
  67. {
  68. int ret;
  69. AVFilterContext *ctx = inlink->dst;
  70. PermsContext *perms = ctx->priv;
  71. AVFrame *out = frame;
  72. enum perm in_perm = av_frame_is_writable(frame) ? RW : RO;
  73. enum perm out_perm;
  74. switch (perms->mode) {
  75. case MODE_TOGGLE: out_perm = in_perm == RO ? RW : RO; break;
  76. case MODE_RANDOM: out_perm = av_lfg_get(&perms->lfg) & 1 ? RW : RO; break;
  77. case MODE_RO: out_perm = RO; break;
  78. case MODE_RW: out_perm = RW; break;
  79. default: out_perm = in_perm; break;
  80. }
  81. av_log(ctx, AV_LOG_VERBOSE, "%s -> %s%s\n",
  82. perm_str[in_perm], perm_str[out_perm],
  83. in_perm == out_perm ? " (no-op)" : "");
  84. if (in_perm == RO && out_perm == RW) {
  85. if ((ret = av_frame_make_writable(frame)) < 0)
  86. return ret;
  87. } else if (in_perm == RW && out_perm == RO) {
  88. out = av_frame_clone(frame);
  89. if (!out)
  90. return AVERROR(ENOMEM);
  91. }
  92. ret = ff_filter_frame(ctx->outputs[0], out);
  93. if (in_perm == RW && out_perm == RO)
  94. av_frame_free(&frame);
  95. return ret;
  96. }
  97. #if CONFIG_APERMS_FILTER
  98. #define aperms_options options
  99. AVFILTER_DEFINE_CLASS(aperms);
  100. static const AVFilterPad aperms_inputs[] = {
  101. {
  102. .name = "default",
  103. .type = AVMEDIA_TYPE_AUDIO,
  104. .filter_frame = filter_frame,
  105. },
  106. { NULL }
  107. };
  108. static const AVFilterPad aperms_outputs[] = {
  109. {
  110. .name = "default",
  111. .type = AVMEDIA_TYPE_AUDIO,
  112. },
  113. { NULL }
  114. };
  115. AVFilter ff_af_aperms = {
  116. .name = "aperms",
  117. .description = NULL_IF_CONFIG_SMALL("Set permissions for the output audio frame."),
  118. .init = init,
  119. .priv_size = sizeof(PermsContext),
  120. .inputs = aperms_inputs,
  121. .outputs = aperms_outputs,
  122. .priv_class = &aperms_class,
  123. };
  124. #endif /* CONFIG_APERMS_FILTER */
  125. #if CONFIG_PERMS_FILTER
  126. #define perms_options options
  127. AVFILTER_DEFINE_CLASS(perms);
  128. static const AVFilterPad perms_inputs[] = {
  129. {
  130. .name = "default",
  131. .type = AVMEDIA_TYPE_VIDEO,
  132. .filter_frame = filter_frame,
  133. },
  134. { NULL }
  135. };
  136. static const AVFilterPad perms_outputs[] = {
  137. {
  138. .name = "default",
  139. .type = AVMEDIA_TYPE_VIDEO,
  140. },
  141. { NULL }
  142. };
  143. AVFilter ff_vf_perms = {
  144. .name = "perms",
  145. .description = NULL_IF_CONFIG_SMALL("Set permissions for the output video frame."),
  146. .init = init,
  147. .priv_size = sizeof(PermsContext),
  148. .inputs = perms_inputs,
  149. .outputs = perms_outputs,
  150. .priv_class = &perms_class,
  151. };
  152. #endif /* CONFIG_PERMS_FILTER */