r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / guicast / vframe.C
bloba75dcbf78a39f578c6f5692f4f9ad7a69f858d15
1 #include <png.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
6 //#include "bccounter.h"
7 #include "bcsignals.h"
8 #include "clip.h"
9 #include "colormodels.h"
10 #include "vframe.h"
12 class PngReadFunction
14 public:
15         static void png_read_function(png_structp png_ptr,
16                    png_bytep data, 
17                                    png_size_t length)
18         {
19                 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
20                 if(frame->image_size - frame->image_offset < length) 
21                         length = frame->image_size - frame->image_offset;
23                 memcpy(data, &frame->image[frame->image_offset], length);
24                 frame->image_offset += length;
25         };
34 //static BCCounter counter;
37 VFrame::VFrame(unsigned char *png_data)
39 //printf("VFrame::VFrame 1\n");
40         reset_parameters();
41 //printf("VFrame::VFrame 1\n");
42         read_png(png_data);
43 //printf("VFrame::VFrame 2\n");
46 VFrame::VFrame(VFrame &frame)
48         reset_parameters();
49         allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
50         memcpy(data, frame.data, bytes_per_line * h);
51 //      counter.up();
54 VFrame::VFrame(unsigned char *data, 
55         int w, 
56         int h, 
57         int color_model, 
58         long bytes_per_line)
60         reset_parameters();
61         allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
62 //      counter.up();
65 VFrame::VFrame(unsigned char *data, 
66                 long y_offset,
67                 long u_offset,
68                 long v_offset, 
69                 int w, 
70                 int h, 
71                 int color_model, 
72                 long bytes_per_line)
74         reset_parameters();
75         allocate_data(data, 
76                 y_offset, 
77                 u_offset, 
78                 v_offset, 
79                 w, 
80                 h, 
81                 color_model, 
82                 bytes_per_line);
83 //      counter.up();
86 VFrame::VFrame()
88         reset_parameters();
89         this->color_model = BC_COMPRESSED;
90 //      counter.up();
103 VFrame::~VFrame()
105         clear_objects();
106 //      counter.down();
109 int VFrame::equivalent(VFrame *src)
111         return (src->get_color_model() == get_color_model() &&
112                 src->get_w() == get_w() &&
113                 src->get_h() == get_h() &&
114                 src->bytes_per_line == bytes_per_line);
117 long VFrame::set_shm_offset(long offset)
119         shm_offset = offset;
120         return 0;
123 long VFrame::get_shm_offset()
125         return shm_offset;
128 int VFrame::params_match(int w, int h, int color_model)
130         return (this->w == w &&
131                 this->h == h &&
132                 this->color_model == color_model);
136 int VFrame::reset_parameters()
138         field2_offset = -1;
139         shared = 0;
140         shm_offset = 0;
141         bytes_per_line = 0;
142         data = 0;
143         rows = 0;
144         color_model = 0;
145         compressed_allocated = 0;
146         compressed_size = 0;   // Size of current image
147         w = 0;
148         h = 0;
149         y = u = v = 0;
150         y_offset = 0;
151         u_offset = 0;
152         v_offset = 0;
153         sequence_number = -1;
154         return 0;
157 int VFrame::clear_objects()
159 // Delete data
160 //printf("VFrame::clear_objects 1 %p %d\n", this, shared);
161         if(!shared)
162         {
163 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
164 if(size > 2560 * 1920)
165 UNBUFFER(data);
166                 if(data) delete [] data;
167                 data = 0;
168         }
170 // Delete row pointers
171         switch(color_model)
172         {
173                 case BC_COMPRESSED:
174                 case BC_YUV420P:
175                         break;
177                 default:
178                         delete [] rows;
179                         break;
180         }
182         return 0;
185 int VFrame::get_field2_offset()
187         return field2_offset;
190 int VFrame::set_field2_offset(int value)
192         this->field2_offset = value;
193         return 0;
196 int VFrame::calculate_bytes_per_pixel(int color_model)
198         return cmodel_calculate_pixelsize(color_model);
201 long VFrame::get_bytes_per_line()
203         return bytes_per_line;
206 long VFrame::get_data_size()
208         return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
209 //      return h * bytes_per_line;
212 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
214         return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
215         return 0;
218 void VFrame::create_row_pointers()
220         switch(color_model)
221         {
222                 case BC_YUV420P:
223                 case BC_YUV411P:
224                         if(!this->v_offset)
225                         {
226                                 this->y_offset = 0;
227                                 this->u_offset = w * h;
228                                 this->v_offset = w * h + w * h / 4;
229                         }
230                         y = this->data + this->y_offset;
231                         u = this->data + this->u_offset;
232                         v = this->data + this->v_offset;
233                         break;
235                 case BC_YUV422P:
236                         if(!this->v_offset)
237                         {
238                                 this->y_offset = 0;
239                                 this->u_offset = w * h;
240                                 this->v_offset = w * h + w * h / 2;
241                         }
242                         y = this->data + this->y_offset;
243                         u = this->data + this->u_offset;
244                         v = this->data + this->v_offset;
245                         break;
247                 default:
248                         rows = new unsigned char*[h];
249                         for(int i = 0; i < h; i++)
250                         {
251                                 rows[i] = &this->data[i * this->bytes_per_line];
252                         }
253                         break;
254         }
257 int VFrame::allocate_data(unsigned char *data, 
258         long y_offset,
259         long u_offset,
260         long v_offset,
261         int w, 
262         int h, 
263         int color_model, 
264         long bytes_per_line)
266         this->w = w;
267         this->h = h;
268         this->color_model = color_model;
269         this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
270         this->y_offset = this->u_offset = this->v_offset = 0;
272         if(bytes_per_line >= 0)
273         {
274                 this->bytes_per_line = bytes_per_line;
275         }
276         else
277                 this->bytes_per_line = this->bytes_per_pixel * w;
279 // Allocate data + padding for MMX
280         if(data)
281         {
282                 shared = 1;
283                 this->data = data;
284                 this->y_offset = y_offset;
285                 this->u_offset = u_offset;
286                 this->v_offset = v_offset;
287         }
288         else
289         {
290                 shared = 0;
291                 int size = calculate_data_size(this->w, 
292                         this->h, 
293                         this->bytes_per_line, 
294                         this->color_model);
295                 this->data = new unsigned char[size];
297 if(size > 2560 * 1920)
298 BUFFER(size, this->data, "VFrame::allocate_data");
300 if(!this->data)
301 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
303 //printf("VFrame::allocate_data %p %d %d\n", this, this->w, this->h);
304 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
305         }
307 // Create row pointers
308         create_row_pointers();
309         return 0;
312 void VFrame::set_memory(unsigned char *data, 
313                 long y_offset,
314                 long u_offset,
315                 long v_offset)
317         shared = 1;
318         this->data = data;
319         this->y_offset = y_offset;
320         this->u_offset = u_offset;
321         this->v_offset = v_offset;
322         y = this->data + this->y_offset;
323         u = this->data + this->u_offset;
324         v = this->data + this->v_offset;
325         create_row_pointers();
328 void VFrame::set_compressed_memory(unsigned char *data,
329         int data_size,
330         int data_allocated)
332         clear_objects();
333         shared = 1;
334         this->data = data;
335         this->compressed_allocated = data_allocated;
336         this->compressed_size = data_size;
340 // Reallocate uncompressed buffer with or without alpha
341 int VFrame::reallocate(unsigned char *data, 
342                 long y_offset,
343                 long u_offset,
344                 long v_offset,
345                 int w, 
346                 int h, 
347                 int color_model, 
348                 long bytes_per_line)
350         clear_objects();
351         reset_parameters();
352         allocate_data(data, 
353                 y_offset, 
354                 u_offset, 
355                 v_offset, 
356                 w, 
357                 h, 
358                 color_model, 
359                 bytes_per_line);
360         return 0;
363 int VFrame::allocate_compressed_data(long bytes)
365         if(bytes < 1) return 1;
367 // Want to preserve original contents
368         if(data && compressed_allocated < bytes)
369         {
370                 unsigned char *new_data = new unsigned char[bytes];
371                 bcopy(data, new_data, compressed_allocated);
372                 delete [] data;
373                 data = new_data;
374                 compressed_allocated = bytes;
375         }
376         else
377         if(!data)
378         {
379                 data = new unsigned char[bytes];
380                 compressed_allocated = bytes;
381                 compressed_size = 0;
382         }
384         return 0;
387 int VFrame::read_png(unsigned char *data)
389         png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
390         png_infop info_ptr = png_create_info_struct(png_ptr);
391         int new_color_model;
393         image_offset = 0;
394         image = data + 4;
395         image_size = (((unsigned long)data[0]) << 24) | 
396                 (((unsigned long)data[1]) << 16) | 
397                 (((unsigned long)data[2]) << 8) | 
398                 (unsigned char)data[3];
399         png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
400         png_read_info(png_ptr, info_ptr);
402         w = png_get_image_width(png_ptr, info_ptr);
403         h = png_get_image_height(png_ptr, info_ptr);
405         switch(png_get_color_type(png_ptr, info_ptr))
406         {
407                 case PNG_COLOR_TYPE_RGB:
408                         new_color_model = BC_RGB888;
409                         break;
411                 case PNG_COLOR_TYPE_RGB_ALPHA:
412                 default:
413                         new_color_model = BC_RGBA8888;
414                         break;
415         }
417         reallocate(NULL, 
418                 0, 
419                 0, 
420                 0, 
421                 w, 
422                 h, 
423                 new_color_model,
424                 -1);
426         png_read_image(png_ptr, get_rows());
427         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
428         return 0;
431 unsigned char* VFrame::get_data()
433         return data;
436 long VFrame::get_compressed_allocated()
438         return compressed_allocated;
441 long VFrame::get_compressed_size()
443         return compressed_size;
446 long VFrame::set_compressed_size(long size)
448         compressed_size = size;
449         return 0;
452 int VFrame::get_color_model()
454         return color_model;
458 int VFrame::equals(VFrame *frame)
460         if(frame->data == data) 
461                 return 1;
462         else
463                 return 0;
466 #define ZERO_YUV(components, type, max) \
467 { \
468         for(int i = 0; i < h; i++) \
469         { \
470                 type *row = (type*)get_rows()[i]; \
471                 for(int j = 0; j < w; j++) \
472                 { \
473                         row[j * components] = 0; \
474                         row[j * components + 1] = (max + 1) / 2; \
475                         row[j * components + 2] = (max + 1) / 2; \
476                         if(components == 4) row[j * components + 3] = 0; \
477                 } \
478         } \
481 int VFrame::clear_frame()
483         switch(color_model)
484         {
485                 case BC_COMPRESSED:
486                         break;
488                 case BC_YUV420P:
489                         bzero(data, h * w * 2);
490                         break;
492                 case BC_YUV888:
493                         ZERO_YUV(3, unsigned char, 0xff);
494                         break;
495                 
496                 case BC_YUVA8888:
497                         ZERO_YUV(4, unsigned char, 0xff);
498                         break;
500                 case BC_YUV161616:
501                         ZERO_YUV(3, uint16_t, 0xffff);
502                         break;
503                 
504                 case BC_YUVA16161616:
505                         ZERO_YUV(4, uint16_t, 0xffff);
506                         break;
507                 
508                 default:
509                         bzero(data, h * bytes_per_line);
510                         break;
511         }
512         return 0;
515 void VFrame::rotate90()
517 // Allocate new frame
518         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
519         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
520         unsigned char **new_rows = new unsigned char*[new_h];
521         for(int i = 0; i < new_h; i++)
522                 new_rows[i] = &new_data[new_bytes_per_line * i];
524 // Copy data
525         for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
526         {
527                 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
528                 {
529                         for(int k = 0; k < bytes_per_pixel; k++)
530                         {
531                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
532                                         rows[in_y][in_x * bytes_per_pixel + k];
533                         }
534                 }
535         }
537 // Swap frames
538         clear_objects();
539         data = new_data;
540         rows = new_rows;
541         bytes_per_line = new_bytes_per_line;
542         w = new_w;
543         h = new_h;
546 void VFrame::rotate270()
548 // Allocate new frame
549         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
550         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
551         unsigned char **new_rows = new unsigned char*[new_h];
552         for(int i = 0; i < new_h; i++)
553                 new_rows[i] = &new_data[new_bytes_per_line * i];
555 // Copy data
556         for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
557         {
558                 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
559                 {
560                         for(int k = 0; k < bytes_per_pixel; k++)
561                         {
562                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
563                                         rows[in_y][in_x * bytes_per_pixel + k];
564                         }
565                 }
566         }
568 // Swap frames
569         clear_objects();
570         data = new_data;
571         rows = new_rows;
572         bytes_per_line = new_bytes_per_line;
573         w = new_w;
574         h = new_h;
577 void VFrame::flip_vert()
579         for(int i = 0, j = h - 1; i < j; i++, j--)
580         {
581                 for(int k = 0; k < bytes_per_line; k++)
582                 {
583                         unsigned char temp = rows[j][k];
584                         rows[j][k] = rows[i][k];
585                         rows[i][k] = temp;
586                 }
587         }
592 int VFrame::copy_from(VFrame *frame)
594         int w = MIN(this->w, frame->get_w());
595         int h = MIN(this->h, frame->get_h());
596         
598         switch(frame->color_model)
599         {
600                 case BC_COMPRESSED:
601                         allocate_compressed_data(frame->compressed_size);
602                         memcpy(data, frame->data, frame->compressed_size);
603                         this->compressed_size = frame->compressed_size;
604                         break;
606                 case BC_YUV420P:
607 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
608                         memcpy(get_y(), frame->get_y(), w * h);
609                         memcpy(get_u(), frame->get_u(), w * h / 4);
610                         memcpy(get_v(), frame->get_v(), w * h / 4);
611                         break;
613                 case BC_YUV422P:
614 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
615                         memcpy(get_y(), frame->get_y(), w * h);
616                         memcpy(get_u(), frame->get_u(), w * h / 2);
617                         memcpy(get_v(), frame->get_v(), w * h / 2);
618                         break;
620                 default:
621 // printf("VFrame::copy_from %d\n", calculate_data_size(w, 
622 //                              h, 
623 //                              -1, 
624 //                              frame->color_model));
625                         memcpy(data, frame->data, calculate_data_size(w, 
626                                 h, 
627                                 -1, 
628                                 frame->color_model));
629                         break;
630         }
632         return 0;
636 #define OVERLAY(type, max, components) \
637 { \
638         type **in_rows = (type**)src->get_rows(); \
639         type **out_rows = (type**)get_rows(); \
640         int in_w = src->get_w(); \
641         int in_h = src->get_h(); \
643         for(int i = 0; i < in_h; i++) \
644         { \
645                 if(i + out_y1 >= 0 && i + out_y1 < h) \
646                 { \
647                         type *src_row = in_rows[i]; \
648                         type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
650                         for(int j = 0; j < in_w; j++) \
651                         { \
652                                 if(j + out_x1 >= 0 && j + out_x1 < w) \
653                                 { \
654                                         int opacity = src_row[3]; \
655                                         int transparency = max - src_row[3]; \
656                                         dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
657                                         dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
658                                         dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
659                                         dst_row[3] = MAX(dst_row[3], src_row[3]); \
660                                 } \
662                                 dst_row += components; \
663                                 src_row += components; \
664                         } \
665                 } \
666         } \
670 void VFrame::overlay(VFrame *src, 
671                 int out_x1, 
672                 int out_y1)
674         switch(get_color_model())
675         {
676                 case BC_RGBA8888:
677                         OVERLAY(unsigned char, 0xff, 4);
678                         break;
679         }
684 int VFrame::get_scale_tables(int *column_table, int *row_table, 
685                         int in_x1, int in_y1, int in_x2, int in_y2,
686                         int out_x1, int out_y1, int out_x2, int out_y2)
688         int y_out, i;
689         float w_in = in_x2 - in_x1;
690         float h_in = in_y2 - in_y1;
691         int w_out = out_x2 - out_x1;
692         int h_out = out_y2 - out_y1;
694         float hscale = w_in / w_out;
695         float vscale = h_in / h_out;
697         for(i = 0; i < w_out; i++)
698         {
699                 column_table[i] = (int)(hscale * i);
700         }
702         for(i = 0; i < h_out; i++)
703         {
704                 row_table[i] = (int)(vscale * i) + in_y1;
705         }
706         return 0;
709 int VFrame::get_bytes_per_pixel()
711         return bytes_per_pixel;
714 unsigned char** VFrame::get_rows()
716         if(rows)
717         {
718                 return rows;
719         }
720         return 0;
723 int VFrame::get_w()
725         return w;
728 int VFrame::get_h()
730         return h;
733 int VFrame::get_w_fixed()
735         return w - 1;
738 int VFrame::get_h_fixed()
740         return h - 1;
743 unsigned char* VFrame::get_y()
745         return y;
748 unsigned char* VFrame::get_u()
750         return u;
753 unsigned char* VFrame::get_v()
755         return v;
758 void VFrame::set_number(long number)
760         sequence_number = number;
763 long VFrame::get_number()
765         return sequence_number;