Skip to content
Snippets Groups Projects
ffmpeg.c 63 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fabrice Bellard's avatar
    Fabrice Bellard committed
            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;
            if (ti1 < 0.1)
                ti1 = 0.1;
            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);
        }
        /* 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
        free(file_table);
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (ist_table) {
            for(i=0;i<nb_istreams;i++) {
                ist = ist_table[i];
                if (ist) {
                    free(ist);
                }
            }
            free(ist_table);
        }
        if (ost_table) {
            for(i=0;i<nb_ostreams;i++) {
                ost = ost_table[i];
                if (ost) {
                    if (ost->pict_tmp.data[0])
                        free(ost->pict_tmp.data[0]);
                    if (ost->video_resample)
                        img_resample_close(ost->img_resample_ctx);
                    if (ost->audio_resample)
                        audio_resample_close(ost->resample);
                    free(ost);
                }
            }
            free(ost_table);
        }
        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 Gerard Lantau\n"
        "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_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",
        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++;
        }
        motion_estimation_method = p - motion_str;
    }
    
    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++;
        m->stream_index = strtol(arg, (char **)&p, 0);
    }
    
    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, **ppktl;
        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;
                    }
                    avcodec_open(&st->codec, codec);
                }
            }
            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];
    
            /* 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);
                    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:
        if (count > 0) {
            /* close each codec */
            for(i=0;i<ic->nb_streams;i++) {
                st = ic->streams[i];
                avcodec_close(&st->codec);
            }
        }
        return ret;
    }
    
    
    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;
        int err, i, ret;
    
        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:
                audio_channels = enc->channels;
                audio_sample_rate = enc->sample_rate;
                break;
            case CODEC_TYPE_VIDEO:
                frame_height = enc->height;
                frame_width = enc->width;
                frame_rate = enc->frame_rate;
                break;
            }
        }
        
        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;
                }
            }
        }
        *has_video_ptr = has_video;
        *has_audio_ptr = has_audio;
    }
    
    
    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;
                }
    
                
                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;
    
                /* XXX: need to find a way to set codec parameters */
                if (oc->format == &ppm_format ||
                    oc->format == &ppmpipe_format) {
                    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_format->audio_codec;
                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;
                audio_enc->channels = audio_channels;
                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)
                nstrcpy(oc->title, sizeof(oc->title), str_title);
            if (str_author)
                nstrcpy(oc->author, sizeof(oc->author), str_author);
            if (str_copyright)
                nstrcpy(oc->copyright, sizeof(oc->copyright), str_copyright);
            if (str_comment)
                nstrcpy(oc->comment, sizeof(oc->comment), str_comment);
        }
    
        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->format->flags & AVFMT_NEEDNUMBER) {
            if (filename_number_test(oc->filename) < 0)
                exit(1);
        }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (!(oc->format->flags & AVFMT_NOFILE)) {
            /* 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_format = NULL;
        audio_disable = 0;
        video_disable = 0;
        audio_codec_id = CODEC_ID_NONE;
        video_codec_id = CODEC_ID_NONE;
    }
    
    
    #ifdef CONFIG_GRAB
    
    /* 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) {
            ic = av_open_input_file("", "video_grab_device", 0, ap);
            if (!ic) {
                fprintf(stderr, "Could not open video grab device\n");
                exit(1);
            }
            input_files[nb_input_files] = ic;
            dump_format(ic, nb_input_files, v4l_device, 0);
            nb_input_files++;
        }
        if (has_audio) {
            ic = av_open_input_file("", "audio_device", 0, ap);
            if (!ic) {
                fprintf(stderr, "Could not open audio grab device\n");
                exit(1);
            }
            input_files[nb_input_files] = ic;
            dump_format(ic, nb_input_files, audio_device, 0);
            nb_input_files++;
        }
    }
    
    #else
    
    void prepare_grab(void)
    {
        fprintf(stderr, "Must supply at least one input file\n");
        exit(1);
    }
    
    #endif
    
    /* open the necessary output devices for playing */
    void prepare_play(void)
    {
    
        file_format = guess_format("audio_device", NULL, NULL);
        if (!file_format) {
            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
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    void show_formats(void)
    {
        AVFormat *f;
        URLProtocol *up;
        AVCodec *p;
        const char **pp;
    
        printf("File formats:\n");
        printf("  Encoding:");
        for(f = first_format; f != NULL; f = f->next) {
            if (f->write_header)
                printf(" %s", f->name);
        }
        printf("\n");
        printf("  Decoding:");
        for(f = first_format; f != NULL; f = f->next) {
            if (f->read_header)
                printf(" %s", f->name);
        }
        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) == ME_ZERO) 
                printf("(fastest)");
            else if ((pp - motion_str) == ME_FULL) 
                printf("(slowest)");
            else if ((pp - motion_str) == ME_LOG) 
                printf("(default)");
            pp++;
        }
        printf("\n");
        exit(1);
    }
    
    void show_help(void)
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        const OptionDef *po;
        int i, expert;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        printf("%s version " FFMPEG_VERSION ", Copyright (c) 2000, 2001 Gerard Lantau\n", 
               prog);
        
        if (!do_play) {
            printf("usage: ffmpeg [[options] -i input_file]... {[options] outfile}...\n"
                   "Hyper fast MPEG1/MPEG4/H263/RV and AC3/MPEG audio encoder\n");
        } else {
            printf("usage: ffplay [options] input_file...\n"
                   "Simple audio player\n");
        }
               
        printf("\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
               "Main options are:\n");
        for(i=0;i<2;i++) {
            if (i == 1)
                printf("\nAdvanced options are:\n");
            for(po = options; po->name != NULL; po++) {
                char buf[64];
                expert = (po->flags & OPT_EXPERT) != 0;
                if (expert == i) {
                    strcpy(buf, po->name);
                    if (po->flags & HAS_ARG) {
                        strcat(buf, " ");
                        strcat(buf, po->argname);
                    }
                    printf("-%-17s  %s\n", buf, po->help);
                }
            }
        }
    
        exit(1);
    }
    
    const OptionDef options[] = {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "L", 0, {(void*)show_licence}, "show license" },
        { "h", 0, {(void*)show_help}, "show help" },
        { "formats", 0, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
        { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
        { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
        { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
        { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream" },
        { "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
        { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" },
        { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" },
        { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" },
        { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" },