Skip to content
Snippets Groups Projects
ffmpeg.c 94.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •                         icodec->channels = codec->channels;
                            if (codec->sample_rate == icodec->sample_rate)
                                ost->audio_resample = 0;
                            else {
                                ost->audio_resample = 1;
                                ost->resample = audio_resample_init(codec->channels, icodec->channels,
                                                            codec->sample_rate, 
                                                            icodec->sample_rate);
                            }
    
                            /* Request specific number of channels */
                            icodec->channels = codec->channels;
                        } else {
                            ost->audio_resample = 1; 
                            ost->resample = audio_resample_init(codec->channels, icodec->channels,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                                                            codec->sample_rate, 
                                                            icodec->sample_rate);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    }
                    ist->decoding_needed = 1;
                    ost->encoding_needed = 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    if (codec->width == icodec->width &&
    
                        codec->height == icodec->height &&
                        frame_topBand == 0 &&
                        frame_bottomBand == 0 &&
                        frame_leftBand == 0 &&
                        frame_rightBand == 0)
                    {
                        ost->video_resample = 0;
                        ost->video_crop = 0;
                    } else if ((codec->width == icodec->width -
                                    (frame_leftBand + frame_rightBand)) &&
                            (codec->height == icodec->height -
                                    (frame_topBand  + frame_bottomBand)))
                    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        ost->video_resample = 0;
    
                        ost->video_crop = 1;
                        ost->topBand = frame_topBand;
                        ost->leftBand = frame_leftBand;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    } else {
    
                        uint8_t *buf;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        ost->video_resample = 1;
    
                        ost->video_crop = 0; // cropping is handled as part of resample
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        buf = av_malloc((codec->width * codec->height * 3) / 2);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        if (!buf)
                            goto fail;
                        ost->pict_tmp.data[0] = buf;
                        ost->pict_tmp.data[1] = ost->pict_tmp.data[0] + (codec->width * codec->height);
                        ost->pict_tmp.data[2] = ost->pict_tmp.data[1] + (codec->width * codec->height) / 4;
                        ost->pict_tmp.linesize[0] = codec->width;
                        ost->pict_tmp.linesize[1] = codec->width / 2;
                        ost->pict_tmp.linesize[2] = codec->width / 2;
    
    
                        ost->img_resample_ctx = img_resample_full_init( 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                                          ost->st->codec.width, ost->st->codec.height,
    
                                          ist->st->codec.width, ist->st->codec.height,
                                          frame_topBand, frame_bottomBand,
                                          frame_leftBand, frame_rightBand);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    }
                    ost->encoding_needed = 1;
                    ist->decoding_needed = 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
    
                /* two pass mode */
                if (ost->encoding_needed && 
                    (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
                    char logfilename[1024];
                    FILE *f;
                    int size;
                    char *logbuffer;
                    
                    snprintf(logfilename, sizeof(logfilename), "%s-%d.log", 
                             pass_logfilename ? 
                             pass_logfilename : DEFAULT_PASS_LOGFILENAME, i);
                    if (codec->flags & CODEC_FLAG_PASS1) {
                        f = fopen(logfilename, "w");
                        if (!f) {
                            perror(logfilename);
                            exit(1);
                        }
                        ost->logfile = f;
                    } else {
                        /* read the log file */
                        f = fopen(logfilename, "r");
                        if (!f) {
                            perror(logfilename);
                            exit(1);
                        }
                        fseek(f, 0, SEEK_END);
                        size = ftell(f);
                        fseek(f, 0, SEEK_SET);
                        logbuffer = av_malloc(size + 1);
                        if (!logbuffer) {
                            fprintf(stderr, "Could not allocate log buffer\n");
                            exit(1);
                        }
                        fread(logbuffer, 1, size, f);
                        fclose(f);
                        logbuffer[size] = '\0';
                        codec->stats_in = logbuffer;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        /* dump the file output parameters - cannot be done before in case
           of stream copy */
        for(i=0;i<nb_output_files;i++) {
            dump_format(output_files[i], i, output_files[i]->filename, 1);
        }
    
        /* dump the stream mapping */
        fprintf(stderr, "Stream mapping:\n");
        for(i=0;i<nb_ostreams;i++) {
            ost = ost_table[i];
            fprintf(stderr, "  Stream #%d.%d -> #%d.%d\n",
                    ist_table[ost->source_index]->file_index,
                    ist_table[ost->source_index]->index,
                    ost->file_index, 
                    ost->index);
        }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* open each encoder */
        for(i=0;i<nb_ostreams;i++) {
            ost = ost_table[i];
            if (ost->encoding_needed) {
                AVCodec *codec;
                codec = avcodec_find_encoder(ost->st->codec.codec_id);
                if (!codec) {
                    fprintf(stderr, "Unsupported codec for output stream #%d.%d\n", 
                            ost->file_index, ost->index);
                    exit(1);
                }
                if (avcodec_open(&ost->st->codec, codec) < 0) {
                    fprintf(stderr, "Error while opening codec for stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n", 
                            ost->file_index, ost->index);
                    exit(1);
                }
            }
        }
    
        /* open each decoder */
        for(i=0;i<nb_istreams;i++) {
            ist = ist_table[i];
            if (ist->decoding_needed) {
                AVCodec *codec;
                codec = avcodec_find_decoder(ist->st->codec.codec_id);
                if (!codec) {
    
                    fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n", 
                            ist->st->codec.codec_id, ist->file_index, ist->index);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    exit(1);
                }
                if (avcodec_open(&ist->st->codec, codec) < 0) {
                    fprintf(stderr, "Error while opening codec for input stream #%d.%d\n", 
                            ist->file_index, ist->index);
                    exit(1);
                }
    
                //if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO)
                //    ist->st->codec.flags |= CODEC_FLAG_REPEAT_FIELD;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        }
    
        /* init pts */
        for(i=0;i<nb_istreams;i++) {
            ist = ist_table[i];
        }
        
        /* compute buffer size max (should use a complete heuristic) */
        for(i=0;i<nb_input_files;i++) {
            file_table[i].buffer_size_max = 2048;
        }
    
        /* open files and write file headers */
        for(i=0;i<nb_output_files;i++) {
            os = output_files[i];
    
            if (av_write_header(os) < 0) {
    
                fprintf(stderr, "Could not write header for output file #%d (incorrect codec paramters ?)\n", i);
                ret = -EINVAL;
                goto fail;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
    #ifndef CONFIG_WIN32
        if (!do_play) {
            fprintf(stderr, "Press [q] to stop encoding\n");
        } else {
            fprintf(stderr, "Press [q] to stop playing\n");
        }
    #endif
        term_init();
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        for(;;) {
            int file_index, ist_index;
            AVPacket pkt;
    
            uint8_t *ptr;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            int len;
    
            uint8_t *data_buf;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            int data_size, got_picture;
            AVPicture picture;
            short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        redo:
    
            if (key) {
                /* read_key() returns 0 on EOF */
                key = read_key();
                if (key == 'q')
                    break;
            }
    
            /* select the stream that we must read now by looking at the
               smallest output pts */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            file_index = -1;
    
            pts_min = 1e10;
            for(i=0;i<nb_ostreams;i++) {
                double pts;
                ost = ost_table[i];
                os = output_files[ost->file_index];
                ist = ist_table[ost->source_index];
                pts = (double)ost->st->pts.val * os->pts_num / os->pts_den;
                if (!file_table[ist->file_index].eof_reached && 
                    pts < pts_min) {
                    pts_min = pts;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    file_index = ist->file_index;
                }
            }
            /* if none, if is finished */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* finish if recording time exhausted */
    
            if (recording_time > 0 && pts_min >= (recording_time / 1000000.0))
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* read a packet from it and output it in the fifo */
            is = input_files[file_index];
            if (av_read_packet(is, &pkt) < 0) {
                file_table[file_index].eof_reached = 1;
                continue;
            }
    
            if (!pkt.size) {
                stream_no_data = is;
            } else {
                stream_no_data = 0;
            }
    
            if (do_hex_dump) {
                printf("stream #%d, size=%d:\n", pkt.stream_index, pkt.size);
                av_hex_dump(pkt.data, pkt.size);
            }
    
            /* the following test is needed in case new streams appear
               dynamically in stream : we ignore them */
            if (pkt.stream_index >= file_table[file_index].nb_streams)
    
                goto discard_packet;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            ist_index = file_table[file_index].ist_index + pkt.stream_index;
            ist = ist_table[ist_index];
    
            if (ist->discard)
                goto discard_packet;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
            // printf("read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
            len = pkt.size;
            ptr = pkt.data;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            while (len > 0) {
    
                int64_t ipts;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
                /* decode the packet if needed */
                data_buf = NULL; /* fail safe */
                data_size = 0;
                if (ist->decoding_needed) {
    
                    /* NOTE1: we only take into account the PTS if a new
                       frame has begun (MPEG semantics) */
                    /* NOTE2: even if the fraction is not initialized,
                       av_frac_set can be used to set the integer part */
                    if (ist->frame_decoded && 
                        pkt.pts != AV_NOPTS_VALUE && 
                        !pts_set) {
                        ipts = pkt.pts;
                        ist->frame_decoded = 0;
                        pts_set = 1;
                    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    switch(ist->st->codec.codec_type) {
                    case CODEC_TYPE_AUDIO:
    
                        /* XXX: could avoid copy if PCM 16 bits with same
                           endianness as CPU */
                        ret = avcodec_decode_audio(&ist->st->codec, samples, &data_size,
                                                   ptr, len);
                        if (ret < 0)
                            goto fail_decode;
    
                        /* Some bug in mpeg audio decoder gives */
                        /* data_size < 0, it seems they are overflows */
                        if (data_size <= 0) {
    
                            /* no audio frame */
                            ptr += ret;
                            len -= ret;
                            continue;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        }
    
                        data_buf = (uint8_t *)samples;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        break;
                    case CODEC_TYPE_VIDEO:
                        if (ist->st->codec.codec_id == CODEC_ID_RAWVIDEO) {
                            int size;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            size = (ist->st->codec.width * ist->st->codec.height);
    
                            avpicture_fill(&picture, ptr, 
                                         ist->st->codec.pix_fmt,
                                         ist->st->codec.width,
                                         ist->st->codec.height);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            ret = len;
                        } else {
    
                            AVFrame big_picture;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2;
                            ret = avcodec_decode_video(&ist->st->codec, 
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                                                       &big_picture, &got_picture, ptr, len);
                            picture= *(AVPicture*)&big_picture;
                            ist->st->quality= big_picture.quality;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            if (ret < 0) {
                            fail_decode:
                                fprintf(stderr, "Error while decoding stream #%d.%d\n",
                                        ist->file_index, ist->index);
                                av_free_packet(&pkt);
                                goto redo;
                            }
                            if (!got_picture) {
                                /* no picture yet */
                                ptr += ret;
                                len -= ret;
                                continue;
                            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        }
                        break;
                    default:
                        goto fail_decode;
                    }
                } else {
                    data_buf = ptr;
                    data_size = len;
                    ret = len;
                }
                ptr += ret;
                len -= ret;
    
    
                buffer_to_free = 0;
                if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) {
                    pre_process_video_frame(ist, &picture, &buffer_to_free);
                }
    
    
                /* frame rate emulation */
                if (ist->st->codec.rate_emu) {
    
                    int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
    
                    int64_t now = av_gettime() - ist->start;
                    if (pts > now)
                        usleep(pts - now);
    
                    ist->frame++;
                }
    
    
    #if 0
                /* mpeg PTS deordering : if it is a P or I frame, the PTS
                   is the one of the next displayed one */
                /* XXX: add mpeg4 too ? */
                if (ist->st->codec.codec_id == CODEC_ID_MPEG1VIDEO) {
                    if (ist->st->codec.pict_type != B_TYPE) {
    
                        int64_t tmp;
    
                        tmp = ist->last_ip_pts;
                        ist->last_ip_pts  = ist->frac_pts.val;
                        ist->frac_pts.val = tmp;
                    }
                }
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                /* transcode raw format, encode packets and output them */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                for(i=0;i<nb_ostreams;i++) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    ost = ost_table[i];
                    if (ost->source_index == ist_index) {
                        os = output_files[ost->file_index];
    
    
                        if (ipts != AV_NOPTS_VALUE) {
    #if 0
                            printf("%d: got pts=%f %f\n", 
                                   i, pkt.pts / 90000.0, 
                                   (ipts - ost->st->pts.val) / 90000.0);
    #endif
                            /* set the input output pts pairs */
                            ost->sync_ipts = (double)ipts * is->pts_num / 
                                is->pts_den;
                            /* XXX: take into account the various fifos,
                               in particular for audio */
                            ost->sync_opts = ost->st->pts.val;
    
                            //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ipts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts); 
                        } else {
                            //printf("pts.val=%lld\n", ost->st->pts.val); 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        if (ost->encoding_needed) {
                            switch(ost->st->codec.codec_type) {
                            case CODEC_TYPE_AUDIO:
                                do_audio_out(os, ost, ist, data_buf, data_size);
                                break;
                            case CODEC_TYPE_VIDEO:
    
                                /* find an audio stream for synchro */
                                {
                                    int i;
                                    AVOutputStream *audio_sync, *ost1;
                                    audio_sync = NULL;
                                    for(i=0;i<nb_ostreams;i++) {
                                        ost1 = ost_table[i];
                                        if (ost1->file_index == ost->file_index &&
                                            ost1->st->codec.codec_type == CODEC_TYPE_AUDIO) {
                                            audio_sync = ost1;
                                            break;
                                        }
                                    }
    
                                    do_video_out(os, ost, ist, &picture, &frame_size, audio_sync);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                                break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            }
                        } else {
    
                            AVFrame avframe;
                                                    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            /* no reencoding needed : output the packet directly */
    
                            /* force the input stream PTS */
    
                            
                            //XXX/FIXME set keyframe flag from demuxer (or optionally from decoder)
                            memset(&avframe, 0, sizeof(AVFrame));
                            ost->st->codec.coded_frame= &avframe;
                            
    
                            av_write_frame(os, ost->index, data_buf, data_size);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        }
                    }
                }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            av_free_packet(&pkt);
            
    
            /* dump report by using the output first video and audio streams */
            print_report(output_files, ost_table, nb_ostreams, 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        /* dump report by using the first video and audio streams */
    
        print_report(output_files, ost_table, nb_ostreams, 1);
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* close each encoder */
        for(i=0;i<nb_ostreams;i++) {
            ost = ost_table[i];
            if (ost->encoding_needed) {
    
                av_freep(&ost->st->codec.stats_in);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                avcodec_close(&ost->st->codec);
            }
        }
        
        /* close each decoder */
        for(i=0;i<nb_istreams;i++) {
            ist = ist_table[i];
            if (ist->decoding_needed) {
                avcodec_close(&ist->st->codec);
            }
        }
        
    
        /* write the trailer if needed and close file */
        for(i=0;i<nb_output_files;i++) {
            os = output_files[i];
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        /* finished ! */
        
        ret = 0;
     fail1:
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        av_free(file_table);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (ist_table) {
            for(i=0;i<nb_istreams;i++) {
                ist = ist_table[i];
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                av_free(ist);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            av_free(ist_table);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        if (ost_table) {
            for(i=0;i<nb_ostreams;i++) {
                ost = ost_table[i];
                if (ost) {
    
                    if (ost->logfile) {
                        fclose(ost->logfile);
                        ost->logfile = NULL;
                    }
    
                    fifo_free(&ost->fifo); /* works even if fifo is not
                                              initialized but set to zero */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    av_free(ost->pict_tmp.data[0]);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    if (ost->video_resample)
                        img_resample_close(ost->img_resample_ctx);
                    if (ost->audio_resample)
                        audio_resample_close(ost->resample);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    av_free(ost);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            av_free(ost_table);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        return ret;
     fail:
        ret = -ENOMEM;
        goto fail1;
    }
    
    #if 0
    int file_read(const char *filename)
    {
        URLContext *h;
        unsigned char buffer[1024];
        int len, i;
    
        if (url_open(&h, filename, O_RDONLY) < 0) {
            printf("could not open '%s'\n", filename);
            return -1;
        }
        for(;;) {
            len = url_read(h, buffer, sizeof(buffer));
            if (len <= 0)
                break;
            for(i=0;i<len;i++) putchar(buffer[i]);
        }
        url_close(h);
        return 0;
    }
    #endif
    
    
    static void show_licence(void)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        printf(
        "ffmpeg version " FFMPEG_VERSION "\n"
    
        "Copyright (c) 2000, 2001, 2002 Fabrice Bellard\n"
        "This library is free software; you can redistribute it and/or\n"
        "modify it under the terms of the GNU Lesser General Public\n"
        "License as published by the Free Software Foundation; either\n"
        "version 2 of the License, or (at your option) any later version.\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        "\n"
    
        "This library is distributed in the hope that it will be useful,\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    
        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
        "Lesser General Public License for more details.\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        "\n"
    
        "You should have received a copy of the GNU Lesser General Public\n"
        "License along with this library; if not, write to the Free Software\n"
        "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        );
        exit(1);
    }
    
    
    static void opt_image_format(const char *arg)
    
    {
        AVImageFormat *f;
        
        for(f = first_image_format; f != NULL; f = f->next) {
            if (!strcmp(arg, f->name))
                break;
        }
        if (!f) {
            fprintf(stderr, "Unknown image format: '%s'\n", arg);
            exit(1);
        }
        image_format = f;
    }
    
    
    static void opt_format(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        /* compatibility stuff for pgmyuv */
        if (!strcmp(arg, "pgmyuv")) {
            opt_image_format(arg);
            arg = "image";
        }
    
    
        file_iformat = av_find_input_format(arg);
        file_oformat = guess_format(arg, NULL, NULL);
        if (!file_iformat && !file_oformat) {
            fprintf(stderr, "Unknown input or output format: %s\n", arg);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            exit(1);
        }
    }
    
    
    static void opt_video_bitrate(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        video_bit_rate = atoi(arg) * 1000;
    }
    
    
    static void opt_video_bitrate_tolerance(const char *arg)
    
    {
        video_bit_rate_tolerance = atoi(arg) * 1000;
    }
    
    
    static void opt_video_bitrate_max(const char *arg)
    
    {
        video_rc_max_rate = atoi(arg) * 1000;
    }
    
    
    static void opt_video_bitrate_min(const char *arg)
    
    {
        video_rc_min_rate = atoi(arg) * 1000;
    }
    
    
    static void opt_video_buffer_size(const char *arg)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    {
        video_rc_buffer_size = atoi(arg) * 1000;
    }
    
    
    static void opt_video_rc_eq(char *arg)
    
    {
        video_rc_eq = arg;
    }
    
    
    static void opt_video_rc_override_string(char *arg)
    
    static void opt_workaround_bugs(const char *arg)
    
    static void opt_dct_algo(const char *arg)
    
    static void opt_idct_algo(const char *arg)
    
    static void opt_error_resilience(const char *arg)
    
    {
        error_resilience = atoi(arg);
    }
    
    
    static void opt_error_concealment(const char *arg)
    
    static void opt_debug(const char *arg)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    {
        debug = atoi(arg);
    }
    
    static void opt_frame_rate(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        frame_rate_base = DEFAULT_FRAME_RATE_BASE; //FIXME not optimal
        frame_rate = (int)(strtod(arg, 0) * frame_rate_base + 0.5);
        //FIXME parse fractions 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void opt_frame_crop_top(const char *arg)
    
    {
        frame_topBand = atoi(arg); 
        if (frame_topBand < 0) {
            fprintf(stderr, "Incorrect top crop size\n");
            exit(1);
        }
        if ((frame_topBand % 2) != 0) {
            fprintf(stderr, "Top crop size must be a multiple of 2\n");
            exit(1);
        }
        if ((frame_topBand) >= frame_height){
        	fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
            exit(1);
        }
        frame_height -= frame_topBand;
    }
    
    
    static void opt_frame_crop_bottom(const char *arg)
    
    {
        frame_bottomBand = atoi(arg);
        if (frame_bottomBand < 0) {
            fprintf(stderr, "Incorrect bottom crop size\n");
            exit(1);
        }
        if ((frame_bottomBand % 2) != 0) {
            fprintf(stderr, "Bottom crop size must be a multiple of 2\n");
            exit(1);        
        }
        if ((frame_bottomBand) >= frame_height){
        	fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
            exit(1);
        }
        frame_height -= frame_bottomBand;
    }
    
    
    static void opt_frame_crop_left(const char *arg)
    
    {
        frame_leftBand = atoi(arg);
        if (frame_leftBand < 0) {
            fprintf(stderr, "Incorrect left crop size\n");
            exit(1);
        }
        if ((frame_leftBand % 2) != 0) {
            fprintf(stderr, "Left crop size must be a multiple of 2\n");
            exit(1);
        }
        if ((frame_leftBand) >= frame_width){
        	fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
            exit(1);
        }
        frame_width -= frame_leftBand;
    }
    
    
    static void opt_frame_crop_right(const char *arg)
    
    {
        frame_rightBand = atoi(arg);
        if (frame_rightBand < 0) {
            fprintf(stderr, "Incorrect right crop size\n");
            exit(1);
        }
        if ((frame_rightBand % 2) != 0) {
            fprintf(stderr, "Right crop size must be a multiple of 2\n");
            exit(1);        
        }
        if ((frame_rightBand) >= frame_width){
        	fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
            exit(1);
        }
        frame_width -= frame_rightBand;
    }
    
    
    static void opt_frame_size(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        parse_image_size(&frame_width, &frame_height, arg);
        if (frame_width <= 0 || frame_height <= 0) {
            fprintf(stderr, "Incorrect frame size\n");
            exit(1);
        }
        if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
            fprintf(stderr, "Frame size must be a multiple of 2\n");
            exit(1);
        }
    }
    
    
    static void opt_gop_size(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        gop_size = atoi(arg);
    }
    
    
    static void opt_b_frames(const char *arg)
    
    {
        b_frames = atoi(arg);
        if (b_frames > FF_MAX_B_FRAMES) {
            fprintf(stderr, "\nCannot have more than %d B frames, increase FF_MAX_B_FRAMES.\n", FF_MAX_B_FRAMES);
            exit(1);
        } else if (b_frames < 1) {
            fprintf(stderr, "\nNumber of B frames must be higher than 0\n");
            exit(1);
        }
    }
    
    
    static void opt_qscale(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        video_qscale = atoi(arg);
        if (video_qscale < 0 ||
            video_qscale > 31) {
            fprintf(stderr, "qscale must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_qmin(const char *arg)
    
    {
        video_qmin = atoi(arg);
        if (video_qmin < 0 ||
            video_qmin > 31) {
            fprintf(stderr, "qmin must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_qmax(const char *arg)
    
    {
        video_qmax = atoi(arg);
        if (video_qmax < 0 ||
            video_qmax > 31) {
            fprintf(stderr, "qmax must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_mb_qmin(const char *arg)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    {
        video_mb_qmin = atoi(arg);
        if (video_mb_qmin < 0 ||
            video_mb_qmin > 31) {
            fprintf(stderr, "qmin must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_mb_qmax(const char *arg)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    {
        video_mb_qmax = atoi(arg);
        if (video_mb_qmax < 0 ||
            video_mb_qmax > 31) {
            fprintf(stderr, "qmax must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_qdiff(const char *arg)
    
    {
        video_qdiff = atoi(arg);
        if (video_qdiff < 0 ||
            video_qdiff > 31) {
            fprintf(stderr, "qdiff must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    static void opt_qblur(const char *arg)
    
    {
        video_qblur = atof(arg);
    }
    
    
    static void opt_qcomp(const char *arg)
    
    {
        video_qcomp = atof(arg);
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    static void opt_rc_initial_cplx(const char *arg)
    
    {
        video_rc_initial_cplx = atof(arg);
    }
    
    static void opt_b_qfactor(const char *arg)
    
    static void opt_i_qfactor(const char *arg)
    
    static void opt_b_qoffset(const char *arg)
    
    static void opt_i_qoffset(const char *arg)
    
    static void opt_packet_size(const char *arg)
    
    static void opt_strict(const char *arg)
    
    {
        strict= atoi(arg);
    }
    
    
    static void opt_audio_bitrate(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        audio_bit_rate = atoi(arg) * 1000;
    }
    
    
    static void opt_audio_rate(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        audio_sample_rate = atoi(arg);
    }
    
    
    static void opt_audio_channels(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        audio_channels = atoi(arg);
    }
    
    
    static void opt_video_device(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        video_device = av_strdup(arg);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void opt_video_channel(const char *arg)
    
    static void opt_audio_device(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        audio_device = av_strdup(arg);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void opt_dv1394(const char *arg)
    
    {
        video_grab_format = "dv1394";
    
        audio_grab_format = NULL;
    
    static void opt_audio_codec(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVCodec *p;
    
    
        if (!strcmp(arg, "copy")) {
            audio_stream_copy = 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        } else {
    
            p = first_avcodec;
            while (p) {
                if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_AUDIO)
                    break;
                p = p->next;
            }
            if (p == NULL) {
                fprintf(stderr, "Unknown audio codec '%s'\n", arg);
                exit(1);
            } else {
                audio_codec_id = p->id;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    }
    
    
    static void add_frame_hooker(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        char *args = av_strdup(arg);
    
    
        argv[0] = strtok(args, " ");
        while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
        }
    
        i = frame_hook_add(argc, argv);
    
        if (i != 0) {
            fprintf(stderr, "Failed to add video hook function: %s\n", arg);
            exit(1);
        }
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    const char *motion_str[] = {
        "zero",
        "full",
        "log",
        "phods",
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        "epzs",
        "x1",
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        NULL,
    };
    
    
    static void opt_motion_estimation(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        const char **p;
        p = motion_str;
        for(;;) {
            if (!*p) {
                fprintf(stderr, "Unknown motion estimation method '%s'\n", arg);
                exit(1);
            }
            if (!strcmp(*p, arg))
                break;
            p++;
        }
    
        me_method = (p - motion_str) + 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void opt_video_codec(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVCodec *p;
    
    
        if (!strcmp(arg, "copy")) {
            video_stream_copy = 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        } else {
    
            p = first_avcodec;
            while (p) {
                if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_VIDEO)