--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -131,7 +131,7 @@
   double            aspect_ratio;
   int               aspect_ratio_prio;
   int               frame_flags;
-  int               crop_right, crop_bottom;
+  int               edge;
 
   int               output_format;
 
@@ -157,6 +157,8 @@
   uint8_t           set_stream_info;
 
 #ifdef ENABLE_VAAPI
+  int                   vaapi_width, vaapi_height;
+  int                   vaapi_profile;
   struct vaapi_context  vaapi_context;
   vaapi_accel_t         *accel;
   vo_frame_t            *accel_img;
@@ -225,6 +227,7 @@
   vo_frame_t *img;
   int width  = context->width;
   int height = context->height;
+  int crop_right = 0, crop_bottom = 0;
   int guarded_render = 0;
 
   ff_check_colorspace (this);
@@ -232,13 +235,13 @@
   if (!this->bih.biWidth || !this->bih.biHeight) {
     this->bih.biWidth = width;
     this->bih.biHeight = height;
-
-    if (this->aspect_ratio_prio == 0) {
-      this->aspect_ratio = (double)width / (double)height;
-      this->aspect_ratio_prio = 1;
-      lprintf("default aspect ratio: %f\n", this->aspect_ratio);
-      this->set_stream_info = 1;
-    }
+  }
+
+  if (this->aspect_ratio_prio == 0) {
+    this->aspect_ratio = (double)width / (double)height;
+    this->aspect_ratio_prio = 1;
+    lprintf("default aspect ratio: %f\n", this->aspect_ratio);
+    this->set_stream_info = 1;
   }
 
   avcodec_align_dimensions(context, &width, &height);
@@ -257,6 +260,26 @@
 #endif
     av_frame->reordered_opaque = context->reordered_opaque;
 
