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.

535 lines
17KB

  1. /*
  2. * Copyright (c) 2012 Stefano Sabatini
  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. /**
  21. * @file
  22. * audio to video multimedia filter
  23. */
  24. #include "libavutil/avassert.h"
  25. #include "libavutil/channel_layout.h"
  26. #include "libavutil/opt.h"
  27. #include "libavutil/parseutils.h"
  28. #include "avfilter.h"
  29. #include "formats.h"
  30. #include "audio.h"
  31. #include "video.h"
  32. #include "internal.h"
  33. enum ShowWavesMode {
  34. MODE_POINT,
  35. MODE_LINE,
  36. MODE_P2P,
  37. MODE_CENTERED_LINE,
  38. MODE_NB,
  39. };
  40. struct frame_node {
  41. AVFrame *frame;
  42. struct frame_node *next;
  43. };
  44. typedef struct {
  45. const AVClass *class;
  46. int w, h;
  47. AVRational rate;
  48. int buf_idx;
  49. int16_t *buf_idy; /* y coordinate of previous sample for each channel */
  50. AVFrame *outpicref;
  51. int n;
  52. int sample_count_mod;
  53. int mode; ///< ShowWavesMode
  54. int split_channels;
  55. void (*draw_sample)(uint8_t *buf, int height, int linesize,
  56. int16_t sample, int16_t *prev_y, int intensity);
  57. /* single picture */
  58. int single_pic;
  59. struct frame_node *audio_frames;
  60. struct frame_node *last_frame;
  61. int64_t total_samples;
  62. int64_t *sum; /* abs sum of the samples per channel */
  63. } ShowWavesContext;
  64. #define OFFSET(x) offsetof(ShowWavesContext, x)
  65. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  66. static const AVOption showwaves_options[] = {
  67. { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
  68. { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
  69. { "mode", "select display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_POINT}, 0, MODE_NB-1, FLAGS, "mode"},
  70. { "point", "draw a point for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_POINT}, .flags=FLAGS, .unit="mode"},
  71. { "line", "draw a line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LINE}, .flags=FLAGS, .unit="mode"},
  72. { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"},
  73. { "cline", "draw a centered line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CENTERED_LINE}, .flags=FLAGS, .unit="mode"},
  74. { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },
  75. { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
  76. { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
  77. { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
  78. { NULL }
  79. };
  80. AVFILTER_DEFINE_CLASS(showwaves);
  81. static av_cold void uninit(AVFilterContext *ctx)
  82. {
  83. ShowWavesContext *showwaves = ctx->priv;
  84. av_frame_free(&showwaves->outpicref);
  85. av_freep(&showwaves->buf_idy);
  86. if (showwaves->single_pic) {
  87. struct frame_node *node = showwaves->audio_frames;
  88. while (node) {
  89. struct frame_node *tmp = node;
  90. node = node->next;
  91. av_frame_free(&tmp->frame);
  92. av_freep(&tmp);
  93. }
  94. av_freep(&showwaves->sum);
  95. showwaves->last_frame = NULL;
  96. }
  97. }
  98. static int query_formats(AVFilterContext *ctx)
  99. {
  100. AVFilterFormats *formats = NULL;
  101. AVFilterChannelLayouts *layouts = NULL;
  102. AVFilterLink *inlink = ctx->inputs[0];
  103. AVFilterLink *outlink = ctx->outputs[0];
  104. static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
  105. static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
  106. /* set input audio formats */
  107. formats = ff_make_format_list(sample_fmts);
  108. if (!formats)
  109. return AVERROR(ENOMEM);
  110. ff_formats_ref(formats, &inlink->out_formats);
  111. layouts = ff_all_channel_layouts();
  112. if (!layouts)
  113. return AVERROR(ENOMEM);
  114. ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
  115. formats = ff_all_samplerates();
  116. if (!formats)
  117. return AVERROR(ENOMEM);
  118. ff_formats_ref(formats, &inlink->out_samplerates);
  119. /* set output video format */
  120. formats = ff_make_format_list(pix_fmts);
  121. if (!formats)
  122. return AVERROR(ENOMEM);
  123. ff_formats_ref(formats, &outlink->in_formats);
  124. return 0;
  125. }
  126. static int config_output(AVFilterLink *outlink)
  127. {
  128. AVFilterContext *ctx = outlink->src;
  129. AVFilterLink *inlink = ctx->inputs[0];
  130. ShowWavesContext *showwaves = ctx->priv;
  131. int nb_channels = inlink->channels;
  132. if (!showwaves->n)
  133. showwaves->n = FFMAX(1, ((double)inlink->sample_rate / (showwaves->w * av_q2d(showwaves->rate))) + 0.5);
  134. showwaves->buf_idx = 0;
  135. if (!(showwaves->buf_idy = av_mallocz_array(nb_channels, sizeof(*showwaves->buf_idy)))) {
  136. av_log(ctx, AV_LOG_ERROR, "Could not allocate showwaves buffer\n");
  137. return AVERROR(ENOMEM);
  138. }
  139. outlink->w = showwaves->w;
  140. outlink->h = showwaves->h;
  141. outlink->sample_aspect_ratio = (AVRational){1,1};
  142. outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n},
  143. (AVRational){showwaves->w,1});
  144. av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n",
  145. showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n);
  146. return 0;
  147. }
  148. inline static int push_frame(AVFilterLink *outlink)
  149. {
  150. AVFilterContext *ctx = outlink->src;
  151. AVFilterLink *inlink = ctx->inputs[0];
  152. ShowWavesContext *showwaves = outlink->src->priv;
  153. int nb_channels = inlink->channels;
  154. int ret, i;
  155. ret = ff_filter_frame(outlink, showwaves->outpicref);
  156. showwaves->outpicref = NULL;
  157. showwaves->buf_idx = 0;
  158. for (i = 0; i < nb_channels; i++)
  159. showwaves->buf_idy[i] = 0;
  160. return ret;
  161. }
  162. static int push_single_pic(AVFilterLink *outlink)
  163. {
  164. AVFilterContext *ctx = outlink->src;
  165. AVFilterLink *inlink = ctx->inputs[0];
  166. ShowWavesContext *showwaves = ctx->priv;
  167. int64_t n = 0, max_samples = showwaves->total_samples / outlink->w;
  168. AVFrame *out = showwaves->outpicref;
  169. struct frame_node *node;
  170. const int nb_channels = inlink->channels;
  171. const int x = 255 / (showwaves->split_channels ? 1 : nb_channels);
  172. const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h;
  173. const int linesize = out->linesize[0];
  174. int col = 0;
  175. int64_t *sum = showwaves->sum;
  176. if (max_samples == 0) {
  177. av_log(ctx, AV_LOG_ERROR, "Too few samples\n");
  178. return AVERROR(EINVAL);
  179. }
  180. av_log(ctx, AV_LOG_DEBUG, "Create frame averaging %"PRId64" samples per column\n", max_samples);
  181. memset(sum, 0, nb_channels);
  182. for (node = showwaves->audio_frames; node; node = node->next) {
  183. int i;
  184. const AVFrame *frame = node->frame;
  185. const int16_t *p = (const int16_t *)frame->data[0];
  186. for (i = 0; i < frame->nb_samples; i++) {
  187. int ch;
  188. for (ch = 0; ch < nb_channels; ch++)
  189. sum[ch] += abs(p[ch + i*nb_channels]) << 1;
  190. if (n++ == max_samples) {
  191. for (ch = 0; ch < nb_channels; ch++) {
  192. int16_t sample = sum[ch] / max_samples;
  193. uint8_t *buf = out->data[0] + col;
  194. if (showwaves->split_channels)
  195. buf += ch*ch_height*linesize;
  196. av_assert0(col < outlink->w);
  197. showwaves->draw_sample(buf, ch_height, linesize, sample, &showwaves->buf_idy[ch], x);
  198. sum[ch] = 0;
  199. }
  200. col++;
  201. n = 0;
  202. }
  203. }
  204. }
  205. return push_frame(outlink);
  206. }
  207. static int request_frame(AVFilterLink *outlink)
  208. {
  209. ShowWavesContext *showwaves = outlink->src->priv;
  210. AVFilterLink *inlink = outlink->src->inputs[0];
  211. int ret;
  212. ret = ff_request_frame(inlink);
  213. if (ret == AVERROR_EOF && showwaves->outpicref) {
  214. if (showwaves->single_pic)
  215. push_single_pic(outlink);
  216. else
  217. push_frame(outlink);
  218. }
  219. return ret;
  220. }
  221. static void draw_sample_point(uint8_t *buf, int height, int linesize,
  222. int16_t sample, int16_t *prev_y, int intensity)
  223. {
  224. const int h = height/2 - av_rescale(sample, height/2, INT16_MAX);
  225. if (h >= 0 && h < height)
  226. buf[h * linesize] += intensity;
  227. }
  228. static void draw_sample_line(uint8_t *buf, int height, int linesize,
  229. int16_t sample, int16_t *prev_y, int intensity)
  230. {
  231. int k;
  232. const int h = height/2 - av_rescale(sample, height/2, INT16_MAX);
  233. int start = height/2;
  234. int end = av_clip(h, 0, height-1);
  235. if (start > end)
  236. FFSWAP(int16_t, start, end);
  237. for (k = start; k < end; k++)
  238. buf[k * linesize] += intensity;
  239. }
  240. static void draw_sample_p2p(uint8_t *buf, int height, int linesize,
  241. int16_t sample, int16_t *prev_y, int intensity)
  242. {
  243. int k;
  244. const int h = height/2 - av_rescale(sample, height/2, INT16_MAX);
  245. if (h >= 0 && h < height) {
  246. buf[h * linesize] += intensity;
  247. if (*prev_y && h != *prev_y) {
  248. int start = *prev_y;
  249. int end = av_clip(h, 0, height-1);
  250. if (start > end)
  251. FFSWAP(int16_t, start, end);
  252. for (k = start + 1; k < end; k++)
  253. buf[k * linesize] += intensity;
  254. }
  255. }
  256. *prev_y = h;
  257. }
  258. static void draw_sample_cline(uint8_t *buf, int height, int linesize,
  259. int16_t sample, int16_t *prev_y, int intensity)
  260. {
  261. int k;
  262. const int h = av_rescale(abs(sample), height, INT16_MAX);
  263. const int start = (height - h) / 2;
  264. const int end = start + h;
  265. for (k = start; k < end; k++)
  266. buf[k * linesize] += intensity;
  267. }
  268. static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p,
  269. const AVFilterLink *inlink, AVFilterLink *outlink,
  270. const AVFrame *in)
  271. {
  272. if (!showwaves->outpicref) {
  273. int j;
  274. AVFrame *out = showwaves->outpicref =
  275. ff_get_video_buffer(outlink, outlink->w, outlink->h);
  276. if (!out)
  277. return AVERROR(ENOMEM);
  278. out->width = outlink->w;
  279. out->height = outlink->h;
  280. out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->channels,
  281. av_make_q(1, inlink->sample_rate),
  282. outlink->time_base);
  283. for (j = 0; j < outlink->h; j++)
  284. memset(out->data[0] + j*out->linesize[0], 0, outlink->w);
  285. }
  286. return 0;
  287. }
  288. static av_cold int init(AVFilterContext *ctx)
  289. {
  290. ShowWavesContext *showwaves = ctx->priv;
  291. if (!strcmp(ctx->filter->name, "showwavespic")) {
  292. showwaves->single_pic = 1;
  293. showwaves->mode = MODE_CENTERED_LINE;
  294. }
  295. switch (showwaves->mode) {
  296. case MODE_POINT: showwaves->draw_sample = draw_sample_point; break;
  297. case MODE_LINE: showwaves->draw_sample = draw_sample_line; break;
  298. case MODE_P2P: showwaves->draw_sample = draw_sample_p2p; break;
  299. case MODE_CENTERED_LINE: showwaves->draw_sample = draw_sample_cline; break;
  300. default:
  301. return AVERROR_BUG;
  302. }
  303. return 0;
  304. }
  305. #if CONFIG_SHOWWAVES_FILTER
  306. static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples)
  307. {
  308. AVFilterContext *ctx = inlink->dst;
  309. AVFilterLink *outlink = ctx->outputs[0];
  310. ShowWavesContext *showwaves = ctx->priv;
  311. const int nb_samples = insamples->nb_samples;
  312. AVFrame *outpicref = showwaves->outpicref;
  313. int16_t *p = (int16_t *)insamples->data[0];
  314. int nb_channels = inlink->channels;
  315. int i, j, ret = 0;
  316. const int n = showwaves->n;
  317. const int x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * n); /* multiplication factor, pre-computed to avoid in-loop divisions */
  318. const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h;
  319. /* draw data in the buffer */
  320. for (i = 0; i < nb_samples; i++) {
  321. ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples);
  322. if (ret < 0)
  323. goto end;
  324. outpicref = showwaves->outpicref;
  325. for (j = 0; j < nb_channels; j++) {
  326. uint8_t *buf = outpicref->data[0] + showwaves->buf_idx;
  327. const int linesize = outpicref->linesize[0];
  328. if (showwaves->split_channels)
  329. buf += j*ch_height*linesize;
  330. showwaves->draw_sample(buf, ch_height, linesize, *p++,
  331. &showwaves->buf_idy[j], x);
  332. }
  333. showwaves->sample_count_mod++;
  334. if (showwaves->sample_count_mod == n) {
  335. showwaves->sample_count_mod = 0;
  336. showwaves->buf_idx++;
  337. }
  338. if (showwaves->buf_idx == showwaves->w)
  339. if ((ret = push_frame(outlink)) < 0)
  340. break;
  341. outpicref = showwaves->outpicref;
  342. }
  343. end:
  344. av_frame_free(&insamples);
  345. return ret;
  346. }
  347. static const AVFilterPad showwaves_inputs[] = {
  348. {
  349. .name = "default",
  350. .type = AVMEDIA_TYPE_AUDIO,
  351. .filter_frame = showwaves_filter_frame,
  352. },
  353. { NULL }
  354. };
  355. static const AVFilterPad showwaves_outputs[] = {
  356. {
  357. .name = "default",
  358. .type = AVMEDIA_TYPE_VIDEO,
  359. .config_props = config_output,
  360. .request_frame = request_frame,
  361. },
  362. { NULL }
  363. };
  364. AVFilter ff_avf_showwaves = {
  365. .name = "showwaves",
  366. .description = NULL_IF_CONFIG_SMALL("Convert input audio to a video output."),
  367. .init = init,
  368. .uninit = uninit,
  369. .query_formats = query_formats,
  370. .priv_size = sizeof(ShowWavesContext),
  371. .inputs = showwaves_inputs,
  372. .outputs = showwaves_outputs,
  373. .priv_class = &showwaves_class,
  374. };
  375. #endif // CONFIG_SHOWWAVES_FILTER
  376. #if CONFIG_SHOWWAVESPIC_FILTER
  377. #define OFFSET(x) offsetof(ShowWavesContext, x)
  378. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  379. static const AVOption showwavespic_options[] = {
  380. { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
  381. { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
  382. { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
  383. { NULL }
  384. };
  385. AVFILTER_DEFINE_CLASS(showwavespic);
  386. static int showwavespic_config_input(AVFilterLink *inlink)
  387. {
  388. AVFilterContext *ctx = inlink->dst;
  389. ShowWavesContext *showwaves = ctx->priv;
  390. if (showwaves->single_pic) {
  391. showwaves->sum = av_mallocz_array(inlink->channels, sizeof(*showwaves->sum));
  392. if (!showwaves->sum)
  393. return AVERROR(ENOMEM);
  394. }
  395. return 0;
  396. }
  397. static int showwavespic_filter_frame(AVFilterLink *inlink, AVFrame *insamples)
  398. {
  399. AVFilterContext *ctx = inlink->dst;
  400. AVFilterLink *outlink = ctx->outputs[0];
  401. ShowWavesContext *showwaves = ctx->priv;
  402. int16_t *p = (int16_t *)insamples->data[0];
  403. int ret = 0;
  404. if (showwaves->single_pic) {
  405. struct frame_node *f;
  406. ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples);
  407. if (ret < 0)
  408. goto end;
  409. /* queue the audio frame */
  410. f = av_malloc(sizeof(*f));
  411. if (!f) {
  412. ret = AVERROR(ENOMEM);
  413. goto end;
  414. }
  415. f->frame = insamples;
  416. f->next = NULL;
  417. if (!showwaves->last_frame) {
  418. showwaves->audio_frames =
  419. showwaves->last_frame = f;
  420. } else {
  421. showwaves->last_frame->next = f;
  422. showwaves->last_frame = f;
  423. }
  424. showwaves->total_samples += insamples->nb_samples;
  425. return 0;
  426. }
  427. end:
  428. av_frame_free(&insamples);
  429. return ret;
  430. }
  431. static const AVFilterPad showwavespic_inputs[] = {
  432. {
  433. .name = "default",
  434. .type = AVMEDIA_TYPE_AUDIO,
  435. .config_props = showwavespic_config_input,
  436. .filter_frame = showwavespic_filter_frame,
  437. },
  438. { NULL }
  439. };
  440. static const AVFilterPad showwavespic_outputs[] = {
  441. {
  442. .name = "default",
  443. .type = AVMEDIA_TYPE_VIDEO,
  444. .config_props = config_output,
  445. .request_frame = request_frame,
  446. },
  447. { NULL }
  448. };
  449. AVFilter ff_avf_showwavespic = {
  450. .name = "showwavespic",
  451. .description = NULL_IF_CONFIG_SMALL("Convert input audio to a video output single picture."),
  452. .init = init,
  453. .uninit = uninit,
  454. .query_formats = query_formats,
  455. .priv_size = sizeof(ShowWavesContext),
  456. .inputs = showwavespic_inputs,
  457. .outputs = showwavespic_outputs,
  458. .priv_class = &showwavespic_class,
  459. };
  460. #endif // CONFIG_SHOWWAVESPIC_FILTER