For last few days I was trying to learn ffmpeg and libtheora API. In the process, I have modified ffmpeg2theora code to include support for start time and end time. ffmpeg2theora -s 60 -e 130 file.avi will produce file.ogg which will be from 60th to 130th second of input file (something like -ss and -endpos in mencoder). This is a useful feature for someone who wants to cut a part of video and encode it using theora. I am attaching modified ffmpeg2theora.c. Just place this file in file from http://www.v2v.cc/~j/ffmpeg2theora/ -- Nilesh Bansal http://www.cse.iitb.ac.in/nilesh/ -------------- next part -------------- /* * ffmpeg2theora.c -- Convert ffmpeg supported a/v files to Ogg Theora * Copyright (C) 2003-2004 <j@v2v.cc> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU 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 "common.h" #include "avformat.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <getopt.h> #include "theora/theora.h" #include "vorbis/codec.h" #include "vorbis/vorbisenc.h" #include "theorautils.h" static double rint(double x) { if (x < 0.0) return (double)(int)(x - 0.5); else return (double)(int)(x + 0.5); } theoraframes_info info; static int using_stdin = 0; typedef struct ff2theora{ AVFormatContext *context; int video_index; int audio_index; int deinterlace; int sample_rate; int channels; int disable_audio; float audio_quality; int output_width; int output_height; double fps; ImgReSampleContext *img_resample_ctx; /* for image resampling/resizing */ ReSampleContext *audio_resample_ctx; ogg_uint32_t aspect_numerator; ogg_uint32_t aspect_denominator; double frame_aspect; int video_quality; /* cropping */ int frame_topBand; int frame_bottomBand; int frame_leftBand; int frame_rightBand; int video_x; int video_y; int frame_x_offset; int frame_y_offset; int start_time; /* In seconds */ int end_time; /* In seconds */ } *ff2theora; /** * Allocate and initialise an AVFrame. */ AVFrame *alloc_picture (int pix_fmt, int width, int height){ AVFrame *picture; uint8_t *picture_buf; int size; picture = avcodec_alloc_frame (); if (!picture) return NULL; size = avpicture_get_size (pix_fmt, width, height); picture_buf = av_malloc (size); if (!picture_buf){ av_free (picture); return NULL; } avpicture_fill ((AVPicture *) picture, picture_buf, pix_fmt, width, height); return picture; } /** * initialize ff2theora with default values * @return ff2theora struct */ ff2theora ff2theora_init (){ ff2theora this = calloc (1, sizeof (*this)); if (this != NULL){ this->disable_audio=0; this->video_index = -1; this->audio_index = -1; this->sample_rate = 44100; // samplerate hmhmhm this->channels = 2; this->output_width=0; // set to 0 to not resize the output this->output_height=0; // set to 0 to not resize the output this->video_quality=31.5; // video quality 5 this->audio_quality=0.297;// audio quality 3 this->aspect_numerator=0; this->aspect_denominator=0; this->frame_aspect=0; this->deinterlace=1; this->frame_topBand=0; this->frame_bottomBand=0; this->frame_leftBand=0; this->frame_rightBand=0; this->start_time=0; this->end_time=0; /* ZERO denotes no end time set */ } return this; } void ff2theora_output(ff2theora this) { int i; AVCodecContext *aenc = NULL; AVCodecContext *venc = NULL; AVStream *astream = NULL; AVStream *vstream = NULL; AVCodec *acodec = NULL; AVCodec *vcodec = NULL; AVIndexEntry * index_entry; float frame_aspect; int frame_number=0; double fps = 0.0; for (i = 0; i < this->context->nb_streams; i++){ AVCodecContext *enc = &this->context->streams[i]->codec; switch (enc->codec_type){ case CODEC_TYPE_VIDEO: if (this->video_index < 0) this->video_index = i; break; case CODEC_TYPE_AUDIO: if (this->audio_index < 0 && !this->disable_audio) this->audio_index = i; break; default: break; } } if (this->video_index >= 0){ vstream = this->context->streams[this->video_index]; venc = &this->context->streams[this->video_index]->codec; vcodec = avcodec_find_decoder (venc->codec_id); fps = (double) venc->frame_rate / venc->frame_rate_base; if (fps > 10000) fps /= 1000; if (vcodec == NULL || avcodec_open (venc, vcodec) < 0) this->video_index = -1; this->fps = fps; if(info.preset == V2V_PRESET_PREVIEW){ // possible sizes 384/288,320/240 int pal_width=384; int pal_height=288; int ntsc_width=320; int ntsc_height=240; if(this->fps==25 && (venc->width!=pal_width || venc->height!=pal_height) ){ this->output_width=pal_width; this->output_height=pal_height; } else if(abs(this->fps-30)<1 && (venc->width!=ntsc_width || venc->height!=ntsc_height) ){ this->output_width=ntsc_width; this->output_height=ntsc_height; } } else if(info.preset == V2V_PRESET_PRO){ if(this->fps==25 && (venc->width!=720 || venc->height!=576) ){ this->output_width=720; this->output_height=576; } else if(abs(this->fps-30)<1 && (venc->width!=720 || venc->height!=480) ){ this->output_width=720; this->output_height=480; } } if (this->deinterlace==1) fprintf(stderr," Deinterlace: on\n"); else fprintf(stderr," Deinterlace: off\n"); if(this->output_height==0 && (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){ this->output_height=venc->height- this->frame_topBand-this->frame_bottomBand; } if(this->output_width==0 && (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){ this->output_width=venc->width- this->frame_leftBand-this->frame_rightBand; } //so frame_aspect is set on the commandline if(this->frame_aspect!=0){ if(this->output_height){ this->aspect_numerator=10000*this->frame_aspect*this->output_height; this->aspect_denominator=10000*this->output_width; } else{ this->aspect_numerator=10000*this->frame_aspect*venc->height; this->aspect_denominator=10000*venc->width; } av_reduce(&this->aspect_numerator,&this->aspect_denominator,this->aspect_numerator,this->aspect_denominator,10000); frame_aspect=this->frame_aspect; } if(venc->sample_aspect_ratio.num!=0 && this->frame_aspect==0){ // just use the ratio from the input this->aspect_numerator=venc->sample_aspect_ratio.num; this->aspect_denominator=venc->sample_aspect_ratio.den; // or we use ratio for the output if(this->output_height){ int width=venc->width-this->frame_leftBand-this->frame_rightBand; int height=venc->height-this->frame_topBand-this->frame_bottomBand; av_reduce(&this->aspect_numerator,&this->aspect_denominator, venc->sample_aspect_ratio.num*width*this->output_height, venc->sample_aspect_ratio.den*height*this->output_width,10000); frame_aspect=(float)(this->aspect_numerator*this->output_width)/ (this->aspect_denominator*this->output_height); } else{ frame_aspect=(float)(this->aspect_numerator*venc->width)/ (this->aspect_denominator*venc->height); } } if(this->aspect_denominator && frame_aspect){ //fprintf(stderr," Pixel Aspect Ratio: %d/%d ",this->aspect_numerator,this->aspect_denominator); fprintf(stderr," Pixel Aspect Ratio: %.2f/1 ",(float)this->aspect_numerator/this->aspect_denominator); fprintf(stderr," Frame Aspect Ratio: %.2f/1\n",frame_aspect); } /* Theora has a divisible-by-sixteen restriction for the encoded video size */ /* scale the frame size up to the nearest /16 and calculate offsets */ this->video_x=((this->output_width + 15) >>4)<<4; this->video_y=((this->output_height + 15) >>4)<<4; this->frame_x_offset=(this->video_x-this->output_width); this->frame_y_offset=(this->video_y-this->output_height); if(this->video_x>0 || this->video_y>0){ // we might need that for values other than /16? int frame_padtop=0, frame_padbottom=0; int frame_padleft=0, frame_padright=0; frame_padbottom=this->frame_x_offset; frame_padleft=this->frame_y_offset; this->img_resample_ctx = img_resample_full_init( //this->output_width, this->output_height, this->video_x, this->video_y, venc->width, venc->height, this->frame_topBand, this->frame_bottomBand, this->frame_leftBand, this->frame_rightBand, frame_padtop, frame_padbottom, frame_padleft, frame_padright ); fprintf(stderr," Resize: %dx%d",venc->width,venc->height); if(this->frame_topBand || this->frame_bottomBand || this->frame_leftBand || this->frame_rightBand){ fprintf(stderr," => %dx%d",venc->width-this->frame_leftBand- this->frame_rightBand,venc->height-this->frame_topBand-this->frame_bottomBand); } if(this->output_width!=(venc->width-this->frame_leftBand-this->frame_rightBand) || this->output_height!=(venc->height-this->frame_topBand-this->frame_bottomBand)) fprintf(stderr," => %dx%d",this->output_width,this->output_height); fprintf(stderr,"\n"); } else{ this->video_x = venc->width; this->video_y = venc->height; this->output_height=venc->height; this->output_width=venc->width; } } if (this->audio_index >= 0){ astream = this->context->streams[this->audio_index]; aenc = &this->context->streams[this->audio_index]->codec; acodec = avcodec_find_decoder (aenc->codec_id); if (this->channels != aenc->channels && aenc->codec_id == CODEC_ID_AC3) aenc->channels = this->channels; if (acodec != NULL && avcodec_open (aenc, acodec) >= 0){ if(this->sample_rate!=aenc->sample_rate || this->channels!=aenc->channels){ this->audio_resample_ctx = audio_resample_init (this->channels,aenc->channels,this->sample_rate,aenc->sample_rate); if(this->sample_rate!=aenc->sample_rate) fprintf(stderr," Resample: %dHz => %dHz\n",aenc->sample_rate,this->sample_rate); if(this->channels!=aenc->channels) fprintf(stderr," Channels: %d => %d\n",aenc->channels,this->channels); } else{ this->audio_resample_ctx=NULL; } } else{ this->audio_index = -1; } } if (this->video_index >= 0 || this->audio_index >=0){ AVFrame *frame=NULL; AVFrame *frame_tmp=NULL; AVFrame *output=NULL; AVFrame *output_tmp=NULL; AVFrame *output_resized=NULL; AVFrame *output_buffered=NULL; AVPacket pkt; int len; int len1; int got_picture; int first = 1; int e_o_s=0; int ret; uint8_t *ptr; int16_t *audio_buf= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE); int16_t *resampled= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE); if(this->video_index >= 0) info.audio_only=0; else info.audio_only=1; if(this->audio_index>=0) info.video_only=0; else info.video_only=1; if(!info.audio_only){ frame = alloc_picture(vstream->codec.pix_fmt, vstream->codec.width,vstream->codec.height); frame_tmp = alloc_picture(vstream->codec.pix_fmt, vstream->codec.width,vstream->codec.height); output_tmp =alloc_picture(PIX_FMT_YUV420P, vstream->codec.width,vstream->codec.height); output =alloc_picture(PIX_FMT_YUV420P, vstream->codec.width,vstream->codec.height); output_resized =alloc_picture(PIX_FMT_YUV420P, this->video_x, this->video_y); //this->output_width,this->output_height); output_buffered =alloc_picture(PIX_FMT_YUV420P, this->video_x, this->video_y); //this->output_width,this->output_height); } if(!info.audio_only){ /* video settings here */ /* config file? commandline options? v2v presets? */ theora_info_init (&info.ti); info.ti.width = this->video_x; info.ti.height = this->video_y; info.ti.frame_width = this->output_width; info.ti.frame_height = this->output_height; info.ti.offset_x = this->frame_x_offset; info.ti.offset_y = this->frame_y_offset; // FIXED: looks like ffmpeg uses num and denum for fps too // venc->frame_rate / venc->frame_rate_base; //info.ti.fps_numerator = 1000000 * (this->fps); /* fps= numerator/denominator */ //info.ti.fps_denominator = 1000000; info.ti.fps_numerator=venc->frame_rate; info.ti.fps_denominator = venc->frame_rate_base; /* this is pixel aspect ratio */ info.ti.aspect_numerator=this->aspect_numerator; info.ti.aspect_denominator=this->aspect_denominator; // FIXME: is all input material with fps==25 OC_CS_ITU_REC_470BG? // guess not, commandline option to select colorspace would be the best. if(this->fps==25) info.ti.colorspace = OC_CS_ITU_REC_470BG; else if(abs(this->fps-30)<1) info.ti.colorspace = OC_CS_ITU_REC_470M; else info.ti.colorspace = OC_CS_UNSPECIFIED; //FIXME: allow target_bitrate as an alternative mode //only use quality mode for now. //info.ti.target_bitrate=1200; info.ti.quality = this->video_quality; info.ti.dropframes_p = 0; info.ti.quick_p = 1; info.ti.keyframe_auto_p = 1; info.ti.keyframe_frequency = 64; info.ti.keyframe_frequency_force = 64; //info.ti.keyframe_data_target_bitrate = info.ti.target_bitrate * 1.5; info.ti.keyframe_auto_threshold = 80; info.ti.keyframe_mindistance = 8; info.ti.noise_sensitivity = 1; // range 0-2, 0 sharp, 2 less sharp,less bandwidth if(info.preset == V2V_PRESET_PREVIEW) info.ti.sharpness=2; } /* audio settings here */ info.channels = this->channels; info.sample_rate = this->sample_rate; info.vorbis_quality = this->audio_quality; theoraframes_init (); printf("AV time base %i\n", AV_TIME_BASE); av_seek_frame( this->context, -1, (int64_t)AV_TIME_BASE*this->start_time, 1); /* main decoding loop */ int no_frames = fps*(this->end_time - this->start_time); if(no_frames < 0){ printf("Error -- end time < start time\n"); exit(1); } do{ if(no_frames > 0){ // printf("%i \n",frame_number); if(frame_number > no_frames){ printf("\nTime to break\n"); break; } } ret = av_read_frame(this->context,&pkt); if(ret<0){ e_o_s=1; } ptr = pkt.data; len = pkt.size; if (e_o_s && !info.audio_only || (ret >= 0 && pkt.stream_index == this->video_index)){ if(len == 0 && !first && !e_o_s){ fprintf (stderr, "no frame available\n"); } while(e_o_s || len > 0){ if(len >0 && (len1 = avcodec_decode_video(&vstream->codec, frame,&got_picture, ptr, len))>0) { //FIXME: move image resize/deinterlace/colorformat transformation // into seperate function if(got_picture){ frame_number++; //For audio only files command line option "-e" will not work //as we donot increment frame_number in audio section. //FIXME: better colorformat transformation to YUV420P /* might have to cast other progressive formats here */ //if(venc->pix_fmt != PIX_FMT_YUV420P){ img_convert((AVPicture *)output,PIX_FMT_YUV420P, (AVPicture *)frame,venc->pix_fmt, venc->width,venc->height); if(this->deinterlace){ if(avpicture_deinterlace((AVPicture *)output_tmp, (AVPicture *)output,PIX_FMT_YUV420P, venc->width,venc->height)<0){ output_tmp=output; } } else output_tmp=output; //} //else{ /* there must be better way to do this, it seems to work like this though */ /* if(frame->linesize[0] != vstream->codec.width){ img_convert((AVPicture *)output_tmp,PIX_FMT_YUV420P, (AVPicture *)frame,venc->pix_fmt,venc->width,venc->height); } else{ output_tmp=frame; } } */ // now output_tmp if(this->img_resample_ctx){ img_resample(this->img_resample_ctx, (AVPicture *)output_resized, (AVPicture *)output_tmp); } else{ output_resized=output_tmp; } } ptr += len1; len -= len1; } first=0; //now output_resized if(theoraframes_add_video(output_resized->data[0], this->video_x,this->video_y,output_resized->linesize[0],e_o_s)){ ret = -1; fprintf (stderr,"No theora frames available\n"); break; } if(e_o_s){ break; } } } if(e_o_s && !info.video_only || (ret >= 0 && pkt.stream_index == this->audio_index)){ while(e_o_s || len > 0 ){ int samples=0; int samples_out=0; int data_size; if(len > 0){ len1 = avcodec_decode_audio(&astream->codec, audio_buf,&data_size, ptr, len); if (len1 < 0){ /* if error, we skip the frame */ break; } len -= len1; ptr += len1; if(data_size >0){ samples =data_size / (aenc->channels * 2); samples_out = samples; if(this->audio_resample_ctx){ samples_out = audio_resample(this->audio_resample_ctx, resampled, audio_buf, samples); } else resampled=audio_buf; } } if (theoraframes_add_audio(resampled, samples_out *(this->channels),samples_out,e_o_s)){ ret = -1; fprintf (stderr,"No audio frames available\n"); } if(e_o_s && len <= 0){ break; } } } /* flush out the file */ theoraframes_flush (e_o_s); av_free_packet (&pkt); } while (ret >= 0); if(audio_buf){ if(audio_buf!=resampled) av_free(resampled); av_free(audio_buf); } if (this->img_resample_ctx) img_resample_close(this->img_resample_ctx); if (this->audio_resample_ctx) audio_resample_close(this->audio_resample_ctx); theoraframes_close (); } else{ fprintf (stderr, "No video or audio stream found\n"); } } void ff2theora_close (ff2theora this){ /* clear out state */ av_free (this); } double aspect_check(const char *arg) { int x = 0, y = 0; double ar = 0; const char *p; p = strchr(arg, ':'); if (p) { x = strtol(arg, (char **)&arg, 10); if (arg == p) y = strtol(arg+1, (char **)&arg, 10); if (x > 0 && y > 0) ar = (double)x / (double)y; } else ar = strtod(arg, (char **)&arg); if (!ar) { fprintf(stderr, "Incorrect aspect ratio specification.\n"); exit(1); } return ar; } int crop_check(ff2theora this, char *name, const char *arg) { int crop_value = atoi(arg); if (crop_value < 0) { fprintf(stderr, "Incorrect %s crop size\n",name); exit(1); } if ((crop_value % 2) != 0) { fprintf(stderr, "%s crop size must be a multiple of 2\n",name); exit(1); } /* if ((crop_value) >= this->height){ fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); exit(1); } */ return crop_value; } void print_presets_info() { fprintf (stderr, // "v2v presets - more info at http://wiki.v2v.cc/presets" "v2v presets\n" "preview\t\thalf size DV video. encoded with Ogg Theora/Ogg Vorbis\n" "\t\t\tVideo: Quality 5;\n" "\t\t\tAudio: Quality 1 - 44,1kHz - Stereo\n\n" "pro\t\tfull size DV video. encoded with Ogg Theora/Ogg Vorbis \n" "\t\t\tVideo: Quality 7;\n" "\t\t\tAudio: Quality 3 - 48kHz - Stereo\n" "\n"); } void print_usage (){ fprintf (stderr, PACKAGE " " PACKAGE_VERSION "\n\n" " usage: " PACKAGE " [options] input\n\n" " Options:\n" "\t --output,-o\t\talternative output\n" "\t --format,-f\t\tspecify input format\n" "\t --width, -x\t\tscale to given size\n" "\t --height,-y\t\tscale to given size\n" "\t --endtime,-e\t\tend encoding at this time (in sec)\n" "\t --starttime,-s\t\tstart encoding at this time (in sec)\n" "\t --aspect\t\tdefine frame aspect ratio: i.e. 4:3 or 16:9\n" "\t --crop[top|bottom|left|right]\tcrop input before resizing\n" "\t --deinterlace,-d \t\t[off|on] disable deinterlace, \n" "\t\t\t\t\tenabled by default right now\n" "\t --videoquality,-v\t[0 to 10] encoding quality for video\n" "\t --audioquality,-a\t[-1 to 10] encoding quality for audio\n" "\t --samplerate,-H\t\tset output samplerate in Hz\n" "\t --nosound\t\tdisable the sound from input\n" "\n" "\t --v2v-preset,-p\tencode file with v2v preset, \n" "\t\t\t\t right now there is preview and pro,\n" "\t\t\t\t '"PACKAGE" -p info' for more informations\n" #ifndef _WIN32 "\t --nice\t\t\tset niceness to n\n" #endif "\t --debug\t\toutputt some more information during encoding\n" "\t --help,-h\t\tthis message\n" "\n Examples:\n" "\tffmpeg2theora videoclip.avi (will write output to videoclip.avi.ogg)\n\n" "\tcat something.dv | ffmpeg2theora -f dv -o output.ogg -\n\n" "\tLive encoding from a DV camcorder (needs a fast machine)\n" "\tdvgrab - | ffmpeg2theora -f dv -x 352 -y 288 -o output.ogg -\n" "\n\tLive encoding and streaming to icecast server:\n" "\t dvgrab --format raw - | \\\n" "\t ffmpeg2theora -f dv -x 160 -y 128 -o /dev/stdout - | \\\n" "\t oggfwd iccast2server 8000 password /theora.ogg\n" "\n"); exit (0); } int main (int argc, char **argv){ int n; int outputfile_set=0; char outputfile_name[255]; char inputfile_name[255]; static int croptop_flag=0; static int cropbottom_flag=0; static int cropright_flag=0; static int cropleft_flag=0; static int nosound_flag=0; static int aspect_flag=0; AVInputFormat *input_fmt=NULL; ff2theora convert = ff2theora_init (); av_register_all (); int c,long_option_index; const char *optstring = "o:f:x:y:v:a:s:e:d:H:c:p:N:D:h::"; struct option options [] = { {"output",required_argument,NULL,'o'}, {"format",required_argument,NULL,'f'}, {"width",required_argument,NULL,'x'}, {"height",required_argument,NULL,'y'}, {"videoquality",required_argument,NULL,'v'}, {"audioquality",required_argument,NULL,'a'}, {"deinterlace",required_argument,NULL,'d'}, {"samplerate",required_argument,NULL,'H'}, {"channels",required_argument,NULL,'c'}, {"nosound",0,&nosound_flag,1}, {"aspect",required_argument,&aspect_flag,1}, {"v2v-preset",required_argument,NULL,'p'}, {"nice",required_argument,NULL,'N'}, {"croptop",required_argument,&croptop_flag,1}, {"cropbottom",required_argument,&cropbottom_flag,1}, {"cropright",required_argument,&cropright_flag,1}, {"cropleft",required_argument,&cropleft_flag,1}, {"starttime",required_argument,NULL,'s'}, {"endtime",required_argument,NULL,'e'}, {"debug",0,NULL,'D'}, {"help",0,NULL,'h'}, {NULL,0,NULL,0} }; if (argc == 1){ print_usage (); } // set some variables; info.debug=0; while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){ switch(c) { case 0: if (nosound_flag){ convert->disable_audio=1; nosound_flag=0; } /* crop */ if (croptop_flag){ convert->frame_topBand=crop_check(convert,"top",optarg); croptop_flag=0; } if (cropbottom_flag){ convert->frame_bottomBand=crop_check(convert,"bottom",optarg); cropbottom_flag=0; } if (cropright_flag){ convert->frame_rightBand=crop_check(convert,"right",optarg); cropleft_flag=0; } if (cropleft_flag){ convert->frame_leftBand=crop_check(convert,"left",optarg); cropleft_flag=0; } if (aspect_flag){ convert->frame_aspect=aspect_check(optarg); aspect_flag=0; } break; case 'o': sprintf(outputfile_name,optarg); outputfile_set=1; break; case 'f': input_fmt=av_find_input_format(optarg); break; case 'x': convert->output_width=atoi(optarg); break; case 'y': convert->output_height=atoi(optarg); break; case 'v': convert->video_quality = rint(atof(optarg)*6.3); if(convert->video_quality <0 || convert->video_quality >63){ fprintf(stderr,"video quality out of range (choose 0 through 10)\n"); exit(1); } break; case 'a': convert->audio_quality=atof(optarg)*.099; if(convert->audio_quality<-.1 || convert->audio_quality>1){ fprintf(stderr,"audio quality out of range (choose -1 through 10)\n"); exit(1); } break; case 's': convert->start_time = atoi(optarg); break; case 'e': convert->end_time = atoi(optarg); break; case 'd': if(!strcmp(optarg,"off")) convert->deinterlace=0; else convert->deinterlace=1; break; case 'H': convert->sample_rate=atoi(optarg); break; /* does not work right now */ case 'c': convert->channels=atoi(optarg); break; case 'p': //v2v presets if(!strcmp(optarg, "info")){ print_presets_info(); exit(1); } else if(!strcmp(optarg, "pro")){ //need a way to set resize here. and not later info.preset=V2V_PRESET_PRO; convert->video_quality = rint(7*6.3); convert->audio_quality=3*.099; convert->channels=2; convert->sample_rate=48000; } else if(!strcmp(optarg,"preview")){ //need a way to set resize here. and not later info.preset=V2V_PRESET_PREVIEW; convert->video_quality = rint(5*6.3); convert->audio_quality=1*.099; convert->channels=2; convert->sample_rate=44100; } else{ fprintf(stderr,"\nunknown preset.\n\n"); print_presets_info(); exit(1); } break; case 'N': n = atoi(optarg); if (n) { #ifndef _WIN32 if (nice(n)<0) { fprintf(stderr,"error setting %d for niceness", n); } #endif } break; case 'D': //enable debug informations info.debug=1; break; case 'h': print_usage (); exit(1); } } //use PREVIEW as default setting if(argc==2){ //need a way to set resize here. and not later info.preset=V2V_PRESET_PREVIEW; convert->video_quality = rint(5*6.3); convert->audio_quality=1*.099; convert->channels=2; convert->sample_rate=44100; } while(optind<argc){ /* assume that anything following the options must be a filename */ if(!strcmp(argv[optind],"-")){ sprintf(inputfile_name,"pipe:"); } else{ sprintf(inputfile_name,"%s",argv[optind]); if(outputfile_set!=1){ sprintf(outputfile_name,"%s.ogg",argv[optind]); outputfile_set=1; } } optind++; } //FIXME: is using_stdin still neded? is it needed as global variable? using_stdin |= !strcmp(inputfile_name, "pipe:" ) || !strcmp( inputfile_name, "/dev/stdin" ); if(outputfile_set!=1){ fprintf(stderr,"you have to specifie an output file with -o output.ogg.\n"); exit(1); } /* could go, but so far no player supports offset_x/y */ if(convert->output_width % 16 || convert->output_height % 16){ fprintf(stderr,"output size must be a multiple of 16 for now.\n"); exit(1); } if(convert->output_width % 4 || convert->output_height % 4){ fprintf(stderr,"output width and hight size must be a multiple of 2.\n"); exit(1); } if (av_open_input_file(&convert->context, inputfile_name, input_fmt, 0, NULL) >= 0){ if (av_find_stream_info (convert->context) >= 0){ info.outfile = fopen(outputfile_name,"wb"); dump_format (convert->context, 0,inputfile_name, 0); if(convert->disable_audio){ fprintf(stderr," [audio disabled].\n"); } ff2theora_output (convert); convert->audio_index =convert->video_index = -1; } else{ fprintf (stderr,"Unable to decode input\n"); } av_close_input_file (convert->context); } else{ fprintf (stderr, "Unable to open file %s\n", inputfile_name); } ff2theora_close (convert); fprintf(stderr,"\n"); return(0); }