[FFmpeg-devel] [PATCH 1/2] avcodec/libdav1d: try to set decoder context parameters during init()

James Almer jamrial at gmail.com
Mon May 11 17:27:55 EEST 2020


If extradata is available, use it to initialize the AVCodecContext before
packet data is seen. Also, don't constantly overwrite it after it's set.

Signed-off-by: James Almer <jamrial at gmail.com>
---
The main benefit from this is using ff_decode_frame_props() to fill frame
props, which includes copying any relevant side data that may be present in
packets, like for example container mastering metadata propagated by a demuxer.

 libavcodec/libdav1d.c | 102 +++++++++++++++++++++++++++++-------------
 1 file changed, 71 insertions(+), 31 deletions(-)

diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index 5248e3f9f5..72f06c550e 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -42,6 +42,8 @@ typedef struct Libdav1dContext {
     int apply_grain;
     int operating_point;
     int all_layers;
+
+    int inited;
 } Libdav1dContext;
 
 static const enum AVPixelFormat pix_fmt[][3] = {
@@ -117,9 +119,59 @@ static void libdav1d_picture_release(Dav1dPicture *p, void *cookie)
     av_buffer_unref(&buf);
 }
 
+static int libdav1d_init_params(AVCodecContext *c, Dav1dSequenceHeader *seq)
+{
+    Libdav1dContext *dav1d = c->priv_data;
+    int res;
+
+    if (dav1d->inited)
+        return 0;
+
+    c->profile = seq->profile;
+    c->level = ((seq->operating_points[0].major_level - 2) << 2)
+               | seq->operating_points[0].minor_level;
+
+    res = ff_set_dimensions(c, seq->max_width, seq->max_height);
+    if (res < 0)
+        return res;
+
+    switch (seq->chr) {
+    case DAV1D_CHR_VERTICAL:
+        c->chroma_sample_location = AVCHROMA_LOC_LEFT;
+        break;
+    case DAV1D_CHR_COLOCATED:
+        c->chroma_sample_location = AVCHROMA_LOC_TOPLEFT;
+        break;
+    }
+    c->colorspace = (enum AVColorSpace) seq->mtrx;
+    c->color_primaries = (enum AVColorPrimaries) seq->pri;
+    c->color_trc = (enum AVColorTransferCharacteristic) seq->trc;
+    c->color_range = seq->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
+
+    if (seq->layout == DAV1D_PIXEL_LAYOUT_I444 &&
+        seq->mtrx == DAV1D_MC_IDENTITY &&
+        seq->pri  == DAV1D_COLOR_PRI_BT709 &&
+        seq->trc  == DAV1D_TRC_SRGB)
+        c->pix_fmt = pix_fmt_rgb[seq->hbd];
+    else
+        c->pix_fmt = pix_fmt[seq->layout][seq->hbd];
+
+    if (seq->num_units_in_tick && seq->time_scale) {
+        av_reduce(&c->framerate.den, &c->framerate.num,
+                  seq->num_units_in_tick, seq->time_scale, INT_MAX);
+        if (seq->equal_picture_interval)
+            c->ticks_per_frame = seq->num_ticks_per_picture;
+    }
+
+    dav1d->inited = 1;
+
+    return 0;
+}
+
 static av_cold int libdav1d_init(AVCodecContext *c)
 {
     Libdav1dContext *dav1d = c->priv_data;
+    Dav1dSequenceHeader seq;
     Dav1dSettings s;
     int threads = (c->thread_count ? c->thread_count : av_cpu_count()) * 3 / 2;
     int res;
@@ -153,6 +205,16 @@ static av_cold int libdav1d_init(AVCodecContext *c)
     if (res < 0)
         return AVERROR(ENOMEM);
 
+    if (c->extradata && c->extradata_size) {
+        res = dav1d_parse_sequence_header(&seq, c->extradata, c->extradata_size);
+        if (res < 0)
+            return AVERROR_INVALIDDATA;
+
+        res = libdav1d_init_params(c, &seq);
+        if (res < 0)
+            return res;
+    }
+
     return 0;
 }
 
@@ -162,6 +224,7 @@ static void libdav1d_flush(AVCodecContext *c)
 
     dav1d_data_unref(&dav1d->data);
     dav1d_flush(dav1d->c);
+    dav1d->inited = 0;
 }
 
 static void libdav1d_data_free(const uint8_t *data, void *opaque) {
@@ -256,9 +319,14 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
     frame->linesize[1] = p->stride[1];
     frame->linesize[2] = p->stride[1];
 
-    c->profile = p->seq_hdr->profile;
-    c->level = ((p->seq_hdr->operating_points[0].major_level - 2) << 2)
-               | p->seq_hdr->operating_points[0].minor_level;
+    res = libdav1d_init_params(c, p->seq_hdr);
+    if (res < 0)
+        return res;
+
+    res = ff_decode_frame_props(c, frame);
+    if (res < 0)
+        return res;
+
     frame->width = p->p.w;
     frame->height = p->p.h;
     if (c->width != p->p.w || c->height != p->p.h) {
@@ -267,39 +335,11 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame)
             goto fail;
     }
 
-    switch (p->seq_hdr->chr) {
-    case DAV1D_CHR_VERTICAL:
-        frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_LEFT;
-        break;
-    case DAV1D_CHR_COLOCATED:
-        frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_TOPLEFT;
-        break;
-    }
-    frame->colorspace = c->colorspace = (enum AVColorSpace) p->seq_hdr->mtrx;
-    frame->color_primaries = c->color_primaries = (enum AVColorPrimaries) p->seq_hdr->pri;
-    frame->color_trc = c->color_trc = (enum AVColorTransferCharacteristic) p->seq_hdr->trc;
-    frame->color_range = c->color_range = p->seq_hdr->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
-
-    if (p->p.layout == DAV1D_PIXEL_LAYOUT_I444 &&
-        p->seq_hdr->mtrx == DAV1D_MC_IDENTITY &&
-        p->seq_hdr->pri  == DAV1D_COLOR_PRI_BT709 &&
-        p->seq_hdr->trc  == DAV1D_TRC_SRGB)
-        frame->format = c->pix_fmt = pix_fmt_rgb[p->seq_hdr->hbd];
-    else
-        frame->format = c->pix_fmt = pix_fmt[p->p.layout][p->seq_hdr->hbd];
-
     if (p->m.user_data.data)
         memcpy(&frame->reordered_opaque, p->m.user_data.data, sizeof(frame->reordered_opaque));
     else
         frame->reordered_opaque = AV_NOPTS_VALUE;
 
-    if (p->seq_hdr->num_units_in_tick && p->seq_hdr->time_scale) {
-        av_reduce(&c->framerate.den, &c->framerate.num,
-                  p->seq_hdr->num_units_in_tick, p->seq_hdr->time_scale, INT_MAX);
-        if (p->seq_hdr->equal_picture_interval)
-            c->ticks_per_frame = p->seq_hdr->num_ticks_per_picture;
-    }
-
     // match timestamps and packet size
     frame->pts = frame->best_effort_timestamp = p->m.timestamp;
 #if FF_API_PKT_PTS
-- 
2.26.2



More information about the ffmpeg-devel mailing list