Skip to content
Snippets Groups Projects
ffmpeg.c 81.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fabrice Bellard's avatar
    Fabrice Bellard committed
                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 for input stream #%d.%d\n", 
                            ist->file_index, ist->index);
                    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 *ptr;
            int len;
            UINT8 *data_buf;
            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;
            }
    
            /* 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
    
    
            if (do_hex_dump) {
                printf("stream #%d, size=%d:\n", pkt.stream_index, pkt.size);
    
                av_hex_dump(pkt.data, pkt.size);
    
    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;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            while (len > 0) {
    
    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 *)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;
                }
                ptr += ret;
                len -= ret;
    
    
                ist->frame_decoded = 1;
    
    #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 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;
                        }
    
    
    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);
                                    if (do_vstats)
                                        do_video_stats(os, ost, 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 */
    
                            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
    
    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;
    }
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    void opt_video_buffer_size(const char *arg)
    {
        video_rc_buffer_size = atoi(arg) * 1000;
    }
    
    
    void opt_video_rc_eq(char *arg)
    {
        video_rc_eq = arg;
    }
    
    
    void opt_video_rc_override_string(char *arg)
    {
        video_rc_override_string = 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_idct_algo(const char *arg)
    {
        idct_algo = atoi(arg);
    }
    
    
    
    void opt_error_resilience(const char *arg)
    {
        error_resilience = atoi(arg);
    }
    
    
    void opt_error_concealment(const char *arg)
    {
        error_concealment = 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_rc_initial_cplx(const char *arg)
    {
        video_rc_initial_cplx = atof(arg);
    }
    
    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);
    }
    
    
    void opt_packet_size(const char *arg)
    {
        packet_size= atoi(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;
    
    
        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
        }
    }
    
    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;
    
    
        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)
                    break;
                p = p->next;
            }
            if (p == NULL) {
                fprintf(stderr, "Unknown video codec '%s'\n", arg);
                exit(1);
            } else {
                video_codec_id = p->id;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    }
    
    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; 
    
                enc->error_concealment = error_concealment; 
    
                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;
                if (video_stream_copy) {
                    st->stream_copy = 1;
                    video_enc->codec_type = CODEC_TYPE_VIDEO;
                } else {
    
                    codec_id = file_oformat->video_codec;
                    if (video_codec_id != CODEC_ID_NONE)
                        codec_id = video_codec_id;
                    
                    video_enc->codec_id = codec_id;
                    
                    video_enc->bit_rate = video_bit_rate;
                    video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
                    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;
                    }