Libav 0.7.1
|
00001 /* 00002 * Filter layer - default implementations 00003 * Copyright (c) 2007 Bobby Bingham 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/audioconvert.h" 00023 #include "libavutil/imgutils.h" 00024 #include "libavutil/samplefmt.h" 00025 #include "avfilter.h" 00026 #include "internal.h" 00027 00028 /* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */ 00029 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr) 00030 { 00031 av_free(ptr->data[0]); 00032 av_free(ptr); 00033 } 00034 00035 /* TODO: set the buffer's priv member to a context structure for the whole 00036 * filter chain. This will allow for a buffer pool instead of the constant 00037 * alloc & free cycle currently implemented. */ 00038 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 00039 { 00040 int linesize[4]; 00041 uint8_t *data[4]; 00042 AVFilterBufferRef *picref = NULL; 00043 00044 // +2 is needed for swscaler, +16 to be SIMD-friendly 00045 if (av_image_alloc(data, linesize, w, h, link->format, 16) < 0) 00046 return NULL; 00047 00048 picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize, 00049 perms, w, h, link->format); 00050 if (!picref) { 00051 av_free(data[0]); 00052 return NULL; 00053 } 00054 00055 return picref; 00056 } 00057 00058 AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms, 00059 enum AVSampleFormat sample_fmt, int size, 00060 int64_t channel_layout, int planar) 00061 { 00062 AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); 00063 AVFilterBufferRef *ref = NULL; 00064 int i, sample_size, chans_nb, bufsize, per_channel_size, step_size = 0; 00065 char *buf; 00066 00067 if (!samples || !(ref = av_mallocz(sizeof(AVFilterBufferRef)))) 00068 goto fail; 00069 00070 ref->buf = samples; 00071 ref->format = sample_fmt; 00072 00073 ref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps)); 00074 if (!ref->audio) 00075 goto fail; 00076 00077 ref->audio->channel_layout = channel_layout; 00078 ref->audio->size = size; 00079 ref->audio->planar = planar; 00080 00081 /* make sure the buffer gets read permission or it's useless for output */ 00082 ref->perms = perms | AV_PERM_READ; 00083 00084 samples->refcount = 1; 00085 samples->free = ff_avfilter_default_free_buffer; 00086 00087 sample_size = av_get_bits_per_sample_fmt(sample_fmt) >>3; 00088 chans_nb = av_get_channel_layout_nb_channels(channel_layout); 00089 00090 per_channel_size = size/chans_nb; 00091 ref->audio->nb_samples = per_channel_size/sample_size; 00092 00093 /* Set the number of bytes to traverse to reach next sample of a particular channel: 00094 * For planar, this is simply the sample size. 00095 * For packed, this is the number of samples * sample_size. 00096 */ 00097 for (i = 0; i < chans_nb; i++) 00098 samples->linesize[i] = planar > 0 ? per_channel_size : sample_size; 00099 memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->linesize[0])); 00100 00101 /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */ 00102 bufsize = (size + 15)&~15; 00103 buf = av_malloc(bufsize); 00104 if (!buf) 00105 goto fail; 00106 00107 /* For planar, set the start point of each channel's data within the buffer 00108 * For packed, set the start point of the entire buffer only 00109 */ 00110 samples->data[0] = buf; 00111 if (buf && planar) { 00112 for (i = 1; i < chans_nb; i++) { 00113 step_size += per_channel_size; 00114 samples->data[i] = buf + step_size; 00115 } 00116 } else { 00117 for (i = 1; i < chans_nb; i++) 00118 samples->data[i] = buf; 00119 } 00120 00121 memset(&samples->data[chans_nb], 0, (8-chans_nb) * sizeof(samples->data[0])); 00122 00123 memcpy(ref->data, samples->data, sizeof(ref->data)); 00124 memcpy(ref->linesize, samples->linesize, sizeof(ref->linesize)); 00125 00126 return ref; 00127 00128 fail: 00129 if (ref) 00130 av_free(ref->audio); 00131 av_free(ref); 00132 av_free(samples); 00133 return NULL; 00134 } 00135 00136 void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) 00137 { 00138 AVFilterLink *outlink = NULL; 00139 00140 if (inlink->dst->output_count) 00141 outlink = inlink->dst->outputs[0]; 00142 00143 if (outlink) { 00144 outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); 00145 avfilter_copy_buffer_ref_props(outlink->out_buf, picref); 00146 avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0)); 00147 } 00148 } 00149 00150 void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) 00151 { 00152 AVFilterLink *outlink = NULL; 00153 00154 if (inlink->dst->output_count) 00155 outlink = inlink->dst->outputs[0]; 00156 00157 if (outlink) 00158 avfilter_draw_slice(outlink, y, h, slice_dir); 00159 } 00160 00161 void avfilter_default_end_frame(AVFilterLink *inlink) 00162 { 00163 AVFilterLink *outlink = NULL; 00164 00165 if (inlink->dst->output_count) 00166 outlink = inlink->dst->outputs[0]; 00167 00168 avfilter_unref_buffer(inlink->cur_buf); 00169 inlink->cur_buf = NULL; 00170 00171 if (outlink) { 00172 if (outlink->out_buf) { 00173 avfilter_unref_buffer(outlink->out_buf); 00174 outlink->out_buf = NULL; 00175 } 00176 avfilter_end_frame(outlink); 00177 } 00178 } 00179 00180 /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */ 00181 void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) 00182 { 00183 AVFilterLink *outlink = NULL; 00184 00185 if (inlink->dst->output_count) 00186 outlink = inlink->dst->outputs[0]; 00187 00188 if (outlink) { 00189 outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE, samplesref->format, 00190 samplesref->audio->size, 00191 samplesref->audio->channel_layout, 00192 samplesref->audio->planar); 00193 outlink->out_buf->pts = samplesref->pts; 00194 outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate; 00195 avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0)); 00196 avfilter_unref_buffer(outlink->out_buf); 00197 outlink->out_buf = NULL; 00198 } 00199 avfilter_unref_buffer(samplesref); 00200 inlink->cur_buf = NULL; 00201 } 00202 00206 int avfilter_default_config_output_link(AVFilterLink *link) 00207 { 00208 if (link->src->input_count && link->src->inputs[0]) { 00209 if (link->type == AVMEDIA_TYPE_VIDEO) { 00210 link->w = link->src->inputs[0]->w; 00211 link->h = link->src->inputs[0]->h; 00212 link->time_base = link->src->inputs[0]->time_base; 00213 } else if (link->type == AVMEDIA_TYPE_AUDIO) { 00214 link->channel_layout = link->src->inputs[0]->channel_layout; 00215 link->sample_rate = link->src->inputs[0]->sample_rate; 00216 } 00217 } else { 00218 /* XXX: any non-simple filter which would cause this branch to be taken 00219 * really should implement its own config_props() for this link. */ 00220 return -1; 00221 } 00222 00223 return 0; 00224 } 00225 00234 void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats) 00235 { 00236 int count = 0, i; 00237 00238 for (i = 0; i < ctx->input_count; i++) { 00239 if (ctx->inputs[i]) { 00240 avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats); 00241 count++; 00242 } 00243 } 00244 for (i = 0; i < ctx->output_count; i++) { 00245 if (ctx->outputs[i]) { 00246 avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats); 00247 count++; 00248 } 00249 } 00250 00251 if (!count) { 00252 av_free(formats->formats); 00253 av_free(formats->refs); 00254 av_free(formats); 00255 } 00256 } 00257 00258 int avfilter_default_query_formats(AVFilterContext *ctx) 00259 { 00260 enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type : 00261 ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type : 00262 AVMEDIA_TYPE_VIDEO; 00263 00264 avfilter_set_common_formats(ctx, avfilter_all_formats(type)); 00265 return 0; 00266 } 00267 00268 void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) 00269 { 00270 avfilter_start_frame(link->dst->outputs[0], picref); 00271 } 00272 00273 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) 00274 { 00275 avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir); 00276 } 00277 00278 void avfilter_null_end_frame(AVFilterLink *link) 00279 { 00280 avfilter_end_frame(link->dst->outputs[0]); 00281 } 00282 00283 void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) 00284 { 00285 avfilter_filter_samples(link->dst->outputs[0], samplesref); 00286 } 00287 00288 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 00289 { 00290 return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h); 00291 } 00292 00293 AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms, 00294 enum AVSampleFormat sample_fmt, int size, 00295 int64_t channel_layout, int packed) 00296 { 00297 return avfilter_get_audio_buffer(link->dst->outputs[0], perms, sample_fmt, 00298 size, channel_layout, packed); 00299 } 00300