9 #include "bcsynchronous.h"
10 #include "bctexture.h"
11 #include "bcwindowbase.h"
13 #include "colormodels.h"
19 static void png_read_function(png_structp png_ptr,
23 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
24 if(frame->image_size - frame->image_offset < length)
25 length = frame->image_size - frame->image_offset;
27 memcpy(data, &frame->image[frame->image_offset], length);
28 frame->image_offset += length;
38 //static BCCounter counter;
41 VFrame::VFrame(unsigned char *png_data)
48 VFrame::VFrame(VFrame &frame)
52 allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
53 memcpy(data, frame.data, bytes_per_line * h);
57 VFrame::VFrame(unsigned char *data,
65 allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
68 VFrame::VFrame(unsigned char *data,
93 this->color_model = BC_COMPRESSED;
109 // Delete effect stack
110 prev_effects.remove_all_objects();
111 next_effects.remove_all_objects();
115 int VFrame::equivalent(VFrame *src, int test_stacks)
117 return (src->get_color_model() == get_color_model() &&
118 src->get_w() == get_w() &&
119 src->get_h() == get_h() &&
120 src->bytes_per_line == bytes_per_line &&
121 (!test_stacks || equal_stacks(src)));
124 long VFrame::set_shm_offset(long offset)
130 long VFrame::get_shm_offset()
135 int VFrame::get_shared()
140 int VFrame::params_match(int w, int h, int color_model)
142 return (this->w == w &&
144 this->color_model == color_model);
148 int VFrame::reset_parameters(int do_opengl)
157 compressed_allocated = 0;
158 compressed_size = 0; // Size of current image
165 sequence_number = -1;
170 // By default, anything is going to be done in RAM
171 opengl_state = VFrame::RAM;
176 prev_effects.set_array_delete();
177 next_effects.set_array_delete();
181 int VFrame::clear_objects(int do_opengl)
198 //int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
199 //if(size > 2560 * 1920)
201 if(data) delete [] data;
205 // Delete row pointers
221 int VFrame::get_field2_offset()
223 return field2_offset;
226 int VFrame::set_field2_offset(int value)
228 this->field2_offset = value;
232 void VFrame::set_keyframe(int value)
234 this->is_keyframe = value;
237 int VFrame::get_keyframe()
243 int VFrame::calculate_bytes_per_pixel(int color_model)
245 return cmodel_calculate_pixelsize(color_model);
248 long VFrame::get_bytes_per_line()
250 return bytes_per_line;
253 long VFrame::get_data_size()
255 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
256 // return h * bytes_per_line;
259 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
261 return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
265 void VFrame::create_row_pointers()
274 this->u_offset = w * h;
275 this->v_offset = w * h + w * h / 4;
277 y = this->data + this->y_offset;
278 u = this->data + this->u_offset;
279 v = this->data + this->v_offset;
286 this->u_offset = w * h;
287 this->v_offset = w * h + w * h / 2;
289 y = this->data + this->y_offset;
290 u = this->data + this->u_offset;
291 v = this->data + this->v_offset;
295 rows = new unsigned char*[h];
296 for(int i = 0; i < h; i++)
298 rows[i] = &this->data[i * this->bytes_per_line];
304 int VFrame::allocate_data(unsigned char *data,
315 this->color_model = color_model;
316 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
317 this->y_offset = this->u_offset = this->v_offset = 0;
319 if(bytes_per_line >= 0)
321 this->bytes_per_line = bytes_per_line;
324 this->bytes_per_line = this->bytes_per_pixel * w;
326 // Allocate data + padding for MMX
331 this->y_offset = y_offset;
332 this->u_offset = u_offset;
333 this->v_offset = v_offset;
338 int size = calculate_data_size(this->w,
340 this->bytes_per_line,
342 this->data = new unsigned char[size];
345 //if(size >= 720 * 480 * 3)
346 //BUFFER2(this->data, "VFrame::allocate_data");
349 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
351 //printf("VFrame::allocate_data %p %d %d\n", this, this->w, this->h);
352 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
355 // Create row pointers
356 create_row_pointers();
360 void VFrame::set_memory(unsigned char *data,
367 this->y_offset = y_offset;
368 this->u_offset = u_offset;
369 this->v_offset = v_offset;
370 y = this->data + this->y_offset;
371 u = this->data + this->u_offset;
372 v = this->data + this->v_offset;
373 create_row_pointers();
376 void VFrame::set_compressed_memory(unsigned char *data,
383 this->compressed_allocated = data_allocated;
384 this->compressed_size = data_size;
388 // Reallocate uncompressed buffer with or without alpha
389 int VFrame::reallocate(unsigned char *data,
411 int VFrame::allocate_compressed_data(long bytes)
413 if(bytes < 1) return 1;
415 // Want to preserve original contents
416 if(data && compressed_allocated < bytes)
418 unsigned char *new_data = new unsigned char[bytes];
419 bcopy(data, new_data, compressed_allocated);
423 compressed_allocated = bytes;
428 data = new unsigned char[bytes];
429 compressed_allocated = bytes;
436 int VFrame::read_png(unsigned char *data)
438 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
439 png_infop info_ptr = png_create_info_struct(png_ptr);
444 image_size = (((unsigned long)data[0]) << 24) |
445 (((unsigned long)data[1]) << 16) |
446 (((unsigned long)data[2]) << 8) |
447 (unsigned char)data[3];
448 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
449 png_read_info(png_ptr, info_ptr);
451 w = png_get_image_width(png_ptr, info_ptr);
452 h = png_get_image_height(png_ptr, info_ptr);
454 int src_color_model = png_get_color_type(png_ptr, info_ptr);
455 switch(src_color_model)
457 case PNG_COLOR_TYPE_RGB:
458 new_color_model = BC_RGB888;
462 case PNG_COLOR_TYPE_GRAY_ALPHA:
463 case PNG_COLOR_TYPE_RGB_ALPHA:
465 new_color_model = BC_RGBA8888;
478 png_read_image(png_ptr, get_rows());
482 if(src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
484 for(int i = 0; i < get_h(); i++)
486 unsigned char *row = get_rows()[i];
487 unsigned char *out_ptr = row + get_w() * 4 - 4;
488 unsigned char *in_ptr = row + get_w() * 2 - 2;
490 for(int j = get_w() - 1; j >= 0; j--)
492 out_ptr[0] = in_ptr[0];
493 out_ptr[1] = in_ptr[0];
494 out_ptr[2] = in_ptr[0];
495 out_ptr[3] = in_ptr[1];
502 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
506 unsigned char* VFrame::get_data()
511 long VFrame::get_compressed_allocated()
513 return compressed_allocated;
516 long VFrame::get_compressed_size()
518 return compressed_size;
521 long VFrame::set_compressed_size(long size)
523 compressed_size = size;
527 int VFrame::get_color_model()
533 int VFrame::equals(VFrame *frame)
535 if(frame->data == data)
541 #define ZERO_YUV(components, type, max) \
543 for(int i = 0; i < h; i++) \
545 type *row = (type*)get_rows()[i]; \
546 for(int j = 0; j < w; j++) \
548 row[j * components] = 0; \
549 row[j * components + 1] = (max + 1) / 2; \
550 row[j * components + 2] = (max + 1) / 2; \
551 if(components == 4) row[j * components + 3] = 0; \
556 int VFrame::clear_frame()
564 bzero(data, h * w * 2);
568 ZERO_YUV(3, unsigned char, 0xff);
572 ZERO_YUV(4, unsigned char, 0xff);
576 ZERO_YUV(3, uint16_t, 0xffff);
579 case BC_YUVA16161616:
580 ZERO_YUV(4, uint16_t, 0xffff);
584 bzero(data, h * bytes_per_line);
590 void VFrame::rotate90()
592 // Allocate new frame
593 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
594 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
595 unsigned char **new_rows = new unsigned char*[new_h];
596 for(int i = 0; i < new_h; i++)
597 new_rows[i] = &new_data[new_bytes_per_line * i];
600 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
602 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
604 for(int k = 0; k < bytes_per_pixel; k++)
606 new_rows[out_y][out_x * bytes_per_pixel + k] =
607 rows[in_y][in_x * bytes_per_pixel + k];
616 bytes_per_line = new_bytes_per_line;
621 void VFrame::rotate270()
623 // Allocate new frame
624 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
625 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
626 unsigned char **new_rows = new unsigned char*[new_h];
627 for(int i = 0; i < new_h; i++)
628 new_rows[i] = &new_data[new_bytes_per_line * i];
631 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
633 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
635 for(int k = 0; k < bytes_per_pixel; k++)
637 new_rows[out_y][out_x * bytes_per_pixel + k] =
638 rows[in_y][in_x * bytes_per_pixel + k];
647 bytes_per_line = new_bytes_per_line;
652 void VFrame::flip_vert()
654 unsigned char *temp = new unsigned char[bytes_per_line];
655 for(int i = 0, j = h - 1; i < j; i++, j--)
657 memcpy(temp, rows[j], bytes_per_line);
658 memcpy(rows[j], rows[i], bytes_per_line);
659 memcpy(rows[i], temp, bytes_per_line);
666 int VFrame::copy_from(VFrame *frame)
668 int w = MIN(this->w, frame->get_w());
669 int h = MIN(this->h, frame->get_h());
672 switch(frame->color_model)
675 allocate_compressed_data(frame->compressed_size);
676 memcpy(data, frame->data, frame->compressed_size);
677 this->compressed_size = frame->compressed_size;
681 //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());
682 memcpy(get_y(), frame->get_y(), w * h);
683 memcpy(get_u(), frame->get_u(), w * h / 4);
684 memcpy(get_v(), frame->get_v(), w * h / 4);
688 //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());
689 memcpy(get_y(), frame->get_y(), w * h);
690 memcpy(get_u(), frame->get_u(), w * h / 2);
691 memcpy(get_v(), frame->get_v(), w * h / 2);
695 // printf("VFrame::copy_from %d\n", calculate_data_size(w,
698 // frame->color_model));
699 memcpy(data, frame->data, calculate_data_size(w,
702 frame->color_model));
710 #define OVERLAY(type, max, components) \
712 type **in_rows = (type**)src->get_rows(); \
713 type **out_rows = (type**)get_rows(); \
714 int in_w = src->get_w(); \
715 int in_h = src->get_h(); \
717 for(int i = 0; i < in_h; i++) \
719 if(i + out_y1 >= 0 && i + out_y1 < h) \
721 type *src_row = in_rows[i]; \
722 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
724 for(int j = 0; j < in_w; j++) \
726 if(j + out_x1 >= 0 && j + out_x1 < w) \
728 int opacity = src_row[3]; \
729 int transparency = max - src_row[3]; \
730 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
731 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
732 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
733 dst_row[3] = MAX(dst_row[3], src_row[3]); \
736 dst_row += components; \
737 src_row += components; \
744 void VFrame::overlay(VFrame *src,
748 switch(get_color_model())
751 OVERLAY(unsigned char, 0xff, 4);
758 int VFrame::get_scale_tables(int *column_table, int *row_table,
759 int in_x1, int in_y1, int in_x2, int in_y2,
760 int out_x1, int out_y1, int out_x2, int out_y2)
763 float w_in = in_x2 - in_x1;
764 float h_in = in_y2 - in_y1;
765 int w_out = out_x2 - out_x1;
766 int h_out = out_y2 - out_y1;
768 float hscale = w_in / w_out;
769 float vscale = h_in / h_out;
771 for(i = 0; i < w_out; i++)
773 column_table[i] = (int)(hscale * i);
776 for(i = 0; i < h_out; i++)
778 row_table[i] = (int)(vscale * i) + in_y1;
783 int VFrame::get_bytes_per_pixel()
785 return bytes_per_pixel;
788 unsigned char** VFrame::get_rows()
807 int VFrame::get_w_fixed()
812 int VFrame::get_h_fixed()
817 unsigned char* VFrame::get_y()
822 unsigned char* VFrame::get_u()
827 unsigned char* VFrame::get_v()
832 void VFrame::set_number(long number)
834 sequence_number = number;
837 long VFrame::get_number()
839 return sequence_number;
842 void VFrame::push_prev_effect(char *name)
845 prev_effects.append(ptr = new char[strlen(name) + 1]);
847 if(prev_effects.total > MAX_STACK_ELEMENTS) prev_effects.remove_object(0);
850 void VFrame::pop_prev_effect()
852 if(prev_effects.total)
853 prev_effects.remove_object(prev_effects.last());
856 void VFrame::push_next_effect(char *name)
859 next_effects.append(ptr = new char[strlen(name) + 1]);
861 if(next_effects.total > MAX_STACK_ELEMENTS) next_effects.remove_object(0);
864 void VFrame::pop_next_effect()
866 if(next_effects.total)
867 next_effects.remove_object(next_effects.last());
870 char* VFrame::get_next_effect(int number)
872 if(!next_effects.total) return "";
874 if(number > next_effects.total - 1) number = next_effects.total - 1;
876 return next_effects.values[next_effects.total - number - 1];
879 char* VFrame::get_prev_effect(int number)
881 if(!prev_effects.total) return "";
883 if(number > prev_effects.total - 1) number = prev_effects.total - 1;
885 return prev_effects.values[prev_effects.total - number - 1];
888 BC_Hash* VFrame::get_params()
893 void VFrame::clear_stacks()
895 next_effects.remove_all_objects();
896 prev_effects.remove_all_objects();
898 params = new BC_Hash;
901 void VFrame::copy_params(VFrame *src)
903 params->copy_from(src->params);
906 void VFrame::copy_stacks(VFrame *src)
910 for(int i = 0; i < src->next_effects.total; i++)
913 next_effects.append(ptr = new char[strlen(src->next_effects.values[i]) + 1]);
914 strcpy(ptr, src->next_effects.values[i]);
916 for(int i = 0; i < src->prev_effects.total; i++)
919 prev_effects.append(ptr = new char[strlen(src->prev_effects.values[i]) + 1]);
920 strcpy(ptr, src->prev_effects.values[i]);
923 params->copy_from(src->params);
926 int VFrame::equal_stacks(VFrame *src)
928 for(int i = 0; i < src->next_effects.total && i < next_effects.total; i++)
930 if(strcmp(src->next_effects.values[i], next_effects.values[i])) return 0;
932 for(int i = 0; i < src->prev_effects.total && i < prev_effects.total; i++)
934 if(strcmp(src->prev_effects.values[i], prev_effects.values[i])) return 0;
936 if(!params->equivalent(src->params)) return 0;
940 void VFrame::dump_stacks()
942 printf("VFrame::dump_stacks\n");
943 printf(" next_effects:\n");
944 for(int i = next_effects.total - 1; i >= 0; i--)
945 printf(" %s\n", next_effects.values[i]);
946 printf(" prev_effects:\n");
947 for(int i = prev_effects.total - 1; i >= 0; i--)
948 printf(" %s\n", prev_effects.values[i]);
951 void VFrame::dump_params()
961 // c-file-style: "linux"