Mercurial > libavcodec.hg
comparison utils.c @ 11311:ee2e050815be libavcodec
Fix avcodec_align_dimensions to return values suitably aligned for FLV decoding
with SSE and add a avcodec_align_dimensions2 taht returns the stride alignment
requirements independently from doing the width/height padding.
| author | reimar |
|---|---|
| date | Sat, 27 Feb 2010 21:13:22 +0000 |
| parents | a090d10c314f |
| children | c4e86bcb2fee |
comparison
equal
deleted
inserted
replaced
| 11310:1ff8ae765206 | 11311:ee2e050815be |
|---|---|
| 29 #define _XOPEN_SOURCE 600 | 29 #define _XOPEN_SOURCE 600 |
| 30 | 30 |
| 31 #include "libavutil/avstring.h" | 31 #include "libavutil/avstring.h" |
| 32 #include "libavutil/integer.h" | 32 #include "libavutil/integer.h" |
| 33 #include "libavutil/crc.h" | 33 #include "libavutil/crc.h" |
| 34 #include "libavutil/pixdesc.h" | |
| 34 #include "avcodec.h" | 35 #include "avcodec.h" |
| 35 #include "dsputil.h" | 36 #include "dsputil.h" |
| 36 #include "opt.h" | 37 #include "opt.h" |
| 37 #include "imgconvert.h" | 38 #include "imgconvert.h" |
| 38 #include "audioconvert.h" | 39 #include "audioconvert.h" |
| 115 enum PixelFormat pix_fmt; | 116 enum PixelFormat pix_fmt; |
| 116 }InternalBuffer; | 117 }InternalBuffer; |
| 117 | 118 |
| 118 #define INTERNAL_BUFFER_SIZE 32 | 119 #define INTERNAL_BUFFER_SIZE 32 |
| 119 | 120 |
| 120 void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ | 121 void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[4]){ |
| 121 int w_align= 1; | 122 int w_align= 1; |
| 122 int h_align= 1; | 123 int h_align= 1; |
| 123 | 124 |
| 124 switch(s->pix_fmt){ | 125 switch(s->pix_fmt){ |
| 125 case PIX_FMT_YUV420P: | 126 case PIX_FMT_YUV420P: |
| 178 | 179 |
| 179 *width = FFALIGN(*width , w_align); | 180 *width = FFALIGN(*width , w_align); |
| 180 *height= FFALIGN(*height, h_align); | 181 *height= FFALIGN(*height, h_align); |
| 181 if(s->codec_id == CODEC_ID_H264) | 182 if(s->codec_id == CODEC_ID_H264) |
| 182 *height+=2; // some of the optimized chroma MC reads one line too much | 183 *height+=2; // some of the optimized chroma MC reads one line too much |
| 184 | |
| 185 linesize_align[0] = | |
| 186 linesize_align[1] = | |
| 187 linesize_align[2] = | |
| 188 linesize_align[3] = STRIDE_ALIGN; | |
| 189 //STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes | |
| 190 //we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the | |
| 191 //picture size unneccessarily in some cases. The solution here is not | |
| 192 //pretty and better ideas are welcome! | |
| 193 #if HAVE_MMX | |
| 194 if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 || | |
| 195 s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F || | |
| 196 s->codec_id == CODEC_ID_VP6A) { | |
| 197 linesize_align[0] = | |
| 198 linesize_align[1] = | |
| 199 linesize_align[2] = 16; | |
| 200 } | |
| 201 #endif | |
| 202 } | |
| 203 | |
| 204 void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ | |
| 205 int chroma_shift = av_pix_fmt_descriptors[s->pix_fmt].log2_chroma_w; | |
| 206 int linesize_align[4]; | |
| 207 int align; | |
| 208 avcodec_align_dimensions2(s, width, height, linesize_align); | |
| 209 align = FFMAX(linesize_align[0], linesize_align[3]); | |
| 210 linesize_align[1] <<= chroma_shift; | |
| 211 linesize_align[2] <<= chroma_shift; | |
| 212 align = FFMAX3(align, linesize_align[1], linesize_align[2]); | |
| 213 *width=FFALIGN(*width, align); | |
| 183 } | 214 } |
| 184 | 215 |
| 185 int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){ | 216 int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){ |
| 186 if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8) | 217 if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8) |
| 187 return 0; | 218 return 0; |
| 242 AVPicture picture; | 273 AVPicture picture; |
| 243 int stride_align[4]; | 274 int stride_align[4]; |
| 244 | 275 |
| 245 avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); | 276 avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); |
| 246 | 277 |
| 247 avcodec_align_dimensions(s, &w, &h); | 278 avcodec_align_dimensions2(s, &w, &h, stride_align); |
| 248 | 279 |
| 249 if(!(s->flags&CODEC_FLAG_EMU_EDGE)){ | 280 if(!(s->flags&CODEC_FLAG_EMU_EDGE)){ |
| 250 w+= EDGE_WIDTH*2; | 281 w+= EDGE_WIDTH*2; |
| 251 h+= EDGE_WIDTH*2; | 282 h+= EDGE_WIDTH*2; |
| 252 } | 283 } |
| 258 // increase alignment of w for next try (rhs gives the lowest bit set in w) | 289 // increase alignment of w for next try (rhs gives the lowest bit set in w) |
| 259 w += w & ~(w-1); | 290 w += w & ~(w-1); |
| 260 | 291 |
| 261 unaligned = 0; | 292 unaligned = 0; |
| 262 for (i=0; i<4; i++){ | 293 for (i=0; i<4; i++){ |
| 263 //STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes | |
| 264 //we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the | |
| 265 //picture size unneccessarily in some cases. The solution here is not | |
| 266 //pretty and better ideas are welcome! | |
| 267 #if HAVE_MMX | |
| 268 if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 || | |
| 269 s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F || | |
| 270 s->codec_id == CODEC_ID_VP6A) | |
| 271 stride_align[i]= 16; | |
| 272 else | |
| 273 #endif | |
| 274 stride_align[i] = STRIDE_ALIGN; | |
| 275 unaligned |= picture.linesize[i] % stride_align[i]; | 294 unaligned |= picture.linesize[i] % stride_align[i]; |
| 276 } | 295 } |
| 277 } while (unaligned); | 296 } while (unaligned); |
| 278 | 297 |
| 279 tmpsize = ff_fill_pointer(&picture, NULL, s->pix_fmt, h); | 298 tmpsize = ff_fill_pointer(&picture, NULL, s->pix_fmt, h); |
