/* oqtencoder.c * Copyright (C) 2001 QT4Linux and OpenQuicktime Teams * * This file is part of OQTEncoder, a free video encoder using the OpenQuickTime * library. * * OQTEncoder is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation. * * OQTEncoder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #define OPTION_NUMBER_MAX 100 #define STRING_LENGTH_MAX 100 #define PROGRAM_NAME "oqtencoder" //#define PGM_HEADER_SIZE typedef struct { char option[STRING_LENGTH_MAX]; char value[STRING_LENGTH_MAX]; } codecoption_t; static FILE *input = NULL; static char videocodec[4] = { '3','I','V','1' }; static int64_t framenumber = -1; static float framerate = 25.0; static codecoption_t videooptions[OPTION_NUMBER_MAX]; static int videooptionnumber = 0; static int colormodel = BC_YUV420PACKED; static char *qtfilename = NULL; static FILE *output = NULL; static quicktime_t *qtout = NULL; static int width = -1; static int height = -1; static void showhelp() { printf("\nUsage: %s [OPTION] \n", PROGRAM_NAME); printf("\nOPTIONS:\n"); printf(" -i\tSpecify the input mode (default PGM on stdin)\n"); printf(" -V\tSets the video codec used (default [%c%c%c%c])\n", videocodec[0], videocodec[1], videocodec[2], videocodec[3]); // printf(" -f\tNumber of frames to encode (default all)\n"); printf(" -F\tSpecifies the framerate (default %f)\n", framerate); printf(" -v\tSpecifies an option to pass to the video codec\n"); printf(" -r\tSpecify the color model (default YUV420P)\n"); printf(" -H\tShows this help\n"); } static void splitoption(char*string, char*option, char*value) { int i = 0; if(!string || !option || !value) return; while(string[i] != '=' && i < strlen(string)) { i++; } if(string[i] =='=') { strncpy(option, string, i); strcpy(value, (&string[i+1])); } } static void close_properly(int sig) { if(qtout) quicktime_close(qtout); signal (sig, SIG_DFL); raise (sig); } int main(int argc, char** argv) { int i = 0; /* setting the input channel */ input = stdin; /* Setting q signal handler just to close properly our file */ signal (SIGINT, close_properly); while(1) { int c = -1; int option_index = 0; /* static struct option long_options[] = { { "input", required_argument, 0, 'i' }, { "videocodec", required_argument, 0, 'V' }, { "framenumber", required_argument, 0, 'f' }, { "framerate", required_argument, 0, 'F' }, { "videocodecoption", required_argument, 0, 'v' }, { "RGBmode", no_argument, 0, 'r' }, { "help", no_argument, 0, 'H' }, { NULL, 0, 0, 0 }}; c = getopt_long_only(argc, argv, "V;f;bF;v;rH", long_options, &option_index); */ c = getopt(argc, argv, "V:f:bF:v:rH"); if (c == -1) break; switch(c) { case 'i': // TO DO break; case 'V': printf("changing codec for %d\n", optarg); *(int32_t*)videocodec = *(int32_t*)optarg; break; case 'f': framenumber = atoi(optarg); break; case 'F': framerate = atof(optarg); break; case 'v': splitoption(optarg, videooptions[videooptionnumber].option, videooptions[videooptionnumber].value); videooptionnumber++; break; case 'r': colormodel = atoi(optarg); break; case 'H': showhelp(); exit(0); break; default: fprintf(stderr, "Unknown option specified %c\n", c); showhelp(); exit(1); } } /* check that there is our quicktime output file as well */ if ((argc - optind) < 1) { showhelp(); exit(1); } qtfilename = argv[optind++]; /* Here we go */ while(!feof(input)) { // char pgmheader[PGM_HEADER_SIZE]; static unsigned char *framebuffer = NULL; static unsigned char **rowbuffer = NULL; static int byteframesize = -1; static int qtcolormodel; /* read the pgm header */ fscanf(input, "P5\n\n%d %d\n255\n", &width, &height); height = height * 2 / 3; if(qtout == NULL) { /* Initialization */ if ( (qtout = quicktime_open(qtfilename, 1, 1) ) == NULL ) { fprintf(stderr, "%s: Cannot open output file.\n", PROGRAM_NAME); exit(1); } /* Setting the codec */ if(quicktime_set_video(qtout, 1, width, height, framerate, videocodec)) { printf("%s: Cannot set options for compressor %s\n", PROGRAM_NAME, videocodec); exit(1); } /* Setting now the codec option */ for(i = 0; i < videooptionnumber; i++) { char buff[STRING_LENGTH_MAX]; int type = quicktime_get_video_param(qtout, 0, videooptions[i].option, buff); int value_si; unsigned int value_ui; double value_d; switch(type) { case QUICKTIME_INTEGER_PARAMETER: value_si = atoi(videooptions[i].value); quicktime_set_video_param(qtout, 0, videooptions[i].option, &value_si); break; case QUICKTIME_UNSIGNED_INTEGER_PARAMETER: value_ui = atol(videooptions[i].value); quicktime_set_video_param(qtout, 0, videooptions[i].option, &value_ui); break; case QUICKTIME_BOOLEAN_PARAMETER: value_si = 0; if(strcmp(videooptions[i].value, "1") == 0 || strcmp(videooptions[i].value, "TRUE") == 0 || strcmp(videooptions[i].value, "true") == 0) value_si = 1; quicktime_set_video_param(qtout, 0, videooptions[i].option, &value_si); break; case QUICKTIME_STRING_PARAMETER: quicktime_set_video_param(qtout, 0, videooptions[i].option, videooptions[i].value); break; case QUICKTIME_DOUBLE_PARAMETER: value_d = atof(videooptions[i].value); quicktime_set_video_param(qtout, 0, videooptions[i].option, &value_d); break; case QUICKTIME_UNKNOWN_PARAMETER: fprintf(stderr, "Ignoring unknown parameter %s\n", videooptions[i].option); break; } } /* We allocate here the frame buffer ... max size to support all the color space */ framebuffer = (unsigned char*) malloc(width * height * 4); rowbuffer = (unsigned char**) malloc(height * sizeof(char*)); switch(colormodel) { case BC_YUV420P: case BC_YUV420PACKED: rowbuffer[0] = framebuffer; rowbuffer[1] = framebuffer + (height * width); rowbuffer[2] = framebuffer + (height * width * 5 / 4); byteframesize = height * width * 3 / 2; qtcolormodel = BC_YUV420P; break; case BC_RGB888: for(i = 0; i < height; i ++) rowbuffer[i]=framebuffer+(width*3*i); byteframesize = width * height * 3; qtcolormodel = colormodel; break; default: fprintf(stderr,"%s: Don't know this color model %d\n", PROGRAM_NAME, colormodel); exit(1); } } /* Reading frame from input */ switch(colormodel) { case BC_YUV420P: case BC_RGB888: if(fread(framebuffer, 1, byteframesize, input) != byteframesize) { fprintf(stderr, "%s: Cannot read frame from input.\n", PROGRAM_NAME); exit(1); } break; case BC_YUV420PACKED: fread (rowbuffer[0], width, height, input); for (i = 0; i < height >> 1; i++) { fread (rowbuffer[1]+i*width/2, width/2, 1, input); fread (rowbuffer[2]+i*width/2, width/2, 1, input); } break; } /* Hum ... compressing now */ quicktime_encode_video(qtout, qtcolormodel, rowbuffer, 0); } /* Time for closing our quicktime file */ quicktime_close(qtout); }