X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=cb15120eee193ddc89588108dbb0d2436d3ce418;hb=41913a35b0fe2f9966cf8dfa2718180fb2febe53;hp=2b7408692ad3f5e5849f85d27696c785e9d22c3e;hpb=49a06a4d25a47c4a99c0714a2a5e17282ec00c1b;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 2b7408692ad..cb15120eee1 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -34,7 +34,6 @@ #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" -#include "libavformat/framehook.h" #include "libavcodec/opt.h" #include "libavcodec/audioconvert.h" #include "libavutil/fifo.h" @@ -163,6 +162,7 @@ static char *audio_language = NULL; static int subtitle_disable = 0; static char *subtitle_codec_name = NULL; static char *subtitle_language = NULL; +static int subtitle_codec_tag = 0; static float mux_preload= 0.5; static float mux_max_delay= 0.7; @@ -172,12 +172,8 @@ static int64_t start_time = 0; static int64_t rec_timestamp = 0; static int64_t input_ts_offset = 0; static int file_overwrite = 0; -static char *str_title = NULL; -static char *str_author = NULL; -static char *str_copyright = NULL; -static char *str_comment = NULL; -static char *str_genre = NULL; -static char *str_album = NULL; +static int metadata_count; +static AVMetadataTag *metadata; static int do_benchmark = 0; static int do_hex_dump = 0; static int do_pkt_dump = 0; @@ -207,7 +203,6 @@ static int audio_volume = 256; static int exit_on_error = 0; static int using_stdin = 0; -static int using_vhook = 0; static int verbose = 1; static int thread_count= 1; static int q_pressed = 0; @@ -269,7 +264,7 @@ typedef struct AVOutputStream { ReSampleContext *resample; /* for audio resampling */ int reformat_pair; AVAudioConvert *reformat_ctx; - AVFifoBuffer fifo; /* for compression: one audio fifo per codec */ + AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */ FILE *logfile; } AVOutputStream; @@ -591,7 +586,7 @@ static void do_audio_out(AVFormatContext *s, if(audio_sync_method){ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts - - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); + - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate; int byte_delta= ((int)idelta)*2*ist->st->codec->channels; @@ -628,13 +623,13 @@ static void do_audio_out(AVFormatContext *s, assert(ost->audio_resample); if(verbose > 2) fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate); -// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2)); +// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2)); av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate); } } }else ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate) - - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong + - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong if (ost->audio_resample) { buftmp = audio_buf; @@ -666,19 +661,19 @@ static void do_audio_out(AVFormatContext *s, /* now encode as many frames as possible */ if (enc->frame_size > 1) { /* output resampled raw samples */ - if (av_fifo_realloc2(&ost->fifo, av_fifo_size(&ost->fifo) + size_out) < 0) { + if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) { fprintf(stderr, "av_fifo_realloc2() failed\n"); av_exit(1); } - av_fifo_generic_write(&ost->fifo, buftmp, size_out, NULL); + av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL); frame_bytes = enc->frame_size * osize * enc->channels; - while (av_fifo_size(&ost->fifo) >= frame_bytes) { + while (av_fifo_size(ost->fifo) >= frame_bytes) { AVPacket pkt; av_init_packet(&pkt); - av_fifo_read(&ost->fifo, audio_buf, frame_bytes); + av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL); //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio() @@ -740,7 +735,7 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void dec = ist->st->codec; /* deinterlace : must be done before any resize */ - if (do_deinterlace || using_vhook) { + if (do_deinterlace) { int size; /* create temporary picture */ @@ -768,10 +763,6 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void picture2 = picture; } - if (CONFIG_VHOOK) - frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height, - 1000000 * ist->pts / AV_TIME_BASE); - if (picture != picture2) *picture = *picture2; *bufp = buf; @@ -865,11 +856,14 @@ static void do_video_out(AVFormatContext *s, //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (video_sync_method == 2) + else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){ + if(vdelta<=-0.6){ + nb_frames=0; + }else if(vdelta>0.6) ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base)); - else if (vdelta > 1.1) + }else if (vdelta > 1.1) nb_frames = lrintf(vdelta); -//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames); +//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames); if (nb_frames == 0){ ++nb_frames_drop; if (verbose>2) @@ -953,7 +947,7 @@ static void do_video_out(AVFormatContext *s, /* better than nothing: use input picture interlaced settings */ big_picture.interlaced_frame = in_picture->interlaced_frame; - if(avctx_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){ + if(avcodec_opts[CODEC_TYPE_VIDEO]->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){ if(top_field_first == -1) big_picture.top_field_first = in_picture->top_field_first; else @@ -1261,8 +1255,9 @@ static int output_packet(AVInputStream *ist, int ist_index, goto discard_packet; } if (ist->st->codec->time_base.num != 0) { + int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num) / + ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } len = 0; @@ -1289,8 +1284,9 @@ static int output_packet(AVInputStream *ist, int ist_index, break; case CODEC_TYPE_VIDEO: if (ist->st->codec->time_base.num != 0) { + int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num) / + ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } break; @@ -1451,13 +1447,13 @@ static int output_packet(AVInputStream *ist, int ist_index, switch(ost->st->codec->codec_type) { case CODEC_TYPE_AUDIO: - fifo_bytes = av_fifo_size(&ost->fifo); + fifo_bytes = av_fifo_size(ost->fifo); ret = 0; /* encode any samples remaining in fifo */ if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { int fs_tmp = enc->frame_size; enc->frame_size = fifo_bytes / (2 * enc->channels); - av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes); + av_fifo_generic_read(ost->fifo, samples, fifo_bytes, NULL); ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples); enc->frame_size = fs_tmp; } @@ -1550,14 +1546,17 @@ static int av_encode(AVFormatContext **output_files, int nb_input_files, AVStreamMap *stream_maps, int nb_stream_maps) { - int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0; + int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; AVOutputStream *ost, **ost_table = NULL; AVInputStream *ist, **ist_table = NULL; AVInputFile *file_table; + char error[1024]; int key; int want_sdp = 1; + uint8_t no_packet[MAX_FILES]={0}; + int no_packet_count=0; file_table= av_mallocz(nb_input_files * sizeof(AVInputFile)); if (!file_table) @@ -1720,6 +1719,7 @@ static int av_encode(AVFormatContext **output_files, /* for each output stream, we compute the right encoding parameters */ for(i=0;ifile_index]; ist = ist_table[ost->source_index]; @@ -1727,9 +1727,9 @@ static int av_encode(AVFormatContext **output_files, codec = ost->st->codec; icodec = ist->st->codec; - if (!ost->st->language[0]) - av_strlcpy(ost->st->language, ist->st->language, - sizeof(ost->st->language)); + if ((lang=av_metadata_get(ist->st->metadata, "language", NULL, 0)) + && !av_metadata_get(ost->st->metadata, "language", NULL, 0)) + av_metadata_set(&ost->st->metadata, "language", lang->value); ost->st->disposition = ist->st->disposition; @@ -1748,9 +1748,10 @@ static int av_encode(AVFormatContext **output_files, codec->bit_rate = icodec->bit_rate; codec->extradata= icodec->extradata; codec->extradata_size= icodec->extradata_size; - if(av_q2d(icodec->time_base) > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000) + if(av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000){ codec->time_base = icodec->time_base; - else + codec->time_base.num *= icodec->ticks_per_frame; + }else codec->time_base = ist->st->time_base; switch(codec->codec_type) { case CODEC_TYPE_AUDIO: @@ -1769,10 +1770,6 @@ static int av_encode(AVFormatContext **output_files, codec->block_align= 0; break; case CODEC_TYPE_VIDEO: - if(using_vhook) { - fprintf(stderr,"-vcodec copy and -vhook are incompatible (frames are not decoded)\n"); - av_exit(1); - } codec->pix_fmt = icodec->pix_fmt; codec->width = icodec->width; codec->height = icodec->height; @@ -1788,7 +1785,8 @@ static int av_encode(AVFormatContext **output_files, } else { switch(codec->codec_type) { case CODEC_TYPE_AUDIO: - if (av_fifo_init(&ost->fifo, 1024)) + ost->fifo= av_fifo_alloc(1024); + if(!ost->fifo) goto fail; ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE); ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1; @@ -1897,37 +1895,15 @@ static int av_encode(AVFormatContext **output_files, } if(codec->codec_type == CODEC_TYPE_VIDEO){ int size= codec->width * codec->height; - bit_buffer_size= FFMAX(bit_buffer_size, 4*size); + bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200); } } if (!bit_buffer) bit_buffer = av_malloc(bit_buffer_size); - if (!bit_buffer) + if (!bit_buffer) { + ret = AVERROR(ENOMEM); goto fail; - - /* dump the file output parameters - cannot be done before in case - of stream copy */ - for(i=0;ifilename, 1); - } - - /* dump the stream mapping */ - if (verbose >= 0) { - fprintf(stderr, "Stream mapping:\n"); - for(i=0;i #%d.%d", - ist_table[ost->source_index]->file_index, - ist_table[ost->source_index]->index, - ost->file_index, - ost->index); - if (ost->sync_ist != ist_table[ost->source_index]) - fprintf(stderr, " [sync #%d.%d]", - ost->sync_ist->file_index, - ost->sync_ist->index); - fprintf(stderr, "\n"); - } } /* open each encoder */ @@ -1938,14 +1914,16 @@ static int av_encode(AVFormatContext **output_files, if (!codec) codec = avcodec_find_encoder(ost->st->codec->codec_id); if (!codec) { - fprintf(stderr, "Unsupported codec for output stream #%d.%d\n", + snprintf(error, sizeof(error), "Unsupported codec for output stream #%d.%d", ost->file_index, ost->index); - av_exit(1); + ret = AVERROR(EINVAL); + goto dump_format; } if (avcodec_open(ost->st->codec, codec) < 0) { - fprintf(stderr, "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n", + snprintf(error, sizeof(error), "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); - av_exit(1); + ret = AVERROR(EINVAL); + goto dump_format; } extra_size += ost->st->codec->extradata_size; } @@ -1959,14 +1937,16 @@ static int av_encode(AVFormatContext **output_files, if (!codec) codec = avcodec_find_decoder(ist->st->codec->codec_id); if (!codec) { - fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n", + snprintf(error, sizeof(error), "Unsupported codec (id=%d) for input stream #%d.%d", ist->st->codec->codec_id, ist->file_index, ist->index); - av_exit(1); + ret = AVERROR(EINVAL); + goto dump_format; } if (avcodec_open(ist->st->codec, codec) < 0) { - fprintf(stderr, "Error while opening codec for input stream #%d.%d\n", + snprintf(error, sizeof(error), "Error while opening codec for input stream #%d.%d", ist->file_index, ist->index); - av_exit(1); + ret = AVERROR(EINVAL); + goto dump_format; } //if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO) // ist->st->codec->flags |= CODEC_FLAG_REPEAT_FIELD; @@ -1986,45 +1966,77 @@ static int av_encode(AVFormatContext **output_files, for (i=0;i= nb_output_files) { - fprintf(stderr, "Invalid output file index %d map_meta_data(%d,%d)\n", out_file_index, out_file_index, in_file_index); + snprintf(error, sizeof(error), "Invalid output file index %d map_meta_data(%d,%d)", + out_file_index, out_file_index, in_file_index); ret = AVERROR(EINVAL); - goto fail; + goto dump_format; } if (in_file_index < 0 || in_file_index >= nb_input_files) { - fprintf(stderr, "Invalid input file index %d map_meta_data(%d,%d)\n", in_file_index, out_file_index, in_file_index); + snprintf(error, sizeof(error), "Invalid input file index %d map_meta_data(%d,%d)", + in_file_index, out_file_index, in_file_index); ret = AVERROR(EINVAL); - goto fail; + goto dump_format; } out_file = output_files[out_file_index]; in_file = input_files[in_file_index]; - strcpy(out_file->title, in_file->title); - strcpy(out_file->author, in_file->author); - strcpy(out_file->copyright, in_file->copyright); - strcpy(out_file->comment, in_file->comment); - strcpy(out_file->album, in_file->album); - out_file->year = in_file->year; - out_file->track = in_file->track; - strcpy(out_file->genre, in_file->genre); + + mtag=NULL; + while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX))) + av_metadata_set(&out_file->metadata, mtag->key, mtag->value); + av_metadata_conv(out_file, out_file->oformat->metadata_conv, + in_file->iformat->metadata_conv); } /* open files and write file headers */ for(i=0;ioformat->name, "rtp")) { want_sdp = 0; } } + + dump_format: + /* dump the file output parameters - cannot be done before in case + of stream copy */ + for(i=0;ifilename, 1); + } + + /* dump the stream mapping */ + if (verbose >= 0) { + fprintf(stderr, "Stream mapping:\n"); + for(i=0;i #%d.%d", + ist_table[ost->source_index]->file_index, + ist_table[ost->source_index]->index, + ost->file_index, + ost->index); + if (ost->sync_ist != ist_table[ost->source_index]) + fprintf(stderr, " [sync #%d.%d]", + ost->sync_ist->file_index, + ost->sync_ist->index); + fprintf(stderr, "\n"); + } + } + + if (ret) { + fprintf(stderr, "%s\n", error); + goto fail; + } + if (want_sdp) { print_sdp(output_files, nb_output_files); } @@ -2065,6 +2077,8 @@ static int av_encode(AVFormatContext **output_files, ost = ost_table[i]; os = output_files[ost->file_index]; ist = ist_table[ost->source_index]; + if(no_packet[ist->file_index]) + continue; if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO) opts = ost->sync_opts * av_q2d(ost->st->codec->time_base); else @@ -2087,6 +2101,12 @@ static int av_encode(AVFormatContext **output_files, } /* if none, if is finished */ if (file_index < 0) { + if(no_packet_count){ + no_packet_count=0; + memset(no_packet, 0, sizeof(no_packet)); + usleep(10000); + continue; + } break; } @@ -2101,8 +2121,11 @@ static int av_encode(AVFormatContext **output_files, /* read a frame from it and output it in the fifo */ is = input_files[file_index]; ret= av_read_frame(is, &pkt); - if(ret == AVERROR(EAGAIN) && strcmp(is->iformat->name, "ffm")) + if(ret == AVERROR(EAGAIN)){ + no_packet[file_index]=1; + no_packet_count++; continue; + } if (ret < 0) { file_table[file_index].eof_reached = 1; if (opt_shortest) @@ -2111,6 +2134,9 @@ static int av_encode(AVFormatContext **output_files, continue; } + no_packet_count=0; + memset(no_packet, 0, sizeof(no_packet)); + if (do_pkt_dump) { av_pkt_dump_log(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump); } @@ -2206,9 +2232,9 @@ static int av_encode(AVFormatContext **output_files, } /* finished ! */ - ret = 0; - fail1: + + fail: av_freep(&bit_buffer); av_free(file_table); @@ -2227,7 +2253,7 @@ static int av_encode(AVFormatContext **output_files, fclose(ost->logfile); ost->logfile = NULL; } - av_fifo_free(&ost->fifo); /* works even if fifo is not + av_fifo_free(ost->fifo); /* works even if fifo is not initialized but set to zero */ av_free(ost->pict_tmp.data[0]); if (ost->video_resample) @@ -2242,9 +2268,6 @@ static int av_encode(AVFormatContext **output_files, av_free(ost_table); } return ret; - fail: - ret = AVERROR(ENOMEM); - goto fail1; } #if 0 @@ -2298,10 +2321,15 @@ static int opt_me_threshold(const char *opt, const char *arg) return 0; } +static void opt_loglevel(const char *opt, const char *arg) +{ + int level = parse_number_or_die(opt, arg, OPT_INT, INT_MIN, INT_MAX); + av_log_set_level(level); +} + static int opt_verbose(const char *opt, const char *arg) { verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10); - av_log_set_level(verbose); return 0; } @@ -2320,7 +2348,7 @@ static int opt_bitrate(const char *opt, const char *arg) opt_default(opt, arg); - if (av_get_int(avctx_opts[codec_type], "b", NULL) < 1000) + if (av_get_int(avcodec_opts[codec_type], "b", NULL) < 1000) fprintf(stderr, "WARNING: The bitrate parameter is set too low. It takes bits/s as argument, not kbits/s\n"); return 0; @@ -2508,9 +2536,13 @@ static void list_fmts(void (*get_fmt_string)(char *buf, int buf_size, int fmt), static void opt_frame_pix_fmt(const char *arg) { - if (strcmp(arg, "list")) + if (strcmp(arg, "list")) { frame_pix_fmt = avcodec_get_pix_fmt(arg); - else { + if (frame_pix_fmt == PIX_FMT_NONE) { + fprintf(stderr, "Unknown pixel format requested: %s\n", arg); + av_exit(1); + } + } else { list_fmts(avcodec_pix_fmt_string, PIX_FMT_NB); av_exit(0); } @@ -2540,6 +2572,24 @@ static void opt_frame_aspect_ratio(const char *arg) frame_aspect_ratio = ar; } +static int opt_metadata(const char *opt, const char *arg) +{ + char *mid= strchr(arg, '='); + + if(!mid){ + fprintf(stderr, "Missing =\n"); + av_exit(1); + } + *mid++= 0; + + metadata_count++; + metadata= av_realloc(metadata, sizeof(*metadata)*metadata_count); + metadata[metadata_count-1].key = av_strdup(arg); + metadata[metadata_count-1].value= av_strdup(mid); + + return 0; +} + static void opt_qscale(const char *arg) { video_qscale = atof(arg); @@ -2631,29 +2681,6 @@ static void opt_video_tag(const char *arg) video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24); } -#if CONFIG_VHOOK -static void add_frame_hooker(const char *arg) -{ - int argc = 0; - char *argv[64]; - int i; - char *args = av_strdup(arg); - - using_vhook = 1; - - argv[0] = strtok(args, " "); - while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) { - } - - i = frame_hook_add(argc, argv); - - if (i != 0) { - fprintf(stderr, "Failed to add video hook function: %s\n", arg); - av_exit(1); - } -} -#endif - static void opt_video_codec(const char *arg) { opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg); @@ -2664,6 +2691,15 @@ static void opt_subtitle_codec(const char *arg) opt_codec(&subtitle_stream_copy, &subtitle_codec_name, CODEC_TYPE_SUBTITLE, arg); } +static void opt_subtitle_tag(const char *arg) +{ + char *tail; + subtitle_codec_tag= strtol(arg, &tail, 0); + + if(!tail || *tail) + subtitle_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24); +} + static void opt_map(const char *arg) { AVStreamMap *m; @@ -2802,6 +2838,7 @@ static void opt_input_file(const char *filename) ic->video_codec_id = find_codec_or_die(video_codec_name , CODEC_TYPE_VIDEO , 0); ic->audio_codec_id = find_codec_or_die(audio_codec_name , CODEC_TYPE_AUDIO , 0); ic->subtitle_codec_id= find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 0); + ic->flags |= AVFMT_FLAG_NONBLOCK; /* open the input file with generic libav function */ err = av_open_input_file(&ic, filename, file_iformat, 0, ap); @@ -2850,7 +2887,7 @@ static void opt_input_file(const char *filename) enc->thread_count= thread_count; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - set_context_opts(enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); //fprintf(stderr, "\nInput Audio channels: %d", enc->channels); channel_layout = enc->channel_layout; audio_channels = enc->channels; @@ -2861,7 +2898,7 @@ static void opt_input_file(const char *filename) ic->streams[i]->discard= AVDISCARD_ALL; break; case CODEC_TYPE_VIDEO: - set_context_opts(enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); frame_height = enc->height; frame_width = enc->width; if(ic->streams[i]->sample_aspect_ratio.num) @@ -2990,11 +3027,11 @@ static void new_video_stream(AVFormatContext *oc) if( (video_global_header&1) || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){ video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; - avctx_opts[CODEC_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER; + avcodec_opts[CODEC_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER; } if(video_global_header&2){ video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER; - avctx_opts[CODEC_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER; + avcodec_opts[CODEC_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER; } if (video_stream_copy) { @@ -3019,7 +3056,7 @@ static void new_video_stream(AVFormatContext *oc) video_enc->codec_id = codec_id; - set_context_opts(video_enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(video_enc, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (codec && codec->supported_framerates && !force_fps) fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)]; @@ -3133,7 +3170,7 @@ static void new_audio_stream(AVFormatContext *oc) if (oc->oformat->flags & AVFMT_GLOBALHEADER) { audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; - avctx_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER; + avcodec_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER; } if (audio_stream_copy) { st->stream_copy = 1; @@ -3141,7 +3178,7 @@ static void new_audio_stream(AVFormatContext *oc) } else { AVCodec *codec; - set_context_opts(audio_enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(audio_enc, avcodec_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (audio_codec_name) { codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1); @@ -3176,7 +3213,7 @@ static void new_audio_stream(AVFormatContext *oc) audio_enc->sample_rate = audio_sample_rate; audio_enc->time_base= (AVRational){1, audio_sample_rate}; if (audio_language) { - av_strlcpy(st->language, audio_language, sizeof(st->language)); + av_metadata_set(&st->metadata, "language", audio_language); av_free(audio_language); audio_language = NULL; } @@ -3204,17 +3241,21 @@ static void new_subtitle_stream(AVFormatContext *oc) subtitle_enc = st->codec; subtitle_enc->codec_type = CODEC_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(avctx_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(avcodec_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1); output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name); } nb_ocodecs++; if (subtitle_language) { - av_strlcpy(st->language, subtitle_language, sizeof(st->language)); + av_metadata_set(&st->metadata, "language", subtitle_language); av_free(subtitle_language); subtitle_language = NULL; } @@ -3333,18 +3374,11 @@ static void opt_output_file(const char *filename) oc->timestamp = rec_timestamp; - if (str_title) - av_strlcpy(oc->title, str_title, sizeof(oc->title)); - if (str_author) - av_strlcpy(oc->author, str_author, sizeof(oc->author)); - if (str_copyright) - av_strlcpy(oc->copyright, str_copyright, sizeof(oc->copyright)); - if (str_comment) - av_strlcpy(oc->comment, str_comment, sizeof(oc->comment)); - if (str_album) - av_strlcpy(oc->album, str_album, sizeof(oc->album)); - if (str_genre) - av_strlcpy(oc->genre, str_genre, sizeof(oc->genre)); + for(; metadata_count>0; metadata_count--){ + av_metadata_set(&oc->metadata, metadata[metadata_count-1].key, + metadata[metadata_count-1].value); + } + av_metadata_conv(oc, oc->oformat->metadata_conv, NULL); } output_files[nb_output_files++] = oc; @@ -3364,13 +3398,10 @@ static void opt_output_file(const char *filename) filename[1] == ':' || av_strstart(filename, "file:", NULL))) { if (url_exist(filename)) { - int c; - if (!using_stdin) { fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); fflush(stderr); - c = getchar(); - if (toupper(c) != 'Y') { + if (!read_yesno()) { fprintf(stderr, "Not overwriting - exiting\n"); av_exit(1); } @@ -3399,6 +3430,7 @@ static void opt_output_file(const char *filename) 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); @@ -3505,7 +3537,7 @@ static void show_help(void) OPT_GRAB, OPT_GRAB); printf("\n"); - av_opt_show(avctx_opts[0], NULL); + av_opt_show(avcodec_opts[0], NULL); printf("\n"); av_opt_show(avformat_opts, NULL); printf("\n"); @@ -3768,13 +3800,8 @@ static const OptionDef options[] = { { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, - { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" }, { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp ('now' to set the current time)", "time" }, - { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" }, - { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" }, - { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" }, - { "genre", HAS_ARG | OPT_STRING, {(void*)&str_genre}, "set the genre", "string" }, - { "album", HAS_ARG | OPT_STRING, {(void*)&str_album}, "set the album", "string" }, + { "metadata", OPT_FUNC2 | HAS_ARG, {(void*)&opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, "add timings for benchmarking" }, @@ -3785,7 +3812,8 @@ static const OptionDef options[] = { { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" }, { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" }, { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "number of times to loop output in formats that support looping (0 loops forever)", "" }, - { "v", HAS_ARG | OPT_FUNC2, {(void*)opt_verbose}, "set the logging verbosity level", "number" }, + { "v", HAS_ARG | OPT_FUNC2, {(void*)opt_verbose}, "set ffmpeg verbosity level", "number" }, + { "loglevel", HAS_ARG | OPT_FUNC2, {(void*)opt_loglevel}, "set libav* logging level", "number" }, { "target", HAS_ARG, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, { "threads", OPT_FUNC2 | HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" }, { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, @@ -3832,9 +3860,6 @@ static const OptionDef options[] = { { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, -#if CONFIG_VHOOK - { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" }, -#endif { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" }, { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" }, { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" }, @@ -3863,6 +3888,7 @@ static const OptionDef options[] = { { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" }, { "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_subtitle_stream}, "add a new subtitle stream to the current output stream" }, { "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" }, + { "stag", HAS_ARG | OPT_EXPERT | OPT_SUBTITLE, {(void*)opt_subtitle_tag}, "force subtitle tag/fourcc", "fourcc/tag" }, /* grab options */ { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" }, @@ -3898,7 +3924,7 @@ int main(int argc, char **argv) url_set_interrupt_cb(decode_interrupt_cb); for(i=0; i