demux: heif: send extradata with avif
[vlc.git] / modules / codec / dav1d.c
blob363e9e7a7828f36c8254b182cf49cf82acd28aad
1 /*****************************************************************************
2 * dav1d.c: dav1d decoder (AV1) module
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
6 * Authors: Adrien Maglo <magsoft@videolan.org>
7 * Based on aom.c by: Tristan Matthews <tmatth@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_timestamp_helper.h>
37 #include <errno.h>
38 #include <dav1d/dav1d.h>
40 #include "../packetizer/iso_color_tables.h"
42 /****************************************************************************
43 * Local prototypes
44 ****************************************************************************/
45 static int OpenDecoder(vlc_object_t *);
46 static void CloseDecoder(vlc_object_t *);
48 /*****************************************************************************
49 * Module descriptor
50 *****************************************************************************/
52 #define THREAD_FRAMES_TEXT N_("Frames Threads")
53 #define THREAD_FRAMES_LONGTEXT N_( "Max number of threads used for frame decoding, default 0=auto" )
54 #define THREAD_TILES_TEXT N_("Tiles Threads")
55 #define THREAD_TILES_LONGTEXT N_( "Max number of threads used for tile decoding, default 0=auto" )
58 vlc_module_begin ()
59 set_shortname("dav1d")
60 set_description(N_("Dav1d video decoder"))
61 set_capability("video decoder", 10000)
62 set_callbacks(OpenDecoder, CloseDecoder)
63 set_category(CAT_INPUT)
64 set_subcategory(SUBCAT_INPUT_VCODEC)
66 add_integer("dav1d-thread-frames", 0,
67 THREAD_FRAMES_TEXT, THREAD_FRAMES_LONGTEXT, false)
68 add_integer("dav1d-thread-tiles", 0,
69 THREAD_TILES_TEXT, THREAD_TILES_LONGTEXT, false)
70 vlc_module_end ()
72 /*****************************************************************************
73 * decoder_sys_t: libaom decoder descriptor
74 *****************************************************************************/
75 typedef struct
77 Dav1dSettings s;
78 Dav1dContext *c;
79 } decoder_sys_t;
81 static const struct
83 vlc_fourcc_t i_chroma;
84 enum Dav1dPixelLayout i_chroma_id;
85 uint8_t i_bitdepth;
86 } chroma_table[] =
88 {VLC_CODEC_GREY, DAV1D_PIXEL_LAYOUT_I400, 8},
89 {VLC_CODEC_I420, DAV1D_PIXEL_LAYOUT_I420, 8},
90 {VLC_CODEC_I422, DAV1D_PIXEL_LAYOUT_I422, 8},
91 {VLC_CODEC_I444, DAV1D_PIXEL_LAYOUT_I444, 8},
93 {VLC_CODEC_I420_10L, DAV1D_PIXEL_LAYOUT_I420, 10},
94 {VLC_CODEC_I422_10L, DAV1D_PIXEL_LAYOUT_I422, 10},
95 {VLC_CODEC_I444_10L, DAV1D_PIXEL_LAYOUT_I444, 10},
98 static vlc_fourcc_t FindVlcChroma(const Dav1dPicture *img)
100 for (unsigned int i = 0; i < ARRAY_SIZE(chroma_table); i++)
101 if (chroma_table[i].i_chroma_id == img->p.layout &&
102 chroma_table[i].i_bitdepth == img->p.bpc)
103 return chroma_table[i].i_chroma;
105 return 0;
108 static int NewPicture(Dav1dPicture *img, void *cookie)
110 decoder_t *dec = cookie;
112 video_format_t *v = &dec->fmt_out.video;
114 v->i_visible_width = img->p.w;
115 v->i_visible_height = img->p.h;
116 v->i_width = (img->p.w + 0x7F) & ~0x7F;
117 v->i_height = (img->p.h + 0x7F) & ~0x7F;
119 if( !v->i_sar_num || !v->i_sar_den )
121 v->i_sar_num = 1;
122 v->i_sar_den = 1;
125 if(dec->fmt_in.video.primaries == COLOR_PRIMARIES_UNDEF && img->seq_hdr)
127 v->primaries = iso_23001_8_cp_to_vlc_primaries(img->seq_hdr->pri);
128 v->transfer = iso_23001_8_tc_to_vlc_xfer(img->seq_hdr->trc);
129 v->space = iso_23001_8_mc_to_vlc_coeffs(img->seq_hdr->mtrx);
130 v->color_range = img->seq_hdr->color_range ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
133 v->projection_mode = dec->fmt_in.video.projection_mode;
134 v->multiview_mode = dec->fmt_in.video.multiview_mode;
135 v->pose = dec->fmt_in.video.pose;
136 dec->fmt_out.video.i_chroma = dec->fmt_out.i_codec = FindVlcChroma(img);
138 if (decoder_UpdateVideoFormat(dec) == VLC_SUCCESS)
140 picture_t *pic = decoder_NewPicture(dec);
141 if (likely(pic != NULL))
143 img->data[0] = pic->p[0].p_pixels;
144 img->stride[0] = pic->p[0].i_pitch;
145 img->data[1] = pic->p[1].p_pixels;
146 img->data[2] = pic->p[2].p_pixels;
147 assert(pic->p[1].i_pitch == pic->p[2].i_pitch);
148 img->stride[1] = pic->p[1].i_pitch;
149 img->allocator_data = pic;
151 return 0;
154 return -1;
157 static void FreePicture(Dav1dPicture *data, void *cookie)
159 picture_t *pic = data->allocator_data;
160 decoder_t *dec = cookie;
161 VLC_UNUSED(dec);
162 picture_Release(pic);
165 /****************************************************************************
166 * Flush: clears decoder between seeks
167 ****************************************************************************/
169 static void FlushDecoder(decoder_t *dec)
171 decoder_sys_t *p_sys = dec->p_sys;
172 dav1d_flush(p_sys->c);
175 static void release_block(const uint8_t *buf, void *b)
177 VLC_UNUSED(buf);
178 block_t *block = b;
179 block_Release(block);
182 /****************************************************************************
183 * Decode: the whole thing
184 ****************************************************************************/
185 static int Decode(decoder_t *dec, block_t *block)
187 decoder_sys_t *p_sys = dec->p_sys;
189 if (block && block->i_flags & (BLOCK_FLAG_CORRUPTED))
191 block_Release(block);
192 return VLCDEC_SUCCESS;
195 Dav1dData data;
196 Dav1dData *p_data = NULL;
198 if (block)
200 p_data = &data;
201 if (unlikely(dav1d_data_wrap(&data, block->p_buffer, block->i_buffer,
202 release_block, block) != 0))
204 block_Release(block);
205 return VLCDEC_ECRITICAL;
207 vlc_tick_t pts = block->i_pts == VLC_TICK_INVALID ? block->i_dts : block->i_pts;
208 p_data->m.timestamp = pts;
211 Dav1dPicture img = { 0 };
213 int i_ret = VLCDEC_SUCCESS;
214 int res;
215 do {
216 res = dav1d_send_data(p_sys->c, p_data);
217 if (res < 0 && res != -EAGAIN)
219 msg_Err(dec, "Decoder feed error %d!", res);
220 i_ret = VLC_EGENERIC;
221 break;
224 res = dav1d_get_picture(p_sys->c, &img);
225 if (res == 0)
227 picture_t *_pic = img.allocator_data;
228 picture_t *pic = picture_Clone(_pic);
229 if (unlikely(pic == NULL))
231 i_ret = VLC_EGENERIC;
232 picture_Release(_pic);
233 break;
235 pic->b_progressive = true; /* codec does not support interlacing */
236 pic->date = img.m.timestamp;
237 /* TODO udpate the color primaries and such */
238 decoder_QueueVideo(dec, pic);
239 dav1d_picture_unref(&img);
241 else if (res != -EAGAIN)
243 msg_Err(dec, "Decoder error %d!", res);
244 i_ret = VLC_EGENERIC;
245 break;
247 } while (res == 0 || (p_data && p_data->sz != 0));
250 return i_ret;
253 /*****************************************************************************
254 * OpenDecoder: probe the decoder
255 *****************************************************************************/
256 static int OpenDecoder(vlc_object_t *p_this)
258 decoder_t *dec = (decoder_t *)p_this;
260 if (dec->fmt_in.i_codec != VLC_CODEC_AV1)
261 return VLC_EGENERIC;
263 decoder_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof(*p_sys));
264 if (!p_sys)
265 return VLC_ENOMEM;
267 dav1d_default_settings(&p_sys->s);
268 p_sys->s.n_tile_threads = var_InheritInteger(p_this, "dav1d-thread-tiles");
269 if (p_sys->s.n_tile_threads == 0)
270 p_sys->s.n_tile_threads = VLC_CLIP(vlc_GetCPUCount(), 1, 4);
271 p_sys->s.n_frame_threads = var_InheritInteger(p_this, "dav1d-thread-frames");
272 if (p_sys->s.n_frame_threads == 0)
273 p_sys->s.n_frame_threads = __MAX(1, vlc_GetCPUCount());
274 p_sys->s.allocator.cookie = dec;
275 p_sys->s.allocator.alloc_picture_callback = NewPicture;
276 p_sys->s.allocator.release_picture_callback = FreePicture;
278 if (dav1d_open(&p_sys->c, &p_sys->s) < 0)
280 msg_Err(p_this, "Could not open the Dav1d decoder");
281 return VLC_EGENERIC;
284 msg_Dbg(p_this, "Using dav1d version %s with %d/%d frame/tile threads",
285 dav1d_version(), p_sys->s.n_frame_threads, p_sys->s.n_tile_threads);
287 dec->pf_decode = Decode;
288 dec->pf_flush = FlushDecoder;
289 dec->i_extra_picture_buffers = (p_sys->s.n_frame_threads - 1);
291 dec->fmt_out.video.i_width = dec->fmt_in.video.i_width;
292 dec->fmt_out.video.i_height = dec->fmt_in.video.i_height;
293 dec->fmt_out.i_codec = VLC_CODEC_I420;
294 dec->p_sys = p_sys;
296 if (dec->fmt_in.video.i_sar_num > 0 && dec->fmt_in.video.i_sar_den > 0) {
297 dec->fmt_out.video.i_sar_num = dec->fmt_in.video.i_sar_num;
298 dec->fmt_out.video.i_sar_den = dec->fmt_in.video.i_sar_den;
301 return VLC_SUCCESS;
304 /*****************************************************************************
305 * CloseDecoder: decoder destruction
306 *****************************************************************************/
307 static void CloseDecoder(vlc_object_t *p_this)
309 decoder_t *dec = (decoder_t *)p_this;
310 decoder_sys_t *p_sys = dec->p_sys;
312 /* Flush decoder */
313 FlushDecoder(dec);
315 dav1d_close(&p_sys->c);