Skip to content
Snippets Groups Projects
ffmpeg.c 74.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fabrice Bellard's avatar
    Fabrice Bellard committed
    
            //        printf("read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
    
            len = pkt.size;
            ptr = pkt.data;
            while (len > 0) {
    
                /* decode the packet if needed */
                data_buf = NULL; /* fail safe */
                data_size = 0;
                if (ist->decoding_needed) {
                    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 *)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 {
                            data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2;
                            ret = avcodec_decode_video(&ist->st->codec, 
                                                       &picture, &got_picture, ptr, len);
                            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;
                }
    
                /* init tickers */
                if (!ist->ticker_inited) {
                    switch (ist->st->codec.codec_type) {
                    case CODEC_TYPE_AUDIO:
                        ticker_init(&ist->pts_ticker,
                                (INT64)ist->st->codec.sample_rate,
                                (INT64)(1000000));
                        ist->ticker_inited = 1;
                        break;
                    case CODEC_TYPE_VIDEO:
                        ticker_init(&ist->pts_ticker,
                                (INT64)ist->st->r_frame_rate,
                                ((INT64)1000000 * FRAME_RATE_BASE));
                        ist->ticker_inited = 1;
                        break;
                    default:
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                /* update pts */
                switch(ist->st->codec.codec_type) {
                case CODEC_TYPE_AUDIO:
    
                    //ist->pts = (INT64)1000000 * ist->sample_index / ist->st->codec.sample_rate;
    
                    ist->pts = ticker_abs(&ist->pts_ticker, ist->sample_index);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    ist->sample_index += data_size / (2 * ist->st->codec.channels);
    
                    ist->pts_increment = (INT64) (data_size / (2 * ist->st->codec.channels)) * 1000000 / ist->st->codec.sample_rate;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    break;
                case CODEC_TYPE_VIDEO:
                    ist->frame_number++;
    
                    //ist->pts = ((INT64)ist->frame_number * 1000000 * FRAME_RATE_BASE) / 
                    //    ist->st->codec.frame_rate;
    
                    ist->pts = ticker_abs(&ist->pts_ticker, ist->frame_number);
    
                    ist->pts_increment = ((INT64) 1000000 * FRAME_RATE_BASE) / 
                        ist->st->codec.frame_rate;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
                ptr += ret;
                len -= ret;
    
                /* transcode raw format, encode packets and output them */
                
                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 (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:
    
                                do_video_out(os, ost, ist, &picture, &frame_size);
                                if (do_vstats)
                                    do_video_stats(ost, ist, frame_size);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                                break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            }
                        } else {
                            /* no reencoding needed : output the packet directly */
    
                            /* force the input stream PTS */
    
                            os->oformat->write_packet(os, ost->index, data_buf, data_size, pkt.pts);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                        }
                    }
                }
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            av_free_packet(&pkt);
            
            /* dump report by using the first video and audio streams */
            {
                char buf[1024];
                AVFormatContext *oc;
                INT64 total_size, ti;
                AVCodecContext *enc;
                int frame_number, vid;
                double bitrate, ti1;
                static INT64 last_time;
    
                if ((min_pts - last_time) >= 500000) {
                    last_time = min_pts;
                    
                    oc = output_files[0];
                    
                    total_size = url_ftell(&oc->pb);
                    
                    buf[0] = '\0';
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    ti = MAXINT64;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    vid = 0;
                    for(i=0;i<nb_ostreams;i++) {
                        ost = ost_table[i];
                        enc = &ost->st->codec;
                        ist = ist_table[ost->source_index];
                        if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
                            frame_number = ist->frame_number;
                            sprintf(buf + strlen(buf), "frame=%5d q=%2d ",
                                    frame_number, enc->quality);
    
                            if (do_psnr)
                                sprintf(buf + strlen(buf), "PSNR=%6.2f ", enc->psnr_y);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                            vid = 1;
                        }
                        /* compute min pts value */
                        if (!ist->discard && ist->pts < ti) {
                            ti = ist->pts;
                        }
                    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    ti1 = (double)ti / 1000000.0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    bitrate = (double)(total_size * 8) / ti1 / 1000.0;
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    sprintf(buf + strlen(buf), 
                            "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
                            (double)total_size / 1024, ti1, bitrate);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    
    
                    fprintf(stderr, "%s   \r", buf);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    fflush(stderr);
                }
            }
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        /* dump report by using the first video and audio streams */
        {
            char buf[1024];
            AVFormatContext *oc;
            INT64 total_size, ti;
            AVCodecContext *enc;
            int frame_number, vid;
            double bitrate, ti1;
    
            oc = output_files[0];
            
            total_size = url_ftell(&oc->pb);
            
            buf[0] = '\0';
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            ti = MAXINT64;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            vid = 0;
            for(i=0;i<nb_ostreams;i++) {
                ost = ost_table[i];
                enc = &ost->st->codec;
                ist = ist_table[ost->source_index];
                if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
                    frame_number = ist->frame_number;
                    sprintf(buf + strlen(buf), "frame=%5d q=%2d ",
                            frame_number, enc->quality);
    
                    if (do_psnr)
                        sprintf(buf + strlen(buf), "PSNR=%6.2f ", enc->psnr_y);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    vid = 1;
                }
                /* compute min pts value */
                if (!ist->discard && ist->pts < ti) {
                    ti = ist->pts;
                }
            }
            
            ti1 = ti / 1000000.0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            bitrate = (double)(total_size * 8) / ti1 / 1000.0;
            
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            sprintf(buf + strlen(buf), 
                    "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
                    (double)total_size / 1024, ti1, bitrate);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            
    
            fprintf(stderr, "%s   \n", buf);
    
    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) {
                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) {
    
                    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
    
    void show_licence(void)
    {
        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);
    }
    
    void opt_format(const char *arg)
    {
    
        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);
        }
    }
    
    void opt_video_bitrate(const char *arg)
    {
        video_bit_rate = atoi(arg) * 1000;
    }
    
    
    void opt_video_bitrate_tolerance(const char *arg)
    {
        video_bit_rate_tolerance = atoi(arg) * 1000;
    }
    
    
    void opt_video_bitrate_max(const char *arg)
    {
        video_rc_max_rate = atoi(arg) * 1000;
    }
    
    void opt_video_bitrate_min(const char *arg)
    {
        video_rc_min_rate = atoi(arg) * 1000;
    }
    
    void opt_video_rc_eq(char *arg)
    {
        video_rc_eq = arg;
    }
    
    
    
    void opt_workaround_bugs(const char *arg)
    {
        workaround_bugs = atoi(arg);
    }
    
    
    void opt_dct_algo(const char *arg)
    {
        dct_algo = atoi(arg);
    }
    
    
    void opt_error_resilience(const char *arg)
    {
        error_resilience = atoi(arg);
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_frame_rate(const char *arg)
    {
        frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
    }
    
    
    
    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;
    }
    
    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;
    }
    
    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;
    }
    
    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;
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_frame_size(const char *arg)
    {
        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);
        }
    }
    
    void opt_gop_size(const char *arg)
    {
        gop_size = atoi(arg);
    }
    
    
    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);
        }
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_qscale(const char *arg)
    {
        video_qscale = atoi(arg);
        if (video_qscale < 0 ||
            video_qscale > 31) {
            fprintf(stderr, "qscale must be >= 1 and <= 31\n");
            exit(1);
        }
    }
    
    
    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);
        }
    }
    
    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);
        }
    }
    
    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);
        }
    }
    
    void opt_qblur(const char *arg)
    {
        video_qblur = atof(arg);
    }
    
    void opt_qcomp(const char *arg)
    {
        video_qcomp = atof(arg);
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    void opt_b_qfactor(const char *arg)
    {
        video_b_qfactor = atof(arg);
    }
    void opt_i_qfactor(const char *arg)
    {
        video_i_qfactor = atof(arg);
    }
    void opt_b_qoffset(const char *arg)
    {
        video_b_qoffset = atof(arg);
    }
    void opt_i_qoffset(const char *arg)
    {
        video_i_qoffset = atof(arg);
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_audio_bitrate(const char *arg)
    {
        audio_bit_rate = atoi(arg) * 1000;
    }
    
    void opt_audio_rate(const char *arg)
    {
        audio_sample_rate = atoi(arg);
    }
    
    void opt_audio_channels(const char *arg)
    {
        audio_channels = atoi(arg);
    }
    
    void opt_video_device(const char *arg)
    {
        v4l_device = strdup(arg);
    }
    
    void opt_audio_device(const char *arg)
    {
        audio_device = strdup(arg);
    }
    
    void opt_audio_codec(const char *arg)
    {
        AVCodec *p;
    
        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;
        }
    }
    
    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,
    };
    
    void opt_motion_estimation(const char *arg)
    {
        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
    }
    
    void opt_video_codec(const char *arg)
    {
        AVCodec *p;
    
        p = first_avcodec;
        while (p) {
            if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_VIDEO)
                break;
            p = p->next;
        }
        if (p == NULL) {
            fprintf(stderr, "Unknown video codec '%s'\n", arg);
            exit(1);
        } else {
            video_codec_id = p->id;
        }
    }
    
    void opt_map(const char *arg)
    {
        AVStreamMap *m;
        const char *p;
    
        p = arg;
        m = &stream_maps[nb_stream_maps++];
    
        m->file_index = strtol(arg, (char **)&p, 0);
        if (*p)
            p++;
    
    Juanjo's avatar
    Juanjo committed
    
        m->stream_index = strtol(p, (char **)&p, 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    void opt_recording_time(const char *arg)
    {
        recording_time = parse_date(arg, 1);
    }
    
    
    void print_error(const char *filename, int err)
    
        switch(err) {
        case AVERROR_NUMEXPECTED:
    
            fprintf(stderr, "%s: Incorrect image filename syntax.\n"
                    "Use '%%d' to specify the image number:\n"
                    "  for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n"
                    "  for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n", 
                    filename);
    
            break;
        case AVERROR_INVALIDDATA:
            fprintf(stderr, "%s: Error while parsing header\n", filename);
            break;
        case AVERROR_NOFMT:
            fprintf(stderr, "%s: Unknown format\n", filename);
            break;
        default:
            fprintf(stderr, "%s: Error while opening file\n", filename);
            break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    void opt_input_file(const char *filename)
    {
        AVFormatContext *ic;
        AVFormatParameters params, *ap = &params;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        /* get default parameters from command line */
    
        memset(ap, 0, sizeof(*ap));
        ap->sample_rate = audio_sample_rate;
        ap->channels = audio_channels;
        ap->frame_rate = frame_rate;
        ap->width = frame_width;
        ap->height = frame_height;
    
        /* open the input file with generic libav function */
        err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (err < 0) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            exit(1);
        }
        
    
        /* If not enough info to get the stream parameters, we decode the
           first frames to get it. (used in mpeg case for example) */
        ret = av_find_stream_info(ic);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (ret < 0) {
            fprintf(stderr, "%s: could not find codec parameters\n", filename);
            exit(1);
        }
    
        /* update the current parameters so that they match the one of the input stream */
        for(i=0;i<ic->nb_streams;i++) {
            AVCodecContext *enc = &ic->streams[i]->codec;
            switch(enc->codec_type) {
            case CODEC_TYPE_AUDIO:
    
                //fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                audio_channels = enc->channels;
                audio_sample_rate = enc->sample_rate;
                break;
            case CODEC_TYPE_VIDEO:
                frame_height = enc->height;
                frame_width = enc->width;
    
                rfps = ic->streams[i]->r_frame_rate;
    
                enc->error_resilience = error_resilience; 
    
                if (enc->frame_rate != rfps) {
    
                    fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
                        i, (float)enc->frame_rate / FRAME_RATE_BASE,
                        (float)rfps / FRAME_RATE_BASE);
    
                /* update the current frame rate to match the stream frame rate */
                frame_rate = rfps;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        }
        
        input_files[nb_input_files] = ic;
        /* dump the file content */
        dump_format(ic, nb_input_files, filename, 0);
        nb_input_files++;
    
        file_iformat = NULL;
        file_oformat = NULL;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
    {
        int has_video, has_audio, i, j;
        AVFormatContext *ic;
    
        has_video = 0;
        has_audio = 0;
        for(j=0;j<nb_input_files;j++) {
            ic = input_files[j];
            for(i=0;i<ic->nb_streams;i++) {
                AVCodecContext *enc = &ic->streams[i]->codec;
                switch(enc->codec_type) {
                case CODEC_TYPE_AUDIO:
                    has_audio = 1;
                    break;
                case CODEC_TYPE_VIDEO:
                    has_video = 1;
                    break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_output_file(const char *filename)
    {
        AVStream *st;
        AVFormatContext *oc;
    
        int use_video, use_audio, nb_streams, input_has_video, input_has_audio;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        int codec_id;
    
        if (!strcmp(filename, "-"))
            filename = "pipe:";
    
        oc = av_mallocz(sizeof(AVFormatContext));
    
    
        if (!file_oformat) {
            file_oformat = guess_format(NULL, filename, NULL);
            if (!file_oformat) {
                fprintf(stderr, "Unable for find a suitable output format for '%s'\n",
                        filename);
                exit(1);
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (!strcmp(file_oformat->name, "ffm") && 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            strstart(filename, "http:", NULL)) {
            /* special case for files sent to ffserver: we get the stream
               parameters from ffserver */
            if (read_ffserver_streams(oc, filename) < 0) {
                fprintf(stderr, "Could not read stream parameters from '%s'\n", filename);
                exit(1);
            }
        } else {
    
            use_video = file_oformat->video_codec != CODEC_ID_NONE;
            use_audio = file_oformat->audio_codec != CODEC_ID_NONE;
    
            /* disable if no corresponding type found and at least one
               input file */
            if (nb_input_files > 0) {
                check_audio_video_inputs(&input_has_video, &input_has_audio);
                if (!input_has_video)
                    use_video = 0;
                if (!input_has_audio)
                    use_audio = 0;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (audio_disable) {
                use_audio = 0;
            }
            if (video_disable) {
                use_video = 0;
            }
            
            nb_streams = 0;
            if (use_video) {
                AVCodecContext *video_enc;
                
                st = av_mallocz(sizeof(AVStream));
                if (!st) {
                    fprintf(stderr, "Could not alloc stream\n");
                    exit(1);
                }
                video_enc = &st->codec;
    
    
                codec_id = file_oformat->video_codec;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                if (video_codec_id != CODEC_ID_NONE)
                    codec_id = video_codec_id;
    
                video_enc->codec_id = codec_id;
                video_enc->codec_type = CODEC_TYPE_VIDEO;
                
                video_enc->bit_rate = video_bit_rate;
    
                video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                video_enc->frame_rate = frame_rate; 
                
                video_enc->width = frame_width;
                video_enc->height = frame_height;
                if (!intra_only)
                    video_enc->gop_size = gop_size;
                else
                    video_enc->gop_size = 0;
                if (video_qscale || same_quality) {
                    video_enc->flags |= CODEC_FLAG_QSCALE;
                    video_enc->quality = video_qscale;
                }
    
                if (use_hq) {
                    video_enc->flags |= CODEC_FLAG_HQ;
                }
                
    
                if (use_4mv) {
                    video_enc->flags |= CODEC_FLAG_HQ;
                    video_enc->flags |= CODEC_FLAG_4MV;
                }
    
                
                if (b_frames) {
                    if (codec_id != CODEC_ID_MPEG4) {
                        fprintf(stderr, "\nB frames encoding only supported by MPEG-4.\n");
                        exit(1);
                    }
                    video_enc->max_b_frames = b_frames;
                    video_enc->b_frame_strategy = 0;
                    video_enc->b_quant_factor = 2.0;
                }
                
                video_enc->qmin = video_qmin;
                video_enc->qmax = video_qmax;
                video_enc->max_qdiff = video_qdiff;
                video_enc->qblur = video_qblur;
                video_enc->qcompress = video_qcomp;
    
                video_enc->rc_eq = video_rc_eq;
                video_enc->rc_max_rate = video_rc_max_rate;
                video_enc->rc_min_rate = video_rc_min_rate;
                video_enc->rc_buffer_size = video_rc_buffer_size;
                video_enc->i_quant_factor = video_i_qfactor;
                video_enc->b_quant_factor = video_b_qfactor;
                video_enc->i_quant_offset = video_i_qoffset;
                video_enc->b_quant_offset = video_b_qoffset;
    
                video_enc->dct_algo = dct_algo;
    
                if (do_psnr)
                    video_enc->get_psnr = 1;
                else
                    video_enc->get_psnr = 0;
    
                video_enc->me_method = me_method;
    
                /* XXX: need to find a way to set codec parameters */
    
                if (oc->oformat->flags & AVFMT_RGB24) {
    
                    video_enc->pix_fmt = PIX_FMT_RGB24;
                }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
                oc->streams[nb_streams] = st;
                nb_streams++;
            }
        
            if (use_audio) {
                AVCodecContext *audio_enc;
    
                st = av_mallocz(sizeof(AVStream));
                if (!st) {
                    fprintf(stderr, "Could not alloc stream\n");
                    exit(1);
                }
                audio_enc = &st->codec;
    
                codec_id = file_oformat->audio_codec;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                if (audio_codec_id != CODEC_ID_NONE)
                    codec_id = audio_codec_id;
                audio_enc->codec_id = codec_id;
                audio_enc->codec_type = CODEC_TYPE_AUDIO;
                
                audio_enc->bit_rate = audio_bit_rate;
                audio_enc->sample_rate = audio_sample_rate;
    
                /* For audio codecs other than AC3 we limit */
                /* the number of coded channels to stereo   */
                if (audio_channels > 2 && codec_id != CODEC_ID_AC3) {
                    audio_enc->channels = 2;
                } else
                    audio_enc->channels = audio_channels;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                oc->streams[nb_streams] = st;
                nb_streams++;
            }
    
            oc->nb_streams = nb_streams;
    
            if (!nb_streams) {
    
                fprintf(stderr, "No audio or video streams available\n");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                exit(1);
            }
    
            if (str_title)
    
                pstrcpy(oc->title, sizeof(oc->title), str_title);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_author)
    
                pstrcpy(oc->author, sizeof(oc->author), str_author);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_copyright)
    
                pstrcpy(oc->copyright, sizeof(oc->copyright), str_copyright);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_comment)
    
                pstrcpy(oc->comment, sizeof(oc->comment), str_comment);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        output_files[nb_output_files] = oc;
        /* dump the file content */
        dump_format(oc, nb_output_files, filename, 1);
        nb_output_files++;
    
        strcpy(oc->filename, filename);
    
    
        /* check filename in case of an image number is expected */
    
        if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
            if (filename_number_test(oc->filename) < 0) {
                print_error(oc->filename, AVERROR_NUMEXPECTED);
    
        if (!(oc->oformat->flags & AVFMT_NOFILE)) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* test if it already exists to avoid loosing precious files */
            if (!file_overwrite && 
                (strchr(filename, ':') == NULL ||
                 strstart(filename, "file:", NULL))) {
                if (url_exist(filename)) {
                    int c;
                    
                    printf("File '%s' already exists. Overwrite ? [y/N] ", filename);
                    fflush(stdout);
                    c = getchar();
                    if (toupper(c) != 'Y') {
                        fprintf(stderr, "Not overwriting - exiting\n");
                        exit(1);
                    }
                }
            }