xyuv.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:25k
源码类别:

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * xyuv.c: a SDL yuv 420 planer viewer.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 Laurent Aimar
  5.  * $Id: xyuv.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdint.h>
  27. #include <SDL/SDL.h>
  28. #define YUV_MAX 20
  29. #define SDL_TITLE "xyuv: %s - %d/%d - %.2ffps"
  30. typedef struct
  31. {
  32.     /* globals */
  33.     int     i_width;
  34.     int     i_height;
  35.     int     i_frame_size;
  36.     int     i_frame;
  37.     int     i_frames;
  38.     float   f_fps;
  39.     float   f_y;
  40.     int     b_pause;
  41.     int     b_grid;
  42.     int     b_split;
  43.     int     b_diff;
  44.     int     i_join;
  45.     /* Constructed picture */
  46.     int     i_wall_width;   /* in picture count */
  47.     /* YUV files */
  48.     int     i_yuv;
  49.     struct
  50.     {
  51.         char    *name;
  52.         FILE    *f;         /* handles */
  53.         int     i_frames;   /* frames count */
  54.         /* Position in the whole picture */
  55.         int     x, y;
  56.     } yuv[YUV_MAX];
  57.     /* SDL */
  58.     int i_sdl_width;
  59.     int i_sdl_height;
  60.     int i_display_width;
  61.     int i_display_height;
  62.     char *title;
  63.     SDL_Surface *screen;
  64.     SDL_Overlay *overlay;
  65.     /* */
  66.     uint8_t *pic;
  67. } xyuv_t;
  68. xyuv_t xyuv = {
  69.     .i_width = 0,
  70.     .i_height = 0,
  71.     .i_frame  = 1,
  72.     .i_frames = 0,
  73.     .f_fps = 25.0,
  74.     .f_y = 0.0,
  75.     .i_wall_width = 0,
  76.     .i_yuv = 0,
  77.     .b_pause = 0,
  78.     .b_split = 0,
  79.     .b_diff = 0,
  80.     .i_join = -1,
  81.     .title = NULL,
  82.     .pic = NULL,
  83. };
  84. static void help( void )
  85. {
  86.     fprintf( stderr,
  87.              "Syntax: xyuv [options] file [file2 ...]n"
  88.              "n"
  89.              "      --help                  Print this helpn"
  90.              "n"
  91.              "  -s, --size <WIDTHxHEIGHT>   Set input sizen"
  92.              "  -w, --width <integer>       Set widthn"
  93.              "  -h, --height <integer>      Set heightn"
  94.              "n"
  95.              "  -S, --split                 Show splited Y/U/V planesn"
  96.              "  -d, --diff                  Show difference (only 2 files) in split moden"
  97.              "  -j, --joint <integer>n"
  98.              "n"
  99.              "  -y <float>                  Set Y factorn"
  100.              "n"
  101.              "  -g, --grid                  Show a grid (macroblock 16x16)n"
  102.              "  -W <integer>                Set wall width (in picture count)n"
  103.              "  -f, --fps <float>           Set fpsn"
  104.              "n" );
  105. }
  106. static void xyuv_count_frames( xyuv_t *xyuv );
  107. static void xyuv_detect( int *pi_width, int *pi_height );
  108. static void xyuv_display( xyuv_t *xyuv, int i_frame );
  109. int main( int argc, char **argv )
  110. {
  111.     int i;
  112.     /* Parse commande line */
  113.     for( i = 1; i < argc; i++ ) {
  114.         if( !strcasecmp( argv[i], "--help" ) ) {
  115.             help();
  116.             return 0;
  117.         }
  118.         if( !strcmp( argv[i], "-d" ) || !strcasecmp( argv[i], "--diff" ) ) {
  119.             xyuv.b_diff = 1;
  120.         } else if( !strcmp( argv[i], "-S" ) || !strcasecmp( argv[i], "--split" ) ) {
  121.             xyuv.b_split = 1;
  122.         } else if( !strcmp( argv[i], "-f" ) || !strcasecmp( argv[i], "--fps" ) ) {
  123.             if( i >= argc -1 ) goto err_missing_arg;
  124.             xyuv.f_fps = atof( argv[++i] );
  125.         } else if( !strcmp( argv[i], "-h" ) || !strcasecmp( argv[i], "--height" ) ) {
  126.             if( i >= argc -1 ) goto err_missing_arg;
  127.             xyuv.i_height = atoi( argv[++i] );
  128.         } else if( !strcmp( argv[i], "-w" ) || !strcasecmp( argv[i], "--width" ) ) {
  129.             if( i >= argc -1 ) goto err_missing_arg;
  130.             xyuv.i_width = atoi( argv[++i] );
  131.         } else if( !strcmp( argv[i], "-s" ) || !strcasecmp( argv[i], "--size" ) ) {
  132.             char *p;
  133.             if( i >= argc -1 ) goto err_missing_arg;
  134.             xyuv.i_width = strtol( argv[++i], &p, 0 );
  135.             p++;
  136.             xyuv.i_height = atoi( p );
  137.         } else if( !strcmp( argv[i], "-W" ) ) {
  138.             if( i >= argc -1 ) goto err_missing_arg;
  139.             xyuv.i_wall_width = atoi( argv[++i] );
  140.         } else if( !strcmp( argv[i], "-y" ) ) {
  141.             if( i >= argc -1 ) goto err_missing_arg;
  142.             xyuv.f_y = atof( argv[++i] );
  143.         } else if( !strcmp( argv[i], "-j" ) || !strcasecmp( argv[i], "--join" ) ) {
  144.             if( i >= argc -1 ) goto err_missing_arg;
  145.             xyuv.i_join = atoi( argv[++i] );
  146.         } else if( !strcmp( argv[i], "-g" ) || !strcasecmp( argv[i], "--grid" ) ) {
  147.             xyuv.b_grid = 1;
  148.         } else {
  149.             FILE *f = fopen( argv[i], "rb" );
  150.             if( !f ) {
  151.                 fprintf( stderr, "cannot open YUV %sn", argv[i] );
  152.             } else {
  153.                 xyuv.yuv[xyuv.i_yuv].name = strdup( argv[i] );
  154.                 xyuv.yuv[xyuv.i_yuv].f = f;
  155.                 xyuv.yuv[xyuv.i_yuv].i_frames = 0;
  156.                 xyuv.i_yuv++;
  157.             }
  158.         }
  159.     }
  160.     if( xyuv.i_yuv == 0 ) {
  161.         fprintf( stderr, "no file to displayn" );
  162.         return -1;
  163.     }
  164.     if( xyuv.i_width == 0 || xyuv.i_height == 0 ) {
  165.         char *psz = xyuv.yuv[0].name;
  166.         char *num;
  167.         char *x;
  168.         /* See if we find widthxheight in the file name */
  169.         for( ;; ) {
  170.             if( !( x = strchr( psz+1, 'x' ) ) ) {
  171.                 break;
  172.             }
  173.             num = x;
  174.             while( num > psz && num[-1] >= '0' && num[-1] <= '9' )
  175.                 num--;
  176.             if( num != x && x[1] >= '0' && x[1] <= '9' ) {
  177.                 xyuv.i_width = atoi( num );
  178.                 xyuv.i_height = atoi( x+1 );
  179.                 break;
  180.             }
  181.             psz = x;
  182.         }
  183.         fprintf( stderr, "file name gives %dx%dn", xyuv.i_width, xyuv.i_height );
  184.     }
  185.     if( xyuv.i_width == 0 || xyuv.i_height == 0 ) {
  186.         xyuv_detect( &xyuv.i_width, &xyuv.i_height );
  187.     }
  188.     if( xyuv.i_width == 0 || xyuv.i_height == 0 ) {
  189.         fprintf( stderr, "invalid or missing frames sizen" );
  190.         return -1;
  191.     }
  192.     if( xyuv.b_diff && xyuv.i_yuv != 2 ) {
  193.         fprintf( stderr, "--diff works only with 2 filesn" );
  194.         return -1;
  195.     }
  196.     if( (xyuv.i_join == 0 || xyuv.i_join >= xyuv.i_width) && xyuv.i_yuv != 2 ) {
  197.         fprintf( stderr, "--join woeks only with two files and range is [1, width-1]n" );
  198.         return -1;
  199.     }
  200.     if( xyuv.i_join % 2 != 0 ) {
  201.         if( xyuv.i_join + 1 < xyuv.i_width )
  202.             xyuv.i_join++;
  203.         else
  204.             xyuv.i_join--;
  205.     }
  206.     /* Now check frames */
  207.     fprintf( stderr, "displaying :n" );
  208.     xyuv.i_frame_size = 3 * xyuv.i_width * xyuv.i_height / 2;
  209.     xyuv_count_frames( &xyuv );
  210.     for( i = 0; i < xyuv.i_yuv; i++ ) {
  211.         fprintf( stderr, " - '%s' : %d framesn", xyuv.yuv[i].name, xyuv.yuv[i].i_frames );
  212.     }
  213.     if( xyuv.i_frames == 0 ) {
  214.         fprintf( stderr, "no frames to displayn" );
  215.     }
  216.     xyuv.pic = malloc( xyuv.i_frame_size );
  217.     /* calculate SDL view */
  218.     if( xyuv.i_wall_width > xyuv.i_yuv ) {
  219.         xyuv.i_wall_width = xyuv.i_yuv;
  220.     }
  221.     if( xyuv.i_wall_width == 0 ) {
  222.         while( xyuv.i_wall_width < xyuv.i_yuv && xyuv.i_wall_width * xyuv.i_wall_width < xyuv.i_yuv ) {
  223.             xyuv.i_wall_width++;
  224.         }
  225.     }
  226.     for( i = 0; i < xyuv.i_yuv; i++ ) {
  227.         if( xyuv.b_diff || xyuv.i_join > 0 ) {
  228.             xyuv.yuv[i].x = 0;
  229.             xyuv.yuv[i].y = 0;
  230.         } else if( xyuv.b_split ) {
  231.             xyuv.yuv[i].x = (i%xyuv.i_wall_width) * 3 * xyuv.i_width / 2;
  232.             xyuv.yuv[i].y = (i/xyuv.i_wall_width) * xyuv.i_height;
  233.         } else {
  234.             xyuv.yuv[i].x = (i%xyuv.i_wall_width) * xyuv.i_width;
  235.             xyuv.yuv[i].y = (i/xyuv.i_wall_width) * xyuv.i_height;
  236.         }
  237.     }
  238.     if( xyuv.b_diff ) {
  239.         xyuv.i_sdl_width = 3 * xyuv.i_width / 2;
  240.         xyuv.i_sdl_height= xyuv.i_height;
  241.     } else if( xyuv.i_join > 0 ) {
  242.         xyuv.i_sdl_width = xyuv.i_width;
  243.         xyuv.i_sdl_height= xyuv.i_height;
  244.     } else if( xyuv.b_split ) {
  245.         xyuv.i_sdl_width = xyuv.i_wall_width * 3 * xyuv.i_width / 2;
  246.         xyuv.i_sdl_height= xyuv.i_height * ( ( xyuv.i_yuv  + xyuv.i_wall_width - 1 ) / xyuv.i_wall_width );
  247.     } else {
  248.         xyuv.i_sdl_width = xyuv.i_wall_width * xyuv.i_width;
  249.         xyuv.i_sdl_height= xyuv.i_height * ( ( xyuv.i_yuv  + xyuv.i_wall_width - 1 ) / xyuv.i_wall_width );
  250.     }
  251.     xyuv.i_display_width = xyuv.i_sdl_width;
  252.     xyuv.i_display_height = xyuv.i_sdl_height;
  253.     /* Open SDL */
  254.     if( SDL_Init( SDL_INIT_EVENTTHREAD|SDL_INIT_NOPARACHUTE|SDL_INIT_VIDEO) ) {
  255.         fprintf( stderr, "cannot init SDLn" );
  256.         return -1;
  257.     }
  258.     SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 100 );
  259.     SDL_EventState( SDL_KEYUP, SDL_IGNORE );
  260.     xyuv.screen = SDL_SetVideoMode( xyuv.i_sdl_width, xyuv.i_sdl_height, 0,
  261.                                     SDL_HWSURFACE|SDL_RESIZABLE|
  262.                                     SDL_ASYNCBLIT|SDL_HWACCEL );
  263.     if( xyuv.screen == NULL ) {
  264.         fprintf( stderr, "SDL_SetVideoMode failedn" );
  265.         return -1;
  266.     }
  267.     SDL_LockSurface( xyuv.screen );
  268.     xyuv.overlay = SDL_CreateYUVOverlay( xyuv.i_sdl_width, xyuv.i_sdl_height,
  269.                                          SDL_YV12_OVERLAY,
  270.                                          xyuv.screen );
  271.     /* reset with black */
  272.     memset( xyuv.overlay->pixels[0],   0, xyuv.overlay->pitches[0] * xyuv.i_sdl_height );
  273.     memset( xyuv.overlay->pixels[1], 128, xyuv.overlay->pitches[1] * xyuv.i_sdl_height / 2);
  274.     memset( xyuv.overlay->pixels[2], 128, xyuv.overlay->pitches[2] * xyuv.i_sdl_height / 2);
  275.     SDL_UnlockSurface( xyuv.screen );
  276.     if( xyuv.overlay == NULL ) {
  277.         fprintf( stderr, "recon: SDL_CreateYUVOverlay failedn" );
  278.         return -1;
  279.     }
  280.     for( ;; ) {
  281.         SDL_Event event;
  282.         static int b_fullscreen = 0;
  283.         int64_t i_start = SDL_GetTicks();
  284.         int i_wait;
  285.         if( !xyuv.b_pause ) {
  286.             xyuv_display( &xyuv, xyuv.i_frame );
  287.         }
  288.         for( ;; ) {
  289.             int b_refresh = 0;
  290.             while( SDL_PollEvent( &event ) )  {
  291.                 switch( event.type )
  292.                 {
  293.                     case SDL_QUIT:
  294.                         if( b_fullscreen )
  295.                             SDL_WM_ToggleFullScreen( xyuv.screen );
  296.                         exit( 1 );
  297.                     case SDL_KEYDOWN:
  298.                         switch( event.key.keysym.sym )
  299.                         {
  300.                             case SDLK_q:
  301.                             case SDLK_ESCAPE:
  302.                                 if( b_fullscreen )
  303.                                     SDL_WM_ToggleFullScreen( xyuv.screen );
  304.                                 exit(1);
  305.                             case SDLK_f:
  306.                                 if( SDL_WM_ToggleFullScreen( xyuv.screen ) )
  307.                                     b_fullscreen = 1 - b_fullscreen;
  308.                                 break;
  309.                             case SDLK_g:
  310.                                 if( xyuv.b_grid )
  311.                                     xyuv.b_grid = 0;
  312.                                 else
  313.                                     xyuv.b_grid = 1;
  314.                                 if( xyuv.b_pause )
  315.                                     b_refresh = 1;
  316.                                 break;
  317.                             case SDLK_SPACE:
  318.                                 if( xyuv.b_pause )
  319.                                     xyuv.b_pause = 0;
  320.                                 else
  321.                                     xyuv.b_pause = 1;
  322.                                 break;
  323.                             case SDLK_LEFT:
  324.                                 if( xyuv.i_frame > 1 ) xyuv.i_frame--;
  325.                                 b_refresh = 1;
  326.                                 break;
  327.                             case SDLK_RIGHT:
  328.                                 if( xyuv.i_frame >= xyuv.i_frames )
  329.                                     xyuv_count_frames( &xyuv );
  330.                                 if( xyuv.i_frame < xyuv.i_frames ) xyuv.i_frame++;
  331.                                 b_refresh = 1;
  332.                                 break;
  333.                             case SDLK_HOME:
  334.                                 xyuv.i_frame = 1;
  335.                                 if( xyuv.b_pause )
  336.                                     b_refresh = 1;
  337.                                 break;
  338.                             case SDLK_END:
  339.                                 xyuv_count_frames( &xyuv );
  340.                                 xyuv.i_frame = xyuv.i_frames;
  341.                                 b_refresh = 1;
  342.                                 break;
  343.                             case SDLK_UP:
  344.                                 xyuv.i_frame += xyuv.i_frames / 20;
  345.                                 if( xyuv.i_frame >= xyuv.i_frames )
  346.                                     xyuv_count_frames( &xyuv );
  347.                                 if( xyuv.i_frame > xyuv.i_frames )
  348.                                     xyuv.i_frame = xyuv.i_frames;
  349.                                 b_refresh = 1;
  350.                                 break;
  351.                             case SDLK_DOWN:
  352.                                 xyuv.i_frame -= xyuv.i_frames / 20;
  353.                                 if( xyuv.i_frame < 1 )
  354.                                     xyuv.i_frame = 1;
  355.                                 b_refresh = 1;
  356.                                 break;
  357.                             case SDLK_PAGEUP:
  358.                                 xyuv.i_frame += xyuv.i_frames / 10;
  359.                                 if( xyuv.i_frame >= xyuv.i_frames )
  360.                                     xyuv_count_frames( &xyuv );
  361.                                 if( xyuv.i_frame > xyuv.i_frames )
  362.                                     xyuv.i_frame = xyuv.i_frames;
  363.                                 b_refresh = 1;
  364.                                 break;
  365.                             case SDLK_PAGEDOWN:
  366.                                 xyuv.i_frame -= xyuv.i_frames / 10;
  367.                                 if( xyuv.i_frame < 1 )
  368.                                     xyuv.i_frame = 1;
  369.                                 b_refresh = 1;
  370.                                 break;
  371.                             default:
  372.                                 break;
  373.                         }
  374.                         break;
  375.                     case SDL_VIDEORESIZE:
  376.                         xyuv.i_display_width = event.resize.w;
  377.                         xyuv.i_display_height = event.resize.h;
  378.                         xyuv.screen = SDL_SetVideoMode( xyuv.i_display_width, xyuv.i_display_height, 0,
  379.                                                         SDL_HWSURFACE|SDL_RESIZABLE|
  380.                                                         SDL_ASYNCBLIT|SDL_HWACCEL );
  381.                         xyuv_display( &xyuv, xyuv.i_frame );
  382.                         break;
  383.                     default:
  384.                         break;
  385.                 }
  386.             }
  387.             if( b_refresh ) {
  388.                 xyuv.b_pause = 1;
  389.                 xyuv_display( &xyuv, xyuv.i_frame );
  390.             }
  391.             /* wait */
  392.             i_wait = 1000 / xyuv.f_fps - ( SDL_GetTicks() - i_start);
  393.             if( i_wait < 0 )
  394.                 break;
  395.             else if( i_wait > 200 )
  396.                 SDL_Delay( 200 );
  397.             else {
  398.                 SDL_Delay( i_wait );
  399.                 break;
  400.             }
  401.         }
  402.         if( !xyuv.b_pause ) {
  403.             /* next frame */
  404.             if( xyuv.i_frame == xyuv.i_frames )
  405.                     xyuv.b_pause = 1;
  406.             else if( xyuv.i_frame < xyuv.i_frames )
  407.                 xyuv.i_frame++;
  408.         }
  409.     }
  410.     return 0;
  411. err_missing_arg:
  412.     fprintf( stderr, "missing arg for option=%sn", argv[i] );
  413.     return -1;
  414. }
  415. static void xyuv_display( xyuv_t *xyuv, int i_frame )
  416. {
  417.     SDL_Rect rect;
  418.     int i_picture = 0;
  419.     int i;
  420.     if( i_frame > xyuv->i_frames )
  421.         return;
  422.     xyuv->i_frame = i_frame;
  423.     /* Load and copy pictue data */
  424.     for( i = 0; i < xyuv->i_yuv; i++ ) {
  425.         int i_plane;
  426.         fprintf( stderr, "yuv[%d] %d/%dn", i, i_frame, xyuv->yuv[i].i_frames );
  427.         if( i_frame - 1 >= xyuv->yuv[i].i_frames ) {
  428.             xyuv_count_frames( xyuv );
  429.             if( i_frame - 1 >= xyuv->yuv[i].i_frames )
  430.                 continue;
  431.         }
  432.         i_picture++;
  433.         fseek( xyuv->yuv[i].f, (xyuv->i_frame-1) * xyuv->i_frame_size, SEEK_SET );
  434.         fread( xyuv->pic, xyuv->i_frame_size, 1, xyuv->yuv[i].f );
  435.         SDL_LockYUVOverlay( xyuv->overlay );
  436.         if( xyuv->b_diff || xyuv->b_split ) {
  437.             /* Reset UV */
  438.             for( i_plane = 1; i_plane < 3; i_plane++ ) {
  439.                 memset( xyuv->overlay->pixels[i_plane], 128, xyuv->overlay->pitches[i_plane] * xyuv->overlay->h / 2 );
  440.             }
  441.             /* Show diff in Y plane of overlay */
  442.             for( i_plane = 0; i_plane < 3; i_plane++ ) {
  443.                 int div = i_plane == 0 ? 1 : 2;
  444.                 uint8_t *src = xyuv->pic;
  445.                 uint8_t *dst = xyuv->overlay->pixels[0] +
  446.                                 (xyuv->yuv[i].x + xyuv->yuv[i].y * xyuv->overlay->pitches[0] );
  447.                 int j;
  448.                 if( i_plane == 1 ) {
  449.                     src +=  5*xyuv->i_width * xyuv->i_height/4;
  450.                     dst += xyuv->i_width;
  451.                 } else if( i_plane == 2 ) {
  452.                     src += xyuv->i_width * xyuv->i_height;
  453.                     dst += xyuv->i_width + xyuv->i_height / 2 * xyuv->overlay->pitches[0];
  454.                 }
  455.                 for( j = 0; j < xyuv->i_height / div; j++ ) {
  456.                     if( i_picture == 1 || xyuv->b_split ) {
  457.                         memcpy( dst, src, xyuv->i_width / div );
  458.                     } else {
  459.                         int k;
  460.                         for( k = 0; k < xyuv->i_width / div; k++ ) {
  461.                             dst[k] = abs( dst[k] - src[k]);
  462.                         }
  463.                     }
  464.                     src += xyuv->i_width / div;
  465.                     dst += xyuv->overlay->pitches[0];
  466.                 }
  467.             }
  468.         } else {
  469.             for( i_plane = 0; i_plane < 3; i_plane++ ) {
  470.                 int div = i_plane == 0 ? 1 : 2;
  471.                 uint8_t *src = xyuv->pic;
  472.                 uint8_t *dst = xyuv->overlay->pixels[i_plane] +
  473.                                 ((xyuv->yuv[i].x + xyuv->yuv[i].y * xyuv->overlay->pitches[i_plane] ) / div );
  474.                 int w = xyuv->i_width / div;
  475.                 int j;
  476.                 if( i_plane == 1 ) {
  477.                     src +=  5*xyuv->i_width * xyuv->i_height/4;
  478.                 } else if( i_plane == 2 ) {
  479.                     src += xyuv->i_width * xyuv->i_height;
  480.                 }
  481.                 if( xyuv->i_join > 0 ) {
  482.                     if( i_picture > 1 ) {
  483.                         src += xyuv->i_join / div;
  484.                         dst += xyuv->i_join / div;
  485.                         w = (xyuv->i_width - xyuv->i_join) /div;
  486.                     } else {
  487.                         w = xyuv->i_join / div;
  488.                     }
  489.                 }
  490.                 for( j = 0; j < xyuv->i_height / div; j++ ) {
  491.                     memcpy( dst, src, w );
  492.                     src += xyuv->i_width / div;
  493.                     dst += xyuv->overlay->pitches[i_plane];
  494.                 }
  495.             }
  496.         }
  497.         SDL_UnlockYUVOverlay( xyuv->overlay );
  498.     }
  499.     if( xyuv->f_y != 0.0 ) {
  500.         uint8_t *pix = xyuv->overlay->pixels[0];
  501.         int j;
  502.         for( j = 0; j < xyuv->i_sdl_height; j++ ) {
  503.             int k;
  504.             for( k = 0; k < xyuv->i_sdl_width; k++ ) {
  505.                 int v= pix[k] * xyuv->f_y;
  506.                 if( v > 255 )
  507.                     pix[k] = 255;
  508.                 else if( v < 0 )
  509.                     pix[k] = 0;
  510.                 else
  511.                     pix[k] = v;
  512.             }
  513.             pix += xyuv->overlay->pitches[0];
  514.         }
  515.     }
  516.     if( xyuv->b_grid ) {
  517.         int x, y;
  518.         for( y = 0; y < xyuv->i_sdl_height; y += 4 ) {
  519.             uint8_t *p = xyuv->overlay->pixels[0] + y * xyuv->overlay->pitches[0];
  520.             for( x = 0; x < xyuv->i_sdl_width; x += 4 ) {
  521.                 if( x%16== 0 || y%16 == 0 )
  522.                     p[x] = 0;
  523.             }
  524.         }
  525.     }
  526.     /* Update display */
  527.     rect.x = 0;
  528.     rect.y = 0;
  529.     rect.w = xyuv->i_display_width;
  530.     rect.h = xyuv->i_display_height;
  531.     SDL_DisplayYUVOverlay( xyuv->overlay, &rect );
  532.     /* Display title */
  533.     if( xyuv->title )
  534.         free( xyuv->title );
  535.     asprintf( &xyuv->title, SDL_TITLE, xyuv->yuv[0].name, xyuv->i_frame, xyuv->i_frames, xyuv->f_fps );
  536.     SDL_WM_SetCaption( xyuv->title, "" );
  537. }
  538. static void xyuv_count_frames( xyuv_t *xyuv )
  539. {
  540.     int i;
  541.     xyuv->i_frames = 0;
  542.     if( xyuv->i_frame_size <= 0 )
  543.         return;
  544.     for( i = 0; i < xyuv->i_yuv; i++ ) {
  545.         /* Beurk but avoid using fstat */
  546.         fseek( xyuv->yuv[i].f, 0, SEEK_END );
  547.         xyuv->yuv[i].i_frames = ftell( xyuv->yuv[i].f ) / xyuv->i_frame_size;
  548.         fprintf( stderr, "count (%d) -> %dn", i, xyuv->yuv[i].i_frames );
  549.         fseek( xyuv->yuv[i].f, 0, SEEK_SET );
  550.         if( xyuv->i_frames < xyuv->yuv[i].i_frames )
  551.             xyuv->i_frames = xyuv->yuv[i].i_frames;
  552.     }
  553. }
  554. static inline int ssd( int a ) { return a*a; }
  555. static void xyuv_detect( int *pi_width, int *pi_height )
  556. {
  557.     static const int pi_size[][2] = {
  558.         {128, 96},
  559.         {160,120},
  560.         {320,244},
  561.         {320,288},
  562.         /* PAL */
  563.         {176,144},  // QCIF
  564.         {352,288},  // CIF
  565.         {352,576},  // 1/2 D1
  566.         {480,576},  // 2/3 D1
  567.         {544,576},
  568.         {640,576},  // VGA
  569.         {704,576},  // D1
  570.         {720,576},  // D1
  571.         /* NTSC */
  572.         {176,112},  // QCIF
  573.         {320,240},  // MPEG I
  574.         {352,240},  // CIF
  575.         {352,480},  // 1/2 D1
  576.         {480,480},  // 2/3 D1
  577.         {544,480},
  578.         {640,480},  // VGA
  579.         {704,480},  // D1
  580.         {720,480},  // D1
  581.         /* */
  582.         {0,0},
  583.     };
  584.     int i_max;
  585.     int i_size_max;
  586.     uint8_t *pic;
  587.     int i;
  588.     *pi_width = 0;
  589.     *pi_height = 0;
  590.     /* Compute size max */
  591.     for( i_max = 0, i_size_max = 0;
  592.             pi_size[i_max][0] != 0 && pi_size[i_max][1] != 0; i_max++ ) {
  593.         int s = pi_size[i_max][0] * pi_size[i_max][1] * 3 / 2;
  594.         if( i_size_max < s )
  595.             i_size_max = s;
  596.     }
  597.     /* Temporary buffer */
  598.     i_size_max *= 3;
  599.     pic = malloc( i_size_max );
  600.     fprintf( stderr, "guessing size for:n" );
  601.     for( i = 0; i < xyuv.i_yuv; i++ ) {
  602.         int j;
  603.         int i_read;
  604.         double dbest = 255*255;
  605.         int    i_best = i_max;
  606.         int64_t t;
  607.         fprintf( stderr, " - %sn", xyuv.yuv[i].name );
  608.         i_read = fread( pic, 1, i_size_max, xyuv.yuv[i].f );
  609.         if( i_read < 0 )
  610.             continue;
  611.         /* Check if file size is at least compatible with one format
  612.          * (if not, ignore file size)*/
  613.         fseek( xyuv.yuv[i].f, 0, SEEK_END );
  614.         t = ftell( xyuv.yuv[i].f );
  615.         fseek( xyuv.yuv[i].f, 0, SEEK_SET );
  616.         for( j = 0; j < i_max; j++ ) {
  617.             const int w = pi_size[j][0];
  618.             const int h = pi_size[j][1];
  619.             const int s = w * h * 3 / 2;
  620.             if( t % s == 0 )
  621.                 break;
  622.         }
  623.         if( j == i_max )
  624.             t = 0;
  625.         /* Try all size */
  626.         for( j = 0; j < i_max; j++ ) {
  627.             const int w = pi_size[j][0];
  628.             const int h = pi_size[j][1];
  629.             const int s = w * h * 3 / 2;
  630.             double dd;
  631.             int x, y, n;
  632.             int64_t d;
  633.             /* To small */
  634.             if( i_read < 3*s )
  635.                 continue;
  636.             /* Check file size */
  637.             if( ( t > 0 && (t % s) != 0  ) ) {
  638.                 fprintf( stderr, "  * %dx%d ignored (incompatible file size)n", w, h );
  639.                 continue;
  640.             }
  641.             /* We do a simple ssd between 2 consecutives lines */
  642.             d = 0;
  643.             for( n = 0; n < 3; n++ ) {
  644.                 uint8_t *p;
  645.                 /* Y */
  646.                 p = &pic[n*s];
  647.                 for( y = 0; y < h-1; y++ ) {
  648.                     for( x = 0; x < w; x++ )
  649.                         d += ssd( p[x] - p[w+x] );
  650.                     p += w;
  651.                 }
  652.                 /* U */
  653.                 p = &pic[n*s+w*h];
  654.                 for( y = 0; y < h/2-1; y++ ) {
  655.                     for( x = 0; x < w/2; x++ )
  656.                         d += ssd( p[x] - p[(w/2)+x] );
  657.                     p += w/2;
  658.                 }
  659.                 /* V */
  660.                 p = &pic[n*s+5*w*h/4];
  661.                 for( y = 0; y < h/2-1; y++ ) {
  662.                     for( x = 0; x < w/2; x++ )
  663.                         d += ssd( p[x] - p[(w/2)+x] );
  664.                     p += w/2;
  665.                 }
  666.             }
  667.             dd = (double)d / (3*w*h*3/2);
  668.             fprintf( stderr, "  * %dx%d d=%fn", w, h, dd );
  669.             if( dd < dbest ) {
  670.                 i_best = j;
  671.                 dbest = dd;
  672.             }
  673.         }
  674.         fseek( xyuv.yuv[i].f, 0, SEEK_SET );
  675.         if( i_best < i_max ) {
  676.             fprintf( stderr, "  -> %dx%dn", pi_size[i_best][0], pi_size[i_best][1] );
  677.             *pi_width = pi_size[i_best][0];
  678.             *pi_height = pi_size[i_best][1];
  679.         }
  680.     }
  681.     free( pic );
  682. }