Ticket #2171: 2171-v2.patch

File 2171-v2.patch, 16.5 KB (added by danielk, 18 years ago)

possible fix

  • libs/libmythtv/avformatdecoder.cpp

     
    15161516
    15171517    VideoFrame *frame = nd->GetNVP()->GetNextVideoFrame(true);
    15181518
    1519     int width = frame->width;
    1520     int height = frame->height;
     1519    for (int i = 0; i < 3; i++)
     1520    {
     1521        pic->data[i]     = frame->buf + frame->offsets[i];
     1522        pic->linesize[i] = frame->pitches[i];
     1523    }
    15211524
    1522     pic->data[0] = frame->buf;
    1523     pic->data[1] = pic->data[0] + width * height;
    1524     pic->data[2] = pic->data[1] + width * height / 4;
    1525 
    1526     pic->linesize[0] = width;
    1527     pic->linesize[1] = width / 2;
    1528     pic->linesize[2] = width / 2;
    1529 
    15301525    pic->opaque = frame;
    15311526    pic->type = FF_BUFFER_TYPE_USER;
    15321527
  • libs/libmythtv/util-xv.cpp

     
    8080        str.append("XvImageMask ");
    8181    return str;
    8282}
    83 
    84 void clear_xv_buffers(VideoBuffers &vbuffers,
    85                       int width, int height, int xv_chroma)
    86 {
    87     if ((GUID_I420_PLANAR == xv_chroma) ||
    88         (GUID_YV12_PLANAR == xv_chroma))
    89     {
    90         for (uint i = 0; i < vbuffers.allocSize(); i++)
    91         {
    92             unsigned char *data = vbuffers.at(i)->buf;
    93             bzero(data, width * height);
    94             memset(data + width * height, 127,
    95                    width * height / 2);
    96         }
    97     }
    98 }
  • libs/libmythtv/frame.h

     
    3737    int top_field_first; // 1 if top field is first.
    3838    int repeat_pict;
    3939    int forcekey; // hardware encoded .nuv
     40
     41    int pitches[3]; // Y, U, & V pitches
     42    int offsets[3]; // Y, U, & V offsets
    4043} VideoFrame;
    4144
    4245#endif
  • libs/libmythtv/util-xv.h

     
    2828extern bool has_open_xv_port(int port);
    2929extern uint cnt_open_xv_port(void);
    3030extern QString xvflags2str(int flags);
    31 extern void clear_xv_buffers(VideoBuffers&, int w, int h, int xv_chroma);
    3231
    3332#endif // _UTIL_XV_H_
  • libs/libmythtv/videoout_xv.h

     
    187187
    188188    // Used for all non-XvMC drawing
    189189    VideoFrame           av_pause_frame;
    190     vector<XShmSegmentInfo> XJ_shm_infos;
     190    vector<XShmSegmentInfo*> XJ_shm_infos;
     191    vector<YUVInfo>      XJ_yuv_infos;
    191192
    192193    // Basic non-Xv drawing info
    193194    XImage              *XJ_non_xv_image;
  • libs/libmythtv/videoout_xv.cpp

     
    199199    if (!res_changed && !cid_changed)
    200200    {
    201201        if (VideoOutputSubType() == XVideo)
    202             clear_xv_buffers(vbuffers, video_dim.width(), video_dim.height(),
    203                              xv_chroma);
     202            vbuffers.Clear(xv_chroma);
    204203        if (asp_changed)
    205204            MoveResize();
    206205        return;
     
    15001499            .arg(num).arg(video_dim.width()).arg(video_dim.height()));
    15011500
    15021501    vector<unsigned char*> bufs;
    1503     XShmSegmentInfo blank;
    1504     // for now make reserve big enough to avoid realloc..
    1505     // we should really have vector of pointers...
    1506     XJ_shm_infos.reserve(max(num + 32, (uint)128));
    15071502    for (uint i = 0; i < num; i++)
    15081503    {
    1509         XJ_shm_infos.push_back(blank);
     1504        XShmSegmentInfo *info = new XShmSegmentInfo;
    15101505        void *image = NULL;
    15111506        int size = 0;
    15121507        int desiredsize = 0;
     
    15151510
    15161511        if (use_xv)
    15171512        {
    1518             image = XvShmCreateImage(XJ_disp, xv_port, xv_chroma, 0,
    1519                                      video_dim.width(), video_dim.height(),
    1520                                      &XJ_shm_infos[i]);
    1521             size = ((XvImage*)image)->data_size + 64;
     1513            XvImage *img =
     1514                XvShmCreateImage(XJ_disp, xv_port, xv_chroma, 0,
     1515                                 video_dim.width(), video_dim.height(), info);
     1516            size = img->data_size + 64;
     1517            image = img;
    15221518            desiredsize = video_dim.width() * video_dim.height() * 3 / 2;
    15231519
    15241520            if (image && size < desiredsize)
     
    15281524                        "requested size.");
    15291525                XFree(image);
    15301526                image = NULL;
     1527                delete info;
    15311528            }
     1529
     1530            if (image && (3 == img->num_planes))
     1531            {
     1532                XJ_shm_infos.push_back(info);
     1533                YUVInfo tmp(img->width, img->height, img->data_size,
     1534                            img->pitches, img->offsets);
     1535                XJ_yuv_infos.push_back(tmp);
     1536            }
     1537            else if (image)
     1538            {
     1539                VERBOSE(VB_IMPORTANT, LOC_ERR + "CreateXvShmImages(): "
     1540                        "XvShmCreateImage() failed to create image "
     1541                        "with the correct number of pixel planes.");
     1542                XFree(image);
     1543                image = NULL;
     1544                delete info;
     1545            }
    15321546        }
    15331547        else
    15341548        {
    15351549            XImage *img =
    15361550                XShmCreateImage(XJ_disp, DefaultVisual(XJ_disp, XJ_screen_num),
    1537                                 XJ_depth, ZPixmap, 0, &XJ_shm_infos[i],
     1551                                XJ_depth, ZPixmap, 0, info,
    15381552                                display_visible_rect.width(),
    15391553                                display_visible_rect.height());
    15401554            size = img->bytes_per_line * img->height + 64;
     
    15481562                        "requested size.");
    15491563                XDestroyImage((XImage *)image);
    15501564                image = NULL;
     1565                delete info;
    15511566            }
     1567
     1568            if (image)
     1569            {
     1570                YUVInfo tmp(img->width, img->height,
     1571                            img->bytes_per_line * img->height, NULL, NULL);
     1572                XJ_yuv_infos.push_back(tmp);
     1573            }
    15521574        }
    15531575
    15541576        X11U;
    15551577
    15561578        if (image)
    15571579        {
    1558             XJ_shm_infos[i].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
    1559             if (XJ_shm_infos[i].shmid >= 0)
     1580            XJ_shm_infos[i]->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
     1581            if (XJ_shm_infos[i]->shmid >= 0)
    15601582            {
    1561                 XJ_shm_infos[i].shmaddr = (char*) shmat(XJ_shm_infos[i].shmid, 0, 0);
     1583                XJ_shm_infos[i]->shmaddr = (char*) shmat(XJ_shm_infos[i]->shmid, 0, 0);
    15621584                if (use_xv)
    1563                     ((XvImage*)image)->data = XJ_shm_infos[i].shmaddr;
     1585                    ((XvImage*)image)->data = XJ_shm_infos[i]->shmaddr;
    15641586                else
    1565                     ((XImage*)image)->data = XJ_shm_infos[i].shmaddr;
    1566                 xv_buffers[(unsigned char*) XJ_shm_infos[i].shmaddr] = image;
    1567                 XJ_shm_infos[i].readOnly = False;
     1587                    ((XImage*)image)->data = XJ_shm_infos[i]->shmaddr;
     1588                xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr] = image;
     1589                XJ_shm_infos[i]->readOnly = False;
    15681590
    15691591                X11L;
    1570                 XShmAttach(XJ_disp, &XJ_shm_infos[i]);
     1592                XShmAttach(XJ_disp, XJ_shm_infos[i]);
    15711593                XSync(XJ_disp, False); // needed for FreeBSD?
    15721594                X11U;
    15731595
    15741596                // Mark for delete immediately.
    15751597                // It won't actually be removed until after we detach it.
    1576                 shmctl(XJ_shm_infos[i].shmid, IPC_RMID, 0);
     1598                shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, 0);
    15771599
    1578                 bufs.push_back((unsigned char*) XJ_shm_infos[i].shmaddr);
     1600                bufs.push_back((unsigned char*) XJ_shm_infos[i]->shmaddr);
    15791601            }
    15801602            else
    15811603            {
     
    16051627        vector<unsigned char*> bufs =
    16061628            CreateShmImages(vbuffers.allocSize(), true);
    16071629        ok = vbuffers.CreateBuffers(
    1608             video_dim.width(), video_dim.height(), bufs);
     1630            video_dim.width(), video_dim.height(), bufs, XJ_yuv_infos);
    16091631
    1610         clear_xv_buffers(vbuffers, video_dim.width(), video_dim.height(),
    1611                          xv_chroma);
    1612 
    16131632        X11S(XSync(XJ_disp, False));
    16141633        if (xv_chroma != GUID_I420_PLANAR)
    16151634            xv_color_conv_buf = new unsigned char[
     
    17471766        }
    17481767    }
    17491768
    1750     for (uint i=0; i<XJ_shm_infos.size(); ++i)
     1769    for (uint i = 0; i < XJ_shm_infos.size(); i++)
    17511770    {
    1752         X11S(XShmDetach(XJ_disp, &(XJ_shm_infos[i])));
     1771        X11S(XShmDetach(XJ_disp, XJ_shm_infos[i]));
    17531772        XvImage *image = (XvImage*)
    1754             xv_buffers[(unsigned char*)XJ_shm_infos[i].shmaddr];
     1773            xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr];
    17551774        if (image)
    17561775        {
    17571776            if ((XImage*)image == (XImage*)XJ_non_xv_image)
     
    17591778            else
    17601779                X11S(XFree(image));
    17611780        }
    1762         if (XJ_shm_infos[i].shmaddr)
    1763             shmdt(XJ_shm_infos[i].shmaddr);
    1764         if (XJ_shm_infos[i].shmid > 0)
    1765             shmctl(XJ_shm_infos[0].shmid, IPC_RMID, 0);
     1781        if (XJ_shm_infos[i]->shmaddr)
     1782            shmdt(XJ_shm_infos[i]->shmaddr);
     1783        if (XJ_shm_infos[i]->shmid > 0)
     1784            shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, 0);
     1785        delete XJ_shm_infos[i];
    17661786    }
    17671787    XJ_shm_infos.clear();
    17681788    xv_buffers.clear();
     
    20502070#endif // USING_XVMC
    20512071}
    20522072
     2073static void convert_yv12_to_yuv420(VideoFrame *frame,
     2074                                   unsigned char *tmp)
     2075{
     2076    if (!tmp)
     2077        return;
     2078    unsigned char *plane1 = frame->buf + frame->offsets[1];
     2079    unsigned char *plane2 = frame->buf + frame->offsets[2];
     2080    uint uv_plane_size = (frame->width * frame->height) >> 2;
     2081
     2082    memcpy(tmp,    plane1, uv_plane_size);
     2083    memcpy(plane1, plane2, uv_plane_size);
     2084    memcpy(plane2, tmp,    uv_plane_size);
     2085}
     2086
    20532087/**
    20542088 * \fn VideoOutputXv::PrepareFrameXv(VideoFrame *frame)
    20552089 * 
     
    20722106    if (image && (GUID_YV12_PLANAR == xv_chroma))
    20732107    {
    20742108        vbuffers.LockFrame(frame, "PrepareFrameXv -- color conversion");
    2075         int width = frame->width;
    2076         int height = frame->height;
    2077 
    2078         memcpy(xv_color_conv_buf, (unsigned char *)image->data +
    2079                (width * height), width * height / 4);
    2080         memcpy((unsigned char *)image->data + (width * height),
    2081                (unsigned char *)image->data + (width * height) * 5 / 4,
    2082                width * height / 4);
    2083         memcpy((unsigned char *)image->data + (width * height) * 5 / 4,
    2084                xv_color_conv_buf, width * height / 4);
     2109        convert_yv12_to_yuv420(frame, xv_color_conv_buf);
    20852110        vbuffers.UnlockFrame(frame, "PrepareFrameXv -- color conversion");
    20862111    }
    20872112
  • libs/libmythtv/videobuffers.h

     
    4444    kVideoBuffer_all       = 0x0000001F,
    4545};
    4646
     47class YUVInfo
     48{
     49  public:
     50    YUVInfo(uint w, uint h, uint size, const int *p, const int *o);
     51    void Clear(unsigned char *data) const;
     52
     53  public:
     54    uint width;
     55    uint height;
     56    uint size;
     57    uint pitches[3];
     58    uint offsets[3];
     59};
     60
    4761class VideoBuffers
    4862{
    4963  public:
     
    5569              uint needprebuffer_small, uint keepprebuffer,
    5670              bool enable_frame_locking = false);
    5771
    58     bool CreateBuffers(int width, int height, vector<unsigned char*> bufs);
     72    bool CreateBuffers(int width, int height,
     73                       vector<unsigned char*> bufs,
     74                       vector<YUVInfo>        yuvinfo);
    5975    bool CreateBuffers(int width, int height);
    6076    void DeleteBuffers(void);
    6177
     
    120136    frame_queue_t Children(const VideoFrame *frame);
    121137    bool HasChildren(const VideoFrame *frame);
    122138
     139    void Clear(uint i, int fourcc);
     140    void Clear(int fourcc);
     141
    123142#ifdef USING_XVMC
    124143    VideoFrame* PastFrame(const VideoFrame *frame);
    125144    VideoFrame* FutureFrame(const VideoFrame *frame);
  • libs/libmythtv/videobuffers.cpp

     
    55#include "mythcontext.h"
    66#include "videobuffers.h"
    77#include "../libavcodec/avcodec.h"
     8#include "util-xv.h"
    89
    910#ifdef USING_XVMC
    1011#include "videoout_xv.h" // for xvmc stuff
     
    1819
    1920int next_dbg_str = 0;
    2021
     22YUVInfo::YUVInfo(uint w, uint h, uint sz, const int *p, const int *o)
     23    : width(w), height(h), size(sz)
     24{
     25    if (p)
     26    {
     27        memcpy(pitches, p, 3 * sizeof(int));
     28    }
     29    else
     30    {
     31        pitches[0] = width;
     32        pitches[1] = pitches[2] = width >> 1;
     33    }
     34
     35    if (o)
     36    {
     37        memcpy(offsets, o, 3 * sizeof(int));
     38    }
     39    else
     40    {
     41        offsets[0] = 0;
     42        offsets[1] = width * height;
     43        offsets[2] = offsets[1] + (offsets[1] >> 2);
     44    }
     45}
     46
    2147/**
     48 * \fn YUVInfo::Clear(unsigned char *data) const
     49 * \brief Init YUV buffer to black
     50 */
     51void YUVInfo::Clear(unsigned char *data) const
     52{
     53    uint ysize  = width * height;
     54    uint uvsize = ysize >> 2;
     55
     56    bzero( data + offsets[0], ysize);
     57    memset(data + offsets[1], 127, uvsize);
     58    memset(data + offsets[2], 127, uvsize);
     59}
     60
     61
     62/**
    2263 * \class VideoBuffers
    2364 *  This class creates tracks the state of the buffers used by
    2465 *  various VideoOutput derived classes.
     
    10711112bool VideoBuffers::CreateBuffers(int width, int height)
    10721113{
    10731114    vector<unsigned char*> bufs;
    1074     return CreateBuffers(width, height, bufs);
     1115    vector<YUVInfo>        yuvinfo;
     1116    return CreateBuffers(width, height, bufs, yuvinfo);
    10751117}
    10761118
    10771119bool VideoBuffers::CreateBuffers(int width, int height,
    1078                                  vector<unsigned char*> bufs)
     1120                                 vector<unsigned char*> bufs,
     1121                                 vector<YUVInfo>        yuvinfo)
    10791122{
    10801123    bool ok = true;
    10811124    uint bpp = 12 / 4; /* bits per pixel div common factor */
     
    10871130    uint adj_w = (width  + 15) & ~0xF;
    10881131    uint adj_h = (height + 15) & ~0xF;
    10891132    uint buf_size = (adj_w * adj_h * bpp + 4/* to round up */) / bpb;
     1133
    10901134    while (bufs.size() < allocSize())
    10911135    {
    10921136        unsigned char *data = (unsigned char*)av_malloc(buf_size + 64);
    10931137
    1094         // init buffers (y plane to 0, u/v planes to 127),
    1095         // to prevent green screens..
    1096         bzero(data, width * height);
    1097         memset(data + width * height, 127, width * height / 2);
     1138        bufs.push_back(data);
     1139        yuvinfo.push_back(YUVInfo(width, height, buf_size, NULL, NULL));
    10981140
    1099         bufs.push_back(data);
    11001141        if (bufs.back())
    11011142        {
    11021143            VERBOSE(VB_PLAYBACK, "Created data @"
     
    11061147        else
    11071148            ok = false;
    11081149    }
     1150
    11091151    for (uint i = 0; i < allocSize(); i++)
    11101152    {
    1111         buffers[i].width = width;
    1112         buffers[i].height = height;
     1153        yuvinfo[i].Clear(bufs[i]);
     1154        buffers[i].width  = yuvinfo[i].width;
     1155        buffers[i].height = yuvinfo[i].height;
     1156        memcpy(buffers[i].pitches, yuvinfo[i].pitches, 3 * sizeof(int));
     1157        memcpy(buffers[i].offsets, yuvinfo[i].offsets, 3 * sizeof(int));
    11131158        buffers[i].bpp = 12;
    1114         buffers[i].size = buf_size;
     1159        buffers[i].size = max(buf_size, yuvinfo[i].size);
    11151160        buffers[i].codec = FMT_YV12;
    11161161        buffers[i].qscale_table = NULL;
    11171162        buffers[i].qstride = 0;
    11181163        buffers[i].buf = bufs[i];
    11191164        ok &= (bufs[i] != NULL);
    11201165    }
     1166
    11211167    return ok;
    11221168}
    11231169
     
    12731319    return str;
    12741320}
    12751321
     1322void VideoBuffers::Clear(uint i, int fourcc)
     1323{
     1324    if ((GUID_I420_PLANAR == fourcc) ||
     1325        (GUID_YV12_PLANAR == fourcc))
     1326    {
     1327        VideoFrame *vf = at(i);
     1328        uint ysize  = vf->width * vf->height;
     1329        uint uvsize = ysize >> 2;
     1330
     1331        bzero( vf->buf + vf->offsets[0], ysize);
     1332        memset(vf->buf + vf->offsets[1], 127, uvsize);
     1333        memset(vf->buf + vf->offsets[2], 127, uvsize);
     1334    }
     1335}
     1336
     1337void VideoBuffers::Clear(int fourcc)
     1338{
     1339    for (uint i = 0; i < allocSize(); i++)
     1340        Clear(i, fourcc);
     1341}
     1342
    12761343/*******************************
    12771344 ** Debugging functions below **
    12781345 *******************************/