Fix T47724: VSE crops video if horizontal resolution isn't divisible by 8
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 15 Mar 2016 08:19:49 +0000 (13:19 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 15 Mar 2016 08:19:49 +0000 (13:19 +0500)
In fact, some areas in FFmpeg might require alignment up to 32, so now we
make temporary conversion in an aligned frame. We only do this if width is
not aligned to 32.

source/blender/imbuf/intern/anim_movie.c

index 1b4ce4225d6fff04a74e084879b7640de559922a..05e6b25b9a531a99feb7006a2f7d41cf3d09e0a8 100644 (file)
@@ -560,6 +560,23 @@ static int startffmpeg(struct anim *anim)
        anim->pFrameDeinterlaced = av_frame_alloc();
        anim->pFrameRGB = av_frame_alloc();
 
+       if ((anim->x & 31) != 0) {
+               anim->pFrameRGB->format = AV_PIX_FMT_RGBA;
+               anim->pFrameRGB->width  = anim->x;
+               anim->pFrameRGB->height = anim->y;
+
+               if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) {
+                       fprintf(stderr, "Could not allocate frame data.\n");
+                       avcodec_close(anim->pCodecCtx);
+                       avformat_close_input(&anim->pFormatCtx);
+                       av_free(anim->pFrameRGB);
+                       av_free(anim->pFrameDeinterlaced);
+                       av_free(anim->pFrame);
+                       anim->pCodecCtx = NULL;
+                       return -1;
+               }
+       }
+
        if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) !=
            anim->x * anim->y * 4)
        {
@@ -685,10 +702,12 @@ static void ffmpeg_postprocess(struct anim *anim)
                        input = anim->pFrameDeinterlaced;
                }
        }
-       
-       avpicture_fill((AVPicture *) anim->pFrameRGB,
-                      (unsigned char *) ibuf->rect,
-                      AV_PIX_FMT_RGBA, anim->x, anim->y);
+
+       if ((anim->x & 31) == 0) {
+               avpicture_fill((AVPicture *) anim->pFrameRGB,
+                              (unsigned char *) ibuf->rect,
+                              AV_PIX_FMT_RGBA, anim->x, anim->y);
+       }
 
        if (ENDIAN_ORDER == B_ENDIAN) {
                int *dstStride   = anim->pFrameRGB->linesize;
@@ -753,6 +772,16 @@ static void ffmpeg_postprocess(struct anim *anim)
                          dstStride2);
        }
 
+       if ((anim->x & 31) != 0) {
+               uint8_t *src = anim->pFrameRGB->data[0];
+               uint8_t *dst = (uint8_t *) ibuf->rect;
+               for (int y = 0; y < anim->y; y++) {
+                       memcpy(dst, src, anim->x * 4);
+                       dst += anim->x * 4;
+                       src += anim->pFrameRGB->linesize[0];
+               }
+       }
+
        if (filter_y) {
                IMB_filtery(ibuf);
        }