summaryrefslogtreecommitdiff
path: root/ffmpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg.c')
-rw-r--r--ffmpeg.c718
1 files changed, 421 insertions, 297 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index ccf9c62486..6196a5ade5 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2,20 +2,20 @@
* ffmpeg main
* Copyright (c) 2000-2003 Fabrice Bellard
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -46,9 +46,13 @@
#include "libavutil/libm.h"
#include "libavformat/os_support.h"
+#include "libavformat/ffm.h" // not public API
+
#if CONFIG_AVFILTER
+# include "libavfilter/avcodec.h"
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
+# include "libavfilter/vsink_buffer.h"
# include "libavfilter/vsrc_buffer.h"
#endif
@@ -68,6 +72,14 @@
#include <sys/select.h>
#endif
+#if HAVE_TERMIOS_H
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <termios.h>
+#elif HAVE_KBHIT
+#include <conio.h>
+#endif
#include <time.h>
#include "cmdutils.h"
@@ -102,13 +114,12 @@ typedef struct ChapterMap {
static const OptionDef options[];
#define MAX_FILES 100
-
+#define MAX_STREAMS 1024 /* arbitrary sanity check value */
static const char *last_asked_format = NULL;
static double *ts_scale;
static int nb_ts_scale;
static AVFormatContext *output_files[MAX_FILES];
-static AVDictionary *output_opts[MAX_FILES];
static int nb_output_files = 0;
static StreamMap *stream_maps = NULL;
@@ -132,6 +143,7 @@ static int frame_width = 0;
static int frame_height = 0;
static float frame_aspect_ratio = 0;
static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
+static int frame_bits_per_raw_sample = 0;
static enum AVSampleFormat audio_sample_fmt = AV_SAMPLE_FMT_NONE;
static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
static AVRational frame_rate;
@@ -188,7 +200,7 @@ static int do_hex_dump = 0;
static int do_pkt_dump = 0;
static int do_psnr = 0;
static int do_pass = 0;
-static char *pass_logfilename_prefix = NULL;
+static const char *pass_logfilename_prefix;
static int audio_stream_copy = 0;
static int video_stream_copy = 0;
static int subtitle_stream_copy = 0;
@@ -197,7 +209,7 @@ static int video_sync_method= -1;
static int audio_sync_method= 0;
static float audio_drift_threshold= 0.1;
static int copy_ts= 0;
-static int copy_tb;
+static int copy_tb= 0;
static int opt_shortest = 0;
static char *vstats_filename;
static FILE *vstats_file;
@@ -206,12 +218,17 @@ static int copy_initial_nonkeyframes = 0;
static int rate_emu = 0;
+static int video_channel = 0;
+static char *video_standard;
+
static int audio_volume = 256;
static int exit_on_error = 0;
static int using_stdin = 0;
static int verbose = 1;
+static int run_as_daemon = 0;
static int thread_count= 1;
+static int q_pressed = 0;
static int64_t video_size = 0;
static int64_t audio_size = 0;
static int64_t extra_size = 0;
@@ -257,7 +274,7 @@ typedef struct OutputStream {
/* video only */
int video_resample;
- AVFrame pict_tmp; /* temporary image for resampling */
+ AVFrame resample_frame; /* temporary frame for image resampling */
struct SwsContext *img_resample_ctx; /* for image resampling */
int resample_height;
int resample_width;
@@ -307,7 +324,6 @@ typedef struct InputStream {
int64_t next_pts; /* synthetic pts for cases where pkt.pts
is not defined */
int64_t pts; /* current pts */
- PtsCorrectionContext pts_ctx;
double ts_scale;
int is_start; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning;
@@ -322,6 +338,12 @@ typedef struct InputFile {
int64_t ts_offset;
} InputFile;
+#if HAVE_TERMIOS_H
+
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+#endif
+
static InputStream *input_streams = NULL;
static int nb_input_streams = 0;
static InputFile *input_files = NULL;
@@ -335,7 +357,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *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;
@@ -355,8 +377,8 @@ static int configure_video_filters(InputStream *ist, OutputStream *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;
@@ -378,8 +400,8 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
ost->graph->scale_sws_opts = av_strdup(args);
if (ost->avfilter) {
- AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
- AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
+ AVFilterInOut *outputs = avfilter_inout_alloc();
+ AVFilterInOut *inputs = avfilter_inout_alloc();
outputs->name = av_strdup("in");
outputs->filter_ctx = last_filter;
@@ -391,7 +413,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
inputs->pad_idx = 0;
inputs->next = NULL;
- if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, inputs, outputs, NULL)) < 0)
+ if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
return ret;
av_freep(&ost->avfilter);
} else {
@@ -415,22 +437,47 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
static void term_exit(void)
{
- av_log(NULL, AV_LOG_QUIET, "");
+ av_log(NULL, AV_LOG_QUIET, "%s", "");
+#if HAVE_TERMIOS_H
+ if(!run_as_daemon)
+ tcsetattr (0, TCSANOW, &oldtty);
+#endif
}
static volatile int received_sigterm = 0;
-static volatile int received_nb_signals = 0;
static void
sigterm_handler(int sig)
{
received_sigterm = sig;
- received_nb_signals++;
+ q_pressed++;
term_exit();
}
static void term_init(void)
{
+#if HAVE_TERMIOS_H
+ if(!run_as_daemon){
+ struct termios tty;
+
+ tcgetattr (0, &tty);
+ oldtty = tty;
+ atexit(term_exit);
+
+ tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+
+ tcsetattr (0, TCSANOW, &tty);
+ signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */
+ }
+#endif
+
signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
#ifdef SIGXCPU
@@ -438,9 +485,41 @@ static void term_init(void)
#endif
}
+/* read a key without blocking */
+static int read_key(void)
+{
+#if HAVE_TERMIOS_H
+ int n = 1;
+ unsigned char ch;
+ struct timeval tv;
+ fd_set rfds;
+
+ if(run_as_daemon)
+ return -1;
+
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ n = select(1, &rfds, NULL, NULL, &tv);
+ if (n > 0) {
+ n = read(0, &ch, 1);
+ if (n == 1)
+ return ch;
+
+ return n;
+ }
+#elif HAVE_KBHIT
+ if(kbhit())
+ return(getch());
+#endif
+ return -1;
+}
+
static int decode_interrupt_cb(void)
{
- return received_nb_signals > 1;
+ q_pressed += read_key() == 'q';
+ return q_pressed > 1;
}
static int ffmpeg_exit(int ret)
@@ -454,7 +533,6 @@ static int ffmpeg_exit(int ret)
avio_close(s->pb);
avformat_free_context(s);
av_free(output_streams_for_file[i]);
- av_dict_free(&output_opts[i]);
}
for(i=0;i<nb_input_files;i++) {
av_close_input_file(input_files[i].ctx);
@@ -479,6 +557,8 @@ static int ffmpeg_exit(int ret)
av_free(subtitle_codec_name);
av_free(data_codec_name);
+ av_free(video_standard);
+
uninit_opts();
av_free(audio_buf);
av_free(audio_out);
@@ -500,15 +580,6 @@ static int ffmpeg_exit(int ret)
return ret;
}
-static void assert_avoptions(AVDictionary *m)
-{
- AVDictionaryEntry *t;
- if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
- av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
- ffmpeg_exit(1);
- }
-}
-
/* similar to ff_dynarray_add() and av_fast_realloc() */
static void *grow_array(void *array, int elem_size, int *size, int new_size)
{
@@ -538,6 +609,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),
@@ -548,46 +621,6 @@ static void choose_sample_fmt(AVStream *st, AVCodec *codec)
}
}
-/**
- * Update the requested input sample format based on the output sample format.
- * This is currently only used to request float output from decoders which
- * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT.
- * Ideally this will be removed in the future when decoders do not do format
- * conversion and only output in their native format.
- */
-static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec,
- AVCodecContext *enc)
-{
- /* if sample formats match or a decoder sample format has already been
- requested, just return */
- if (enc->sample_fmt == dec->sample_fmt ||
- dec->request_sample_fmt > AV_SAMPLE_FMT_NONE)
- return;
-
- /* if decoder supports more than one output format */
- if (dec_codec && dec_codec->sample_fmts &&
- dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE &&
- dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) {
- const enum AVSampleFormat *p;
- int min_dec = -1, min_inc = -1;
-
- /* find a matching sample format in the encoder */
- for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) {
- if (*p == enc->sample_fmt) {
- dec->request_sample_fmt = *p;
- return;
- } else if (*p > enc->sample_fmt) {
- min_inc = FFMIN(min_inc, *p - enc->sample_fmt);
- } else
- min_dec = FFMIN(min_dec, enc->sample_fmt - *p);
- }
-
- /* if none match, provide the one that matches quality closest */
- dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc :
- enc->sample_fmt - min_dec;
- }
-}
-
static void choose_sample_rate(AVStream *st, AVCodec *codec)
{
if(codec && codec->supported_samplerates){
@@ -671,10 +704,10 @@ static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx, AVCode
static int read_ffserver_streams(AVFormatContext *s, const char *filename)
{
int i, err;
- AVFormatContext *ic = NULL;
+ AVFormatContext *ic;
int nopts = 0;
- err = avformat_open_input(&ic, filename, NULL, NULL);
+ err = av_open_input_file(&ic, filename, NULL, FFM_PACKET_SIZE, NULL);
if (err < 0)
return err;
/* copy stream format */
@@ -689,7 +722,8 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
// FIXME: a more elegant solution is needed
memcpy(st, ic->streams[i], sizeof(AVStream));
- st->info = NULL;
+ st->info = av_malloc(sizeof(*st->info));
+ memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
avcodec_copy_context(st->codec, ic->streams[i]->codec);
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -793,7 +827,7 @@ need_realloc:
ffmpeg_exit(1);
}
- if (enc->channels != dec->channels || enc->sample_rate != dec->sample_rate)
+ if (enc->channels != dec->channels)
ost->audio_resample = 1;
resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||
@@ -819,7 +853,7 @@ need_realloc:
ost->resample_sample_rate == enc->sample_rate) {
ost->resample = NULL;
ost->audio_resample = 0;
- } else if (ost->audio_resample) {
+ } else {
if (dec->sample_fmt != AV_SAMPLE_FMT_S16)
fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n");
ost->resample = av_audio_resample_init(enc->channels, dec->channels,
@@ -1111,7 +1145,7 @@ static void do_video_out(AVFormatContext *s,
AVFrame *in_picture,
int *frame_size, float quality)
{
- int nb_frames, i, ret, resample_changed;
+ int nb_frames, i, ret, av_unused resample_changed;
AVFrame *final_picture, *formatted_picture;
AVCodecContext *enc, *dec;
double sync_ipts;
@@ -1158,6 +1192,7 @@ static void do_video_out(AVFormatContext *s,
formatted_picture = in_picture;
final_picture = formatted_picture;
+#if !CONFIG_AVFILTER
resample_changed = ost->resample_width != dec->width ||
ost->resample_height != dec->height ||
ost->resample_pix_fmt != dec->pix_fmt;
@@ -1168,24 +1203,32 @@ static void do_video_out(AVFormatContext *s,
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));
- if(!ost->video_resample)
- ffmpeg_exit(1);
+ ost->resample_width = dec->width;
+ ost->resample_height = dec->height;
+ ost->resample_pix_fmt = dec->pix_fmt;
}
-#if !CONFIG_AVFILTER
+ ost->video_resample = dec->width != enc->width ||
+ dec->height != enc->height ||
+ dec->pix_fmt != enc->pix_fmt;
+
if (ost->video_resample) {
- final_picture = &ost->pict_tmp;
- if (resample_changed) {
+ final_picture = &ost->resample_frame;
+ if (!ost->img_resample_ctx || resample_changed) {
+ /* initialize the destination picture */
+ if (!ost->resample_frame.data[0]) {
+ avcodec_get_frame_defaults(&ost->resample_frame);
+ if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt,
+ enc->width, enc->height)) {
+ fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
+ ffmpeg_exit(1);
+ }
+ }
/* initialize a new scaler context */
sws_freeContext(ost->img_resample_ctx);
- ost->img_resample_ctx = sws_getContext(
- ist->st->codec->width,
- ist->st->codec->height,
- ist->st->codec->pix_fmt,
- ost->st->codec->width,
- ost->st->codec->height,
- ost->st->codec->pix_fmt,
- ost->sws_flags, NULL, NULL, NULL);
+ ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,
+ enc->width, enc->height, enc->pix_fmt,
+ ost->sws_flags, NULL, NULL, NULL);
if (ost->img_resample_ctx == NULL) {
fprintf(stderr, "Cannot get resampling context\n");
ffmpeg_exit(1);
@@ -1329,7 +1372,8 @@ static void print_report(AVFormatContext **output_files,
int64_t total_size;
AVCodecContext *enc;
int frame_number, vid, i;
- double bitrate, ti1, pts;
+ double bitrate;
+ int64_t pts = INT64_MAX;
static int64_t last_time = -1;
static int qp_histogram[52];
@@ -1354,7 +1398,6 @@ static void print_report(AVFormatContext **output_files,
total_size= avio_tell(oc->pb);
buf[0] = '\0';
- ti1 = 1e10;
vid = 0;
for(i=0;i<nb_ostreams;i++) {
float q = -1;
@@ -1405,19 +1448,28 @@ static void print_report(AVFormatContext **output_files,
vid = 1;
}
/* compute min output value */
- pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
- if ((pts < ti1) && (pts > 0))
- ti1 = pts;
+ pts = FFMIN(pts, av_rescale_q(ost->st->pts.val,
+ ost->st->time_base, AV_TIME_BASE_Q));
}
- if (ti1 < 0.01)
- ti1 = 0.01;
if (verbose > 0 || is_last_report) {
- bitrate = (double)(total_size * 8) / ti1 / 1000.0;
+ int hours, mins, secs, us;
+ secs = pts / AV_TIME_BASE;
+ us = pts % AV_TIME_BASE;
+ mins = secs / 60;
+ secs %= 60;
+ hours = mins / 60;
+ mins %= 60;
+ bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0;
+
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ "size=%8.0fkB time=", total_size / 1024.0);
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ "%02d:%02d:%02d.%02d ", hours, mins, secs,
+ (100 * us) / AV_TIME_BASE);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
- (double)total_size / 1024, ti1, bitrate);
+ "bitrate=%6.1fkbits/s", bitrate);
if (nb_frames_dup || nb_frames_drop)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
@@ -1554,7 +1606,7 @@ static int output_packet(InputStream *ist, int ist_index,
/* no picture yet */
goto discard_packet;
}
- ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
+ ist->next_pts = ist->pts = picture.best_effort_timestamp;
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 *
@@ -1599,19 +1651,16 @@ static int output_packet(InputStream *ist, int ist_index,
}
#if CONFIG_AVFILTER
- if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- for (i = 0; i < nb_ostreams; i++) {
+ if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (start_time == 0 || ist->pts >= start_time) {
+ for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->input_video_filter && ost->source_index == ist_index) {
- AVRational sar;
- if (ist->st->sample_aspect_ratio.num)
- sar = ist->st->sample_aspect_ratio;
- else
- sar = ist->st->codec->sample_aspect_ratio;
- // add it to be filtered
- av_vsrc_buffer_add_frame(ost->input_video_filter, &picture,
- ist->pts,
- sar);
+ if (!picture.sample_aspect_ratio.num)
+ picture.sample_aspect_ratio = ist->st->sample_aspect_ratio;
+ picture.pts = ist->pts;
+
+ av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE);
}
}
}
@@ -1650,11 +1699,15 @@ static int output_packet(InputStream *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)
- get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb);
- if (ost->picref)
- ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
+ 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) {
+ 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];
@@ -1670,7 +1723,7 @@ static int output_packet(InputStream *ist, int ist_index,
case AVMEDIA_TYPE_VIDEO:
#if CONFIG_AVFILTER
if (ost->picref->video && !ost->frame_aspect_ratio)
- ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect;
+ ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
#endif
do_video_out(os, ost, ist, &picture, &frame_size,
same_quality ? quality : ost->st->codec->global_quality);
@@ -1686,6 +1739,7 @@ static int output_packet(InputStream *ist, int ist_index,
}
} else {
AVFrame avframe; //FIXME/XXX remove this
+ AVPicture pict;
AVPacket opkt;
int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
@@ -1739,6 +1793,13 @@ static int output_packet(InputStream *ist, int ist_index,
opkt.size = data_size;
}
+ if (os->oformat->flags & AVFMT_RAWPICTURE) {
+ /* store AVPicture in AVPacket, as expected by the output format */
+ avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
+ opkt.data = (uint8_t *)&pict;
+ opkt.size = sizeof(AVPicture);
+ opkt.flags |= AV_PKT_FLAG_KEY;
+ }
write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
ost->st->codec->frame_number++;
ost->frame_number++;
@@ -1748,8 +1809,7 @@ static int output_packet(InputStream *ist, int ist_index,
cont:
frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
- if (ost->picref)
- avfilter_unref_buffer(ost->picref);
+ avfilter_unref_buffer(ost->picref);
}
#endif
}
@@ -1932,15 +1992,19 @@ static int transcode(AVFormatContext **output_files,
int nb_input_files,
StreamMap *stream_maps, int nb_stream_maps)
{
- int ret = 0, i, j, k, n, nb_ostreams = 0;
+ int ret = 0, i, j, k, n, nb_ostreams = 0, step;
+
AVFormatContext *is, *os;
AVCodecContext *codec, *icodec;
OutputStream *ost, **ost_table = NULL;
InputStream *ist;
char error[1024];
+ int key;
int want_sdp = 1;
uint8_t no_packet[MAX_FILES]={0};
int no_packet_count=0;
+ int nb_frame_threshold[AVMEDIA_TYPE_NB]={0};
+ int nb_streams[AVMEDIA_TYPE_NB]={0};
if (rate_emu)
for (i = 0; i < nb_input_streams; i++)
@@ -1988,6 +2052,43 @@ static int transcode(AVFormatContext **output_files,
ost_table = av_mallocz(sizeof(OutputStream *) * nb_ostreams);
if (!ost_table)
goto fail;
+
+ for(k=0;k<nb_output_files;k++) {
+ os = output_files[k];
+ for(i=0;i<os->nb_streams;i++,n++) {
+ nb_streams[os->streams[i]->codec->codec_type]++;
+ }
+ }
+ for(step=1<<30; step; step>>=1){
+ int found_streams[AVMEDIA_TYPE_NB]={0};
+ for(j=0; j<AVMEDIA_TYPE_NB; j++)
+ nb_frame_threshold[j] += step;
+
+ for(j=0; j<nb_input_streams; j++) {
+ int skip=0;
+ ist = &input_streams[j];
+ if(opt_programid){
+ int pi,si;
+ AVFormatContext *f= input_files[ ist->file_index ].ctx;
+ skip=1;
+ for(pi=0; pi<f->nb_programs; pi++){
+ AVProgram *p= f->programs[pi];
+ if(p->id == opt_programid)
+ for(si=0; si<p->nb_stream_indexes; si++){
+ if(f->streams[ p->stream_index[si] ] == ist->st)
+ skip=0;
+ }
+ }
+ }
+ if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip
+ && nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames){
+ found_streams[ist->st->codec->codec_type]++;
+ }
+ }
+ for(j=0; j<AVMEDIA_TYPE_NB; j++)
+ if(found_streams[j] < nb_streams[j])
+ nb_frame_threshold[j] -= step;
+ }
n = 0;
for(k=0;k<nb_output_files;k++) {
os = output_files[k];
@@ -2009,7 +2110,6 @@ static int transcode(AVFormatContext **output_files,
}
} else {
- int best_nb_frames=-1;
/* get corresponding input stream index : we select the first one with the right type */
found = 0;
for (j = 0; j < nb_input_streams; j++) {
@@ -2029,12 +2129,11 @@ static int transcode(AVFormatContext **output_files,
}
}
if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip &&
- ist->st->codec->codec_type == ost->st->codec->codec_type) {
- if(best_nb_frames < ist->st->codec_info_nb_frames){
- best_nb_frames= ist->st->codec_info_nb_frames;
+ ist->st->codec->codec_type == ost->st->codec->codec_type &&
+ nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames) {
ost->source_index = j;
found = 1;
- }
+ break;
}
}
@@ -2174,9 +2273,10 @@ static int transcode(AVFormatContext **output_files,
if (codec->sample_fmt == AV_SAMPLE_FMT_NONE)
codec->sample_fmt = icodec->sample_fmt;
choose_sample_fmt(ost->st, ost->enc);
- if (!codec->channels)
+ if (!codec->channels) {
codec->channels = icodec->channels;
- codec->channel_layout = icodec->channel_layout;
+ codec->channel_layout = icodec->channel_layout;
+ }
if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
codec->channel_layout = 0;
ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
@@ -2200,27 +2300,7 @@ static int transcode(AVFormatContext **output_files,
codec->height != icodec->height ||
codec->pix_fmt != icodec->pix_fmt;
if (ost->video_resample) {
-#if !CONFIG_AVFILTER
- avcodec_get_frame_defaults(&ost->pict_tmp);
- if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
- codec->width, codec->height)) {
- fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
- ffmpeg_exit(1);
- }
- ost->img_resample_ctx = sws_getContext(
- icodec->width,
- icodec->height,
- icodec->pix_fmt,
- codec->width,
- codec->height,
- codec->pix_fmt,
- ost->sws_flags, NULL, NULL, NULL);
- if (ost->img_resample_ctx == NULL) {
- fprintf(stderr, "Cannot get resampling context\n");
- ffmpeg_exit(1);
- }
-#endif
- codec->bits_per_raw_sample= 0;
+ codec->bits_per_raw_sample= frame_bits_per_raw_sample;
}
if (!codec->width || !codec->height) {
codec->width = icodec->width;
@@ -2239,6 +2319,11 @@ static int transcode(AVFormatContext **output_files,
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)) {
@@ -2256,7 +2341,7 @@ static int transcode(AVFormatContext **output_files,
break;
}
/* two pass mode */
- if (ost->encoding_needed &&
+ if (ost->encoding_needed && codec->codec_id != CODEC_ID_H264 &&
(codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
char logfilename[1024];
FILE *f;
@@ -2283,8 +2368,9 @@ static int transcode(AVFormatContext **output_files,
}
}
if(codec->codec_type == AVMEDIA_TYPE_VIDEO){
+ /* maximum video buffer size is 6-bytes per pixel, plus DPX header size */
int size= codec->width * codec->height;
- bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200);
+ bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 1664);
}
}
@@ -2341,17 +2427,6 @@ static int transcode(AVFormatContext **output_files,
ret = AVERROR(EINVAL);
goto dump_format;
}
-
- /* update requested sample format for the decoder based on the
- corresponding encoder sample format */
- for (j = 0; j < nb_ostreams; j++) {
- ost = ost_table[j];
- if (ost->source_index == i) {
- update_sample_fmt(ist->st->codec, codec, ost->st->codec);
- break;
- }
- }
-
if (avcodec_open(ist->st->codec, codec) < 0) {
snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d",
ist->file_index, ist->st->index);
@@ -2370,7 +2445,6 @@ static int transcode(AVFormatContext **output_files,
st= ist->st;
ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0;
ist->next_pts = AV_NOPTS_VALUE;
- init_pts_correction(&ist->pts_ctx);
ist->is_start = 1;
}
@@ -2466,12 +2540,11 @@ static int transcode(AVFormatContext **output_files,
/* open files and write file headers */
for(i=0;i<nb_output_files;i++) {
os = output_files[i];
- if (avformat_write_header(os, &output_opts[i]) < 0) {
+ if (av_write_header(os) < 0) {
snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
ret = AVERROR(EINVAL);
goto dump_format;
}
- assert_avoptions(output_opts[i]);
if (strcmp(output_files[i]->oformat->name, "rtp")) {
want_sdp = 0;
}
@@ -2511,8 +2584,11 @@ static int transcode(AVFormatContext **output_files,
print_sdp(output_files, nb_output_files);
}
- if (verbose >= 0)
- fprintf(stderr, "Press ctrl-c to stop encoding\n");
+ if (!using_stdin) {
+ if(verbose >= 0)
+ fprintf(stderr, "Press [q] to stop, [?] for help\n");
+ avio_set_interrupt_cb(decode_interrupt_cb);
+ }
term_init();
timer_start = av_gettime();
@@ -2526,6 +2602,57 @@ static int transcode(AVFormatContext **output_files,
redo:
ipts_min= 1e100;
opts_min= 1e100;
+ /* if 'q' pressed, exits */
+ if (!using_stdin) {
+ if (q_pressed)
+ break;
+ /* read_key() returns 0 on EOF */
+ key = read_key();
+ if (key == 'q')
+ break;
+ if (key == '+') verbose++;
+ if (key == '-') verbose--;
+ if (key == 's') qp_hist ^= 1;
+ if (key == 'h'){
+ if (do_hex_dump){
+ do_hex_dump = do_pkt_dump = 0;
+ } else if(do_pkt_dump){
+ do_hex_dump = 1;
+ } else
+ do_pkt_dump = 1;
+ av_log_set_level(AV_LOG_DEBUG);
+ }
+ if (key == 'd' || key == 'D'){
+ int debug=0;
+ if(key == 'D') {
+ debug = input_streams[0].st->codec->debug<<1;
+ if(!debug) debug = 1;
+ while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
+ debug += debug;
+ }else
+ scanf("%d", &debug);
+ for(i=0;i<nb_input_streams;i++) {
+ input_streams[i].st->codec->debug = debug;
+ }
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ ost->st->codec->debug = debug;
+ }
+ if(debug) av_log_set_level(AV_LOG_DEBUG);
+ fprintf(stderr,"debug=%d\n", debug);
+ }
+ if (key == '?'){
+ fprintf(stderr, "key function\n"
+ "? show this help\n"
+ "+ increase verbosity\n"
+ "- decrease verbosity\n"
+ "D cycle through available debug modes\n"
+ "h dump packets/hex press to cycle through the 3 states\n"
+ "q quit\n"
+ "s Show QP histogram\n"
+ );
+ }
+ }
/* select the stream that we must read now by looking at the
smallest output pts */
@@ -2631,7 +2758,11 @@ static int transcode(AVFormatContext **output_files,
/* finish if recording time exhausted */
if (recording_time != INT64_MAX &&
- av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) >= 0) {
+ (pkt.pts != AV_NOPTS_VALUE ?
+ av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000})
+ :
+ av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000})
+ )>= 0) {
ist->is_past_recording_time = 1;
goto discard_packet;
}
@@ -2713,7 +2844,7 @@ static int transcode(AVFormatContext **output_files,
av_fifo_free(ost->fifo); /* works even if fifo is not
initialized but set to zero */
av_freep(&ost->st->codec->subtitle_header);
- av_free(ost->pict_tmp.data[0]);
+ av_free(ost->resample_frame.data[0]);
av_free(ost->forced_kf_pts);
if (ost->video_resample)
sws_freeContext(ost->img_resample_ctx);
@@ -2803,7 +2934,7 @@ static int opt_frame_pix_fmt(const char *opt, const char *arg)
return AVERROR(EINVAL);
}
} else {
- show_pix_fmts();
+ opt_pix_fmts(NULL, NULL);
ffmpeg_exit(0);
}
return 0;
@@ -2852,7 +2983,7 @@ static int opt_metadata(const char *opt, const char *arg)
static int opt_qscale(const char *opt, const char *arg)
{
video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
- if (video_qscale == 0) {
+ if (video_qscale <= 0 || video_qscale > 255) {
fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
return AVERROR(EINVAL);
}
@@ -2862,6 +2993,7 @@ static int opt_qscale(const char *opt, const char *arg)
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);
+ opt_default(opt, arg);
return 0;
}
@@ -2907,21 +3039,25 @@ static int opt_audio_channels(const char *opt, const char *arg)
static int opt_video_channel(const char *opt, const char *arg)
{
- av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
- opt_default("channel", arg);
+ video_channel = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
return 0;
}
static int opt_video_standard(const char *opt, const char *arg)
{
- av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
- opt_default("standard", arg);
+ video_standard = av_strdup(arg);
return 0;
}
-static int opt_codec(int *pstream_copy, char **pcodec_name,
- int codec_type, const char *arg)
+static int opt_codec(const char *opt, const char *arg)
{
+ 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; }
+
av_freep(pcodec_name);
if (!strcmp(arg, "copy")) {
*pstream_copy = 1;
@@ -2931,26 +3067,6 @@ static int opt_codec(int *pstream_copy, char **pcodec_name,
return 0;
}
-static int opt_audio_codec(const char *opt, const char *arg)
-{
- return opt_codec(&audio_stream_copy, &audio_codec_name, AVMEDIA_TYPE_AUDIO, arg);
-}
-
-static int opt_video_codec(const char *opt, const char *arg)
-{
- return opt_codec(&video_stream_copy, &video_codec_name, AVMEDIA_TYPE_VIDEO, arg);
-}
-
-static int opt_subtitle_codec(const char *opt, const char *arg)
-{
- return opt_codec(&subtitle_stream_copy, &subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, arg);
-}
-
-static int opt_data_codec(const char *opt, const char *arg)
-{
- return opt_codec(&data_stream_copy, &data_codec_name, AVMEDIA_TYPE_DATA, arg);
-}
-
static int opt_codec_tag(const char *opt, const char *arg)
{
char *tail;
@@ -3151,10 +3267,10 @@ static enum CodecID find_codec_or_die(const char *name, int type, int encoder, i
static int opt_input_file(const char *opt, const char *filename)
{
AVFormatContext *ic;
+ AVFormatParameters params, *ap = &params;
AVInputFormat *file_iformat = NULL;
int err, i, ret, rfps, rfps_base;
int64_t timestamp;
- uint8_t buf[128];
if (last_asked_format) {
if (!(file_iformat = av_find_input_format(last_asked_format))) {
@@ -3176,24 +3292,21 @@ static int opt_input_file(const char *opt, const char *filename)
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);
+
+ memset(ap, 0, sizeof(*ap));
+ ap->prealloced_context = 1;
+ ap->sample_rate = audio_sample_rate;
+ ap->channels = audio_channels;
+ ap->time_base.den = frame_rate.num;
+ ap->time_base.num = frame_rate.den;
+ ap->width = frame_width;
+ ap->height = frame_height;
+ ap->pix_fmt = frame_pix_fmt;
+ // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
+ ap->channel = video_channel;
+ ap->standard = video_standard;
+
+ set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
ic->video_codec_id =
find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0,
@@ -3204,16 +3317,20 @@ static int opt_input_file(const char *opt, const char *filename)
ic->subtitle_codec_id=
find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0,
avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
- ic->flags |= AVFMT_FLAG_NONBLOCK;
+ ic->flags |= AVFMT_FLAG_NONBLOCK | AVFMT_FLAG_PRIV_OPT;
/* open the input file with generic libav function */
- err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
+ err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
+ if(err >= 0){
+ set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
+ err = av_demuxer_open(ic, ap);
+ if(err < 0)
+ avformat_free_context(ic);
+ }
if (err < 0) {
print_error(filename, err);
ffmpeg_exit(1);
}
- assert_avoptions(format_opts);
-
if(opt_programid) {
int i, j;
int found=0;
@@ -3243,23 +3360,6 @@ static int opt_input_file(const char *opt, const char *filename)
ic->loop_input = loop_input;
}
- /* Set AVCodecContext options so they will be seen by av_find_stream_info() */
- for (i = 0; i < ic->nb_streams; i++) {
- AVCodecContext *dec = ic->streams[i]->codec;
- switch (dec->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO],
- AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM,
- NULL);
- break;
- case AVMEDIA_TYPE_VIDEO:
- set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO],
- AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM,
- NULL);
- break;
- }
- }
-
/* If not enough info to get the stream parameters, we decode the
first frames to get it. (used in mpeg case for example) */
ret = av_find_stream_info(ic);
@@ -3305,12 +3405,16 @@ static int opt_input_file(const char *opt, const char *filename)
switch (dec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ist->dec = avcodec_find_decoder_by_name(audio_codec_name);
+ if(!ist->dec)
+ ist->dec = avcodec_find_decoder(dec->codec_id);
set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, ist->dec);
if(audio_disable)
st->discard= AVDISCARD_ALL;
break;
case AVMEDIA_TYPE_VIDEO:
- ist->dec = avcodec_find_decoder_by_name(video_codec_name);
+ ist->dec= avcodec_find_decoder_by_name(video_codec_name);
+ if(!ist->dec)
+ ist->dec = 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, ist->dec);
rfps = ic->streams[i]->r_frame_rate.num;
rfps_base = ic->streams[i]->r_frame_rate.den;
@@ -3340,6 +3444,8 @@ static int opt_input_file(const char *opt, const char *filename)
break;
case AVMEDIA_TYPE_SUBTITLE:
ist->dec = avcodec_find_decoder_by_name(subtitle_codec_name);
+ if(!ist->dec)
+ ist->dec = avcodec_find_decoder(dec->codec_id);
if(subtitle_disable)
st->discard = AVDISCARD_ALL;
break;
@@ -3360,6 +3466,8 @@ static int opt_input_file(const char *opt, const char *filename)
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);
+ top_field_first = -1;
+ video_channel = 0;
frame_rate = (AVRational){0, 0};
frame_pix_fmt = PIX_FMT_NONE;
frame_height = 0;
@@ -3446,7 +3554,7 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
ost->frame_aspect_ratio = frame_aspect_ratio;
frame_aspect_ratio = 0;
#if CONFIG_AVFILTER
- ost->avfilter= vfilters;
+ ost->avfilter = vfilters;
vfilters = NULL;
#endif
}
@@ -3483,6 +3591,7 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
video_enc->width = frame_width;
video_enc->height = frame_height;
video_enc->pix_fmt = frame_pix_fmt;
+ video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
if (intra_only)
@@ -3742,40 +3851,29 @@ static int opt_streamid(const char *opt, const char *arg)
return 0;
}
-static void opt_output_file(const char *filename)
+static int opt_output_file(const char *opt, const char *filename)
{
AVFormatContext *oc;
int err, use_video, use_audio, use_subtitle, use_data;
int input_has_video, input_has_audio, input_has_subtitle, input_has_data;
+ AVFormatParameters params, *ap = &params;
AVOutputFormat *file_oformat;
+ if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){
+ fprintf(stderr, "Too many output files\n");
+ ffmpeg_exit(1);
+ }
+
if (!strcmp(filename, "-"))
filename = "pipe:";
- oc = avformat_alloc_context();
+ err = avformat_alloc_output_context2(&oc, NULL, last_asked_format, filename);
+ last_asked_format = NULL;
if (!oc) {
- print_error(filename, AVERROR(ENOMEM));
+ print_error(filename, err);
ffmpeg_exit(1);
}
-
- if (last_asked_format) {
- file_oformat = av_guess_format(last_asked_format, NULL, NULL);
- if (!file_oformat) {
- fprintf(stderr, "Requested output format '%s' is not a suitable output format\n", last_asked_format);
- ffmpeg_exit(1);
- }
- last_asked_format = NULL;
- } else {
- file_oformat = av_guess_format(NULL, filename, NULL);
- if (!file_oformat) {
- fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
- filename);
- ffmpeg_exit(1);
- }
- }
-
- oc->oformat = file_oformat;
- av_strlcpy(oc->filename, filename, sizeof(oc->filename));
+ file_oformat= oc->oformat;
if (!strcmp(file_oformat->name, "ffm") &&
av_strstart(filename, "http:", NULL)) {
@@ -3822,7 +3920,6 @@ static void opt_output_file(const char *filename)
av_dict_free(&metadata);
}
- av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
output_files[nb_output_files++] = oc;
/* check filename in case of an image number is expected */
@@ -3862,8 +3959,17 @@ static void opt_output_file(const char *filename)
}
}
+ memset(ap, 0, sizeof(*ap));
+ if (av_set_parameters(oc, ap) < 0) {
+ fprintf(stderr, "%s: Invalid encoding parameters\n",
+ oc->filename);
+ ffmpeg_exit(1);
+ }
+
oc->preload= (int)(mux_preload*AV_TIME_BASE);
oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
+
+ set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
if (loop_output >= 0) {
av_log(NULL, AV_LOG_WARNING, "-loop_output is deprecated, use -loop\n");
oc->loop_output = loop_output;
@@ -3880,6 +3986,7 @@ static void opt_output_file(const char *filename)
av_freep(&forced_key_frames);
uninit_opts();
init_opts();
+ return 0;
}
/* same option as mencoder */
@@ -3942,16 +4049,18 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
}
}
-static void opt_inter_matrix(const char *arg)
+static int opt_inter_matrix(const char *opt, const char *arg)
{
inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
parse_matrix_coeffs(inter_matrix, arg);
+ return 0;
}
-static void opt_intra_matrix(const char *arg)
+static int opt_intra_matrix(const char *opt, const char *arg)
{
intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
parse_matrix_coeffs(intra_matrix, arg);
+ return 0;
}
static void show_usage(void)
@@ -3961,11 +4070,10 @@ static void show_usage(void)
printf("\n");
}
-static void show_help(void)
+static int opt_help(const char *opt, const char *arg)
{
AVCodec *c;
AVOutputFormat *oformat = NULL;
- AVInputFormat *iformat = NULL;
av_log_set_callback(log_callback_help);
show_usage();
@@ -4016,15 +4124,8 @@ static void show_help(void)
}
}
- /* individual demuxer options */
- while ((iformat = av_iformat_next(iformat))) {
- if (iformat->priv_class) {
- av_opt_show2(&iformat->priv_class, NULL, AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
- }
- }
-
av_opt_show2(sws_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
+ return 0;
}
static int opt_target(const char *opt, const char *arg)
@@ -4084,8 +4185,8 @@ static int opt_target(const char *opt, const char *arg)
}
if(!strcmp(arg, "vcd")) {
- opt_video_codec("vcodec", "mpeg1video");
- opt_audio_codec("vcodec", "mp2");
+ opt_codec("vcodec", "mpeg1video");
+ opt_codec("acodec", "mp2");
opt_format("f", "vcd");
opt_frame_size("s", norm == PAL ? "352x288" : "352x240");
@@ -4112,12 +4213,13 @@ static int opt_target(const char *opt, const char *arg)
mux_preload= (36000+3*1200) / 90000.0; //0.44
} else if(!strcmp(arg, "svcd")) {
- opt_video_codec("vcodec", "mpeg2video");
- opt_audio_codec("acodec", "mp2");
+ opt_codec("vcodec", "mpeg2video");
+ opt_codec("acodec", "mp2");
opt_format("f", "svcd");
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");
@@ -4134,12 +4236,13 @@ static int opt_target(const char *opt, const char *arg)
} else if(!strcmp(arg, "dvd")) {
- opt_video_codec("vcodec", "mpeg2video");
- opt_audio_codec("vcodec", "ac3");
+ opt_codec("vcodec", "mpeg2video");
+ opt_codec("acodec", "ac3");
opt_format("f", "dvd");
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");
@@ -4233,14 +4336,11 @@ static int opt_preset(const char *opt, const char *arg)
fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
ffmpeg_exit(1);
}
- if(!strcmp(tmp, "acodec")){
- opt_audio_codec(tmp, tmp2);
- }else if(!strcmp(tmp, "vcodec")){
- opt_video_codec(tmp, tmp2);
- }else if(!strcmp(tmp, "scodec")){
- opt_subtitle_codec(tmp, tmp2);
- }else if(!strcmp(tmp, "dcodec")){
- opt_data_codec(tmp, tmp2);
+ if (!strcmp(tmp, "acodec") ||
+ !strcmp(tmp, "vcodec") ||
+ !strcmp(tmp, "scodec") ||
+ !strcmp(tmp, "dcodec")) {
+ opt_codec(tmp, tmp2);
}else if(opt_default(tmp, tmp2) < 0){
fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
ffmpeg_exit(1);
@@ -4252,6 +4352,17 @@ static int opt_preset(const char *opt, const char *arg)
return 0;
}
+static void log_callback_null(void* ptr, int level, const char* fmt, va_list vl)
+{
+}
+
+static int opt_passlogfile(const char *opt, const char *arg)
+{
+ pass_logfilename_prefix = arg;
+ opt_default("passlogfile", arg);
+ return 0;
+}
+
static const OptionDef options[] = {
/* main options */
#include "cmdutils_common_opts.h"
@@ -4304,7 +4415,8 @@ static const OptionDef options[] = {
{ "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
{ "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
{ "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format, 'list' as argument shows all the pixel formats supported", "format" },
- { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
+ { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&frame_bits_per_raw_sample}, "set the number of bits per raw sample", "number" },
+ { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
{ "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
{ "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
{ "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
@@ -4318,12 +4430,12 @@ static const OptionDef options[] = {
{ "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
{ "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" },
{ "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
- { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
+ { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_codec}, "force video codec ('copy' to copy stream)", "codec" },
{ "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "threshold" },
{ "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality},
"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_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
+ { "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" },
{ "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
@@ -4351,7 +4463,7 @@ static const OptionDef options[] = {
{ "ar", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" },
{ "ac", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_channels}, "set number of audio channels", "channels" },
{ "an", OPT_BOOL | OPT_AUDIO, {(void*)&audio_disable}, "disable audio" },
- { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
+ { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_codec}, "force audio codec ('copy' to copy stream)", "codec" },
{ "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_codec_tag}, "force audio tag/fourcc", "fourcc/tag" },
{ "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
{ "newaudio", OPT_AUDIO, {(void*)opt_new_stream}, "add a new audio stream to the current output stream" },
@@ -4360,14 +4472,14 @@ static const OptionDef options[] = {
/* subtitle options */
{ "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" },
- { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
+ { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
{ "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_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_codec_tag}, "force subtitle tag/fourcc", "fourcc/tag" },
/* grab options */
- { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "deprecated, use -channel", "channel" },
- { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "deprecated, use -standard", "standard" },
+ { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" },
+ { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" },
{ "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" },
/* muxer options */
@@ -4383,7 +4495,7 @@ static const OptionDef options[] = {
{ "spre", HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_preset}, "set the subtitle options to the indicated preset", "preset" },
{ "fpre", HAS_ARG | OPT_EXPERT, {(void*)opt_preset}, "set options from indicated preset file", "filename" },
/* data codec support */
- { "dcodec", HAS_ARG | OPT_DATA, {(void*)opt_data_codec}, "force data codec ('copy' to copy stream)", "codec" },
+ { "dcodec", HAS_ARG | OPT_DATA, {(void*)opt_codec}, "force data codec ('copy' to copy stream)", "codec" },
{ "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
{ NULL, },
@@ -4395,6 +4507,14 @@ int main(int argc, char **argv)
av_log_set_flags(AV_LOG_SKIP_REPEATED);
+ if(argc>1 && !strcmp(argv[1], "-d")){
+ run_as_daemon=1;
+ verbose=-1;
+ av_log_set_callback(log_callback_null);
+ argc--;
+ argv++;
+ }
+
avcodec_register_all();
#if CONFIG_AVDEVICE
avdevice_register_all();
@@ -4404,11 +4524,15 @@ int main(int argc, char **argv)
#endif
av_register_all();
- avio_set_interrupt_cb(decode_interrupt_cb);
+#if HAVE_ISATTY
+ if(isatty(STDIN_FILENO))
+ avio_set_interrupt_cb(decode_interrupt_cb);
+#endif
init_opts();
- show_banner();
+ if(verbose>=0)
+ show_banner();
/* parse options */
parse_options(argc, argv, options, opt_output_file);