move variables into struct, add option to define format
This commit is contained in:
parent
da8b1c5c75
commit
fb83d36b65
1 changed files with 91 additions and 44 deletions
135
oxframe.c
135
oxframe.c
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue