MythTV  master
util-osd.cpp
Go to the documentation of this file.
1 #include "util-osd.h"
2 #include "dithertable.h"
3 
4 #if HAVE_BIGENDIAN
5 #define R_OI 1
6 #define G_OI 2
7 #define B_OI 3
8 #define A_OI 0
9 #else
10 #define R_OI 2
11 #define G_OI 1
12 #define B_OI 0
13 #define A_OI 3
14 #endif
15 
16 void yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image,
17  int left, int top, int right, int bottom)
18 {
19  static bool s_bReported;
20  bool c_aligned = !(left % ALIGN_C || top % ALIGN_C);
21 
22 #ifdef MMX
23  if (c_aligned &&
24  !(left % ALIGN_X_MMX || right % ALIGN_X_MMX || bottom % ALIGN_C) )
25  {
26  mmx_yuv888_to_yv12(frame, osd_image, left, top, right, bottom);
27  return;
28  }
29 
30  // This can happen with a non fullscreen window
31  if (c_aligned && !s_bReported)
32  {
33  s_bReported = true;
34  LOG(VB_GENERAL, LOG_WARNING, QString(
35  "OSD image size is odd; performance will suffer.\n"
36  "\t\t\tVideo window position and size must be a multiple of %1x%2.")
37  .arg(ALIGN_X_MMX).arg(ALIGN_C));
38  }
39 #endif
40 
41  if (c_aligned)
42  {
43  c_yuv888_to_yv12(frame, osd_image, left, top, right, bottom);
44  return;
45  }
46 
47  if (!s_bReported)
48  {
49  s_bReported = true;
50  LOG(VB_GENERAL, LOG_WARNING, QString(
51  "Unable to display the OSD.\n"
52  "\t\t\tVideo window position and size must be a multiple of %1x%2.")
53  .arg(ALIGN_C).arg(ALIGN_C));
54  }
55 }
56 
57 #ifdef MMX
58 #define ASM(code) __asm__ __volatile__(code);
59 void inline mmx_yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image,
60  int left, int top, int right, int bottom)
61 {
62  unsigned char *src1, *src2, *y1, *y2, *u, *v;
63  int y_wrap, src_wrap, u_wrap, v_wrap, width, height;
64 
65  width = right - left;
66  height = bottom - top;
67  src1 = osd_image->scanLine(top) + (left << 2);
68  src2 = src1 + osd_image->bytesPerLine();
69  src_wrap = (osd_image->bytesPerLine() << 1)- (width << 2);
70 
71  y1 = frame->buf + frame->offsets[0] + (frame->pitches[0] * top) + left;
72  y2 = y1 + frame->pitches[0];
73  u = frame->buf + frame->offsets[1] +
74  (frame->pitches[1] * (top >> 1)) + (left >> 1);
75  v = frame->buf + frame->offsets[2] +
76  (frame->pitches[2] * (top >> 1)) + (left >> 1);
77  y_wrap = (frame->pitches[0] << 1) - width;
78  u_wrap = frame->pitches[1] - (width >> 1);
79  v_wrap = frame->pitches[2] - (width >> 1);
80 
81  static long long MMX_MAX = 0xFFFFFFFFFFFFFFFFLL;
82  static long long MMX_MIN = 0x0000000000000000LL;
83  static long long MMX_255 = 0x00FF00FF00FF00FFLL;
84  static long long tmp_u, tmp_v, tmp_a;
85 
86  for (int row = 0; row < height; row += 2)
87  {
88  for (int col = 0; col < (width >> 3); col++)
89  {
90  // here be pain
91  // unpack and luminance - row 1 01234567
92  ASM("movq %0, %%mm1"::"m"(src1[0])) // mm1: A2Y2U2V2 A1Y1U1V1 .t......
93  ASM("movq %mm1, %mm2") // mm2: A2Y2U2V2 A1Y1U1V1 .tt.....
94  ASM("punpckhbw %0, %%mm1"::"m"(src1[8])) // mm1: A4A2Y4Y2 U4U2V4V2 .tt.....
95  ASM("punpcklbw %0, %%mm2"::"m"(src1[8])) // mm2: A3A1Y3Y1 U3U1V3V1 .tt.....
96  ASM("movq %mm2, %mm0") // mm0: A3A1Y3Y1 U3U1V3V1 ttt.....
97  ASM("punpckhbw %mm1, %mm2") // mm2: A4A3A2A1 Y4Y3Y2Y1 .tA..... AY stage 1
98  ASM("punpcklbw %mm1, %mm0") // mm0: U4U3U2U1 V4V3V2V1 U.A..... UV stage 1
99  ASM("movq %0, %%mm3"::"m"(src1[16])) // mm3: A6Y6U6V6 A5Y5U5V5 U.At....
100  ASM("movq %mm3, %mm4") // mm4: A6Y6U6V6 A5YU55V5 U.Att...
101  ASM("punpckhbw %0, %%mm3"::"m"(src1[24])) // mm3: A8A6Y8Y6 U8U6V8V6 U.Att...
102  ASM("punpcklbw %0, %%mm4"::"m"(src1[24])) // mm4: A7A5Y7Y5 U7U5V7V5 U.Att...
103  ASM("movq %mm4, %mm1") // mm1: A7A5Y7Y5 U7U5V7V5 UtAtt...
104  ASM("punpckhbw %mm3, %mm1") // mm1: A8A7A6A5 Y8Y7Y6Y5 UtAtt... AY stage 2
105  ASM("punpcklbw %mm3, %mm4") // mm4: U8U7U6U5 V8V7V6V5 UtA.V... UV stage 2
106  ASM("movq %mm2, %mm3") // mm3: A4A3A2A1 Y4Y3Y2Y1 UtAtV...
107  ASM("punpckldq %mm1, %mm3") // mm3: Y8Y7Y6Y5 Y4Y3Y2Y1 UtAYV... 8-1 Y
108  ASM("punpckhdq %mm1, %mm2") // mm2: A8A7A6A5 A4A3A2A1 UtAYV... 8-1 A
109  ASM("movq %0, %%mm7"::"m"(MMX_MAX)) // mm7: FFFFFFFF FFFFFFFF U.AYV..t 255
110  ASM("psubusb %mm2, %mm7") // mm7: A8A7A6A5 A4A3A2A1 U.AYV..t 8-1 (255-a)
111  ASM("movq %mm7, %mm6") // mm6: A8A7A6A5 A4A3A2A1 U.AYV.tt 8-1 (255-a)
112  ASM("movq %mm7, %mm2") // mm2: A8A7A6A5 A4A3A2A1 U.AYV.tt 8-1 (255-a)
113  ASM("punpckhbw %0, %%mm7"::"m"(MMX_MIN)) // mm7: 00A800A7 00A600A4 U.AYV.tt 8-5 (255-a)
114  ASM("punpcklbw %0, %%mm6"::"m"(MMX_MIN)) // mm6: 00A400A3 00A200A1 U.AYV.tt 4-1 (255-a)
115  ASM("movq %0, %%mm5"::"m"(*y1)) // mm5: D8D7D6D5 D4D3D2D1 U.AYVttt 8-1 dest
116  ASM("movq %mm5, %mm1") // mm1: D8D7D6D5 D4D3D2D1 UtAYVttt
117  ASM("punpckhbw %0, %%mm5"::"m"(MMX_MIN)) // mm5: 00D800D7 00D600D5 UtAYVttt
118  ASM("punpcklbw %0, %%mm1"::"m"(MMX_MIN)) // mm1: 00D400D3 00D200D1 UtAYVttt
119  ASM("pmullw %mm7, %mm5") // mm5: D8D8D7D7 D6D6D5D5 UtAYVttt 8-5 dest*(255-a)
120  ASM("pmullw %mm6, %mm1") // mm1: D4D4D3D3 D2D2D1D1 UtAYVtt. 4-1 dest*(255-a)
121  ASM("psrlw $8, %mm5") // mm5: 00D800D7 00D600D5 UtAYVt.. 8-5 (dest*(255-a))/256
122  ASM("psrlw $8, %mm1") // mm1: 00D400D3 00D200D1 UtAYVt.. 4-1 (dest*(255-a))/256
123  ASM("packuswb %mm5, %mm1") // mm1: D8D7D6D5 D4D3D2D1 UtAYV... 8-1 (dest*(255-a))/256
124  ASM("paddusb %mm1, %mm3") // mm3: D8D7D6D5 D4D3D2D1 U.AYV... 8-1 (dest*(255-a))/256+y
125  ASM("movq %%mm3, %0":"=m"(*y1):) // U.A.V... row 1 y
126  ASM("movq %mm0, %mm1") // mm1: U4U3U2U1 V4V3V2V1 uuA.v...
127  ASM("punpckhdq %mm4, %mm0") // mm0: U8U7U6U5 U4U3U2U1 UuA.v... 8-1 u
128  ASM("punpckldq %mm4, %mm1") // mm1: V8V7V6V5 V4V3V2V1 UVA..... 9-1 v
129  // store u,v and for sub-sampling
130  ASM("movq %%mm0, %0":"=m"(tmp_u):)
131  ASM("movq %%mm1, %0":"=m"(tmp_v):)
132  ASM("movq %%mm2, %0":"=m"(tmp_a):)
133  // unpack and luminance - row 2
134  ASM("movq %0, %%mm1"::"m"(src2[0])) // mm1: A2Y2U2V2 A1Y1U1V1 .t......
135  ASM("movq %mm1, %mm2") // mm2: A2Y2U2V2 A1Y1U1V1 .tt.....
136  ASM("punpckhbw %0, %%mm1"::"m"(src2[8])) // mm1: A4A2Y4Y2 U4U2V4V2 .tt.....
137  ASM("punpcklbw %0, %%mm2"::"m"(src2[8])) // mm2: A3A1Y3Y1 U3U1V3V1 .tt.....
138  ASM("movq %mm2, %mm0") // mm0: A3A1Y3Y1 U3U1V3V1 ttt.....
139  ASM("punpckhbw %mm1, %mm2") // mm2: A4A3A2A1 Y4Y3Y2Y1 .tA..... AY stage 1
140  ASM("punpcklbw %mm1, %mm0") // mm0: U4U3U2U1 V4V3V2V1 U.A..... UV stage 1
141  ASM("movq %0, %%mm3"::"m"(src2[16])) // mm3: A6Y6U6V6 A5Y5U5V5 U.At....
142  ASM("movq %mm3, %mm4") // mm4: A6Y6U6V6 A5YU55V5 U.Att...
143  ASM("punpckhbw %0, %%mm3"::"m"(src2[24])) // mm3: A8A6Y8Y6 U8U6V8V6 U.Att...
144  ASM("punpcklbw %0, %%mm4"::"m"(src2[24])) // mm4: A7A5Y7Y5 U7U5V7V5 U.Att...
145  ASM("movq %mm4, %mm1") // mm1: A7A5Y7Y5 U7U5V7V5 UtAtt...
146  ASM("punpckhbw %mm3, %mm1") // mm1: A8A7A6A5 Y8Y7Y6Y5 UtAtt... AY stage 2
147  ASM("punpcklbw %mm3, %mm4") // mm4: U8U7U6U5 V8V7V6V5 UtA.V... UV stage 2
148  ASM("movq %mm2, %mm3") // mm3: A4A3A2A1 Y4Y3Y2Y1 UtAtV...
149  ASM("punpckldq %mm1, %mm3") // mm3: Y8Y7Y6Y5 Y4Y3Y2Y1 UtAYV... 8-1 Y
150  ASM("punpckhdq %mm1, %mm2") // mm2: A8A7A6A5 A4A3A2A1 UtAYV... 8-1 A
151  ASM("movq %0, %%mm7"::"m"(MMX_MAX)) // mm7: FFFFFFFF FFFFFFFF U.AYV..t 255
152  ASM("psubusb %mm2, %mm7") // mm7: A8A7A6A5 A4A3A2A1 U.AYV..t 8-1 (255-a)
153  ASM("movq %mm7, %mm6") // mm6: A8A7A6A5 A4A3A2A1 U.AYV.tt 8-1 (255-a)
154  ASM("movq %mm7, %mm2") // mm2: A8A7A6A5 A4A3A2A1 U.AYV.tt 8-1 (255-a)
155  ASM("punpckhbw %0, %%mm7"::"m"(MMX_MIN)) // mm7: 00A800A7 00A600A4 U.AYV.tt 8-5 (255-a)
156  ASM("punpcklbw %0, %%mm6"::"m"(MMX_MIN)) // mm6: 00A400A3 00A200A1 U.AYV.tt 4-1 (255-a)
157  ASM("movq %0, %%mm5"::"m"(*y2)) // mm5: D8D7D6D5 D4D3D2D1 U.AYVttt 8-1 dest
158  ASM("movq %mm5, %mm1") // mm1: D8D7D6D5 D4D3D2D1 UtAYVttt
159  ASM("punpckhbw %0, %%mm5"::"m"(MMX_MIN)) // mm5: 00D800D7 00D600D5 UtAYVttt
160  ASM("punpcklbw %0, %%mm1"::"m"(MMX_MIN)) // mm1: 00D400D3 00D200D1 UtAYVttt
161  ASM("pmullw %mm7, %mm5") // mm5: D8D8D7D7 D6D6D5D5 UtAYVttt 8-5 dest*(255-a)
162  ASM("pmullw %mm6, %mm1") // mm1: D4D4D3D3 D2D2D1D1 UtAYVtt. 4-1 dest*(255-a)
163  ASM("psrlw $8, %mm5") // mm5: 00D800D7 00D600D5 UtAYVt.. 8-5 (dest*(255-a))/256
164  ASM("psrlw $8, %mm1") // mm1: 00D400D3 00D200D1 UtAYVt.. 4-1 (dest*(255-a))/256
165  ASM("packuswb %mm5, %mm1") // mm1: D8D7D6D5 D4D3D2D1 UtAYV... 8-1 (dest*(255-a))/256
166  ASM("paddusb %mm1, %mm3") // mm3: D8D7D6D5 D4D3D2D1 U.AYV... 8-1 (dest*(255-a))/256+y
167  ASM("movq %%mm3, %0":"=m"(*y2):) // U.A.V... row 1 y
168  ASM("movq %mm0, %mm1") // mm1: U4U3U2U1 V4V3V2V1 uuA.v...
169  ASM("punpckhdq %mm4, %mm0") // mm0: U8U7U6U5 U4U3U2U1 UuA.v... 8-1 u
170  ASM("punpckldq %mm4, %mm1") // mm1: V8V7V6V5 V4V3V2V1 UVA..... 9-1 v
171  // subsample alpha
172  ASM("movq %mm2, %mm3") // mm3: A8A7A6A5 A4A3A2A1 UVAA.... copy row 2 a
173  ASM("movq %0, %%mm4"::"m"(tmp_a)) // mm4: A8A7A6A5 A4A3A2A1 UVAA.... row 1 a
174  ASM("movq %mm4, %mm5") // mm5: A8A7A6A5 A4A3A2A1 UVAAAA.. copy row 1 a
175  ASM("psrlw $8, %mm2") // mm2: 00A800A6 00A400A2 UVAAAA.. row 2
176  ASM("pand %0, %%mm3"::"m"(MMX_255)) // mm3: 00A700A5 00A300A1 UVAAAA.. row 2
177  ASM("psrlw $8, %mm4") // mm4: 00A800A6 00A400A2 UVAAAA.. row 1
178  ASM("pand %0, %%mm5"::"m"(MMX_255)) // mm5: 00A700A5 00A300A1 UVAAAA.. row 1
179  ASM("paddusw %mm5, %mm4") // add
180  ASM("paddusw %mm4, %mm3")
181  ASM("paddusw %mm3, %mm2")
182  ASM("psrlw $2, %mm2") // mm2: xxA4xxA3 xxA2xxA1 UVA..... /4
183  ASM("pand %0, %%mm2"::"m"(MMX_255)) // mm2: 00A400A3 00A200A1 UVA.....
184  // subsample u
185  ASM("movq %mm0, %mm3") // mm3: U8U7U6U5 U4U3U2U1 UVAU.... copy row 2 u
186  ASM("movq %0, %%mm4"::"m"(tmp_u)) // mm4: U8U7U6U5 U4U3U2U1 UVAUU... row 1 u
187  ASM("movq %mm4, %mm5") // mm5: U8U7U6U5 U4U3U2U1 UVAUUU.. copy row 1 u
188  ASM("psrlw $8, %mm0") // mm0: 00U800U6 00U400U2 UVAUUU.. row 2
189  ASM("pand %0, %%mm3"::"m"(MMX_255)) // mm3: 00U700U5 00U300U1 UVAUUU.. row 2
190  ASM("psrlw $8, %mm4") // mm4: 00U800U6 00U400U2 UVAUUU.. row 1
191  ASM("pand %0, %%mm5"::"m"(MMX_255)) // mm5: 00U700U5 00U300U1 UVAUUU.. row 1
192  ASM("paddusw %mm5, %mm4") // add
193  ASM("paddusw %mm4, %mm3")
194  ASM("paddusw %mm3, %mm0")
195  ASM("psrlw $2, %mm0") // mm0: xxU4xxU3 xxU2xxU1 UVA..... /4
196  ASM("pand %0, %%mm0"::"m"(MMX_255)) // mm0: 00U400U3 00U200U1 UVA.....
197  // blend u
198  ASM("movd %0, %%mm3"::"m"(*u)) // mm3: 00000000 D4D3D2D1 UVAt.... 4-1 dest u
199  ASM("punpcklbw %0, %%mm3"::"m"(MMX_MIN)) // mm3: 00D400D3 00D200D1 UVAt.... 4-1 dest u
200  ASM("pmullw %mm2, %mm3") // mm3: 00D400D3 00D200D1 UVAt.... destu * (255-a)
201  ASM("psrlw $8, %mm3") // mm3: 00D400D3 00D200D1 UVAt.... (destu*(255-a))/256
202  ASM("paddusb %mm3, %mm0") // mm0: xxR4xxR3 xxR2xxR1 UVA..... (destu*(255-a))/256 + u
203  ASM("packuswb %mm1, %mm0") // mm0: xxxxxxxx U4U3U2U1 UVA..... (destu*(255-a))/256 + u
204  ASM("movd %%mm0, %0":"=m"(*u):) // output .VA.....
205  // subsample v
206  ASM("movq %mm1, %mm3") // mm3: U8U7U6U5 U4U3U2U1 .VAV.... copy row 2 v
207  ASM("movq %0, %%mm4"::"m"(tmp_v)) // mm4: U8U7U6U5 U4U3U2U1 .VAVV... row 1 v
208  ASM("movq %mm4, %mm5") // mm5: U8U7U6U5 U4U3U2U1 .VAVVV.. copy row 1 v
209  ASM("psrlw $8, %mm1") // mm1: 00U800U6 00U400U2 .VAVVV.. row 2
210  ASM("pand %0, %%mm3"::"m"(MMX_255)) // mm3: 00U700U5 00U300U1 .VAVVV.. row 2
211  ASM("psrlw $8, %mm4") // mm4: 00U800U6 00U400U2 .VAVVV.. row 1
212  ASM("pand %0, %%mm5"::"m"(MMX_255)) // mm5: 00U700U5 00U300U1 .VAVVV.. row 1
213  ASM("paddusw %mm5, %mm4") // add
214  ASM("paddusw %mm4, %mm3")
215  ASM("paddusw %mm3, %mm1")
216  ASM("psrlw $2, %mm1") // mm1: xxU4xxU3 xxU2xxU1 .VA..... /4
217  ASM("pand %0, %%mm1"::"m"(MMX_255)) // mm1: 00U400U3 00U200U1 .VA.....
218  // blend v
219  ASM("movd %0, %%mm3"::"m"(*v)) // mm3: 00000000 D4D3D2D1 .VAt.... 4-1 dest v
220  ASM("punpcklbw %0, %%mm3"::"m"(MMX_MIN)) // mm3: 00D400D3 00D200D1 .VAt.... 4-1 dest v
221  ASM("pmullw %mm2, %mm3") // mm3: 00D400D3 00D200D1 .V.t.... destv * (255-a)
222  ASM("psrlw $8, %mm3") // mm3: 00D400D3 00D200D1 .V.t.... (destv*(255-a))/256
223  ASM("paddusb %mm3, %mm1") // mm1: xxR4xxR3 xxR2xxR1 .V...... (destv*(255-a))/256 + v
224  ASM("packuswb %mm2, %mm1") // mm1: xxxxxxxx V4V3V2V1 .V...... (destv*(255-a))/256 + v
225  ASM("movd %%mm1, %0":"=m"(*v):) // output ........
226 
227  src1 += 32; src2 += 32; y1 += 8; y2 += 8; u += 4; v += 4;
228  }
229  y1 += y_wrap; y2 += y_wrap; u+= u_wrap; v += v_wrap;
230  src1 += src_wrap; src2 += src_wrap;
231  }
232  ASM("emms")
233 }
234 #endif
235 
236 void c_yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image,
237  int left, int top, int right, int bottom)
238 {
239  const int width = right - left;
240  const int height = bottom - top;
241 
242  unsigned char *udest = frame->buf + frame->offsets[1];
243  unsigned char *vdest = frame->buf + frame->offsets[2];
244  udest += frame->pitches[1] * (top >> 1) + (left >> 1);
245  vdest += frame->pitches[2] * (top >> 1) + (left >> 1);
246 
247  unsigned char *y1 = frame->buf + frame->offsets[0]
248  + frame->pitches[0] * top + left;
249  unsigned char *y3 = y1 + frame->pitches[0];
250  const int y_wrap = (frame->pitches[0] << 1) - width;
251 
252  const unsigned char *src = osd_image->scanLine(top) + left * sizeof(QRgb);
253  const int bpl = osd_image->bytesPerLine();
254 
255  for (int row = 0; row < height; row += 2)
256  {
257  const QRgb *p1 = reinterpret_cast<const QRgb* >(src);
258  const QRgb *p3 = reinterpret_cast<const QRgb* >(src + bpl);
259 
260  for (int col = 0, maxcol = width / 2; col < maxcol; ++col)
261  {
262  QRgb rgb1 = p1[0], rgb2 = p1[1], rgb3 = p3[0], rgb4 = p3[1];
263  int alpha1 = 255 - qAlpha(rgb1);
264  int alpha2 = 255 - qAlpha(rgb2);
265  int alpha3 = 255 - qAlpha(rgb3);
266  int alpha4 = 255 - qAlpha(rgb4);
267  int alphaUV = (alpha1 + alpha2 + alpha3 + alpha4) >> 2;
268 
269  // Note - in the code below qRed is not really red, it
270  // is Y, or luminance. qGreen is U chrominance and qBlue
271  // is V chrominance.
272  if (alphaUV == 0)
273  {
274  // Special case optimized for raspberry pi
275  // This code handles opaque images. In this
276  // case it is not necessary to merge in the background.
277  y1[0] = qRed(rgb1);
278  y1[1] = qRed(rgb2);
279  y3[0] = qRed(rgb3);
280  y3[1] = qRed(rgb4);
281  udest[col] = (qGreen(rgb1) + qGreen(rgb2) + qGreen(rgb3) + qGreen(rgb4)) >> 2;
282  vdest[col] = (qBlue(rgb1) + qBlue(rgb2) + qBlue(rgb3) + qBlue(rgb4)) >> 2;
283  }
284  else if (alphaUV < 255)
285  {
286  // This code handles transparency. it is skipped
287  // if the image is invisible (alphaUV == 255)
288  // This section could handle all cases, but for
289  // optimizing CPU usage three cases are handled differently.
290  y1[0] = ((y1[0] * alpha1) >> 8) + qRed(rgb1);
291  y1[1] = ((y1[1] * alpha2) >> 8) + qRed(rgb2);
292  y3[0] = ((y3[0] * alpha3) >> 8) + qRed(rgb3);
293  y3[1] = ((y3[1] * alpha4) >> 8) + qRed(rgb4);
294 
295  int u = (qGreen(rgb1) + qGreen(rgb2) + qGreen(rgb3) + qGreen(rgb4)) >> 2;
296  udest[col] = ((udest[col] * alphaUV) >> 8) + u;
297 
298  int v = (qBlue(rgb1) + qBlue(rgb2) + qBlue(rgb3) + qBlue(rgb4)) >> 2;
299  vdest[col] = ((vdest[col] * alphaUV) >> 8) + v;
300  }
301  y1 += 2, y3 += 2;
302  p1 += 2, p3 += 2;
303  }
304 
305  y1 += y_wrap, y3 += y_wrap;
306  udest += frame->pitches[1];
307  vdest += frame->pitches[2];
308  src += bpl << 1;
309  }
310 }
311 
312 void yuv888_to_i44(unsigned char *dest, MythImage *osd_image, QSize dst_size,
313  int left, int top, int right, int bottom, bool ifirst)
314 {
315  int width, ashift, amask, ishift, imask, src_wrap, dst_wrap;
316  unsigned char *src, *alpha, *dst;
317 
318  width = right - left;
319  ashift = ifirst ? 0 : 4;
320  amask = ifirst ? 0x0f : 0xf0;
321  ishift = ifirst ? 4 : 0;
322  imask = ifirst ? 0xf0 : 0x0f;
323 
324  src = osd_image->scanLine(top) + (left << 2) + R_OI;
325  alpha = osd_image->scanLine(top) + (left << 2) + A_OI;
326  dst = dest + dst_size.width() * top + left;
327  dst_wrap = dst_size.width() - width;
328  src_wrap = osd_image->bytesPerLine() - (width << 2);
329 
330  for (int row = top; row < bottom; row++)
331  {
332  const unsigned char *dmp = DM[row & (DM_HEIGHT - 1)];
333  for (int col = left; col < right; col++)
334  {
335  int grey;
336 
337  grey = *src + ((dmp[col & (DM_WIDTH - 1)] << 2) >> 4);
338  grey = (grey - (grey >> 4)) >> 4;
339 
340  *dst = (((*alpha >> 4) << ashift) & amask) |
341  (((grey) << ishift) & imask);
342 
343  alpha += 4;
344  src += 4;
345  dst++;
346  }
347  alpha += src_wrap;
348  src += src_wrap;
349  dst += dst_wrap;
350  }
351 }
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
void c_yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image, int left, int top, int right, int bottom)
Definition: util-osd.cpp:236
#define A_OI
Definition: util-osd.cpp:13
#define DM_HEIGHT
Definition: dithertable.h:10
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
static const unsigned char DM[128][128]
Definition: dithertable.h:11
#define ALIGN_X_MMX
Definition: util-osd.h:10
void yuv888_to_i44(unsigned char *dest, MythImage *osd_image, QSize dst_size, int left, int top, int right, int bottom, bool ifirst)
Definition: util-osd.cpp:312
void mmx_yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image, int left, int top, int right, int bottom)
Definition: util-osd.cpp:59
#define R_OI
Definition: util-osd.cpp:10
void yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image, int left, int top, int right, int bottom)
Definition: util-osd.cpp:16
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define ASM(code)
Definition: util-osd.cpp:58
#define DM_WIDTH
Definition: dithertable.h:8
#define ALIGN_C
Definition: util-osd.h:8
unsigned char * buf
Definition: mythframe.h:39
static guint32 * p1
Definition: goom_core.c:35