Libav 0.7.1
|
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