Libav 0.7.1
libavfilter/formats.c
Go to the documentation of this file.
00001 /*
00002  * Filter layer - format negotiation
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/pixdesc.h"
00023 #include "avfilter.h"
00024 
00028 static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a)
00029 {
00030     int i;
00031 
00032     for(i = 0; i < a->refcount; i ++) {
00033         ret->refs[ret->refcount] = a->refs[i];
00034         *ret->refs[ret->refcount++] = ret;
00035     }
00036 
00037     av_free(a->refs);
00038     av_free(a->formats);
00039     av_free(a);
00040 }
00041 
00042 AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
00043 {
00044     AVFilterFormats *ret;
00045     unsigned i, j, k = 0;
00046 
00047     ret = av_mallocz(sizeof(AVFilterFormats));
00048 
00049     /* merge list of formats */
00050     ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,
00051                                                            b->format_count));
00052     for(i = 0; i < a->format_count; i ++)
00053         for(j = 0; j < b->format_count; j ++)
00054             if(a->formats[i] == b->formats[j])
00055                 ret->formats[k++] = a->formats[i];
00056 
00057     ret->format_count = k;
00058     /* check that there was at least one common format */
00059     if(!ret->format_count) {
00060         av_free(ret->formats);
00061         av_free(ret);
00062         return NULL;
00063     }
00064 
00065     ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount));
00066 
00067     merge_ref(ret, a);
00068     merge_ref(ret, b);
00069 
00070     return ret;
00071 }
00072 
00073 AVFilterFormats *avfilter_make_format_list(const int *fmts)
00074 {
00075     AVFilterFormats *formats;
00076     int count;
00077 
00078     for (count = 0; fmts[count] != -1; count++)
00079         ;
00080 
00081     formats               = av_mallocz(sizeof(AVFilterFormats));
00082     formats->formats      = av_malloc(sizeof(*formats->formats) * count);
00083     formats->format_count = count;
00084     memcpy(formats->formats, fmts, sizeof(*formats->formats) * count);
00085 
00086     return formats;
00087 }
00088 
00089 int avfilter_add_format(AVFilterFormats **avff, int fmt)
00090 {
00091     int *fmts;
00092 
00093     if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats))))
00094         return AVERROR(ENOMEM);
00095 
00096     fmts = av_realloc((*avff)->formats,
00097                       sizeof(*(*avff)->formats) * ((*avff)->format_count+1));
00098     if (!fmts)
00099         return AVERROR(ENOMEM);
00100 
00101     (*avff)->formats = fmts;
00102     (*avff)->formats[(*avff)->format_count++] = fmt;
00103     return 0;
00104 }
00105 
00106 AVFilterFormats *avfilter_all_formats(enum AVMediaType type)
00107 {
00108     AVFilterFormats *ret = NULL;
00109     int fmt;
00110     int num_formats = type == AVMEDIA_TYPE_VIDEO ? PIX_FMT_NB    :
00111                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
00112 
00113     for (fmt = 0; fmt < num_formats; fmt++)
00114         if ((type != AVMEDIA_TYPE_VIDEO) ||
00115             (type == AVMEDIA_TYPE_VIDEO && !(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_HWACCEL)))
00116             avfilter_add_format(&ret, fmt);
00117 
00118     return ret;
00119 }
00120 
00121 void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
00122 {
00123     *ref = f;
00124     f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount);
00125     f->refs[f->refcount-1] = ref;
00126 }
00127 
00128 static int find_ref_index(AVFilterFormats **ref)
00129 {
00130     int i;
00131     for(i = 0; i < (*ref)->refcount; i ++)
00132         if((*ref)->refs[i] == ref)
00133             return i;
00134     return -1;
00135 }
00136 
00137 void avfilter_formats_unref(AVFilterFormats **ref)
00138 {
00139     int idx;
00140 
00141     if (!*ref)
00142         return;
00143 
00144     idx = find_ref_index(ref);
00145 
00146     if(idx >= 0)
00147         memmove((*ref)->refs + idx, (*ref)->refs + idx+1,
00148             sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1));
00149 
00150     if(!--(*ref)->refcount) {
00151         av_free((*ref)->formats);
00152         av_free((*ref)->refs);
00153         av_free(*ref);
00154     }
00155     *ref = NULL;
00156 }
00157 
00158 void avfilter_formats_changeref(AVFilterFormats **oldref,
00159                                 AVFilterFormats **newref)
00160 {
00161     int idx = find_ref_index(oldref);
00162 
00163     if(idx >= 0) {
00164         (*oldref)->refs[idx] = newref;
00165         *newref = *oldref;
00166         *oldref = NULL;
00167     }
00168 }
00169