Ticket #1655: aligndim.diff

File aligndim.diff, 3.9 KB (added by reimar, 17 years ago)

fix avcodec_align_dimensions to fix crashes with some flv files due to unaligned SSE access

  • libavcodec/utils.c

     
    117117
    118118#define INTERNAL_BUFFER_SIZE 32
    119119
    120 void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
     120void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int *linesize_align){
    121121    int w_align= 1;
    122122    int h_align= 1;
    123123
     
    180180    *height= FFALIGN(*height, h_align);
    181181    if(s->codec_id == CODEC_ID_H264)
    182182        *height+=2; // some of the optimized chroma MC reads one line too much
     183
     184    *linesize_align = STRIDE_ALIGN;
     185//STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes
     186//we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the
     187//picture size unneccessarily in some cases. The solution here is not
     188//pretty and better ideas are welcome!
     189#if HAVE_MMX
     190    if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 ||
     191       s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F ||
     192       s->codec_id == CODEC_ID_VP6A)
     193        *linesize_align = 16;
     194#endif
    183195}
    184196
     197void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
     198    int linesize_align;
     199    avcodec_align_dimensions2(s, width, height, &linesize_align);
     200    *width=FFALIGN(*width, 2*linesize_align);
     201}
     202
    185203int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){
    186204    if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8)
    187205        return 0;
     
    260278
    261279            unaligned = 0;
    262280            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
    274281                stride_align[i] = STRIDE_ALIGN;
    275282                unaligned |= picture.linesize[i] % stride_align[i];
    276283            }
  • libavcodec/avcodec.h

     
    13671367    /**
    13681368     * Called at the beginning of each frame to get a buffer for it.
    13691369     * If pic.reference is set then the frame will be read later by libavcodec.
    1370      * avcodec_align_dimensions() should be used to find the required width and
     1370     * avcodec_align_dimensions2() should be used to find the required width and
    13711371     * height, as they normally need to be rounded up to the next multiple of 16.
    13721372     * if CODEC_CAP_DR1 is not set then get_buffer() must call
    13731373     * avcodec_default_get_buffer() instead of providing buffers allocated by
     
    32263226int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic);
    32273227void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic);
    32283228int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic);
     3229/**
     3230 * Modifies width and height values so that they will result in a memory
     3231 * buffer that is acceptable for the codec if you do not use any horizontal
     3232 * padding.
     3233 */
    32293234void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);
     3235/**
     3236 * Modifies width and height values so that they will result in a memory
     3237 * buffer that is acceptable for the codec if you also ensure that all
     3238 * line sizes are a multiple of linesize_align.
     3239 */
     3240void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
     3241                               int *linesize_align);
    32303242
    32313243/**
    32323244 * Checks if the given dimension of a picture is valid, meaning that all