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.

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