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