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.

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