int main(int argc, char *argv[]) { int error = 0; int frame_count = -1; char *row_pointers[3]; int do_audio = 0; int do_video = 0; int channels = 0; long afragment = 65536; float **audio_output; int layer = 0; int astream = 0; char input_path[1024]; char output_path[1024]; int i; long current_frame = 0; long current_sample = 0; pthread_mutex_init(&mutex, NULL); signal(SIGINT, trap_interrupt); input_path[0] = 0; output_path[0] = 0; if(argc < 3) { printf("Usage: %s [-a] [-v] <mpeg file> <output movie> [frame count]\n", argv[0]); exit(1); } for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-a")) { do_audio = 1; } else if(!strcmp(argv[i], "-v")) { do_video = 1; } else if(!input_path[0]) { strcpy(input_path, argv[i]); } else if(!output_path[0]) { strcpy(output_path, argv[i]); } else frame_count = atol(argv[i]); } //printf("main 1\n"); if(!(input = mpeg3_open(input_path, &error))) { exit(1); } //printf("main 1\n"); if(!(output = quicktime_open(output_path, 0, 1))) { exit(1); } //printf("main 1\n"); if(do_video) { if(!mpeg3_total_vstreams(input)) { do_video = 0; } else { quicktime_set_video(output, 1, mpeg3_video_width(input, layer), mpeg3_video_height(input, layer), mpeg3_frame_rate(input, layer), VIDEO_CODEC); quicktime_set_jpeg(output, 80, 0); } } //printf("main 1\n"); if(do_audio) { if(!mpeg3_total_astreams(input)) { do_audio = 0; } else { int i; channels = mpeg3_audio_channels(input, astream); quicktime_set_audio(output, channels, mpeg3_sample_rate(input, 0), 24, AUDIO_CODEC); audio_output = malloc(sizeof(float*) * channels); for(i = 0; i < channels; i++) audio_output[i] = malloc(sizeof(float) * afragment); } } //printf("main 1\n"); // quicktime_set_jpeg(output, 100, 0); // mpeg3_set_mmx(input, 0); while((!(do_video && mpeg3_end_of_video(input, layer)) || !(do_audio && mpeg3_end_of_audio(input, astream))) && (current_frame < frame_count || frame_count < 0)) { //printf("%d %d\n", mpeg3_end_of_video(input, layer), mpeg3_end_of_audio(input, astream)); if(do_audio) { if(!mpeg3_end_of_audio(input, astream)) { int fragment = afragment; int i, j, k; i = astream; k = 0; for(j = 0; j < mpeg3_audio_channels(input, i); j++, k++) { if(j == 0) mpeg3_read_audio(input, audio_output[k], /* Pointer to pre-allocated buffer of floats */ 0, /* Pointer to pre-allocated buffer of int16's */ j, /* Channel to decode */ fragment, /* Number of samples to decode */ i); else mpeg3_reread_audio(input, audio_output[k], /* Pointer to pre-allocated buffer of floats */ 0, /* Pointer to pre-allocated buffer of int16's */ j, /* Channel to decode */ fragment, /* Number of samples to decode */ i); } quicktime_encode_audio(output, 0, audio_output, fragment); current_sample += fragment; if(!do_video) { printf(" %d samples written\r", current_sample); fflush(stdout); } } else current_sample += afragment; } if(do_video) { if(!mpeg3_end_of_video(input, layer)) { int fragment; if(do_audio) fragment = (long)((double)current_sample / mpeg3_sample_rate(input, 0) * mpeg3_frame_rate(input, layer) - current_frame); else fragment = 1; for(i = 0; i < fragment && !mpeg3_end_of_video(input, layer); i++) { mpeg3_read_yuvframe_ptr(input, &row_pointers[0], &row_pointers[1], &row_pointers[2], layer); switch(mpeg3_colormodel(input, layer)) { case MPEG3_YUV420P: quicktime_set_cmodel(output, BC_YUV420P); break; case MPEG3_YUV422P: quicktime_set_cmodel(output, BC_YUV422P); break; } quicktime_encode_video(output, (unsigned char **)row_pointers, 0); current_frame++; printf(" %d frames written\r", current_frame); fflush(stdout); } } } } printf("main 2\n"); printf("\n"); quicktime_close(output); mpeg3_close(input); }
void write_frame() { int result = 0; int i; // Shift data into frame buffer frame_buffer_size = frame_end - buffer; memcpy(frame_buffer, buffer, frame_buffer_size); /* * if( * buffer[0] == 0xc2 && * buffer[1] == 0x5c && * buffer[2] == 0x43 && * buffer[3] == 0x49 && * buffer[4] == 0x95 && * buffer[5] == 0xc4 && * buffer[6] == 0xa6 && * buffer[7] == 0x2b) * printf("write_frame %d\n", __LINE__); */ // Shift input buffer buffer_size = end - frame_end; memcpy(buffer, frame_end, buffer_size); // Seek to end of this NAL ptr -= (frame_end - buffer); end = buffer + buffer_size; if(!frame_buffer_size) return; /* * static int debug_count = 0; * char string[1024]; * sprintf(string, "test%06d", debug_count++); * printf("write_frame %d: %s\n", __LINE__, string); * FILE *test = fopen(string, "w"); * fwrite(frame_buffer, frame_buffer_size, 1, test); * fclose(test); */ int got_picture = 0; AVFrame picture; // Skip frames until first keyframe /* * if(!bytes_written && !is_keyframe) * { * } * else */ if(pass == 0) { // Decode header only printf("write_frame %d pass=%d %d\n", __LINE__, pass, frame_buffer_size); /* * static FILE *test = 0; * if(!test) test = fopen("test", "w"); * fwrite(buffer, output_size, 1, test); */ avcodec_get_frame_defaults(&picture); avcodec_decode_video(decoder_context, &picture, &got_picture, buffer, frame_buffer_size); printf("write_frame %d %d\n", __LINE__, frame_buffer_size); if(decoder_context->width > 0) { video_width = decoder_context->width; video_height = decoder_context->height; video_frame_rate = (double)decoder_context->time_base.den / decoder_context->time_base.num / 2; got_header = 1; printf("%s format:\nwidth=%d\nheight=%d\nframerate=%f\naudio_track=%d\nsamplerate=%d\nchannels=%d\n", in_path, video_width, video_height, video_frame_rate, audio_track, audio_samplerate, audio_channels); } } else { /* * printf("write_frame: %s at offset %llx\n", * is_keyframe ? "Keyframe" : "Frame", * bytes_written); */ if(!quicktime_fd) { quicktime_fd = quicktime_open(out_path, 0, 1); if(!quicktime_fd) { fprintf(stderr, "write_frame: Failed to open %s for writing\n", out_path); exit(1); } #ifdef ENCODE_AUDIO quicktime_set_audio(quicktime_fd, audio_channels, audio_samplerate, 16, QUICKTIME_MP4A); quicktime_set_parameter(quicktime_fd, "mp4a_bitrate", &audio_bitrate); #endif quicktime_set_video(quicktime_fd, 1, video_width, video_height, video_frame_rate, QUICKTIME_H264); } // Convert NAL codes to AVC format unsigned char *ptr2 = frame_buffer + NAL_CODE_SIZE; unsigned char *end2 = frame_buffer + frame_buffer_size; unsigned char *last_start = frame_buffer; int nal_size; int total_nals = 1; while(ptr2 < end2 + NAL_CODE_SIZE) { // Start of next NAL code if(ptr2[0] == 0x00 && ptr2[1] == 0x00 && ptr2[2] == 0x00 && ptr2[3] == 0x01) { nal_size = ptr2 - last_start - 4; last_start[0] = (nal_size & 0xff000000) >> 24; last_start[1] = (nal_size & 0xff0000) >> 16; last_start[2] = (nal_size & 0xff00) >> 8; last_start[3] = (nal_size & 0xff); last_start = ptr2; ptr2 += 4; total_nals++; } else ptr2++; }
int cmdline_main (int argc, char *argv[]) { guchar *output; int num_frames = 1; #ifdef MOVIES int generate_movie = 0; quicktime_t *output_movie; guchar **rows; #endif int antialiasing = 0, supersampling = 0; int img_width, img_height; char *generator = 0; userval_info_t *userval_info; int num_input_drawables = 0; gboolean size_is_set = FALSE; char *script = NULL; char *output_filename; gboolean htmldoc = FALSE; define_t *defines = NULL; int bench_render_count = 1; int render_num; gboolean bench_no_output = FALSE; gboolean bench_no_backend = FALSE; int compile_time_limit = DEFAULT_OPTIMIZATION_TIMEOUT; for (;;) { static struct option long_options[] = { { "version", no_argument, 0, OPTION_VERSION }, { "help", no_argument, 0, OPTION_HELP }, { "intersampling", no_argument, 0, 'i' }, { "oversampling", no_argument, 0, 'o' }, { "cache", required_argument, 0, 'c' }, { "generator", required_argument, 0, 'g' }, { "size", required_argument, 0, 's' }, { "script-file", required_argument, 0, 'f' }, { "htmldoc", no_argument, 0, OPTION_HTMLDOC }, { "bench-no-output", no_argument, 0, OPTION_BENCH_NO_OUTPUT }, { "bench-only-compile", no_argument, 0, OPTION_BENCH_ONLY_COMPILE }, { "bench-no-compile-time-limit", no_argument, 0, OPTION_BENCH_NO_COMPILE_TIME_LIMIT }, { "bench-no-backend", no_argument, 0, OPTION_BENCH_NO_BACKEND }, { "bench-render-count", required_argument, 0, OPTION_BENCH_RENDER_COUNT }, #ifdef MOVIES { "frames", required_argument, 0, 'F' }, { "movie", required_argument, 0, 'M' }, #endif { 0, 0, 0, 0 } }; int option, option_index; option = getopt_long(argc, argv, #ifdef MOVIES "f:ioF:D:M:c:g:s:", #else "f:ioD:c:g:s:", #endif long_options, &option_index); if (option == -1) break; switch (option) { case OPTION_VERSION : printf("MathMap " MATHMAP_VERSION "\n" "\n" "Copyright (C) 1997-2009 Mark Probst\n" "\n" "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); return 0; case OPTION_HELP : usage(); return 0; case OPTION_HTMLDOC : htmldoc = TRUE; break; case 'f' : if (!g_file_get_contents(optarg, &script, NULL, NULL)) { fprintf(stderr, _("Error: The script file `%s' could not be read.\n"), optarg); return 1; } break; case 'i' : antialiasing = 1; break; case 'o' : supersampling = 1; break; case 'c' : cache_size = atoi(optarg); assert(cache_size > 0); break; case 'D' : append_define(optarg, &defines); break; case 'I' : alloc_cmdline_image_input_drawable(optarg); break; case 'g' : generator = optarg; break; case 's' : if (!parse_image_size(optarg, &img_width, &img_height)) { fprintf(stderr, _("Error: Invalid image size. Syntax is <width>x<height>. Example: 1024x768.\n")); exit(1); } size_is_set = 1; break; case OPTION_BENCH_RENDER_COUNT : bench_render_count = atoi(optarg); break; case OPTION_BENCH_ONLY_COMPILE : bench_render_count = 0; break; case OPTION_BENCH_NO_OUTPUT : bench_no_output = TRUE; break; case OPTION_BENCH_NO_COMPILE_TIME_LIMIT : compile_time_limit = -1; break; case OPTION_BENCH_NO_BACKEND : bench_no_backend = TRUE; break; #ifdef MOVIES case 'F' : generate_movie = 1; num_frames = atoi(optarg); assert(num_frames > 0); break; case 'M' : alloc_cmdline_movie_input_drawable(optarg); break; #endif } } if (script != NULL) { if (argc - optind != 1) { usage(); return 1; } output_filename = argv[optind]; } else { if (argc - optind != 2) { usage(); return 1; } script = argv[optind]; output_filename = argv[optind + 1]; } init_tags(); init_builtins(); init_macros(); init_compiler(); if (htmldoc) { mathmap_t *mathmap = parse_mathmap(script); filter_t *filter; FILE *out; if (mathmap == NULL) { fprintf(stderr, _("Error: Could not read MathMap script: %s\n"), error_string); return 1; } out = fopen(output_filename, "w"); if (out == NULL) { fprintf(stderr, _("Error: Cannot open file `%s' for writing: %s\n"), output_filename, strerror(errno)); return 1; } for (filter = mathmap->filters; filter != NULL; filter = filter->next) { if (filter->kind != FILTER_MATHMAP) continue; if (!write_filter_html_doc(out, filter->v.mathmap.decl)) return 1; } fclose(out); } else if (generator == 0) { char *support_paths[4]; mathmap_t *mathmap; mathmap_invocation_t *invocation; int current_frame; support_paths[0] = g_strdup_printf("%s/mathmap", GIMPDATADIR); support_paths[1] = g_strdup_printf("%s/.gimp-2.6/mathmap", getenv("HOME")); support_paths[2] = g_strdup_printf("%s/.gimp-2.4/mathmap", getenv("HOME")); support_paths[3] = NULL; mathmap = compile_mathmap(script, support_paths, compile_time_limit, bench_no_backend); if (bench_no_backend) return 0; if (mathmap == 0) { fprintf(stderr, _("Error: %s\n"), error_string); exit(1); } if (bench_render_count == 0) return 0; if (!size_is_set) for (userval_info = mathmap->main_filter->userval_infos; userval_info != NULL; userval_info = userval_info->next) { define_t *define; unsigned char *image; if (userval_info->type != USERVAL_IMAGE) continue; define = lookup_define(defines, userval_info->name); if (define == NULL) { fprintf(stderr, _("Error: No value defined for input image `%s'.\n"), userval_info->name); return 1; } image = read_image(define->value, &img_width, &img_height); if (image == NULL) { fprintf(stderr, _("Error: Could not read input image `%s'.\n"), define->value); return 1; } free(image); size_is_set = TRUE; break; } if (!size_is_set) { fprintf(stderr, _("Error: Image size not set and no input images given.\n")); exit(1); } invocation = invoke_mathmap(mathmap, NULL, img_width, img_height, TRUE); for (userval_info = mathmap->main_filter->userval_infos; userval_info != NULL; userval_info = userval_info->next) { userval_t *userval = &invocation->uservals[userval_info->index]; define_t *define = lookup_define(defines, userval_info->name); if (define == NULL) { if (userval_info->type == USERVAL_IMAGE) { fprintf(stderr, _("Error: No value defined for input image `%s'.\n"), userval_info->name); return 1; } } else switch (userval_info->type) { case USERVAL_INT_CONST : userval->v.int_const = atoi(define->value); break; case USERVAL_FLOAT_CONST : userval->v.float_const = g_ascii_strtod(define->value, NULL); break; case USERVAL_BOOL_CONST : userval->v.bool_const = (float)atoi(define->value); break; case USERVAL_IMAGE : assign_image_userval_drawable(userval_info, userval, alloc_cmdline_image_input_drawable(define->value)); ++num_input_drawables; break; default : fprintf(stderr, _("Error: Can only define user values for types int, float, bool and image.\n")); return 1; } } for (render_num = 0; render_num < bench_render_count; ++render_num) { #ifdef MOVIES for (i = 0; i < num_input_drawables; ++i) if (input_drawables[i].type == DRAWABLE_MOVIE) { assert(quicktime_video_width(input_drawables[i].v.movie, 0) == img_width); assert(quicktime_video_height(input_drawables[i].v.movie, 0) == img_height); } #endif invocation_set_antialiasing(invocation, antialiasing); invocation->supersampling = supersampling; invocation->output_bpp = 4; output = (guchar*)malloc((long)invocation->output_bpp * (long)img_width * (long)img_height); assert(output != 0); #ifdef MOVIES if (generate_movie) { output_movie = quicktime_open(output_filename, 0, 1); assert(output_movie != 0); quicktime_set_video(output_movie, 1, img_width, img_height, 25, QUICKTIME_JPEG); assert(quicktime_supported_video(output_movie, 0)); quicktime_seek_start(output_movie); rows = (guchar**)malloc(sizeof(guchar*) * img_height); for (i = 0; i < img_height; ++i) rows[i] = output + img_width * invocation->output_bpp * i; } #endif for (current_frame = 0; current_frame < num_frames; ++current_frame) { float current_t = (float)current_frame / (float)num_frames; image_t *closure = closure_image_alloc(&invocation->mathfuncs, NULL, invocation->mathmap->main_filter->num_uservals, invocation->uservals, img_width, img_height); mathmap_frame_t *frame = invocation_new_frame(invocation, closure, current_frame, current_t); call_invocation_parallel_and_join(frame, closure, 0, 0, img_width, img_height, output, 1); invocation_free_frame(frame); #ifdef MOVIES if (generate_movie && !bench_no_output) { fprintf(stderr, _("writing frame %d\n"), current_frame); assert(quicktime_encode_video(output_movie, rows, 0) == 0); } #endif closure_image_free(closure); } if (!bench_no_output) { #ifdef MOVIES if (generate_movie) quicktime_close(output_movie); else #endif write_image(output_filename, img_width, img_height, output, invocation->output_bpp, img_width * invocation->output_bpp, IMAGE_FORMAT_PNG); } free(output); } } else { if (strcmp(generator, "blender") == 0) { if (!blender_generate_plug_in(script, output_filename)) return 1; } /* else if (strcmp(generator, "pixeltree") == 0) { if (!pixeltree_generate_plug_in(argv[optind], argv[optind + 1])) return 1; } */ else { fprintf(stderr, _("Unknown generator `%s'\n"), generator); return 1; } } return 0; }