Libav
|
00001 /* 00002 * Filter layer - format negotiation 00003 * copyright (c) 2007 Bobby Bingham 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 enum PixelFormat *pix_fmts) 00074 { 00075 AVFilterFormats *formats; 00076 int count; 00077 00078 for (count = 0; pix_fmts[count] != PIX_FMT_NONE; 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, pix_fmts, sizeof(*formats->formats) * count); 00085 00086 return formats; 00087 } 00088 00089 int avfilter_add_colorspace(AVFilterFormats **avff, enum PixelFormat pix_fmt) 00090 { 00091 enum PixelFormat *pix_fmts; 00092 00093 if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats)))) 00094 return AVERROR(ENOMEM); 00095 00096 pix_fmts = av_realloc((*avff)->formats, 00097 sizeof((*avff)->formats) * ((*avff)->format_count+1)); 00098 if (!pix_fmts) 00099 return AVERROR(ENOMEM); 00100 00101 (*avff)->formats = pix_fmts; 00102 (*avff)->formats[(*avff)->format_count++] = pix_fmt; 00103 return 0; 00104 } 00105 00106 AVFilterFormats *avfilter_all_colorspaces(void) 00107 { 00108 AVFilterFormats *ret = NULL; 00109 enum PixelFormat pix_fmt; 00110 00111 for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) 00112 if (!(av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL)) 00113 avfilter_add_colorspace(&ret, pix_fmt); 00114 00115 return ret; 00116 } 00117 00118 void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref) 00119 { 00120 *ref = f; 00121 f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount); 00122 f->refs[f->refcount-1] = ref; 00123 } 00124 00125 static int find_ref_index(AVFilterFormats **ref) 00126 { 00127 int i; 00128 for(i = 0; i < (*ref)->refcount; i ++) 00129 if((*ref)->refs[i] == ref) 00130 return i; 00131 return -1; 00132 } 00133 00134 void avfilter_formats_unref(AVFilterFormats **ref) 00135 { 00136 int idx; 00137 00138 if (!*ref) 00139 return; 00140 00141 idx = find_ref_index(ref); 00142 00143 if(idx >= 0) 00144 memmove((*ref)->refs + idx, (*ref)->refs + idx+1, 00145 sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1)); 00146 00147 if(!--(*ref)->refcount) { 00148 av_free((*ref)->formats); 00149 av_free((*ref)->refs); 00150 av_free(*ref); 00151 } 00152 *ref = NULL; 00153 } 00154 00155 void avfilter_formats_changeref(AVFilterFormats **oldref, 00156 AVFilterFormats **newref) 00157 { 00158 int idx = find_ref_index(oldref); 00159 00160 if(idx >= 0) { 00161 (*oldref)->refs[idx] = newref; 00162 *newref = *oldref; 00163 *oldref = NULL; 00164 } 00165 } 00166