summaryrefslogtreecommitdiff
path: root/ffmpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg.c')
-rw-r--r--ffmpeg.c439
1 files changed, 286 insertions, 153 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index d3a85dde89..5481ac2539 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
*/
@@ -47,6 +47,8 @@
#include "libavutil/libm.h"
#include "libavformat/os_support.h"
+#include "libavformat/ffm.h" // not public API
+
#if CONFIG_AVFILTER
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
@@ -69,7 +71,12 @@
#include <sys/select.h>
#endif
-#if HAVE_KBHIT
+#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>
@@ -108,8 +115,6 @@ static const OptionDef options[];
#define MAX_FILES 100
#define MAX_STREAMS 1024 /* arbitrary sanity check value */
-#define FFM_PACKET_SIZE 4096 //XXX a duplicate of the line in ffm.h
-
static const char *last_asked_format = NULL;
static AVFormatContext *input_files[MAX_FILES];
static int64_t input_files_ts_offset[MAX_FILES];
@@ -145,6 +150,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;
@@ -167,7 +173,8 @@ static int loop_output = AVFMT_NOOUTPUTLOOP;
static int qp_hist = 0;
#if CONFIG_AVFILTER
static char *vfilters = NULL;
-static AVFilterGraph *graph = NULL;
+#else
+static unsigned int sws_flags = SWS_BICUBIC;
#endif
static int intra_only = 0;
@@ -200,7 +207,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;
@@ -226,6 +233,7 @@ 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;
@@ -240,8 +248,6 @@ static char *forced_key_frames = NULL;
static float dts_delta_threshold = 10;
-static unsigned int sws_flags = SWS_BICUBIC;
-
static int64_t timer_start;
static uint8_t *audio_buf;
@@ -279,9 +285,7 @@ typedef struct AVOutputStream {
int resample_width;
int resample_pix_fmt;
- /* full frame size of first frame */
- int original_height;
- int original_width;
+ float frame_aspect_ratio;
/* forced key frames */
int64_t *forced_kf_pts;
@@ -298,6 +302,14 @@ typedef struct AVOutputStream {
AVAudioConvert *reformat_ctx;
AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */
FILE *logfile;
+
+#if CONFIG_AVFILTER
+ AVFilterContext *output_video_filter;
+ AVFilterContext *input_video_filter;
+ AVFilterBufferRef *picref;
+ char *avfilter;
+ AVFilterGraph *graph;
+#endif
} AVOutputStream;
static AVOutputStream **output_streams_for_file[MAX_FILES] = { NULL };
@@ -315,16 +327,12 @@ typedef struct AVInputStream {
int64_t next_pts; /* synthetic pts for cases where pkt.pts
is not defined */
int64_t pts; /* current pts */
- PtsCorrectionContext pts_ctx;
int is_start; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning;
int is_past_recording_time;
#if CONFIG_AVFILTER
- AVFilterContext *output_video_filter;
- AVFilterContext *input_video_filter;
AVFrame *filter_frame;
int has_filter_frame;
- AVFilterBufferRef *picref;
#endif
} AVInputStream;
@@ -335,9 +343,15 @@ typedef struct AVInputFile {
int nb_streams; /* nb streams we are aware of */
} AVInputFile;
+#if HAVE_TERMIOS_H
+
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+#endif
+
#if CONFIG_AVFILTER
-static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
+static int configure_video_filters(AVInputStream *ist, AVOutputStream *ost)
{
AVFilterContext *last_filter, *filter;
/** filter graph containing all filters including input & output */
@@ -348,7 +362,7 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
char args[255];
int ret;
- graph = avfilter_graph_alloc();
+ ost->graph = avfilter_graph_alloc();
if (ist->st->sample_aspect_ratio.num){
sample_aspect_ratio = ist->st->sample_aspect_ratio;
@@ -359,15 +373,15 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
sample_aspect_ratio.num, sample_aspect_ratio.den);
- ret = avfilter_graph_create_filter(&ist->input_video_filter, avfilter_get_by_name("buffer"),
- "src", args, NULL, graph);
+ ret = avfilter_graph_create_filter(&ost->input_video_filter, avfilter_get_by_name("buffer"),
+ "src", args, NULL, ost->graph);
if (ret < 0)
return ret;
- ret = avfilter_graph_create_filter(&ist->output_video_filter, &ffsink,
- "out", NULL, &ffsink_ctx, graph);
+ ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink,
+ "out", NULL, &ffsink_ctx, ost->graph);
if (ret < 0)
return ret;
- last_filter = ist->input_video_filter;
+ last_filter = ost->input_video_filter;
if (codec->width != icodec->width || codec->height != icodec->height) {
snprintf(args, 255, "%d:%d:flags=0x%X",
@@ -375,7 +389,7 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
codec->height,
(int)av_get_int(sws_opts, "sws_flags", NULL));
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
- NULL, args, NULL, graph)) < 0)
+ NULL, args, NULL, ost->graph)) < 0)
return ret;
if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
return ret;
@@ -383,9 +397,9 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
}
snprintf(args, sizeof(args), "flags=0x%X", (int)av_get_int(sws_opts, "sws_flags", NULL));
- graph->scale_sws_opts = av_strdup(args);
+ ost->graph->scale_sws_opts = av_strdup(args);
- if (vfilters) {
+ if (ost->avfilter) {
AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
@@ -395,25 +409,27 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
outputs->next = NULL;
inputs->name = av_strdup("out");
- inputs->filter_ctx = ist->output_video_filter;
+ inputs->filter_ctx = ost->output_video_filter;
inputs->pad_idx = 0;
inputs->next = NULL;
- if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
+ if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, inputs, outputs, NULL)) < 0)
return ret;
- av_freep(&vfilters);
+ av_freep(&ost->avfilter);
} else {
- if ((ret = avfilter_link(last_filter, 0, ist->output_video_filter, 0)) < 0)
+ if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0)
return ret;
}
- if ((ret = avfilter_graph_config(graph, NULL)) < 0)
+ if ((ret = avfilter_graph_config(ost->graph, NULL)) < 0)
return ret;
- codec->width = ist->output_video_filter->inputs[0]->w;
- codec->height = ist->output_video_filter->inputs[0]->h;
+ codec->width = ost->output_video_filter->inputs[0]->w;
+ codec->height = ost->output_video_filter->inputs[0]->h;
codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
- ist->output_video_filter->inputs[0]->sample_aspect_ratio;
+ ost->frame_aspect_ratio ? // overriden by the -aspect cli option
+ av_d2q(ost->frame_aspect_ratio*codec->height/codec->width, 255) :
+ ost->output_video_filter->inputs[0]->sample_aspect_ratio;
return 0;
}
@@ -422,6 +438,10 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
static void term_exit(void)
{
av_log(NULL, AV_LOG_QUIET, "");
+#if HAVE_TERMIOS_H
+ if(!run_as_daemon)
+ tcsetattr (0, TCSANOW, &oldtty);
+#endif
}
static volatile int received_sigterm = 0;
@@ -430,11 +450,34 @@ static void
sigterm_handler(int sig)
{
received_sigterm = sig;
+ 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
@@ -445,7 +488,28 @@ static void term_init(void)
/* read a key without blocking */
static int read_key(void)
{
-#if HAVE_KBHIT
+#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
@@ -454,7 +518,8 @@ static int read_key(void)
static int decode_interrupt_cb(void)
{
- return q_pressed || (q_pressed = read_key() == 'q');
+ q_pressed += read_key() == 'q';
+ return q_pressed > 1;
}
static int ffmpeg_exit(int ret)
@@ -588,8 +653,15 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
if(*p == st->codec->pix_fmt)
break;
}
- if(*p == -1)
+ if (*p == -1) {
+ if(st->codec->pix_fmt != PIX_FMT_NONE)
+ av_log(NULL, AV_LOG_WARNING,
+ "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
+ av_pix_fmt_descriptors[st->codec->pix_fmt].name,
+ codec->name,
+ av_pix_fmt_descriptors[codec->pix_fmts[0]].name);
st->codec->pix_fmt = codec->pix_fmts[0];
+ }
}
}
@@ -1067,8 +1139,8 @@ static void do_video_out(AVFormatContext *s,
AVFrame *in_picture,
int *frame_size)
{
- int nb_frames, i, ret;
- AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src;
+ int nb_frames, i, ret, resample_changed;
+ AVFrame *final_picture, *formatted_picture, *resampling_dst;
AVCodecContext *enc, *dec;
double sync_ipts;
@@ -1113,26 +1185,26 @@ static void do_video_out(AVFormatContext *s,
formatted_picture = in_picture;
final_picture = formatted_picture;
- padding_src = formatted_picture;
resampling_dst = &ost->pict_tmp;
- if ( ost->resample_height != ist->st->codec->height
- || ost->resample_width != ist->st->codec->width
- || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) {
+ resample_changed = ost->resample_width != dec->width ||
+ ost->resample_height != dec->height ||
+ ost->resample_pix_fmt != dec->pix_fmt;
- fprintf(stderr,"Input Stream #%d.%d frame size changed to %dx%d, %s\n", ist->file_index, ist->index, ist->st->codec->width, ist->st->codec->height,avcodec_get_pix_fmt_name(ist->st->codec->pix_fmt));
+ 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",
+ ist->file_index, ist->index,
+ ost->resample_width, ost->resample_height, avcodec_get_pix_fmt_name(ost->resample_pix_fmt),
+ dec->width , dec->height , avcodec_get_pix_fmt_name(dec->pix_fmt));
if(!ost->video_resample)
ffmpeg_exit(1);
}
#if !CONFIG_AVFILTER
if (ost->video_resample) {
- padding_src = NULL;
final_picture = &ost->pict_tmp;
- if( ost->resample_height != ist->st->codec->height
- || ost->resample_width != ist->st->codec->width
- || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) {
-
+ if (resample_changed) {
/* initialize a new scaler context */
sws_freeContext(ost->img_resample_ctx);
sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
@@ -1315,26 +1387,25 @@ static void print_report(AVFormatContext **output_files,
ti1 = 1e10;
vid = 0;
for(i=0;i<nb_ostreams;i++) {
+ float q= -1;
ost = ost_table[i];
enc = ost->st->codec;
+ if(!ost->st->stream_copy && enc->coded_frame)
+ q= enc->coded_frame->quality/(float)FF_QP2LAMBDA;
if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
- !ost->st->stream_copy ?
- enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
}
if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
float t = (av_gettime()-timer_start) / 1000000.0;
frame_number = ost->frame_number;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
- frame_number, (t>1)?(int)(frame_number/t+0.5) : 0,
- !ost->st->stream_copy ?
- enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+ frame_number, (t>1)?(int)(frame_number/t+0.5) : 0, q);
if(is_last_report)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
if(qp_hist){
int j;
- int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+ int qp= lrintf(q);
if(qp>=0 && qp<FF_ARRAY_ELEMS(qp_histogram))
qp_histogram[qp]++;
for(j=0; j<32; j++)
@@ -1371,7 +1442,7 @@ static void print_report(AVFormatContext **output_files,
if (ti1 < 0.01)
ti1 = 0.01;
- if (verbose || is_last_report) {
+ if (verbose > 0 || is_last_report) {
bitrate = (double)(total_size * 8) / ti1 / 1000.0;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
@@ -1418,7 +1489,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
int ret, i;
int got_picture;
AVFrame picture;
- void *buffer_to_free;
+ void *buffer_to_free = NULL;
static unsigned int samples_size= 0;
AVSubtitle subtitle, *subtitle_to_free;
int64_t pkt_pts = AV_NOPTS_VALUE;
@@ -1511,7 +1582,7 @@ static int output_packet(AVInputStream *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 *
@@ -1519,6 +1590,8 @@ static int output_packet(AVInputStream *ist, int ist_index,
ist->st->codec->time_base.den;
}
avpkt.size = 0;
+ buffer_to_free = NULL;
+ pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free);
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(ist->st->codec,
@@ -1553,21 +1626,21 @@ static int output_packet(AVInputStream *ist, int ist_index,
avpkt.size = 0;
}
- buffer_to_free = NULL;
- if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- pre_process_video_frame(ist, (AVPicture *)&picture,
- &buffer_to_free);
- }
-
#if CONFIG_AVFILTER
- if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->input_video_filter) {
- 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(ist->input_video_filter, &picture,
- ist->pts,
- sar);
+ if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
+ 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_frame2(ost->input_video_filter, &picture,
+ ist->pts,
+ sar, ist->st->codec->width, ist->st->codec->height,
+ ist->st->codec->pix_fmt, ""); //TODO user setable params
+ }
+ }
}
#endif
@@ -1592,26 +1665,24 @@ static int output_packet(AVInputStream *ist, int ist_index,
if (pts > now)
usleep(pts - now);
}
-#if CONFIG_AVFILTER
- frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
- !ist->output_video_filter || avfilter_poll_frame(ist->output_video_filter->inputs[0]);
-#endif
/* if output time reached then transcode raw format,
encode packets and output them */
if (start_time == 0 || ist->pts >= start_time)
-#if CONFIG_AVFILTER
- while (frame_available) {
- AVRational ist_pts_tb;
- if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->output_video_filter)
- get_filtered_video_frame(ist->output_video_filter, &picture, &ist->picref, &ist_pts_tb);
- if (ist->picref)
- ist->pts = av_rescale_q(ist->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
-#endif
for(i=0;i<nb_ostreams;i++) {
int frame_size;
ost = ost_table[i];
if (ost->source_index == ist_index) {
+#if CONFIG_AVFILTER
+ 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);
+#endif
os = output_files[ost->file_index];
/* set the input output pts pairs */
@@ -1625,8 +1696,8 @@ static int output_packet(AVInputStream *ist, int ist_index,
break;
case AVMEDIA_TYPE_VIDEO:
#if CONFIG_AVFILTER
- if (ist->picref->video)
- ost->st->codec->sample_aspect_ratio = ist->picref->video->pixel_aspect;
+ if (ost->picref->video && !ost->frame_aspect_ratio)
+ ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect;
#endif
do_video_out(os, ost, ist, &picture, &frame_size);
if (vstats_filename && frame_size)
@@ -1647,7 +1718,11 @@ static int output_packet(AVInputStream *ist, int ist_index,
av_init_packet(&opkt);
if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
+#if !CONFIG_AVFILTER
continue;
+#else
+ goto cont;
+#endif
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
@@ -1695,16 +1770,17 @@ static int output_packet(AVInputStream *ist, int ist_index,
ost->frame_number++;
av_free_packet(&opkt);
}
+#if CONFIG_AVFILTER
+ 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);
+ }
+#endif
}
}
-#if CONFIG_AVFILTER
- frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
- ist->output_video_filter && avfilter_poll_frame(ist->output_video_filter->inputs[0]);
- if(ist->picref)
- avfilter_unref_buffer(ist->picref);
- }
-#endif
av_free(buffer_to_free);
/* XXX: allocate the subtitles in the codec ? */
if (subtitle_to_free) {
@@ -1884,7 +1960,7 @@ static int transcode(AVFormatContext **output_files,
int nb_input_files,
AVStreamMap *stream_maps, int nb_stream_maps)
{
- int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0;
+ int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0, step;
AVFormatContext *is, *os;
AVCodecContext *codec, *icodec;
AVOutputStream *ost, **ost_table = NULL;
@@ -1895,6 +1971,8 @@ static int transcode(AVFormatContext **output_files,
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};
file_table= av_mallocz(nb_input_files * sizeof(AVInputFile));
if (!file_table)
@@ -1979,6 +2057,43 @@ static int transcode(AVFormatContext **output_files,
ost_table = av_mallocz(sizeof(AVOutputStream *) * 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_istreams; j++) {
+ int skip=0;
+ ist = ist_table[j];
+ if(opt_programid){
+ int pi,si;
+ AVFormatContext *f= input_files[ ist->file_index ];
+ 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];
@@ -2001,7 +2116,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_istreams;j++) {
@@ -2021,12 +2135,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;
}
}
@@ -2130,6 +2243,13 @@ static int transcode(AVFormatContext **output_files,
codec->width = icodec->width;
codec->height = icodec->height;
codec->has_b_frames = icodec->has_b_frames;
+ if (!codec->sample_aspect_ratio.num) {
+ codec->sample_aspect_ratio =
+ ost->st->sample_aspect_ratio =
+ ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
+ ist->st->codec->sample_aspect_ratio.num ?
+ ist->st->codec->sample_aspect_ratio : (AVRational){0, 1};
+ }
break;
case AVMEDIA_TYPE_SUBTITLE:
codec->width = icodec->width;
@@ -2158,9 +2278,9 @@ static int transcode(AVFormatContext **output_files,
fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n");
ffmpeg_exit(1);
}
- ost->video_resample = (codec->width != icodec->width ||
- codec->height != icodec->height ||
- (codec->pix_fmt != icodec->pix_fmt));
+ ost->video_resample = codec->width != icodec->width ||
+ codec->height != icodec->height ||
+ codec->pix_fmt != icodec->pix_fmt;
if (ost->video_resample) {
#if !CONFIG_AVFILTER
avcodec_get_frame_defaults(&ost->pict_tmp);
@@ -2182,11 +2302,8 @@ static int transcode(AVFormatContext **output_files,
fprintf(stderr, "Cannot get resampling context\n");
ffmpeg_exit(1);
}
-
- ost->original_height = icodec->height;
- ost->original_width = icodec->width;
#endif
- codec->bits_per_raw_sample= 0;
+ codec->bits_per_raw_sample= frame_bits_per_raw_sample;
}
ost->resample_height = icodec->height;
ost->resample_width = icodec->width;
@@ -2195,7 +2312,7 @@ static int transcode(AVFormatContext **output_files,
ist->decoding_needed = 1;
#if CONFIG_AVFILTER
- if (configure_filters(ist, ost)) {
+ if (configure_video_filters(ist, ost)) {
fprintf(stderr, "Error opening filters!\n");
exit(1);
}
@@ -2210,7 +2327,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;
@@ -2237,8 +2354,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);
}
}
@@ -2315,7 +2433,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;
}
@@ -2455,12 +2572,9 @@ static int transcode(AVFormatContext **output_files,
print_sdp(output_files, nb_output_files);
}
- if (!using_stdin && verbose >= 0) {
-#if HAVE_KBHIT
- fprintf(stderr, "Press [q] to stop encoding\n");
-#else
- fprintf(stderr, "Press ctrl-c to stop encoding\n");
-#endif
+ if (!using_stdin) {
+ if(verbose >= 0)
+ fprintf(stderr, "Press [q] to stop encoding\n");
avio_set_interrupt_cb(decode_interrupt_cb);
}
term_init();
@@ -2640,6 +2754,9 @@ static int transcode(AVFormatContext **output_files,
av_freep(&ost->st->codec->stats_in);
avcodec_close(ost->st->codec);
}
+#if CONFIG_AVFILTER
+ avfilter_graph_free(&ost->graph);
+#endif
}
/* close each decoder */
@@ -2649,9 +2766,6 @@ static int transcode(AVFormatContext **output_files,
avcodec_close(ist->st->codec);
}
}
-#if CONFIG_AVFILTER
- avfilter_graph_free(&graph);
-#endif
/* finished ! */
ret = 0;
@@ -2815,19 +2929,20 @@ static int opt_metadata(const char *opt, const char *arg)
return 0;
}
-static void opt_qscale(const char *arg)
+static int opt_qscale(const char *opt, const char *arg)
{
- video_qscale = atof(arg);
- if (video_qscale <= 0 ||
- video_qscale > 255) {
+ video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
+ if (video_qscale <= 0 || video_qscale > 255) {
fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
- ffmpeg_exit(1);
+ return AVERROR(EINVAL);
}
+ return 0;
}
-static void opt_top_field_first(const char *arg)
+static int opt_top_field_first(const char *opt, const char *arg)
{
- top_field_first= atoi(arg);
+ top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
+ return 0;
}
static int opt_thread_count(const char *opt, const char *arg)
@@ -2849,7 +2964,10 @@ static void opt_audio_sample_fmt(const char *arg)
ffmpeg_exit(1);
}
} else {
- list_fmts(av_get_sample_fmt_string, AV_SAMPLE_FMT_NB);
+ int i;
+ char fmt_str[128];
+ for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
+ printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
ffmpeg_exit(0);
}
}
@@ -2866,9 +2984,10 @@ static int opt_audio_channels(const char *opt, const char *arg)
return 0;
}
-static void opt_video_channel(const char *arg)
+static int opt_video_channel(const char *opt, const char *arg)
{
- video_channel = strtol(arg, NULL, 0);
+ video_channel = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
+ return 0;
}
static void opt_video_standard(const char *arg)
@@ -3230,11 +3349,6 @@ static void opt_input_file(const char *filename)
set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
frame_height = dec->height;
frame_width = dec->width;
- if(ic->streams[i]->sample_aspect_ratio.num)
- frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio);
- else
- frame_aspect_ratio=av_q2d(dec->sample_aspect_ratio);
- frame_aspect_ratio *= (float) dec->width / dec->height;
frame_pix_fmt = dec->pix_fmt;
rfps = ic->streams[i]->r_frame_rate.num;
rfps_base = ic->streams[i]->r_frame_rate.den;
@@ -3358,6 +3472,12 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
codec = avcodec_find_encoder(codec_id);
}
+ ost->frame_aspect_ratio = frame_aspect_ratio;
+ frame_aspect_ratio = 0;
+#if CONFIG_AVFILTER
+ ost->avfilter= vfilters;
+ vfilters= NULL;
+#endif
}
avcodec_get_context_defaults3(st->codec, codec);
@@ -3401,8 +3521,8 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
video_enc->width = frame_width;
video_enc->height = frame_height;
- video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
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;
choose_pixel_fmt(st, codec);
@@ -3780,7 +3900,6 @@ static void opt_output_file(const char *filename)
oc->preload= (int)(mux_preload*AV_TIME_BASE);
oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
oc->loop_output = loop_output;
- oc->flags |= AVFMT_FLAG_NONBLOCK;
set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
@@ -3788,15 +3907,10 @@ static void opt_output_file(const char *filename)
}
/* same option as mencoder */
-static void opt_pass(const char *pass_str)
+static int opt_pass(const char *opt, const char *arg)
{
- int pass;
- pass = atoi(pass_str);
- if (pass != 1 && pass != 2) {
- fprintf(stderr, "pass number can be only 1 or 2\n");
- ffmpeg_exit(1);
- }
- do_pass = pass;
+ do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 2);
+ return 0;
}
static int64_t getutime(void)
@@ -3973,7 +4087,7 @@ static void opt_target(const char *arg)
}
}
}
- if(verbose && norm != UNKNOWN)
+ if(verbose > 0 && norm != UNKNOWN)
fprintf(stderr, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC");
}
@@ -4150,6 +4264,16 @@ 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 void opt_passlogfile(const char *arg)
+{
+ pass_logfilename_prefix = arg;
+ opt_default("passlogfile", arg);
+}
+
static const OptionDef options[] = {
/* main options */
#include "cmdutils_common_opts.h"
@@ -4203,6 +4327,7 @@ 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" },
+ { "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", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
{ "cropbottom", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
{ "cropleft", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
@@ -4215,14 +4340,14 @@ static const OptionDef options[] = {
{ "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
{ "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
{ "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" },
+ { "qscale", HAS_ARG | OPT_FUNC2 | 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" },
{ "me_threshold", HAS_ARG | OPT_FUNC2 | 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" },
+ { "pass", HAS_ARG | OPT_FUNC2 | 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" },
{ "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
@@ -4233,7 +4358,7 @@ static const OptionDef options[] = {
#endif
{ "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
{ "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
- { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
+ { "top", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
{ "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
{ "vtag", OPT_FUNC2 | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_codec_tag}, "force video tag/fourcc", "fourcc/tag" },
{ "newvideo", OPT_VIDEO | OPT_FUNC2, {(void*)opt_new_stream}, "add a new video stream to the current output stream" },
@@ -4265,7 +4390,7 @@ static const OptionDef options[] = {
{ "stag", OPT_FUNC2 | 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}, "set video grab channel (DV1394 only)", "channel" },
+ { "vc", HAS_ARG | OPT_FUNC2 | 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", "" },
@@ -4292,6 +4417,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();