1 
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 
6 #define SCHRO_ENABLE_UNSTABLE_API 1
7 
8 #include "schrovirtframe.h"
9 #include <schroedinger/schro.h>
10 #include <schroedinger/schroutils.h>
11 #include <string.h>
12 #include <math.h>
13 #include <orc/orc.h>
14 
15 #include <schroedinger/schroorc.h>
16 
17 
18 SchroFrame *
schro_frame_new_virtual(SchroMemoryDomain * domain,SchroFrameFormat format,int width,int height)19 schro_frame_new_virtual (SchroMemoryDomain * domain, SchroFrameFormat format,
20     int width, int height)
21 {
22   SchroFrame *frame = schro_frame_new ();
23   int bytes_pp;
24   int h_shift, v_shift;
25   int chroma_width;
26   int chroma_height;
27   int i;
28 
29   frame->format = format;
30   frame->width = width;
31   frame->height = height;
32   frame->domain = domain;
33 
34   if (SCHRO_FRAME_IS_PACKED (format)) {
35     frame->components[0].format = format;
36     frame->components[0].width = width;
37     frame->components[0].height = height;
38     if (format == SCHRO_FRAME_FORMAT_AYUV) {
39       frame->components[0].stride = width * 4;
40     } else if (format == SCHRO_FRAME_FORMAT_v216) {
41       frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 4;
42     } else if (format == SCHRO_FRAME_FORMAT_v210) {
43       frame->components[0].stride = ((width + 47) / 48) * 128;
44     } else {
45       frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 2;
46     }
47     frame->components[0].length = frame->components[0].stride * height;
48 
49     frame->components[0].data = frame->regions[0];
50     frame->components[0].v_shift = 0;
51     frame->components[0].h_shift = 0;
52 
53     frame->regions[0] =
54         malloc (frame->components[0].stride * SCHRO_FRAME_CACHE_SIZE);
55     for (i = 0; i < SCHRO_FRAME_CACHE_SIZE; i++) {
56       frame->cached_lines[0][i] = 0;
57     }
58     frame->is_virtual = TRUE;
59 
60     return frame;
61   }
62 
63   switch (SCHRO_FRAME_FORMAT_DEPTH (format)) {
64     case SCHRO_FRAME_FORMAT_DEPTH_U8:
65       bytes_pp = 1;
66       break;
67     case SCHRO_FRAME_FORMAT_DEPTH_S16:
68       bytes_pp = 2;
69       break;
70     case SCHRO_FRAME_FORMAT_DEPTH_S32:
71       bytes_pp = 4;
72       break;
73     default:
74       SCHRO_ASSERT (0);
75       bytes_pp = 0;
76       break;
77   }
78 
79   h_shift = SCHRO_FRAME_FORMAT_H_SHIFT (format);
80   v_shift = SCHRO_FRAME_FORMAT_V_SHIFT (format);
81   chroma_width = ROUND_UP_SHIFT (width, h_shift);
82   chroma_height = ROUND_UP_SHIFT (height, v_shift);
83 
84   frame->components[0].format = format;
85   frame->components[0].width = width;
86   frame->components[0].height = height;
87   frame->components[0].stride = ROUND_UP_4 (width * bytes_pp);
88   frame->components[0].length =
89       frame->components[0].stride * frame->components[0].height;
90   frame->components[0].v_shift = 0;
91   frame->components[0].h_shift = 0;
92 
93   frame->components[1].format = format;
94   frame->components[1].width = chroma_width;
95   frame->components[1].height = chroma_height;
96   frame->components[1].stride = ROUND_UP_4 (chroma_width * bytes_pp);
97   frame->components[1].length =
98       frame->components[1].stride * frame->components[1].height;
99   frame->components[1].v_shift = v_shift;
100   frame->components[1].h_shift = h_shift;
101 
102   frame->components[2].format = format;
103   frame->components[2].width = chroma_width;
104   frame->components[2].height = chroma_height;
105   frame->components[2].stride = ROUND_UP_4 (chroma_width * bytes_pp);
106   frame->components[2].length =
107       frame->components[2].stride * frame->components[2].height;
108   frame->components[2].v_shift = v_shift;
109   frame->components[2].h_shift = h_shift;
110 
111   for (i = 0; i < 3; i++) {
112     SchroFrameData *comp = &frame->components[i];
113     int j;
114 
115     frame->regions[i] = malloc (comp->stride * SCHRO_FRAME_CACHE_SIZE);
116     for (j = 0; j < SCHRO_FRAME_CACHE_SIZE; j++) {
117       frame->cached_lines[i][j] = 0;
118     }
119   }
120   frame->is_virtual = TRUE;
121 
122   return frame;
123 }
124 
125 static void
schro_virt_frame_prep_cache_line(SchroFrame * frame,int component,int i)126 schro_virt_frame_prep_cache_line (SchroFrame * frame, int component, int i)
127 {
128   int j;
129 
130   if (i < frame->cache_offset[component]) {
131     SCHRO_ERROR ("cache failure: %d outside [%d,%d]", i,
132         frame->cache_offset[component],
133         frame->cache_offset[component] + SCHRO_FRAME_CACHE_SIZE - 1);
134 
135     frame->cache_offset[component] = i;
136     for (j = 0; j < SCHRO_FRAME_CACHE_SIZE; j++) {
137       frame->cached_lines[component][j] = 0;
138     }
139   }
140 
141   while (i >= frame->cache_offset[component] + SCHRO_FRAME_CACHE_SIZE) {
142     j = frame->cache_offset[component] & (SCHRO_FRAME_CACHE_SIZE - 1);
143     frame->cached_lines[component][j] = 0;
144 
145     frame->cache_offset[component]++;
146   }
147 }
148 
149 void *
schro_virt_frame_get_line_unrendered(SchroFrame * frame,int component,int i)150 schro_virt_frame_get_line_unrendered (SchroFrame * frame, int component, int i)
151 {
152   SchroFrameData *comp = &frame->components[component];
153   int j;
154 
155   //SCHRO_ASSERT(i >= 0);
156   //SCHRO_ASSERT(i < comp->height);
157 
158   if (!frame->is_virtual) {
159     return SCHRO_FRAME_DATA_GET_LINE (&frame->components[component], i);
160   }
161 
162   schro_virt_frame_prep_cache_line (frame, component, i);
163   j = i & (SCHRO_FRAME_CACHE_SIZE - 1);
164 
165   return SCHRO_OFFSET (frame->regions[component], comp->stride * j);
166 }
167 
168 void *
schro_virt_frame_get_line(SchroFrame * frame,int component,int i)169 schro_virt_frame_get_line (SchroFrame * frame, int component, int i)
170 {
171   SchroFrameData *comp = &frame->components[component];
172   int j;
173 
174   //SCHRO_ASSERT(i >= 0);
175   //SCHRO_ASSERT(i < comp->height);
176 
177   if (!frame->is_virtual) {
178     return SCHRO_FRAME_DATA_GET_LINE (&frame->components[component], i);
179   }
180 
181   schro_virt_frame_prep_cache_line (frame, component, i);
182   j = i & (SCHRO_FRAME_CACHE_SIZE - 1);
183 
184   if (!frame->cached_lines[component][j]) {
185     schro_virt_frame_render_line (frame,
186         SCHRO_OFFSET (frame->regions[component], comp->stride * j), component,
187         i);
188     frame->cached_lines[component][j] = 1;
189   }
190 
191   return SCHRO_OFFSET (frame->regions[component], comp->stride * j);
192 }
193 
194 void
schro_virt_frame_set_line_rendered(SchroFrame * frame,int component,int i)195 schro_virt_frame_set_line_rendered (SchroFrame * frame, int component, int i)
196 {
197   int j;
198 
199   //SCHRO_ASSERT(i >= 0);
200   //SCHRO_ASSERT(i < comp->height);
201   //SCHRO_ASSERT(frame->is_virtual);
202 
203   j = i & (SCHRO_FRAME_CACHE_SIZE - 1);
204   frame->cached_lines[component][j] = 1;
205 }
206 
207 void
schro_virt_frame_render_line(SchroFrame * frame,void * dest,int component,int i)208 schro_virt_frame_render_line (SchroFrame * frame, void *dest,
209     int component, int i)
210 {
211   frame->render_line (frame, dest, component, i);
212 }
213 
214 static void
copy(SchroFrame * frame,void * _dest,int component,int i)215 copy (SchroFrame * frame, void *_dest, int component, int i)
216 {
217   uint8_t *dest = _dest;
218   uint8_t *src;
219 
220   src = schro_virt_frame_get_line (frame, component, i);
221   switch (SCHRO_FRAME_FORMAT_DEPTH (frame->format)) {
222     case SCHRO_FRAME_FORMAT_DEPTH_U8:
223       orc_memcpy (dest, src, frame->components[component].width);
224       break;
225     case SCHRO_FRAME_FORMAT_DEPTH_S16:
226       orc_memcpy (dest, src, frame->components[component].width * sizeof(int16_t));
227       break;
228     case SCHRO_FRAME_FORMAT_DEPTH_S32:
229       orc_memcpy (dest, src, frame->components[component].width * sizeof(int32_t));
230       break;
231     default:
232       SCHRO_ASSERT (0);
233       break;
234   }
235 }
236 
237 void
schro_virt_frame_render(SchroFrame * frame,SchroFrame * dest)238 schro_virt_frame_render (SchroFrame * frame, SchroFrame * dest)
239 {
240   int i, k;
241 
242   SCHRO_ASSERT (frame->width == dest->width);
243   SCHRO_ASSERT (frame->height >= dest->height);
244 
245   if (frame->is_virtual) {
246     for (k = 0; k < 3; k++) {
247       SchroFrameData *comp = dest->components + k;
248 
249       for (i = 0; i < dest->components[k].height; i++) {
250         schro_virt_frame_render_line (frame,
251             SCHRO_FRAME_DATA_GET_LINE (comp, i), k, i);
252       }
253     }
254   } else {
255     for (k = 0; k < 3; k++) {
256       SchroFrameData *comp = dest->components + k;
257 
258       for (i = 0; i < dest->components[k].height; i++) {
259         copy (frame, SCHRO_FRAME_DATA_GET_LINE (comp, i), k, i);
260       }
261     }
262   }
263 }
264 
265 #ifdef unused
266 void
schro_virt_frame_render_downsample_horiz_cosite(SchroFrame * frame,void * _dest,int component,int i)267 schro_virt_frame_render_downsample_horiz_cosite (SchroFrame * frame,
268     void *_dest, int component, int i)
269 {
270   uint8_t *dest = _dest;
271   uint8_t *src;
272   int j;
273   int n_src;
274 
275   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
276   n_src = frame->virt_frame1->components[component].width;
277 
278   for (j = 0; j < frame->components[component].width; j++) {
279     int x = 0;
280     x += 1 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
281     x += 2 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
282     x += 1 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
283     dest[j] = CLAMP ((x + 2) >> 2, 0, 255);
284   }
285 }
286 #endif
287 
288 #ifdef unused
289 void
schro_virt_frame_render_downsample_horiz_halfsite(SchroFrame * frame,void * _dest,int component,int i)290 schro_virt_frame_render_downsample_horiz_halfsite (SchroFrame * frame,
291     void *_dest, int component, int i)
292 {
293   uint8_t *dest = _dest;
294   uint8_t *src;
295   int j;
296   int n_src;
297   int taps = 4;
298   int k;
299 
300   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
301   n_src = frame->virt_frame1->components[component].width;
302 
303   switch (taps) {
304     case 4:
305       for (j = 0; j < frame->components[component].width; j++) {
306         int x = 0;
307         x += 6 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
308         x += 26 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
309         x += 26 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
310         x += 6 * src[CLAMP (j * 2 + 2, 0, n_src - 1)];
311         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
312       }
313       break;
314     case 6:
315       for (j = 0; j < frame->components[component].width; j++) {
316         int x = 0;
317         x += -3 * src[CLAMP (j * 2 - 2, 0, n_src - 1)];
318         x += 8 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
319         x += 27 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
320         x += 27 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
321         x += 8 * src[CLAMP (j * 2 + 2, 0, n_src - 1)];
322         x += -3 * src[CLAMP (j * 2 + 3, 0, n_src - 1)];
323         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
324       }
325     case 8:
326       for (j = 0; j < frame->components[component].width; j++) {
327         int x = 0;
328         const int taps8[8] = { -2, -4, 9, 29, 29, 9, -4, -2 };
329         for (k = 0; k < 8; k++) {
330           x += taps8[k] * src[CLAMP (j * 2 - 3 + k, 0, n_src - 1)];
331         }
332         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
333       }
334       break;
335     case 10:
336       for (j = 0; j < frame->components[component].width; j++) {
337         int x = 0;
338         const int taps10[10] = { 1, -2, -5, 9, 29, 29, 9, -5, -2, 1 };
339         for (k = 0; k < 10; k++) {
340           x += taps10[k] * src[CLAMP (j * 2 - 4 + k, 0, n_src - 1)];
341         }
342         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
343       }
344       break;
345     default:
346       break;
347   }
348 }
349 #endif
350 
351 #ifdef unused
352 SchroFrame *
schro_virt_frame_new_horiz_downsample(SchroFrame * vf,int cosite)353 schro_virt_frame_new_horiz_downsample (SchroFrame * vf, int cosite)
354 {
355   SchroFrame *virt_frame;
356 
357   virt_frame =
358       schro_frame_new_virtual (NULL, vf->format, vf->width / 2, vf->height);
359   virt_frame->virt_frame1 = vf;
360   if (cosite) {
361     virt_frame->render_line = schro_virt_frame_render_downsample_horiz_cosite;
362   } else {
363     virt_frame->render_line = schro_virt_frame_render_downsample_horiz_halfsite;
364   }
365 
366   return virt_frame;
367 }
368 #endif
369 
370 #ifdef unused
371 void
schro_virt_frame_render_downsample_vert_cosite(SchroFrame * frame,void * _dest,int component,int i)372 schro_virt_frame_render_downsample_vert_cosite (SchroFrame * frame,
373     void *_dest, int component, int i)
374 {
375   uint8_t *dest = _dest;
376   uint8_t *src1;
377   uint8_t *src2;
378   uint8_t *src3;
379   int j;
380   int n_src;
381 
382   n_src = frame->virt_frame1->components[component].height;
383   src1 = schro_virt_frame_get_line (frame->virt_frame1, component,
384       CLAMP (i * 2 - 1, 0, n_src - 1));
385   src2 = schro_virt_frame_get_line (frame->virt_frame1, component,
386       CLAMP (i * 2 + 0, 0, n_src - 1));
387   src3 = schro_virt_frame_get_line (frame->virt_frame1, component,
388       CLAMP (i * 2 + 1, 0, n_src - 1));
389 
390   for (j = 0; j < frame->components[component].width; j++) {
391     int x = 0;
392     x += 1 * src1[j];
393     x += 2 * src2[j];
394     x += 1 * src3[j];
395     dest[j] = CLAMP ((x + 2) >> 2, 0, 255);
396   }
397 }
398 #endif
399 
400 #ifdef unused
401 void
schro_virt_frame_render_downsample_vert_halfsite(SchroFrame * frame,void * _dest,int component,int i)402 schro_virt_frame_render_downsample_vert_halfsite (SchroFrame * frame,
403     void *_dest, int component, int i)
404 {
405   uint8_t *dest = _dest;
406   uint8_t *src[10];
407   int j;
408   int n_src;
409   int taps = 4;
410   int k;
411 
412   n_src = frame->virt_frame1->components[component].height;
413   for (j = 0; j < taps; j++) {
414     src[j] = schro_virt_frame_get_line (frame->virt_frame1, component,
415         CLAMP (i * 2 - (taps - 2) / 2 + j, 0, n_src - 1));
416   }
417 
418   switch (taps) {
419     case 4:
420       for (j = 0; j < frame->components[component].width; j++) {
421         int x = 0;
422         x += 6 * src[0][j];
423         x += 26 * src[1][j];
424         x += 26 * src[2][j];
425         x += 6 * src[3][j];
426         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
427       }
428       break;
429     case 6:
430       for (j = 0; j < frame->components[component].width; j++) {
431         int x = 0;
432         x += -3 * src[0][j];
433         x += 8 * src[1][j];
434         x += 27 * src[2][j];
435         x += 27 * src[3][j];
436         x += 8 * src[4][j];
437         x += -3 * src[5][j];
438         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
439       }
440       break;
441     case 8:
442       for (j = 0; j < frame->components[component].width; j++) {
443         int x = 0;
444         const int taps8[8] = { -2, -4, 9, 29, 29, 9, -4, -2 };
445         for (k = 0; k < 8; k++) {
446           x += taps8[k] * src[k][j];
447         }
448         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
449       }
450       break;
451     case 10:
452       for (j = 0; j < frame->components[component].width; j++) {
453         int x = 0;
454         const int taps10[10] = { 1, -2, -5, 9, 29, 29, 9, -5, -2, 1 };
455         //const int taps10[10] = { -1, 1, 6, 11, 15, 15, 11, 6, 1, -1 };
456         for (k = 0; k < 10; k++) {
457           x += taps10[k] * src[k][j];
458         }
459         dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
460       }
461       break;
462     default:
463       SCHRO_ASSERT (0);
464       break;
465   }
466 }
467 #endif
468 
469 #ifdef unused
470 SchroFrame *
schro_virt_frame_new_vert_downsample(SchroFrame * vf,int cosite)471 schro_virt_frame_new_vert_downsample (SchroFrame * vf, int cosite)
472 {
473   SchroFrame *virt_frame;
474 
475   virt_frame =
476       schro_frame_new_virtual (NULL, vf->format, vf->width, vf->height / 2);
477   virt_frame->virt_frame1 = vf;
478   if (cosite) {
479     virt_frame->render_line = schro_virt_frame_render_downsample_vert_cosite;
480   } else {
481     virt_frame->render_line = schro_virt_frame_render_downsample_vert_halfsite;
482   }
483 
484   return virt_frame;
485 }
486 #endif
487 
488 #ifdef unused
489 void
get_taps(double * taps,double x)490 get_taps (double *taps, double x)
491 {
492   taps[3] = x * x * (x - 1);
493   taps[2] = x * (-x * x + x + 1);
494   x = 1 - x;
495   taps[1] = x * (-x * x + x + 1);
496   taps[0] = x * x * (x - 1);
497 }
498 #endif
499 
500 #ifdef unused
501 void
schro_virt_frame_render_resample_vert(SchroFrame * frame,void * _dest,int component,int i)502 schro_virt_frame_render_resample_vert (SchroFrame * frame, void *_dest,
503     int component, int i)
504 {
505   uint8_t *dest = _dest;
506   uint8_t *src1;
507   uint8_t *src2;
508   uint8_t *src3;
509   uint8_t *src4;
510   int j;
511   int n_src;
512   double taps[4];
513   double *scale = (double *) frame->virt_priv;
514   double x;
515   int src_i;
516 
517   x = (*scale) * i;
518   src_i = floor (x);
519   get_taps (taps, x - floor (x));
520 
521   n_src = frame->virt_frame1->components[component].height;
522   src1 = schro_virt_frame_get_line (frame->virt_frame1, component,
523       CLAMP (src_i - 1, 0, n_src - 1));
524   src2 = schro_virt_frame_get_line (frame->virt_frame1, component,
525       CLAMP (src_i + 0, 0, n_src - 1));
526   src3 = schro_virt_frame_get_line (frame->virt_frame1, component,
527       CLAMP (src_i + 1, 0, n_src - 1));
528   src4 = schro_virt_frame_get_line (frame->virt_frame1, component,
529       CLAMP (src_i + 2, 0, n_src - 1));
530 
531   for (j = 0; j < frame->components[component].width; j++) {
532     double x = 0;
533     x += taps[0] * src1[j];
534     x += taps[1] * src2[j];
535     x += taps[2] * src3[j];
536     x += taps[3] * src4[j];
537     dest[j] = CLAMP (rint (x), 0, 255);
538   }
539 }
540 #endif
541 
542 #ifdef unused
543 SchroFrame *
schro_virt_frame_new_vert_resample(SchroFrame * vf,int height)544 schro_virt_frame_new_vert_resample (SchroFrame * vf, int height)
545 {
546   SchroFrame *virt_frame;
547   double *scale;
548 
549   virt_frame = schro_frame_new_virtual (NULL, vf->format, vf->width, height);
550   virt_frame->virt_frame1 = vf;
551   virt_frame->render_line = schro_virt_frame_render_resample_vert;
552 
553   scale = malloc (sizeof (double));
554   virt_frame->virt_priv = scale;
555 
556   *scale = (double) vf->height / height;
557 
558   return virt_frame;
559 }
560 #endif
561 
562 #ifdef unused
563 void
schro_virt_frame_render_resample_horiz(SchroFrame * frame,void * _dest,int component,int i)564 schro_virt_frame_render_resample_horiz (SchroFrame * frame, void *_dest,
565     int component, int i)
566 {
567   uint8_t *dest = _dest;
568   uint8_t *src;
569   int j;
570   int n_src;
571   double taps[4];
572   double *scale = (double *) frame->virt_priv;
573   int src_i;
574 
575   n_src = frame->virt_frame1->components[component].width;
576   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
577 
578   for (j = 0; j < frame->components[component].width; j++) {
579     double x;
580     double y = 0;
581 
582     x = (*scale) * j;
583     src_i = floor (x);
584     get_taps (taps, x - floor (x));
585 
586     y = 0;
587     y += taps[0] * src[CLAMP (src_i - 1, 0, n_src - 1)];
588     y += taps[1] * src[CLAMP (src_i + 0, 0, n_src - 1)];
589     y += taps[2] * src[CLAMP (src_i + 1, 0, n_src - 1)];
590     y += taps[3] * src[CLAMP (src_i + 2, 0, n_src - 1)];
591     dest[j] = CLAMP (rint (y), 0, 255);
592   }
593 }
594 #endif
595 
596 #ifdef unused
597 SchroFrame *
schro_virt_frame_new_horiz_resample(SchroFrame * vf,int width)598 schro_virt_frame_new_horiz_resample (SchroFrame * vf, int width)
599 {
600   SchroFrame *virt_frame;
601   double *scale;
602 
603   virt_frame = schro_frame_new_virtual (NULL, vf->format, width, vf->height);
604   virt_frame->virt_frame1 = vf;
605   virt_frame->render_line = schro_virt_frame_render_resample_horiz;
606 
607   scale = malloc (sizeof (double));
608   virt_frame->virt_priv = scale;
609 
610   *scale = (double) vf->width / width;
611 
612   return virt_frame;
613 }
614 #endif
615 
616 static void
unpack_yuyv(SchroFrame * frame,void * _dest,int component,int i)617 unpack_yuyv (SchroFrame * frame, void *_dest, int component, int i)
618 {
619   uint8_t *dest = _dest;
620   uint8_t *src;
621 
622   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
623 
624   switch (component) {
625     case 0:
626       orc_unpack_yuyv_y (dest, (void *) src, frame->width);
627       break;
628     case 1:
629       orc_unpack_yuyv_u (dest, (void *) src, frame->width / 2);
630       break;
631     case 2:
632       orc_unpack_yuyv_v (dest, (void *) src, frame->width / 2);
633       break;
634     default:
635       SCHRO_ASSERT (0);
636   }
637 }
638 
639 static void
unpack_uyvy(SchroFrame * frame,void * _dest,int component,int i)640 unpack_uyvy (SchroFrame * frame, void *_dest, int component, int i)
641 {
642   uint8_t *dest = _dest;
643   uint8_t *src;
644 
645   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
646 
647   switch (component) {
648     case 0:
649       orc_unpack_uyvy_y (dest, (void *) src, frame->width);
650       break;
651     case 1:
652       orc_unpack_uyvy_u (dest, (void *) src, frame->width / 2);
653       break;
654     case 2:
655       orc_unpack_uyvy_v (dest, (void *) src, frame->width / 2);
656       break;
657     default:
658       SCHRO_ASSERT (0);
659   }
660 }
661 
662 static void
unpack_ayuv(SchroFrame * frame,void * _dest,int component,int i)663 unpack_ayuv (SchroFrame * frame, void *_dest, int component, int i)
664 {
665   uint8_t *dest = _dest;
666   uint8_t *src;
667   int j;
668 
669   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
670 
671   switch (component) {
672     case 0:
673       for (j = 0; j < frame->width; j++) {
674         dest[j] = src[j * 4 + 1];
675       }
676       break;
677     case 1:
678       for (j = 0; j < frame->width; j++) {
679         dest[j] = src[j * 4 + 2];
680       }
681       break;
682     case 2:
683       for (j = 0; j < frame->width; j++) {
684         dest[j] = src[j * 4 + 3];
685       }
686       break;
687     default:
688       SCHRO_ASSERT (0);
689   }
690 }
691 
692 static void
unpack_AY64(SchroFrame * frame,void * _dest,int component,int i)693 unpack_AY64 (SchroFrame * frame, void *_dest, int component, int i)
694 {
695   int32_t *dest = _dest;
696   uint16_t *src;
697   int j;
698 
699   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
700 
701   switch (component) {
702     case 0:
703       for (j = 0; j < frame->width; j++) {
704         dest[j] = src[j * 4 + 1] - 32768;
705       }
706       break;
707     case 1:
708       for (j = 0; j < frame->width; j++) {
709         dest[j] = src[j * 4 + 2] - 32768;
710       }
711       break;
712     case 2:
713       for (j = 0; j < frame->width; j++) {
714         dest[j] = src[j * 4 + 3] - 32768;
715       }
716       break;
717     default:
718       SCHRO_ASSERT (0);
719   }
720 }
721 
722 static void
unpack_v210(SchroFrame * frame,void * _dest,int component,int i)723 unpack_v210 (SchroFrame * frame, void *_dest, int component, int i)
724 {
725   int16_t *dest = _dest;
726   uint8_t *src;
727   int j;
728 
729   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
730 
731 #define READ_UINT32_LE(a) (((uint8_t *)(a))[0] | (((uint8_t *)(a))[1]<<8) | \
732   (((uint8_t *)(a))[2]<<16) | (((uint8_t *)(a))[3]<<24))
733   switch (component) {
734     case 0:
735       for (j = 0; j < frame->width / 6; j++) {
736         dest[j * 6 + 0] =
737             ((READ_UINT32_LE (src + j * 16 + 0) >> 10) & 0x3ff) - 512;
738         dest[j * 6 + 1] =
739             ((READ_UINT32_LE (src + j * 16 + 4) >> 0) & 0x3ff) - 512;
740         dest[j * 6 + 2] =
741             ((READ_UINT32_LE (src + j * 16 + 4) >> 20) & 0x3ff) - 512;
742         dest[j * 6 + 3] =
743             ((READ_UINT32_LE (src + j * 16 + 8) >> 10) & 0x3ff) - 512;
744         dest[j * 6 + 4] =
745             ((READ_UINT32_LE (src + j * 16 + 12) >> 0) & 0x3ff) - 512;
746         dest[j * 6 + 5] =
747             ((READ_UINT32_LE (src + j * 16 + 12) >> 20) & 0x3ff) - 512;
748       }
749       if (j * 6 + 0 < frame->width) {
750         dest[j * 6 + 0] =
751             ((READ_UINT32_LE (src + j * 16 + 0) >> 10) & 0x3ff) - 512;
752       }
753       if (j * 6 + 1 < frame->width) {
754         dest[j * 6 + 1] =
755             ((READ_UINT32_LE (src + j * 16 + 4) >> 0) & 0x3ff) - 512;
756       }
757       if (j * 6 + 2 < frame->width) {
758         dest[j * 6 + 2] =
759             ((READ_UINT32_LE (src + j * 16 + 4) >> 20) & 0x3ff) - 512;
760       }
761       if (j * 6 + 3 < frame->width) {
762         dest[j * 6 + 3] =
763             ((READ_UINT32_LE (src + j * 16 + 8) >> 10) & 0x3ff) - 512;
764       }
765       if (j * 6 + 4 < frame->width) {
766         dest[j * 6 + 4] =
767             ((READ_UINT32_LE (src + j * 16 + 12) >> 0) & 0x3ff) - 512;
768       }
769       if (j * 6 + 5 < frame->width) {
770         dest[j * 6 + 5] =
771             ((READ_UINT32_LE (src + j * 16 + 12) >> 20) & 0x3ff) - 512;
772       }
773       break;
774     case 1:
775       for (j = 0; j < frame->width / 6; j++) {
776         dest[j * 3 + 0] =
777             ((READ_UINT32_LE (src + j * 16 + 0) >> 0) & 0x3ff) - 512;
778         dest[j * 3 + 1] =
779             ((READ_UINT32_LE (src + j * 16 + 4) >> 10) & 0x3ff) - 512;
780         dest[j * 3 + 2] =
781             ((READ_UINT32_LE (src + j * 16 + 8) >> 20) & 0x3ff) - 512;
782       }
783       if (j * 6 + 0 < frame->width) {
784         dest[j * 3 + 0] =
785             ((READ_UINT32_LE (src + j * 16 + 0) >> 0) & 0x3ff) - 512;
786       }
787       if (j * 6 + 2 < frame->width) {
788         dest[j * 3 + 1] =
789             ((READ_UINT32_LE (src + j * 16 + 4) >> 10) & 0x3ff) - 512;
790       }
791       if (j * 6 + 4 < frame->width) {
792         dest[j * 3 + 2] =
793             ((READ_UINT32_LE (src + j * 16 + 8) >> 20) & 0x3ff) - 512;
794       }
795       break;
796     case 2:
797       for (j = 0; j < frame->width / 6; j++) {
798         dest[j * 3 + 0] =
799             ((READ_UINT32_LE (src + j * 16 + 0) >> 20) & 0x3ff) - 512;
800         dest[j * 3 + 1] =
801             ((READ_UINT32_LE (src + j * 16 + 8) >> 0) & 0x3ff) - 512;
802         dest[j * 3 + 2] =
803             ((READ_UINT32_LE (src + j * 16 + 12) >> 10) & 0x3ff) - 512;
804       }
805       if (j * 6 + 0 < frame->width) {
806         dest[j * 3 + 0] =
807             ((READ_UINT32_LE (src + j * 16 + 0) >> 20) & 0x3ff) - 512;
808       }
809       if (j * 6 + 2 < frame->width) {
810         dest[j * 3 + 1] =
811             ((READ_UINT32_LE (src + j * 16 + 8) >> 0) & 0x3ff) - 512;
812       }
813       if (j * 6 + 4 < frame->width) {
814         dest[j * 3 + 2] =
815             ((READ_UINT32_LE (src + j * 16 + 12) >> 10) & 0x3ff) - 512;
816       }
817       break;
818     default:
819       SCHRO_ASSERT (0);
820   }
821 }
822 
823 static void
unpack_v216(SchroFrame * frame,void * _dest,int component,int i)824 unpack_v216 (SchroFrame * frame, void *_dest, int component, int i)
825 {
826   int16_t *dest = _dest;
827   uint8_t *src;
828   int j;
829 
830   src = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
831 
832   switch (component) {
833     case 0:
834       for (j = 0; j < frame->width; j++) {
835         dest[j] = src[j * 4 + 2 + 1];
836       }
837       break;
838     case 1:
839       for (j = 0; j < frame->width / 2; j++) {
840         dest[j] = src[j * 8 + 0 + 1];
841       }
842       break;
843     case 2:
844       for (j = 0; j < frame->width / 2; j++) {
845         dest[j] = src[j * 8 + 4 + 1];
846       }
847       break;
848     default:
849       SCHRO_ASSERT (0);
850   }
851 }
852 
853 SchroFrame *
schro_virt_frame_new_unpack(SchroFrame * vf)854 schro_virt_frame_new_unpack (SchroFrame * vf)
855 {
856   SchroFrame *virt_frame;
857   SchroFrameFormat format;
858   SchroFrameRenderFunc render_line;
859 
860   switch (vf->format) {
861     case SCHRO_FRAME_FORMAT_YUYV:
862       format = SCHRO_FRAME_FORMAT_U8_422;
863       render_line = unpack_yuyv;
864       break;
865     case SCHRO_FRAME_FORMAT_UYVY:
866       format = SCHRO_FRAME_FORMAT_U8_422;
867       render_line = unpack_uyvy;
868       break;
869     case SCHRO_FRAME_FORMAT_AYUV:
870       format = SCHRO_FRAME_FORMAT_U8_444;
871       render_line = unpack_ayuv;
872       break;
873     case SCHRO_FRAME_FORMAT_v210:
874       format = SCHRO_FRAME_FORMAT_S16_422;
875       render_line = unpack_v210;
876       break;
877     case SCHRO_FRAME_FORMAT_v216:
878       format = SCHRO_FRAME_FORMAT_S16_422;
879       render_line = unpack_v216;
880       break;
881     case SCHRO_FRAME_FORMAT_AY64:
882       format = SCHRO_FRAME_FORMAT_S32_444;
883       render_line = unpack_AY64;
884       break;
885     default:
886       return vf;
887   }
888 
889   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
890   virt_frame->virt_frame1 = vf;
891   virt_frame->render_line = render_line;
892 
893   return virt_frame;
894 }
895 
896 
897 static void
pack_yuyv(SchroFrame * frame,void * _dest,int component,int i)898 pack_yuyv (SchroFrame * frame, void *_dest, int component, int i)
899 {
900   uint32_t *dest = _dest;
901   uint8_t *src_y;
902   uint8_t *src_u;
903   uint8_t *src_v;
904 
905   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
906   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
907   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
908 
909   orc_packyuyv (dest, src_y, src_u, src_v, frame->width / 2);
910 }
911 
912 
913 SchroFrame *
schro_virt_frame_new_pack_YUY2(SchroFrame * vf)914 schro_virt_frame_new_pack_YUY2 (SchroFrame * vf)
915 {
916   SchroFrame *virt_frame;
917 
918   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_YUYV,
919       vf->width, vf->height);
920   virt_frame->virt_frame1 = vf;
921   virt_frame->render_line = pack_yuyv;
922 
923   return virt_frame;
924 }
925 
926 static void
pack_uyvy(SchroFrame * frame,void * _dest,int component,int i)927 pack_uyvy (SchroFrame * frame, void *_dest, int component, int i)
928 {
929   uint8_t *dest = _dest;
930   uint8_t *src_y;
931   uint8_t *src_u;
932   uint8_t *src_v;
933   int j;
934 
935   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
936   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
937   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
938 
939   for (j = 0; j < frame->width / 2; j++) {
940     dest[j * 4 + 1] = src_y[j * 2 + 0];
941     dest[j * 4 + 3] = src_y[j * 2 + 1];
942     dest[j * 4 + 0] = src_u[j];
943     dest[j * 4 + 2] = src_v[j];
944   }
945 }
946 
947 SchroFrame *
schro_virt_frame_new_pack_UYVY(SchroFrame * vf)948 schro_virt_frame_new_pack_UYVY (SchroFrame * vf)
949 {
950   SchroFrame *virt_frame;
951 
952   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_YUYV,
953       vf->width, vf->height);
954   virt_frame->virt_frame1 = vf;
955   virt_frame->render_line = pack_uyvy;
956 
957   return virt_frame;
958 }
959 
960 static void
pack_v216(SchroFrame * frame,void * _dest,int component,int i)961 pack_v216 (SchroFrame * frame, void *_dest, int component, int i)
962 {
963   uint8_t *dest = _dest;
964   uint8_t *src_y;
965   uint8_t *src_u;
966   uint8_t *src_v;
967   int j;
968 
969   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
970   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
971   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
972 
973   for (j = 0; j < frame->width / 2; j++) {
974     dest[j * 8 + 0] = src_u[j];
975     dest[j * 8 + 1] = src_u[j];
976     dest[j * 8 + 2] = src_y[j * 2 + 0];
977     dest[j * 8 + 3] = src_y[j * 2 + 0];
978     dest[j * 8 + 4] = src_v[j];
979     dest[j * 8 + 5] = src_v[j];
980     dest[j * 8 + 6] = src_y[j * 2 + 1];
981     dest[j * 8 + 7] = src_y[j * 2 + 1];
982   }
983 }
984 
985 SchroFrame *
schro_virt_frame_new_pack_v216(SchroFrame * vf)986 schro_virt_frame_new_pack_v216 (SchroFrame * vf)
987 {
988   SchroFrame *virt_frame;
989 
990   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_v216,
991       vf->width, vf->height);
992   virt_frame->virt_frame1 = vf;
993   virt_frame->render_line = pack_v216;
994 
995   return virt_frame;
996 }
997 
998 static void
pack_v210_s16(SchroFrame * frame,void * _dest,int component,int i)999 pack_v210_s16 (SchroFrame * frame, void *_dest, int component, int i)
1000 {
1001   uint8_t *dest = _dest;
1002   int16_t *src_y;
1003   int16_t *src_u;
1004   int16_t *src_v;
1005   int j;
1006   uint32_t val;
1007 
1008   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1009   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1010   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1011 
1012 #define TO_10(x) (CLAMP(((x) + 512), 0, 1023))
1013 #define WRITE_UINT32_LE(a,b) do { \
1014   ((uint8_t *)(a))[0] = (b)&0xff; \
1015   ((uint8_t *)(a))[1] = ((b)>>8)&0xff; \
1016   ((uint8_t *)(a))[2] = ((b)>>16)&0xff; \
1017   ((uint8_t *)(a))[3] = ((b)>>24)&0xff; \
1018 } while(0)
1019   for (j = 0; j < frame->width / 6; j++) {
1020     int y0, y1, y2, y3, y4, y5;
1021     int cr0, cr1, cr2;
1022     int cb0, cb1, cb2;
1023 
1024     y0 = TO_10 (src_y[j * 6 + 0]);
1025     y1 = TO_10 (src_y[j * 6 + 1]);
1026     y2 = TO_10 (src_y[j * 6 + 2]);
1027     y3 = TO_10 (src_y[j * 6 + 3]);
1028     y4 = TO_10 (src_y[j * 6 + 4]);
1029     y5 = TO_10 (src_y[j * 6 + 5]);
1030     cb0 = TO_10 (src_u[j * 3 + 0]);
1031     cb1 = TO_10 (src_u[j * 3 + 1]);
1032     cb2 = TO_10 (src_u[j * 3 + 2]);
1033     cr0 = TO_10 (src_v[j * 3 + 0]);
1034     cr1 = TO_10 (src_v[j * 3 + 1]);
1035     cr2 = TO_10 (src_v[j * 3 + 2]);
1036 
1037     val = (cr0 << 20) | (y0 << 10) | (cb0);
1038     WRITE_UINT32_LE (dest + j * 16 + 0, val);
1039 
1040     val = (y2 << 20) | (cb1 << 10) | (y1);
1041     WRITE_UINT32_LE (dest + j * 16 + 4, val);
1042 
1043     val = (cb2 << 20) | (y3 << 10) | (cr1);
1044     WRITE_UINT32_LE (dest + j * 16 + 8, val);
1045 
1046     val = (y5 << 20) | (cr2 << 10) | (y4);
1047     WRITE_UINT32_LE (dest + j * 16 + 12, val);
1048   }
1049   if (j * 6 < frame->width) {
1050     int y0, y1, y2, y3, y4, y5;
1051     int cr0, cr1, cr2;
1052     int cb0, cb1, cb2;
1053 
1054     y0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_y[j * 6 + 0]) : 0;
1055     y1 = ((j * 6 + 1) < frame->width) ? TO_10 (src_y[j * 6 + 1]) : 0;
1056     y2 = ((j * 6 + 2) < frame->width) ? TO_10 (src_y[j * 6 + 2]) : 0;
1057     y3 = ((j * 6 + 3) < frame->width) ? TO_10 (src_y[j * 6 + 3]) : 0;
1058     y4 = ((j * 6 + 4) < frame->width) ? TO_10 (src_y[j * 6 + 4]) : 0;
1059     y5 = ((j * 6 + 5) < frame->width) ? TO_10 (src_y[j * 6 + 5]) : 0;
1060     cb0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_u[j * 3 + 0]) : 0;
1061     cb1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_u[j * 3 + 1]) : 0;
1062     cb2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_u[j * 3 + 2]) : 0;
1063     cr0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_v[j * 3 + 0]) : 0;
1064     cr1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_v[j * 3 + 1]) : 0;
1065     cr2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_v[j * 3 + 2]) : 0;
1066 
1067     val = (cr0 << 20) | (y0 << 10) | (cb0);
1068     WRITE_UINT32_LE (dest + j * 16 + 0, val);
1069 
1070     val = (y2 << 20) | (cb1 << 10) | (y1);
1071     WRITE_UINT32_LE (dest + j * 16 + 4, val);
1072 
1073     val = (cb2 << 20) | (y3 << 10) | (cr1);
1074     WRITE_UINT32_LE (dest + j * 16 + 8, val);
1075 
1076     val = (y5 << 20) | (cr2 << 10) | (y4);
1077     WRITE_UINT32_LE (dest + j * 16 + 12, val);
1078   }
1079 #undef TO_10
1080 
1081 }
1082 
1083 static void
pack_v210(SchroFrame * frame,void * _dest,int component,int i)1084 pack_v210 (SchroFrame * frame, void *_dest, int component, int i)
1085 {
1086   uint8_t *dest = _dest;
1087   uint8_t *src_y;
1088   uint8_t *src_u;
1089   uint8_t *src_v;
1090   int j;
1091   uint32_t val;
1092 
1093   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1094   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1095   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1096 
1097 #define TO_10(x) (((x)<<2) | ((x)>>6))
1098 #define WRITE_UINT32_LE(a,b) do { \
1099   ((uint8_t *)(a))[0] = (b)&0xff; \
1100   ((uint8_t *)(a))[1] = ((b)>>8)&0xff; \
1101   ((uint8_t *)(a))[2] = ((b)>>16)&0xff; \
1102   ((uint8_t *)(a))[3] = ((b)>>24)&0xff; \
1103 } while(0)
1104   for (j = 0; j < frame->width / 6; j++) {
1105     int y0, y1, y2, y3, y4, y5;
1106     int cr0, cr1, cr2;
1107     int cb0, cb1, cb2;
1108 
1109     y0 = TO_10 (src_y[j * 6 + 0]);
1110     y1 = TO_10 (src_y[j * 6 + 1]);
1111     y2 = TO_10 (src_y[j * 6 + 2]);
1112     y3 = TO_10 (src_y[j * 6 + 3]);
1113     y4 = TO_10 (src_y[j * 6 + 4]);
1114     y5 = TO_10 (src_y[j * 6 + 5]);
1115     cb0 = TO_10 (src_u[j * 3 + 0]);
1116     cb1 = TO_10 (src_u[j * 3 + 1]);
1117     cb2 = TO_10 (src_u[j * 3 + 2]);
1118     cr0 = TO_10 (src_v[j * 3 + 0]);
1119     cr1 = TO_10 (src_v[j * 3 + 1]);
1120     cr2 = TO_10 (src_v[j * 3 + 2]);
1121 
1122     val = (cr0 << 20) | (y0 << 10) | (cb0);
1123     WRITE_UINT32_LE (dest + j * 16 + 0, val);
1124 
1125     val = (y2 << 20) | (cb1 << 10) | (y1);
1126     WRITE_UINT32_LE (dest + j * 16 + 4, val);
1127 
1128     val = (cb2 << 20) | (y3 << 10) | (cr1);
1129     WRITE_UINT32_LE (dest + j * 16 + 8, val);
1130 
1131     val = (y5 << 20) | (cr2 << 10) | (y4);
1132     WRITE_UINT32_LE (dest + j * 16 + 12, val);
1133   }
1134   if (j * 6 < frame->width) {
1135     int y0, y1, y2, y3, y4, y5;
1136     int cr0, cr1, cr2;
1137     int cb0, cb1, cb2;
1138 
1139     y0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_y[j * 6 + 0]) : 0;
1140     y1 = ((j * 6 + 1) < frame->width) ? TO_10 (src_y[j * 6 + 1]) : 0;
1141     y2 = ((j * 6 + 2) < frame->width) ? TO_10 (src_y[j * 6 + 2]) : 0;
1142     y3 = ((j * 6 + 3) < frame->width) ? TO_10 (src_y[j * 6 + 3]) : 0;
1143     y4 = ((j * 6 + 4) < frame->width) ? TO_10 (src_y[j * 6 + 4]) : 0;
1144     y5 = ((j * 6 + 5) < frame->width) ? TO_10 (src_y[j * 6 + 5]) : 0;
1145     cb0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_u[j * 3 + 0]) : 0;
1146     cb1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_u[j * 3 + 1]) : 0;
1147     cb2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_u[j * 3 + 2]) : 0;
1148     cr0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_v[j * 3 + 0]) : 0;
1149     cr1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_v[j * 3 + 1]) : 0;
1150     cr2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_v[j * 3 + 2]) : 0;
1151 
1152     val = (cr0 << 20) | (y0 << 10) | (cb0);
1153     WRITE_UINT32_LE (dest + j * 16 + 0, val);
1154 
1155     val = (y2 << 20) | (cb1 << 10) | (y1);
1156     WRITE_UINT32_LE (dest + j * 16 + 4, val);
1157 
1158     val = (cb2 << 20) | (y3 << 10) | (cr1);
1159     WRITE_UINT32_LE (dest + j * 16 + 8, val);
1160 
1161     val = (y5 << 20) | (cr2 << 10) | (y4);
1162     WRITE_UINT32_LE (dest + j * 16 + 12, val);
1163   }
1164 
1165 }
1166 
1167 SchroFrame *
schro_virt_frame_new_pack_v210(SchroFrame * vf)1168 schro_virt_frame_new_pack_v210 (SchroFrame * vf)
1169 {
1170   SchroFrame *virt_frame;
1171 
1172   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_v210,
1173       vf->width, vf->height);
1174   virt_frame->virt_frame1 = vf;
1175   if (vf->format == SCHRO_FRAME_FORMAT_S16_422) {
1176     virt_frame->render_line = pack_v210_s16;
1177   } else {
1178     virt_frame->render_line = pack_v210;
1179   }
1180 
1181   return virt_frame;
1182 }
1183 
1184 static void
pack_ayuv(SchroFrame * frame,void * _dest,int component,int i)1185 pack_ayuv (SchroFrame * frame, void *_dest, int component, int i)
1186 {
1187   uint8_t *dest = _dest;
1188   uint8_t *src_y;
1189   uint8_t *src_u;
1190   uint8_t *src_v;
1191   int j;
1192 
1193   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1194   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1195   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1196 
1197   for (j = 0; j < frame->width; j++) {
1198     dest[j * 4 + 0] = 0xff;
1199     dest[j * 4 + 1] = src_y[j];
1200     dest[j * 4 + 2] = src_u[j];
1201     dest[j * 4 + 3] = src_v[j];
1202   }
1203 }
1204 
1205 SchroFrame *
schro_virt_frame_new_pack_AYUV(SchroFrame * vf)1206 schro_virt_frame_new_pack_AYUV (SchroFrame * vf)
1207 {
1208   SchroFrame *virt_frame;
1209 
1210   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_AYUV,
1211       vf->width, vf->height);
1212   virt_frame->virt_frame1 = vf;
1213   virt_frame->render_line = pack_ayuv;
1214 
1215   return virt_frame;
1216 }
1217 
1218 static void
pack_ayuv64(SchroFrame * frame,void * _dest,int component,int i)1219 pack_ayuv64 (SchroFrame * frame, void *_dest, int component, int i)
1220 {
1221   uint16_t *dest = _dest;
1222   int32_t *src_y;
1223   int32_t *src_u;
1224   int32_t *src_v;
1225   int j;
1226 
1227   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1228   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1229   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1230 
1231   for (j = 0; j < frame->width; j++) {
1232     dest[j * 4 + 0] = 0xffff;
1233     dest[j * 4 + 1] = CLAMP(src_y[j] + 0x8000, 0, 0xffff);
1234     dest[j * 4 + 2] = CLAMP(src_u[j] + 0x8000, 0, 0xffff);
1235     dest[j * 4 + 3] = CLAMP(src_v[j] + 0x8000, 0, 0xffff);
1236   }
1237 }
1238 
1239 SchroFrame *
schro_virt_frame_new_pack_AY64(SchroFrame * vf)1240 schro_virt_frame_new_pack_AY64 (SchroFrame * vf)
1241 {
1242   SchroFrame *virt_frame;
1243 
1244   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_AY64,
1245       vf->width, vf->height);
1246   virt_frame->virt_frame1 = vf;
1247   virt_frame->render_line = pack_ayuv64;
1248 
1249   return virt_frame;
1250 }
1251 
1252 #ifdef unused
1253 static void
pack_rgb(SchroFrame * frame,void * _dest,int component,int i)1254 pack_rgb (SchroFrame * frame, void *_dest, int component, int i)
1255 {
1256   uint8_t *dest = _dest;
1257   uint8_t *src_y;
1258   uint8_t *src_u;
1259   uint8_t *src_v;
1260   int j;
1261 
1262   src_y = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1263   src_u = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1264   src_v = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1265 
1266   for (j = 0; j < frame->width; j++) {
1267     dest[j * 3 + 0] = src_y[j];
1268     dest[j * 3 + 1] = src_u[j];
1269     dest[j * 3 + 2] = src_v[j];
1270   }
1271 }
1272 #endif
1273 
1274 #ifdef unused
1275 SchroFrame *
schro_virt_frame_new_pack_RGB(SchroFrame * vf)1276 schro_virt_frame_new_pack_RGB (SchroFrame * vf)
1277 {
1278   SchroFrame *virt_frame;
1279 
1280   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_RGB,
1281       vf->width, vf->height);
1282   virt_frame->virt_frame1 = vf;
1283   virt_frame->render_line = pack_rgb;
1284 
1285   return virt_frame;
1286 }
1287 #endif
1288 
1289 #ifdef unused
1290 static void
color_matrix(SchroFrame * frame,void * _dest,int component,int i)1291 color_matrix (SchroFrame * frame, void *_dest, int component, int i)
1292 {
1293   uint8_t *dest = _dest;
1294   uint8_t *src1;
1295   uint8_t *src2;
1296   uint8_t *src3;
1297   double m1, m2, m3;
1298   double offset;
1299   int j;
1300 
1301   src1 = schro_virt_frame_get_line (frame->virt_frame1, 0, i);
1302   src2 = schro_virt_frame_get_line (frame->virt_frame1, 1, i);
1303   src3 = schro_virt_frame_get_line (frame->virt_frame1, 2, i);
1304 
1305   switch (component) {
1306     case 0:
1307       m1 = 0.25679;
1308       m2 = 0.50413;
1309       m3 = 0.097906;
1310       offset = 16;
1311       break;
1312     case 1:
1313       m1 = -0.14822;
1314       m2 = -0.29099;
1315       m3 = 0.43922;
1316       offset = 128;
1317       break;
1318     case 2:
1319       m1 = 0.43922;
1320       m2 = -0.36779;
1321       m3 = -0.071427;
1322       offset = 128;
1323       break;
1324     default:
1325       m1 = 0.0;
1326       m2 = 0.0;
1327       m3 = 0.0;
1328       offset = 0;
1329       break;
1330   }
1331 
1332   for (j = 0; j < frame->width; j++) {
1333     dest[j] = floor (src1[j] * m1 + src2[j] * m2 + src3[j] * m3 + offset + 0.5);
1334   }
1335 
1336 }
1337 #endif
1338 
1339 #ifdef unused
1340 SchroFrame *
schro_virt_frame_new_color_matrix(SchroFrame * vf)1341 schro_virt_frame_new_color_matrix (SchroFrame * vf)
1342 {
1343   SchroFrame *virt_frame;
1344 
1345   virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_U8_444,
1346       vf->width, vf->height);
1347   virt_frame->virt_frame1 = vf;
1348   virt_frame->render_line = color_matrix;
1349 
1350   return virt_frame;
1351 }
1352 #endif
1353 
1354 static void
convert_444_422(SchroFrame * frame,void * _dest,int component,int i)1355 convert_444_422 (SchroFrame * frame, void *_dest, int component, int i)
1356 {
1357   uint8_t *dest = _dest;
1358   uint8_t *src;
1359   int j;
1360 
1361   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1362 
1363   if (component == 0) {
1364     orc_memcpy (dest, src, frame->width);
1365   } else {
1366     for (j = 0; j < frame->components[component].width; j++) {
1367       dest[j] = src[j * 2];
1368     }
1369   }
1370 }
1371 
1372 static void
convert_444_420(SchroFrame * frame,void * _dest,int component,int i)1373 convert_444_420 (SchroFrame * frame, void *_dest, int component, int i)
1374 {
1375   uint8_t *dest = _dest;
1376   uint8_t *src;
1377   int j;
1378 
1379   if (component == 0) {
1380     src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1381     orc_memcpy (dest, src, frame->components[component].width);
1382   } else {
1383     src = schro_virt_frame_get_line (frame->virt_frame1, component, i * 2);
1384     for (j = 0; j < frame->components[component].width; j++) {
1385       dest[j] = src[j * 2];
1386     }
1387   }
1388 }
1389 
1390 static void
convert_422_420(SchroFrame * frame,void * _dest,int component,int i)1391 convert_422_420 (SchroFrame * frame, void *_dest, int component, int i)
1392 {
1393   uint8_t *dest = _dest;
1394   uint8_t *src;
1395 
1396   if (component == 0) {
1397     src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1398   } else {
1399     src = schro_virt_frame_get_line (frame->virt_frame1, component, i * 2);
1400   }
1401   orc_memcpy (dest, src, frame->components[component].width);
1402 }
1403 
1404 /* up */
1405 
1406 static void
convert_422_444(SchroFrame * frame,void * _dest,int component,int i)1407 convert_422_444 (SchroFrame * frame, void *_dest, int component, int i)
1408 {
1409   uint8_t *dest = _dest;
1410   uint8_t *src;
1411   int j;
1412 
1413   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1414 
1415   if (component == 0) {
1416     orc_memcpy (dest, src, frame->width);
1417   } else {
1418     for (j = 0; j < frame->components[component].width; j++) {
1419       dest[j] = src[j >> 1];
1420     }
1421   }
1422 }
1423 
1424 static void
convert_420_444(SchroFrame * frame,void * _dest,int component,int i)1425 convert_420_444 (SchroFrame * frame, void *_dest, int component, int i)
1426 {
1427   uint8_t *dest = _dest;
1428   uint8_t *src;
1429   int j;
1430 
1431   if (component == 0) {
1432     src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1433     orc_memcpy (dest, src, frame->components[component].width);
1434   } else {
1435     src = schro_virt_frame_get_line (frame->virt_frame1, component, i >> 1);
1436     for (j = 0; j < frame->components[component].width; j++) {
1437       dest[j] = src[j >> 1];
1438     }
1439   }
1440 }
1441 
1442 static void
convert_420_422(SchroFrame * frame,void * _dest,int component,int i)1443 convert_420_422 (SchroFrame * frame, void *_dest, int component, int i)
1444 {
1445   uint8_t *dest = _dest;
1446   uint8_t *src;
1447 
1448   if (component == 0) {
1449     src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1450   } else {
1451     src = schro_virt_frame_get_line (frame->virt_frame1, component, i >> 1);
1452   }
1453   orc_memcpy (dest, src, frame->components[component].width);
1454 }
1455 
1456 SchroFrame *
schro_virt_frame_new_subsample(SchroFrame * vf,SchroFrameFormat format)1457 schro_virt_frame_new_subsample (SchroFrame * vf, SchroFrameFormat format)
1458 {
1459   SchroFrame *virt_frame;
1460   SchroFrameRenderFunc render_line;
1461 
1462   if (vf->format == format) {
1463     return vf;
1464   }
1465   if (vf->format == SCHRO_FRAME_FORMAT_U8_422 &&
1466       format == SCHRO_FRAME_FORMAT_U8_420) {
1467     render_line = convert_422_420;
1468   } else if (vf->format == SCHRO_FRAME_FORMAT_U8_444 &&
1469       format == SCHRO_FRAME_FORMAT_U8_420) {
1470     render_line = convert_444_420;
1471   } else if (vf->format == SCHRO_FRAME_FORMAT_U8_444 &&
1472       format == SCHRO_FRAME_FORMAT_U8_422) {
1473     render_line = convert_444_422;
1474   } else if (vf->format == SCHRO_FRAME_FORMAT_U8_420 &&
1475       format == SCHRO_FRAME_FORMAT_U8_422) {
1476     render_line = convert_420_422;
1477   } else if (vf->format == SCHRO_FRAME_FORMAT_U8_420 &&
1478       format == SCHRO_FRAME_FORMAT_U8_444) {
1479     render_line = convert_420_444;
1480   } else if (vf->format == SCHRO_FRAME_FORMAT_U8_422 &&
1481       format == SCHRO_FRAME_FORMAT_U8_444) {
1482     render_line = convert_422_444;
1483   } else {
1484     SCHRO_ASSERT (0);
1485     return NULL;
1486   }
1487   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
1488   virt_frame->virt_frame1 = vf;
1489   virt_frame->render_line = render_line;
1490 
1491   return virt_frame;
1492 }
1493 
1494 
1495 #if 0
1496 SchroFrame *
1497 schro_virt_frame_new_horiz_downsample_take (SchroFrame * vf, int cosite)
1498 {
1499   SchroFrame *virt_frame;
1500   virt_frame = schro_virt_frame_new_horiz_downsample (vf, cosite);
1501   schro_frame_unref (vf);
1502   return virt_frame;
1503 }
1504 
1505 SchroFrame *
1506 schro_virt_frame_new_vert_downsample_take (SchroFrame * vf, int cosite)
1507 {
1508   SchroFrame *virt_frame;
1509   virt_frame = schro_virt_frame_new_vert_downsample (vf, cosite);
1510   schro_frame_unref (vf);
1511   return virt_frame;
1512 }
1513 
1514 SchroFrame *
1515 schro_virt_frame_new_vert_resample_take (SchroFrame * vf, int height)
1516 {
1517   SchroFrame *virt_frame;
1518   virt_frame = schro_virt_frame_new_vert_resample (vf, height);
1519   schro_frame_unref (vf);
1520   return virt_frame;
1521 }
1522 
1523 SchroFrame *
1524 schro_virt_frame_new_horiz_resample_take (SchroFrame * vf, int width)
1525 {
1526   SchroFrame *virt_frame;
1527   virt_frame = schro_virt_frame_new_horiz_resample (vf, width);
1528   schro_frame_unref (vf);
1529   return virt_frame;
1530 }
1531 
1532 SchroFrame *
1533 schro_virt_frame_new_unpack_take (SchroFrame * vf)
1534 {
1535   SchroFrame *virt_frame;
1536   virt_frame = schro_virt_frame_new_unpack (vf);
1537   schro_frame_unref (vf);
1538   return virt_frame;
1539 }
1540 
1541 SchroFrame *
1542 schro_virt_frame_new_pack_YUY2_take (SchroFrame * vf)
1543 {
1544   SchroFrame *virt_frame;
1545   virt_frame = schro_virt_frame_new_pack_YUY2 (vf);
1546   schro_frame_unref (vf);
1547   return virt_frame;
1548 }
1549 
1550 SchroFrame *
1551 schro_virt_frame_new_pack_UYVY_take (SchroFrame * vf)
1552 {
1553   SchroFrame *virt_frame;
1554   virt_frame = schro_virt_frame_new_pack_UYVY (vf);
1555   schro_frame_unref (vf);
1556   return virt_frame;
1557 }
1558 
1559 SchroFrame *
1560 schro_virt_frame_new_pack_v216_take (SchroFrame * vf)
1561 {
1562   SchroFrame *virt_frame;
1563   virt_frame = schro_virt_frame_new_pack_v216 (vf);
1564   schro_frame_unref (vf);
1565   return virt_frame;
1566 }
1567 
1568 SchroFrame *
1569 schro_virt_frame_new_pack_v210_take (SchroFrame * vf)
1570 {
1571   SchroFrame *virt_frame;
1572   virt_frame = schro_virt_frame_new_pack_v210 (vf);
1573   schro_frame_unref (vf);
1574   return virt_frame;
1575 }
1576 
1577 SchroFrame *
1578 schro_virt_frame_new_pack_AYUV_take (SchroFrame * vf)
1579 {
1580   SchroFrame *virt_frame;
1581   virt_frame = schro_virt_frame_new_pack_AYUV (vf);
1582   schro_frame_unref (vf);
1583   return virt_frame;
1584 }
1585 
1586 SchroFrame *
1587 schro_virt_frame_new_pack_RGB_take (SchroFrame * vf)
1588 {
1589   SchroFrame *virt_frame;
1590   virt_frame = schro_virt_frame_new_pack_RGB (vf);
1591   schro_frame_unref (vf);
1592   return virt_frame;
1593 }
1594 
1595 SchroFrame *
1596 schro_virt_frame_new_subsample_take (SchroFrame * vf, SchroFrameFormat format)
1597 {
1598   SchroFrame *virt_frame;
1599   virt_frame = schro_virt_frame_new_subsample (vf, format);
1600   schro_frame_unref (vf);
1601   return virt_frame;
1602 }
1603 #endif
1604 
1605 static void
convert_u8_s16(SchroFrame * frame,void * _dest,int component,int i)1606 convert_u8_s16 (SchroFrame * frame, void *_dest, int component, int i)
1607 {
1608   uint8_t *dest = _dest;
1609   int16_t *src;
1610 
1611   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1612   orc_offsetconvert_u8_s16 (dest, src, frame->components[component].width);
1613 }
1614 
1615 SchroFrame *
schro_virt_frame_new_convert_u8(SchroFrame * vf)1616 schro_virt_frame_new_convert_u8 (SchroFrame * vf)
1617 {
1618   SchroFrame *virt_frame;
1619   SchroFrameFormat format;
1620 
1621   format = (vf->format & 3) | SCHRO_FRAME_FORMAT_U8_444;
1622 
1623   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
1624   virt_frame->virt_frame1 = vf;
1625   virt_frame->render_line = convert_u8_s16;
1626   virt_frame->virt_priv = schro_malloc (sizeof (int16_t) * vf->width);
1627 
1628   return virt_frame;
1629 }
1630 
1631 static void
convert_u8_s32(SchroFrame * frame,void * _dest,int component,int i)1632 convert_u8_s32 (SchroFrame * frame, void *_dest, int component, int i)
1633 {
1634   uint8_t *dest = _dest;
1635   int32_t *src;
1636 
1637   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1638   orc_offsetconvert_u8_s32 (dest, src, frame->components[component].width);
1639 }
1640 
1641 SchroFrame *
schro_virt_frame_new_convert_u8_s32(SchroFrame * vf)1642 schro_virt_frame_new_convert_u8_s32 (SchroFrame * vf)
1643 {
1644   SchroFrame *virt_frame;
1645   SchroFrameFormat format;
1646 
1647   format = (vf->format & 3) | SCHRO_FRAME_FORMAT_U8_444;
1648 
1649   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
1650   virt_frame->virt_frame1 = vf;
1651   virt_frame->render_line = convert_u8_s32;
1652   virt_frame->virt_priv = schro_malloc (sizeof (int32_t) * vf->width);
1653 
1654   return virt_frame;
1655 }
1656 
1657 static void
convert_s16_u8(SchroFrame * frame,void * _dest,int component,int i)1658 convert_s16_u8 (SchroFrame * frame, void *_dest, int component, int i)
1659 {
1660   int16_t *dest = _dest;
1661   uint8_t *src;
1662 
1663   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1664 
1665   orc_offsetconvert_s16_u8 (dest, src, frame->components[component].width);
1666 }
1667 
1668 static void
convert_s16_s32(SchroFrame * frame,void * _dest,int component,int i)1669 convert_s16_s32 (SchroFrame * frame, void *_dest, int component, int i)
1670 {
1671   int16_t *dest = _dest;
1672   int32_t *src;
1673 
1674   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1675 
1676   orc_convert_s16_s32 (dest, src, frame->components[component].width);
1677 }
1678 
1679 SchroFrame *
schro_virt_frame_new_convert_s16(SchroFrame * vf)1680 schro_virt_frame_new_convert_s16 (SchroFrame * vf)
1681 {
1682   SchroFrame *virt_frame;
1683   SchroFrameFormat format;
1684 
1685   format = (vf->format & 3) | SCHRO_FRAME_FORMAT_S16_444;
1686 
1687   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
1688   virt_frame->virt_frame1 = vf;
1689   if (SCHRO_FRAME_FORMAT_DEPTH (vf->format) == SCHRO_FRAME_FORMAT_DEPTH_S32) {
1690     virt_frame->render_line = convert_s16_s32;
1691   } else {
1692     virt_frame->render_line = convert_s16_u8;
1693   }
1694 
1695   return virt_frame;
1696 }
1697 
1698 static void
convert_s32_u8(SchroFrame * frame,void * _dest,int component,int i)1699 convert_s32_u8 (SchroFrame * frame, void *_dest, int component, int i)
1700 {
1701   int32_t *dest = _dest;
1702   uint8_t *src;
1703 
1704   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1705 
1706   orc_offsetconvert_s32_u8 (dest, src, frame->components[component].width);
1707 }
1708 
1709 static void
convert_s32_s16(SchroFrame * frame,void * _dest,int component,int i)1710 convert_s32_s16 (SchroFrame * frame, void *_dest, int component, int i)
1711 {
1712   int32_t *dest = _dest;
1713   int16_t *src;
1714 
1715   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1716 
1717   orc_convert_s32_s16 (dest, src, frame->components[component].width);
1718 }
1719 
1720 SchroFrame *
schro_virt_frame_new_convert_s32(SchroFrame * vf)1721 schro_virt_frame_new_convert_s32 (SchroFrame * vf)
1722 {
1723   SchroFrame *virt_frame;
1724   SchroFrameFormat format;
1725 
1726   format = (vf->format & 3) | SCHRO_FRAME_FORMAT_S32_444;
1727 
1728   virt_frame = schro_frame_new_virtual (NULL, format, vf->width, vf->height);
1729   virt_frame->virt_frame1 = vf;
1730   if (SCHRO_FRAME_FORMAT_DEPTH (vf->format) == SCHRO_FRAME_FORMAT_DEPTH_S16) {
1731     virt_frame->render_line = convert_s32_s16;
1732   } else {
1733     virt_frame->render_line = convert_s32_u8;
1734   }
1735 
1736   return virt_frame;
1737 }
1738 
1739 static void
crop_u8(SchroFrame * frame,void * _dest,int component,int i)1740 crop_u8 (SchroFrame * frame, void *_dest, int component, int i)
1741 {
1742   uint8_t *dest = _dest;
1743   uint8_t *src;
1744 
1745   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1746   orc_memcpy (dest, src, frame->components[component].width);
1747 }
1748 
1749 static void
crop_s16(SchroFrame * frame,void * _dest,int component,int i)1750 crop_s16 (SchroFrame * frame, void *_dest, int component, int i)
1751 {
1752   int16_t *dest = _dest;
1753   int16_t *src;
1754 
1755   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1756   orc_memcpy (dest, src, frame->components[component].width * sizeof (int16_t));
1757 }
1758 
1759 static void
crop_s32(SchroFrame * frame,void * _dest,int component,int i)1760 crop_s32 (SchroFrame * frame, void *_dest, int component, int i)
1761 {
1762   int16_t *dest = _dest;
1763   int16_t *src;
1764 
1765   src = schro_virt_frame_get_line (frame->virt_frame1, component, i);
1766   orc_memcpy (dest, src, frame->components[component].width * sizeof (int32_t));
1767 }
1768 
1769 SchroFrame *
schro_virt_frame_new_crop(SchroFrame * vf,int width,int height)1770 schro_virt_frame_new_crop (SchroFrame * vf, int width, int height)
1771 {
1772   SchroFrame *virt_frame;
1773 
1774   if (width == vf->width && height == vf->height)
1775     return vf;
1776 
1777   SCHRO_ASSERT (width <= vf->width);
1778   SCHRO_ASSERT (height <= vf->height);
1779 
1780   virt_frame = schro_frame_new_virtual (NULL, vf->format, width, height);
1781   virt_frame->virt_frame1 = vf;
1782   switch (SCHRO_FRAME_FORMAT_DEPTH (vf->format)) {
1783     case SCHRO_FRAME_FORMAT_DEPTH_U8:
1784       virt_frame->render_line = crop_u8;
1785       break;
1786     case SCHRO_FRAME_FORMAT_DEPTH_S16:
1787       virt_frame->render_line = crop_s16;
1788       break;
1789     default:
1790       virt_frame->render_line = crop_s32;
1791       break;
1792   }
1793 
1794   return virt_frame;
1795 }
1796 
1797 static void
edge_extend_u8(SchroFrame * frame,void * _dest,int component,int i)1798 edge_extend_u8 (SchroFrame * frame, void *_dest, int component, int i)
1799 {
1800   uint8_t *dest = _dest;
1801   uint8_t *src;
1802   SchroFrame *srcframe = frame->virt_frame1;
1803 
1804   src = schro_virt_frame_get_line (frame->virt_frame1, component,
1805       MIN (i, srcframe->components[component].height - 1));
1806   orc_memcpy (dest, src, srcframe->components[component].width);
1807   orc_splat_u8_ns (dest + srcframe->components[component].width,
1808       dest[srcframe->components[component].width - 1],
1809       frame->components[component].width -
1810       srcframe->components[component].width);
1811 }
1812 
1813 static void
edge_extend_s16(SchroFrame * frame,void * _dest,int component,int i)1814 edge_extend_s16 (SchroFrame * frame, void *_dest, int component, int i)
1815 {
1816   int16_t *dest = _dest;
1817   int16_t *src;
1818   SchroFrame *srcframe = frame->virt_frame1;
1819 
1820   src = schro_virt_frame_get_line (frame->virt_frame1, component,
1821       MIN (i, srcframe->components[component].height - 1));
1822   orc_memcpy (dest, src,
1823       srcframe->components[component].width * sizeof (int16_t));
1824   orc_splat_s16_ns (dest + srcframe->components[component].width,
1825       dest[srcframe->components[component].width - 1],
1826       frame->components[component].width -
1827       srcframe->components[component].width);
1828 }
1829 
1830 static void
edge_extend_s32(SchroFrame * frame,void * _dest,int component,int i)1831 edge_extend_s32 (SchroFrame * frame, void *_dest, int component, int i)
1832 {
1833   int32_t *dest = _dest;
1834   int32_t *src;
1835   SchroFrame *srcframe = frame->virt_frame1;
1836 
1837   src = schro_virt_frame_get_line (frame->virt_frame1, component,
1838       MIN (i, srcframe->components[component].height - 1));
1839   orc_memcpy (dest, src,
1840       srcframe->components[component].width * sizeof (int32_t));
1841   orc_splat_s32_ns (dest + srcframe->components[component].width,
1842       dest[srcframe->components[component].width - 1],
1843       frame->components[component].width -
1844       srcframe->components[component].width);
1845 }
1846 
1847 SchroFrame *
schro_virt_frame_new_edgeextend(SchroFrame * vf,int width,int height)1848 schro_virt_frame_new_edgeextend (SchroFrame * vf, int width, int height)
1849 {
1850   SchroFrame *virt_frame;
1851 
1852   if (width == vf->width && height == vf->height)
1853     return vf;
1854 
1855   SCHRO_ASSERT (width >= vf->width);
1856   SCHRO_ASSERT (height >= vf->height);
1857 
1858   virt_frame = schro_frame_new_virtual (NULL, vf->format, width, height);
1859   virt_frame->virt_frame1 = vf;
1860   switch (SCHRO_FRAME_FORMAT_DEPTH (vf->format)) {
1861     case SCHRO_FRAME_FORMAT_DEPTH_U8:
1862       virt_frame->render_line = edge_extend_u8;
1863       break;
1864     case SCHRO_FRAME_FORMAT_DEPTH_S16:
1865       virt_frame->render_line = edge_extend_s16;
1866       break;
1867     case SCHRO_FRAME_FORMAT_DEPTH_S32:
1868       virt_frame->render_line = edge_extend_s32;
1869       break;
1870     default:
1871       SCHRO_ASSERT (0);
1872       break;
1873   }
1874 
1875   return virt_frame;
1876 }
1877