xyuv.c
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:25k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

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