Skip to content
Snippets Groups Projects
ffmpeg.c 68.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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;
                }
    
                /* 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:
                        abort();
                    }
                }
    
    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_tick(&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_tick(&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;
    }
    
    
    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_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_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;
                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;
    
                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);
                    }
                }
            }
            
            /* open the file */
            if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
                fprintf(stderr, "Could not open '%s'\n", filename);
                exit(1);
            }
        }
    
        /* reset some options */
    
        file_oformat = NULL;
        file_iformat = NULL;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        audio_disable = 0;
        video_disable = 0;
        audio_codec_id = CODEC_ID_NONE;
        video_codec_id = CODEC_ID_NONE;
    }
    
    
    /* prepare dummy protocols for grab */
    void prepare_grab(void)
    {
        int has_video, has_audio, i, j;
        AVFormatContext *oc;
        AVFormatContext *ic;
        AVFormatParameters ap1, *ap = &ap1;
    
        /* see if audio/video inputs are needed */
        has_video = 0;
        has_audio = 0;
        memset(ap, 0, sizeof(*ap));
        for(j=0;j<nb_output_files;j++) {
            oc = output_files[j];
            for(i=0;i<oc->nb_streams;i++) {
                AVCodecContext *enc = &oc->streams[i]->codec;
                switch(enc->codec_type) {
                case CODEC_TYPE_AUDIO:
                    if (enc->sample_rate > ap->sample_rate)
                        ap->sample_rate = enc->sample_rate;
                    if (enc->channels > ap->channels)
                        ap->channels = enc->channels;
                    has_audio = 1;
                    break;
                case CODEC_TYPE_VIDEO:
                    if (enc->width > ap->width)
                        ap->width = enc->width;
                    if (enc->height > ap->height)
                        ap->height = enc->height;
                    if (enc->frame_rate > ap->frame_rate)
                        ap->frame_rate = enc->frame_rate;
                    has_video = 1;
                    break;
    
                }
            }
        }
        
        if (has_video == 0 && has_audio == 0) {
            fprintf(stderr, "Output file must have at least one audio or video stream\n");
            exit(1);
        }
        
        if (has_video) {
    
            AVInputFormat *fmt1;
            fmt1 = av_find_input_format("video_grab_device");
            if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
    
                fprintf(stderr, "Could not find video grab device\n");
    
            /* by now video grab has one stream */
            ic->streams[0]->r_frame_rate = ap->frame_rate;
    
            input_files[nb_input_files] = ic;
            dump_format(ic, nb_input_files, v4l_device, 0);
            nb_input_files++;
        }
        if (has_audio) {
    
            AVInputFormat *fmt1;
            fmt1 = av_find_input_format("audio_device");
            if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
    
                fprintf(stderr, "Could not find audio grab device\n");
    
                exit(1);
            }
            input_files[nb_input_files] = ic;
            dump_format(ic, nb_input_files, audio_device, 0);
            nb_input_files++;
        }
    }
    
    /* open the necessary output devices for playing */
    void prepare_play(void)
    {
    
        file_iformat = NULL;
        file_oformat = guess_format("audio_device", NULL, NULL);
        if (!file_oformat) {
    
            fprintf(stderr, "Could not find audio device\n");
            exit(1);
        }
        
        opt_output_file(audio_device);
    }
    
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #ifndef CONFIG_WIN32
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    INT64 getutime(void)
    {
        struct rusage rusage;
    
        getrusage(RUSAGE_SELF, &rusage);
        return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #else
    INT64 getutime(void)
    {
      return gettime();
    }
    #endif
    
    extern int ffm_nopts;
    
    void opt_bitexact(void)
    {
        avcodec_set_bit_exact();
        /* disable generate of real time pts in ffm (need to be supressed anyway) */
        ffm_nopts = 1;
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void show_formats(void)
    {
    
        AVInputFormat *ifmt;
        AVOutputFormat *ofmt;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        URLProtocol *up;
        AVCodec *p;
        const char **pp;
    
        printf("File formats:\n");
        printf("  Encoding:");
    
        for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) {
            printf(" %s", ofmt->name);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        printf("\n");
        printf("  Decoding:");
    
        for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) {
            printf(" %s", ifmt->name);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        printf("\n");
    
        printf("Codecs:\n");
        printf("  Encoders:");
        for(p = first_avcodec; p != NULL; p = p->next) {
            if (p->encode)
                printf(" %s", p->name);
        }
        printf("\n");
    
        printf("  Decoders:");
        for(p = first_avcodec; p != NULL; p = p->next) {
            if (p->decode)
                printf(" %s", p->name);
        }
        printf("\n");
    
        printf("Supported file protocols:");
        for(up = first_protocol; up != NULL; up = up->next)
            printf(" %s:", up->name);
        printf("\n");
        
        printf("Frame size abbreviations: sqcif qcif cif 4cif\n");
        printf("Motion estimation methods:");
        pp = motion_str;
        while (*pp) {
            printf(" %s", *pp);
    
            if ((pp - motion_str + 1) == ME_ZERO) 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                printf("(fastest)");
    
            else if ((pp - motion_str + 1) == ME_FULL) 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                printf("(slowest)");
    
            else if ((pp - motion_str + 1) == ME_EPZS) 
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                printf("(default)");