Skip to content
Snippets Groups Projects
ffmpeg.c 154 KiB
Newer Older
  • Learn to ignore specific revisions
  •     if (last_asked_format) {
    
            if (!(file_iformat = av_find_input_format(last_asked_format))) {
                fprintf(stderr, "Unknown input format: '%s'\n", last_asked_format);
    
                ffmpeg_exit(1);
    
        if (!strcmp(filename, "-"))
            filename = "pipe:";
    
    
        using_stdin |= !strncmp(filename, "pipe:", 5) ||
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* get default parameters from command line */
    
        if (!ic) {
            print_error(filename, AVERROR(ENOMEM));
    
            ffmpeg_exit(1);
    
        ap->prealloced_context = 1;
    
        ap->sample_rate = audio_sample_rate;
        ap->channels = audio_channels;
    
        ap->time_base.den = frame_rate.num;
        ap->time_base.num = frame_rate.den;
    
        ap->width = frame_width;
        ap->height = frame_height;
    
        ap->pix_fmt = frame_pix_fmt;
    
       // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
    
        ap->channel = video_channel;
        ap->standard = video_standard;
    
        set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
    
        ic->video_codec_id   =
            find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0,
                              avcodec_opts[AVMEDIA_TYPE_VIDEO   ]->strict_std_compliance);
        ic->audio_codec_id   =
            find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0,
                              avcodec_opts[AVMEDIA_TYPE_AUDIO   ]->strict_std_compliance);
        ic->subtitle_codec_id=
            find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0,
                              avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
    
        ic->flags |= AVFMT_FLAG_NONBLOCK;
    
        if(pgmyuv_compatibility_hack)
            ic->video_codec_id= CODEC_ID_PGMYUV;
    
    
        /* 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) {
    
            ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
            int i, j;
            int found=0;
            for(i=0; i<ic->nb_streams; i++){
                ic->streams[i]->discard= AVDISCARD_ALL;
            }
            for(i=0; i<ic->nb_programs; i++){
                AVProgram *p= ic->programs[i];
                if(p->id != opt_programid){
                    p->discard = AVDISCARD_ALL;
                }else{
                    found=1;
                    for(j=0; j<p->nb_stream_indexes; j++){
    
                        ic->streams[p->stream_index[j]]->discard= AVDISCARD_DEFAULT;
    
                    }
                }
            }
            if(!found){
                fprintf(stderr, "Specified program id not found\n");
    
                ffmpeg_exit(1);
    
            }
            opt_programid=0;
    
        /* 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);
    
        if (ret < 0 && verbose >= 0) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            fprintf(stderr, "%s: could not find codec parameters\n", filename);
    
            av_close_input_file(ic);
    
            ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        timestamp = start_time;
        /* add the stream start time */
        if (ic->start_time != AV_NOPTS_VALUE)
            timestamp += ic->start_time;
    
    
        /* if seeking requested, we execute it */
        if (start_time != 0) {
    
            ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
    
                fprintf(stderr, "%s: could not seek to position %0.3f\n",
    
                        filename, (double)timestamp / AV_TIME_BASE);
            }
            /* reset seek info */
            start_time = 0;
        }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* update the current parameters so that they match the one of the input stream */
        for(i=0;i<ic->nb_streams;i++) {
    
            AVStream *st = ic->streams[i];
    
            AVCodecContext *dec = st->codec;
            avcodec_thread_init(dec, thread_count);
    
            input_codecs = grow_array(input_codecs, sizeof(*input_codecs), &nb_input_codecs, nb_input_codecs + 1);
    
            switch (dec->codec_type) {
    
                input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(audio_codec_name);
                set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
    
                //fprintf(stderr, "\nInput Audio channels: %d", dec->channels);
                channel_layout    = dec->channel_layout;
                audio_channels    = dec->channels;
                audio_sample_rate = dec->sample_rate;
                audio_sample_fmt  = dec->sample_fmt;
    
                    st->discard= AVDISCARD_ALL;
    
                /* Note that av_find_stream_info can add more streams, and we
                 * currently have no chance of setting up lowres decoding
                 * early enough for them. */
                if (dec->lowres)
                    audio_sample_rate >>= dec->lowres;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
                input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(video_codec_name);
                set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
    
                frame_height = dec->height;
                frame_width  = dec->width;
    
                if(ic->streams[i]->sample_aspect_ratio.num)
                    frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio);
                else
    
                    frame_aspect_ratio=av_q2d(dec->sample_aspect_ratio);
                frame_aspect_ratio *= (float) dec->width / dec->height;
                frame_pix_fmt = dec->pix_fmt;
    
                rfps      = ic->streams[i]->r_frame_rate.num;
                rfps_base = ic->streams[i]->r_frame_rate.den;
    
                if (dec->lowres) {
                    dec->flags |= CODEC_FLAG_EMU_EDGE;
                    frame_height >>= dec->lowres;
                    frame_width  >>= dec->lowres;
    
                    dec->debug |= FF_DEBUG_MV;
    
                if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
    
                        fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
    
                                i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
    
                        (float)rfps / rfps_base, rfps, rfps_base);
    
                /* update the current frame rate to match the stream frame rate */
    
                frame_rate.num = rfps;
                frame_rate.den = rfps_base;
    
                    st->discard= AVDISCARD_ALL;
    
                else if(video_discard)
    
                    st->discard= video_discard;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
                input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(subtitle_codec_name);
    
                    st->discard = AVDISCARD_ALL;
    
            case AVMEDIA_TYPE_ATTACHMENT:
            case AVMEDIA_TYPE_UNKNOWN:
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        input_files[nb_input_files] = ic;
    
        input_files_ts_offset[nb_input_files] = input_ts_offset - (copy_ts ? 0 : timestamp);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* dump the file content */
    
        if (verbose >= 0)
            dump_format(ic, nb_input_files, filename, 0);
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        nb_input_files++;
    
        video_channel = 0;
    
        av_freep(&video_codec_name);
        av_freep(&audio_codec_name);
        av_freep(&subtitle_codec_name);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
                                             int *has_subtitle_ptr)
    
        int has_video, has_audio, has_subtitle, i, j;
    
        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;
    
                case AVMEDIA_TYPE_DATA:
                case AVMEDIA_TYPE_ATTACHMENT:
                case AVMEDIA_TYPE_UNKNOWN:
    
                }
            }
        }
        *has_video_ptr = has_video;
        *has_audio_ptr = has_audio;
    
        *has_subtitle_ptr = has_subtitle;
    
    static void new_video_stream(AVFormatContext *oc, int file_idx)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVStream *st;
    
        enum CodecID codec_id;
    
        st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
    
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
    
            ffmpeg_exit(1);
    
        ost = new_output_stream(oc, file_idx);
    
        output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
    
        if(!video_stream_copy){
            if (video_codec_name) {
                codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1,
                                             avcodec_opts[AVMEDIA_TYPE_VIDEO]->strict_std_compliance);
                codec = avcodec_find_encoder_by_name(video_codec_name);
    
                output_codecs[nb_output_codecs-1] = codec;
    
            } else {
                codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
                codec = avcodec_find_encoder(codec_id);
            }
        }
    
        avcodec_get_context_defaults3(st->codec, codec);
    
        ost->bitstream_filters = video_bitstream_filters;
    
    Måns Rullgård's avatar
    Måns Rullgård committed
        avcodec_thread_init(st->codec, thread_count);
    
        if(video_codec_tag)
            video_enc->codec_tag= video_codec_tag;
    
           || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){
    
            video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
    
            avcodec_opts[AVMEDIA_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
    
        }
        if(video_global_header&2){
    
            video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
    
            avcodec_opts[AVMEDIA_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER;
    
        if (video_stream_copy) {
            st->stream_copy = 1;
    
            video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
    
            video_enc->sample_aspect_ratio =
    
            st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
    
            const char *p;
    
            AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
    
            set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
    
            if (codec && codec->supported_framerates && !force_fps)
                fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
    
            video_enc->time_base.den = fps.num;
            video_enc->time_base.num = fps.den;
    
            video_enc->width = frame_width;
            video_enc->height = frame_height;
    
            video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
    
            st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
    
                video_enc->gop_size = 0;
            if (video_qscale || same_quality) {
                video_enc->flags |= CODEC_FLAG_QSCALE;
    
                video_enc->global_quality=
    
                    st->quality = FF_QP2LAMBDA * video_qscale;
            }
    
            if(intra_matrix)
                video_enc->intra_matrix = intra_matrix;
            if(inter_matrix)
                video_enc->inter_matrix = inter_matrix;
    
            p= video_rc_override_string;
            for(i=0; p; i++){
                int start, end, q;
                int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
                if(e!=3){
                    fprintf(stderr, "error parsing rc_override\n");
    
                    ffmpeg_exit(1);
    
                video_enc->rc_override=
                    av_realloc(video_enc->rc_override,
    
                               sizeof(RcOverride)*(i+1));
                video_enc->rc_override[i].start_frame= start;
                video_enc->rc_override[i].end_frame  = end;
                if(q>0){
                    video_enc->rc_override[i].qscale= q;
                    video_enc->rc_override[i].quality_factor= 1.0;
                }
                else{
                    video_enc->rc_override[i].qscale= 0;
                    video_enc->rc_override[i].quality_factor= -q/100.0;
                }
                p= strchr(p, '/');
                if(p) p++;
            }
            video_enc->rc_override_count=i;
    
            if (!video_enc->rc_initial_buffer_occupancy)
                video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
    
            video_enc->me_threshold= me_threshold;
            video_enc->intra_dc_precision= intra_dc_precision - 8;
    
            if (do_psnr)
                video_enc->flags|= CODEC_FLAG_PSNR;
    
            /* two pass mode */
            if (do_pass) {
                if (do_pass == 1) {
                    video_enc->flags |= CODEC_FLAG_PASS1;
                } else {
                    video_enc->flags |= CODEC_FLAG_PASS2;
                }
            }
    
    
            if (forced_key_frames)
                parse_forced_key_frames(forced_key_frames, ost, video_enc);
    
            av_metadata_set2(&st->metadata, "language", video_language, 0);
    
    
        /* reset some key parameters */
        video_disable = 0;
    
        av_freep(&forced_key_frames);
    
        frame_pix_fmt = PIX_FMT_NONE;
    
    static void new_audio_stream(AVFormatContext *oc, int file_idx)
    
        enum CodecID codec_id;
    
        st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
    
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
    
            ffmpeg_exit(1);
    
        ost = new_output_stream(oc, file_idx);
    
        output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
    
        if(!audio_stream_copy){
            if (audio_codec_name) {
                codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1,
                                             avcodec_opts[AVMEDIA_TYPE_AUDIO]->strict_std_compliance);
                codec = avcodec_find_encoder_by_name(audio_codec_name);
    
                output_codecs[nb_output_codecs-1] = codec;
    
            } else {
                codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
                codec = avcodec_find_encoder(codec_id);
            }
        }
    
        avcodec_get_context_defaults3(st->codec, codec);
    
        ost->bitstream_filters = audio_bitstream_filters;
    
    Måns Rullgård's avatar
    Måns Rullgård committed
        avcodec_thread_init(st->codec, thread_count);
    
        audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
    
        if(audio_codec_tag)
            audio_enc->codec_tag= audio_codec_tag;
    
        if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
    
            audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
    
            avcodec_opts[AVMEDIA_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
    
        if (audio_stream_copy) {
            st->stream_copy = 1;
            audio_enc->channels = audio_channels;
    
            audio_enc->sample_rate = audio_sample_rate;
    
            set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
    
            if (audio_qscale > QSCALE_NONE) {
                audio_enc->flags |= CODEC_FLAG_QSCALE;
                audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
            }
    
            audio_enc->channels = audio_channels;
    
            audio_enc->sample_fmt = audio_sample_fmt;
    
            audio_enc->sample_rate = audio_sample_rate;
    
            audio_enc->channel_layout = channel_layout;
    
            if (avcodec_channel_layout_num_channels(channel_layout) != audio_channels)
                audio_enc->channel_layout = 0;
    
        audio_enc->time_base= (AVRational){1, audio_sample_rate};
    
            av_metadata_set2(&st->metadata, "language", audio_language, 0);
    
    static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
    
        st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
    
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
    
            ffmpeg_exit(1);
    
        ost = new_output_stream(oc, file_idx);
    
        subtitle_enc = st->codec;
    
        output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
    
        if(!subtitle_stream_copy){
            subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,
                                                       avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
    
            codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);
    
        }
        avcodec_get_context_defaults3(st->codec, codec);
    
        ost->bitstream_filters = subtitle_bitstream_filters;
    
        subtitle_bitstream_filters= NULL;
    
    
        subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
    
    
        if(subtitle_codec_tag)
            subtitle_enc->codec_tag= subtitle_codec_tag;
    
    
        if (subtitle_stream_copy) {
            st->stream_copy = 1;
        } else {
    
            set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
    
            av_metadata_set2(&st->metadata, "language", subtitle_language, 0);
    
            av_freep(&subtitle_language);
    
    static int opt_new_stream(const char *opt, const char *arg)
    
        int file_idx = nb_output_files - 1;
    
        if (nb_output_files <= 0) {
            fprintf(stderr, "At least one output file must be specified\n");
    
            ffmpeg_exit(1);
    
        if      (!strcmp(opt, "newvideo"   )) new_video_stream   (oc, file_idx);
        else if (!strcmp(opt, "newaudio"   )) new_audio_stream   (oc, file_idx);
        else if (!strcmp(opt, "newsubtitle")) new_subtitle_stream(oc, file_idx);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        else av_assert0(0);
    
    /* arg format is "output-stream-index:streamid-value". */
    
    static int opt_streamid(const char *opt, const char *arg)
    
    {
        int idx;
        char *p;
        char idx_str[16];
    
        strncpy(idx_str, arg, sizeof(idx_str));
        idx_str[sizeof(idx_str)-1] = '\0';
        p = strchr(idx_str, ':');
        if (!p) {
            fprintf(stderr,
                    "Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
                    arg, opt);
    
            ffmpeg_exit(1);
    
        }
        *p++ = '\0';
        idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
    
        streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1);
    
        streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
    
    static void opt_output_file(const char *filename)
    {
        AVFormatContext *oc;
    
        int err, use_video, use_audio, use_subtitle;
    
        int input_has_video, input_has_audio, input_has_subtitle;
    
        AVOutputFormat *file_oformat;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        if (!strcmp(filename, "-"))
            filename = "pipe:";
    
    
        if (!oc) {
            print_error(filename, AVERROR(ENOMEM));
    
            ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (last_asked_format) {
    
            file_oformat = av_guess_format(last_asked_format, NULL, NULL);
    
            if (!file_oformat) {
                fprintf(stderr, "Requested output format '%s' is not a suitable output format\n", last_asked_format);
    
                ffmpeg_exit(1);
    
            }
            last_asked_format = NULL;
        } else {
    
            file_oformat = av_guess_format(NULL, filename, NULL);
    
                fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
    
                ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        av_strlcpy(oc->filename, filename, sizeof(oc->filename));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (!strcmp(file_oformat->name, "ffm") &&
    
            av_strstart(filename, "http:", NULL)) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* special case for files sent to ffserver: we get the stream
               parameters from ffserver */
    
            int err = read_ffserver_streams(oc, filename);
            if (err < 0) {
                print_error(filename, err);
    
                ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        } else {
    
            use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
            use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
            use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
    
            /* disable if no corresponding type found and at least one
               input file */
            if (nb_input_files > 0) {
    
                check_audio_video_sub_inputs(&input_has_video, &input_has_audio,
                                             &input_has_subtitle);
    
                if (!input_has_video)
                    use_video = 0;
                if (!input_has_audio)
                    use_audio = 0;
    
                if (!input_has_subtitle)
                    use_subtitle = 0;
    
            if (audio_disable)    use_audio    = 0;
            if (video_disable)    use_video    = 0;
            if (subtitle_disable) use_subtitle = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
            if (use_video)    new_video_stream(oc, nb_output_files);
            if (use_audio)    new_audio_stream(oc, nb_output_files);
            if (use_subtitle) new_subtitle_stream(oc, nb_output_files);
    
            oc->timestamp = recording_timestamp;
    
            while ((tag = av_metadata_get(metadata, "", tag, AV_METADATA_IGNORE_SUFFIX)))
                av_metadata_set2(&oc->metadata, tag->key, tag->value, 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        output_files[nb_output_files++] = oc;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* check filename in case of an image number is expected */
    
        if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
    
                print_error(oc->filename, AVERROR_NUMEXPECTED);
    
                ffmpeg_exit(1);
    
        if (!(oc->oformat->flags & AVFMT_NOFILE)) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* test if it already exists to avoid loosing precious files */
    
            if (!file_overwrite &&
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                (strchr(filename, ':') == NULL ||
    
                 av_strstart(filename, "file:", NULL))) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                if (url_exist(filename)) {
    
                        fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                        fflush(stderr);
    
                        if (!read_yesno()) {
    
                            fprintf(stderr, "Not overwriting - exiting\n");
    
                            ffmpeg_exit(1);
    
                        fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
    
                        ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* open the file */
    
            if ((err = url_fopen(&oc->pb, filename, URL_WRONLY)) < 0) {
                print_error(filename, err);
    
                ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        }
    
    
        memset(ap, 0, sizeof(*ap));
        if (av_set_parameters(oc, ap) < 0) {
            fprintf(stderr, "%s: Invalid encoding parameters\n",
                    oc->filename);
    
            ffmpeg_exit(1);
    
        oc->preload= (int)(mux_preload*AV_TIME_BASE);
        oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
    
        oc->loop_output = loop_output;
    
        oc->flags |= AVFMT_FLAG_NONBLOCK;
    
        set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
    
        nb_streamid_map = 0;
    
        av_freep(&forced_key_frames);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    /* same option as mencoder */
    
    static void opt_pass(const char *pass_str)
    
    {
        int pass;
        pass = atoi(pass_str);
        if (pass != 1 && pass != 2) {
            fprintf(stderr, "pass number can be only 1 or 2\n");
    
            ffmpeg_exit(1);
    
    static int64_t getutime(void)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        struct rusage rusage;
    
        getrusage(RUSAGE_SELF, &rusage);
        return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
    
    #elif HAVE_GETPROCESSTIMES
    
        HANDLE proc;
        FILETIME c, e, k, u;
        proc = GetCurrentProcess();
        GetProcessTimes(proc, &c, &e, &k, &u);
        return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
    #else
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        return av_gettime();
    
    Ramiro Polla's avatar
    Ramiro Polla committed
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    static int64_t getmaxrss(void)
    {
    #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
        struct rusage rusage;
        getrusage(RUSAGE_SELF, &rusage);
        return (int64_t)rusage.ru_maxrss * 1024;
    #elif HAVE_GETPROCESSMEMORYINFO
        HANDLE proc;
        PROCESS_MEMORY_COUNTERS memcounters;
        proc = GetCurrentProcess();
        memcounters.cb = sizeof(memcounters);
        GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
        return memcounters.PeakPagefileUsage;
    #else
        return 0;
    #endif
    }
    
    
    static void parse_matrix_coeffs(uint16_t *dest, const char *str)
    
    {
        int i;
        const char *p = str;
        for(i = 0;; i++) {
            dest[i] = atoi(p);
            if(i == 63)
                break;
            p = strchr(p, ',');
            if(!p) {
                fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
    
                ffmpeg_exit(1);
    
    static void opt_inter_matrix(const char *arg)
    
    {
        inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
        parse_matrix_coeffs(inter_matrix, arg);
    }
    
    
    static void opt_intra_matrix(const char *arg)
    
    {
        intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
        parse_matrix_coeffs(intra_matrix, arg);
    }
    
    
    static void show_usage(void)
    
        printf("Hyper fast Audio and Video encoder\n");
    
        printf("usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...\n");
    
    }
    
    static void show_help(void)
    {
        av_log_set_callback(log_callback_help);
        show_usage();
    
        show_help_options(options, "Main options:\n",
    
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0);
    
        show_help_options(options, "\nAdvanced options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB,
                          OPT_EXPERT);
    
        show_help_options(options, "\nVideo options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_VIDEO);
        show_help_options(options, "\nAdvanced Video options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_VIDEO | OPT_EXPERT);
        show_help_options(options, "\nAudio options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_AUDIO);
        show_help_options(options, "\nAdvanced Audio options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_AUDIO | OPT_EXPERT);
        show_help_options(options, "\nSubtitle options:\n",
                          OPT_SUBTITLE | OPT_GRAB,
                          OPT_SUBTITLE);
        show_help_options(options, "\nAudio/Video grab options:\n",
                          OPT_GRAB,
                          OPT_GRAB);
    
        av_opt_show2(avcodec_opts[0], NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
    
        av_opt_show2(avformat_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
    
        av_opt_show2(sws_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
    
    static void opt_target(const char *arg)
    {
    
        enum { PAL, NTSC, FILM, UNKNOWN } norm = UNKNOWN;
    
        static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
    
            arg += 4;
        } else if(!strncmp(arg, "ntsc-", 5)) {
    
        } else if(!strncmp(arg, "film-", 5)) {
    
        } else {
            int fr;
            /* Calculate FR via float to avoid int overflow */
    
            fr = (int)(frame_rate.num * 1000.0 / frame_rate.den);
    
            } else if((fr == 29970) || (fr == 23976)) {
    
            } else {
                /* Try to determine PAL/NTSC by peeking in the input files */
                if(nb_input_files) {
                    int i, j;
                    for(j = 0; j < nb_input_files; j++) {
                        for(i = 0; i < input_files[j]->nb_streams; i++) {
    
                            AVCodecContext *c = input_files[j]->streams[i]->codec;
    
                            if(c->codec_type != AVMEDIA_TYPE_VIDEO)
    
                            fr = c->time_base.den * 1000 / c->time_base.num;
    
                                break;
                            } else if((fr == 29970) || (fr == 23976)) {
    
                fprintf(stderr, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC");
    
            fprintf(stderr, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
            fprintf(stderr, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
    
            fprintf(stderr, "or set a framerate with \"-r xxx\".\n");
    
            ffmpeg_exit(1);
    
        }
    
        if(!strcmp(arg, "vcd")) {
    
            opt_video_codec("mpeg1video");
            opt_audio_codec("mp2");
            opt_format("vcd");
    
    
            opt_frame_size(norm == PAL ? "352x288" : "352x240");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("g", norm == PAL ? "15" : "18");
    
            opt_default("maxrate", "1150000");
            opt_default("minrate", "1150000");
    
            opt_default("bufsize", "327680"); // 40*1024*8;
    
            audio_channels = 2;
    
            opt_default("packetsize", "2324");
    
            opt_default("muxrate", "1411200"); // 2352 * 75 * 8;
    
            /* We have to offset the PTS, so that it is consistent with the SCR.
               SCR starts at 36000, but the first two packs contain only padding
               and the first pack from the other stream, respectively, may also have
               been written before.
               So the real data starts at SCR 36000+3*1200. */
            mux_preload= (36000+3*1200) / 90000.0; //0.44
    
        } else if(!strcmp(arg, "svcd")) {
    
            opt_video_codec("mpeg2video");
            opt_audio_codec("mp2");
    
            opt_frame_size(norm == PAL ? "480x576" : "480x480");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("g", norm == PAL ? "15" : "18");
    
            opt_default("maxrate", "2516000");
            opt_default("minrate", "0"); //1145000;
    
            opt_default("bufsize", "1835008"); //224*1024*8;
    
            opt_default("flags", "+scan_offset");
    
            opt_default("packetsize", "2324");
    
        } else if(!strcmp(arg, "dvd")) {
    
            opt_video_codec("mpeg2video");
            opt_audio_codec("ac3");
    
            opt_frame_size(norm == PAL ? "720x576" : "720x480");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("g", norm == PAL ? "15" : "18");
    
            opt_default("maxrate", "9000000");
            opt_default("minrate", "0"); //1500000;
    
            opt_default("bufsize", "1835008"); //224*1024*8;
    
            opt_default("packetsize", "2048");  // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
    
            opt_default("muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
    
            opt_frame_size(norm == PAL ? "720x576" : "720x480");
    
            opt_frame_pix_fmt(!strncmp(arg, "dv50", 4) ? "yuv422p" :
    
                              (norm == PAL ? "yuv420p" : "yuv411p"));
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
        } else {
            fprintf(stderr, "Unknown target: %s\n", arg);
    
            ffmpeg_exit(1);
    
    static void opt_vstats_file (const char *arg)
    {
        av_free (vstats_filename);
        vstats_filename=av_strdup (arg);
    }
    
    static void opt_vstats (void)
    {
        char filename[40];
        time_t today2 = time(NULL);
        struct tm *today = localtime(&today2);
    
        snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min,
                 today->tm_sec);
        opt_vstats_file(filename);
    }
    
    
    static int opt_bsf(const char *opt, const char *arg)
    
    {
        AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
        AVBitStreamFilterContext **bsfp;
    
        if(!bsfc){
    
    Alex Beregszaszi's avatar
    Alex Beregszaszi committed
            fprintf(stderr, "Unknown bitstream filter %s\n", arg);
    
            ffmpeg_exit(1);
    
        bsfp= *opt == 'v' ? &video_bitstream_filters :
              *opt == 'a' ? &audio_bitstream_filters :
                            &subtitle_bitstream_filters;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    static int opt_preset(const char *opt, const char *arg)
    {
    
        char filename[1000], tmp[1000], tmp2[1000], line[1000];
    
        const char *base[3]= { getenv("FFMPEG_DATADIR"),
                               getenv("HOME"),
    
            for(i=0; i<3 && !f; i++){
                if(!base[i])
                    continue;
                snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", arg);