+    /* reinitialize vaapi for new image size */
+    if (context->width != this->vaapi_width || context->height != this->vaapi_height) {
+      VAStatus status;
+
+      this->vaapi_width  = context->width;
+      this->vaapi_height = context->height;
+      status = this->accel->vaapi_init (this->accel_img, this->vaapi_profile,
+        context->width, context->height, 0);
+
+      if (status == VA_STATUS_SUCCESS) {
+        ff_vaapi_context_t *va_context = this->accel->get_context (this->accel_img);
+
+        if (va_context) {
+          this->vaapi_context.config_id  = va_context->va_config_id;
+          this->vaapi_context.context_id = va_context->va_context_id;
+          this->vaapi_context.display    = va_context->va_display;
+        }
+      }
+    }
+
     if(!this->accel->guarded_render(this->accel_img)) {
       img = this->stream->video_out->get_frame (this->stream->video_out,
                                             width,
@@ -305,6 +328,12 @@
     guarded_render = this->accel->guarded_render(this->accel_img);
 #endif /* ENABLE_VAAPI */
 
+  /* The alignment rhapsody */
+  width  += 2 * this->edge;
+  height += 2 * this->edge;
+  width   = (width + 15) & ~15;
+  height  = (height + 15) & ~15;
+
   if ((this->full2mpeg || (this->context->pix_fmt != PIX_FMT_YUV420P &&
 			   this->context->pix_fmt != PIX_FMT_YUVJ420P)) || guarded_render) {
     if (!this->is_direct_rendering_disabled) {
@@ -322,8 +351,8 @@
 
   if((width != this->bih.biWidth) || (height != this->bih.biHeight)) {
     if(this->stream->video_out->get_capabilities(this->stream->video_out) & VO_CAP_CROP) {
-      this->crop_right = width - this->bih.biWidth;
-      this->crop_bottom = height - this->bih.biHeight;
+      crop_right = width - this->bih.biWidth - this->edge;
+      crop_bottom = height - this->bih.biHeight - this->edge;
     } else {
       if (!this->is_direct_rendering_disabled) {
         xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
@@ -349,6 +378,8 @@
 
   av_frame->opaque = img;
 
+  av_frame->extended_data = av_frame->data;
+
   av_frame->data[0]= img->base[0];
   av_frame->data[1]= img->base[1];
   av_frame->data[2]= img->base[2];
@@ -356,6 +387,16 @@
   av_frame->linesize[0] = img->pitches[0];
   av_frame->linesize[1] = img->pitches[1];
   av_frame->linesize[2] = img->pitches[2];
+
+  if (this->output_format == XINE_IMGFMT_YV12) {
+    av_frame->data[0] += (img->pitches[0] + 1) * this->edge;
+    av_frame->data[1] += (img->pitches[1] + 1) * this->edge / 2;
+    av_frame->data[2] += (img->pitches[2] + 1) * this->edge / 2;
+    img->crop_left   = this->edge;
+    img->crop_top    = this->edge;
+    img->crop_right  = crop_right;
+    img->crop_bottom = crop_bottom;
+  }
 
   /* We should really keep track of the ages of xine frames (see
    * avcodec_default_get_buffer in libavcodec/utils.c)
@@ -436,9 +477,14 @@
 };
 
 #ifdef ENABLE_VAAPI
+/* TJ. libavcodec calls this with a list of supported pixel formats and lets us choose 1.
+   Returning PIX_FMT_VAAPI_VLD enables VAAPI.
+   However, at this point we only got image width and height from container, being unreliable
+   or zero (MPEG-TS). Thus we repeat vaapi_context initialization in get_buffer when needed.
+   This should be OK since NAL unit parsing is always done in software. */
 static enum PixelFormat get_format(struct AVCodecContext *context, const enum PixelFormat *fmt)
 {
-  int i, profile;
+  int i;
   ff_video_decoder_t *this = (ff_video_decoder_t *)context->opaque;
 
   if(!this->class->enable_vaapi || !this->accel_img)
@@ -450,12 +496,21 @@
     if (fmt[i] != PIX_FMT_VAAPI_VLD)
       continue;
 
-    profile = accel->profile_from_imgfmt(this->accel_img, fmt[i], context->codec_id, this->class->vaapi_mpeg_softdec);
-
-    if (profile >= 0) {
+    this->vaapi_profile = accel->profile_from_imgfmt (this->accel_img, fmt[i],
+      context->codec_id, this->class->vaapi_mpeg_softdec);
+
+    if (this->vaapi_profile >= 0) {
+      int width  = context->width;
+      int height = context->height;
       VAStatus status;
 
-      status = accel->vaapi_init(this->accel_img, profile, context->width, context->height, 0);
+      if (!width || !height) {
+        width  = 1920;
+        height = 1080;
+      }
+      this->vaapi_width  = width;
+      this->vaapi_height = height;
+      status = accel->vaapi_init (this->accel_img, this->vaapi_profile, width, height, 0);
 
       if( status == VA_STATUS_SUCCESS ) {
         ff_vaapi_context_t *va_context = accel->get_context(this->accel_img);
@@ -513,10 +568,20 @@
     _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC);
 
 
-  /* Some codecs (eg rv10) copy flags in init so it's necessary to set
-   * this flag here in case we are going to use direct rendering */
+  this->stream->video_out->open (this->stream->video_out, this->stream);
+
+  this->edge = 0;
   if(this->codec->capabilities & CODEC_CAP_DR1 && this->class->enable_dri) {
-    this->context->flags |= CODEC_FLAG_EMU_EDGE;
+    if (this->stream->video_out->get_capabilities (this->stream->video_out) & VO_CAP_CROP) {
+      /* We can crop. Fine. Lets allow decoders to paint over the frame edges.
+         This will be slightly faster. And it is also a workaround for buggy
+         v54 who likes to ignore EMU_EDGE for wmv2 and xvid. */
+      this->edge = avcodec_get_edge_width ();
+    } else {
+      /* Some codecs (eg rv10) copy flags in init so it's necessary to set
+       * this flag here in case we are going to use direct rendering */
+      this->context->flags |= CODEC_FLAG_EMU_EDGE;
+    }
   }
 
   /* TJ. without this, it wont work at all on my machine */
@@ -575,6 +640,7 @@
     free(this->context);
     this->context = NULL;
     _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+    this->stream->video_out->close (this->stream->video_out, this->stream);
     return;
   }
 
@@ -590,6 +656,7 @@
       free(this->context);
       this->context = NULL;
       _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+      this->stream->video_out->close (this->stream->video_out, this->stream);
       return;
     }
   }
@@ -619,8 +686,6 @@
 
     set_stream_info(this);
   }
-
-  (this->stream->video_out->open) (this->stream->video_out, this->stream);
 
   this->skipframes = 0;
 
@@ -1449,9 +1514,6 @@
         img->duration = this->video_step * 3 / 2;
       else
         img->duration = this->video_step;
-
-      img->crop_right  = this->crop_right;
-      img->crop_bottom = this->crop_bottom;
 
 #ifdef ENABLE_VAAPI
       if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
@@ -1731,6 +1793,8 @@
                                                     this->aspect_ratio,
                                                     this->output_format,
                                                     VO_BOTH_FIELDS|this->frame_flags);
+          img->crop_right  = img->width  - this->bih.biWidth;
+          img->crop_bottom = img->height - this->bih.biHeight;
           free_img = 1;
         } else {
           /* DR1 */
@@ -1745,19 +1809,22 @@
         if(this->pp_available && this->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
 
           if(this->av_frame->opaque) {
-            /* DR1 */
+            /* DR1: filter into a new frame. Same size to avoid reallcation, just move the
+               image to top left corner. */
             img = this->stream->video_out->get_frame (this->stream->video_out,
-                                                      (img->width  + 15) & ~15,
-                                                      (img->height + 15) & ~15,
+                                                      img->width,
+                                                      img->height,
                                                       this->aspect_ratio,
                                                       this->output_format,
                                                       VO_BOTH_FIELDS|this->frame_flags);
+            img->crop_right  = img->width  - this->bih.biWidth;
+            img->crop_bottom = img->height - this->bih.biHeight;
             free_img = 1;
           }
 
           pp_postprocess((const uint8_t **)this->av_frame->data, this->av_frame->linesize,
                         img->base, img->pitches,
-                        img->width, img->height,
+                        this->bih.biWidth, this->bih.biHeight,
                         this->av_frame->qscale_table, this->av_frame->qstride,
                         this->our_mode, this->our_context,
                         this->av_frame->pict_type);
@@ -1785,10 +1852,6 @@
           img->duration = video_step_to_use * 3 / 2;
         else
           img->duration = video_step_to_use;
-
-        /* additionally crop away the extra pixels due to adjusting frame size above */
-        img->crop_right  = img->width  - this->bih.biWidth;
-        img->crop_bottom = img->height - this->bih.biHeight;
 
         /* transfer some more frame settings for deinterlacing */
         img->progressive_frame = !this->av_frame->interlaced_frame;