1 /*****************************************************************
2  * gavl - a general purpose audio/video processing library
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <gavl.h>
23 
24 #include <video.h>
25 #include <config.h>
26 #include <accel.h>
27 
28 #define DO_ROUND
29 #include "c/colorspace_tables.h"
30 #include "c/colorspace_macros.h"
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 /* Taken from a52dec (thanks guys) */
37 
38 #ifdef HAVE_MEMALIGN
39 /* some systems have memalign() but no declaration for it */
40 void * memalign (size_t align, size_t size);
41 #else
42 /* assume malloc alignment is sufficient */
43 #define memalign(align,size) malloc (size)
44 #endif
45 
46 #define ALIGNMENT_BYTES 16
47 #define ALIGN(a) a=((a+ALIGNMENT_BYTES-1)/ALIGNMENT_BYTES)*ALIGNMENT_BYTES
48 
video_frame_alloc(gavl_video_frame_t * ret,const gavl_video_format_t * format,int align)49 static void video_frame_alloc(gavl_video_frame_t * ret,
50                               const gavl_video_format_t * format, int align)
51   {
52   int planar;
53 
54   if(format->pixelformat == GAVL_PIXELFORMAT_NONE)
55     {
56     fprintf(stderr, "Pixelformat not specified for video frame\n");
57     return;
58     }
59   planar = gavl_pixelformat_is_planar(format->pixelformat);
60 
61   if(planar)
62     {
63     int sub_h;
64     int sub_v;
65     int bpc;
66 
67     gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
68 
69     bpc = gavl_pixelformat_bytes_per_component(format->pixelformat);
70 
71     if(!ret->strides[0])
72       {
73       ret->strides[0] = bpc * format->frame_width;
74       ret->strides[1] = bpc * ((format->frame_width + sub_h - 1) / sub_h);
75       ret->strides[2] = ret->strides[1];
76 
77       if(align)
78         {
79         ALIGN(ret->strides[0]);
80         ALIGN(ret->strides[1]);
81         ALIGN(ret->strides[2]);
82         }
83       }
84 
85     ret->planes[0] = memalign(ALIGNMENT_BYTES,
86                               ret->strides[0]*format->frame_height+
87                               ret->strides[1]*((format->frame_height+sub_v-1)/sub_v)+
88                               ret->strides[2]*((format->frame_height+sub_v-1)/sub_v));
89     ret->planes[1] = ret->planes[0] + ret->strides[0]*format->frame_height;
90     ret->planes[2] = ret->planes[1] + ret->strides[1]*((format->frame_height+sub_v-1)/sub_v);
91     }
92   else // Packed
93     {
94     if(!ret->strides[0])
95       {
96       ret->strides[0] =
97         format->frame_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
98       if(align)
99         ALIGN(ret->strides[0]);
100       }
101     ret->planes[0] = memalign(ALIGNMENT_BYTES,
102                               ret->strides[0] * format->frame_height);
103     }
104   }
105 
video_frame_free(gavl_video_frame_t * frame)106 static void video_frame_free(gavl_video_frame_t * frame)
107   {
108   if(frame->planes[0])
109     free(frame->planes[0]);
110   frame->planes[0] = NULL;
111   }
112 
gavl_video_frame_create(const gavl_video_format_t * format)113 gavl_video_frame_t * gavl_video_frame_create(const gavl_video_format_t * format)
114   {
115   gavl_video_frame_t * ret = calloc(1, sizeof(gavl_video_frame_t));
116   if(format)
117     video_frame_alloc(ret, format, 1);
118   ret->timecode = GAVL_TIMECODE_INVALID_MASK;
119   return ret;
120   }
121 
gavl_video_frame_create_nopad(const gavl_video_format_t * format)122 gavl_video_frame_t * gavl_video_frame_create_nopad(const gavl_video_format_t * format)
123   {
124   gavl_video_frame_t * ret = calloc(1, sizeof(gavl_video_frame_t));
125   if(format)
126     video_frame_alloc(ret, format, 0);
127   ret->timecode = GAVL_TIMECODE_INVALID_MASK;
128   return ret;
129   }
130 
131 
gavl_video_frame_destroy(gavl_video_frame_t * frame)132 void gavl_video_frame_destroy(gavl_video_frame_t * frame)
133   {
134   video_frame_free(frame);
135   free(frame);
136   }
137 
gavl_video_frame_null(gavl_video_frame_t * frame)138 void gavl_video_frame_null(gavl_video_frame_t* frame)
139   {
140   frame->planes[0] = NULL;
141   }
142 
gavl_video_frame_clear_mask(gavl_video_frame_t * frame,const gavl_video_format_t * format,int mask)143 void gavl_video_frame_clear_mask(gavl_video_frame_t * frame,
144                                  const gavl_video_format_t * format, int mask)
145   {
146   int i, j;
147   uint16_t * ptr_16;
148   uint16_t * ptr_16_u;
149   uint16_t * ptr_16_v;
150   float * ptr_float;
151   uint8_t * line_start;
152   uint8_t * line_start_u;
153   uint8_t * line_start_v;
154   int bytes;
155 
156   switch(format->pixelformat)
157     {
158     case GAVL_RGB_15:
159     case GAVL_BGR_15:
160     case GAVL_RGB_16:
161     case GAVL_BGR_16:
162     case GAVL_RGB_24:
163     case GAVL_BGR_24:
164     case GAVL_RGB_32:
165     case GAVL_BGR_32:
166     case GAVL_RGB_48:
167     case GAVL_RGB_FLOAT:
168     case GAVL_GRAY_8:
169     case GAVL_GRAY_16:
170     case GAVL_GRAY_FLOAT:
171     case GAVL_YUV_FLOAT:
172       if(mask & CLEAR_MASK_PLANE_0)
173         {
174         bytes = format->frame_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
175         for(i = 0; i < format->frame_height; i++)
176           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
177         }
178       break;
179     case GAVL_RGBA_32:
180       if(!(mask & CLEAR_MASK_PLANE_0))
181         break;
182       for(i = 0; i < format->frame_height; i++)
183         {
184         for(j = 0; j < format->frame_width; j++)
185           {
186           frame->planes[0][4*j + i*frame->strides[0]]   = 0x00; /* R */
187           frame->planes[0][4*j + i*frame->strides[0]+1] = 0x00; /* G */
188           frame->planes[0][4*j + i*frame->strides[0]+2] = 0x00; /* B */
189           frame->planes[0][4*j + i*frame->strides[0]+3] = 0xFF; /* A */
190           }
191         }
192       break;
193     case GAVL_GRAYA_16:
194       if(!(mask & CLEAR_MASK_PLANE_0))
195         break;
196       for(i = 0; i < format->frame_height; i++)
197         {
198         for(j = 0; j < format->frame_width; j++)
199           {
200           frame->planes[0][2*j + i*frame->strides[0]]   = 0x00; /* Gray */
201           frame->planes[0][2*j + i*frame->strides[0]+1] = 0xFF; /* A    */
202           }
203         }
204       break;
205     case GAVL_YUVA_32:
206       if(!(mask & CLEAR_MASK_PLANE_0))
207         break;
208       for(i = 0; i < format->frame_height; i++)
209         {
210         for(j = 0; j < format->frame_width; j++)
211           {
212           frame->planes[0][4*j + i*frame->strides[0]]   = 0x00; /* Y */
213           frame->planes[0][4*j + i*frame->strides[0]+1] = 0x80; /* U */
214           frame->planes[0][4*j + i*frame->strides[0]+2] = 0x80; /* V */
215           frame->planes[0][4*j + i*frame->strides[0]+3] = 0xEB; /* A */
216           }
217         }
218       break;
219     case GAVL_RGBA_64:
220       if(!(mask & CLEAR_MASK_PLANE_0))
221         break;
222 
223       line_start = frame->planes[0];
224 
225       for(i = 0; i < format->frame_height; i++)
226         {
227         ptr_16 = (uint16_t*)line_start;
228         for(j = 0; j < format->frame_width; j++)
229           {
230           *(ptr_16++) = 0x0000;
231           *(ptr_16++) = 0x0000;
232           *(ptr_16++) = 0x0000;
233           *(ptr_16++) = 0xFFFF;
234           }
235         line_start += frame->strides[0];
236         }
237 
238       break;
239     case GAVL_GRAYA_32:
240       if(!(mask & CLEAR_MASK_PLANE_0))
241         break;
242 
243       line_start = frame->planes[0];
244 
245       for(i = 0; i < format->frame_height; i++)
246         {
247         ptr_16 = (uint16_t*)line_start;
248         for(j = 0; j < format->frame_width; j++)
249           {
250           *(ptr_16++) = 0x0000;
251           *(ptr_16++) = 0xFFFF;
252           }
253         line_start += frame->strides[0];
254         }
255 
256       break;
257     case GAVL_YUVA_64:
258       if(!(mask & CLEAR_MASK_PLANE_0))
259         break;
260 
261       line_start = frame->planes[0];
262 
263       for(i = 0; i < format->frame_height; i++)
264         {
265         ptr_16 = (uint16_t*)line_start;
266         for(j = 0; j < format->frame_width; j++)
267           {
268           *(ptr_16++) = 0x0000;
269           *(ptr_16++) = 0x8000;
270           *(ptr_16++) = 0x8000;
271           *(ptr_16++) = 0xFFFF;
272           }
273         line_start += frame->strides[0];
274         }
275 
276       break;
277     case GAVL_RGBA_FLOAT:
278     case GAVL_YUVA_FLOAT:
279       if(!(mask & CLEAR_MASK_PLANE_0))
280         break;
281       line_start = frame->planes[0];
282 
283       for(i = 0; i < format->frame_height; i++)
284         {
285         ptr_float = (float*)line_start;
286         for(j = 0; j < format->frame_width; j++)
287           {
288           *(ptr_float++) = 0.0;
289           *(ptr_float++) = 0.0;
290           *(ptr_float++) = 0.0;
291           *(ptr_float++) = 1.0;
292           }
293         line_start += frame->strides[0];
294         }
295       break;
296     case GAVL_GRAYA_FLOAT:
297       if(!(mask & CLEAR_MASK_PLANE_0))
298         break;
299       line_start = frame->planes[0];
300 
301       for(i = 0; i < format->frame_height; i++)
302         {
303         ptr_float = (float*)line_start;
304         for(j = 0; j < format->frame_width; j++)
305           {
306           *(ptr_float++) = 0.0;
307           *(ptr_float++) = 1.0;
308           }
309         line_start += frame->strides[0];
310         }
311       break;
312     case GAVL_YUY2:
313       if(!(mask & CLEAR_MASK_PLANE_0))
314         break;
315       for(i = 0; i < format->frame_height; i++)
316         {
317         for(j = 0; j < format->frame_width; j++)
318           {
319           frame->planes[0][2*j + i*frame->strides[0]]   = 0x00; /* Y   */
320           frame->planes[0][2*j + i*frame->strides[0]+1] = 0x80; /* U/V */
321           }
322         }
323       break;
324     case GAVL_UYVY:
325       if(!(mask & CLEAR_MASK_PLANE_0))
326         break;
327       for(i = 0; i < format->frame_height; i++)
328         {
329         for(j = 0; j < format->frame_width; j++)
330           {
331           frame->planes[0][2*j + i*frame->strides[0]+1] = 0x00; /* Y */
332           frame->planes[0][2*j + i*frame->strides[0]]   = 0x80; /* U/V   */
333           }
334         }
335       break;
336     case GAVL_YUV_444_P_16:
337       if(mask & CLEAR_MASK_PLANE_0)
338         {
339         bytes = format->frame_width * 2;
340         for(i = 0; i < format->frame_height; i++)
341           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
342         }
343 
344       if(!(mask & (CLEAR_MASK_PLANE_1 | CLEAR_MASK_PLANE_2)))
345         break;
346 
347       line_start_u = frame->planes[1];
348       line_start_v = frame->planes[2];
349       for(i = 0; i < format->frame_height; i++)
350         {
351         ptr_16_u = (uint16_t*)line_start_u;
352         ptr_16_v = (uint16_t*)line_start_v;
353 
354         if(mask & CLEAR_MASK_PLANE_1)
355           {
356           for(j = 0; j < format->frame_width; j++)
357             {
358             *(ptr_16_u++) = 0x8000;
359             }
360           }
361 
362         if(mask & CLEAR_MASK_PLANE_2)
363           {
364           for(j = 0; j < format->frame_width; j++)
365             {
366             *(ptr_16_v++) = 0x8000;
367             }
368           }
369 
370         line_start_u += frame->strides[1];
371         line_start_v += frame->strides[2];
372         }
373       break;
374     case GAVL_YUV_422_P_16:
375       if(mask & CLEAR_MASK_PLANE_0)
376         {
377         bytes = format->frame_width * 2;
378         for(i = 0; i < format->frame_height; i++)
379           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
380         }
381 
382       if(!(mask & (CLEAR_MASK_PLANE_1 | CLEAR_MASK_PLANE_2)))
383         break;
384 
385       line_start_u = frame->planes[1];
386       line_start_v = frame->planes[2];
387       for(i = 0; i < format->frame_height; i++)
388         {
389         ptr_16_u = (uint16_t*)line_start_u;
390         ptr_16_v = (uint16_t*)line_start_v;
391 
392         if(mask & CLEAR_MASK_PLANE_1)
393           {
394           for(j = 0; j < format->frame_width/2; j++)
395             {
396             *(ptr_16_u++) = 0x8000;
397             }
398           }
399         if(mask & CLEAR_MASK_PLANE_2)
400           {
401           for(j = 0; j < format->frame_width/2; j++)
402             {
403             *(ptr_16_v++) = 0x8000;
404             }
405           }
406 
407         line_start_u += frame->strides[1];
408         line_start_v += frame->strides[2];
409         }
410       break;
411     case GAVL_YUV_420_P:
412     case GAVL_YUVJ_420_P:
413       if(mask & CLEAR_MASK_PLANE_0)
414         {
415         bytes = format->frame_width;
416         for(i = 0; i < format->frame_height; i++)
417           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
418         }
419       if(mask & CLEAR_MASK_PLANE_1)
420         {
421         bytes = format->frame_width / 2;
422         for(i = 0; i < format->frame_height / 2; i++)
423           memset(frame->planes[1] + i * frame->strides[1], 0x80, bytes);
424         }
425       if(mask & CLEAR_MASK_PLANE_2)
426         {
427         bytes = format->frame_width / 2;
428         for(i = 0; i < format->frame_height / 2; i++)
429           memset(frame->planes[2] + i * frame->strides[2], 0x80, bytes);
430         }
431       break;
432     case GAVL_YUV_410_P:
433       if(mask & CLEAR_MASK_PLANE_0)
434         {
435         bytes = format->frame_width;
436         for(i = 0; i < format->frame_height; i++)
437           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
438         }
439       if(mask & CLEAR_MASK_PLANE_1)
440         {
441         bytes = format->frame_width / 4;
442         for(i = 0; i < format->frame_height / 4; i++)
443           memset(frame->planes[1] + i * frame->strides[1], 0x80, bytes);
444         }
445       if(mask & CLEAR_MASK_PLANE_2)
446         {
447         bytes = format->frame_width / 4;
448         for(i = 0; i < format->frame_height / 4; i++)
449           memset(frame->planes[2] + i * frame->strides[2], 0x80, bytes);
450         }
451       break;
452     case GAVL_YUV_411_P:
453       if(mask & CLEAR_MASK_PLANE_0)
454         {
455         bytes = format->frame_width;
456         for(i = 0; i < format->frame_height; i++)
457           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
458         }
459       if(mask & CLEAR_MASK_PLANE_1)
460         {
461         bytes = format->frame_width / 4;
462         for(i = 0; i < format->frame_height; i++)
463           memset(frame->planes[1] + i * frame->strides[1], 0x80, bytes);
464         }
465       if(mask & CLEAR_MASK_PLANE_2)
466         {
467         bytes = format->frame_width / 4;
468         for(i = 0; i < format->frame_height; i++)
469           memset(frame->planes[2] + i * frame->strides[2], 0x80, bytes);
470         }
471       break;
472     case GAVL_YUV_422_P:
473     case GAVL_YUVJ_422_P:
474       if(mask & CLEAR_MASK_PLANE_0)
475         {
476         bytes = format->frame_width;
477         for(i = 0; i < format->frame_height; i++)
478           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
479         }
480       if(mask & CLEAR_MASK_PLANE_1)
481         {
482         bytes = format->frame_width / 2;
483         for(i = 0; i < format->frame_height; i++)
484           memset(frame->planes[1] + i * frame->strides[1], 0x80, bytes);
485         }
486       if(mask & CLEAR_MASK_PLANE_2)
487         {
488         bytes = format->frame_width / 2;
489         for(i = 0; i < format->frame_height; i++)
490           memset(frame->planes[2] + i * frame->strides[2], 0x80, bytes);
491         }
492       break;
493     case GAVL_YUV_444_P:
494     case GAVL_YUVJ_444_P:
495       if(mask & CLEAR_MASK_PLANE_0)
496         {
497         bytes = format->frame_width;
498         for(i = 0; i < format->frame_height; i++)
499           memset(frame->planes[0] + i * frame->strides[0], 0x00, bytes);
500         }
501       if(mask & CLEAR_MASK_PLANE_1)
502         {
503         bytes = format->frame_width;
504         for(i = 0; i < format->frame_height; i++)
505           memset(frame->planes[1] + i * frame->strides[1], 0x80, bytes);
506         }
507       if(mask & CLEAR_MASK_PLANE_2)
508         {
509         bytes = format->frame_width;
510         for(i = 0; i < format->frame_height; i++)
511           memset(frame->planes[2] + i * frame->strides[2], 0x80, bytes);
512         }
513       break;
514     case GAVL_PIXELFORMAT_NONE:
515       break;
516     }
517   }
518 
519 
gavl_video_frame_clear(gavl_video_frame_t * frame,const gavl_video_format_t * format)520 void gavl_video_frame_clear(gavl_video_frame_t * frame,
521                             const gavl_video_format_t * format)
522   {
523   gavl_video_frame_clear_mask(frame, format, CLEAR_MASK_ALL);
524   }
525 
copy_plane(gavl_video_frame_t * dst,const gavl_video_frame_t * src,int plane,int bytes_per_line,int height)526 static void copy_plane(gavl_video_frame_t * dst,
527                        const gavl_video_frame_t * src, int plane,
528                        int bytes_per_line, int height)
529   {
530   int j;
531   uint8_t * sp, *dp;
532   sp = src->planes[plane];
533   dp = dst->planes[plane];
534 
535   if((src->strides[plane] == dst->strides[plane]) &&
536      (src->strides[plane] == bytes_per_line))
537     gavl_memcpy(dp, sp, bytes_per_line * height);
538   else
539     {
540     for(j = 0; j < height; j++)
541       {
542       gavl_memcpy(dp, sp, bytes_per_line);
543       sp += src->strides[plane];
544       dp += dst->strides[plane];
545       }
546     }
547   }
548 
gavl_video_frame_copy_plane(const gavl_video_format_t * format,gavl_video_frame_t * dst,const gavl_video_frame_t * src,int plane)549 void gavl_video_frame_copy_plane(const gavl_video_format_t * format,
550                                  gavl_video_frame_t * dst,
551                                  const gavl_video_frame_t * src, int plane)
552   {
553   int bytes_per_line;
554   int sub_h, sub_v;
555   int height = format->image_height;
556   gavl_init_memcpy();
557   sub_h = 1;
558   sub_v = 1;
559 
560   bytes_per_line = gavl_pixelformat_is_planar(format->pixelformat) ?
561     format->image_width * gavl_pixelformat_bytes_per_component(format->pixelformat) :
562     format->image_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
563 
564   if(plane > 0)
565     {
566     gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
567     bytes_per_line /= sub_h;
568     height /= sub_v;
569     }
570   copy_plane(dst, src, plane, bytes_per_line, height);
571   }
572 
gavl_video_frame_copy(const gavl_video_format_t * format,gavl_video_frame_t * dst,const gavl_video_frame_t * src)573 void gavl_video_frame_copy(const gavl_video_format_t * format,
574                            gavl_video_frame_t * dst,
575                            const gavl_video_frame_t * src)
576   {
577   int i;
578   int height;
579   int bytes_per_line;
580   int sub_h, sub_v;
581   int planes;
582   gavl_init_memcpy();
583 #if 0
584   fprintf(stderr, "gavl_video_frame_copy, %d %d format:\n",
585           src->strides[0], dst->strides[0]);
586   gavl_video_format_dump(format);
587 #endif
588   planes = gavl_pixelformat_num_planes(format->pixelformat);
589   height = format->image_height;
590 
591   bytes_per_line = gavl_pixelformat_is_planar(format->pixelformat) ?
592     format->image_width * gavl_pixelformat_bytes_per_component(format->pixelformat) :
593     format->image_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
594 
595   for(i = 0; i < planes; i++)
596     {
597     if(i == 1)
598       {
599       gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
600       bytes_per_line /= sub_h;
601       height /= sub_v;
602       }
603     copy_plane(dst, src, i, bytes_per_line, height);
604     }
605 
606   }
607 
608 
609 
flip_scanline_1(uint8_t * dst,uint8_t * src,int len)610 static void flip_scanline_1(uint8_t * dst, uint8_t * src, int len)
611   {
612   int i;
613   dst += (len-1);
614 
615   for(i = 0; i < len; i++)
616     {
617     *dst = *src;
618     dst--;
619     src++;
620     }
621   }
622 
flip_scanline_2(uint8_t * dst,uint8_t * src,int len)623 static void flip_scanline_2(uint8_t * dst, uint8_t * src, int len)
624   {
625   int i;
626   dst += 2*(len-1);
627 
628   for(i = 0; i < len; i++)
629     {
630     dst[0] = src[0];
631     dst[1] = src[1];
632 
633     dst-=2;
634     src+=2;
635     }
636 
637   }
638 
flip_scanline_yuy2(uint8_t * dst,uint8_t * src,int len)639 static void flip_scanline_yuy2(uint8_t * dst, uint8_t * src, int len)
640   {
641   int i;
642   dst += 2*(len-1)-2;
643 
644   for(i = 0; i < len/2; i++)
645     {
646     dst[0] = src[2]; /* Y */
647     dst[1] = src[1]; /* U */
648     dst[2] = src[0]; /* Y */
649     dst[3] = src[3]; /* U */
650 
651     dst-=4;
652     src+=4;
653     }
654 
655   }
656 
flip_scanline_uyvy(uint8_t * dst,uint8_t * src,int len)657 static void flip_scanline_uyvy(uint8_t * dst, uint8_t * src, int len)
658   {
659   int i;
660   dst += 2*(len-1)-2;
661 
662   for(i = 0; i < len/2; i++)
663     {
664     dst[0] = src[0]; /* U */
665     dst[1] = src[3]; /* Y */
666     dst[2] = src[2]; /* V */
667     dst[3] = src[1]; /* Y */
668 
669     dst-=4;
670     src+=4;
671     }
672 
673   }
674 
675 
flip_scanline_3(uint8_t * dst,uint8_t * src,int len)676 static void flip_scanline_3(uint8_t * dst, uint8_t * src, int len)
677   {
678   int i;
679   dst += 3*(len-1);
680 
681   for(i = 0; i < len; i++)
682     {
683     dst[0] = src[0];
684     dst[1] = src[1];
685     dst[2] = src[2];
686 
687     dst-=3;
688     src+=3;
689     }
690 
691   }
692 
flip_scanline_4(uint8_t * dst,uint8_t * src,int len)693 static void flip_scanline_4(uint8_t * dst, uint8_t * src, int len)
694   {
695   int i;
696   dst += 4*(len-1);
697 
698   for(i = 0; i < len; i++)
699     {
700     dst[0] = src[0];
701     dst[1] = src[1];
702     dst[2] = src[2];
703     dst[3] = src[3];
704 
705     dst-=4;
706     src+=4;
707     }
708 
709   }
710 
flip_scanline_6(uint8_t * dst,uint8_t * src,int len)711 static void flip_scanline_6(uint8_t * dst, uint8_t * src, int len)
712   {
713   int i;
714   dst += 6*(len-1);
715 
716   for(i = 0; i < len; i++)
717     {
718     dst[0] = src[0];
719     dst[1] = src[1];
720     dst[2] = src[2];
721     dst[3] = src[3];
722     dst[4] = src[4];
723     dst[5] = src[5];
724 
725     dst-=6;
726     src+=6;
727     }
728 
729   }
730 
flip_scanline_8(uint8_t * dst,uint8_t * src,int len)731 static void flip_scanline_8(uint8_t * dst, uint8_t * src, int len)
732   {
733   int i;
734   dst += 8*(len-1);
735 
736   for(i = 0; i < len; i++)
737     {
738     dst[0] = src[0];
739     dst[1] = src[1];
740     dst[2] = src[2];
741     dst[3] = src[3];
742     dst[4] = src[4];
743     dst[5] = src[5];
744     dst[6] = src[6];
745     dst[7] = src[7];
746 
747     dst-=8;
748     src+=8;
749     }
750 
751   }
752 
flip_scanline_12(uint8_t * dst,uint8_t * src,int len)753 static void flip_scanline_12(uint8_t * dst, uint8_t * src, int len)
754   {
755   int i;
756   dst += 12*(len-1);
757 
758   for(i = 0; i < len; i++)
759     {
760     gavl_memcpy(dst, src, 12);
761 
762     dst-=12;
763     src+=12;
764     }
765 
766   }
767 
flip_scanline_16(uint8_t * dst,uint8_t * src,int len)768 static void flip_scanline_16(uint8_t * dst, uint8_t * src, int len)
769   {
770   int i;
771   dst += 16*(len-1);
772 
773   for(i = 0; i < len; i++)
774     {
775     gavl_memcpy(dst, src, 16);
776 
777     dst-=16;
778     src+=16;
779     }
780   }
781 
782 
783 
784 typedef void (*flip_scanline_func)(uint8_t * dst, uint8_t * src, int len);
785 
find_flip_scanline_func(gavl_pixelformat_t csp)786 static flip_scanline_func find_flip_scanline_func(gavl_pixelformat_t csp)
787   {
788   switch(csp)
789     {
790     case GAVL_RGB_15:
791     case GAVL_BGR_15:
792     case GAVL_RGB_16:
793     case GAVL_BGR_16:
794     case GAVL_YUV_444_P_16:
795     case GAVL_YUV_422_P_16:
796     case GAVL_GRAYA_16:
797     case GAVL_GRAY_16:
798       return flip_scanline_2;
799       break;
800     case GAVL_RGB_24:
801     case GAVL_BGR_24:
802       return flip_scanline_3;
803       break;
804     case GAVL_RGB_32:
805     case GAVL_BGR_32:
806     case GAVL_RGBA_32:
807     case GAVL_YUVA_32:
808     case GAVL_GRAYA_32:
809     case GAVL_GRAY_FLOAT:
810       return flip_scanline_4;
811       break;
812     case GAVL_RGB_48:
813       return flip_scanline_6;
814       break;
815     case GAVL_RGBA_64:
816     case GAVL_YUVA_64:
817     case GAVL_GRAYA_FLOAT:
818       return flip_scanline_8;
819       break;
820     case GAVL_RGB_FLOAT:
821     case GAVL_YUV_FLOAT:
822       return flip_scanline_12;
823       break;
824     case GAVL_RGBA_FLOAT:
825     case GAVL_YUVA_FLOAT:
826       return flip_scanline_16;
827       break;
828     case GAVL_YUV_420_P:
829     case GAVL_YUV_410_P:
830     case GAVL_YUV_422_P:
831     case GAVL_YUV_411_P:
832     case GAVL_YUV_444_P:
833     case GAVL_YUVJ_420_P:
834     case GAVL_YUVJ_422_P:
835     case GAVL_YUVJ_444_P:
836     case GAVL_GRAY_8:
837       return flip_scanline_1;
838       break;
839     case GAVL_YUY2:
840       return flip_scanline_yuy2;
841       break;
842     case GAVL_UYVY:
843       return flip_scanline_uyvy;
844       break;
845     case GAVL_PIXELFORMAT_NONE:
846       break;
847     }
848   return NULL;
849   }
850 
gavl_video_frame_copy_flip_x(const gavl_video_format_t * format,gavl_video_frame_t * dst,const gavl_video_frame_t * src)851 void gavl_video_frame_copy_flip_x(const gavl_video_format_t * format,
852                                   gavl_video_frame_t * dst,
853                                   const gavl_video_frame_t * src)
854   {
855   uint8_t * src_ptr;
856   uint8_t * dst_ptr;
857 
858   int i, j, jmax, width;
859   int sub_h, sub_v;
860   int planes;
861   flip_scanline_func func;
862 
863   planes = gavl_pixelformat_num_planes(format->pixelformat);
864   func = find_flip_scanline_func(format->pixelformat);
865 
866   sub_h = 1;
867   sub_v = 1;
868 
869   jmax = format->image_height;
870   width = format->image_width;
871 
872   gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
873 
874   for(i = 0; i < planes; i++)
875     {
876     src_ptr = src->planes[i];
877     dst_ptr = dst->planes[i];
878 
879     for(j = 0; j < jmax; j++)
880       {
881       func(dst_ptr, src_ptr, width);
882 
883       src_ptr += src->strides[i];
884       dst_ptr += dst->strides[i];
885       }
886     if(!i)
887       {
888       jmax /= sub_v;
889       width /= sub_h;
890       }
891     }
892 
893   }
894 
gavl_video_frame_copy_flip_y(const gavl_video_format_t * format,gavl_video_frame_t * dst,const gavl_video_frame_t * src)895 void gavl_video_frame_copy_flip_y(const gavl_video_format_t * format,
896                                   gavl_video_frame_t * dst,
897                                   const gavl_video_frame_t * src)
898   {
899   uint8_t * src_ptr;
900   uint8_t * dst_ptr;
901 
902   int i, j;
903   int sub_h, sub_v;
904   int planes;
905   int bytes_per_line;
906   gavl_init_memcpy();
907   planes = gavl_pixelformat_num_planes(format->pixelformat);
908 
909   sub_h = 1;
910   sub_v = 1;
911 
912   for(i = 0; i < planes; i++)
913     {
914     if(i)
915       gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
916 
917     src_ptr = src->planes[i] +
918       ((format->image_height / sub_v) - 1) * src->strides[i];
919 
920     dst_ptr = dst->planes[i];
921 
922     bytes_per_line =
923       dst->strides[i] < src->strides[i] ?
924       dst->strides[i] : src->strides[i];
925 
926     for(j = 0; j < format->image_height / sub_v; j++)
927       {
928       gavl_memcpy(dst_ptr, src_ptr, bytes_per_line);
929 
930       src_ptr -= src->strides[i];
931       dst_ptr += dst->strides[i];
932       }
933     }
934 
935   }
936 
gavl_video_frame_copy_flip_xy(const gavl_video_format_t * format,gavl_video_frame_t * dst,const gavl_video_frame_t * src)937 void gavl_video_frame_copy_flip_xy(const gavl_video_format_t * format,
938                                    gavl_video_frame_t * dst,
939                                    const gavl_video_frame_t * src)
940   {
941   uint8_t * src_ptr;
942   uint8_t * dst_ptr;
943 
944   int i, j;
945   int sub_h, sub_v;
946   int planes;
947   flip_scanline_func func;
948 
949   planes = gavl_pixelformat_num_planes(format->pixelformat);
950   func = find_flip_scanline_func(format->pixelformat);
951 
952   sub_h = 1;
953   sub_v = 1;
954 
955   for(i = 0; i < planes; i++)
956     {
957     if(i)
958       gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
959 
960     src_ptr = src->planes[i] +
961       ((format->image_height / sub_v) - 1) * src->strides[i];
962 
963     dst_ptr = dst->planes[i];
964 
965     for(j = 0; j < format->image_height / sub_v; j++)
966       {
967       func(dst_ptr, src_ptr, format->image_width / sub_h);
968 
969       src_ptr -= src->strides[i];
970       dst_ptr += dst->strides[i];
971       }
972     }
973 
974   }
975 
976 
977 
gavl_video_frame_dump(gavl_video_frame_t * frame,const gavl_video_format_t * format,const char * namebase)978 void gavl_video_frame_dump(gavl_video_frame_t * frame,
979                            const gavl_video_format_t * format,
980                            const char * namebase)
981   {
982   char * filename;
983   int baselen;
984   int sub_h, sub_v;
985   int planes;
986   int i, j;
987 
988   FILE * output;
989 
990   planes = gavl_pixelformat_num_planes(format->pixelformat);
991 
992   baselen = strlen(namebase);
993 
994   filename = malloc(baselen + 4);
995   strcpy(filename, namebase);
996 
997   sub_h = 1;
998   sub_v = 1;
999 
1000   for(i = 0; i < planes; i++)
1001     {
1002     filename[baselen]   = '.';
1003     filename[baselen+1] = 'p';
1004     filename[baselen+2] = i + 1 + '0';
1005     filename[baselen+3] = '\0';
1006 
1007     output = fopen(filename, "wb");
1008 
1009     if(i == 1)
1010       gavl_pixelformat_chroma_sub(format->pixelformat,
1011                           &sub_h, &sub_v);
1012 
1013     for(j = 0; j < format->image_height / sub_v; j++)
1014       {
1015       fwrite(frame->planes[i] + j*frame->strides[i], 1,  format->image_width / sub_h,
1016              output);
1017       }
1018     fclose(output);
1019     }
1020   free(filename);
1021   }
1022 
gavl_video_frame_get_subframe(gavl_pixelformat_t pixelformat,const gavl_video_frame_t * src,gavl_video_frame_t * dst,gavl_rectangle_i_t * src_rect)1023 void gavl_video_frame_get_subframe(gavl_pixelformat_t pixelformat,
1024                                    const gavl_video_frame_t * src,
1025                                    gavl_video_frame_t * dst,
1026                                    gavl_rectangle_i_t * src_rect)
1027   {
1028   int uv_sub_h, uv_sub_v;
1029   int i;
1030   int bytes;
1031   int num_planes = gavl_pixelformat_num_planes(pixelformat);
1032 
1033   dst->strides[0] = src->strides[0];
1034 
1035   if(num_planes > 1)
1036     {
1037     gavl_pixelformat_chroma_sub(pixelformat, &uv_sub_h,
1038                                &uv_sub_v);
1039     bytes = gavl_pixelformat_bytes_per_component(pixelformat);
1040     dst->planes[0] = src->planes[0] + src_rect->y * src->strides[0] + src_rect->x * bytes;
1041 
1042     for(i = 1; i < num_planes; i++)
1043       {
1044       dst->planes[i] = src->planes[i] + (src_rect->y/uv_sub_v) * src->strides[i] + (src_rect->x/uv_sub_h) * bytes;
1045       dst->strides[i] = src->strides[i];
1046       }
1047     }
1048   else
1049     {
1050     if(((pixelformat == GAVL_YUY2) || (pixelformat == GAVL_UYVY)) &&
1051        (src_rect->x & 1))
1052       src_rect->x--;
1053     bytes = gavl_pixelformat_bytes_per_pixel(pixelformat);
1054     dst->planes[0] = src->planes[0] + src_rect->y * src->strides[0] + src_rect->x * bytes;
1055     }
1056   }
1057 
gavl_video_frame_get_field(gavl_pixelformat_t pixelformat,const gavl_video_frame_t * src,gavl_video_frame_t * dst,int field)1058 void gavl_video_frame_get_field(gavl_pixelformat_t pixelformat,
1059                                 const gavl_video_frame_t * src,
1060                                 gavl_video_frame_t * dst,
1061                                 int field)
1062   {
1063   int i, num_planes;
1064   num_planes = gavl_pixelformat_num_planes(pixelformat);
1065   for(i = 0; i < num_planes; i++)
1066     {
1067     dst->planes[i] = src->planes[i] + field * src->strides[i];
1068     dst->strides[i] = src->strides[i] * 2;
1069     }
1070   }
1071 
1072 #define FILL_FUNC_HEAD_PACKED(TYPE) \
1073   uint8_t * dst_start; \
1074   TYPE * dst; \
1075   int i, j; \
1076   dst_start = frame->planes[0]; \
1077   for(i = 0; i < format->image_height; i++) \
1078     { \
1079     dst = (TYPE*)dst_start; \
1080     for(j = 0; j < format->image_width; j++) \
1081       {
1082 
1083 #define FILL_FUNC_HEAD_PACKED_422(TYPE) \
1084   uint8_t * dst_start;          \
1085   TYPE * dst;                   \
1086   int i, j, jmax;               \
1087   jmax = format->image_width / 2; \
1088   dst_start = frame->planes[0]; \
1089   for(i = 0; i < format->image_height; i++) \
1090     { \
1091     dst = (TYPE*)dst_start; \
1092     for(j = 0; j < jmax; j++) \
1093       {
1094 
1095 
1096 #define FILL_FUNC_TAIL_PACKED(ADVANCE)             \
1097       dst+=ADVANCE;                                \
1098       }                                            \
1099     dst_start += frame->strides[0];                 \
1100     }
1101 
fill_8_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,uint8_t color)1102 static void fill_8_packed(gavl_video_frame_t * frame,
1103                           const gavl_video_format_t * format,
1104                           uint8_t color)
1105   {
1106   FILL_FUNC_HEAD_PACKED(uint8_t);
1107   *dst = color;
1108   FILL_FUNC_TAIL_PACKED(1);
1109   }
1110 
fill_16_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,uint16_t color)1111 static void fill_16_packed(gavl_video_frame_t * frame,
1112                            const gavl_video_format_t * format,
1113                            uint16_t color)
1114   {
1115   FILL_FUNC_HEAD_PACKED(uint16_t);
1116   *dst = color;
1117   FILL_FUNC_TAIL_PACKED(1);
1118   }
1119 
fill_24_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,const uint8_t * color)1120 static void fill_24_packed(gavl_video_frame_t * frame,
1121                            const gavl_video_format_t * format,
1122                            const uint8_t * color)
1123   {
1124   FILL_FUNC_HEAD_PACKED(uint8_t);
1125   dst[0] = color[0];
1126   dst[1] = color[1];
1127   dst[2] = color[2];
1128   FILL_FUNC_TAIL_PACKED(3);
1129   }
1130 
fill_32_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,const uint8_t * _color)1131 static void fill_32_packed(gavl_video_frame_t * frame,
1132                            const gavl_video_format_t * format,
1133                            const uint8_t * _color)
1134   {
1135   uint32_t * color = (uint32_t*)_color;
1136   FILL_FUNC_HEAD_PACKED(uint32_t);
1137   *dst = *color;
1138   FILL_FUNC_TAIL_PACKED(1);
1139   }
1140 
fill_32_packed_422(gavl_video_frame_t * frame,const gavl_video_format_t * format,const uint8_t * _color)1141 static void fill_32_packed_422(gavl_video_frame_t * frame,
1142                                const gavl_video_format_t * format,
1143                                const uint8_t * _color)
1144   {
1145   uint32_t * color = (uint32_t*)_color;
1146   FILL_FUNC_HEAD_PACKED_422(uint32_t);
1147   *dst = *color;
1148   FILL_FUNC_TAIL_PACKED(1);
1149   }
1150 
1151 
fill_48_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,const uint16_t * color)1152 static void fill_48_packed(gavl_video_frame_t * frame,
1153                            const gavl_video_format_t * format,
1154                            const uint16_t * color)
1155   {
1156   FILL_FUNC_HEAD_PACKED(uint16_t);
1157   gavl_memcpy(dst, color, 3*sizeof(*dst));
1158   FILL_FUNC_TAIL_PACKED(3);
1159   }
1160 
fill_64_packed(gavl_video_frame_t * frame,const gavl_video_format_t * format,const uint16_t * color)1161 static void fill_64_packed(gavl_video_frame_t * frame,
1162                            const gavl_video_format_t * format,
1163                            const uint16_t * color)
1164   {
1165   FILL_FUNC_HEAD_PACKED(uint16_t);
1166   gavl_memcpy(dst, color, 4*sizeof(*dst));
1167   FILL_FUNC_TAIL_PACKED(4);
1168   }
1169 
fill_float_gray(gavl_video_frame_t * frame,const gavl_video_format_t * format,const float * color)1170 static void fill_float_gray(gavl_video_frame_t * frame,
1171                            const gavl_video_format_t * format,
1172                            const float * color)
1173   {
1174   FILL_FUNC_HEAD_PACKED(float);
1175   gavl_memcpy(dst, color, sizeof(*dst));
1176   FILL_FUNC_TAIL_PACKED(1);
1177   }
1178 
fill_float_graya(gavl_video_frame_t * frame,const gavl_video_format_t * format,const float * color)1179 static void fill_float_graya(gavl_video_frame_t * frame,
1180                            const gavl_video_format_t * format,
1181                            const float * color)
1182   {
1183   FILL_FUNC_HEAD_PACKED(float);
1184   gavl_memcpy(dst, color, 2*sizeof(*dst));
1185   FILL_FUNC_TAIL_PACKED(2);
1186   }
1187 
fill_float_rgb(gavl_video_frame_t * frame,const gavl_video_format_t * format,const float * color)1188 static void fill_float_rgb(gavl_video_frame_t * frame,
1189                            const gavl_video_format_t * format,
1190                            const float * color)
1191   {
1192   FILL_FUNC_HEAD_PACKED(float);
1193   gavl_memcpy(dst, color, 3*sizeof(*dst));
1194   FILL_FUNC_TAIL_PACKED(3);
1195   }
1196 
fill_float_rgba(gavl_video_frame_t * frame,const gavl_video_format_t * format,const float * color)1197 static void fill_float_rgba(gavl_video_frame_t * frame,
1198                             const gavl_video_format_t * format,
1199                             const float * color)
1200   {
1201   FILL_FUNC_HEAD_PACKED(float);
1202   gavl_memcpy(dst, color, 4*sizeof(*dst));
1203   FILL_FUNC_TAIL_PACKED(4);
1204   }
1205 
1206 #define FILL_FUNC_HEAD_PLANAR(TYPE) \
1207   uint8_t * dst_start; \
1208   TYPE * dst; \
1209   int i, j; \
1210   dst_start = frame->planes[0]; \
1211   for(i = 0; i < format->image_height; i++) \
1212     { \
1213     dst = (TYPE*)dst_start; \
1214     for(j = 0; j < format->image_width; j++) \
1215       {
1216 
1217 #define FILL_FUNC_TAIL_PLANAR(ADVANCE)             \
1218       dst+=ADVANCE;                                \
1219       }                                            \
1220     dst_start += frame->strides[0];                 \
1221     }
1222 
1223 
fill_planar_8(gavl_video_frame_t * frame,const gavl_video_format_t * format,uint8_t * color)1224 static void fill_planar_8(gavl_video_frame_t * frame,
1225                           const gavl_video_format_t * format,
1226                           uint8_t * color)
1227   {
1228   int i, imax;
1229   int sub_h, sub_v;
1230 
1231   uint8_t * dst, *dst_1;
1232 
1233   gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
1234 
1235   /* Luminance */
1236   dst = frame->planes[0];
1237   for(i = 0; i < format->image_height; i++)
1238     {
1239     memset(dst, color[0], format->image_width);
1240     dst += frame->strides[0];
1241     }
1242   /* Chrominance */
1243 
1244   dst   = frame->planes[1];
1245   dst_1 = frame->planes[2];
1246 
1247   imax = format->image_height / sub_v;
1248 
1249   for(i = 0; i < imax; i++)
1250     {
1251     memset(dst,   color[1], format->image_width/sub_h);
1252     memset(dst_1, color[2], format->image_width/sub_h);
1253     dst   += frame->strides[1];
1254     dst_1 += frame->strides[2];
1255     }
1256   }
1257 
fill_planar_16(gavl_video_frame_t * frame,const gavl_video_format_t * format,uint16_t * color)1258 static void fill_planar_16(gavl_video_frame_t * frame,
1259                            const gavl_video_format_t * format,
1260                            uint16_t * color)
1261   {
1262   int i, j, imax, jmax;
1263   int sub_h, sub_v;
1264 
1265   uint16_t * dst, *dst_1;
1266   uint8_t * dst_start, *dst_start_1;
1267 
1268   gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
1269 
1270   /* Luminance */
1271   dst_start = frame->planes[0];
1272   for(i = 0; i < format->image_height; i++)
1273     {
1274     dst = (uint16_t*)dst_start;
1275 
1276     for(j = 0; j < format->image_width; j++)
1277       {
1278       *dst = color[0];
1279       dst++;
1280       }
1281     dst_start += frame->strides[0];
1282     }
1283   /* Chrominance */
1284 
1285   imax = format->image_height / sub_v;
1286   jmax = format->image_width  / sub_h;
1287 
1288   dst_start   = frame->planes[1];
1289   dst_start_1 = frame->planes[2];
1290 
1291   for(i = 0; i < imax; i++)
1292     {
1293     dst = (uint16_t*)dst_start;
1294     dst_1 = (uint16_t*)dst_start_1;
1295 
1296     for(j = 0; j < jmax; j++)
1297       {
1298       *dst = color[1];
1299       *dst_1 = color[2];
1300       dst++;
1301       dst_1++;
1302       }
1303     dst_start   += frame->strides[1];
1304     dst_start_1 += frame->strides[2];
1305     }
1306 
1307 
1308 
1309   }
1310 
1311 
gavl_video_frame_fill(gavl_video_frame_t * frame,const gavl_video_format_t * format,const float * color)1312 void gavl_video_frame_fill(gavl_video_frame_t * frame,
1313                            const gavl_video_format_t * format,
1314                            const float * color)
1315   {
1316   INIT_RGB_FLOAT_TO_YUV
1317   uint16_t packed_16;
1318   uint8_t  packed_32[4];
1319   uint16_t packed_64[4];
1320   float color_float[4];
1321 
1322   gavl_init_memcpy();
1323 
1324   switch(format->pixelformat)
1325     {
1326     case GAVL_GRAY_8:
1327       RGB_FLOAT_TO_YUVJ_8(color[0], color[1], color[2], packed_32[0],
1328                           packed_32[1], packed_32[2]);
1329       fill_8_packed(frame, format, packed_32[0]);
1330       break;
1331     case GAVL_GRAYA_16:
1332       RGB_FLOAT_TO_YUVJ_8(color[0], color[1], color[2], packed_32[0],
1333                           packed_32[1], packed_32[2]);
1334       /* This overwrites packed_32[1] from the lone before */
1335       RGB_FLOAT_TO_8(color[3], packed_32[1]);
1336 #ifndef WORDS_BIGENDIAN
1337       packed_16 = (packed_32[1] << 8) | packed_32[0];
1338 #else
1339       packed_16 = (packed_32[0] << 8) | packed_32[1];
1340 #endif
1341       fill_16_packed(frame, format, packed_16);
1342       break;
1343     case GAVL_GRAY_16:
1344       RGB_FLOAT_TO_YJ_16(color[0], color[1], color[2], packed_16);
1345       fill_16_packed(frame, format, packed_16);
1346       break;
1347     case GAVL_GRAYA_32:
1348       RGB_FLOAT_TO_YJ_16(color[0], color[1], color[2], packed_64[0]);
1349       RGB_FLOAT_TO_16(color[3], packed_64[1]);
1350 #ifndef WORDS_BIGENDIAN
1351       packed_32[0] = packed_64[0] & 0xff;
1352       packed_32[1] = packed_64[0] >> 8;
1353       packed_32[2] = packed_64[1] & 0xff;
1354       packed_32[3] = packed_64[1] >> 8;
1355 #else
1356       packed_32[1] = packed_64[0] & 0xff;
1357       packed_32[0] = packed_64[0] >> 8;
1358       packed_32[3] = packed_64[1] & 0xff;
1359       packed_32[2] = packed_64[1] >> 8;
1360 #endif
1361       fill_32_packed(frame, format, packed_32);
1362       break;
1363     case GAVL_RGB_15:
1364       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1365       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1366       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1367       PACK_8_TO_RGB15(packed_32[0],packed_32[1],packed_32[2],packed_16);
1368       fill_16_packed(frame, format, packed_16);
1369       break;
1370     case GAVL_BGR_15:
1371       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1372       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1373       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1374       PACK_8_TO_BGR15(packed_32[0],packed_32[1],packed_32[2],packed_16);
1375       fill_16_packed(frame, format, packed_16);
1376       break;
1377     case GAVL_RGB_16:
1378       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1379       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1380       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1381       PACK_8_TO_RGB16(packed_32[0],packed_32[1],packed_32[2],packed_16);
1382       fill_16_packed(frame, format, packed_16);
1383       break;
1384     case GAVL_BGR_16:
1385       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1386       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1387       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1388       PACK_8_TO_BGR16(packed_32[0],packed_32[1],packed_32[2],packed_16);
1389       fill_16_packed(frame, format, packed_16);
1390       break;
1391     case GAVL_RGB_24:
1392       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1393       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1394       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1395       fill_24_packed(frame, format, packed_32);
1396       break;
1397     case GAVL_BGR_24:
1398       RGB_FLOAT_TO_8(color[0], packed_32[2]);
1399       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1400       RGB_FLOAT_TO_8(color[2], packed_32[0]);
1401       fill_24_packed(frame, format, packed_32);
1402       break;
1403     case GAVL_RGB_32:
1404       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1405       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1406       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1407       fill_32_packed(frame, format, packed_32);
1408       break;
1409     case GAVL_BGR_32:
1410       RGB_FLOAT_TO_8(color[0], packed_32[2]);
1411       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1412       RGB_FLOAT_TO_8(color[2], packed_32[0]);
1413       fill_32_packed(frame, format, packed_32);
1414       break;
1415     case GAVL_YUVA_32:
1416       RGB_FLOAT_TO_YUV_8(color[0], color[1], color[2],
1417                          packed_32[0], packed_32[1], packed_32[2]);
1418       RGB_FLOAT_TO_8(color[3], packed_32[3]);
1419       fill_32_packed(frame, format, packed_32);
1420       break;
1421     case GAVL_RGBA_32:
1422       RGB_FLOAT_TO_8(color[0], packed_32[0]);
1423       RGB_FLOAT_TO_8(color[1], packed_32[1]);
1424       RGB_FLOAT_TO_8(color[2], packed_32[2]);
1425       RGB_FLOAT_TO_8(color[3], packed_32[3]);
1426       fill_32_packed(frame, format, packed_32);
1427       break;
1428     case GAVL_RGB_48:
1429       RGB_FLOAT_TO_16(color[0], packed_64[0]);
1430       RGB_FLOAT_TO_16(color[1], packed_64[1]);
1431       RGB_FLOAT_TO_16(color[2], packed_64[2]);
1432       fill_48_packed(frame, format, packed_64);
1433       break;
1434     case GAVL_RGBA_64:
1435       RGB_FLOAT_TO_16(color[0], packed_64[0]);
1436       RGB_FLOAT_TO_16(color[1], packed_64[1]);
1437       RGB_FLOAT_TO_16(color[2], packed_64[2]);
1438       RGB_FLOAT_TO_16(color[3], packed_64[3]);
1439       fill_64_packed(frame, format, packed_64);
1440       break;
1441     case GAVL_YUVA_64:
1442       RGB_FLOAT_TO_YUV_16(color[0], color[1], color[2], packed_64[0],
1443                           packed_64[1], packed_64[2]);
1444       RGB_FLOAT_TO_16(color[3], packed_64[3]);
1445       fill_64_packed(frame, format, packed_64);
1446       break;
1447     case GAVL_GRAY_FLOAT:
1448       RGB_FLOAT_TO_Y_FLOAT(color[0], color[1], color[2], color_float[0]);
1449       fill_float_gray(frame, format, color_float);
1450       break;
1451     case GAVL_GRAYA_FLOAT:
1452       RGB_FLOAT_TO_Y_FLOAT(color[0], color[1], color[2], color_float[0]);
1453       color_float[1] = color[4];
1454       fill_float_graya(frame, format, color_float);
1455       break;
1456     case GAVL_YUV_FLOAT:
1457       RGB_FLOAT_TO_YUV_FLOAT(color[0], color[1], color[2],
1458                              color_float[0], color_float[1], color_float[2]);
1459       fill_float_rgb(frame, format, color_float);
1460       break;
1461     case GAVL_YUVA_FLOAT:
1462       RGB_FLOAT_TO_YUV_FLOAT(color[0], color[1], color[2],
1463                              color_float[0], color_float[1], color_float[2]);
1464       color_float[3] = color[3];
1465       fill_float_rgba(frame, format, color);
1466       break;
1467     case GAVL_RGB_FLOAT:
1468       fill_float_rgb(frame, format, color);
1469       break;
1470     case GAVL_RGBA_FLOAT:
1471       fill_float_rgba(frame, format, color);
1472       break;
1473     case GAVL_YUY2:
1474       RGB_FLOAT_TO_YUV_8(color[0], color[1], color[2],
1475                          packed_32[0], /* Y */
1476                          packed_32[1], /* U */
1477                          packed_32[3]);/* V */
1478       packed_32[2] = packed_32[0];     /* Y */
1479       fill_32_packed_422(frame, format, packed_32);
1480       break;
1481     case GAVL_UYVY:
1482       RGB_FLOAT_TO_YUV_8(color[0], color[1], color[2],
1483                          packed_32[1], /* Y */
1484                          packed_32[0], /* U */
1485                          packed_32[2]);/* V */
1486       packed_32[3] = packed_32[1];     /* Y */
1487       fill_32_packed_422(frame, format, packed_32);
1488       break;
1489     case GAVL_YUVJ_420_P:
1490     case GAVL_YUVJ_444_P:
1491     case GAVL_YUVJ_422_P:
1492       RGB_FLOAT_TO_YUVJ_8(color[0], color[1], color[2], packed_32[0],
1493                           packed_32[1], packed_32[2]);
1494       fill_planar_8(frame, format, packed_32);
1495       break;
1496     case GAVL_YUV_444_P:
1497     case GAVL_YUV_422_P:
1498     case GAVL_YUV_420_P:
1499     case GAVL_YUV_410_P:
1500     case GAVL_YUV_411_P:
1501       RGB_FLOAT_TO_YUV_8(color[0], color[1], color[2], packed_32[0],
1502                          packed_32[1], packed_32[2]);
1503       fill_planar_8(frame, format, packed_32);
1504       break;
1505     case GAVL_YUV_422_P_16:
1506     case GAVL_YUV_444_P_16:
1507       RGB_FLOAT_TO_YUV_16(color[0], color[1], color[2], packed_64[0],
1508                           packed_64[1], packed_64[2]);
1509       fill_planar_16(frame, format, packed_64);
1510       break;
1511     case GAVL_PIXELFORMAT_NONE:
1512       fprintf(stderr, "Pixelformat not specified for video frame\n");
1513       return;
1514     }
1515   }
1516 
gavl_video_frame_copy_metadata(gavl_video_frame_t * dst,const gavl_video_frame_t * src)1517 void gavl_video_frame_copy_metadata(gavl_video_frame_t * dst,
1518                                     const gavl_video_frame_t * src)
1519   {
1520   dst->timestamp       = src->timestamp;
1521   dst->duration        = src->duration;
1522   dst->timecode        = src->timecode;
1523   dst->interlace_mode  = src->interlace_mode;
1524   }
1525 
gavl_video_frame_set_strides(gavl_video_frame_t * frame,const gavl_video_format_t * format)1526 void gavl_video_frame_set_strides(gavl_video_frame_t * frame,
1527                                   const gavl_video_format_t * format)
1528   {
1529   int i;
1530   int bytes_per_line;
1531   int sub_h, sub_v;
1532   int num_planes = gavl_pixelformat_num_planes(format->pixelformat);
1533   bytes_per_line = gavl_pixelformat_is_planar(format->pixelformat) ?
1534     format->frame_width * gavl_pixelformat_bytes_per_component(format->pixelformat) :
1535     format->frame_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
1536 
1537   gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
1538 
1539   for(i = 0; i < num_planes; i++)
1540     {
1541     frame->strides[i] = bytes_per_line;
1542     if(i)
1543       frame->strides[i] /= sub_h;
1544     }
1545   }
1546 
gavl_video_frame_set_planes(gavl_video_frame_t * frame,const gavl_video_format_t * format,uint8_t * buffer)1547 void gavl_video_frame_set_planes(gavl_video_frame_t * frame,
1548                                  const gavl_video_format_t * format,
1549                                  uint8_t * buffer)
1550   {
1551   int i;
1552   int sub_h, sub_v;
1553   int advance;
1554   int num_planes;
1555   if(!frame->strides[0])
1556     gavl_video_frame_set_strides(frame, format);
1557 
1558   if(buffer)
1559     {
1560     num_planes = gavl_pixelformat_num_planes(format->pixelformat);
1561     gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
1562 
1563     for(i = 0; i < num_planes; i++)
1564       {
1565       frame->planes[i] = buffer;
1566       advance = frame->strides[i] * format->frame_height;
1567       if(i)
1568         advance /= sub_v;
1569       buffer += advance;
1570       }
1571     }
1572   else
1573     {
1574     video_frame_alloc(frame, format, 0);
1575     }
1576 
1577   }
1578 
gavl_video_frames_equal(const gavl_video_format_t * format,const gavl_video_frame_t * f1,const gavl_video_frame_t * f2)1579 int gavl_video_frames_equal(const gavl_video_format_t * format,
1580                             const gavl_video_frame_t * f1,
1581                             const gavl_video_frame_t * f2)
1582   {
1583   int i, j;
1584   int height;
1585   int bytes_per_line;
1586   int sub_h, sub_v;
1587   int planes;
1588 
1589   planes = gavl_pixelformat_num_planes(format->pixelformat);
1590   height = format->image_height;
1591 
1592   bytes_per_line = gavl_pixelformat_is_planar(format->pixelformat) ?
1593     format->image_width * gavl_pixelformat_bytes_per_component(format->pixelformat) :
1594     format->image_width * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
1595 
1596   for(i = 0; i < planes; i++)
1597     {
1598     if(i == 1)
1599       {
1600       gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
1601       bytes_per_line /= sub_h;
1602       height /= sub_v;
1603       }
1604 
1605     for(j = 0; j < height; j++)
1606       {
1607       if(memcmp(f1->planes[i] + j * f1->strides[i],
1608                 f2->planes[i] + j * f2->strides[i], bytes_per_line))
1609         return 0;
1610       }
1611     }
1612   return 1;
1613   }
1614