1/* 2 * Filter layer - format negotiation 3 * copyright (c) 2007 Bobby Bingham 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/pixdesc.h" 23#include "avfilter.h" 24 25/** 26 * Add all refs from a to ret and destroy a. 27 */ 28static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a) 29{ 30 int i; 31 32 for(i = 0; i < a->refcount; i ++) { 33 ret->refs[ret->refcount] = a->refs[i]; 34 *ret->refs[ret->refcount++] = ret; 35 } 36 37 av_free(a->refs); 38 av_free(a->formats); 39 av_free(a); 40} 41 42AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b) 43{ 44 AVFilterFormats *ret; 45 unsigned i, j, k = 0; 46 47 ret = av_mallocz(sizeof(AVFilterFormats)); 48 49 /* merge list of formats */ 50 ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count, 51 b->format_count)); 52 for(i = 0; i < a->format_count; i ++) 53 for(j = 0; j < b->format_count; j ++) 54 if(a->formats[i] == b->formats[j]) 55 ret->formats[k++] = a->formats[i]; 56 57 ret->format_count = k; 58 /* check that there was at least one common format */ 59 if(!ret->format_count) { 60 av_free(ret->formats); 61 av_free(ret); 62 return NULL; 63 } 64 65 ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount)); 66 67 merge_ref(ret, a); 68 merge_ref(ret, b); 69 70 return ret; 71} 72 73AVFilterFormats *avfilter_make_format_list(const enum PixelFormat *pix_fmts) 74{ 75 AVFilterFormats *formats; 76 int count; 77 78 for (count = 0; pix_fmts[count] != PIX_FMT_NONE; count++) 79 ; 80 81 formats = av_mallocz(sizeof(AVFilterFormats)); 82 formats->formats = av_malloc(sizeof(*formats->formats) * count); 83 formats->format_count = count; 84 memcpy(formats->formats, pix_fmts, sizeof(*formats->formats) * count); 85 86 return formats; 87} 88 89int avfilter_add_colorspace(AVFilterFormats **avff, enum PixelFormat pix_fmt) 90{ 91 enum PixelFormat *pix_fmts; 92 93 if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats)))) 94 return AVERROR(ENOMEM); 95 96 pix_fmts = av_realloc((*avff)->formats, 97 sizeof((*avff)->formats) * ((*avff)->format_count+1)); 98 if (!pix_fmts) 99 return AVERROR(ENOMEM); 100 101 (*avff)->formats = pix_fmts; 102 (*avff)->formats[(*avff)->format_count++] = pix_fmt; 103 return 0; 104} 105 106AVFilterFormats *avfilter_all_colorspaces(void) 107{ 108 AVFilterFormats *ret = NULL; 109 enum PixelFormat pix_fmt; 110 111 for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) 112 if (!(av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL)) 113 avfilter_add_colorspace(&ret, pix_fmt); 114 115 return ret; 116} 117 118void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref) 119{ 120 *ref = f; 121 f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount); 122 f->refs[f->refcount-1] = ref; 123} 124 125static int find_ref_index(AVFilterFormats **ref) 126{ 127 int i; 128 for(i = 0; i < (*ref)->refcount; i ++) 129 if((*ref)->refs[i] == ref) 130 return i; 131 return -1; 132} 133 134void avfilter_formats_unref(AVFilterFormats **ref) 135{ 136 int idx; 137 138 if (!*ref) 139 return; 140 141 idx = find_ref_index(ref); 142 143 if(idx >= 0) 144 memmove((*ref)->refs + idx, (*ref)->refs + idx+1, 145 sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1)); 146 147 if(!--(*ref)->refcount) { 148 av_free((*ref)->formats); 149 av_free((*ref)->refs); 150 av_free(*ref); 151 } 152 *ref = NULL; 153} 154 155void avfilter_formats_changeref(AVFilterFormats **oldref, 156 AVFilterFormats **newref) 157{ 158 int idx = find_ref_index(oldref); 159 160 if(idx >= 0) { 161 (*oldref)->refs[idx] = newref; 162 *newref = *oldref; 163 *oldref = NULL; 164 } 165} 166 167