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