Skip to content
Snippets Groups Projects
ffmpeg.c 163 KiB
Newer Older
  • Learn to ignore specific revisions
  • static void opt_video_codec(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        opt_codec(&video_stream_copy, &video_codec_name, AVMEDIA_TYPE_VIDEO, arg);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    static void opt_subtitle_codec(const char *arg)
    {
    
        opt_codec(&subtitle_stream_copy, &subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, arg);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int opt_codec_tag(const char *opt, const char *arg)
    
        uint32_t *codec_tag;
    
        codec_tag = !strcmp(opt, "atag") ? &audio_codec_tag :
                    !strcmp(opt, "vtag") ? &video_codec_tag :
                    !strcmp(opt, "stag") ? &subtitle_codec_tag : NULL;
    
        if (!codec_tag)
            return -1;
    
        *codec_tag = strtol(arg, &tail, 0);
        if (!tail || *tail)
    
            *codec_tag = AV_RL32(arg);
    
    static void opt_map(const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVStreamMap *m;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1);
        m = &stream_maps[nb_stream_maps-1];
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        m->file_index = strtol(arg, &p, 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (*p)
            p++;
    
        m->stream_index = strtol(p, &p, 0);
    
            m->sync_file_index = strtol(p, &p, 0);
    
            m->sync_stream_index = strtol(p, &p, 0);
    
        } else {
            m->sync_file_index = m->file_index;
            m->sync_stream_index = m->stream_index;
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void parse_meta_type(char *arg, char *type, int *index, char **endptr)
    
    {
        *endptr = arg;
        if (*arg == ',') {
            *type = *(++arg);
            switch (*arg) {
            case 'g':
                break;
            case 's':
            case 'c':
            case 'p':
                *index = strtol(++arg, endptr, 0);
                break;
            default:
                fprintf(stderr, "Invalid metadata type %c.\n", *arg);
                ffmpeg_exit(1);
            }
        } else
            *type = 'g';
    }
    
    
    static void opt_map_metadata(const char *arg)
    
        meta_data_maps = grow_array(meta_data_maps, sizeof(*meta_data_maps),
                                    &nb_meta_data_maps, nb_meta_data_maps + 1);
    
        m = &meta_data_maps[nb_meta_data_maps - 1][0];
        m->file = strtol(arg, &p, 0);
        parse_meta_type(p, &m->type, &m->index, &p);
    
        m1 = &meta_data_maps[nb_meta_data_maps - 1][1];
        m1->file = strtol(p, &p, 0);
        parse_meta_type(p, &m1->type, &m1->index, &p);
    
        if (m->type == 'g' || m1->type == 'g')
            metadata_global_autocopy = 0;
    
        if (m->type == 's' || m1->type == 's')
            metadata_streams_autocopy = 0;
        if (m->type == 'c' || m1->type == 'c')
            metadata_chapters_autocopy = 0;
    
    static void opt_map_meta_data(const char *arg)
    {
        fprintf(stderr, "-map_meta_data is deprecated and will be removed soon. "
                        "Use -map_metadata instead.\n");
        opt_map_metadata(arg);
    }
    
    
    static void opt_map_chapters(const char *arg)
    {
        AVChapterMap *c;
        char *p;
    
        chapter_maps = grow_array(chapter_maps, sizeof(*chapter_maps), &nb_chapter_maps,
                                  nb_chapter_maps + 1);
        c = &chapter_maps[nb_chapter_maps - 1];
        c->out_file = strtol(arg, &p, 0);
        if (*p)
            p++;
    
        c->in_file = strtol(p, &p, 0);
    }
    
    
    static void opt_input_ts_scale(const char *arg)
    {
        unsigned int stream;
        double scale;
        char *p;
    
        stream = strtol(arg, &p, 0);
        if (*p)
            p++;
        scale= strtod(p, &p);
    
        if(stream >= MAX_STREAMS)
    
            ffmpeg_exit(1);
    
        input_files_ts_scale[nb_input_files] = grow_array(input_files_ts_scale[nb_input_files], sizeof(*input_files_ts_scale[nb_input_files]), &nb_input_files_ts_scale[nb_input_files], stream + 1);
    
        input_files_ts_scale[nb_input_files][stream]= scale;
    }
    
    
    static int opt_recording_time(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        recording_time = parse_time_or_die(opt, arg, 1);
        return 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int opt_start_time(const char *opt, const char *arg)
    
        start_time = parse_time_or_die(opt, arg, 1);
        return 0;
    
    static int opt_recording_timestamp(const char *opt, const char *arg)
    
        recording_timestamp = parse_time_or_die(opt, arg, 0) / 1000000;
    
    static int opt_input_ts_offset(const char *opt, const char *arg)
    
        input_ts_offset = parse_time_or_die(opt, arg, 1);
        return 0;
    
    static enum CodecID find_codec_or_die(const char *name, int type, int encoder, int strict)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        const char *codec_string = encoder ? "encoder" : "decoder";
    
        AVCodec *codec;
    
        if(!name)
            return CODEC_ID_NONE;
        codec = encoder ?
            avcodec_find_encoder_by_name(name) :
            avcodec_find_decoder_by_name(name);
        if(!codec) {
    
            fprintf(stderr, "Unknown %s '%s'\n", codec_string, name);
    
            ffmpeg_exit(1);
    
            fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
    
            ffmpeg_exit(1);
    
        if(codec->capabilities & CODEC_CAP_EXPERIMENTAL &&
           strict > FF_COMPLIANCE_EXPERIMENTAL) {
            fprintf(stderr, "%s '%s' is experimental and might produce bad "
                    "results.\nAdd '-strict experimental' if you want to use it.\n",
                    codec_string, codec->name);
    
            codec = encoder ?
                avcodec_find_encoder(codec->id) :
                avcodec_find_decoder(codec->id);
            if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL))
                fprintf(stderr, "Or use the non experimental %s '%s'.\n",
                        codec_string, codec->name);
    
            ffmpeg_exit(1);
    
    static void opt_input_file(const char *filename)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVFormatContext *ic;
        AVFormatParameters params, *ap = &params;
    
        AVInputFormat *file_iformat = NULL;
    
        int64_t timestamp;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        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;
    
        /* 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;
    
            dec->thread_count = 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_aspect_ratio_override = 0;
    
                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->height = frame_height;
                    dec->width  = frame_width;
    
                    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 */
    
            av_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;
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        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);
            }
    
            if(frame_aspect_ratio_override){
                i = vfilters ? strlen(vfilters) : 0;
                vfilters = av_realloc(vfilters, i+100);
                snprintf(vfilters+i, 100, "%csetdar=%f\n", i?',':' ', frame_aspect_ratio);
                frame_aspect_ratio=0;
                frame_aspect_ratio_override=0;
            }
    
    
            ost->avfilter= vfilters;
            vfilters= NULL;
    
        }
    
        avcodec_get_context_defaults3(st->codec, codec);
    
        ost->bitstream_filters = video_bitstream_filters;
    
        st->codec->thread_count= 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);
    
            video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
    
            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)
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        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;
    
        st->codec->thread_count= 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 (av_get_channel_layout_nb_channels(channel_layout) != audio_channels)
    
        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)
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        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){
    
            if (subtitle_codec_name) {
                codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
                                             avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
                codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);
    
            } else {
                codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_SUBTITLE);
                codec = avcodec_find_encoder(codec_id);
            }
    
        }
        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 (oc->oformat->flags & AVFMT_GLOBALHEADER) {
            subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
            avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
    
        if (subtitle_stream_copy) {
            st->stream_copy = 1;
        } else {
    
            subtitle_enc->codec_id = codec_id;
    
            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;
    
            av_metadata_copy(&oc->metadata, metadata, 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 = avio_open(&oc->pb, filename, AVIO_WRONLY)) < 0) {
    
                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;
    
        set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
    
        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)
    {
    
        AVOutputFormat *oformat = NULL;