00001 #include "osdchromakey.h"
00002
00003
00004
00005
00006 #include <cmath>
00007
00008
00009 #include <sys/ipc.h>
00010 #include <sys/shm.h>
00011
00012
00013 #include "osd.h"
00014 #include "osdsurface.h"
00015 #include "osdchromakey.h"
00016
00017 #include "mythcontext.h"
00018 #include "videoout_xv.h"
00019 #include "util-x11.h"
00020
00021 #define LOC QString("OSDChroma: ")
00022 #define LOC_ERR QString("OSDChroma Error: ")
00023
00024 void ChromaKeyOSD::AllocImage(int i)
00025 {
00026 X11L;
00027 XImage *shm_img =
00028 XShmCreateImage(videoOutput->XJ_disp,
00029 DefaultVisual(videoOutput->XJ_disp,
00030 videoOutput->XJ_screen_num),
00031 videoOutput->XJ_depth, ZPixmap, 0,
00032 &shm_infos[i],
00033 videoOutput->display_visible_rect.width(),
00034 videoOutput->display_visible_rect.height());
00035 uint size = shm_img->bytes_per_line * (shm_img->height+1) + 128;
00036 X11U;
00037
00038 if (shm_img)
00039 {
00040 shm_infos[i].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
00041 if (shm_infos[i].shmid >= 0)
00042 {
00043 shm_infos[i].shmaddr = (char*) shmat(shm_infos[i].shmid, 0, 0);
00044
00045 shm_img->data = shm_infos[i].shmaddr;
00046 shm_infos[i].readOnly = False;
00047
00048 X11L;
00049 XShmAttach(videoOutput->XJ_disp, &shm_infos[i]);
00050 XSync(videoOutput->XJ_disp, False);
00051 X11U;
00052
00053
00054
00055 shmctl(shm_infos[i].shmid, IPC_RMID, 0);
00056 }
00057 }
00058
00059 img[i] = shm_img;
00060 bzero((vf+i), sizeof(VideoFrame));
00061 vf[i].buf = (unsigned char*) shm_infos[i].shmaddr;
00062 vf[i].codec = FMT_ARGB32;
00063 vf[i].height = videoOutput->display_visible_rect.height();
00064 vf[i].width = videoOutput->display_visible_rect.width();
00065 vf[i].bpp = 32;
00066 }
00067
00068 void ChromaKeyOSD::FreeImage(int i)
00069 {
00070 if (!img[i])
00071 return;
00072
00073 X11L;
00074 XShmDetach(videoOutput->XJ_disp, &(shm_infos[i]));
00075 XFree(img[i]);
00076 img[i] = NULL;
00077 X11U;
00078
00079 if (shm_infos[i].shmaddr)
00080 shmdt(shm_infos[i].shmaddr);
00081 if (shm_infos[i].shmid > 0)
00082 shmctl(shm_infos[0].shmid, IPC_RMID, 0);
00083
00084 bzero((shm_infos+i), sizeof(XShmSegmentInfo));
00085 bzero((vf+i), sizeof(VideoFrame));
00086 }
00087
00088 void ChromaKeyOSD::Reinit(int i)
00089 {
00090
00091 QSize new_res(vf[i].width, vf[i].height);
00092 if (new_res != videoOutput->display_visible_rect.size())
00093 {
00094 FreeImage(i);
00095 AllocImage(i);
00096 }
00097
00098 uint key = videoOutput->xv_colorkey;
00099 uint bpl = img[i]->bytes_per_line;
00100
00101
00102 char *cln = (char*)av_malloc(bpl + 128);
00103 bzero(cln, bpl);
00104 int j = max(videoOutput->display_video_rect.left() -
00105 videoOutput->display_visible_rect.left(), 0);
00106 int ej = min(videoOutput->display_video_rect.left() +
00107 videoOutput->display_video_rect.width(), vf[i].width);
00108 for (; j < ej; ++j)
00109 ((uint*)cln)[j] = key;
00110
00111
00112 int boboff = (int) round(
00113 ((double)videoOutput->display_video_rect.height()) / 456 - 0.00001);
00114 boboff = (videoOutput->m_deinterlacing &&
00115 videoOutput->m_deintfiltername == "bobdeint") ? boboff : 0;
00116
00117
00118 int cstart = min(max(videoOutput->display_video_rect.top() + boboff, 0),
00119 vf[i].height - 1);
00120 int cend = min(max(videoOutput->display_video_rect.top() +
00121 videoOutput->display_video_rect.height(), 0),
00122 vf[i].height);
00123
00124
00125 char *buf = shm_infos[i].shmaddr;
00126 int ldispy = min(max(videoOutput->display_visible_rect.top(), 0),
00127 vf[i].height - 1);
00128
00129 VERBOSE(VB_PLAYBACK, LOC + "cstart: "<<cstart<<" cend: "<<cend);
00130 VERBOSE(VB_PLAYBACK, LOC + "ldispy: "<<ldispy<<" height: "<<vf[i].height);
00131
00132 if (cstart > ldispy)
00133 bzero(buf + (ldispy * bpl), (cstart - ldispy) * bpl);
00134 for (j = cstart; j < cend; ++j)
00135 memcpy(buf + (j*bpl), cln, bpl);
00136 if (cend < vf[i].height)
00137 bzero(buf + (cend * bpl), (vf[i].height - cend) * bpl);
00138
00139 av_free(cln);
00140 }
00141
00146 bool ChromaKeyOSD::ProcessOSD(OSD *osd)
00147 {
00148 OSDSurface *osdsurf = NULL;
00149 if (osd)
00150 osdsurf = osd->Display();
00151
00152 int next = (current+1) & 0x1;
00153 if (!osdsurf && current >= 0)
00154 {
00155 Reset();
00156 return true;
00157 }
00158 else if (!osdsurf || (revision == osdsurf->GetRevision()))
00159 return false;
00160
00161
00162 Reinit(next);
00163
00164
00165 unsigned char *buf = (unsigned char*) shm_infos[next].shmaddr;
00166 osdsurf->BlendToARGB(buf, img[next]->bytes_per_line, vf[next].height,
00167 false, 16);
00168
00169
00170 revision = osdsurf->GetRevision();
00171 current = next;
00172
00173 return true;
00174 }
00175