Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 10733)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -1516,17 +1516,12 @@
 
     VideoFrame *frame = nd->GetNVP()->GetNextVideoFrame(true);
 
-    int width = frame->width;
-    int height = frame->height;
+    for (int i = 0; i < 3; i++)
+    {
+        pic->data[i]     = frame->buf + frame->offsets[i];
+        pic->linesize[i] = frame->pitches[i];
+    }
 
-    pic->data[0] = frame->buf;
-    pic->data[1] = pic->data[0] + width * height;
-    pic->data[2] = pic->data[1] + width * height / 4;
-
-    pic->linesize[0] = width;
-    pic->linesize[1] = width / 2;
-    pic->linesize[2] = width / 2;
-
     pic->opaque = frame;
     pic->type = FF_BUFFER_TYPE_USER;
 
Index: libs/libmythtv/util-xv.cpp
===================================================================
--- libs/libmythtv/util-xv.cpp	(revision 10733)
+++ libs/libmythtv/util-xv.cpp	(working copy)
@@ -80,19 +80,3 @@
         str.append("XvImageMask ");
     return str;
 }
-
-void clear_xv_buffers(VideoBuffers &vbuffers,
-                      int width, int height, int xv_chroma)
-{
-    if ((GUID_I420_PLANAR == xv_chroma) ||
-        (GUID_YV12_PLANAR == xv_chroma))
-    {
-        for (uint i = 0; i < vbuffers.allocSize(); i++)
-        {
-            unsigned char *data = vbuffers.at(i)->buf;
-            bzero(data, width * height);
-            memset(data + width * height, 127,
-                   width * height / 2);
-        }
-    }
-}
Index: libs/libmythtv/frame.h
===================================================================
--- libs/libmythtv/frame.h	(revision 10733)
+++ libs/libmythtv/frame.h	(working copy)
@@ -37,6 +37,9 @@
     int top_field_first; // 1 if top field is first.
     int repeat_pict;
     int forcekey; // hardware encoded .nuv
+
+    int pitches[3]; // Y, U, & V pitches
+    int offsets[3]; // Y, U, & V offsets
 } VideoFrame;
 
 #endif
Index: libs/libmythtv/util-xv.h
===================================================================
--- libs/libmythtv/util-xv.h	(revision 10733)
+++ libs/libmythtv/util-xv.h	(working copy)
@@ -28,6 +28,5 @@
 extern bool has_open_xv_port(int port);
 extern uint cnt_open_xv_port(void);
 extern QString xvflags2str(int flags);
-extern void clear_xv_buffers(VideoBuffers&, int w, int h, int xv_chroma);
 
 #endif // _UTIL_XV_H_
Index: libs/libmythtv/videoout_xv.h
===================================================================
--- libs/libmythtv/videoout_xv.h	(revision 10733)
+++ libs/libmythtv/videoout_xv.h	(working copy)
@@ -187,7 +187,8 @@
 
     // Used for all non-XvMC drawing
     VideoFrame           av_pause_frame;
-    vector<XShmSegmentInfo> XJ_shm_infos;
+    vector<XShmSegmentInfo*> XJ_shm_infos;
+    vector<YUVInfo>      XJ_yuv_infos;
 
     // Basic non-Xv drawing info
     XImage              *XJ_non_xv_image;
Index: libs/libmythtv/videoout_xv.cpp
===================================================================
--- libs/libmythtv/videoout_xv.cpp	(revision 10733)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -199,8 +199,7 @@
     if (!res_changed && !cid_changed)
     {
         if (VideoOutputSubType() == XVideo)
-            clear_xv_buffers(vbuffers, video_dim.width(), video_dim.height(),
-                             xv_chroma);
+            vbuffers.Clear(xv_chroma);
         if (asp_changed)
             MoveResize();
         return;
@@ -1500,13 +1499,9 @@
             .arg(num).arg(video_dim.width()).arg(video_dim.height()));
 
     vector<unsigned char*> bufs;
-    XShmSegmentInfo blank;
-    // for now make reserve big enough to avoid realloc.. 
-    // we should really have vector of pointers...
-    XJ_shm_infos.reserve(max(num + 32, (uint)128));
     for (uint i = 0; i < num; i++)
     {
-        XJ_shm_infos.push_back(blank);
+        XShmSegmentInfo *info = new XShmSegmentInfo;
         void *image = NULL;
         int size = 0;
         int desiredsize = 0;
@@ -1515,10 +1510,11 @@
 
         if (use_xv)
         {
-            image = XvShmCreateImage(XJ_disp, xv_port, xv_chroma, 0, 
-                                     video_dim.width(), video_dim.height(),
-                                     &XJ_shm_infos[i]);
-            size = ((XvImage*)image)->data_size + 64;
+            XvImage *img =
+                XvShmCreateImage(XJ_disp, xv_port, xv_chroma, 0, 
+                                 video_dim.width(), video_dim.height(), info);
+            size = img->data_size + 64;
+            image = img;
             desiredsize = video_dim.width() * video_dim.height() * 3 / 2;
 
             if (image && size < desiredsize)
@@ -1528,13 +1524,31 @@
                         "requested size.");
                 XFree(image);
                 image = NULL;
+                delete info;
             }
