From fd2c04ce6b3ea73301c0fa8376c3982352ad381d Mon Sep 17 00:00:00 2001 From: Nathan Caldwell Date: Mon, 19 Jan 2009 15:34:45 -0700 Subject: [PATCH] Handle multiple frames, and outdir. --- common.h | 4 +++ frameshot.c | 84 ++++++++++++++++++++++++++++++++++++++++++++----------------- input/y4m.c | 1 + utils.c | 12 +++++++++ utils.h | 1 + 5 files changed, 79 insertions(+), 23 deletions(-) diff --git a/common.h b/common.h index 643e7d3..e14e7cb 100644 --- a/common.h +++ b/common.h @@ -1,4 +1,6 @@ +#define MAX_FRAMES 1024 + typedef void *hnd_t; typedef struct @@ -22,4 +24,6 @@ typedef struct typedef struct { uint32_t i_width, i_height; + int i_frames; + uint32_t frames[MAX_FRAMES]; } config_t; diff --git a/frameshot.c b/frameshot.c index 099336e..6166a4d 100644 --- a/frameshot.c +++ b/frameshot.c @@ -1,16 +1,20 @@ +#include #include #include #include +#include +#include +#include +#include #include -#include -#include #define _GNU_SOURCE #include #include "common.h" +#include "utils.h" #include "output.h" #include "input.h" @@ -32,7 +36,8 @@ enum }; typedef struct { - hnd_t hout; + char *psz_outdir; + int i_zlevel; hnd_t hin; } cli_opt_t; @@ -76,7 +81,7 @@ static void show_help(void) " -h, --help Displays this message.\n" ); HELP( " -f, --frames Frames numbers to grab.\n" ); - HELP( " -o, --output Prefix to use for each output image.\n" ); + HELP( " -o, --outdir Output directory for images.\n" ); HELP( " -z, --compression Ammount of compression to use.\n" ); HELP( " -1, --fast Use fastest compression.\n" ); HELP( " -9, --best Use best (slowest) compression.\n" ); @@ -87,8 +92,9 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op { char *psz_filename = NULL; int i_zlevel = Z_DEFAULT_COMPRESSION; - char *psz; + char *psz, *psz_token; int b_y4m = 0; + struct stat sb; memset( opt, 0, sizeof(*opt) ); @@ -111,7 +117,7 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op { "best", no_argument, NULL, '9' }, { "frames", required_argument, NULL, 'f' }, { "help", no_argument, NULL, 'h' }, - { "output", required_argument, NULL, 'o' }, + { "outdir", required_argument, NULL, 'o' }, { "compression", required_argument, NULL, 'z' }, {0, 0, 0, 0} }; @@ -133,13 +139,40 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op i_zlevel = Z_BEST_COMPRESSION; break; case 'f': - + for( config->i_frames = 0; config->i_frames < MAX_FRAMES; config->i_frames++, optarg = NULL ) + { + psz_token = strtok(optarg, ","); + if( psz_token == NULL ) + break; + config->frames[config->i_frames] = atoi(psz_token); + } + qsort(config->frames, config->i_frames, sizeof(*config->frames), intcmp); + break; case 'o': + opt->psz_outdir = strdup(optarg); + if( stat( opt->psz_outdir, &sb ) < 0 ) + { + if( mkdir( opt->psz_outdir, S_IRWXU ) < 0 ) + { + fprintf( stderr, "ERROR: Unable to create output directory.\n" ); + perror("mkdir"); + return -1; + } + } else { + if( !S_ISDIR(sb.st_mode) ) + { + fprintf(stderr, "ERROR: Outdir exists, and is not a directory." ); + return -1; + } + } break; case 'z': - i_zlevel = atoi(optarg); - if( i_zlevel < 0 || i_zlevel > 9) - i_zlevel = Z_DEFAULT_COMPRESSION; + if( optarg == NULL || optarg[0] < '0' || optarg[0] > '9' ) + { + opt->i_zlevel = Z_DEFAULT_COMPRESSION; + break; + } + opt->i_zlevel = atoi(optarg); break; case 'h': default: @@ -151,7 +184,7 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op /* Get the input file name */ if( optind > argc - 1 ) { - fprintf( stderr, "[error]: No input file.\n" ); + fprintf( stderr, "ERROR: No input file.\n" ); show_help(); return -1; } @@ -161,14 +194,8 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op if( !strncasecmp( psz, ".y4m", 4 ) ) b_y4m = 1; - if( !opt->hout ) - { - char *psz_outname = strdup( psz_filename ); - char *psz_ext = strrchr( psz_outname, '.' ); - strcpy( psz_ext, ".png" ); - p_open_outfile( psz_outname, &opt->hout, i_zlevel ); - free(psz_outname); - } + if( !opt->psz_outdir ) + opt->psz_outdir = getcwd(NULL, 0); if( b_y4m ) { @@ -188,7 +215,10 @@ static int parse_options( int argc, char **argv, config_t *config, cli_opt_t *op static int grab_frames( config_t *config, cli_opt_t *opt ) { + hnd_t hout; picture_t pic; + int i; + char tmp[PATH_MAX]; pic.img.plane[0] = malloc(3 * config->i_width * config->i_height / 2); pic.img.plane[1] = pic.img.plane[0] + config->i_width * config->i_height; @@ -199,12 +229,20 @@ static int grab_frames( config_t *config, cli_opt_t *opt ) pic.img.i_stride[1] = pic.img.i_stride[2] = config->i_width / 2; pic.img.i_stride[3] = 0; - p_read_frame( opt->hin, &pic, 1 ); - - p_write_image( opt->hout, &pic, config ); + for(i = 0; i < config->i_frames; i++ ) + { + p_read_frame( opt->hin, &pic, config->frames[i] ); + + snprintf(tmp, PATH_MAX, "%s/%05d.png", opt->psz_outdir, config->frames[i]); + p_open_outfile( tmp, &hout, opt->i_zlevel ); + p_write_image( hout, &pic, config ); + p_close_outfile( hout ); + } p_close_infile( opt->hin ); - p_close_outfile( opt->hout ); + + if( opt->psz_outdir ) + free(opt->psz_outdir); return 0; } diff --git a/input/y4m.c b/input/y4m.c index 8f36e2f..b25f7d9 100644 --- a/input/y4m.c +++ b/input/y4m.c @@ -183,6 +183,7 @@ int read_frame_y4m( hnd_t handle, picture_t *p_pic, int i_frame ) || fread(p_pic->img.plane[2], 1, h->width * h->height / 4, h->fh) <= 0) return -1; + p_pic->i_pts = i_frame; h->next_frame = i_frame+1; return 0; diff --git a/utils.c b/utils.c index 95a1059..0208983 100644 --- a/utils.c +++ b/utils.c @@ -17,3 +17,15 @@ void reduce_fraction( int *n, int *d ) *n /= b; *d /= b; } + +int intcmp( const void *p1, const void *p2 ) +{ + int i1 = *(int *)p1; + int i2 = *(int *)p2; + if( i1 > i2 ) + return 1; + else if( i1 < i2 ) + return -1; + + return 0; +} diff --git a/utils.h b/utils.h index ab7988a..f2c7882 100644 --- a/utils.h +++ b/utils.h @@ -1,2 +1,3 @@ void reduce_fraction( int *n, int *d ); +int intcmp( const void *p1, const void *p2 ); -- 2.11.4.GIT