Skip to content
Snippets Groups Projects
ffmpeg.c 169 KiB
Newer Older
  • Learn to ignore specific revisions
  •     return 0;
    
    static int opt_frame_aspect_ratio(const char *opt, const char *arg)
    
            x = strtol(arg, &end, 10);
            if (end == p)
                y = strtol(end+1, &end, 10);
    
            if (x > 0 && y > 0)
                ar = (double)x / (double)y;
    
            ar = strtod(arg, NULL);
    
    
        if (!ar) {
            fprintf(stderr, "Incorrect aspect ratio specification.\n");
    
            return AVERROR(EINVAL);
    
        return 0;
    
    static int opt_metadata(const char *opt, const char *arg)
    {
        char *mid= strchr(arg, '=');
    
        if(!mid){
            fprintf(stderr, "Missing =\n");
    
            ffmpeg_exit(1);
    
        av_dict_set(&metadata, arg, mid, 0);
    
    static int opt_qscale(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
        if (video_qscale <= 0 || video_qscale > 255) {
    
    Loren Merritt's avatar
    Loren Merritt committed
            fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int opt_top_field_first(const char *opt, const char *arg)
    
        top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
    
        return opt_default(opt, arg);
    
    static int opt_thread_count(const char *opt, const char *arg)
    
        thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
    
        if (verbose >= 0)
            fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
    
    static int opt_audio_sample_fmt(const char *opt, const char *arg)
    
            audio_sample_fmt = av_get_sample_fmt(arg);
    
            if (audio_sample_fmt == AV_SAMPLE_FMT_NONE) {
                av_log(NULL, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
    
                return AVERROR(EINVAL);
    
            int i;
            char fmt_str[128];
            for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
                printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
    
            ffmpeg_exit(0);
    
        return 0;
    
    static int opt_audio_rate(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
        return 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int opt_audio_channels(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
        return 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int opt_video_channel(const char *opt, const char *arg)
    
        av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
    
        return opt_default("channel", arg);
    
    static int opt_video_standard(const char *opt, const char *arg)
    
        av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
    
        return opt_default("standard", arg);
    
    static int opt_codec(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        int *pstream_copy; char **pcodec_name; enum AVMediaType codec_type;
    
        if      (!strcmp(opt, "acodec")) { pstream_copy = &audio_stream_copy;    pcodec_name = &audio_codec_name;    codec_type = AVMEDIA_TYPE_AUDIO;    }
        else if (!strcmp(opt, "vcodec")) { pstream_copy = &video_stream_copy;    pcodec_name = &video_codec_name;    codec_type = AVMEDIA_TYPE_VIDEO;    }
        else if (!strcmp(opt, "scodec")) { pstream_copy = &subtitle_stream_copy; pcodec_name = &subtitle_codec_name; codec_type = AVMEDIA_TYPE_SUBTITLE; }
        else if (!strcmp(opt, "dcodec")) { pstream_copy = &data_stream_copy;     pcodec_name = &data_codec_name;     codec_type = AVMEDIA_TYPE_DATA;     }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        } else {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        return 0;
    
    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 int opt_map(const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
    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;
        }
    
        return 0;
    
    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 int opt_map_metadata(const char *opt, const char *arg)
    
        MetadataMap *m, *m1;
    
        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 int opt_map_meta_data(const char *opt, const char *arg)
    
    {
        fprintf(stderr, "-map_meta_data is deprecated and will be removed soon. "
                        "Use -map_metadata instead.\n");
    
        return opt_map_metadata(opt, arg);
    
    static int opt_map_chapters(const char *opt, const char *arg)
    
        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);
    
        return 0;
    
    static int opt_input_ts_scale(const char *opt, const char *arg)
    
    {
        unsigned int stream;
        double scale;
        char *p;
    
        stream = strtol(arg, &p, 0);
        if (*p)
            p++;
        scale= strtod(p, &p);
    
    
        ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1);
        ts_scale[stream] = scale;
    
        return 0;
    
    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)
    
        char buf[128];
        int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
        struct tm time = *gmtime((time_t*)&recording_timestamp);
        strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
        opt_metadata("metadata", buf);
    
        av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
                                     "tag instead.\n", opt);
    
    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)
    
    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);
    
    static int opt_input_file(const char *opt, const char *filename)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVFormatContext *ic;
    
        AVInputFormat *file_iformat = NULL;
    
        int64_t timestamp;
    
        uint8_t buf[128];
    
        AVDictionary **opts;
        int orig_nb_streams;                     // number of streams before avformat_find_stream_info
    
    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);
    
        if (audio_sample_rate) {
            snprintf(buf, sizeof(buf), "%d", audio_sample_rate);
            av_dict_set(&format_opts, "sample_rate", buf, 0);
        }
        if (audio_channels) {
            snprintf(buf, sizeof(buf), "%d", audio_channels);
            av_dict_set(&format_opts, "channels", buf, 0);
        }
        if (frame_rate.num) {
            snprintf(buf, sizeof(buf), "%d/%d", frame_rate.num, frame_rate.den);
            av_dict_set(&format_opts, "framerate", buf, 0);
        }
        if (frame_width && frame_height) {
            snprintf(buf, sizeof(buf), "%dx%d", frame_width, frame_height);
            av_dict_set(&format_opts, "video_size", buf, 0);
        }
        if (frame_pix_fmt != PIX_FMT_NONE)
            av_dict_set(&format_opts, "pixel_format", av_get_pix_fmt_name(frame_pix_fmt), 0);
    
            find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0);
    
            find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0);
    
            find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
    
        ic->flags |= AVFMT_FLAG_NONBLOCK;
    
    Carl Eugen Hoyos's avatar
    Carl Eugen Hoyos committed
        if (loop_input) {
            av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n");
            ic->loop_input = loop_input;
        }
    
    
        /* open the input file with generic libav function */
    
        err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (err < 0) {
    
            ffmpeg_exit(1);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        assert_avoptions(format_opts);
    
    
            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;
    
        /* Set AVCodecContext options for avformat_find_stream_info */
    
        opts = setup_find_stream_info_opts(ic, codec_opts);
    
        orig_nb_streams = ic->nb_streams;
    
        /* If not enough info to get the stream parameters, we decode the
           first frames to get it. (used in mpeg case for example) */
    
        ret = avformat_find_stream_info(ic, opts);
    
        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;
    
            InputStream *ist;
    
            dec->thread_count = thread_count;
    
    
            input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
            ist = &input_streams[nb_input_streams - 1];
            ist->st = st;
            ist->file_index = nb_input_files;
            ist->discard = 1;
    
            ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
    
            if (i < nb_ts_scale)
                ist->ts_scale = ts_scale[i];
    
    
            switch (dec->codec_type) {
    
                ist->dec = avcodec_find_decoder_by_name(audio_codec_name);
    
                if(!ist->dec)
                    ist->dec = avcodec_find_decoder(dec->codec_id);
    
                    st->discard= AVDISCARD_ALL;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
                ist->dec= avcodec_find_decoder_by_name(video_codec_name);
                if(!ist->dec)
                    ist->dec = avcodec_find_decoder(dec->codec_id);
    
                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;
    
                    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);
    
                    st->discard= AVDISCARD_ALL;
    
                else if(video_discard)
    
                    st->discard= video_discard;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
    
                ist->dec = avcodec_find_decoder_by_name(subtitle_codec_name);
    
                if(!ist->dec)
                    ist->dec = avcodec_find_decoder(dec->codec_id);
    
                    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
        /* dump the file content */
    
            av_dump_format(ic, nb_input_files, filename, 0);
    
        input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
        input_files[nb_input_files - 1].ctx        = ic;
        input_files[nb_input_files - 1].ist_index  = nb_input_streams - ic->nb_streams;
    
        input_files[nb_input_files - 1].ts_offset  = input_ts_offset - (copy_ts ? 0 : timestamp);
    
        input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
    
        audio_sample_fmt  = AV_SAMPLE_FMT_NONE;
    
        av_freep(&ts_scale);
        nb_ts_scale = 0;
    
        for (i = 0; i < orig_nb_streams; i++)
            av_dict_free(&opts[i]);
        av_freep(&opts);
    
        av_freep(&video_codec_name);
        av_freep(&audio_codec_name);
        av_freep(&subtitle_codec_name);
    
        return 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static void check_inputs(int *has_video_ptr,
                             int *has_audio_ptr,
                             int *has_subtitle_ptr,
                             int *has_data_ptr)
    
        int has_video, has_audio, has_subtitle, has_data, i, j;
    
            ic = input_files[j].ctx;
    
                AVCodecContext *enc = ic->streams[i]->codec;
    
                case AVMEDIA_TYPE_DATA:
                case AVMEDIA_TYPE_ATTACHMENT:
                case AVMEDIA_TYPE_UNKNOWN:
    
                    has_data = 1;
    
                }
            }
        }
        *has_video_ptr = has_video;
        *has_audio_ptr = has_audio;
    
        *has_subtitle_ptr = has_subtitle;
    
        *has_data_ptr = has_data;
    
    static void new_video_stream(AVFormatContext *oc, int file_idx)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        AVStream *st;
    
        OutputStream *ost;
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        if(!video_stream_copy){
            if (video_codec_name) {
    
                codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1);
    
                codec = avcodec_find_encoder_by_name(video_codec_name);
            } else {
                codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
                codec = avcodec_find_encoder(codec_id);
            }
    
        ost = new_output_stream(oc, file_idx, codec);
        st  = ost->st;
        if (!video_stream_copy) {
    
            ost->frame_aspect_ratio = frame_aspect_ratio;
            frame_aspect_ratio = 0;
    
            ost->avfilter = vfilters;
    
        ost->bitstream_filters = video_bitstream_filters;
    
        st->codec->thread_count= thread_count;
    
        if(video_codec_tag)
            video_enc->codec_tag= video_codec_tag;
    
        if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
    
            video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
    
        video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
    
        if (video_stream_copy) {
            st->stream_copy = 1;
    
            video_enc->sample_aspect_ratio =
    
            st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
    
            const char *p;
    
            if (frame_rate.num)
                ost->frame_rate = frame_rate;
    
            video_enc->width = frame_width;
            video_enc->height = frame_height;
    
            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 = 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_dict_set(&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)
    
        OutputStream *ost;
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        if(!audio_stream_copy){
            if (audio_codec_name) {
    
                codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1);
    
                codec = avcodec_find_encoder_by_name(audio_codec_name);
            } else {
                codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
                codec = avcodec_find_encoder(codec_id);
            }
        }
    
        ost = new_output_stream(oc, file_idx, codec);
        st  = ost->st;
    
        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;
    
        if (audio_stream_copy) {
            st->stream_copy = 1;
        } else {
            audio_enc->codec_id = codec_id;
    
            if (audio_qscale > QSCALE_NONE) {
                audio_enc->flags |= CODEC_FLAG_QSCALE;
    
                audio_enc->global_quality = FF_QP2LAMBDA * audio_qscale;
    
            if (audio_channels)
                audio_enc->channels = audio_channels;
    
            if (audio_sample_fmt != AV_SAMPLE_FMT_NONE)
                audio_enc->sample_fmt = audio_sample_fmt;
    
            if (audio_sample_rate)
                audio_enc->sample_rate = audio_sample_rate;
    
            av_dict_set(&st->metadata, "language", audio_language, 0);
    
    static void new_data_stream(AVFormatContext *oc, int file_idx)
    {
        AVStream *st;
    
        AVCodecContext *data_enc;
    
    
        ost = new_output_stream(oc, file_idx, NULL);
        st  = ost->st;
    
        data_enc = st->codec;
        if (!data_stream_copy) {
            fprintf(stderr, "Data stream encoding not supported yet (only streamcopy)\n");
            ffmpeg_exit(1);
        }
    
        data_enc->codec_type = AVMEDIA_TYPE_DATA;
    
        if (data_codec_tag)
            data_enc->codec_tag= data_codec_tag;
    
        if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
            data_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
        if (data_stream_copy) {
            st->stream_copy = 1;
        }
    
        data_disable = 0;
        av_freep(&data_codec_name);
        data_stream_copy = 0;
    }
    
    
    static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
    
        OutputStream *ost;
    
    Baptiste Coudurier's avatar
    Baptiste Coudurier committed
        enum CodecID codec_id = CODEC_ID_NONE;
    
        if(!subtitle_stream_copy){
    
            if (subtitle_codec_name) {
    
                codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1);
    
                codec = 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);
            }
    
        ost = new_output_stream(oc, file_idx, codec);
        st  = ost->st;
        subtitle_enc = st->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;
        }
    
        if (subtitle_stream_copy) {
            st->stream_copy = 1;
        } else {
    
            subtitle_enc->codec_id = codec_id;
    
            av_dict_set(&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);
    
        else if (!strcmp(opt, "newdata"    )) new_data_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)
    
        av_strlcpy(idx_str, arg, sizeof(idx_str));
    
        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);
    
        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 int opt_output_file(const char *opt, const char *filename)
    
        int err, use_video, use_audio, use_subtitle, use_data;
        int input_has_video, input_has_audio, input_has_subtitle, input_has_data;
    
        AVOutputFormat *file_oformat;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){
            fprintf(stderr, "Too many output files\n");
            ffmpeg_exit(1);
        }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (!strcmp(filename, "-"))
            filename = "pipe:";
    
    
        err = avformat_alloc_output_context2(&oc, NULL, last_asked_format, filename);
    
            ffmpeg_exit(1);
    
    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;
    
            use_data = data_stream_copy ||  data_codec_name; /* XXX once generic data codec will be available add a ->data_codec reference and use it here */
    
            /* disable if no corresponding type found */
            check_inputs(&input_has_video,
                         &input_has_audio,
                         &input_has_subtitle,
                         &input_has_data);
    
            if (!input_has_video)
                use_video = 0;
            if (!input_has_audio)
                use_audio = 0;
            if (!input_has_subtitle)
                use_subtitle = 0;
            if (!input_has_data)
                use_data = 0;
    
            if (audio_disable)    use_audio    = 0;
            if (video_disable)    use_video    = 0;
            if (subtitle_disable) use_subtitle = 0;
    
            if (data_disable)     use_data     = 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);
    
            if (use_data)     new_data_stream(oc, nb_output_files);
    
            av_dict_copy(&oc->metadata, metadata, 0);
            av_dict_free(&metadata);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
    
        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(EINVAL));
    
                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))) {
    
                if (avio_check(filename, 0) == 0) {
    
                        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_FLAG_WRITE)) < 0) {