|
@@ -51,6 +51,7 @@
|
|
|
# include "libavfilter/avcodec.h"
|
|
|
# include "libavfilter/avfilter.h"
|
|
|
# include "libavfilter/avfiltergraph.h"
|
|
|
+# include "libavfilter/vsink_buffer.h"
|
|
|
# include "libavfilter/vsrc_buffer.h"
|
|
|
#endif
|
|
|
|
|
@@ -124,9 +125,7 @@ static int nb_input_codecs = 0;
|
|
|
static int nb_input_files_ts_scale[MAX_FILES] = {0};
|
|
|
|
|
|
static AVFormatContext *output_files[MAX_FILES];
|
|
|
-static AVCodec **output_codecs = NULL;
|
|
|
static int nb_output_files = 0;
|
|
|
-static int nb_output_codecs = 0;
|
|
|
|
|
|
static AVStreamMap *stream_maps = NULL;
|
|
|
static int nb_stream_maps;
|
|
@@ -278,6 +277,8 @@ typedef struct AVOutputStream {
|
|
|
struct AVInputStream *sync_ist; /* input stream to sync against */
|
|
|
int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
|
|
|
AVBitStreamFilterContext *bitstream_filters;
|
|
|
+ AVCodec *enc;
|
|
|
+
|
|
|
/* video only */
|
|
|
int video_resample;
|
|
|
AVFrame resample_frame; /* temporary frame for image resampling */
|
|
@@ -365,7 +366,7 @@ static int configure_video_filters(AVInputStream *ist, AVOutputStream *ost)
|
|
|
/** filter graph containing all filters including input & output */
|
|
|
AVCodecContext *codec = ost->st->codec;
|
|
|
AVCodecContext *icodec = ist->st->codec;
|
|
|
- FFSinkContext ffsink_ctx = { .pix_fmt = codec->pix_fmt };
|
|
|
+ enum PixelFormat pix_fmts[] = { codec->pix_fmt, PIX_FMT_NONE };
|
|
|
AVRational sample_aspect_ratio;
|
|
|
char args[255];
|
|
|
int ret;
|
|
@@ -385,8 +386,8 @@ static int configure_video_filters(AVInputStream *ist, AVOutputStream *ost)
|
|
|
"src", args, NULL, ost->graph);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
- ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink,
|
|
|
- "out", NULL, &ffsink_ctx, ost->graph);
|
|
|
+ ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
|
|
|
+ "out", NULL, pix_fmts, ost->graph);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
last_filter = ost->input_video_filter;
|
|
@@ -556,7 +557,6 @@ static int ffmpeg_exit(int ret)
|
|
|
|
|
|
av_free(streamid_map);
|
|
|
av_free(input_codecs);
|
|
|
- av_free(output_codecs);
|
|
|
av_free(stream_maps);
|
|
|
av_free(meta_data_maps);
|
|
|
|
|
@@ -620,6 +620,8 @@ static void choose_sample_fmt(AVStream *st, AVCodec *codec)
|
|
|
break;
|
|
|
}
|
|
|
if (*p == -1) {
|
|
|
+ if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
|
|
|
+ av_log(NULL, AV_LOG_ERROR, "Convertion will not be lossless'\n");
|
|
|
av_log(NULL, AV_LOG_WARNING,
|
|
|
"Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
|
|
|
av_get_sample_fmt_name(st->codec->sample_fmt),
|
|
@@ -809,8 +811,8 @@ static void do_audio_out(AVFormatContext *s,
|
|
|
int size_out, frame_bytes, ret, resample_changed;
|
|
|
AVCodecContext *enc= ost->st->codec;
|
|
|
AVCodecContext *dec= ist->st->codec;
|
|
|
- int osize= av_get_bits_per_sample_fmt(enc->sample_fmt)/8;
|
|
|
- int isize= av_get_bits_per_sample_fmt(dec->sample_fmt)/8;
|
|
|
+ int osize = av_get_bytes_per_sample(enc->sample_fmt);
|
|
|
+ int isize = av_get_bytes_per_sample(dec->sample_fmt);
|
|
|
const int coded_bps = av_get_bits_per_sample(enc->codec->id);
|
|
|
|
|
|
need_realloc:
|
|
@@ -1530,7 +1532,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
|
|
|
#endif
|
|
|
|
|
|
AVPacket avpkt;
|
|
|
- int bps = av_get_bits_per_sample_fmt(ist->st->codec->sample_fmt)>>3;
|
|
|
+ int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
|
|
|
|
|
|
if(ist->next_pts == AV_NOPTS_VALUE)
|
|
|
ist->next_pts= ist->pts;
|
|
@@ -1708,12 +1710,15 @@ static int output_packet(AVInputStream *ist, int ist_index,
|
|
|
frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
|
|
|
!ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]);
|
|
|
while (frame_available) {
|
|
|
- AVRational ist_pts_tb;
|
|
|
- if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter)
|
|
|
- if (get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb) < 0)
|
|
|
+ if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) {
|
|
|
+ AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
|
|
|
+ if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
|
|
|
goto cont;
|
|
|
- if (ost->picref)
|
|
|
- ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
|
|
|
+ if (ost->picref) {
|
|
|
+ avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref);
|
|
|
+ ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
|
|
|
+ }
|
|
|
+ }
|
|
|
#endif
|
|
|
os = output_files[ost->file_index];
|
|
|
|
|
@@ -2263,6 +2268,8 @@ static int transcode(AVFormatContext **output_files,
|
|
|
abort();
|
|
|
}
|
|
|
} else {
|
|
|
+ if (!ost->enc)
|
|
|
+ ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
|
|
|
switch(codec->codec_type) {
|
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
|
ost->fifo= av_fifo_alloc(1024);
|
|
@@ -2274,7 +2281,7 @@ static int transcode(AVFormatContext **output_files,
|
|
|
if (icodec->lowres)
|
|
|
codec->sample_rate >>= icodec->lowres;
|
|
|
}
|
|
|
- choose_sample_rate(ost->st, codec->codec);
|
|
|
+ choose_sample_rate(ost->st, ost->enc);
|
|
|
codec->time_base = (AVRational){1, codec->sample_rate};
|
|
|
if (!codec->channels)
|
|
|
codec->channels = icodec->channels;
|
|
@@ -2289,6 +2296,10 @@ static int transcode(AVFormatContext **output_files,
|
|
|
ost->resample_channels = icodec->channels;
|
|
|
break;
|
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
|
+ if (codec->pix_fmt == PIX_FMT_NONE)
|
|
|
+ codec->pix_fmt = icodec->pix_fmt;
|
|
|
+ choose_pixel_fmt(ost->st, ost->enc);
|
|
|
+
|
|
|
if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
|
|
|
fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n");
|
|
|
ffmpeg_exit(1);
|
|
@@ -2299,6 +2310,10 @@ static int transcode(AVFormatContext **output_files,
|
|
|
if (ost->video_resample) {
|
|
|
codec->bits_per_raw_sample= frame_bits_per_raw_sample;
|
|
|
}
|
|
|
+ if (!codec->width || !codec->height) {
|
|
|
+ codec->width = icodec->width;
|
|
|
+ codec->height = icodec->height;
|
|
|
+ }
|
|
|
ost->resample_height = icodec->height;
|
|
|
ost->resample_width = icodec->width;
|
|
|
ost->resample_pix_fmt= icodec->pix_fmt;
|
|
@@ -2307,11 +2322,16 @@ static int transcode(AVFormatContext **output_files,
|
|
|
|
|
|
if (!ost->frame_rate.num)
|
|
|
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1};
|
|
|
- if (codec->codec && codec->codec->supported_framerates && !force_fps) {
|
|
|
- int idx = av_find_nearest_q_idx(ost->frame_rate, codec->codec->supported_framerates);
|
|
|
- ost->frame_rate = codec->codec->supported_framerates[idx];
|
|
|
+ if (ost->enc && ost->enc->supported_framerates && !force_fps) {
|
|
|
+ int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
|
|
|
+ ost->frame_rate = ost->enc->supported_framerates[idx];
|
|
|
}
|
|
|
codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
|
|
|
+ if( av_q2d(codec->time_base) < 0.001 && video_sync_method
|
|
|
+ && (video_sync_method==1 || (video_sync_method<0 && !(os->oformat->flags & AVFMT_VARIABLE_FPS)))){
|
|
|
+ av_log(os, AV_LOG_WARNING, "Frame rate very high for a muxer not effciciently supporting it.\n"
|
|
|
+ "Please consider specifiying a lower framerate, a different muxer or -vsync 2\n");
|
|
|
+ }
|
|
|
|
|
|
#if CONFIG_AVFILTER
|
|
|
if (configure_video_filters(ist, ost)) {
|
|
@@ -2375,10 +2395,8 @@ static int transcode(AVFormatContext **output_files,
|
|
|
for(i=0;i<nb_ostreams;i++) {
|
|
|
ost = ost_table[i];
|
|
|
if (ost->encoding_needed) {
|
|
|
- AVCodec *codec = i < nb_output_codecs ? output_codecs[i] : NULL;
|
|
|
+ AVCodec *codec = ost->enc;
|
|
|
AVCodecContext *dec = input_streams[ost->source_index].st->codec;
|
|
|
- if (!codec)
|
|
|
- codec = avcodec_find_encoder(ost->st->codec->codec_id);
|
|
|
if (!codec) {
|
|
|
snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d.%d",
|
|
|
ost->st->codec->codec_id, ost->file_index, ost->index);
|
|
@@ -3399,17 +3417,12 @@ static int opt_input_file(const char *opt, const char *filename)
|
|
|
if(!input_codecs[nb_input_codecs-1])
|
|
|
input_codecs[nb_input_codecs-1] = avcodec_find_decoder(dec->codec_id);
|
|
|
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;
|
|
|
- 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->height >>= dec->lowres;
|
|
|
+ dec->width >>= dec->lowres;
|
|
|
}
|
|
|
if(me_threshold)
|
|
|
dec->debug |= FF_DEBUG_MV;
|
|
@@ -3454,9 +3467,12 @@ static int opt_input_file(const char *opt, const char *filename)
|
|
|
input_files[nb_input_files - 1].ctx = ic;
|
|
|
input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
|
|
|
|
|
|
- video_channel = 0;
|
|
|
top_field_first = -1;
|
|
|
+ video_channel = 0;
|
|
|
frame_rate = (AVRational){0, 0};
|
|
|
+ frame_pix_fmt = PIX_FMT_NONE;
|
|
|
+ frame_height = 0;
|
|
|
+ frame_width = 0;
|
|
|
audio_sample_rate = 0;
|
|
|
audio_channels = 0;
|
|
|
|
|
@@ -3526,13 +3542,12 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
|
|
|
}
|
|
|
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;
|
|
|
+ ost->enc = codec;
|
|
|
} else {
|
|
|
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
|
|
|
codec = avcodec_find_encoder(codec_id);
|
|
@@ -3581,8 +3596,6 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
|
|
|
video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
|
|
|
st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
|
|
|
|
|
|
- choose_pixel_fmt(st, codec);
|
|
|
-
|
|
|
if (intra_only)
|
|
|
video_enc->gop_size = 0;
|
|
|
if (video_qscale || same_quality) {
|
|
@@ -3669,13 +3682,12 @@ static void new_audio_stream(AVFormatContext *oc, int file_idx)
|
|
|
}
|
|
|
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;
|
|
|
+ ost->enc = codec;
|
|
|
} else {
|
|
|
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
|
|
|
codec = avcodec_find_encoder(codec_id);
|
|
@@ -3741,7 +3753,6 @@ static void new_data_stream(AVFormatContext *oc, int file_idx)
|
|
|
}
|
|
|
new_output_stream(oc, file_idx);
|
|
|
data_enc = st->codec;
|
|
|
- output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
|
|
|
if (!data_stream_copy) {
|
|
|
fprintf(stderr, "Data stream encoding not supported yet (only streamcopy)\n");
|
|
|
ffmpeg_exit(1);
|
|
@@ -3781,12 +3792,12 @@ static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
|
|
|
}
|
|
|
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,
|
|
|
avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
|
|
|
- codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);
|
|
|
+ codec = avcodec_find_encoder_by_name(subtitle_codec_name);
|
|
|
+ ost->enc = codec;
|
|
|
} else {
|
|
|
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_SUBTITLE);
|
|
|
codec = avcodec_find_encoder(codec_id);
|
|
@@ -3990,6 +4001,8 @@ static int opt_output_file(const char *opt, const char *filename)
|
|
|
set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
|
|
|
|
|
|
frame_rate = (AVRational){0, 0};
|
|
|
+ frame_width = 0;
|
|
|
+ frame_height = 0;
|
|
|
audio_sample_rate = 0;
|
|
|
audio_channels = 0;
|
|
|
|
|
@@ -4226,6 +4239,7 @@ static int opt_target(const char *opt, const char *arg)
|
|
|
|
|
|
opt_frame_size("s", norm == PAL ? "480x576" : "480x480");
|
|
|
opt_frame_rate("r", frame_rates[norm]);
|
|
|
+ opt_frame_pix_fmt("pix_fmt", "yuv420p");
|
|
|
opt_default("g", norm == PAL ? "15" : "18");
|
|
|
|
|
|
opt_default("b", "2040000");
|
|
@@ -4248,6 +4262,7 @@ static int opt_target(const char *opt, const char *arg)
|
|
|
|
|
|
opt_frame_size("vcodec", norm == PAL ? "720x576" : "720x480");
|
|
|
opt_frame_rate("r", frame_rates[norm]);
|
|
|
+ opt_frame_pix_fmt("pix_fmt", "yuv420p");
|
|
|
opt_default("g", norm == PAL ? "15" : "18");
|
|
|
|
|
|
opt_default("b", "6000000");
|