move variables into struct, add option to define format

This commit is contained in:
j 2010-05-02 18:25:32 +02:00
parent da8b1c5c75
commit fb83d36b65

135
oxframe.c
View file

@ -28,22 +28,21 @@
#include <Imlib2.h> #include <Imlib2.h>
static const char *output = NULL; typedef enum {
oxImageNotSet,
oxPNG,
oxJPG,
} oxImageFormat;
long frame_pos = 0, duration = 0; typedef struct _oxstate {
int image_width = -1, image_height = -1; const char *input;
const char *output;
const char *optstring = "h:x:y:p:i:o:"; oxImageFormat format;
struct option options [] = { long frame_pos;
{"help",required_argument,NULL,'h'}, long duration;
{"width",required_argument,NULL,'x'}, int image_width;
{"height",required_argument,NULL,'y'}, int image_height;
{"pos",required_argument,NULL,'p'}, } oxstate;
{"input",required_argument,NULL,'i'},
{"output",required_argument,NULL,'o'},
{NULL,0,NULL,0}
};
static void usage(void){ static void usage(void){
fprintf(stderr, fprintf(stderr,
@ -60,11 +59,14 @@ static void usage(void){
" -o OUTPUT, --output=OUTPUT\n" " -o OUTPUT, --output=OUTPUT\n"
" path to save frame to, jpg, png supported\n" " path to save frame to, jpg, png supported\n"
" (defaults to png)\n" " (defaults to png)\n"
" -f FORMAT, --output=FORMAT\n"
" output format, jpg or png\n"
" if not provided detected from output extension\n"
); );
exit(0); exit(0);
} }
void write_png_file(OggPlayRGBChannels *data) { void write_image_file(OggPlayRGBChannels *data, oxstate * state) {
Imlib_Image *frame = NULL, Imlib_Image *frame = NULL,
*image = NULL; *image = NULL;
@ -72,40 +74,40 @@ void write_png_file(OggPlayRGBChannels *data) {
frame = imlib_create_image_using_data(data->rgb_width, data->rgb_height, frame = imlib_create_image_using_data(data->rgb_width, data->rgb_height,
(unsigned int *)data->ptro); (unsigned int *)data->ptro);
if (image_width > 0 && image_height < 0) { if (state->image_width > 0 && state->image_height < 0) {
image_height = data->rgb_height * image_width / data->rgb_width; state->image_height = data->rgb_height * state->image_width / data->rgb_width;
} }
if (image_height > 0 && image_width < 0) { if (state->image_height > 0 && state->image_width < 0) {
image_width = data->rgb_width * image_height / data->rgb_height; state->image_width = data->rgb_width * state->image_height / data->rgb_height;
} }
if (image_width > 0) { if (state->image_width > 0) {
image = imlib_create_image(image_width, image_height); image = imlib_create_image(state->image_width, state->image_height);
imlib_context_set_image(image); imlib_context_set_image(image);
imlib_blend_image_onto_image(frame, 0, imlib_blend_image_onto_image(frame, 0,
0, 0, data->rgb_width, data->rgb_height, 0, 0, data->rgb_width, data->rgb_height,
0, 0, 0, 0,
image_width, image_height); state->image_width, state->image_height);
} else { } else {
imlib_context_set_image(frame); imlib_context_set_image(frame);
} }
if (strstr(&(output[strlen(output)-4]), ".jpg") == NULL) if(state->format == oxPNG)
imlib_image_set_format("png"); imlib_image_set_format("png");
else else
imlib_image_set_format("jpg"); imlib_image_set_format("jpg");
imlib_save_image(output); imlib_save_image(state->output);
imlib_free_image_and_decache(); imlib_free_image_and_decache();
imlib_context_set_image(frame); imlib_context_set_image(frame);
imlib_free_image_and_decache(); imlib_free_image_and_decache();
if (image_width > 0) { if (state->image_width > 0) {
imlib_context_set_image(image); imlib_context_set_image(image);
imlib_free_image_and_decache(); imlib_free_image_and_decache();
} }
} }
void write_frame (OggPlay * player, int track_num, void write_frame (OggPlay * player, int track_num,
OggPlayVideoData * video_data) { OggPlayVideoData * video_data, oxstate * state) {
OggPlayYUVChannels from; OggPlayYUVChannels from;
OggPlayRGBChannels to; OggPlayRGBChannels to;
@ -128,7 +130,7 @@ void write_frame (OggPlay * player, int track_num,
oggplay_yuv2bgra (&from, &to); oggplay_yuv2bgra (&from, &to);
write_png_file(&to); write_image_file(&to, state);
free(to.ptro); free(to.ptro);
} }
@ -139,6 +141,7 @@ int dump_frame_callback (OggPlay *player, int num_tracks,
OggPlayDataHeader ** headers; OggPlayDataHeader ** headers;
OggPlayVideoData * video_data; OggPlayVideoData * video_data;
OggPlayDataType type; OggPlayDataType type;
oxstate * state = (oxstate *)user;
for (i = 0; i < num_tracks; i++) { for (i = 0; i < num_tracks; i++) {
type = oggplay_callback_info_get_type(track_info[i]); type = oggplay_callback_info_get_type(track_info[i]);
@ -153,15 +156,14 @@ int dump_frame_callback (OggPlay *player, int num_tracks,
break; break;
} }
long pt = oggplay_callback_info_get_presentation_time(headers[0]); long pt = oggplay_callback_info_get_presentation_time(headers[0]);
//printf("time: %ld %ld %ld\n", pt, duration, duration-pt); //printf("time: %ld %ld %ld\n", pt, state->duration, state->duration-pt);
if (pt >= frame_pos) { if (pt >= state->frame_pos) {
video_data = oggplay_callback_info_get_video_data(headers[0]); video_data = oggplay_callback_info_get_video_data(headers[0]);
write_frame(player, i, video_data); write_frame(player, i, video_data, state);
exit(0); exit(0);
} else if (duration-pt < 500) { } else if (state->duration - pt < 500) {
video_data = oggplay_callback_info_get_video_data(headers[0]); video_data = oggplay_callback_info_get_video_data(headers[0]);
write_frame(player, i, video_data); write_frame(player, i, video_data, state);
} }
break; break;
@ -173,6 +175,16 @@ int dump_frame_callback (OggPlay *player, int num_tracks,
return 0; return 0;
} }
void init_state(oxstate *state) {
state->input = NULL;
state->output = NULL;
state->frame_pos = 0;
state->duration = 0;
state->image_width = -1;
state->image_height = -1;
state->format = oxImageNotSet;
}
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
int c,long_option_index; int c,long_option_index;
@ -183,6 +195,22 @@ int main (int argc, char * argv[]) {
int fps_denom = 1; int fps_denom = 1;
int granuleshift = 6; int granuleshift = 6;
long max_num, offset; long max_num, offset;
oxstate state;
const char *optstring = "h:x:y:p:i:o:f:";
struct option options [] = {
{"help",required_argument,NULL,'h'},
{"width",required_argument,NULL,'x'},
{"height",required_argument,NULL,'y'},
{"pos",required_argument,NULL,'p'},
{"input",required_argument,NULL,'i'},
{"output",required_argument,NULL,'o'},
{"format",required_argument,NULL,'f'},
{NULL,0,NULL,0}
};
init_state(&state);
while(1) { while(1) {
c=getopt_long(argc, argv, optstring, options, &long_option_index); c=getopt_long(argc, argv, optstring, options, &long_option_index);
@ -194,19 +222,25 @@ int main (int argc, char * argv[]) {
usage(); usage();
break; break;
case 'x': case 'x':
image_width = atoi(optarg); state.image_width = atoi(optarg);
break; break;
case 'y': case 'y':
image_height = atoi(optarg); state.image_height = atoi(optarg);
break; break;
case 'p': case 'p':
frame_pos = 1000 * atof(optarg); state.frame_pos = 1000 * atof(optarg);
break; break;
case 'i': case 'i':
reader = oggplay_file_reader_new(optarg); state.input = optarg;
reader = oggplay_file_reader_new(state.input);
break; break;
case 'o': case 'o':
output = optarg; state.output = optarg;
case 'f':
if (strstr(optarg, "jpg") == NULL)
state.format = oxPNG;
else
state.format = oxJPG;
break; break;
} }
} }
@ -215,8 +249,19 @@ int main (int argc, char * argv[]) {
usage(); usage();
} }
if(state.format == oxImageNotSet) {
if (strstr(&(state.output[strlen(state.output)-4]), ".jpg") == NULL)
state.format = oxPNG;
else
state.format = oxJPG;
}
player = oggplay_open_with_reader(reader); player = oggplay_open_with_reader(reader);
if (state.input == NULL) {
fprintf (stderr, "please provide input file\n");
exit (1);
}
if (player == NULL) { if (player == NULL) {
fprintf (stderr, "could not initialise oggplay with this file\n"); fprintf (stderr, "could not initialise oggplay with this file\n");
exit (1); exit (1);
@ -229,21 +274,23 @@ int main (int argc, char * argv[]) {
} }
oggplay_set_track_active(player, i); oggplay_set_track_active(player, i);
} }
oggplay_set_data_callback(player, dump_frame_callback, NULL); oggplay_set_data_callback(player, dump_frame_callback, &state);
max_num = 1 << granuleshift; max_num = 1 << granuleshift;
offset = (1000 * max_num * fps_denom) / fps_num; offset = (1000 * max_num * fps_denom) / fps_num;
duration = oggplay_get_duration(player); state.duration = oggplay_get_duration(player);
/*
if (frame_pos > duration) { if (frame_pos > duration) {
fprintf (stderr, "can not seek to frame later than duration\n"); fprintf (stderr, "can not seek to frame later than duration\n");
exit (1); exit (1);
} }
*/
if(frame_pos - offset > 0) { if(state.frame_pos - offset > 0) {
if (oggplay_seek(player, frame_pos - offset) == E_OGGPLAY_CANT_SEEK) { if (oggplay_seek(player, state.frame_pos - offset) == E_OGGPLAY_CANT_SEEK) {
fprintf (stderr, "failed to seeek to %ld\n", frame_pos); fprintf (stderr, "failed to seeek to %ld\n", state.frame_pos);
exit (1); exit (1);
} }
} }