ffmpeg: add option readrate
Allows to read inputs at arbitrary rates. -re is equivalent to -readrate 1 Tested with -copyts {+ start_at_zero}, -ss, streamcopied & decoded streams.
This commit is contained in:
parent
075157ec86
commit
c320b78e95
@ -1575,14 +1575,21 @@ Exit after ffmpeg has been running for @var{duration} seconds in CPU user time.
|
|||||||
Dump each input packet to stderr.
|
Dump each input packet to stderr.
|
||||||
@item -hex (@emph{global})
|
@item -hex (@emph{global})
|
||||||
When dumping packets, also dump the payload.
|
When dumping packets, also dump the payload.
|
||||||
|
@item -readrate @var{speed} (@emph{input})
|
||||||
|
Limit input read speed.
|
||||||
|
|
||||||
|
Its value is a floating-point positive number which represents the maximum duration of
|
||||||
|
media, in seconds, that should be ingested in one second of wallclock time.
|
||||||
|
Default value is zero and represents no imposed limitation on speed of ingestion.
|
||||||
|
Value @code{1} represents real-time speed and is equivalent to @code{-re}.
|
||||||
|
|
||||||
|
Mainly used to simulate a capture device or live input stream (e.g. when reading from a file).
|
||||||
|
Should not be used with a low value when input is an actual capture device or live stream as
|
||||||
|
it may cause packet loss.
|
||||||
|
|
||||||
|
It is useful for when flow speed of output packets is important, such as live streaming.
|
||||||
@item -re (@emph{input})
|
@item -re (@emph{input})
|
||||||
Read input at native frame rate. Mainly used to simulate a grab device,
|
Read input at native frame rate. This is equivalent to setting @code{-readrate 1}.
|
||||||
or live input stream (e.g. when reading from a file). Should not be used
|
|
||||||
with actual grab devices or live input streams (where it can cause packet
|
|
||||||
loss).
|
|
||||||
By default @command{ffmpeg} attempts to read the input(s) as fast as possible.
|
|
||||||
This option will slow down the reading of the input(s) to the native frame rate
|
|
||||||
of the input(s). It is useful for real-time output (e.g. live streaming).
|
|
||||||
@item -vsync @var{parameter}
|
@item -vsync @var{parameter}
|
||||||
Video sync method.
|
Video sync method.
|
||||||
For compatibility reasons old values can be specified as numbers.
|
For compatibility reasons old values can be specified as numbers.
|
||||||
|
@ -3765,7 +3765,7 @@ static int transcode_init(void)
|
|||||||
/* init framerate emulation */
|
/* init framerate emulation */
|
||||||
for (i = 0; i < nb_input_files; i++) {
|
for (i = 0; i < nb_input_files; i++) {
|
||||||
InputFile *ifile = input_files[i];
|
InputFile *ifile = input_files[i];
|
||||||
if (ifile->rate_emu)
|
if (ifile->readrate || ifile->rate_emu)
|
||||||
for (j = 0; j < ifile->nb_streams; j++)
|
for (j = 0; j < ifile->nb_streams; j++)
|
||||||
input_streams[j + ifile->ist_index]->start = av_gettime_relative();
|
input_streams[j + ifile->ist_index]->start = av_gettime_relative();
|
||||||
}
|
}
|
||||||
@ -4225,12 +4225,19 @@ static int get_input_packet_mt(InputFile *f, AVPacket **pkt)
|
|||||||
|
|
||||||
static int get_input_packet(InputFile *f, AVPacket **pkt)
|
static int get_input_packet(InputFile *f, AVPacket **pkt)
|
||||||
{
|
{
|
||||||
if (f->rate_emu) {
|
if (f->readrate || f->rate_emu) {
|
||||||
int i;
|
int i;
|
||||||
|
int64_t file_start = copy_ts * (
|
||||||
|
(f->ctx->start_time != AV_NOPTS_VALUE ? f->ctx->start_time * !start_at_zero : 0) +
|
||||||
|
(f->start_time != AV_NOPTS_VALUE ? f->start_time : 0)
|
||||||
|
);
|
||||||
|
float scale = f->rate_emu ? 1.0 : f->readrate;
|
||||||
for (i = 0; i < f->nb_streams; i++) {
|
for (i = 0; i < f->nb_streams; i++) {
|
||||||
InputStream *ist = input_streams[f->ist_index + i];
|
InputStream *ist = input_streams[f->ist_index + i];
|
||||||
|
if (!ist->nb_packets) continue;
|
||||||
|
int64_t stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start);
|
||||||
int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
|
int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
|
||||||
int64_t now = av_gettime_relative() - ist->start;
|
int64_t now = (av_gettime_relative() - ist->start)*scale + stream_ts_offset;
|
||||||
if (pts > now)
|
if (pts > now)
|
||||||
return AVERROR(EAGAIN);
|
return AVERROR(EAGAIN);
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,7 @@ typedef struct OptionsContext {
|
|||||||
int64_t input_ts_offset;
|
int64_t input_ts_offset;
|
||||||
int loop;
|
int loop;
|
||||||
int rate_emu;
|
int rate_emu;
|
||||||
|
float readrate;
|
||||||
int accurate_seek;
|
int accurate_seek;
|
||||||
int thread_queue_size;
|
int thread_queue_size;
|
||||||
|
|
||||||
@ -418,6 +419,7 @@ typedef struct InputFile {
|
|||||||
from ctx.nb_streams if new streams appear during av_read_frame() */
|
from ctx.nb_streams if new streams appear during av_read_frame() */
|
||||||
int nb_streams_warn; /* number of streams that the user was warned of */
|
int nb_streams_warn; /* number of streams that the user was warned of */
|
||||||
int rate_emu;
|
int rate_emu;
|
||||||
|
float readrate;
|
||||||
int accurate_seek;
|
int accurate_seek;
|
||||||
|
|
||||||
AVPacket *pkt;
|
AVPacket *pkt;
|
||||||
|
@ -1286,6 +1286,17 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
|||||||
f->loop = o->loop;
|
f->loop = o->loop;
|
||||||
f->duration = 0;
|
f->duration = 0;
|
||||||
f->time_base = (AVRational){ 1, 1 };
|
f->time_base = (AVRational){ 1, 1 };
|
||||||
|
|
||||||
|
f->readrate = o->readrate ? o->readrate : 0.0;
|
||||||
|
if (f->readrate < 0.0f) {
|
||||||
|
av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", nb_input_files, f->readrate);
|
||||||
|
exit_program(1);
|
||||||
|
}
|
||||||
|
if (f->readrate && f->rate_emu) {
|
||||||
|
av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", nb_input_files, f->readrate);
|
||||||
|
f->rate_emu = 0;
|
||||||
|
}
|
||||||
|
|
||||||
f->pkt = av_packet_alloc();
|
f->pkt = av_packet_alloc();
|
||||||
if (!f->pkt)
|
if (!f->pkt)
|
||||||
exit_program(1);
|
exit_program(1);
|
||||||
@ -3507,7 +3518,10 @@ const OptionDef options[] = {
|
|||||||
"when dumping packets, also dump the payload" },
|
"when dumping packets, also dump the payload" },
|
||||||
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||||
OPT_INPUT, { .off = OFFSET(rate_emu) },
|
OPT_INPUT, { .off = OFFSET(rate_emu) },
|
||||||
"read input at native frame rate", "" },
|
"read input at native frame rate; equivalent to -readrate 1", "" },
|
||||||
|
{ "readrate", HAS_ARG | OPT_FLOAT | OPT_OFFSET |
|
||||||
|
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(readrate) },
|
||||||
|
"read input at specified rate", "speed" },
|
||||||
{ "target", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_target },
|
{ "target", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_target },
|
||||||
"specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" "
|
"specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" "
|
||||||
"with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" },
|
"with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user