+
+            if (image && (3 == img->num_planes))
+            {
+                XJ_shm_infos.push_back(info);
+                YUVInfo tmp(img->width, img->height, img->data_size,
+                            img->pitches, img->offsets);
+                XJ_yuv_infos.push_back(tmp);
+            }
+            else if (image)
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "CreateXvShmImages(): "
+                        "XvShmCreateImage() failed to create image "
+                        "with the correct number of pixel planes.");
+                XFree(image);
+                image = NULL;
+                delete info;
+            }
         }
         else
         {
             XImage *img =
                 XShmCreateImage(XJ_disp, DefaultVisual(XJ_disp, XJ_screen_num),
-                                XJ_depth, ZPixmap, 0, &XJ_shm_infos[i],
+                                XJ_depth, ZPixmap, 0, info,
                                 display_visible_rect.width(),
                                 display_visible_rect.height());
             size = img->bytes_per_line * img->height + 64;
@@ -1548,34 +1562,42 @@
                         "requested size.");
                 XDestroyImage((XImage *)image);
                 image = NULL;
+                delete info;
             }
+
+            if (image)
+            {
+                YUVInfo tmp(img->width, img->height,
+                            img->bytes_per_line * img->height, NULL, NULL);
+                XJ_yuv_infos.push_back(tmp);
+            }
         }
 
         X11U;
 
         if (image)
         {
-            XJ_shm_infos[i].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
-            if (XJ_shm_infos[i].shmid >= 0)
+            XJ_shm_infos[i]->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
+            if (XJ_shm_infos[i]->shmid >= 0)
             {
-                XJ_shm_infos[i].shmaddr = (char*) shmat(XJ_shm_infos[i].shmid, 0, 0);
+                XJ_shm_infos[i]->shmaddr = (char*) shmat(XJ_shm_infos[i]->shmid, 0, 0);
                 if (use_xv)
-                    ((XvImage*)image)->data = XJ_shm_infos[i].shmaddr;
+                    ((XvImage*)image)->data = XJ_shm_infos[i]->shmaddr;
                 else
-                    ((XImage*)image)->data = XJ_shm_infos[i].shmaddr;
-                xv_buffers[(unsigned char*) XJ_shm_infos[i].shmaddr] = image;
-                XJ_shm_infos[i].readOnly = False;
+                    ((XImage*)image)->data = XJ_shm_infos[i]->shmaddr;
+                xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr] = image;
+                XJ_shm_infos[i]->readOnly = False;
 
                 X11L;
-                XShmAttach(XJ_disp, &XJ_shm_infos[i]);
+                XShmAttach(XJ_disp, XJ_shm_infos[i]);
                 XSync(XJ_disp, False); // needed for FreeBSD?
                 X11U;
 
                 // Mark for delete immediately.
                 // It won't actually be removed until after we detach it.
-                shmctl(XJ_shm_infos[i].shmid, IPC_RMID, 0);
+                shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, 0);
 
-                bufs.push_back((unsigned char*) XJ_shm_infos[i].shmaddr);
+                bufs.push_back((unsigned char*) XJ_shm_infos[i]->shmaddr);
             }
             else
             { 
@@ -1605,11 +1627,8 @@
         vector<unsigned char*> bufs = 
             CreateShmImages(vbuffers.allocSize(), true);
         ok = vbuffers.CreateBuffers(
-            video_dim.width(), video_dim.height(), bufs);
+            video_dim.width(), video_dim.height(), bufs, XJ_yuv_infos);
 
-        clear_xv_buffers(vbuffers, video_dim.width(), video_dim.height(),
-                         xv_chroma);
-
         X11S(XSync(XJ_disp, False));
         if (xv_chroma != GUID_I420_PLANAR)
             xv_color_conv_buf = new unsigned char[
@@ -1747,11 +1766,11 @@
         }
     }
 
