00001 #include <png.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdint.h>
00005
00006
00007 #include "bcsignals.h"
00008 #include "clip.h"
00009 #include "colormodels.h"
00010 #include "vframe.h"
00011
00012 class PngReadFunction
00013 {
00014 public:
00015 static void png_read_function(png_structp png_ptr,
00016 png_bytep data,
00017 png_size_t length)
00018 {
00019 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
00020 if(frame->image_size - frame->image_offset < length)
00021 length = frame->image_size - frame->image_offset;
00022
00023 memcpy(data, &frame->image[frame->image_offset], length);
00024 frame->image_offset += length;
00025 };
00026 };
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 VFrame::VFrame(unsigned char *png_data)
00038 {
00039
00040 reset_parameters();
00041
00042 read_png(png_data);
00043
00044 }
00045
00046 VFrame::VFrame(const PngData& png_data)
00047 {
00048
00049 reset_parameters();
00050
00051 read_png(png_data);
00052
00053 }
00054
00055 VFrame::VFrame(VFrame &frame)
00056 {
00057 reset_parameters();
00058 allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
00059 memcpy(data, frame.data, bytes_per_line * h);
00060
00061 }
00062
00063 VFrame::VFrame(unsigned char *data,
00064 int w,
00065 int h,
00066 int color_model,
00067 long bytes_per_line)
00068 {
00069 reset_parameters();
00070 allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
00071
00072 }
00073
00074 VFrame::VFrame(unsigned char *data,
00075 long y_offset,
00076 long u_offset,
00077 long v_offset,
00078 int w,
00079 int h,
00080 int color_model,
00081 long bytes_per_line)
00082 {
00083 reset_parameters();
00084 allocate_data(data,
00085 y_offset,
00086 u_offset,
00087 v_offset,
00088 w,
00089 h,
00090 color_model,
00091 bytes_per_line);
00092
00093 }
00094
00095 VFrame::VFrame()
00096 {
00097 reset_parameters();
00098 this->color_model = BC_COMPRESSED;
00099
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 VFrame::~VFrame()
00113 {
00114 clear_objects();
00115
00116 }
00117
00118 int VFrame::equivalent(VFrame *src)
00119 {
00120 return (src->get_color_model() == get_color_model() &&
00121 src->get_w() == get_w() &&
00122 src->get_h() == get_h() &&
00123 src->bytes_per_line == bytes_per_line);
00124 }
00125
00126 long VFrame::set_shm_offset(long offset)
00127 {
00128 shm_offset = offset;
00129 return 0;
00130 }
00131
00132 long VFrame::get_shm_offset()
00133 {
00134 return shm_offset;
00135 }
00136
00137 int VFrame::params_match(int w, int h, int color_model)
00138 {
00139 return (this->w == w &&
00140 this->h == h &&
00141 this->color_model == color_model);
00142 }
00143
00144
00145 int VFrame::reset_parameters()
00146 {
00147 field2_offset = -1;
00148 shared = 0;
00149 shm_offset = 0;
00150 bytes_per_line = 0;
00151 data = 0;
00152 rows = 0;
00153 color_model = 0;
00154 compressed_allocated = 0;
00155 compressed_size = 0;
00156 w = 0;
00157 h = 0;
00158 y = u = v = 0;
00159 y_offset = 0;
00160 u_offset = 0;
00161 v_offset = 0;
00162 sequence_number = -1;
00163 is_keyframe = 0;
00164 return 0;
00165 }
00166
00167 int VFrame::clear_objects()
00168 {
00169
00170
00171 if(!shared)
00172 {
00173 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
00174 if(size > 2560 * 1920)
00175 UNBUFFER(data);
00176 if(data) delete [] data;
00177 data = 0;
00178 }
00179
00180
00181 switch(color_model)
00182 {
00183 case BC_COMPRESSED:
00184 case BC_YUV420P:
00185 break;
00186
00187 default:
00188 delete [] rows;
00189 break;
00190 }
00191
00192 return 0;
00193 }
00194
00195 int VFrame::get_field2_offset()
00196 {
00197 return field2_offset;
00198 }
00199
00200 int VFrame::set_field2_offset(int value)
00201 {
00202 this->field2_offset = value;
00203 return 0;
00204 }
00205
00206 void VFrame::set_keyframe(int value)
00207 {
00208 this->is_keyframe = value;
00209 }
00210
00211 int VFrame::get_keyframe()
00212 {
00213 return is_keyframe;
00214 }
00215
00216
00217 int VFrame::calculate_bytes_per_pixel(int color_model)
00218 {
00219 return cmodel_calculate_pixelsize(color_model);
00220 }
00221
00222 long VFrame::get_bytes_per_line()
00223 {
00224 return bytes_per_line;
00225 }
00226
00227 long VFrame::get_data_size()
00228 {
00229 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
00230
00231 }
00232
00233 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
00234 {
00235 return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
00236 return 0;
00237 }
00238
00239 void VFrame::create_row_pointers()
00240 {
00241 switch(color_model)
00242 {
00243 case BC_YUV420P:
00244 case BC_YUV411P:
00245 if(!this->v_offset)
00246 {
00247 this->y_offset = 0;
00248 this->u_offset = w * h;
00249 this->v_offset = w * h + w * h / 4;
00250 }
00251 y = this->data + this->y_offset;
00252 u = this->data + this->u_offset;
00253 v = this->data + this->v_offset;
00254 break;
00255
00256 case BC_YUV422P:
00257 if(!this->v_offset)
00258 {
00259 this->y_offset = 0;
00260 this->u_offset = w * h;
00261 this->v_offset = w * h + w * h / 2;
00262 }
00263 y = this->data + this->y_offset;
00264 u = this->data + this->u_offset;
00265 v = this->data + this->v_offset;
00266 break;
00267
00268 default:
00269 rows = new unsigned char*[h];
00270 for(int i = 0; i < h; i++)
00271 {
00272 rows[i] = &this->data[i * this->bytes_per_line];
00273 }
00274 break;
00275 }
00276 }
00277
00278 int VFrame::allocate_data(unsigned char *data,
00279 long y_offset,
00280 long u_offset,
00281 long v_offset,
00282 int w,
00283 int h,
00284 int color_model,
00285 long bytes_per_line)
00286 {
00287 this->w = w;
00288 this->h = h;
00289 this->color_model = color_model;
00290 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
00291 this->y_offset = this->u_offset = this->v_offset = 0;
00292
00293 if(bytes_per_line >= 0)
00294 {
00295 this->bytes_per_line = bytes_per_line;
00296 }
00297 else
00298 this->bytes_per_line = this->bytes_per_pixel * w;
00299
00300
00301 if(data)
00302 {
00303 shared = 1;
00304 this->data = data;
00305 this->y_offset = y_offset;
00306 this->u_offset = u_offset;
00307 this->v_offset = v_offset;
00308 }
00309 else
00310 {
00311 shared = 0;
00312 int size = calculate_data_size(this->w,
00313 this->h,
00314 this->bytes_per_line,
00315 this->color_model);
00316 this->data = new unsigned char[size];
00317
00318 if(size > 2560 * 1920)
00319 BUFFER(size, this->data, "VFrame::allocate_data");
00320
00321 if(!this->data)
00322 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
00323
00324
00325
00326 }
00327
00328
00329 create_row_pointers();
00330 return 0;
00331 }
00332
00333 void VFrame::set_memory(unsigned char *data,
00334 long y_offset,
00335 long u_offset,
00336 long v_offset)
00337 {
00338 shared = 1;
00339 this->data = data;
00340 this->y_offset = y_offset;
00341 this->u_offset = u_offset;
00342 this->v_offset = v_offset;
00343 y = this->data + this->y_offset;
00344 u = this->data + this->u_offset;
00345 v = this->data + this->v_offset;
00346 create_row_pointers();
00347 }
00348
00349 void VFrame::set_compressed_memory(unsigned char *data,
00350 int data_size,
00351 int data_allocated)
00352 {
00353 clear_objects();
00354 shared = 1;
00355 this->data = data;
00356 this->compressed_allocated = data_allocated;
00357 this->compressed_size = data_size;
00358 }
00359
00360
00361
00362 int VFrame::reallocate(unsigned char *data,
00363 long y_offset,
00364 long u_offset,
00365 long v_offset,
00366 int w,
00367 int h,
00368 int color_model,
00369 long bytes_per_line)
00370 {
00371 clear_objects();
00372 reset_parameters();
00373 allocate_data(data,
00374 y_offset,
00375 u_offset,
00376 v_offset,
00377 w,
00378 h,
00379 color_model,
00380 bytes_per_line);
00381 return 0;
00382 }
00383
00384 int VFrame::allocate_compressed_data(long bytes)
00385 {
00386 if(bytes < 1) return 1;
00387
00388
00389 if(data && compressed_allocated < bytes)
00390 {
00391 unsigned char *new_data = new unsigned char[bytes];
00392 bcopy(data, new_data, compressed_allocated);
00393 delete [] data;
00394 data = new_data;
00395 compressed_allocated = bytes;
00396 }
00397 else
00398 if(!data)
00399 {
00400 data = new unsigned char[bytes];
00401 compressed_allocated = bytes;
00402 compressed_size = 0;
00403 }
00404
00405 return 0;
00406 }
00407
00408 int VFrame::read_png(unsigned char *data)
00409 {
00410 PngData d;
00411 d.size = (((unsigned long)data[0]) << 24) |
00412 (((unsigned long)data[1]) << 16) |
00413 (((unsigned long)data[2]) << 8) |
00414 (unsigned char)data[3];
00415 d.data = data + 4;
00416 read_png(d);
00417 }
00418
00419 int VFrame::read_png(const PngData& data)
00420 {
00421 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00422 png_infop info_ptr = png_create_info_struct(png_ptr);
00423 int new_color_model;
00424
00425 image_offset = 0;
00426 image = data.data;
00427 image_size = data.size;
00428 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
00429 png_read_info(png_ptr, info_ptr);
00430
00431 w = png_get_image_width(png_ptr, info_ptr);
00432 h = png_get_image_height(png_ptr, info_ptr);
00433
00434 int src_color_model = png_get_color_type(png_ptr, info_ptr);
00435 switch(src_color_model)
00436 {
00437 case PNG_COLOR_TYPE_RGB:
00438 new_color_model = BC_RGB888;
00439 break;
00440
00441
00442 case PNG_COLOR_TYPE_GRAY_ALPHA:
00443 case PNG_COLOR_TYPE_RGB_ALPHA:
00444 default:
00445 new_color_model = BC_RGBA8888;
00446 break;
00447 }
00448
00449 reallocate(NULL,
00450 0,
00451 0,
00452 0,
00453 w,
00454 h,
00455 new_color_model,
00456 -1);
00457
00458 png_read_image(png_ptr, get_rows());
00459
00460
00461
00462 if(src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
00463 {
00464 for(int i = 0; i < get_h(); i++)
00465 {
00466 unsigned char *row = get_rows()[i];
00467 unsigned char *out_ptr = row + get_w() * 4 - 4;
00468 unsigned char *in_ptr = row + get_w() * 2 - 2;
00469
00470 for(int j = get_w() - 1; j >= 0; j--)
00471 {
00472 out_ptr[0] = in_ptr[0];
00473 out_ptr[1] = in_ptr[0];
00474 out_ptr[2] = in_ptr[0];
00475 out_ptr[3] = in_ptr[1];
00476 out_ptr -= 4;
00477 in_ptr -= 2;
00478 }
00479 }
00480 }
00481
00482 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00483 return 0;
00484 }
00485
00486 unsigned char* VFrame::get_data()
00487 {
00488 return data;
00489 }
00490
00491 long VFrame::get_compressed_allocated()
00492 {
00493 return compressed_allocated;
00494 }
00495
00496 long VFrame::get_compressed_size()
00497 {
00498 return compressed_size;
00499 }
00500
00501 long VFrame::set_compressed_size(long size)
00502 {
00503 compressed_size = size;
00504 return 0;
00505 }
00506
00507 int VFrame::get_color_model()
00508 {
00509 return color_model;
00510 }
00511
00512
00513 int VFrame::equals(VFrame *frame)
00514 {
00515 if(frame->data == data)
00516 return 1;
00517 else
00518 return 0;
00519 }
00520
00521 #define ZERO_YUV(components, type, max) \
00522 { \
00523 for(int i = 0; i < h; i++) \
00524 { \
00525 type *row = (type*)get_rows()[i]; \
00526 for(int j = 0; j < w; j++) \
00527 { \
00528 row[j * components] = 0; \
00529 row[j * components + 1] = (max + 1) / 2; \
00530 row[j * components + 2] = (max + 1) / 2; \
00531 if(components == 4) row[j * components + 3] = 0; \
00532 } \
00533 } \
00534 }
00535
00536 int VFrame::clear_frame()
00537 {
00538 switch(color_model)
00539 {
00540 case BC_COMPRESSED:
00541 break;
00542
00543 case BC_YUV420P:
00544 bzero(data, h * w * 2);
00545 break;
00546
00547 case BC_YUV888:
00548 ZERO_YUV(3, unsigned char, 0xff);
00549 break;
00550
00551 case BC_YUVA8888:
00552 ZERO_YUV(4, unsigned char, 0xff);
00553 break;
00554
00555 case BC_YUV161616:
00556 ZERO_YUV(3, uint16_t, 0xffff);
00557 break;
00558
00559 case BC_YUVA16161616:
00560 ZERO_YUV(4, uint16_t, 0xffff);
00561 break;
00562
00563 default:
00564 bzero(data, h * bytes_per_line);
00565 break;
00566 }
00567 return 0;
00568 }
00569
00570 void VFrame::rotate90()
00571 {
00572
00573 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
00574 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
00575 unsigned char **new_rows = new unsigned char*[new_h];
00576 for(int i = 0; i < new_h; i++)
00577 new_rows[i] = &new_data[new_bytes_per_line * i];
00578
00579
00580 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
00581 {
00582 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
00583 {
00584 for(int k = 0; k < bytes_per_pixel; k++)
00585 {
00586 new_rows[out_y][out_x * bytes_per_pixel + k] =
00587 rows[in_y][in_x * bytes_per_pixel + k];
00588 }
00589 }
00590 }
00591
00592
00593 clear_objects();
00594 data = new_data;
00595 rows = new_rows;
00596 bytes_per_line = new_bytes_per_line;
00597 w = new_w;
00598 h = new_h;
00599 }
00600
00601 void VFrame::rotate270()
00602 {
00603
00604 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
00605 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
00606 unsigned char **new_rows = new unsigned char*[new_h];
00607 for(int i = 0; i < new_h; i++)
00608 new_rows[i] = &new_data[new_bytes_per_line * i];
00609
00610
00611 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
00612 {
00613 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
00614 {
00615 for(int k = 0; k < bytes_per_pixel; k++)
00616 {
00617 new_rows[out_y][out_x * bytes_per_pixel + k] =
00618 rows[in_y][in_x * bytes_per_pixel + k];
00619 }
00620 }
00621 }
00622
00623
00624 clear_objects();
00625 data = new_data;
00626 rows = new_rows;
00627 bytes_per_line = new_bytes_per_line;
00628 w = new_w;
00629 h = new_h;
00630 }
00631
00632 void VFrame::flip_vert()
00633 {
00634 for(int i = 0, j = h - 1; i < j; i++, j--)
00635 {
00636 for(int k = 0; k < bytes_per_line; k++)
00637 {
00638 unsigned char temp = rows[j][k];
00639 rows[j][k] = rows[i][k];
00640 rows[i][k] = temp;
00641 }
00642 }
00643 }
00644
00645
00646
00647 int VFrame::copy_from(VFrame *frame)
00648 {
00649 int w = MIN(this->w, frame->get_w());
00650 int h = MIN(this->h, frame->get_h());
00651
00652
00653 switch(frame->color_model)
00654 {
00655 case BC_COMPRESSED:
00656 allocate_compressed_data(frame->compressed_size);
00657 memcpy(data, frame->data, frame->compressed_size);
00658 this->compressed_size = frame->compressed_size;
00659 break;
00660
00661 case BC_YUV420P:
00662
00663 memcpy(get_y(), frame->get_y(), w * h);
00664 memcpy(get_u(), frame->get_u(), w * h / 4);
00665 memcpy(get_v(), frame->get_v(), w * h / 4);
00666 break;
00667
00668 case BC_YUV422P:
00669
00670 memcpy(get_y(), frame->get_y(), w * h);
00671 memcpy(get_u(), frame->get_u(), w * h / 2);
00672 memcpy(get_v(), frame->get_v(), w * h / 2);
00673 break;
00674
00675 default:
00676
00677
00678
00679
00680 memcpy(data, frame->data, calculate_data_size(w,
00681 h,
00682 -1,
00683 frame->color_model));
00684 break;
00685 }
00686
00687 return 0;
00688 }
00689
00690
00691 #define OVERLAY(type, max, components) \
00692 { \
00693 type **in_rows = (type**)src->get_rows(); \
00694 type **out_rows = (type**)get_rows(); \
00695 int in_w = src->get_w(); \
00696 int in_h = src->get_h(); \
00697 \
00698 for(int i = 0; i < in_h; i++) \
00699 { \
00700 if(i + out_y1 >= 0 && i + out_y1 < h) \
00701 { \
00702 type *src_row = in_rows[i]; \
00703 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
00704 \
00705 for(int j = 0; j < in_w; j++) \
00706 { \
00707 if(j + out_x1 >= 0 && j + out_x1 < w) \
00708 { \
00709 int opacity = src_row[3]; \
00710 int transparency = max - src_row[3]; \
00711 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
00712 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
00713 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
00714 dst_row[3] = MAX(dst_row[3], src_row[3]); \
00715 } \
00716 \
00717 dst_row += components; \
00718 src_row += components; \
00719 } \
00720 } \
00721 } \
00722 }
00723
00724
00725 void VFrame::overlay(VFrame *src,
00726 int out_x1,
00727 int out_y1)
00728 {
00729 switch(get_color_model())
00730 {
00731 case BC_RGBA8888:
00732 OVERLAY(unsigned char, 0xff, 4);
00733 break;
00734 }
00735 }
00736
00737
00738
00739 int VFrame::get_scale_tables(int *column_table, int *row_table,
00740 int in_x1, int in_y1, int in_x2, int in_y2,
00741 int out_x1, int out_y1, int out_x2, int out_y2)
00742 {
00743 int y_out, i;
00744 float w_in = in_x2 - in_x1;
00745 float h_in = in_y2 - in_y1;
00746 int w_out = out_x2 - out_x1;
00747 int h_out = out_y2 - out_y1;
00748
00749 float hscale = w_in / w_out;
00750 float vscale = h_in / h_out;
00751
00752 for(i = 0; i < w_out; i++)
00753 {
00754 column_table[i] = (int)(hscale * i);
00755 }
00756
00757 for(i = 0; i < h_out; i++)
00758 {
00759 row_table[i] = (int)(vscale * i) + in_y1;
00760 }
00761 return 0;
00762 }
00763
00764 int VFrame::get_bytes_per_pixel()
00765 {
00766 return bytes_per_pixel;
00767 }
00768
00769 unsigned char** VFrame::get_rows()
00770 {
00771 if(rows)
00772 {
00773 return rows;
00774 }
00775 return 0;
00776 }
00777
00778 int VFrame::get_w()
00779 {
00780 return w;
00781 }
00782
00783 int VFrame::get_h()
00784 {
00785 return h;
00786 }
00787
00788 int VFrame::get_w_fixed()
00789 {
00790 return w - 1;
00791 }
00792
00793 int VFrame::get_h_fixed()
00794 {
00795 return h - 1;
00796 }
00797
00798 unsigned char* VFrame::get_y()
00799 {
00800 return y;
00801 }
00802
00803 unsigned char* VFrame::get_u()
00804 {
00805 return u;
00806 }
00807
00808 unsigned char* VFrame::get_v()
00809 {
00810 return v;
00811 }
00812
00813 void VFrame::set_number(long number)
00814 {
00815 sequence_number = number;
00816 }
00817
00818 long VFrame::get_number()
00819 {
00820 return sequence_number;
00821 }
00822
00823
00824
00825