Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Copyright (c) Stefano Sabatini | stefasab at gmail.com | |
3 | * Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu | |
4 | * | |
5 | * This file is part of FFmpeg. | |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * FFmpeg is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with FFmpeg; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #include "libavutil/avassert.h" | |
23 | #include "libavutil/channel_layout.h" | |
24 | #include "libavutil/common.h" | |
25 | #include "libavcodec/avcodec.h" | |
26 | ||
27 | #include "audio.h" | |
28 | #include "avfilter.h" | |
29 | #include "internal.h" | |
30 | ||
31 | int avfilter_ref_get_channels(AVFilterBufferRef *ref) | |
32 | { | |
33 | return ref->audio ? ref->audio->channels : 0; | |
34 | } | |
35 | ||
36 | AVFrame *ff_null_get_audio_buffer(AVFilterLink *link, int nb_samples) | |
37 | { | |
38 | return ff_get_audio_buffer(link->dst->outputs[0], nb_samples); | |
39 | } | |
40 | ||
41 | AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples) | |
42 | { | |
43 | AVFrame *frame = av_frame_alloc(); | |
44 | int channels = link->channels; | |
45 | int ret; | |
46 | ||
47 | av_assert0(channels == av_get_channel_layout_nb_channels(link->channel_layout) || !av_get_channel_layout_nb_channels(link->channel_layout)); | |
48 | ||
49 | if (!frame) | |
50 | return NULL; | |
51 | ||
52 | frame->nb_samples = nb_samples; | |
53 | frame->format = link->format; | |
54 | av_frame_set_channels(frame, link->channels); | |
55 | frame->channel_layout = link->channel_layout; | |
56 | frame->sample_rate = link->sample_rate; | |
57 | ret = av_frame_get_buffer(frame, 0); | |
58 | if (ret < 0) { | |
59 | av_frame_free(&frame); | |
60 | return NULL; | |
61 | } | |
62 | ||
63 | av_samples_set_silence(frame->extended_data, 0, nb_samples, channels, | |
64 | link->format); | |
65 | ||
66 | ||
67 | return frame; | |
68 | } | |
69 | ||
70 | AVFrame *ff_get_audio_buffer(AVFilterLink *link, int nb_samples) | |
71 | { | |
72 | AVFrame *ret = NULL; | |
73 | ||
74 | if (link->dstpad->get_audio_buffer) | |
75 | ret = link->dstpad->get_audio_buffer(link, nb_samples); | |
76 | ||
77 | if (!ret) | |
78 | ret = ff_default_get_audio_buffer(link, nb_samples); | |
79 | ||
80 | return ret; | |
81 | } | |
82 | ||
83 | #if FF_API_AVFILTERBUFFER | |
84 | AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays_channels(uint8_t **data, | |
85 | int linesize,int perms, | |
86 | int nb_samples, | |
87 | enum AVSampleFormat sample_fmt, | |
88 | int channels, | |
89 | uint64_t channel_layout) | |
90 | { | |
91 | int planes; | |
92 | AVFilterBuffer *samples = av_mallocz(sizeof(*samples)); | |
93 | AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref)); | |
94 | ||
95 | if (!samples || !samplesref) | |
96 | goto fail; | |
97 | ||
98 | av_assert0(channels); | |
99 | av_assert0(channel_layout == 0 || | |
100 | channels == av_get_channel_layout_nb_channels(channel_layout)); | |
101 | ||
102 | samplesref->buf = samples; | |
103 | samplesref->buf->free = ff_avfilter_default_free_buffer; | |
104 | if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio)))) | |
105 | goto fail; | |
106 | ||
107 | samplesref->audio->nb_samples = nb_samples; | |
108 | samplesref->audio->channel_layout = channel_layout; | |
109 | samplesref->audio->channels = channels; | |
110 | ||
111 | planes = av_sample_fmt_is_planar(sample_fmt) ? channels : 1; | |
112 | ||
113 | /* make sure the buffer gets read permission or it's useless for output */ | |
114 | samplesref->perms = perms | AV_PERM_READ; | |
115 | ||
116 | samples->refcount = 1; | |
117 | samplesref->type = AVMEDIA_TYPE_AUDIO; | |
118 | samplesref->format = sample_fmt; | |
119 | ||
120 | memcpy(samples->data, data, | |
121 | FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0])); | |
122 | memcpy(samplesref->data, samples->data, sizeof(samples->data)); | |
123 | ||
124 | samples->linesize[0] = samplesref->linesize[0] = linesize; | |
125 | ||
126 | if (planes > FF_ARRAY_ELEMS(samples->data)) { | |
127 | samples-> extended_data = av_mallocz_array(sizeof(*samples->extended_data), | |
128 | planes); | |
129 | samplesref->extended_data = av_mallocz_array(sizeof(*samplesref->extended_data), | |
130 | planes); | |
131 | ||
132 | if (!samples->extended_data || !samplesref->extended_data) | |
133 | goto fail; | |
134 | ||
135 | memcpy(samples-> extended_data, data, sizeof(*data)*planes); | |
136 | memcpy(samplesref->extended_data, data, sizeof(*data)*planes); | |
137 | } else { | |
138 | samples->extended_data = samples->data; | |
139 | samplesref->extended_data = samplesref->data; | |
140 | } | |
141 | ||
142 | samplesref->pts = AV_NOPTS_VALUE; | |
143 | ||
144 | return samplesref; | |
145 | ||
146 | fail: | |
147 | if (samples && samples->extended_data != samples->data) | |
148 | av_freep(&samples->extended_data); | |
149 | if (samplesref) { | |
150 | av_freep(&samplesref->audio); | |
151 | if (samplesref->extended_data != samplesref->data) | |
152 | av_freep(&samplesref->extended_data); | |
153 | } | |
154 | av_freep(&samplesref); | |
155 | av_freep(&samples); | |
156 | return NULL; | |
157 | } | |
158 | ||
159 | AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays(uint8_t **data, | |
160 | int linesize,int perms, | |
161 | int nb_samples, | |
162 | enum AVSampleFormat sample_fmt, | |
163 | uint64_t channel_layout) | |
164 | { | |
165 | int channels = av_get_channel_layout_nb_channels(channel_layout); | |
166 | return avfilter_get_audio_buffer_ref_from_arrays_channels(data, linesize, perms, | |
167 | nb_samples, sample_fmt, | |
168 | channels, channel_layout); | |
169 | } | |
170 | #endif |