#include <errno.h>
#include <signal.h>
#include <limits.h>
-#include <unistd.h>
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavutil/avstring.h"
#include "libavutil/libm.h"
#include "libavutil/imgutils.h"
+#include "libavutil/time.h"
#include "libavformat/os_support.h"
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
# include "libavfilter/buffersrc.h"
# include "libavfilter/buffersink.h"
-# include "libavfilter/vsrc_buffer.h"
#if HAVE_SYS_RESOURCE_H
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/resource.h>
#elif HAVE_GETPROCESSTIMES
#include <windows.h>
#include <sys/select.h>
#endif
+#if HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
#include <time.h>
#include "cmdutils.h"
int index; ///< stream/chapter/program number
} MetadataMap;
-static const OptionDef options[];
+static const OptionDef *options;
static int video_discard = 0;
static int same_quant = 0;
static int print_stats = 1;
+#if HAVE_PTHREADS
+/* signal to input threads that they should exit; set by the main thread */
+static int transcoding_finished;
+#endif
+
#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
typedef struct InputFilter {
int nb_outputs;
} FilterGraph;
-typedef struct FrameBuffer {
- uint8_t *base[4];
- uint8_t *data[4];
- int linesize[4];
-
- int h, w;
- enum PixelFormat pix_fmt;
-
- int refcount;
- struct InputStream *ist;
- struct FrameBuffer *next;
-} FrameBuffer;
-
typedef struct InputStream {
int file_index;
AVStream *st;
int nb_streams; /* number of stream that avconv is aware of; may be different
from ctx.nb_streams if new streams appear during av_read_frame() */
int rate_emu;
+
+#if HAVE_PTHREADS
+ pthread_t thread; /* thread reading from this file */
+ int finished; /* the thread has exited */
+ int joined; /* the thread has been joined */
+ pthread_mutex_t fifo_lock; /* lock for access to fifo */
+ pthread_cond_t fifo_cond; /* the main thread will signal on this cond after reading from fifo */
+ AVFifoBuffer *fifo; /* demuxed packets are stored here; freed by the main thread */
+#endif
} InputFile;
typedef struct OutputStream {
int64_t *forced_kf_pts;
int forced_kf_count;
int forced_kf_index;
+ char *forced_keyframes;
FILE *logfile;
init_opts();
}
-static int alloc_buffer(InputStream *ist, AVCodecContext *s, FrameBuffer **pbuf)
-{
- FrameBuffer *buf = av_mallocz(sizeof(*buf));
- 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
- int w = s->width, h = s->height;
-
- if (!buf)
- return AVERROR(ENOMEM);
-
- if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
- w += 2*edge;
- h += 2*edge;
- }
-
- avcodec_align_dimensions(s, &w, &h);
- if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
- s->pix_fmt, 32)) < 0) {
- av_freep(&buf);
- return ret;
- }
- /* XXX this shouldn't be needed, but some tests break without this line
- * those decoders are buggy and need to be fixed.
- * the following tests fail:
- * cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
- */
- memset(buf->base[0], 128, ret);
-
- avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
- for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
- const int h_shift = i==0 ? 0 : h_chroma_shift;
- const int v_shift = i==0 ? 0 : v_chroma_shift;
- if (s->flags & CODEC_FLAG_EMU_EDGE)
- buf->data[i] = buf->base[i];
- else
- buf->data[i] = buf->base[i] +
- FFALIGN((buf->linesize[i]*edge >> v_shift) +
- (pixel_size*edge >> h_shift), 32);
- }
- buf->w = s->width;
- buf->h = s->height;
- buf->pix_fmt = s->pix_fmt;
- buf->ist = ist;
-
- *pbuf = buf;
- return 0;
-}
-
-static void free_buffer_pool(InputStream *ist)
-{
- FrameBuffer *buf = ist->buffer_pool;
- while (buf) {
- ist->buffer_pool = buf->next;
- av_freep(&buf->base[0]);
- av_free(buf);
- buf = ist->buffer_pool;
- }
-}
-
-static void unref_buffer(InputStream *ist, FrameBuffer *buf)
-{
- av_assert0(buf->refcount);
- buf->refcount--;
- if (!buf->refcount) {
- buf->next = ist->buffer_pool;
- ist->buffer_pool = buf;
- }
-}
-
-static int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
-{
- InputStream *ist = s->opaque;
- FrameBuffer *buf;
- int ret, i;
-
- if (!ist->buffer_pool && (ret = alloc_buffer(ist, s, &ist->buffer_pool)) < 0)
- return ret;
-
- buf = ist->buffer_pool;
- ist->buffer_pool = buf->next;
- buf->next = NULL;
- if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
- av_freep(&buf->base[0]);
- av_free(buf);
- if ((ret = alloc_buffer(ist, s, &buf)) < 0)
- return ret;
- }
- buf->refcount++;
-
- frame->opaque = buf;
- frame->type = FF_BUFFER_TYPE_USER;
- frame->extended_data = frame->data;
- frame->pkt_pts = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE;
- frame->width = buf->w;
- frame->height = buf->h;
- frame->format = buf->pix_fmt;
- frame->sample_aspect_ratio = s->sample_aspect_ratio;
-
- for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
- frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't
- frame->data[i] = buf->data[i];
- frame->linesize[i] = buf->linesize[i];
- }
-
- return 0;
-}
-
-static void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
-{
- InputStream *ist = s->opaque;
- FrameBuffer *buf = frame->opaque;
- int i;
-
- for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
- frame->data[i] = NULL;
-
- unref_buffer(ist, buf);
-}
-
-static void filter_release_buffer(AVFilterBuffer *fb)
-{
- FrameBuffer *buf = fb->priv;
- av_free(fb);
- unref_buffer(buf->ist, buf);
-}
-
/**
* Define a function for building a string containing a list of
* allowed formats,
static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
{
- InputStream *ist;
- enum AVMediaType type = in->filter_ctx->input_pads[in->pad_idx].type;
+ InputStream *ist = NULL;
+ enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
int i;
// TODO: support other filter types
exit_program(1);
}
}
+ av_assert0(ist);
+
ist->discard = 0;
ist->decoding_needed = 1;
ist->st->discard = AVDISCARD_NONE;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
int ret;
+ char name[255];
-
+ snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
ret = avfilter_graph_create_filter(&ofilter->filter,
avfilter_get_by_name("buffersink"),
- "out", NULL, pix_fmts, fg->graph);
+ name, NULL, pix_fmts, fg->graph);
if (ret < 0)
return ret;
codec->width,
codec->height,
(unsigned)ost->sws_flags);
+ snprintf(name, sizeof(name), "scaler for output stream %d:%d",
+ ost->file_index, ost->index);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
- NULL, args, NULL, fg->graph)) < 0)
+ name, args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
return ret;
if ((pix_fmts = choose_pix_fmts(ost))) {
AVFilterContext *filter;
+ snprintf(name, sizeof(name), "pixel format for output stream %d:%d",
+ ost->file_index, ost->index);
if ((ret = avfilter_graph_create_filter(&filter,
avfilter_get_by_name("format"),
"format", pix_fmts, NULL,
snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
ost->frame_rate.den);
+ snprintf(name, sizeof(name), "fps for output stream %d:%d",
+ ost->file_index, ost->index);
ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"),
- "fps", args, NULL, fg->graph);
+ name, args, NULL, fg->graph);
if (ret < 0)
return ret;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
char *sample_fmts, *sample_rates, *channel_layouts;
+ char name[255];
int ret;
+
+ snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
ret = avfilter_graph_create_filter(&ofilter->filter,
avfilter_get_by_name("abuffersink"),
- "out", NULL, NULL, fg->graph);
+ name, NULL, NULL, fg->graph);
if (ret < 0)
return ret;
av_freep(&sample_rates);
av_freep(&channel_layouts);
+ snprintf(name, sizeof(name), "audio format for output stream %d:%d",
+ ost->file_index, ost->index);
ret = avfilter_graph_create_filter(&format,
avfilter_get_by_name("aformat"),
- "aformat", args, NULL, fg->graph);
+ name, args, NULL, fg->graph);
if (ret < 0)
return ret;
pad_idx = 0;
}
- if (audio_sync_method > 0) {
- AVFilterContext *async;
- char args[256];
- int len = 0;
-
- av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
- "asyncts audio filter instead.\n");
-
- if (audio_sync_method > 1)
- len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
- "max_comp=%d:", audio_sync_method);
- snprintf(args + len, sizeof(args) - len, "min_delta=%f",
- audio_drift_threshold);
-
- ret = avfilter_graph_create_filter(&async,
- avfilter_get_by_name("asyncts"),
- "async", args, NULL, fg->graph);
- if (ret < 0)
- return ret;
-
- ret = avfilter_link(last_filter, pad_idx, async, 0);
- if (ret < 0)
- return ret;
-
- last_filter = async;
- pad_idx = 0;
- }
-
if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
return ret;
\
avio_printf(pb, "%s", ctx->filter->name); \
if (nb_pads > 1) \
- avio_printf(pb, ":%s", pads[inout->pad_idx].name); \
+ avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
avio_w8(pb, 0); \
avio_close_dyn_buf(pb, &f->name); \
}
av_freep(&ofilter->name);
DESCRIBE_FILTER_LINK(ofilter, out, 0);
- switch (out->filter_ctx->output_pads[out->pad_idx].type) {
+ switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
default: av_assert0(0);
ist->framerate.num} :
ist->st->time_base;
AVRational sar;
- char args[255];
+ char args[255], name[255];
int pad_idx = in->pad_idx;
int ret;
snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
ist->st->codec->height, ist->st->codec->pix_fmt,
tb.num, tb.den, sar.num, sar.den);
+ snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
+ ist->file_index, ist->st->index);
- if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, in->name,
+ if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, name,
args, NULL, fg->graph)) < 0)
return ret;
if (ist->framerate.num) {
AVFilterContext *setpts;
+ snprintf(name, sizeof(name), "force CFR for input from stream %d:%d",
+ ist->file_index, ist->st->index);
if ((ret = avfilter_graph_create_filter(&setpts,
avfilter_get_by_name("setpts"),
- "setpts", "N", NULL,
+ name, "N", NULL,
fg->graph)) < 0)
return ret;
AVFilter *filter = avfilter_get_by_name("abuffer");
InputStream *ist = ifilter->ist;
int pad_idx = in->pad_idx;
- char args[255];
+ char args[255], name[255];
int ret;
snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
":channel_layout=0x%"PRIx64,
- ist->st->time_base.num, ist->st->time_base.den,
+ 1, ist->st->codec->sample_rate,
ist->st->codec->sample_rate,
av_get_sample_fmt_name(ist->st->codec->sample_fmt),
ist->st->codec->channel_layout);
+ snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
+ ist->file_index, ist->st->index);
if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter,
- in->name, args, NULL,
+ name, args, NULL,
fg->graph)) < 0)
return ret;
snprintf(args + len, sizeof(args) - len, "min_delta=%f",
audio_drift_threshold);
+ snprintf(name, sizeof(name), "graph %d audio sync for input stream %d:%d",
+ fg->index, ist->file_index, ist->st->index);
ret = avfilter_graph_create_filter(&async,
avfilter_get_by_name("asyncts"),
- "async", args, NULL, fg->graph);
+ name, args, NULL, fg->graph);
if (ret < 0)
return ret;
av_freep(&ifilter->name);
DESCRIBE_FILTER_LINK(ifilter, in, 1);
- switch (in->filter_ctx->input_pads[in->pad_idx].type) {
+ switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in);
case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in);
default: av_assert0(0);
}
output_streams[i]->bitstream_filters = NULL;
+ av_freep(&output_streams[i]->forced_keyframes);
av_freep(&output_streams[i]->avfilter);
av_freep(&output_streams[i]->filtered_frame);
av_freep(&output_streams[i]);
for (i = 0; i < nb_input_streams; i++) {
av_freep(&input_streams[i]->decoded_frame);
av_dict_free(&input_streams[i]->opts);
- free_buffer_pool(input_streams[i]);
+ free_buffer_pool(&input_streams[i]->buffer_pool);
av_freep(&input_streams[i]->filters);
av_freep(&input_streams[i]);
}
else
ret = av_buffersink_read(ost->filter->filter, &picref);
- if (ret < 0)
+ if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
break;
+ else if (ret < 0)
+ return ret;
avfilter_copy_buf_props(filtered_frame, picref);
- if (picref->pts != AV_NOPTS_VALUE)
+ if (picref->pts != AV_NOPTS_VALUE) {
filtered_frame->pts = av_rescale_q(picref->pts,
ost->filter->filter->inputs[0]->time_base,
ost->st->codec->time_base) -
AV_TIME_BASE_Q,
ost->st->codec->time_base);
- if (of->start_time && filtered_frame->pts < of->start_time) {
- avfilter_unref_buffer(picref);
- continue;
+ if (of->start_time && filtered_frame->pts < 0) {
+ avfilter_unref_buffer(picref);
+ continue;
+ }
}
switch (ost->filter->filter->inputs[0]->type) {
int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE);
int64_t now = av_gettime() - ist->start;
if (pts > now)
- usleep(pts - now);
+ av_usleep(pts - now);
}
}
}
}
+ if (decoded_frame->pts != AV_NOPTS_VALUE)
+ decoded_frame->pts = av_rescale_q(decoded_frame->pts,
+ ist->st->time_base,
+ (AVRational){1, ist->st->codec->sample_rate});
for (i = 0; i < ist->nb_filters; i++)
av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame);
ret = decode_video (ist, &avpkt, &got_output);
if (avpkt.duration)
ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
- else if (ist->st->r_frame_rate.num)
- ist->next_dts += av_rescale_q(1, (AVRational){ist->st->r_frame_rate.den,
- ist->st->r_frame_rate.num},
+ else if (ist->st->avg_frame_rate.num)
+ ist->next_dts += av_rescale_q(1, (AVRational){ist->st->avg_frame_rate.den,
+ ist->st->avg_frame_rate.num},
AV_TIME_BASE_Q);
else if (ist->st->codec->time_base.num != 0) {
int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 :
if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) {
ist->st->codec->get_buffer = codec_get_buffer;
ist->st->codec->release_buffer = codec_release_buffer;
- ist->st->codec->opaque = ist;
+ ist->st->codec->opaque = &ist->buffer_pool;
}
if (!av_dict_get(ist->opts, "threads", NULL, 0))
return NULL;
}
+static void parse_forced_key_frames(char *kf, OutputStream *ost,
+ AVCodecContext *avctx)
+{
+ char *p;
+ int n = 1, i;
+ int64_t t;
+
+ for (p = kf; *p; p++)
+ if (*p == ',')
+ n++;
+ ost->forced_kf_count = n;
+ ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
+ if (!ost->forced_kf_pts) {
+ av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
+ exit_program(1);
+ }
+
+ p = kf;
+ for (i = 0; i < n; i++) {
+ char *next = strchr(p, ',');
+
+ if (next)
+ *next++ = 0;
+
+ t = parse_time_or_die("force_key_frames", p, 1);
+ ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
+
+ p = next;
+ }
+}
+
static int transcode_init(void)
{
int ret = 0, i, j, k;
(video_sync_method == VSYNC_CFR ||
(video_sync_method == VSYNC_AUTO &&
!(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS))))) {
- ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
+ ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
codec->bits_per_raw_sample = 0;
}
+ if (ost->forced_keyframes)
+ parse_forced_key_frames(ost->forced_keyframes, ost,
+ ost->st->codec);
break;
case AVMEDIA_TYPE_SUBTITLE:
codec->time_base = (AVRational){1, 1000};
if (ost->is_past_recording_time ||
(os->pb && avio_tell(os->pb) >= of->limit_filesize))
continue;
- if (ost->frame_number > ost->max_frames) {
+ if (ost->frame_number >= ost->max_frames) {
int j;
for (j = 0; j < of->ctx->nb_streams; j++)
output_streams[of->ost_index + j]->is_past_recording_time = 1;
return file_index;
}
+#if HAVE_PTHREADS
+static void *input_thread(void *arg)
+{
+ InputFile *f = arg;
+ int ret = 0;
+
+ while (!transcoding_finished && ret >= 0) {
+ AVPacket pkt;
+ ret = av_read_frame(f->ctx, &pkt);
+
+ if (ret == AVERROR(EAGAIN)) {
+ av_usleep(10000);
+ ret = 0;
+ continue;
+ } else if (ret < 0)
+ break;
+
+ pthread_mutex_lock(&f->fifo_lock);
+ while (!av_fifo_space(f->fifo))
+ pthread_cond_wait(&f->fifo_cond, &f->fifo_lock);
+
+ av_dup_packet(&pkt);
+ av_fifo_generic_write(f->fifo, &pkt, sizeof(pkt), NULL);
+
+ pthread_mutex_unlock(&f->fifo_lock);
+ }
+
+ f->finished = 1;
+ return NULL;
+}
+
+static void free_input_threads(void)
+{
+ int i;
+
+ if (nb_input_files == 1)
+ return;
+
+ transcoding_finished = 1;
+
+ for (i = 0; i < nb_input_files; i++) {
+ InputFile *f = input_files[i];
+ AVPacket pkt;
+
+ if (!f->fifo || f->joined)
+ continue;
+
+ pthread_mutex_lock(&f->fifo_lock);
+ while (av_fifo_size(f->fifo)) {
+ av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL);
+ av_free_packet(&pkt);
+ }
+ pthread_cond_signal(&f->fifo_cond);
+ pthread_mutex_unlock(&f->fifo_lock);
+
+ pthread_join(f->thread, NULL);
+ f->joined = 1;
+
+ while (av_fifo_size(f->fifo)) {
+ av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL);
+ av_free_packet(&pkt);
+ }
+ av_fifo_free(f->fifo);
+ }
+}
+
+static int init_input_threads(void)
+{
+ int i, ret;
+
+ if (nb_input_files == 1)
+ return 0;
+
+ for (i = 0; i < nb_input_files; i++) {
+ InputFile *f = input_files[i];
+
+ if (!(f->fifo = av_fifo_alloc(8*sizeof(AVPacket))))
+ return AVERROR(ENOMEM);
+
+ pthread_mutex_init(&f->fifo_lock, NULL);
+ pthread_cond_init (&f->fifo_cond, NULL);
+
+ if ((ret = pthread_create(&f->thread, NULL, input_thread, f)))
+ return AVERROR(ret);
+ }
+ return 0;
+}
+
+static int get_input_packet_mt(InputFile *f, AVPacket *pkt)
+{
+ int ret = 0;
+
+ pthread_mutex_lock(&f->fifo_lock);
+
+ if (av_fifo_size(f->fifo)) {
+ av_fifo_generic_read(f->fifo, pkt, sizeof(*pkt), NULL);
+ pthread_cond_signal(&f->fifo_cond);
+ } else {
+ if (f->finished)
+ ret = AVERROR_EOF;
+ else
+ ret = AVERROR(EAGAIN);
+ }
+
+ pthread_mutex_unlock(&f->fifo_lock);
+
+ return ret;
+}
+#endif
+
+static int get_input_packet(InputFile *f, AVPacket *pkt)
+{
+#if HAVE_PTHREADS
+ if (nb_input_files > 1)
+ return get_input_packet_mt(f, pkt);
+#endif
+ return av_read_frame(f->ctx, pkt);
+}
+
/*
* The following code is the main loop of the file converter
*/
timer_start = av_gettime();
+#if HAVE_PTHREADS
+ if ((ret = init_input_threads()) < 0)
+ goto fail;
+#endif
+
for (; received_sigterm == 0;) {
int file_index, ist_index;
AVPacket pkt;
if (no_packet_count) {
no_packet_count = 0;
memset(no_packet, 0, nb_input_files);
- usleep(10000);
+ av_usleep(10000);
continue;
}
+ av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n");
break;
}
- /* read a frame from it and output it in the fifo */
is = input_files[file_index]->ctx;
- ret = av_read_frame(is, &pkt);
+ ret = get_input_packet(input_files[file_index], &pkt);
+
if (ret == AVERROR(EAGAIN)) {
no_packet[file_index] = 1;
no_packet_count++;
continue;
}
if (ret < 0) {
+ if (ret != AVERROR_EOF) {
+ print_error(is->filename, ret);
+ if (exit_on_error)
+ exit_program(1);
+ }
input_files[file_index]->eof_reached = 1;
for (i = 0; i < input_files[file_index]->nb_streams; i++) {
/* dump report by using the output first video and audio streams */
print_report(0, timer_start);
}
+#if HAVE_PTHREADS
+ free_input_threads();
+#endif
/* at the end of stream, we must flush the decoder buffers */
for (i = 0; i < nb_input_streams; i++) {
fail:
av_freep(&no_packet);
+#if HAVE_PTHREADS
+ free_input_threads();
+#endif
if (output_streams) {
for (i = 0; i < nb_output_streams; i++) {
METADATA_CHECK_INDEX(index, context->nb_programs, "program")\
meta = &context->programs[index]->metadata;\
break;\
+ default: av_assert0(0);\
}\
SET_DICT(type_in, meta_in, ic, idx_in);
ist->file_index = nb_input_files;
ist->discard = 1;
st->discard = AVDISCARD_ALL;
- ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
+ ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st, NULL);
ist->ts_scale = 1.0;
MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
return 0;
}
-static void parse_forced_key_frames(char *kf, OutputStream *ost,
- AVCodecContext *avctx)
-{
- char *p;
- int n = 1, i;
- int64_t t;
-
- for (p = kf; *p; p++)
- if (*p == ',')
- n++;
- ost->forced_kf_count = n;
- ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
- if (!ost->forced_kf_pts) {
- av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
- exit_program(1);
- }
- for (i = 0; i < n; i++) {
- p = i ? strchr(p, ',') + 1 : kf;
- t = parse_time_or_die("force_key_frames", p, 1);
- ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
- }
-}
-
static uint8_t *get_line(AVIOContext *s)
{
AVIOContext *line;
st->codec->codec_type = type;
choose_encoder(o, oc, ost);
if (ost->enc) {
- ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st);
+ ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st, ost->enc);
}
avcodec_get_context_defaults3(st->codec, ost->enc);
if (!ost->stream_copy) {
const char *p = NULL;
- char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
+ char *frame_rate = NULL, *frame_size = NULL;
char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
char *intra_matrix = NULL, *inter_matrix = NULL;
const char *filters = "null";
}
}
- MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_key_frames, oc, st);
- if (forced_key_frames)
- parse_forced_key_frames(forced_key_frames, ost, video_enc);
+ MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st);
+ if (ost->forced_keyframes)
+ ost->forced_keyframes = av_strdup(ost->forced_keyframes);
MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st);
{
OutputStream *ost;
- switch (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type) {
+ switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
+ ofilter->out_tmp->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc); break;
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break;
default:
if (!ofilter->out_tmp || ofilter->out_tmp->name)
continue;
- switch (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type) {
+ switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
+ ofilter->out_tmp->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break;
case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break;
case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
} else if (ret < 0)
exit_program(1);
}
- printf("ret %d, stream_spec %s\n", ret, stream_spec);
}
else {
switch (type) {
}
#define OFFSET(x) offsetof(OptionsContext, x)
-static const OptionDef options[] = {
+static const OptionDef real_options[] = {
/* main options */
#include "cmdutils_common_opts.h"
{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET, {.off = OFFSET(format)}, "force format", "fmt" },
OptionsContext o = { 0 };
int64_t ti;
+ options = real_options;
reset_options(&o);
av_log_set_flags(AV_LOG_SKIP_REPEATED);