#include "libavutil/avassert.h"
+#define VSYNC_AUTO -1
+#define VSYNC_PASSTHROUGH 0
+#define VSYNC_CFR 1
+#define VSYNC_VFR 2
+#define VSYNC_DROP 0xff
+
const char program_name[] = "ffmpeg";
const int program_birth_year = 2000;
static int same_quant = 0;
static int do_deinterlace = 0;
static int intra_dc_precision = 8;
-static int loop_input = 0;
-static int loop_output = AVFMT_NOOUTPUTLOOP;
static int qp_hist = 0;
static int intra_only = 0;
static const char *video_codec_name = NULL;
static int do_psnr = 0;
static int do_pass = 0;
static const char *pass_logfilename_prefix;
-static int video_sync_method = -1;
+static int video_sync_method = VSYNC_AUTO;
static int audio_sync_method = 0;
static float audio_drift_threshold = 0.1;
static int copy_ts = 0;
static int print_stats = 1;
static uint8_t *audio_buf;
-static uint8_t *audio_out;
-static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
+static unsigned int allocated_audio_buf_size;
static uint8_t *input_tmp= NULL;
AVFrame *filtered_frame;
int64_t start; /* time when read started */
- int64_t next_pts; /* synthetic pts for cases where pkt.pts
- is not defined */
- int64_t pts; /* current pts */
+ /* predicted dts of the next packet read for this stream or (when there are
+ * several frames in a packet) of the next frame in current packet */
+ int64_t next_dts;
+ /* dts of the last packet read for this stream */
+ int64_t dts;
+
+ int64_t next_pts; ///< synthetic pts for the next decode frame
+ int64_t pts; ///< current pts of the decoded frame
double ts_scale;
int is_start; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning;
int frame_number;
/* input pts and corresponding output pts
for A/V sync */
- // double sync_ipts; /* dts from the AVPacket of the demuxer in second units */
struct InputStream *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;
int64_t max_frames;
+ AVFrame *output_frame;
/* video only */
int video_resample;
/* init terminal so that we can grab keys */
static struct termios oldtty;
+static int restore_tty;
#endif
typedef struct OutputFile {
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; /* desired length of the resulting file in microseconds */
int64_t start_time; /* start time in microseconds */
- uint64_t limit_filesize;
+ uint64_t limit_filesize; /* filesize limit expressed in bytes */
} OutputFile;
static InputStream *input_streams = NULL;
init_opts();
}
-static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf)
+static int alloc_buffer(AVCodecContext *s, InputStream *ist, FrameBuffer **pbuf)
{
- AVCodecContext *s = ist->st->codec;
FrameBuffer *buf = av_mallocz(sizeof(*buf));
- int ret, i;
+ int i, ret;
const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
int h_chroma_shift, v_chroma_shift;
int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
FrameBuffer *buf;
int ret, i;
- if (!ist->buffer_pool && (ret = alloc_buffer(ist, &ist->buffer_pool)) < 0)
+ if(av_image_check_size(s->width, s->height, 0, s))
+ return -1;
+
+ if (!ist->buffer_pool && (ret = alloc_buffer(s, ist, &ist->buffer_pool)) < 0)
return ret;
buf = ist->buffer_pool;
av_freep(&buf->base[0]);
av_free(buf);
ist->dr1 = 0;
- if ((ret = alloc_buffer(ist, &buf)) < 0)
+ if ((ret = alloc_buffer(s, ist, &buf)) < 0)
return ret;
}
buf->refcount++;
"src", args, NULL, ost->graph);
if (ret < 0)
return ret;
+
#if FF_API_OLD_VSINK_API
ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
"out", NULL, pix_fmts, ost->graph);
"out", NULL, buffersink_params, ost->graph);
#endif
av_freep(&buffersink_params);
+
if (ret < 0)
return ret;
last_filter = ost->input_video_filter;
{
av_log(NULL, AV_LOG_QUIET, "%s", "");
#if HAVE_TERMIOS_H
- if(!run_as_daemon)
+ if(restore_tty)
tcsetattr (0, TCSANOW, &oldtty);
#endif
}
if(!run_as_daemon){
struct termios tty;
- tcgetattr (0, &tty);
+ if (tcgetattr (0, &tty) == 0) {
oldtty = tty;
+ restore_tty = 1;
atexit(term_exit);
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
+ }
signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */
}
#endif
bsfc = next;
}
output_streams[i].bitstream_filters = NULL;
+
+ if (output_streams[i].output_frame) {
+ AVFrame *frame = output_streams[i].output_frame;
+ if (frame->extended_data != frame->data)
+ av_freep(&frame->extended_data);
+ av_freep(&frame);
+ }
}
for (i = 0; i < nb_input_files; i++) {
avformat_close_input(&input_files[i].ctx);
uninit_opts();
av_free(audio_buf);
- av_free(audio_out);
- allocated_audio_buf_size = allocated_audio_out_size = 0;
+ allocated_audio_buf_size = 0;
#if CONFIG_AVFILTER
avfilter_uninit();
}
}
-static double get_sync_ipts(const OutputStream *ost)
+static double
+get_sync_ipts(const OutputStream *ost, int64_t pts)
{
- const InputStream *ist = ost->sync_ist;
OutputFile *of = &output_files[ost->file_index];
- return (double)(ist->pts - of->start_time) / AV_TIME_BASE;
+ return (double)(pts - of->start_time) / AV_TIME_BASE;
}
static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
AVCodecContext *avctx = ost->st->codec;
int ret;
+ /*
+ * Audio encoders may split the packets -- #frames in != #packets out.
+ * But there is no reordering, so we can limit the number of output packets
+ * by simply dropping them here.
+ * Counting encoded video frames needs to be done separately because of
+ * reordering, see do_video_out()
+ */
+ if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
+ if (ost->frame_number >= ost->max_frames)
+ return;
+ ost->frame_number++;
+ }
+
while (bsfc) {
AVPacket new_pkt = *pkt;
int a = av_bitstream_filter_filter(bsfc, avctx, NULL,
av_free_packet(pkt);
new_pkt.destruct = av_destruct_packet;
} else if (a < 0) {
- av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s",
+ av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s",
bsfc->filter->name, pkt->stream_index,
avctx->codec ? avctx->codec->name : "copy");
print_error("", a);
bsfc = bsfc->next;
}
+ pkt->stream_index = ost->index;
ret = av_interleaved_write_frame(s, pkt);
if (ret < 0) {
print_error("av_interleaved_write_frame()", ret);
exit_program(1);
}
- ost->frame_number++;
}
static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size)
memset(buf, fill_char, size);
}
+static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
+ const uint8_t *buf, int buf_size)
+{
+ AVCodecContext *enc = ost->st->codec;
+ AVFrame *frame = NULL;
+ AVPacket pkt;
+ int ret, got_packet;
+
+ av_init_packet(&pkt);
+ pkt.data = NULL;
+ pkt.size = 0;
+
+ if (buf) {
+ if (!ost->output_frame) {
+ ost->output_frame = avcodec_alloc_frame();
+ if (!ost->output_frame) {
+ av_log(NULL, AV_LOG_FATAL, "out-of-memory in encode_audio_frame()\n");
+ exit_program(1);
+ }
+ }
+ frame = ost->output_frame;
+ if (frame->extended_data != frame->data)
+ av_freep(&frame->extended_data);
+ avcodec_get_frame_defaults(frame);
+
+ frame->nb_samples = buf_size /
+ (enc->channels * av_get_bytes_per_sample(enc->sample_fmt));
+ if ((ret = avcodec_fill_audio_frame(frame, enc->channels, enc->sample_fmt,
+ buf, buf_size, 1)) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
+ exit_program(1);
+ }
+
+ ost->sync_opts += frame->nb_samples;
+ }
+
+ got_packet = 0;
+ if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
+ exit_program(1);
+ }
+
+ ret = pkt.size;
+
+ if (got_packet) {
+ if (pkt.pts != AV_NOPTS_VALUE)
+ pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
+ if (pkt.duration > 0)
+ pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
+
+ write_frame(s, &pkt, ost);
+
+ audio_size += pkt.size;
+
+ av_free_packet(&pkt);
+ }
+
+ return ret;
+}
+
static void do_audio_out(AVFormatContext *s, OutputStream *ost,
InputStream *ist, AVFrame *decoded_frame)
{
uint8_t *buftmp;
- int64_t audio_out_size, audio_buf_size;
+ int64_t audio_buf_size, size_out;
- int size_out, frame_bytes, ret, resample_changed;
+ int frame_bytes, resample_changed;
AVCodecContext *enc = ost->st->codec;
AVCodecContext *dec = ist->st->codec;
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);
uint8_t *buf = decoded_frame->data[0];
int size = decoded_frame->nb_samples * dec->channels * isize;
int64_t allocated_for_size = size;
audio_buf_size = FFMAX(audio_buf_size, enc->frame_size);
audio_buf_size *= osize * enc->channels;
- audio_out_size = FFMAX(audio_buf_size, enc->frame_size * osize * enc->channels);
- if (coded_bps > 8 * osize)
- audio_out_size = audio_out_size * coded_bps / (8*osize);
- audio_out_size += FF_MIN_BUFFER_SIZE;
-
- if (audio_out_size > INT_MAX || audio_buf_size > INT_MAX) {
+ if (audio_buf_size > INT_MAX) {
av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n");
exit_program(1);
}
av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);
- av_fast_malloc(&audio_out, &allocated_audio_out_size, audio_out_size);
- if (!audio_buf || !audio_out) {
+ if (!audio_buf) {
av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
exit_program(1);
}
av_opt_set_int(ost->swr, "icl", av_get_default_channel_layout(ost->audio_channels_mapped), 0);
av_opt_set_int(ost->swr, "uch", ost->audio_channels_mapped, 0);
}
- av_opt_set_int(ost->swr, "ich", dec->channels, 0);
- av_opt_set_int(ost->swr, "och", enc->channels, 0);
+ if (av_opt_set_int(ost->swr, "ich", dec->channels, 0) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Unsupported number of input channels\n");
+ exit_program(1);
+ }
+ if (av_opt_set_int(ost->swr, "och", enc->channels, 0) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Unsupported number of output channels\n");
+ exit_program(1);
+ }
if(audio_sync_method>1) av_opt_set_int(ost->swr, "flags", SWR_FLAG_RESAMPLE, 0);
if(ost->swr && swr_init(ost->swr) < 0){
av_log(NULL, AV_LOG_FATAL, "swr_init() failed\n");
av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
if (audio_sync_method) {
- double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts -
+ double delta = get_sync_ipts(ost, ist->pts) * enc->sample_rate - ost->sync_opts -
av_fifo_size(ost->fifo) / (enc->channels * osize);
int idelta = delta * dec->sample_rate / enc->sample_rate;
int byte_delta = idelta * isize * dec->channels;
av_log(NULL, AV_LOG_VERBOSE, "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));
- swr_compensate(ost->swr, comp, enc->sample_rate);
+ swr_set_compensation(ost->swr, comp, enc->sample_rate);
}
}
} else
- ost->sync_opts = lrintf(get_sync_ipts(ost) * enc->sample_rate) -
+ ost->sync_opts = lrintf(get_sync_ipts(ost, ist->pts) * enc->sample_rate) -
av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong
- if (ost->audio_resample) {
+ if (ost->audio_resample || ost->audio_channels_mapped) {
buftmp = audio_buf;
size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp}, audio_buf_size / (enc->channels * osize),
(const uint8_t*[]){buf }, size / (dec->channels * isize));
av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
/* now encode as many frames as possible */
- if (enc->frame_size > 1) {
+ if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
/* output resampled raw samples */
if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
frame_bytes = enc->frame_size * osize * enc->channels;
while (av_fifo_size(ost->fifo) >= frame_bytes) {
- AVPacket pkt;
- av_init_packet(&pkt);
-
av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
-
- // FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
-
- ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
- (short *)audio_buf);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
- exit_program(1);
- }
- audio_size += ret;
- pkt.stream_index = ost->index;
- pkt.data = audio_out;
- pkt.size = ret;
- if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
- pkt.flags |= AV_PKT_FLAG_KEY;
- write_frame(s, &pkt, ost);
-
- ost->sync_opts += enc->frame_size;
+ encode_audio_frame(s, ost, audio_buf, frame_bytes);
}
} else {
- AVPacket pkt;
- av_init_packet(&pkt);
-
- ost->sync_opts += size_out / (osize * enc->channels);
-
- /* output a pcm frame */
- /* determine the size of the coded buffer */
- size_out /= osize;
- if (coded_bps)
- size_out = size_out * coded_bps / 8;
-
- if (size_out > audio_out_size) {
- av_log(NULL, AV_LOG_FATAL, "Internal error, buffer size too small\n");
- exit_program(1);
- }
-
- // FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
- ret = avcodec_encode_audio(enc, audio_out, size_out,
- (short *)buftmp);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
- exit_program(1);
- }
- audio_size += ret;
- pkt.stream_index = ost->index;
- pkt.data = audio_out;
- pkt.size = ret;
- if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
- pkt.flags |= AV_PKT_FLAG_KEY;
- write_frame(s, &pkt, ost);
+ encode_audio_frame(s, ost, buftmp, size_out);
}
}
nb = 1;
for (i = 0; i < nb; i++) {
+ ost->sync_opts = av_rescale_q(pts, ist->st->time_base, enc->time_base);
+
sub->pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q);
// start_display_time is required to be 0
sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q);
}
av_init_packet(&pkt);
- pkt.stream_index = ost->index;
pkt.data = subtitle_out;
pkt.size = subtitle_out_size;
pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base);
}
}
-static int bit_buffer_size = 1024 * 256;
-static uint8_t *bit_buffer = NULL;
-
static void do_video_resample(OutputStream *ost,
InputStream *ist,
AVFrame *in_picture,
#else
AVCodecContext *dec = ist->st->codec;
AVCodecContext *enc = ost->st->codec;
- int resample_changed = ost->resample_width != dec->width ||
- ost->resample_height != dec->height ||
- ost->resample_pix_fmt != dec->pix_fmt;
+ int resample_changed = ost->resample_width != in_picture->width ||
+ ost->resample_height != in_picture->height ||
+ ost->resample_pix_fmt != in_picture->format;
*out_picture = in_picture;
if (resample_changed) {
av_log(NULL, AV_LOG_INFO,
- "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
+ "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s / frm size:%dx%d fmt:%s\n",
ist->file_index, ist->st->index,
ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
- dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt));
- ost->resample_width = dec->width;
- ost->resample_height = dec->height;
- ost->resample_pix_fmt = dec->pix_fmt;
+ dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt),
+ in_picture->width, in_picture->height, av_get_pix_fmt_name(in_picture->format));
+ ost->resample_width = in_picture->width;
+ ost->resample_height = in_picture->height;
+ ost->resample_pix_fmt = in_picture->format;
}
- ost->video_resample = dec->width != enc->width ||
- dec->height != enc->height ||
- dec->pix_fmt != enc->pix_fmt;
+ ost->video_resample = in_picture->width != enc->width ||
+ in_picture->height != enc->height ||
+ in_picture->format != enc->pix_fmt;
if (ost->video_resample) {
*out_picture = &ost->resample_frame;
}
/* initialize a new scaler context */
sws_freeContext(ost->img_resample_ctx);
- ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,
+ ost->img_resample_ctx = sws_getContext(in_picture->width, in_picture->height, in_picture->format,
enc->width, enc->height, enc->pix_fmt,
ost->sws_flags, NULL, NULL, NULL);
if (ost->img_resample_ctx == NULL) {
duration /= av_q2d(enc->time_base);
}
- sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base);
+ sync_ipts = get_sync_ipts(ost, in_picture->pts) / av_q2d(enc->time_base);
/* by default, we output a single frame */
nb_frames = 1;
*frame_size = 0;
format_video_sync = video_sync_method;
- if (format_video_sync < 0)
- format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : 2) : 1;
+ if (format_video_sync == VSYNC_AUTO)
+ format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : 1;
- if (format_video_sync) {
+ if (format_video_sync != VSYNC_PASSTHROUGH && format_video_sync != VSYNC_DROP) {
double vdelta = sync_ipts - ost->sync_opts + duration;
// 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 (format_video_sync == 2) {
+ else if (format_video_sync == VSYNC_VFR) {
if (vdelta <= -0.6) {
nb_frames = 0;
} else if (vdelta > 0.6)
ost->sync_opts = lrintf(sync_ipts);
} 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, get_sync_ipts(ost), nb_frames);
if (nb_frames == 0) {
++nb_frames_drop;
av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n");
for (i = 0; i < nb_frames; i++) {
AVPacket pkt;
av_init_packet(&pkt);
- pkt.stream_index = ost->index;
+ pkt.data = NULL;
+ pkt.size = 0;
if (s->oformat->flags & AVFMT_RAWPICTURE &&
enc->codec->id == CODEC_ID_RAWVIDEO) {
write_frame(s, &pkt, ost);
} else {
+ int got_packet;
AVFrame big_picture;
big_picture = *final_picture;
big_picture.quality = quality;
if (!enc->me_threshold)
big_picture.pict_type = 0;
-// big_picture.pts = AV_NOPTS_VALUE;
big_picture.pts = ost->sync_opts;
-// big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
-// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
if (ost->forced_kf_index < ost->forced_kf_count &&
big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
big_picture.pict_type = AV_PICTURE_TYPE_I;
ost->forced_kf_index++;
}
- ret = avcodec_encode_video(enc,
- bit_buffer, bit_buffer_size,
- &big_picture);
+ ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
- if (ret > 0) {
- pkt.data = bit_buffer;
- pkt.size = ret;
- if (enc->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
-/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
- pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,
- pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/
-
- if (enc->coded_frame->key_frame)
- pkt.flags |= AV_PKT_FLAG_KEY;
+ if (got_packet) {
+ if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
+ pkt.pts = ost->sync_opts;
+
+ if (pkt.pts != AV_NOPTS_VALUE)
+ pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
+ if (pkt.dts != AV_NOPTS_VALUE)
+ pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
+
+ if (format_video_sync == VSYNC_DROP)
+ pkt.pts = pkt.dts = AV_NOPTS_VALUE;
+
write_frame(s, &pkt, ost);
- *frame_size = ret;
- video_size += ret;
- // fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
- // enc->frame_number-1, ret, enc->pict_type);
+ *frame_size = pkt.size;
+ video_size += pkt.size;
+
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
}
ost->sync_opts++;
+ /*
+ * For video, number of frames in == number of packets out.
+ * But there may be reordering, so we can't throw away frames on encoder
+ * flush, we need to limit them here, before they go into encoder.
+ */
+ ost->frame_number++;
}
}
OutputStream *ost = &ost_table[i];
AVCodecContext *enc = ost->st->codec;
AVFormatContext *os = output_files[ost->file_index].ctx;
+ int stop_encoding = 0;
if (!ost->encoding_needed)
continue;
for (;;) {
AVPacket pkt;
- int fifo_bytes;
+ int fifo_bytes, got_packet;
av_init_packet(&pkt);
- pkt.stream_index = ost->index;
+ pkt.data = NULL;
+ pkt.size = 0;
switch (ost->st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
fifo_bytes = av_fifo_size(ost->fifo);
- ret = 0;
- /* encode any samples remaining in fifo */
if (fifo_bytes > 0) {
- int osize = av_get_bytes_per_sample(enc->sample_fmt);
- int fs_tmp = enc->frame_size;
+ /* encode any samples remaining in fifo */
+ int frame_bytes = fifo_bytes;
av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
- if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
- enc->frame_size = fifo_bytes / (osize * enc->channels);
- } else { /* pad */
- int frame_bytes = enc->frame_size*osize*enc->channels;
+
+ /* pad last frame with silence if needed */
+ if (!(enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)) {
+ frame_bytes = enc->frame_size * enc->channels *
+ av_get_bytes_per_sample(enc->sample_fmt);
if (allocated_audio_buf_size < frame_bytes)
exit_program(1);
generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
}
-
- ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf);
- pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
- ost->st->time_base.num, enc->sample_rate);
- enc->frame_size = fs_tmp;
- }
- if (ret <= 0) {
- ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
- }
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
- exit_program(1);
+ encode_audio_frame(os, ost, audio_buf, frame_bytes);
+ } else {
+ /* flush encoder with NULL frames until it is done
+ returning packets */
+ if (encode_audio_frame(os, ost, NULL, 0) == 0) {
+ stop_encoding = 1;
+ break;
+ }
}
- audio_size += ret;
- pkt.flags |= AV_PKT_FLAG_KEY;
break;
case AVMEDIA_TYPE_VIDEO:
- ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
+ ret = avcodec_encode_video2(enc, &pkt, NULL, &got_packet);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
- video_size += ret;
- if (enc->coded_frame && enc->coded_frame->key_frame)
- pkt.flags |= AV_PKT_FLAG_KEY;
+ video_size += pkt.size;
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
+ if (!got_packet) {
+ stop_encoding = 1;
+ break;
+ }
+ if (pkt.pts != AV_NOPTS_VALUE)
+ pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
+ if (pkt.dts != AV_NOPTS_VALUE)
+ pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
+ write_frame(os, &pkt, ost);
break;
default:
- ret = -1;
+ stop_encoding = 1;
}
-
- if (ret <= 0)
+ if (stop_encoding)
break;
- pkt.data = bit_buffer;
- pkt.size = ret;
- if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
- write_frame(os, &pkt, ost);
}
}
}
ost->sync_opts++;
}
- opkt.stream_index = ost->index;
if (pkt->pts != AV_NOPTS_VALUE)
opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
else
opkt.pts = AV_NOPTS_VALUE;
if (pkt->dts == AV_NOPTS_VALUE)
- opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
+ opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->st->time_base);
else
opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
opkt.dts -= ost_tb_start_time;
static void rate_emu_sleep(InputStream *ist)
{
if (input_files[ist->file_index].rate_emu) {
- int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE);
+ int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
int64_t now = av_gettime() - ist->start;
if (pts > now)
usleep(pts - now);
/* if the decoder provides a pts, use it instead of the last packet pts.
the decoder could be delaying output by a packet or more. */
if (decoded_frame->pts != AV_NOPTS_VALUE)
- ist->next_pts = decoded_frame->pts;
+ ist->dts = ist->next_dts = ist->pts = ist->next_pts = decoded_frame->pts;
- /* increment next_pts to use for the case where the input stream does not
+ /* increment next_dts to use for the case where the input stream does not
have timestamps or there are multiple frames in the packet */
ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
avctx->sample_rate;
+ ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
+ avctx->sample_rate;
+
// preprocess audio (volume)
if (audio_volume != 256) {
return ret;
}
-static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts, int64_t *pkt_dts)
+static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts)
{
AVFrame *decoded_frame, *filtered_frame = NULL;
void *buffer_to_free = NULL;
#if CONFIG_AVFILTER
int frame_available = 1;
#endif
- int duration=0;
int64_t *best_effort_timestamp;
AVRational *frame_sample_aspect;
avcodec_get_frame_defaults(ist->decoded_frame);
decoded_frame = ist->decoded_frame;
pkt->pts = *pkt_pts;
- pkt->dts = *pkt_dts;
+ pkt->dts = ist->dts;
*pkt_pts = AV_NOPTS_VALUE;
- if (pkt->duration) {
- duration = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
- } else 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;
- duration = ((int64_t)AV_TIME_BASE *
- ist->st->codec->time_base.num * ticks) /
- ist->st->codec->time_base.den;
- }
-
- if(*pkt_dts != AV_NOPTS_VALUE && duration) {
- *pkt_dts += duration;
- }else
- *pkt_dts = AV_NOPTS_VALUE;
-
ret = avcodec_decode_video2(ist->st->codec,
decoded_frame, got_output, pkt);
if (ret < 0)
best_effort_timestamp= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "best_effort_timestamp");
if(*best_effort_timestamp != AV_NOPTS_VALUE)
- ist->next_pts = ist->pts = *best_effort_timestamp;
+ ist->next_pts = ist->pts = decoded_frame->pts = *best_effort_timestamp;
- ist->next_pts += duration;
pkt->size = 0;
pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for(i=0;i<nb_output_streams;i++) {
OutputStream *ost = ost = &output_streams[i];
- if(check_output_constraints(ist, ost)){
+ if(check_output_constraints(ist, ost) && ost->encoding_needed){
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
decoded_frame->pts = ist->pts;
ist->st->codec->pix_fmt);
avfilter_copy_frame_props(fb, decoded_frame);
- fb->pts = ist->pts;
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
*filtered_frame= *decoded_frame; //for me_threshold
if (ost->picref) {
avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref);
- ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
+ filtered_frame->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
}
}
if (ost->picref->video && !ost->frame_aspect_ratio)
{
int ret = 0, i;
int got_output;
- int64_t pkt_dts = AV_NOPTS_VALUE;
int64_t pkt_pts = AV_NOPTS_VALUE;
AVPacket avpkt;
+ if (ist->next_dts == AV_NOPTS_VALUE)
+ ist->next_dts = ist->dts;
if (ist->next_pts == AV_NOPTS_VALUE)
ist->next_pts = ist->pts;
}
if (pkt->dts != AV_NOPTS_VALUE) {
+ ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
- pkt_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
}
if(pkt->pts != AV_NOPTS_VALUE)
pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
// while we have more to decode or while the decoder did output something on EOF
while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
+ int duration;
handle_eof:
ist->pts = ist->next_pts;
+ ist->dts = ist->next_dts;
if (avpkt.size && avpkt.size != pkt->size) {
av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING,
ret = transcode_audio (ist, &avpkt, &got_output);
break;
case AVMEDIA_TYPE_VIDEO:
- ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts, &pkt_dts);
+ ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts);
+ if (avpkt.duration) {
+ duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
+ } else 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;
+ duration = ((int64_t)AV_TIME_BASE *
+ ist->st->codec->time_base.num * ticks) /
+ ist->st->codec->time_base.den;
+ } else
+ duration = 0;
+
+ if(ist->dts != AV_NOPTS_VALUE && duration) {
+ ist->next_dts += duration;
+ }else
+ ist->next_dts = AV_NOPTS_VALUE;
+
+ if (got_output)
+ ist->next_pts += duration; //FIXME the duration is not correct in some cases
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = transcode_subtitles(ist, &avpkt, &got_output);
/* handle stream copy */
if (!ist->decoding_needed) {
rate_emu_sleep(ist);
- ist->pts = ist->next_pts;
+ ist->dts = ist->next_dts;
switch (ist->st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
+ ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
ist->st->codec->sample_rate;
break;
case AVMEDIA_TYPE_VIDEO:
if (pkt->duration) {
- ist->next_pts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
+ ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
} else 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->next_dts += ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num * ticks) /
ist->st->codec->time_base.den;
}
break;
}
+ ist->pts = ist->dts;
+ ist->next_pts = ist->next_dts;
}
for (i = 0; pkt && i < nb_ostreams; i++) {
OutputStream *ost = &ost_table[i];
ist->st->codec->opaque = ist;
}
+ if (!av_dict_get(ist->opts, "threads", NULL, 0))
+ av_dict_set(&ist->opts, "threads", "auto", 0);
if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
ist->file_index, ist->st->index);
assert_avoptions(ist->opts);
}
- ist->pts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
+ ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
ist->next_pts = AV_NOPTS_VALUE;
+ ist->next_dts = AV_NOPTS_VALUE;
ist->is_start = 1;
return 0;
codec->extradata_size= icodec->extradata_size;
codec->time_base = ist->st->time_base;
+ /*
+ * Avi is a special case here because it supports variable fps but
+ * having the fps and timebase differe significantly adds quite some
+ * overhead
+ */
if(!strcmp(oc->oformat->name, "avi")) {
if ( copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > 2*av_q2d(ist->st->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500
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 && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
+ if ( av_q2d(codec->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
+ && (video_sync_method == VSYNC_CFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
av_log(oc, 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");
}
#endif
break;
case AVMEDIA_TYPE_SUBTITLE:
+ codec->time_base = (AVRational){1, 1000};
break;
default:
abort();
}
}
}
- if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- /* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)*/
- int size = codec->width * codec->height;
- bit_buffer_size = FFMAX(bit_buffer_size, 7*size + 10000);
- }
- }
-
- if (!bit_buffer)
- bit_buffer = av_malloc(bit_buffer_size);
- if (!bit_buffer) {
- av_log(NULL, AV_LOG_ERROR, "Cannot allocate %d bytes output buffer\n",
- bit_buffer_size);
- return AVERROR(ENOMEM);
}
/* open each encoder */
memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size);
ost->st->codec->subtitle_header_size = dec->subtitle_header_size;
}
+ if (!av_dict_get(ost->opts, "threads", NULL, 0))
+ av_dict_set(&ost->opts, "threads", "auto", 0);
if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) {
snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height",
ost->file_index, ost->index);
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts *= ist->ts_scale;
- //fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n",
- // ist->next_pts,
- // pkt.dts, input_files[ist->file_index].ts_offset,
+ //fprintf(stderr, "next:%"PRId64" dts:%"PRId64"/%"PRId64" off:%"PRId64" %d\n",
+ // ist->next_dts,
+ // ist->dts, av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q), input_files[ist->file_index].ts_offset,
// ist->st->codec->codec_type);
- if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE
+ if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE
&& (is->iformat->flags & AVFMT_TS_DISCONT)) {
int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
- int64_t delta = pkt_dts - ist->next_pts;
+ int64_t delta = pkt_dts - ist->next_dts;
if((delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
(delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
ret = 0;
fail:
- av_freep(&bit_buffer);
av_freep(&no_packet);
if (output_streams) {
return -1;
}
-static double parse_frame_aspect_ratio(const char *arg)
-{
- int x = 0, y = 0;
- double ar = 0;
- const char *p;
- char *end;
-
- p = strchr(arg, ':');
- if (p) {
- x = strtol(arg, &end, 10);
- if (end == p)
- y = strtol(end + 1, &end, 10);
- if (x > 0 && y > 0)
- ar = (double)x / (double)y;
- } else
- ar = strtod(arg, NULL);
-
- if (!ar) {
- av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n");
- exit_program(1);
- }
- return ar;
-}
-
static int opt_video_channel(const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
ic->flags |= AVFMT_FLAG_NONBLOCK;
ic->interrupt_callback = int_cb;
- if (loop_input) {
- av_log(NULL, AV_LOG_WARNING,
- "-loop_input is deprecated, use -loop 1\n"
- "Note, both loop options only work with -f image2\n"
- );
- ic->loop_input = loop_input;
- }
-
/* open the input file with generic avformat function */
err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
if (err < 0) {
}
MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
- if (frame_aspect_ratio)
- ost->frame_aspect_ratio = parse_frame_aspect_ratio(frame_aspect_ratio);
+ if (frame_aspect_ratio) {
+ AVRational q;
+ if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
+ q.num <= 0 || q.den <= 0) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio);
+ exit_program(1);
+ }
+ ost->frame_aspect_ratio = av_q2d(q);
+ }
video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
ost->top_field_first = -1;
MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
- MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
-
#if CONFIG_AVFILTER
MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
if (filters)
ost->avfilter = av_strdup(filters);
#endif
+ } else {
+ MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
}
return ost;
}
oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
- if (loop_output >= 0) {
- av_log(NULL, AV_LOG_WARNING, "-loop_output is deprecated, use -loop\n");
- oc->loop_output = loop_output;
- }
-
/* copy metadata */
for (i = 0; i < o->nb_metadata_map; i++) {
char *p;
static void show_usage(void)
{
- printf("Hyper fast Audio and Video encoder\n");
- printf("usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
- printf("\n");
+ av_log(NULL, AV_LOG_INFO, "Hyper fast Audio and Video encoder\n");
+ av_log(NULL, AV_LOG_INFO, "usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
+ av_log(NULL, AV_LOG_INFO, "\n");
}
static int opt_help(const char *opt, const char *arg)
static int opt_old2new(OptionsContext *o, const char *opt, const char *arg)
{
- char *s= av_malloc(strlen(opt)+2);
- snprintf(s, strlen(opt)+2, "%s:%c", opt+1, *opt);
- return parse_option(o, s, arg, options);
+ char *s = av_asprintf("%s:%c", opt + 1, *opt);
+ int ret = parse_option(o, s, arg, options);
+ av_free(s);
+ return ret;
}
static int opt_bitrate(OptionsContext *o, const char *opt, const char *arg)
{
if(!strcmp(opt, "b")){
av_log(0,AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n");
- return parse_option(o, av_strdup("b:v"), arg, options);
+ return parse_option(o, "b:v", arg, options);
}
return opt_default(opt, arg);
}
+static int opt_qscale(OptionsContext *o, const char *opt, const char *arg)
+{
+ char *s;
+ int ret;
+ if(!strcmp(opt, "qscale")){
+ av_log(0,AV_LOG_WARNING, "Please use -q:a or -q:v, -qscale is ambiguous\n");
+ return parse_option(o, "q:v", arg, options);
+ }
+ s = av_asprintf("q%s", opt + 6);
+ ret = parse_option(o, s, arg, options);
+ av_free(s);
+ return ret;
+}
+
static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg)
{
return parse_option(o, "filter:v", arg, options);
}
+static int opt_vsync(const char *opt, const char *arg)
+{
+ if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR;
+ else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR;
+ else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH;
+ else if (!av_strcasecmp(arg, "drop")) video_sync_method = VSYNC_DROP;
+
+ if (video_sync_method == VSYNC_AUTO)
+ video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR);
+ return 0;
+}
+
+static int opt_deinterlace(const char *opt, const char *arg)
+{
+ av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -filter:v yadif instead\n", opt);
+ do_deinterlace = 1;
+ return 0;
+}
+
#define OFFSET(x) offsetof(OptionsContext, x)
static const OptionDef options[] = {
/* main options */
{ "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
"when dumping packets, also dump the payload" },
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" },
- { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" },
- { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" },
{ "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
- { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
+ { "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
{ "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" },
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" },
{ "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" },
{ "tag", OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" },
{ "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
- { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
+ { "qscale", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_qscale}, "use fixed quality scale (VBR)", "q" },
#if CONFIG_AVFILTER
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
#endif
"use same quantizer as source (implies VBR)" },
{ "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" },
{ "passlogfile", HAS_ARG | OPT_VIDEO, {(void*)&opt_passlogfile}, "select two pass log file name prefix", "prefix" },
- { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
- "deinterlace pictures" },
+ { "deinterlace", OPT_EXPERT | OPT_VIDEO, {(void*)opt_deinterlace},
+ "this option is deprecated, use the yadif filter instead" },
{ "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" },