Libav 0.7.1
|
00001 /* 00002 * This file is part of Libav. 00003 * 00004 * Libav is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * Libav is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with Libav; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00024 #include "imgutils.h" 00025 #include "internal.h" 00026 #include "pixdesc.h" 00027 00028 void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], 00029 const AVPixFmtDescriptor *pixdesc) 00030 { 00031 int i; 00032 memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0])); 00033 if (max_pixstep_comps) 00034 memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0])); 00035 00036 for (i = 0; i < 4; i++) { 00037 const AVComponentDescriptor *comp = &(pixdesc->comp[i]); 00038 if ((comp->step_minus1+1) > max_pixsteps[comp->plane]) { 00039 max_pixsteps[comp->plane] = comp->step_minus1+1; 00040 if (max_pixstep_comps) 00041 max_pixstep_comps[comp->plane] = i; 00042 } 00043 } 00044 } 00045 00046 int av_image_get_linesize(enum PixelFormat pix_fmt, int width, int plane) 00047 { 00048 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00049 int max_step [4]; /* max pixel step for each plane */ 00050 int max_step_comp[4]; /* the component for each plane which has the max pixel step */ 00051 int s; 00052 00053 if (desc->flags & PIX_FMT_BITSTREAM) 00054 return (width * (desc->comp[0].step_minus1+1) + 7) >> 3; 00055 00056 av_image_fill_max_pixsteps(max_step, max_step_comp, desc); 00057 s = (max_step_comp[plane] == 1 || max_step_comp[plane] == 2) ? desc->log2_chroma_w : 0; 00058 return max_step[plane] * (((width + (1 << s) - 1)) >> s); 00059 } 00060 00061 int av_image_fill_linesizes(int linesizes[4], enum PixelFormat pix_fmt, int width) 00062 { 00063 int i; 00064 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00065 int max_step [4]; /* max pixel step for each plane */ 00066 int max_step_comp[4]; /* the component for each plane which has the max pixel step */ 00067 00068 memset(linesizes, 0, 4*sizeof(linesizes[0])); 00069 00070 if ((unsigned)pix_fmt >= PIX_FMT_NB || desc->flags & PIX_FMT_HWACCEL) 00071 return AVERROR(EINVAL); 00072 00073 if (desc->flags & PIX_FMT_BITSTREAM) { 00074 if (width > (INT_MAX -7) / (desc->comp[0].step_minus1+1)) 00075 return AVERROR(EINVAL); 00076 linesizes[0] = (width * (desc->comp[0].step_minus1+1) + 7) >> 3; 00077 return 0; 00078 } 00079 00080 av_image_fill_max_pixsteps(max_step, max_step_comp, desc); 00081 for (i = 0; i < 4; i++) { 00082 int s = (max_step_comp[i] == 1 || max_step_comp[i] == 2) ? desc->log2_chroma_w : 0; 00083 int shifted_w = ((width + (1 << s) - 1)) >> s; 00084 if (max_step[i] > INT_MAX / shifted_w) 00085 return AVERROR(EINVAL); 00086 linesizes[i] = max_step[i] * shifted_w; 00087 } 00088 00089 return 0; 00090 } 00091 00092 int av_image_fill_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, int height, 00093 uint8_t *ptr, const int linesizes[4]) 00094 { 00095 int i, total_size, size[4], has_plane[4]; 00096 00097 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00098 memset(data , 0, sizeof(data[0])*4); 00099 memset(size , 0, sizeof(size)); 00100 memset(has_plane, 0, sizeof(has_plane)); 00101 00102 if ((unsigned)pix_fmt >= PIX_FMT_NB || desc->flags & PIX_FMT_HWACCEL) 00103 return AVERROR(EINVAL); 00104 00105 data[0] = ptr; 00106 if (linesizes[0] > (INT_MAX - 1024) / height) 00107 return AVERROR(EINVAL); 00108 size[0] = linesizes[0] * height; 00109 00110 if (desc->flags & PIX_FMT_PAL) { 00111 size[0] = (size[0] + 3) & ~3; 00112 data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */ 00113 return size[0] + 256 * 4; 00114 } 00115 00116 for (i = 0; i < 4; i++) 00117 has_plane[desc->comp[i].plane] = 1; 00118 00119 total_size = size[0]; 00120 for (i = 1; i < 4 && has_plane[i]; i++) { 00121 int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; 00122 data[i] = data[i-1] + size[i-1]; 00123 h = (height + (1 << s) - 1) >> s; 00124 if (linesizes[i] > INT_MAX / h) 00125 return AVERROR(EINVAL); 00126 size[i] = h * linesizes[i]; 00127 if (total_size > INT_MAX - size[i]) 00128 return AVERROR(EINVAL); 00129 total_size += size[i]; 00130 } 00131 00132 return total_size; 00133 } 00134 00135 int ff_set_systematic_pal2(uint32_t pal[256], enum PixelFormat pix_fmt) 00136 { 00137 int i; 00138 00139 for (i = 0; i < 256; i++) { 00140 int r, g, b; 00141 00142 switch (pix_fmt) { 00143 case PIX_FMT_RGB8: 00144 r = (i>>5 )*36; 00145 g = ((i>>2)&7)*36; 00146 b = (i&3 )*85; 00147 break; 00148 case PIX_FMT_BGR8: 00149 b = (i>>6 )*85; 00150 g = ((i>>3)&7)*36; 00151 r = (i&7 )*36; 00152 break; 00153 case PIX_FMT_RGB4_BYTE: 00154 r = (i>>3 )*255; 00155 g = ((i>>1)&3)*85; 00156 b = (i&1 )*255; 00157 break; 00158 case PIX_FMT_BGR4_BYTE: 00159 b = (i>>3 )*255; 00160 g = ((i>>1)&3)*85; 00161 r = (i&1 )*255; 00162 break; 00163 case PIX_FMT_GRAY8: 00164 r = b = g = i; 00165 break; 00166 default: 00167 return AVERROR(EINVAL); 00168 } 00169 pal[i] = b + (g<<8) + (r<<16); 00170 } 00171 00172 return 0; 00173 } 00174 00175 int av_image_alloc(uint8_t *pointers[4], int linesizes[4], 00176 int w, int h, enum PixelFormat pix_fmt, int align) 00177 { 00178 int i, ret; 00179 uint8_t *buf; 00180 00181 if ((ret = av_image_check_size(w, h, 0, NULL)) < 0) 00182 return ret; 00183 if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, w)) < 0) 00184 return ret; 00185 00186 for (i = 0; i < 4; i++) 00187 linesizes[i] = FFALIGN(linesizes[i], align); 00188 00189 if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, NULL, linesizes)) < 0) 00190 return ret; 00191 buf = av_malloc(ret + align); 00192 if (!buf) 00193 return AVERROR(ENOMEM); 00194 if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, buf, linesizes)) < 0) { 00195 av_free(buf); 00196 return ret; 00197 } 00198 if (av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_PAL) 00199 ff_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt); 00200 00201 return ret; 00202 } 00203 00204 typedef struct ImgUtils { 00205 const AVClass *class; 00206 int log_offset; 00207 void *log_ctx; 00208 } ImgUtils; 00209 00210 static const AVClass imgutils_class = { "IMGUTILS", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(ImgUtils, log_offset), offsetof(ImgUtils, log_ctx) }; 00211 00212 int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx) 00213 { 00214 ImgUtils imgutils = { &imgutils_class, log_offset, log_ctx }; 00215 00216 if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8) 00217 return 0; 00218 00219 av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h); 00220 return AVERROR(EINVAL); 00221 } 00222 00223 void av_image_copy_plane(uint8_t *dst, int dst_linesize, 00224 const uint8_t *src, int src_linesize, 00225 int bytewidth, int height) 00226 { 00227 if (!dst || !src) 00228 return; 00229 for (;height > 0; height--) { 00230 memcpy(dst, src, bytewidth); 00231 dst += dst_linesize; 00232 src += src_linesize; 00233 } 00234 } 00235 00236 void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], 00237 const uint8_t *src_data[4], const int src_linesizes[4], 00238 enum PixelFormat pix_fmt, int width, int height) 00239 { 00240 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 00241 00242 if (desc->flags & PIX_FMT_HWACCEL) 00243 return; 00244 00245 if (desc->flags & PIX_FMT_PAL) { 00246 av_image_copy_plane(dst_data[0], dst_linesizes[0], 00247 src_data[0], src_linesizes[0], 00248 width, height); 00249 /* copy the palette */ 00250 memcpy(dst_data[1], src_data[1], 4*256); 00251 } else { 00252 int i, planes_nb = 0; 00253 00254 for (i = 0; i < desc->nb_components; i++) 00255 planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); 00256 00257 for (i = 0; i < planes_nb; i++) { 00258 int h = height; 00259 int bwidth = av_image_get_linesize(pix_fmt, width, i); 00260 if (i == 1 || i == 2) { 00261 h= -((-height)>>desc->log2_chroma_h); 00262 } 00263 av_image_copy_plane(dst_data[i], dst_linesizes[i], 00264 src_data[i], src_linesizes[i], 00265 bwidth, h); 00266 } 00267 } 00268 }