...
 
Commits (1)
......@@ -38,6 +38,7 @@ typedef struct Dav1dData {
size_t sz; ///< data size
struct Dav1dRef *ref; ///< allocation origin
Dav1dDataProps m; ///< user provided metadata passed to the output picture
int drop_frame; ///< attempt to drop frames from this data
} Dav1dData;
/**
......
......@@ -48,6 +48,7 @@ uint8_t *dav1d_data_create_internal(Dav1dData *const buf, const size_t sz) {
buf->data = buf->ref->const_data;
buf->sz = buf->m.size = sz;
dav1d_data_props_set_defaults(&buf->m);
buf->drop_frame = 0;
return buf->ref->data;
}
......@@ -67,6 +68,7 @@ int dav1d_data_wrap_internal(Dav1dData *const buf, const uint8_t *const ptr,
buf->data = ptr;
buf->sz = buf->m.size = sz;
dav1d_data_props_set_defaults(&buf->m);
buf->drop_frame = 0;
return 0;
}
......
......@@ -1430,35 +1430,37 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
if (c->seq_hdr && c->frame_hdr) {
if (c->frame_hdr->show_existing_frame) {
if (!c->refs[c->frame_hdr->existing_frame_idx].p.p.data[0]) return -EINVAL;
if (c->n_fc == 1) {
dav1d_picture_ref(&c->out,
&c->refs[c->frame_hdr->existing_frame_idx].p.p);
dav1d_data_props_copy(&c->out.m, &in->m);
} else {
// need to append this to the frame output queue
const unsigned next = c->frame_thread.next++;
if (c->frame_thread.next == c->n_fc)
c->frame_thread.next = 0;
Dav1dFrameContext *const f = &c->fc[next];
pthread_mutex_lock(&f->frame_thread.td.lock);
while (f->n_tile_data > 0)
pthread_cond_wait(&f->frame_thread.td.cond,
&f->frame_thread.td.lock);
Dav1dThreadPicture *const out_delayed =
&c->frame_thread.out_delayed[next];
if (out_delayed->p.data[0]) {
const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
memory_order_relaxed);
if (out_delayed->visible && progress != FRAME_ERROR)
dav1d_picture_ref(&c->out, &out_delayed->p);
dav1d_thread_picture_unref(out_delayed);
if (!in->drop_frame) {
if (c->n_fc == 1) {
dav1d_picture_ref(&c->out,
&c->refs[c->frame_hdr->existing_frame_idx].p.p);
dav1d_data_props_copy(&c->out.m, &in->m);
} else {
// need to append this to the frame output queue
const unsigned next = c->frame_thread.next++;
if (c->frame_thread.next == c->n_fc)
c->frame_thread.next = 0;
Dav1dFrameContext *const f = &c->fc[next];
pthread_mutex_lock(&f->frame_thread.td.lock);
while (f->n_tile_data > 0)
pthread_cond_wait(&f->frame_thread.td.cond,
&f->frame_thread.td.lock);
Dav1dThreadPicture *const out_delayed =
&c->frame_thread.out_delayed[next];
if (out_delayed->p.data[0]) {
const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
memory_order_relaxed);
if (out_delayed->visible && progress != FRAME_ERROR)
dav1d_picture_ref(&c->out, &out_delayed->p);
dav1d_thread_picture_unref(out_delayed);
}
dav1d_thread_picture_ref(out_delayed,
&c->refs[c->frame_hdr->existing_frame_idx].p);
out_delayed->visible = 1;
dav1d_data_props_copy(&out_delayed->p.m, &in->m);
pthread_mutex_unlock(&f->frame_thread.td.lock);
}
dav1d_thread_picture_ref(out_delayed,
&c->refs[c->frame_hdr->existing_frame_idx].p);
out_delayed->visible = 1;
dav1d_data_props_copy(&out_delayed->p.m, &in->m);
pthread_mutex_unlock(&f->frame_thread.td.lock);
}
if (c->refs[c->frame_hdr->existing_frame_idx].p.p.frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY) {
const int r = c->frame_hdr->existing_frame_idx;
......
......@@ -176,7 +176,7 @@ int dav1d_thread_picture_alloc(Dav1dContext *const c, Dav1dFrameContext *const f
(void **) &p->progress);
if (res) return res;
p->visible = f->frame_hdr->show_frame;
p->visible = f->frame_hdr->show_frame && !f->tile[0].data.drop_frame;
if (p->t) {
atomic_init(&p->progress[0], 0);
atomic_init(&p->progress[1], 0);
......
......@@ -128,6 +128,7 @@ int main(const int argc, char *const *const argv) {
do {
memset(&p, 0, sizeof(p));
data.drop_frame = cli_settings.drop_frames;
if ((res = dav1d_send_data(c, &data)) < 0) {
if (res != -EAGAIN) {
fprintf(stderr, "Error decoding frame: %s\n",
......
......@@ -41,7 +41,7 @@
#include "dav1d_cli_parse.h"
#include "src/cpu.h"
static const char short_opts[] = "i:o:vql:s:";
static const char short_opts[] = "i:o:vqdl:s:";
enum {
ARG_DEMUXER = 256,
......@@ -59,6 +59,7 @@ static const struct option long_opts[] = {
{ "input", 1, NULL, 'i' },
{ "output", 1, NULL, 'o' },
{ "quiet", 0, NULL, 'q' },
{ "dropframes", 0, NULL, 'd' },
{ "demuxer", 1, NULL, ARG_DEMUXER },
{ "muxer", 1, NULL, ARG_MUXER },
{ "version", 0, NULL, 'v' },
......@@ -99,6 +100,7 @@ static void usage(const char *const app, const char *const reason, ...) {
" --demuxer $name: force demuxer type ('ivf' or 'annexb'; default: detect from extension)\n"
" --muxer $name: force muxer type ('md5', 'yuv', 'yuv4mpeg2' or 'null'; default: detect from extension)\n"
" --quiet/-q: disable status messages\n"
" --dropframes/-d: drop all frames\n"
" --limit/-l $num: stop decoding after $num frames\n"
" --skip/-s $num: skip decoding of the first $num frames\n"
" --version/-v: print version and exit\n"
......@@ -226,6 +228,9 @@ void parse(const int argc, char *const *const argv,
case 'q':
cli_settings->quiet = 1;
break;
case 'd':
cli_settings->drop_frames = 1;
break;
case 'l':
cli_settings->limit = parse_unsigned(optarg, 'l', argv[0]);
break;
......
......@@ -37,7 +37,7 @@ typedef struct {
const char *muxer;
const char *verify;
unsigned limit, skip;
int quiet;
int quiet, drop_frames;
} CLISettings;
void parse(const int argc, char *const *const argv,
......