r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / guicast / vframe.C
blob324ab39281e6f32bf7f9d32319bc455658a4241b
1 #include <png.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
6 //#include "bccounter.h"
7 #include "clip.h"
8 #include "colormodels.h"
9 #include "vframe.h"
11 class PngReadFunction
13 public:
14         static void png_read_function(png_structp png_ptr,
15                    png_bytep data, 
16                                    png_size_t length)
17         {
18                 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
19                 if(frame->image_size - frame->image_offset < length) 
20                         length = frame->image_size - frame->image_offset;
22                 memcpy(data, &frame->image[frame->image_offset], length);
23                 frame->image_offset += length;
24         };
33 //static BCCounter counter;
36 VFrame::VFrame(unsigned char *png_data)
38 //printf("VFrame::VFrame 1\n");
39         reset_parameters();
40 //printf("VFrame::VFrame 1\n");
41         read_png(png_data);
42 //printf("VFrame::VFrame 2\n");
45 VFrame::VFrame(VFrame &frame)
47         reset_parameters();
48         allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
49         memcpy(data, frame.data, bytes_per_line * h);
50 //      counter.up();
53 VFrame::VFrame(unsigned char *data, 
54         int w, 
55         int h, 
56         int color_model, 
57         long bytes_per_line)
59         reset_parameters();
60         allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
61 //      counter.up();
64 VFrame::VFrame(unsigned char *data, 
65                 long y_offset,
66                 long u_offset,
67                 long v_offset, 
68                 int w, 
69                 int h, 
70                 int color_model, 
71                 long bytes_per_line)
73         reset_parameters();
74         allocate_data(data, 
75                 y_offset, 
76                 u_offset, 
77                 v_offset, 
78                 w, 
79                 h, 
80                 color_model, 
81                 bytes_per_line);
82 //      counter.up();
85 VFrame::VFrame()
87         reset_parameters();
88         this->color_model = BC_COMPRESSED;
89 //      counter.up();
102 VFrame::~VFrame()
104         clear_objects();
105 //      counter.down();
108 long VFrame::set_shm_offset(long offset)
110         shm_offset = offset;
111         return 0;
114 long VFrame::get_shm_offset()
116         return shm_offset;
119 int VFrame::params_match(int w, int h, int color_model)
121         return (this->w == w &&
122                 this->h == h &&
123                 this->color_model == color_model);
127 int VFrame::reset_parameters()
129         field2_offset = -1;
130         shared = 0;
131         shm_offset = 0;
132         bytes_per_line = 0;
133         data = 0;
134         rows = 0;
135         color_model = 0;
136         compressed_allocated = 0;
137         compressed_size = 0;   // Size of current image
138         w = 0;
139         h = 0;
140         y = u = v = 0;
141         y_offset = 0;
142         u_offset = 0;
143         v_offset = 0;
144         sequence_number = -1;
145         return 0;
148 int VFrame::clear_objects()
150 // Delete data
151 //printf("VFrame::clear_objects 1 %p %d\n", this, shared);
152         if(!shared)
153         {
154                 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
155 //printf("VFrame::clear_objects %p %d %d\n", this, this->w, this->h);
156 //if(size > 1000000) printf("VFrame::clear_objects %d\n", size);
157                 if(data) delete [] data;
158                 data = 0;
159         }
161 // Delete row pointers
162         switch(color_model)
163         {
164                 case BC_COMPRESSED:
165                 case BC_YUV420P:
166                         break;
168                 default:
169                         delete [] rows;
170                         break;
171         }
173         return 0;
176 int VFrame::get_field2_offset()
178         return field2_offset;
181 int VFrame::set_field2_offset(int value)
183         this->field2_offset = value;
184         return 0;
187 int VFrame::calculate_bytes_per_pixel(int color_model)
189         return cmodel_calculate_pixelsize(color_model);
192 long VFrame::get_bytes_per_line()
194         return bytes_per_line;
197 long VFrame::get_data_size()
199         return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
200 //      return h * bytes_per_line;
203 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
205         return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
206         return 0;
209 void VFrame::create_row_pointers()
211         switch(color_model)
212         {
213                 case BC_YUV420P:
214                 case BC_YUV411P:
215                         if(!this->v_offset)
216                         {
217                                 this->y_offset = 0;
218                                 this->u_offset = w * h;
219                                 this->v_offset = w * h + w * h / 4;
220                         }
221                         y = this->data + this->y_offset;
222                         u = this->data + this->u_offset;
223                         v = this->data + this->v_offset;
224                         break;
226                 case BC_YUV422P:
227                         if(!this->v_offset)
228                         {
229                                 this->y_offset = 0;
230                                 this->u_offset = w * h;
231                                 this->v_offset = w * h + w * h / 2;
232                         }
233                         y = this->data + this->y_offset;
234                         u = this->data + this->u_offset;
235                         v = this->data + this->v_offset;
236                         break;
238                 default:
239                         rows = new unsigned char*[h];
240                         for(int i = 0; i < h; i++)
241                         {
242                                 rows[i] = &this->data[i * this->bytes_per_line];
243                         }
244                         break;
245         }
248 int VFrame::allocate_data(unsigned char *data, 
249         long y_offset,
250         long u_offset,
251         long v_offset,
252         int w, 
253         int h, 
254         int color_model, 
255         long bytes_per_line)
257         this->w = w;
258         this->h = h;
259         this->color_model = color_model;
260         this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
261         this->y_offset = this->u_offset = this->v_offset = 0;
263         if(bytes_per_line >= 0)
264         {
265                 this->bytes_per_line = bytes_per_line;
266         }
267         else
268                 this->bytes_per_line = this->bytes_per_pixel * w;
270 // Allocate data + padding for MMX
271         if(data)
272         {
273                 shared = 1;
274                 this->data = data;
275                 this->y_offset = y_offset;
276                 this->u_offset = u_offset;
277                 this->v_offset = v_offset;
278         }
279         else
280         {
281                 shared = 0;
282                 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
283                 this->data = new unsigned char[size];
284 if(!this->data)
285 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
287 //printf("VFrame::allocate_data %p %d %d\n", this, this->w, this->h);
288 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
289         }
291 // Create row pointers
292         create_row_pointers();
293         return 0;
296 void VFrame::set_memory(unsigned char *data, 
297                 long y_offset,
298                 long u_offset,
299                 long v_offset)
301         shared = 1;
302         this->data = data;
303         this->y_offset = y_offset;
304         this->u_offset = u_offset;
305         this->v_offset = v_offset;
306         y = this->data + this->y_offset;
307         u = this->data + this->u_offset;
308         v = this->data + this->v_offset;
309         create_row_pointers();
312 // Reallocate uncompressed buffer with or without alpha
313 int VFrame::reallocate(unsigned char *data, 
314                 long y_offset,
315                 long u_offset,
316                 long v_offset,
317                 int w, 
318                 int h, 
319                 int color_model, 
320                 long bytes_per_line)
322         clear_objects();
323         reset_parameters();
324         allocate_data(data, y_offset, u_offset, v_offset, w, h, color_model, bytes_per_line);
325         return 0;
328 int VFrame::allocate_compressed_data(long bytes)
330         if(bytes < 1) return 1;
332 // Want to preserve original contents
333         if(data && compressed_allocated < bytes)
334         {
335 //printf("VFrame::allocate_compressed_data 1 %d\n", bytes);
336                 unsigned char *new_data = new unsigned char[bytes];
337 //printf("VFrame::allocate_compressed_data 1\n");
338                 bcopy(data, new_data, compressed_allocated);
339 //printf("VFrame::allocate_compressed_data 1\n");
340                 delete [] data;
341 //printf("VFrame::allocate_compressed_data 1\n");
342                 data = new_data;
343                 compressed_allocated = bytes;
344 //printf("VFrame::allocate_compressed_data 2\n");
345         }
346         else
347         if(!data)
348         {
349                 data = new unsigned char[bytes];
350                 compressed_allocated = bytes;
351                 compressed_size = 0;
352         }
354         return 0;
357 int VFrame::read_png(unsigned char *data)
359         png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
360         png_infop info_ptr = png_create_info_struct(png_ptr);
361         int new_color_model;
363         image_offset = 0;
364         image = data + 4;
365         image_size = (((unsigned long)data[0]) << 24) | 
366                 (((unsigned long)data[1]) << 16) | 
367                 (((unsigned long)data[2]) << 8) | 
368                 (unsigned char)data[3];
369         png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
370         png_read_info(png_ptr, info_ptr);
372         w = png_get_image_width(png_ptr, info_ptr);
373         h = png_get_image_height(png_ptr, info_ptr);
375         switch(png_get_color_type(png_ptr, info_ptr))
376         {
377                 case PNG_COLOR_TYPE_RGB:
378                         new_color_model = BC_RGB888;
379                         break;
381                 case PNG_COLOR_TYPE_RGB_ALPHA:
382                 default:
383                         new_color_model = BC_RGBA8888;
384                         break;
385         }
387         reallocate(NULL, 
388                 0, 
389                 0, 
390                 0, 
391                 w, 
392                 h, 
393                 new_color_model,
394                 -1);
396         png_read_image(png_ptr, get_rows());
397         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
398         return 0;
401 unsigned char* VFrame::get_data()
403         return data;
406 long VFrame::get_compressed_allocated()
408         return compressed_allocated;
411 long VFrame::get_compressed_size()
413         return compressed_size;
416 long VFrame::set_compressed_size(long size)
418         compressed_size = size;
419         return 0;
422 int VFrame::get_color_model()
424         return color_model;
428 int VFrame::equals(VFrame *frame)
430         if(frame->data == data) 
431                 return 1;
432         else
433                 return 0;
436 #define ZERO_YUV(components, type, max) \
437 { \
438         for(int i = 0; i < h; i++) \
439         { \
440                 type *row = (type*)get_rows()[i]; \
441                 for(int j = 0; j < w; j++) \
442                 { \
443                         row[j * components] = 0; \
444                         row[j * components + 1] = (max + 1) / 2; \
445                         row[j * components + 2] = (max + 1) / 2; \
446                         if(components == 4) row[j * components + 3] = 0; \
447                 } \
448         } \
451 int VFrame::clear_frame()
453         switch(color_model)
454         {
455                 case BC_COMPRESSED:
456                         break;
458                 case BC_YUV420P:
459                         bzero(data, h * w * 2);
460                         break;
462                 case BC_YUV888:
463                         ZERO_YUV(3, unsigned char, 0xff);
464                         break;
465                 
466                 case BC_YUVA8888:
467                         ZERO_YUV(4, unsigned char, 0xff);
468                         break;
470                 case BC_YUV161616:
471                         ZERO_YUV(3, uint16_t, 0xffff);
472                         break;
473                 
474                 case BC_YUVA16161616:
475                         ZERO_YUV(4, uint16_t, 0xffff);
476                         break;
477                 
478                 default:
479                         bzero(data, h * bytes_per_line);
480                         break;
481         }
482         return 0;
485 void VFrame::rotate90()
487 // Allocate new frame
488         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
489         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
490         unsigned char **new_rows = new unsigned char*[new_h];
491         for(int i = 0; i < new_h; i++)
492                 new_rows[i] = &new_data[new_bytes_per_line * i];
494 // Copy data
495         for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
496         {
497                 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
498                 {
499                         for(int k = 0; k < bytes_per_pixel; k++)
500                         {
501                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
502                                         rows[in_y][in_x * bytes_per_pixel + k];
503                         }
504                 }
505         }
507 // Swap frames
508         clear_objects();
509         data = new_data;
510         rows = new_rows;
511         bytes_per_line = new_bytes_per_line;
512         w = new_w;
513         h = new_h;
516 void VFrame::rotate270()
518 // Allocate new frame
519         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
520         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
521         unsigned char **new_rows = new unsigned char*[new_h];
522         for(int i = 0; i < new_h; i++)
523                 new_rows[i] = &new_data[new_bytes_per_line * i];
525 // Copy data
526         for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
527         {
528                 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
529                 {
530                         for(int k = 0; k < bytes_per_pixel; k++)
531                         {
532                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
533                                         rows[in_y][in_x * bytes_per_pixel + k];
534                         }
535                 }
536         }
538 // Swap frames
539         clear_objects();
540         data = new_data;
541         rows = new_rows;
542         bytes_per_line = new_bytes_per_line;
543         w = new_w;
544         h = new_h;
547 void VFrame::flip_vert()
549         for(int i = 0, j = h - 1; i < j; i++, j--)
550         {
551                 for(int k = 0; k < bytes_per_line; k++)
552                 {
553                         unsigned char temp = rows[j][k];
554                         rows[j][k] = rows[i][k];
555                         rows[i][k] = temp;
556                 }
557         }
561 #define APPLY_FADE(equivalent, input_rows, output_rows, max, type, chroma_zero, components) \
562 { \
563         int64_t opacity = (int64_t)(alpha * max); \
564         int64_t transparency = (int64_t)(max - opacity); \
566         for(int i = 0; i < h; i++) \
567         { \
568                 type *in_row = (type*)input_rows[i]; \
569                 type *out_row = (type*)output_rows[i]; \
571                 for(int j = 0; j < w; j++) \
572                 { \
573                         if(components == 3) \
574                         { \
575                                 out_row[j * components] =  \
576                                         (type)((int64_t)in_row[j * components] * opacity / max); \
577                                 out_row[j * components + 1] =  \
578                                         (type)(((int64_t)in_row[j * components + 1] * opacity +  \
579                                                 (int64_t)chroma_zero * transparency) / max); \
580                                 out_row[j * components + 2] =  \
581                                         (type)(((int64_t)in_row[j * components + 2] * opacity +  \
582                                                 (int64_t)chroma_zero * transparency) / max); \
583                         } \
584                         else \
585                         { \
586                                 if(!equivalent) \
587                                 { \
588                                         out_row[j * components] = in_row[j * components]; \
589                                         out_row[j * components + 1] = in_row[j * components + 1]; \
590                                         out_row[j * components + 2] = in_row[j * components + 2]; \
591                                 } \
593                                 out_row[j * components + 3] =  \
594                                         (type)((int64_t)in_row[j * components + 3] * opacity / max); \
595                         } \
596                 } \
597         } \
601 // Fade the frame but don't move data around
602 int VFrame::apply_fade(float alpha)
604 printf("VFrame::apply_fade: Never call this.  Use FadeEngine instead.\n");
605         if(alpha != 1)
606         {
607                 switch(color_model)
608                 {
609                         case BC_RGB888:
610                                 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x0, 3);
611                                 break;
612                         case BC_RGBA8888:
613                                 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x0, 4);
614                                 break;
615                         case BC_RGB161616:
616                                 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x0, 3);
617                                 break;
618                         case BC_RGBA16161616:
619                                 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x0, 4);
620                                 break;
621                         case BC_YUV888:
622                                 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x80, 3);
623                                 break;
624                         case BC_YUVA8888:
625                                 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x80, 4);
626                                 break;
627                         case BC_YUV161616:
628                                 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x8000, 3);
629                                 break;
630                         case BC_YUVA16161616:
631                                 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x8000, 4);
632                                 break;
633                 }
634         }
635         return 0;
638 // Fade the frame while moving data around
639 int VFrame::replace_from(VFrame *frame, float alpha)
641 printf("VFrame::replace_from: Never call this.  Use FadeEngine instead.\n");
642         if(alpha != 1)
643         {
644                 switch(color_model)
645                 {
646                         case BC_RGB888:
647                                 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x0, 3);
648                                 break;
649                         case BC_RGBA8888:
650                                 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x0, 4);
651                                 break;
652                         case BC_RGB161616:
653                                 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x0, 3);
654                                 break;
655                         case BC_RGBA16161616:
656                                 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x0, 4);
657                                 break;
658                         case BC_YUV888:
659                                 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x80, 3);
660                                 break;
661                         case BC_YUVA8888:
662                                 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x80, 4);
663                                 break;
664                         case BC_YUV161616:
665                                 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x8000, 3);
666                                 break;
667                         case BC_YUVA16161616:
668                                 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x8000, 4);
669                                 break;
670                 }
671         }
672         else
673                 copy_from(frame);
675         return 0;
678 int VFrame::copy_from(VFrame *frame)
680         switch(frame->color_model)
681         {
682                 case BC_COMPRESSED:
683                         allocate_compressed_data(frame->compressed_size);
684                         memcpy(data, frame->data, frame->compressed_size);
685                         this->compressed_size = frame->compressed_size;
686                         break;
688                 case BC_YUV420P:
689 //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());
690                         memcpy(get_y(), frame->get_y(), w * h);
691                         memcpy(get_u(), frame->get_u(), w * h / 4);
692                         memcpy(get_v(), frame->get_v(), w * h / 4);
693                         break;
695                 case BC_YUV422P:
696 //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());
697                         memcpy(get_y(), frame->get_y(), w * h);
698                         memcpy(get_u(), frame->get_u(), w * h / 2);
699                         memcpy(get_v(), frame->get_v(), w * h / 2);
700                         break;
702                 default:
703 // printf("VFrame::copy_from %d\n", calculate_data_size(w, 
704 //                              h, 
705 //                              -1, 
706 //                              frame->color_model));
707                         memcpy(data, frame->data, calculate_data_size(w, 
708                                 h, 
709                                 -1, 
710                                 frame->color_model));
711                         break;
712         }
714         return 0;
718 #define OVERLAY(type, max, components) \
719 { \
720         type **in_rows = (type**)src->get_rows(); \
721         type **out_rows = (type**)get_rows(); \
722         int in_w = src->get_w(); \
723         int in_h = src->get_h(); \
725         for(int i = 0; i < in_h; i++) \
726         { \
727                 if(i + out_y1 >= 0 && i + out_y1 < h) \
728                 { \
729                         type *src_row = in_rows[i]; \
730                         type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
732                         for(int j = 0; j < in_w; j++) \
733                         { \
734                                 if(j + out_x1 >= 0 && j + out_x1 < w) \
735                                 { \
736                                         int opacity = src_row[3]; \
737                                         int transparency = max - src_row[3]; \
738                                         dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
739                                         dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
740                                         dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
741                                         dst_row[3] = MAX(dst_row[3], src_row[3]); \
742                                 } \
744                                 dst_row += components; \
745                                 src_row += components; \
746                         } \
747                 } \
748         } \
752 void VFrame::overlay(VFrame *src, 
753                 int out_x1, 
754                 int out_y1)
756         switch(get_color_model())
757         {
758                 case BC_RGBA8888:
759                         OVERLAY(unsigned char, 0xff, 4);
760                         break;
761         }
766 int VFrame::get_scale_tables(int *column_table, int *row_table, 
767                         int in_x1, int in_y1, int in_x2, int in_y2,
768                         int out_x1, int out_y1, int out_x2, int out_y2)
770         int y_out, i;
771         float w_in = in_x2 - in_x1;
772         float h_in = in_y2 - in_y1;
773         int w_out = out_x2 - out_x1;
774         int h_out = out_y2 - out_y1;
776         float hscale = w_in / w_out;
777         float vscale = h_in / h_out;
779         for(i = 0; i < w_out; i++)
780         {
781                 column_table[i] = (int)(hscale * i);
782         }
784         for(i = 0; i < h_out; i++)
785         {
786                 row_table[i] = (int)(vscale * i) + in_y1;
787         }
788         return 0;
791 int VFrame::get_bytes_per_pixel()
793         return bytes_per_pixel;
796 unsigned char** VFrame::get_rows()
798         if(rows)
799         {
800                 return rows;
801         }
802         return 0;
805 int VFrame::get_w()
807         return w;
810 int VFrame::get_h()
812         return h;
815 int VFrame::get_w_fixed()
817         return w - 1;
820 int VFrame::get_h_fixed()
822         return h - 1;
825 unsigned char* VFrame::get_y()
827         return y;
830 unsigned char* VFrame::get_u()
832         return u;
835 unsigned char* VFrame::get_v()
837         return v;
840 void VFrame::set_number(long number)
842         sequence_number = number;
845 long VFrame::get_number()
847         return sequence_number;