-    for (uint i=0; i<XJ_shm_infos.size(); ++i)
+    for (uint i = 0; i < XJ_shm_infos.size(); i++)
     {
-        X11S(XShmDetach(XJ_disp, &(XJ_shm_infos[i])));
+        X11S(XShmDetach(XJ_disp, XJ_shm_infos[i]));
         XvImage *image = (XvImage*) 
-            xv_buffers[(unsigned char*)XJ_shm_infos[i].shmaddr];
+            xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr];
         if (image)
         {
             if ((XImage*)image == (XImage*)XJ_non_xv_image)
@@ -1759,10 +1778,11 @@
             else
                 X11S(XFree(image));
         }
-        if (XJ_shm_infos[i].shmaddr)
-            shmdt(XJ_shm_infos[i].shmaddr);
-        if (XJ_shm_infos[i].shmid > 0)
-            shmctl(XJ_shm_infos[0].shmid, IPC_RMID, 0);
+        if (XJ_shm_infos[i]->shmaddr)
+            shmdt(XJ_shm_infos[i]->shmaddr);
+        if (XJ_shm_infos[i]->shmid > 0)
+            shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, 0);
+        delete XJ_shm_infos[i];
     }
     XJ_shm_infos.clear();
     xv_buffers.clear();
@@ -2050,6 +2070,20 @@
 #endif // USING_XVMC
 }
 
+static void convert_yv12_to_yuv420(VideoFrame *frame,
+                                   unsigned char *tmp)
+{
+    if (!tmp)
+        return;
+    unsigned char *plane1 = frame->buf + frame->offsets[1];
+    unsigned char *plane2 = frame->buf + frame->offsets[2];
+    uint uv_plane_size = (frame->width * frame->height) >> 2;
+
+    memcpy(tmp,    plane1, uv_plane_size);
+    memcpy(plane1, plane2, uv_plane_size);
+    memcpy(plane2, tmp,    uv_plane_size);
+}
+
 /**
  * \fn VideoOutputXv::PrepareFrameXv(VideoFrame *frame)
  *  
@@ -2072,16 +2106,7 @@
     if (image && (GUID_YV12_PLANAR == xv_chroma))
     {
         vbuffers.LockFrame(frame, "PrepareFrameXv -- color conversion");
-        int width = frame->width;
-        int height = frame->height;
-
-        memcpy(xv_color_conv_buf, (unsigned char *)image->data + 
-               (width * height), width * height / 4);
-        memcpy((unsigned char *)image->data + (width * height),
-               (unsigned char *)image->data + (width * height) * 5 / 4,
-               width * height / 4);
-        memcpy((unsigned char *)image->data + (width * height) * 5 / 4,
-               xv_color_conv_buf, width * height / 4);
+        convert_yv12_to_yuv420(frame, xv_color_conv_buf);
         vbuffers.UnlockFrame(frame, "PrepareFrameXv -- color conversion");
     }
 
Index: libs/libmythtv/videobuffers.h
===================================================================
--- libs/libmythtv/videobuffers.h	(revision 10733)
+++ libs/libmythtv/videobuffers.h	(working copy)
@@ -44,6 +44,20 @@
     kVideoBuffer_all       = 0x0000001F,
 };
 
+class YUVInfo
+{
+  public:
+    YUVInfo(uint w, uint h, uint size, const int *p, const int *o);
+    void Clear(unsigned char *data) const;
+
+  public:
+    uint width;
+    uint height;
+    uint size;
+    uint pitches[3];
+    uint offsets[3];
+};
+
 class VideoBuffers
 {
   public:
@@ -55,7 +69,9 @@
               uint needprebuffer_small, uint keepprebuffer,
               bool enable_frame_locking = false);
 
-    bool CreateBuffers(int width, int height, vector<unsigned char*> bufs);
+    bool CreateBuffers(int width, int height,
+                       vector<unsigned char*> bufs,
+                       vector<YUVInfo>        yuvinfo);
     bool CreateBuffers(int width, int height);
     void DeleteBuffers(void);
 
@@ -120,6 +136,9 @@
     frame_queue_t Children(const VideoFrame *frame);
     bool HasChildren(const VideoFrame *frame);
 
+    void Clear(uint i, int fourcc);
+    void Clear(int fourcc);
+
 #ifdef USING_XVMC
     VideoFrame* PastFrame(const VideoFrame *frame);
     VideoFrame* FutureFrame(const VideoFrame *frame);
Index: libs/libmythtv/videobuffers.cpp
===================================================================
--- libs/libmythtv/videobuffers.cpp	(revision 10733)
+++ libs/libmythtv/videobuffers.cpp	(working copy)
@@ -5,6 +5,7 @@
 #include "mythcontext.h"
 #include "videobuffers.h"
 #include "../libavcodec/avcodec.h"
+#include "util-xv.h"
 
 #ifdef USING_XVMC
 #include "videoout_xv.h" // for xvmc stuff
@@ -18,7 +19,47 @@
 
 int next_dbg_str = 0;
 
+YUVInfo::YUVInfo(uint w, uint h, uint sz, const int *p, const int *o)
+    : width(w), height(h), size(sz)
+{
+    if (p)
+    {
+        memcpy(pitches, p, 3 * sizeof(int));
+    }
+    else
+    {
+        pitches[0] = width;
+        pitches[1] = pitches[2] = width >> 1;
+    }
+
+    if (o)
+    {
+        memcpy(offsets, o, 3 * sizeof(int));
+    }
+    else
+    {
+        offsets[0] = 0;
+        offsets[1] = width * height;
+        offsets[2] = offsets[1] + (offsets[1] >> 2);
+    }
+}
+
 /**
+ * \fn YUVInfo::Clear(unsigned char *data) const
+ * \brief Init YUV buffer to black
+ */
+void YUVInfo::Clear(unsigned char *data) const
+{
+    uint ysize  = width * height;
+    uint uvsize = ysize >> 2;
+
+    bzero( data + offsets[0], ysize);
+    memset(data + offsets[1], 127, uvsize);
+    memset(data + offsets[2], 127, uvsize);
+}
+
+
+/**
  * \class VideoBuffers
  *  This class creates tracks the state of the buffers used by 
  *  various VideoOutput derived classes.
@@ -1071,11 +1112,13 @@
 bool VideoBuffers::CreateBuffers(int width, int height)
 {
     vector<unsigned char*> bufs;
-    return CreateBuffers(width, height, bufs);
+    vector<YUVInfo>        yuvinfo;
+    return CreateBuffers(width, height, bufs, yuvinfo);
 }
 
 bool VideoBuffers::CreateBuffers(int width, int height,
-                                 vector<unsigned char*> bufs)
+                                 vector<unsigned char*> bufs,
+                                 vector<YUVInfo>        yuvinfo)
 {
     bool ok = true;
     uint bpp = 12 / 4; /* bits per pixel div common factor */
