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.

210 lines
6.5KB

  1. /*
  2. * Copyright (c) 2011 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. * buffer sink
  23. */
  24. #include "libavutil/audio_fifo.h"
  25. #include "libavutil/audioconvert.h"
  26. #include "libavutil/fifo.h"
  27. #include "libavutil/mathematics.h"
  28. #include "audio.h"
  29. #include "avfilter.h"
  30. #include "buffersink.h"
  31. #include "internal.h"
  32. typedef struct {
  33. AVFifoBuffer *fifo; ///< FIFO buffer of frame references
  34. AVAudioFifo *audio_fifo; ///< FIFO for audio samples
  35. int64_t next_pts; ///< interpolating audio pts
  36. } BufferSinkContext;
  37. #define FIFO_INIT_SIZE 8
  38. static av_cold void uninit(AVFilterContext *ctx)
  39. {
  40. BufferSinkContext *sink = ctx->priv;
  41. while (sink->fifo && av_fifo_size(sink->fifo)) {
  42. AVFilterBufferRef *buf;
  43. av_fifo_generic_read(sink->fifo, &buf, sizeof(buf), NULL);
  44. avfilter_unref_buffer(buf);
  45. }
  46. av_fifo_free(sink->fifo);
  47. if (sink->audio_fifo)
  48. av_audio_fifo_free(sink->audio_fifo);
  49. }
  50. static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
  51. {
  52. BufferSinkContext *sink = ctx->priv;
  53. if (!(sink->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef*)))) {
  54. av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
  55. return AVERROR(ENOMEM);
  56. }
  57. return 0;
  58. }
  59. static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
  60. {
  61. BufferSinkContext *sink = ctx->priv;
  62. if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
  63. (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) {
  64. av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n");
  65. return;
  66. }
  67. av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);
  68. }
  69. static void end_frame(AVFilterLink *link)
  70. {
  71. write_buf(link->dst, link->cur_buf);
  72. link->cur_buf = NULL;
  73. }
  74. static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
  75. {
  76. write_buf(link->dst, buf);
  77. }
  78. int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
  79. {
  80. BufferSinkContext *sink = ctx->priv;
  81. AVFilterLink *link = ctx->inputs[0];
  82. int ret;
  83. if (!buf) {
  84. if (av_fifo_size(sink->fifo))
  85. return av_fifo_size(sink->fifo)/sizeof(*buf);
  86. else
  87. return ff_poll_frame(ctx->inputs[0]);
  88. }
  89. if (!av_fifo_size(sink->fifo) &&
  90. (ret = ff_request_frame(link)) < 0)
  91. return ret;
  92. if (!av_fifo_size(sink->fifo))
  93. return AVERROR(EINVAL);
  94. av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL);
  95. return 0;
  96. }
  97. static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
  98. int nb_samples)
  99. {
  100. BufferSinkContext *s = ctx->priv;
  101. AVFilterLink *link = ctx->inputs[0];
  102. AVFilterBufferRef *buf;
  103. if (!(buf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples)))
  104. return AVERROR(ENOMEM);
  105. av_audio_fifo_read(s->audio_fifo, (void**)buf->extended_data, nb_samples);
  106. buf->pts = s->next_pts;
  107. s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate},
  108. link->time_base);
  109. *pbuf = buf;
  110. return 0;
  111. }
  112. int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
  113. int nb_samples)
  114. {
  115. BufferSinkContext *s = ctx->priv;
  116. AVFilterLink *link = ctx->inputs[0];
  117. int ret = 0;
  118. if (!s->audio_fifo) {
  119. int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
  120. if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
  121. return AVERROR(ENOMEM);
  122. }
  123. while (ret >= 0) {
  124. AVFilterBufferRef *buf;
  125. if (av_audio_fifo_size(s->audio_fifo) >= nb_samples)
  126. return read_from_fifo(ctx, pbuf, nb_samples);
  127. ret = av_buffersink_read(ctx, &buf);
  128. if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo))
  129. return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo));
  130. else if (ret < 0)
  131. return ret;
  132. if (buf->pts != AV_NOPTS_VALUE) {
  133. s->next_pts = buf->pts -
  134. av_rescale_q(av_audio_fifo_size(s->audio_fifo),
  135. (AVRational){ 1, link->sample_rate },
  136. link->time_base);
  137. }
  138. ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data,
  139. buf->audio->nb_samples);
  140. avfilter_unref_buffer(buf);
  141. }
  142. return ret;
  143. }
  144. AVFilter avfilter_vsink_buffer = {
  145. .name = "buffersink_old",
  146. .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
  147. .priv_size = sizeof(BufferSinkContext),
  148. .init = init,
  149. .uninit = uninit,
  150. .inputs = (AVFilterPad[]) {{ .name = "default",
  151. .type = AVMEDIA_TYPE_VIDEO,
  152. .end_frame = end_frame,
  153. .min_perms = AV_PERM_READ, },
  154. { .name = NULL }},
  155. .outputs = (AVFilterPad[]) {{ .name = NULL }},
  156. };
  157. AVFilter avfilter_asink_abuffer = {
  158. .name = "abuffersink_old",
  159. .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
  160. .priv_size = sizeof(BufferSinkContext),
  161. .init = init,
  162. .uninit = uninit,
  163. .inputs = (AVFilterPad[]) {{ .name = "default",
  164. .type = AVMEDIA_TYPE_AUDIO,
  165. .filter_samples = filter_samples,
  166. .min_perms = AV_PERM_READ, },
  167. { .name = NULL }},
  168. .outputs = (AVFilterPad[]) {{ .name = NULL }},
  169. };