00001
00002
00003
00004 #ifdef USING_XVMC
00005
00006 #include <sys/types.h>
00007 #include <sys/ipc.h>
00008 #include <sys/shm.h>
00009 #include <unistd.h>
00010
00011 #include "osdxvmc.h"
00012 #include "videoout_xv.h"
00013
00014 extern "C" XvImage *XvShmCreateImage(Display*, XvPortID, int, char*,
00015 int, int, XShmSegmentInfo*);
00016
00017 #define NO_SUBPICTURE 0
00018 #define OVERLAY_SUBPICTURE 1
00019 #define BLEND_SUBPICTURE 2
00020 #define BACKEND_SUBPICTURE 3
00021
00022 static inline xvmc_render_state_t *GetRender(VideoFrame *frame);
00023
00024 XvMCOSD::XvMCOSD(Display *disp, int port, int surface_type_id,
00025 int xvmc_surf_flags)
00026 : XJ_disp(disp), XJ_width(0), XJ_height(0),
00027 xv_port(port), osd_palette(NULL), osd_xv_image(NULL),
00028 osd_subpict_mode(NO_SUBPICTURE), osd_subpict_clear_color(0),
00029 osd_subpict_alloc(false)
00030 {
00031 bzero(&osd_subpict, sizeof(osd_subpict));
00032
00033 int num = 0;
00034 XvImageFormatValues *xvfmv = NULL;
00035 X11S(xvfmv = XvMCListSubpictureTypes(XJ_disp, xv_port,
00036 surface_type_id, &num));
00037
00038 for (int i = (xvfmv) ? 0 : num; i < num; i++)
00039 {
00040 if (GUID_IA44_PACKED == xvfmv[i].id || GUID_AI44_PACKED == xvfmv[i].id)
00041 {
00042 osd_subpict_info = xvfmv[i];
00043 bool be = (XVMC_BACKEND_SUBPICTURE & xvmc_surf_flags);
00044 osd_subpict_mode = (be) ? BACKEND_SUBPICTURE : BLEND_SUBPICTURE;
00045 break;
00046 }
00047 }
00048
00049 if (xvfmv)
00050 X11S(XFree(xvfmv));
00051 }
00052
00053 void XvMCOSD::CreateBuffer(XvMCContext &xvmc_ctx, int width, int height)
00054 {
00055 if (NO_SUBPICTURE == osd_subpict_mode)
00056 {
00057 VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed because "
00058 "no subpicture is available");
00059 osd_subpict_alloc = false;
00060 return;
00061 }
00062
00063 XJ_width = width;
00064 XJ_height = height;
00065
00066 osd_subpict_clear_color = 0;
00067 int ret = Success;
00068 X11S(ret = XvMCCreateSubpicture(XJ_disp, &xvmc_ctx, &osd_subpict,
00069 XJ_width, XJ_height, osd_subpict_info.id));
00070
00071 if (ret != Success)
00072 {
00073 VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvMCCreateSubpicture");
00074 osd_subpict_mode = NO_SUBPICTURE;
00075 osd_subpict_alloc = false;
00076 return;
00077 }
00078
00079 X11L;
00080 XvMCClearSubpicture(XJ_disp, &osd_subpict, 0, 0, XJ_width,
00081 XJ_height, osd_subpict_clear_color);
00082
00083 osd_xv_image = XvShmCreateImage(XJ_disp, xv_port,
00084 osd_subpict_info.id, NULL,
00085 XJ_width, XJ_height,
00086 &XJ_osd_shm_info);
00087 X11U;
00088
00089 if (!osd_xv_image)
00090 {
00091 VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvShmCreateImage");
00092 osd_subpict_mode = NO_SUBPICTURE;
00093 osd_subpict_alloc = false;
00094 return;
00095 }
00096 XJ_osd_shm_info.shmid = shmget(IPC_PRIVATE, osd_xv_image->data_size,
00097 IPC_CREAT | 0777);
00098 XJ_osd_shm_info.shmaddr = (char *)shmat(XJ_osd_shm_info.shmid, 0, 0);
00099 XJ_osd_shm_info.readOnly = False;
00100
00101 osd_xv_image->data = XJ_osd_shm_info.shmaddr;
00102
00103 X11S(XShmAttach(XJ_disp, &XJ_osd_shm_info));
00104
00105 shmctl(XJ_osd_shm_info.shmid, IPC_RMID, 0);
00106
00107 if (osd_subpict.num_palette_entries > 0)
00108 {
00109 int snum = osd_subpict.num_palette_entries;
00110 int seb = osd_subpict.entry_bytes;
00111
00112 osd_palette = new unsigned char[snum * seb];
00113
00114 for (int i = 0; i < snum; i++)
00115 {
00116 int Y = i * (1 << osd_subpict_info.y_sample_bits) / snum;
00117 int U = 1 << (osd_subpict_info.u_sample_bits - 1);
00118 int V = 1 << (osd_subpict_info.v_sample_bits - 1);
00119 for (int j = 0; j < seb; j++)
00120 {
00121 switch (osd_subpict.component_order[j])
00122 {
00123 case 'U': osd_palette[i * seb + j] = U; break;
00124 case 'V': osd_palette[i * seb + j] = V; break;
00125 case 'Y':
00126 default: osd_palette[i * seb + j] = Y; break;
00127 }
00128 }
00129 }
00130
00131 X11S(XvMCSetSubpicturePalette(XJ_disp, &osd_subpict, osd_palette));
00132 }
00133 osd_subpict_alloc = true;
00134 }
00135
00136 void XvMCOSD::DeleteBuffer()
00137 {
00138 if (!osd_subpict_alloc)
00139 return;
00140
00141 X11L;
00142 XvMCDestroySubpicture(XJ_disp, &osd_subpict);
00143
00144 XShmDetach(XJ_disp, &XJ_osd_shm_info);
00145 shmdt(XJ_osd_shm_info.shmaddr);
00146
00147 osd_subpict_alloc = false;
00148 XFree(osd_xv_image);
00149 XFlush(XJ_disp);
00150 X11U;
00151 usleep(50);
00152
00153 X11S(XSync(XJ_disp, false));
00154
00155 if (osd_palette)
00156 delete [] osd_palette;
00157 }
00158
00159 void XvMCOSD::CompositeOSD(VideoFrame* frame, VideoFrame* osdframe)
00160 {
00161 if (!osd_subpict_alloc)
00162 return;
00163
00164 X11L;
00165 XvMCCompositeSubpicture(XJ_disp, &osd_subpict,
00166 osd_xv_image, 0, 0,
00167 XJ_width, XJ_height, 0, 0);
00168
00169 XvMCFlushSubpicture(XJ_disp, &osd_subpict);
00170 X11U;
00171
00172 if (osd_subpict_mode == BLEND_SUBPICTURE && osdframe)
00173 {
00174 xvmc_render_state_t *render = GetRender(frame);
00175 xvmc_render_state_t *osdren = GetRender(osdframe);
00176
00177 X11S(XvMCSyncSubpicture(XJ_disp, &osd_subpict));
00178 VideoOutputXv::SyncSurface(frame);
00179
00180 X11L;
00181 XvMCBlendSubpicture2(XJ_disp, render->p_surface,
00182 osdren->p_surface, &osd_subpict,
00183 0, 0, XJ_width, XJ_height,
00184 0, 0, XJ_width, XJ_height);
00185 XvMCFlushSurface(XJ_disp, osdren->p_surface);
00186 X11U;
00187 }
00188 else if (osd_subpict_mode == BACKEND_SUBPICTURE)
00189 {
00190 X11L;
00191 XvMCSyncSubpicture(XJ_disp, &osd_subpict);
00192 XvMCBlendSubpicture(XJ_disp, GetRender(frame)->p_surface,
00193 &osd_subpict, 0, 0, XJ_width,
00194 XJ_height, 0, 0, XJ_width, XJ_height);
00195 XvMCFlushSurface(XJ_disp, GetRender(frame)->p_surface);
00196 X11U;
00197 }
00198
00199 }
00200
00201 bool XvMCOSD::NeedFrame()
00202 {
00203 return osd_subpict_mode == BLEND_SUBPICTURE;
00204 }
00205
00206 bool XvMCOSD::IsValid()
00207 {
00208 return osd_subpict_mode != NO_SUBPICTURE &&
00209 osd_subpict_mode != OVERLAY_SUBPICTURE;
00210 }
00211
00212 static inline xvmc_render_state_t *GetRender(VideoFrame *frame)
00213 {
00214 if (frame)
00215 return (xvmc_render_state_t*) frame->buf;
00216 else
00217 return NULL;
00218 }
00219
00220 #endif // USING_XVMC