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.

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