Skip to content
Snippets Groups Projects
ffmpeg.c 76 KiB
Newer Older
  • Learn to ignore specific revisions
  •                     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;
                            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:
                        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->format->write_packet(os, ost->index, data_buf, data_size, pkt.pts);
    
    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];
            os->format->write_trailer(os);
        }
        /* 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) {
    
    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"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        "Copyright (c) 2000, 2001, 2002 Gerard Lantau\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        "This program is free software; you can redistribute it and/or modify\n"
        "it under the terms of the GNU General Public License as published by\n"
        "the Free Software Foundation; either version 2 of the License, or\n"
        "(at your option) any later version.\n"
        "\n"
        "This program is distributed in the hope that it will be useful,\n"
        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
        "GNU General Public License for more details.\n"
        "\n"
        "You should have received a copy of the GNU General Public License\n"
        "along with this program; if not, write to the Free Software\n"
        "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
        );
        exit(1);
    }
    
    void opt_format(const char *arg)
    {
        AVFormat *f;
        f = first_format;
        while (f != NULL && strcmp(f->name, arg) != 0) f = f->next;
        if (f == NULL) {
            fprintf(stderr, "Invalid format: %s\n", arg);
            exit(1);
        }
        file_format = f;
    }
    
    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);
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #ifdef CONFIG_GRAB
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void opt_video_device(const char *arg)
    {
        v4l_device = strdup(arg);
    }
    
    void opt_audio_device(const char *arg)
    {
        audio_device = strdup(arg);
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    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);
    }
    
    /* return the number of packet read to find the codec parameters */
    int find_codec_parameters(AVFormatContext *ic)
    {
        int val, i, count, ret, got_picture, size;
        AVCodec *codec;
        AVCodecContext *enc;
        AVStream *st;
        AVPacket *pkt;
        AVPicture picture;
    
        AVPacketList *pktl=NULL, **ppktl;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
        UINT8 *ptr;
    
        count = 0;
        ppktl = &ic->packet_buffer;
        for(;;) {
            for(i=0;i<ic->nb_streams;i++) {
                enc = &ic->streams[i]->codec;
                
                switch(enc->codec_type) {
                case CODEC_TYPE_AUDIO:
                    val = enc->sample_rate;
                    break;
                case CODEC_TYPE_VIDEO:
                    val = enc->width;
                    break;
                default:
                    val = 1;
                    break;
                }
                /* if no parameters supplied, then we should read it from
                   the stream */
                if (val == 0)
                    break;
            }
            if (i == ic->nb_streams) {
                ret = count;
                break;
            }
    
            if (count == 0) {
                /* open each codec */
                for(i=0;i<ic->nb_streams;i++) {
                    st = ic->streams[i];
                    codec = avcodec_find_decoder(st->codec.codec_id);
                    if (codec == NULL) {
                        ret = -1;
                        goto the_end;
                    }
    
                    ret = avcodec_open(&st->codec, codec);
                    if (ret < 0)
                        goto the_end;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
            }
            pktl = av_mallocz(sizeof(AVPacketList));
            if (!pktl) {
                ret = -1;
                break;
            }
    
            /* add the packet in the buffered packet list */
            *ppktl = pktl;
            ppktl = &pktl->next;
    
            pkt = &pktl->pkt;
            if (ic->format->read_packet(ic, pkt) < 0) {
                ret = -1;
                break;
            }
            st = ic->streams[pkt->stream_index];
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* decode the data and update codec parameters */
            ptr = pkt->data;
            size = pkt->size;
            while (size > 0) {
                switch(st->codec.codec_type) {
                case CODEC_TYPE_VIDEO:
                    ret = avcodec_decode_video(&st->codec, &picture, &got_picture, ptr, size);
    
                    if (st->codec.codec_id == CODEC_ID_MPEG1VIDEO) {
                        //mpegvid = pkt->stream_index;
                        //fps = st->codec.frame_rate;
                    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    break;
                case CODEC_TYPE_AUDIO:
                    ret = avcodec_decode_audio(&st->codec, samples, &got_picture, ptr, size);
                    break;
                default:
                    ret = -1;
                    break;
                }
                if (ret < 0) {
                    ret = -1;
                    goto the_end;
                }
                if (got_picture)
                    break;
                ptr += ret;
                size -= ret;
            }
    
            count++;
        }
     the_end:
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* close each codec */
            for(i=0;i<ic->nb_streams;i++) {
                st = ic->streams[i];
                avcodec_close(&st->codec);
            }
        }
        return ret;
    }
    
    
    /* Returns the real frame rate of telecine streams */
    int get_real_fps(AVFormatContext *ic, AVFormat *fmt, AVFormatParameters *ap, int stream_id)
    {
        int frame_num, r_frames, fps, rfps;
        int ret, got_picture, size;
        UINT8 *ptr;
        AVStream *st;
        AVPacket *pkt;
        AVPicture picture;
        AVPacketList *pktl=NULL, **ppktl=NULL;
        AVCodec *codec;
        AVFormatContext *fc;
                
        frame_num = 0;
        r_frames = 0;
        fps = rfps = -1;
        if (stream_id < 0 || stream_id >= ic->nb_streams)
            return -1;
    
        /* We must use another AVFormatContext, and open the
           file again, since we do not have good seeking */        
        fc = av_mallocz(sizeof(AVFormatContext));
        if (!fc)
            goto the_end;
        
        strcpy(fc->filename, ic->filename);
        
        /* open file */
        if (!(fmt->flags & AVFMT_NOFILE)) {
            if (url_fopen(&fc->pb, fc->filename, URL_RDONLY) < 0) {
                fprintf(stderr, "Could not open '%s'\n", fc->filename);
                exit(1);
            }
        }
        
        /* check format */
        if (!fmt) {
            goto the_end;
        }
        fc->format = fmt;
        
        /* Read header */
        ret = fc->format->read_header(fc, ap);
        if (ret < 0) {
            fprintf(stderr, "%s: Error while parsing header\n", fc->filename);
            goto the_end;
        }
    
        /* Find and open codec */    
        st = fc->streams[stream_id];
        codec = avcodec_find_decoder(st->codec.codec_id);
        if (codec == NULL) {
            goto the_end;
        }
        ret = avcodec_open(&st->codec, codec);
        if (ret < 0)
            goto the_end;
            
        ppktl = &fc->packet_buffer;    
        if (stream_id > -1) {
            /* check telecine MPEG video streams, we */
            /* decode 40 frames to get the real fps  */
            while(1) {
                
                pktl = av_mallocz(sizeof(AVPacketList));
                if (!pktl) {
                    goto the_end;
                    break;
                }
                /* add the packet in the buffered packet list */
                *ppktl = pktl;
                ppktl = &pktl->next;
    
                pkt = &pktl->pkt;
                if (fc->format->read_packet(fc, pkt) < 0) {
                    goto the_end;
                    break;
                }
                st = fc->streams[pkt->stream_index];
    
                /* decode the video */
                ptr = pkt->data;
                size = pkt->size;
                while (size > 0) {
                    if (pkt->stream_index == stream_id) {
                        ret = avcodec_decode_video(&st->codec, &picture, &got_picture, ptr, size);
                        fps = st->codec.frame_rate;                    
                        if (ret < 0) {
                            goto the_end;
                        }
                        if (got_picture) {
                            frame_num++;
                            r_frames += st->codec.repeat_pict;
                        }
                    }
                    ptr += ret;
                    size -= ret;
                 }
                 if (frame_num > 39)
                     break;
            }
            rfps = (fps * frame_num) / (frame_num + (r_frames >> 1)); 
            /* close codec */
            avcodec_close(&st->codec);
        }
    the_end:
        /* FIXME: leak in packet_buffer */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        av_free(fc);
    
    int filename_number_test(const char *filename)
    {
        char buf[1024];
    
        if (get_frame_filename(buf, sizeof(buf), filename, 1) < 0) {
            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);
            return -1;
        } else {
            return 0;
        }
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    void opt_input_file(const char *filename)
    {
        AVFormatContext *ic;
        AVFormatParameters params, *ap = &params;
        URLFormat url_format;
        AVFormat *fmt;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        ic = av_mallocz(sizeof(AVFormatContext));
        strcpy(ic->filename, filename);
        /* first format guess to know if we must open file */
        fmt = file_format;
        if (!fmt) 
            fmt = guess_format(NULL, filename, NULL);
        
        if (fmt == NULL || !(fmt->flags & AVFMT_NOFILE)) {
            /* open file */
            if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) {
                fprintf(stderr, "Could not open '%s'\n", filename);
                exit(1);
            }
        
            /* find format and set default parameters */
            fmt = file_format;
            err = url_getformat(url_fileno(&ic->pb), &url_format);
            if (err >= 0) {
                if (!fmt)
                    fmt = guess_format(url_format.format_name, NULL, NULL);
                ap->sample_rate = url_format.sample_rate;
                ap->frame_rate = url_format.frame_rate;
                ap->channels = url_format.channels;
                ap->width = url_format.width;
                ap->height = url_format.height;
                ap->pix_fmt = url_format.pix_fmt;
            } else {
                if (!fmt)
                    fmt = guess_format(NULL, filename, NULL);
                memset(ap, 0, sizeof(*ap));
            }
        } else {
            memset(ap, 0, sizeof(*ap));
        }
    
        if (!fmt || !fmt->read_header) {
            fprintf(stderr, "%s: Unknown file format\n", filename);
            exit(1);
        }
        ic->format = fmt;
    
        /* get default parameters from command line */
        if (!ap->sample_rate)
            ap->sample_rate = audio_sample_rate;
        if (!ap->channels)
            ap->channels = audio_channels;
    
        if (!ap->frame_rate)
            ap->frame_rate = frame_rate;
        if (!ap->width)
            ap->width = frame_width;
        if (!ap->height)
            ap->height = frame_height;
    
    
        /* check filename in case of an image number is expected */
        if (ic->format->flags & AVFMT_NEEDNUMBER) {
            if (filename_number_test(ic->filename) < 0)
                exit(1);
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        
        err = ic->format->read_header(ic, ap);
        if (err < 0) {
            fprintf(stderr, "%s: Error while parsing header\n", filename);
            exit(1);
        }
        
        /* If not enough info for the codecs, we decode the first frames
           to get it. (used in mpeg case for example) */
        ret = find_codec_parameters(ic);
        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 = enc->frame_rate;
                if (enc->codec_id == CODEC_ID_MPEG1VIDEO) {
                    rfps = get_real_fps(ic, fmt, ap, i);
                }
                if (rfps > 0 && rfps != enc->frame_rate) {
                    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);
                } else                   
                    frame_rate = enc->frame_rate;
                ic->streams[i]->r_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_format = NULL;
    }
    
    
    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_format) {
            file_format = guess_format(NULL, filename, NULL);
            if (!file_format)
                file_format = &mpeg_mux_format;
        }
        
        oc->format = file_format;
    
        if (!strcmp(file_format->name, "ffm") && 
            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_format->video_codec != CODEC_ID_NONE;
            use_audio = file_format->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_format->video_codec;
                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;