@@ -1087,16 +1130,14 @@
     uint adj_w = (width  + 15) & ~0xF;
     uint adj_h = (height + 15) & ~0xF;
     uint buf_size = (adj_w * adj_h * bpp + 4/* to round up */) / bpb;
+
     while (bufs.size() < allocSize())
     {
         unsigned char *data = (unsigned char*)av_malloc(buf_size + 64);
 
-        // init buffers (y plane to 0, u/v planes to 127),
-        // to prevent green screens..
-        bzero(data, width * height);
-        memset(data + width * height, 127, width * height / 2);
+        bufs.push_back(data);
+        yuvinfo.push_back(YUVInfo(width, height, buf_size, NULL, NULL));
 
-        bufs.push_back(data);
         if (bufs.back())
         {
             VERBOSE(VB_PLAYBACK, "Created data @"
@@ -1106,18 +1147,23 @@
         else
             ok = false;
     }
+
     for (uint i = 0; i < allocSize(); i++)
     {
-        buffers[i].width = width;
-        buffers[i].height = height;
+        yuvinfo[i].Clear(bufs[i]);
+        buffers[i].width  = yuvinfo[i].width;
+        buffers[i].height = yuvinfo[i].height;
+        memcpy(buffers[i].pitches, yuvinfo[i].pitches, 3 * sizeof(int));
+        memcpy(buffers[i].offsets, yuvinfo[i].offsets, 3 * sizeof(int));
         buffers[i].bpp = 12;
-        buffers[i].size = buf_size;
+        buffers[i].size = max(buf_size, yuvinfo[i].size);
         buffers[i].codec = FMT_YV12;
         buffers[i].qscale_table = NULL;
         buffers[i].qstride = 0;
         buffers[i].buf = bufs[i];
         ok &= (bufs[i] != NULL);
     }
+
     return ok;
 }
 
@@ -1273,6 +1319,27 @@
     return str;
 }
 
+void VideoBuffers::Clear(uint i, int fourcc)
+{
+    if ((GUID_I420_PLANAR == fourcc) ||
+        (GUID_YV12_PLANAR == fourcc))
+    {
+        VideoFrame *vf = at(i);
+        uint ysize  = vf->width * vf->height;
+        uint uvsize = ysize >> 2;
+
+        bzero( vf->buf + vf->offsets[0], ysize);
+        memset(vf->buf + vf->offsets[1], 127, uvsize);
+        memset(vf->buf + vf->offsets[2], 127, uvsize);
+    }
+}
+
+void VideoBuffers::Clear(int fourcc)
+{
+    for (uint i = 0; i < allocSize(); i++)
+        Clear(i, fourcc);
+}
+
 /*******************************
  ** Debugging functions below **
  *******************************/
