home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / quicktime / yv12.c < prev    next >
C/C++ Source or Header  |  2000-11-29  |  12KB  |  391 lines

  1. #include "colormodels.h"
  2. #include "yv12.h"
  3.  
  4. #ifndef CLAMP
  5. #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  6. #endif
  7.  
  8. static int quicktime_delete_codec_yv12(quicktime_video_map_t *vtrack)
  9. {
  10.     quicktime_yv12_codec_t *codec;
  11.  
  12.     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  13.     free(codec->work_buffer);
  14.     free(codec);
  15.     return 0;
  16. }
  17.  
  18. static int quicktime_reads_colormodel_yv12(quicktime_t *file, 
  19.         int colormodel, 
  20.         int track)
  21. {
  22.     return (colormodel == BC_RGB888 ||
  23.         colormodel == BC_YUV888 ||
  24.         colormodel == BC_YUV420P);
  25. }
  26.  
  27. static int quicktime_writes_colormodel_yv12(quicktime_t *file, 
  28.         int colormodel, 
  29.         int track)
  30. {
  31.     return (colormodel == BC_YUV420P);
  32. }
  33.  
  34.  
  35. static int quicktime_decode_yv12(quicktime_t *file, unsigned char **row_pointers, int track)
  36. {
  37.     long bytes, x, y;
  38.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  39.     quicktime_yv12_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  40.     int width = vtrack->track->tkhd.track_width;
  41.     int height = vtrack->track->tkhd.track_height;
  42.     unsigned char *buffer;
  43.     unsigned char *output_row0, *output_row1, *y_plane0, *y_plane1, *u_plane, *v_plane;
  44.     long y_size, u_size, v_size;
  45.     int result = 0;
  46.     int y1, u, v, y2, r, g, b, y3, y4;
  47.     int bytes_per_row = width * cmodel_calculate_pixelsize(file->color_model);
  48.  
  49.     y_size = codec->coded_h * codec->coded_w;
  50.     u_size = codec->coded_h * codec->coded_w / 4;
  51.     v_size = codec->coded_h * codec->coded_w / 4;
  52.  
  53.     vtrack->track->tkhd.track_width;
  54.     quicktime_set_video_position(file, vtrack->current_position, track);
  55.     bytes = quicktime_frame_size(file, vtrack->current_position, track);
  56.  
  57.     switch(file->color_model)
  58.     {
  59.         case BC_RGB888:
  60.             buffer = codec->work_buffer;
  61.             result = !quicktime_read_data(file, buffer, bytes);
  62.  
  63.             for(y = 0; y < height; y += 2)
  64.             {
  65.                 y_plane0 = codec->work_buffer + y * codec->coded_w;
  66.                 y_plane1 = codec->work_buffer + (y + 1) * codec->coded_w;
  67.                 u_plane = codec->work_buffer + y_size + y * codec->coded_w / 4;
  68.                 v_plane = codec->work_buffer + y_size + u_size + y * codec->coded_w / 4;
  69.                 output_row0 = row_pointers[y];
  70.                 if(y + 1 < height) output_row1 = row_pointers[y + 1];
  71.  
  72.                 for(x = 0; x < width; x += 2)
  73.                 {
  74.                     y1 = *y_plane0++;
  75.                     y1 <<= 16;
  76.                     u = *u_plane++;
  77.                     v = *v_plane++;
  78.                     
  79.                     r = ((y1 + codec->yuv_table.vtor_tab[v]) >> 16);
  80.                     g = ((y1 + codec->yuv_table.utog_tab[u] + codec->yuv_table.vtog_tab[v]) >> 16);
  81.                     b = ((y1 + codec->yuv_table.utob_tab[u]) >> 16);
  82.  
  83.                     *output_row0++ = CLAMP(r, 0, 255);
  84.                     *output_row0++ = CLAMP(g, 0, 255);
  85.                     *output_row0++ = CLAMP(b, 0, 255);
  86.  
  87.                     if(y + 1 < height)
  88.                     {
  89.                         y1 = *y_plane1++;
  90.                         y1 <<= 16;
  91.                         r = ((y1 + codec->yuv_table.vtor_tab[v]) >> 16);
  92.                         g = ((y1 + codec->yuv_table.utog_tab[u] + codec->yuv_table.vtog_tab[v]) >> 16);
  93.                         b = ((y1 + codec->yuv_table.utob_tab[u]) >> 16);
  94.  
  95.                         *output_row1++ = CLAMP(r, 0, 255);
  96.                         *output_row1++ = CLAMP(g, 0, 255);
  97.                         *output_row1++ = CLAMP(b, 0, 255);
  98.                     }
  99.                     
  100.                     if(x + 1 < width)
  101.                     {
  102.                         y1 = *y_plane0++;
  103.                         y1 <<= 16;
  104.                         r = ((y1 + codec->yuv_table.vtor_tab[v]) >> 16);
  105.                         g = ((y1 + codec->yuv_table.utog_tab[u] + codec->yuv_table.vtog_tab[v]) >> 16);
  106.                         b = ((y1 + codec->yuv_table.utob_tab[u]) >> 16);
  107.  
  108.                         *output_row0++ = CLAMP(r, 0, 255);
  109.                         *output_row0++ = CLAMP(g, 0, 255);
  110.                         *output_row0++ = CLAMP(b, 0, 255);
  111.                     }
  112.                     
  113.                     if(y + 1 < height && x + 1 < width)
  114.                     {
  115.                         y1 = *y_plane1++;
  116.                         y1 <<= 16;
  117.                         r = ((y1 + codec->yuv_table.vtor_tab[v]) >> 16);
  118.                         g = ((y1 + codec->yuv_table.utog_tab[u] + codec->yuv_table.vtog_tab[v]) >> 16);
  119.                         b = ((y1 + codec->yuv_table.utob_tab[u]) >> 16);
  120.  
  121.                         *output_row1++ = CLAMP(r, 0, 255);
  122.                         *output_row1++ = CLAMP(g, 0, 255);
  123.                         *output_row1++ = CLAMP(b, 0, 255);
  124.                     }
  125.                 }
  126.             }
  127.             break;
  128.  
  129.         case BC_YUV888:
  130.             buffer = codec->work_buffer;
  131.             result = !quicktime_read_data(file, buffer, bytes);
  132.  
  133.             for(y = 0; y < height; y += 2)
  134.             {
  135.                 y_plane0 = codec->work_buffer + y * codec->coded_w;
  136.                 y_plane1 = codec->work_buffer + (y + 1) * codec->coded_w;
  137.                 u_plane = codec->work_buffer + y_size + y * codec->coded_w / 4;
  138.                 v_plane = codec->work_buffer + y_size + u_size + y * codec->coded_w / 4;
  139.                 output_row0 = row_pointers[y];
  140.                 if(y + 1 < height) output_row1 = row_pointers[y + 1];
  141.  
  142.                 for(x = 0; x < width; x += 2)
  143.                 {
  144.                     *output_row0++ = *y_plane0++;
  145.                     *output_row0++ = u = *u_plane++;
  146.                     *output_row0++ = v = *v_plane++;
  147.  
  148.                     if(y + 1 < height)
  149.                     {
  150.                         *output_row1++ = *y_plane1++;
  151.                         *output_row1++ = u;
  152.                         *output_row1++ = v;
  153.                     }
  154.  
  155.                     if(x + 1 < height)
  156.                     {
  157.                         *output_row0++ = *y_plane0++;
  158.                         *output_row0++ = u;
  159.                         *output_row0++ = v;
  160.                     }
  161.  
  162.                     if(x + 1 < height && y + 1 < height)
  163.                     {
  164.                         *output_row1++ = *y_plane1++;
  165.                         *output_row1++ = u;
  166.                         *output_row1++ = v;
  167.                     }
  168.                 }
  169.             }
  170.             break;
  171.  
  172.         case BC_YUV420P:
  173.             result = !quicktime_read_data(file, row_pointers[0], y_size);
  174.             result = !quicktime_read_data(file, row_pointers[1], u_size);
  175.             result = !quicktime_read_data(file, row_pointers[2], v_size);
  176.             break;
  177.     }
  178.  
  179.     return result;
  180. }
  181.  
  182. static int quicktime_encode_yv12(quicktime_t *file, unsigned char **row_pointers, int track)
  183. {
  184.     long offset = quicktime_position(file);
  185.     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  186.     quicktime_yv12_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  187.     int result = 0;
  188.     int width = vtrack->track->tkhd.track_width;
  189.     int height = vtrack->track->tkhd.track_height;
  190.     long bytes;
  191.     unsigned char *y_plane0, *y_plane1, *u_plane, *v_plane;
  192.     long y_size, u_size, v_size;
  193.     unsigned char *input_row0, *input_row1;
  194.     int x, y;
  195.     int y1, u, y2, v, y3, y4, subscript;
  196.     int r, g, b;
  197.  
  198.     y_size = codec->coded_h * codec->coded_w;
  199.     u_size = codec->coded_h * codec->coded_w / 4;
  200.     v_size = codec->coded_h * codec->coded_w / 4;
  201.     bytes = y_size + u_size + v_size;
  202.  
  203.     switch(file->color_model)
  204.     {
  205.         case BC_RGB888:
  206.             for(y = 0; y < height; y += 2)
  207.             {
  208.                 y_plane0 = codec->work_buffer + y * codec->coded_w;
  209.                 y_plane1 = codec->work_buffer + (y + 1) * codec->coded_w;
  210.                 u_plane = codec->work_buffer + y_size + y * codec->coded_w / 4;
  211.                 v_plane = codec->work_buffer + y_size + u_size + y * codec->coded_w / 4;
  212.                 input_row0 = row_pointers[y];
  213.                 if(y + 1 < height) input_row1 = row_pointers[y + 1];
  214.                 
  215.                 for(x = 0; x < width; x += 2)
  216.                 {
  217.                     r = *input_row0++;
  218.                     g = *input_row0++;
  219.                     b = *input_row0++;
  220.                     y1 = (codec->yuv_table.rtoy_tab[r] + 
  221.                         codec->yuv_table.gtoy_tab[g] + 
  222.                         codec->yuv_table.btoy_tab[b]) >> 16;
  223.                     u = (codec->yuv_table.rtou_tab[r] + 
  224.                         codec->yuv_table.gtou_tab[g] + 
  225.                         codec->yuv_table.btou_tab[b]);
  226.                     v = (codec->yuv_table.rtov_tab[r] + 
  227.                         codec->yuv_table.gtov_tab[g] + 
  228.                         codec->yuv_table.btov_tab[b]);
  229.                     subscript = 1;
  230.  
  231.                     if(y + 1 < height)
  232.                     {
  233.                         r = *input_row1++;
  234.                         g = *input_row1++;
  235.                         b = *input_row1++;
  236.                         y2 = (codec->yuv_table.rtoy_tab[r] + 
  237.                             codec->yuv_table.gtoy_tab[g] + 
  238.                             codec->yuv_table.btoy_tab[b]) >> 16;
  239.                         u += (codec->yuv_table.rtou_tab[r] + 
  240.                             codec->yuv_table.gtou_tab[g] + 
  241.                             codec->yuv_table.btou_tab[b]);
  242.                         v += (codec->yuv_table.rtov_tab[r] + 
  243.                             codec->yuv_table.gtov_tab[g] + 
  244.                             codec->yuv_table.btov_tab[b]);
  245.                         subscript++;
  246.                     }
  247.  
  248.                     if(x + 1 < width)
  249.                     {
  250.                         r = *input_row0++;
  251.                         g = *input_row0++;
  252.                         b = *input_row0++;
  253.                         y3 = (codec->yuv_table.rtoy_tab[r] + 
  254.                             codec->yuv_table.gtoy_tab[g] + 
  255.                             codec->yuv_table.btoy_tab[b]) >> 16;
  256.                         u += (codec->yuv_table.rtou_tab[r] + 
  257.                             codec->yuv_table.gtou_tab[g] + 
  258.                             codec->yuv_table.btou_tab[b]);
  259.                         v += (codec->yuv_table.rtov_tab[r] + 
  260.                             codec->yuv_table.gtov_tab[g] + 
  261.                             codec->yuv_table.btov_tab[b]);
  262.                         subscript++;
  263.                     }
  264.  
  265.                     if(x + 1 < width && y + 1 < height)
  266.                     {
  267.                         r = *input_row1++;
  268.                         g = *input_row1++;
  269.                         b = *input_row1++;
  270.                         y4 = (codec->yuv_table.rtoy_tab[r] + 
  271.                             codec->yuv_table.gtoy_tab[g] + 
  272.                             codec->yuv_table.btoy_tab[b]) >> 16;
  273.                         u += (codec->yuv_table.rtou_tab[r] + 
  274.                             codec->yuv_table.gtou_tab[g] + 
  275.                             codec->yuv_table.btou_tab[b]);
  276.                         v += (codec->yuv_table.rtov_tab[r] + 
  277.                             codec->yuv_table.gtov_tab[g] + 
  278.                             codec->yuv_table.btov_tab[b]);
  279.                         subscript++;
  280.                     }
  281.  
  282.                     *y_plane0++ = CLAMP(y1, 0, 255);
  283.                     *y_plane1++ = CLAMP(y2, 0, 255);
  284.                     *y_plane0++ = CLAMP(y3, 0, 255);
  285.                     *y_plane1++ = CLAMP(y4, 0, 255);
  286.  
  287.                     u /= subscript;
  288.                     v /= subscript;
  289.                     u >>= 16;
  290.                     v >>= 16;
  291.                     *u_plane++ = CLAMP(u, -128, 127) + 128;
  292.                     *v_plane++ = CLAMP(v, -128, 127) + 128;
  293.                 }
  294.             }
  295.             result = !quicktime_write_data(file, codec->work_buffer, bytes);
  296.             break;
  297.  
  298.         case BC_YUV888:
  299.             for(y = 0; y < height; y += 2)
  300.             {
  301.                 y_plane0 = codec->work_buffer + y * codec->coded_w;
  302.                 y_plane1 = codec->work_buffer + (y + 1) * codec->coded_w;
  303.                 u_plane = codec->work_buffer + y_size + y * codec->coded_w / 4;
  304.                 v_plane = codec->work_buffer + y_size + u_size + y * codec->coded_w / 4;
  305.                 input_row0 = row_pointers[y];
  306.                 if(y + 1 < height) input_row1 = row_pointers[y + 1];
  307.                 
  308.                 for(x = 0; x < width; x += 2)
  309.                 {
  310.                     *y_plane0++ = *input_row0++;
  311.                     u = *input_row0++;
  312.                     v = *input_row0++;
  313.                     subscript = 1;
  314.  
  315.                     if(y + 1 < height)
  316.                     {
  317.                         *y_plane1++ = *input_row1++;
  318.                         u += *input_row1++;
  319.                         v += *input_row1++;
  320.                         subscript++;
  321.                     }
  322.  
  323.                     if(x + 1 < width)
  324.                     {
  325.                         *y_plane0++ = *input_row0++;
  326.                         u += *input_row0++;
  327.                         v += *input_row0++;
  328.                         subscript++;
  329.                     }
  330.  
  331.                     if(x + 1 < width && y + 1 < height)
  332.                     {
  333.                         *y_plane1++ = *input_row1++;
  334.                         u += *input_row1++;
  335.                         v += *input_row1++;
  336.                         subscript++;
  337.                     }
  338.  
  339.                     u /= subscript;
  340.                     v /= subscript;
  341.                     *u_plane++ = CLAMP(u, 0, 255);
  342.                     *v_plane++ = CLAMP(v, 0, 255);
  343.                 }
  344.             }
  345.             result = !quicktime_write_data(file, codec->work_buffer, bytes);
  346.             break;
  347.  
  348.         case BC_YUV420P:
  349.             result = !quicktime_write_data(file, row_pointers[0], y_size);
  350.             result = !quicktime_write_data(file, row_pointers[1], u_size);
  351.             result = !quicktime_write_data(file, row_pointers[2], v_size);
  352.             break;
  353.     }
  354.  
  355.     quicktime_update_tables(file,
  356.                         file->vtracks[track].track,
  357.                         offset,
  358.                         file->vtracks[track].current_chunk,
  359.                         file->vtracks[track].current_position,
  360.                         1,
  361.                         bytes);
  362.  
  363.     file->vtracks[track].current_chunk++;
  364.     return result;
  365. }
  366.  
  367. void quicktime_init_codec_yv12(quicktime_video_map_t *vtrack)
  368. {
  369.     int i;
  370.     quicktime_yv12_codec_t *codec;
  371.  
  372. /* Init public items */
  373.     ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_yv12_codec_t));
  374.     ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = quicktime_delete_codec_yv12;
  375.     ((quicktime_codec_t*)vtrack->codec)->decode_video = quicktime_decode_yv12;
  376.     ((quicktime_codec_t*)vtrack->codec)->encode_video = quicktime_encode_yv12;
  377.     ((quicktime_codec_t*)vtrack->codec)->decode_audio = 0;
  378.     ((quicktime_codec_t*)vtrack->codec)->encode_audio = 0;
  379.     ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = quicktime_reads_colormodel_yv12;
  380.  
  381. /* Init private items */
  382.     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  383.     codec->coded_w = (int)(vtrack->track->tkhd.track_width / 2);
  384.     codec->coded_w *= 2;
  385.     codec->coded_h = (int)(vtrack->track->tkhd.track_height / 2);
  386.     codec->coded_h *= 2;
  387.     cmodel_init_yuv(&codec->yuv_table);
  388.     codec->work_buffer = malloc(codec->coded_w * codec->coded_w + codec->coded_w * codec->coded_w / 2);
  389. }
  390.  
  391.