nvcodec: Add AV1 decoder
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / nvcodec / gstnvvp8dec.c
1 /* GStreamer
2  * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/cuda/gstcudautils.h>
25
26 #include "gstnvvp8dec.h"
27 #include "gstnvdecoder.h"
28
29 #include <string.h>
30
31 GST_DEBUG_CATEGORY_STATIC (gst_nv_vp8_dec_debug);
32 #define GST_CAT_DEFAULT gst_nv_vp8_dec_debug
33
34 struct _GstNvVp8Dec
35 {
36   GstVp8Decoder parent;
37
38   GstVideoCodecState *output_state;
39
40   GstCudaContext *context;
41   GstNvDecoder *decoder;
42   CUVIDPICPARAMS params;
43
44   guint width, height;
45 };
46
47 struct _GstNvVp8DecClass
48 {
49   GstVp8DecoderClass parent_class;
50   guint cuda_device_id;
51 };
52
53 #define gst_nv_vp8_dec_parent_class parent_class
54
55 /**
56  * GstNvVp8Dec:
57  *
58  * Since: 1.20
59  */
60 G_DEFINE_TYPE (GstNvVp8Dec, gst_nv_vp8_dec, GST_TYPE_VP8_DECODER);
61
62 static void gst_nv_vp8_dec_set_context (GstElement * element,
63     GstContext * context);
64 static gboolean gst_nv_vp8_dec_open (GstVideoDecoder * decoder);
65 static gboolean gst_nv_vp8_dec_close (GstVideoDecoder * decoder);
66 static gboolean gst_nv_vp8_dec_negotiate (GstVideoDecoder * decoder);
67 static gboolean gst_nv_vp8_dec_decide_allocation (GstVideoDecoder *
68     decoder, GstQuery * query);
69 static gboolean gst_nv_vp8_dec_src_query (GstVideoDecoder * decoder,
70     GstQuery * query);
71
72 /* GstVp8Decoder */
73 static GstFlowReturn gst_nv_vp8_dec_new_sequence (GstVp8Decoder * decoder,
74     const GstVp8FrameHdr * frame_hdr, gint max_dpb_size);
75 static GstFlowReturn gst_nv_vp8_dec_new_picture (GstVp8Decoder * decoder,
76     GstVideoCodecFrame * frame, GstVp8Picture * picture);
77 static GstFlowReturn gst_nv_vp8_dec_decode_picture (GstVp8Decoder * decoder,
78     GstVp8Picture * picture, GstVp8Parser * parser);
79 static GstFlowReturn gst_nv_vp8_dec_output_picture (GstVp8Decoder *
80     decoder, GstVideoCodecFrame * frame, GstVp8Picture * picture);
81 static guint gst_nv_vp8_dec_get_preferred_output_delay (GstVp8Decoder * decoder,
82     gboolean is_live);
83
84 static void
85 gst_nv_vp8_dec_class_init (GstNvVp8DecClass * klass)
86 {
87   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
88   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
89   GstVp8DecoderClass *vp8decoder_class = GST_VP8_DECODER_CLASS (klass);
90
91   element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_set_context);
92
93   decoder_class->open = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_open);
94   decoder_class->close = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_close);
95   decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_negotiate);
96   decoder_class->decide_allocation =
97       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_decide_allocation);
98   decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_src_query);
99
100   vp8decoder_class->new_sequence =
101       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_new_sequence);
102   vp8decoder_class->new_picture =
103       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_new_picture);
104   vp8decoder_class->decode_picture =
105       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_decode_picture);
106   vp8decoder_class->output_picture =
107       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_output_picture);
108   vp8decoder_class->get_preferred_output_delay =
109       GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_get_preferred_output_delay);
110
111   GST_DEBUG_CATEGORY_INIT (gst_nv_vp8_dec_debug,
112       "nvvp8dec", 0, "NVIDIA VP8 Decoder");
113
114   gst_type_mark_as_plugin_api (GST_TYPE_NV_VP8_DEC, 0);
115 }
116
117 static void
118 gst_nv_vp8_dec_init (GstNvVp8Dec * self)
119 {
120 }
121
122 static void
123 gst_nv_vp8_dec_set_context (GstElement * element, GstContext * context)
124 {
125   GstNvVp8Dec *self = GST_NV_VP8_DEC (element);
126   GstNvVp8DecClass *klass = GST_NV_VP8_DEC_GET_CLASS (self);
127
128   GST_DEBUG_OBJECT (self, "set context %s",
129       gst_context_get_context_type (context));
130
131   if (gst_cuda_handle_set_context (element, context, klass->cuda_device_id,
132           &self->context)) {
133     goto done;
134   }
135
136   if (self->decoder)
137     gst_nv_decoder_handle_set_context (self->decoder, element, context);
138
139 done:
140   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
141 }
142
143 static gboolean
144 gst_nv_vp8_dec_open (GstVideoDecoder * decoder)
145 {
146   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
147   GstNvVp8DecClass *klass = GST_NV_VP8_DEC_GET_CLASS (self);
148
149   if (!gst_cuda_ensure_element_context (GST_ELEMENT (self),
150           klass->cuda_device_id, &self->context)) {
151     GST_ERROR_OBJECT (self, "Required element data is unavailable");
152     return FALSE;
153   }
154
155   self->decoder = gst_nv_decoder_new (self->context);
156   if (!self->decoder) {
157     GST_ERROR_OBJECT (self, "Failed to create decoder object");
158     gst_clear_object (&self->context);
159
160     return FALSE;
161   }
162
163   return TRUE;
164 }
165
166 static gboolean
167 gst_nv_vp8_dec_close (GstVideoDecoder * decoder)
168 {
169   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
170
171   g_clear_pointer (&self->output_state, gst_video_codec_state_unref);
172   gst_clear_object (&self->decoder);
173   gst_clear_object (&self->context);
174
175   return TRUE;
176 }
177
178 static gboolean
179 gst_nv_vp8_dec_negotiate (GstVideoDecoder * decoder)
180 {
181   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
182   GstVp8Decoder *vp8dec = GST_VP8_DECODER (decoder);
183
184   GST_DEBUG_OBJECT (self, "negotiate");
185
186   gst_nv_decoder_negotiate (self->decoder, decoder, vp8dec->input_state,
187       &self->output_state);
188
189   /* TODO: add support D3D11 memory */
190
191   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
192 }
193
194 static gboolean
195 gst_nv_vp8_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
196 {
197   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
198
199   if (!gst_nv_decoder_decide_allocation (self->decoder, decoder, query)) {
200     GST_WARNING_OBJECT (self, "Failed to handle decide allocation");
201     return FALSE;
202   }
203
204   return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
205       (decoder, query);
206 }
207
208 static gboolean
209 gst_nv_vp8_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
210 {
211   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
212
213   switch (GST_QUERY_TYPE (query)) {
214     case GST_QUERY_CONTEXT:
215       if (gst_cuda_handle_context_query (GST_ELEMENT (decoder), query,
216               self->context)) {
217         return TRUE;
218       } else if (self->decoder &&
219           gst_nv_decoder_handle_context_query (self->decoder, decoder, query)) {
220         return TRUE;
221       }
222       break;
223     default:
224       break;
225   }
226
227   return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
228 }
229
230 static GstFlowReturn
231 gst_nv_vp8_dec_new_sequence (GstVp8Decoder * decoder,
232     const GstVp8FrameHdr * frame_hdr, gint max_dpb_size)
233 {
234   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
235   gboolean modified = FALSE;
236
237   GST_LOG_OBJECT (self, "new sequence");
238
239   if (self->width != frame_hdr->width || self->height != frame_hdr->height) {
240     if (self->decoder) {
241       GST_INFO_OBJECT (self, "resolution changed %dx%d -> %dx%d",
242           self->width, self->height, frame_hdr->width, frame_hdr->height);
243     }
244
245     self->width = frame_hdr->width;
246     self->height = frame_hdr->height;
247
248     modified = TRUE;
249   }
250
251   if (modified || !gst_nv_decoder_is_configured (self->decoder)) {
252     GstVideoInfo info;
253
254     gst_video_info_set_format (&info,
255         GST_VIDEO_FORMAT_NV12, self->width, self->height);
256
257     if (!gst_nv_decoder_configure (self->decoder,
258             cudaVideoCodec_VP8, &info, self->width, self->height, 8,
259             max_dpb_size, FALSE)) {
260       GST_ERROR_OBJECT (self, "Failed to configure decoder");
261       return GST_FLOW_NOT_NEGOTIATED;
262     }
263
264     if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
265       GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
266       return GST_FLOW_NOT_NEGOTIATED;
267     }
268
269     memset (&self->params, 0, sizeof (CUVIDPICPARAMS));
270
271     self->params.PicWidthInMbs = GST_ROUND_UP_16 (self->width) >> 4;
272     self->params.FrameHeightInMbs = GST_ROUND_UP_16 (self->height) >> 4;
273
274     self->params.CodecSpecific.vp8.width = self->width;
275     self->params.CodecSpecific.vp8.height = self->height;
276   }
277
278   return GST_FLOW_OK;
279 }
280
281 static GstFlowReturn
282 gst_nv_vp8_dec_new_picture (GstVp8Decoder * decoder,
283     GstVideoCodecFrame * frame, GstVp8Picture * picture)
284 {
285   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
286   GstNvDecoderFrame *nv_frame;
287
288   nv_frame = gst_nv_decoder_new_frame (self->decoder);
289   if (!nv_frame) {
290     GST_ERROR_OBJECT (self, "No available decoder frame");
291     return GST_FLOW_ERROR;
292   }
293
294   GST_LOG_OBJECT (self,
295       "New decoder frame %p (index %d)", nv_frame, nv_frame->index);
296
297   gst_vp8_picture_set_user_data (picture,
298       nv_frame, (GDestroyNotify) gst_nv_decoder_frame_unref);
299
300   return GST_FLOW_OK;
301 }
302
303 static GstNvDecoderFrame *
304 gst_nv_vp8_dec_get_decoder_frame_from_picture (GstNvVp8Dec * self,
305     GstVp8Picture * picture)
306 {
307   GstNvDecoderFrame *frame;
308
309   frame = (GstNvDecoderFrame *) gst_vp8_picture_get_user_data (picture);
310
311   if (!frame)
312     GST_DEBUG_OBJECT (self, "current picture does not have decoder frame");
313
314   return frame;
315 }
316
317 static GstFlowReturn
318 gst_nv_vp8_dec_decode_picture (GstVp8Decoder * decoder,
319     GstVp8Picture * picture, GstVp8Parser * parser)
320 {
321   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
322   GstVp8FrameHdr *frame_hdr = &picture->frame_hdr;
323   GstNvDecoderFrame *frame;
324   GstNvDecoderFrame *other_frame;
325   guint offset = 0;
326
327   GST_LOG_OBJECT (self, "Decode picture, size %" G_GSIZE_FORMAT, picture->size);
328
329   frame = gst_nv_vp8_dec_get_decoder_frame_from_picture (self, picture);
330   if (!frame) {
331     GST_ERROR_OBJECT (self, "Decoder frame is unavailable");
332     return GST_FLOW_ERROR;
333   }
334
335   self->params.nBitstreamDataLen = picture->size;
336   self->params.pBitstreamData = picture->data;
337   self->params.nNumSlices = 1;
338   self->params.pSliceDataOffsets = &offset;
339
340   self->params.CurrPicIdx = frame->index;
341
342   self->params.CodecSpecific.vp8.first_partition_size =
343       frame_hdr->first_part_size;
344
345   if (decoder->alt_ref_picture) {
346     other_frame =
347         gst_nv_vp8_dec_get_decoder_frame_from_picture (self,
348         decoder->alt_ref_picture);
349     if (!other_frame) {
350       GST_ERROR_OBJECT (self, "Couldn't get decoder frame for AltRef");
351       return GST_FLOW_ERROR;
352     }
353
354     self->params.CodecSpecific.vp8.AltRefIdx = other_frame->index;
355   } else {
356     self->params.CodecSpecific.vp8.AltRefIdx = 0xff;
357   }
358
359   if (decoder->golden_ref_picture) {
360     other_frame =
361         gst_nv_vp8_dec_get_decoder_frame_from_picture (self,
362         decoder->golden_ref_picture);
363     if (!other_frame) {
364       GST_ERROR_OBJECT (self, "Couldn't get decoder frame for GoldenRef");
365       return GST_FLOW_ERROR;
366     }
367
368     self->params.CodecSpecific.vp8.GoldenRefIdx = other_frame->index;
369   } else {
370     self->params.CodecSpecific.vp8.GoldenRefIdx = 0xff;
371   }
372
373   if (decoder->last_picture) {
374     other_frame =
375         gst_nv_vp8_dec_get_decoder_frame_from_picture (self,
376         decoder->last_picture);
377     if (!other_frame) {
378       GST_ERROR_OBJECT (self, "Couldn't get decoder frame for LastRef");
379       return GST_FLOW_ERROR;
380     }
381
382     self->params.CodecSpecific.vp8.LastRefIdx = other_frame->index;
383   } else {
384     self->params.CodecSpecific.vp8.LastRefIdx = 0xff;
385   }
386
387   self->params.CodecSpecific.vp8.vp8_frame_tag.frame_type =
388       frame_hdr->key_frame ? 0 : 1;
389   self->params.CodecSpecific.vp8.vp8_frame_tag.version = frame_hdr->version;
390   self->params.CodecSpecific.vp8.vp8_frame_tag.show_frame =
391       frame_hdr->show_frame;
392   self->params.CodecSpecific.vp8.vp8_frame_tag.update_mb_segmentation_data =
393       parser->segmentation.segmentation_enabled ?
394       parser->segmentation.update_segment_feature_data : 0;
395
396   if (!gst_nv_decoder_decode_picture (self->decoder, &self->params))
397     return GST_FLOW_ERROR;
398
399   return GST_FLOW_OK;
400 }
401
402 static GstFlowReturn
403 gst_nv_vp8_dec_output_picture (GstVp8Decoder * decoder,
404     GstVideoCodecFrame * frame, GstVp8Picture * picture)
405 {
406   GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
407   GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
408   GstNvDecoderFrame *decoder_frame;
409
410   GST_LOG_OBJECT (self, "Outputting picture %p", picture);
411
412   decoder_frame = (GstNvDecoderFrame *) gst_vp8_picture_get_user_data (picture);
413   if (!decoder_frame) {
414     GST_ERROR_OBJECT (self, "No decoder frame in picture %p", picture);
415     goto error;
416   }
417
418   if (!gst_nv_decoder_finish_frame (self->decoder, vdec, decoder_frame,
419           &frame->output_buffer)) {
420     GST_ERROR_OBJECT (self, "Failed to handle output picture");
421     goto error;
422   }
423
424   gst_vp8_picture_unref (picture);
425
426   return gst_video_decoder_finish_frame (vdec, frame);
427
428 error:
429   gst_video_decoder_drop_frame (vdec, frame);
430   gst_vp8_picture_unref (picture);
431
432   return GST_FLOW_ERROR;
433 }
434
435 static guint
436 gst_nv_vp8_dec_get_preferred_output_delay (GstVp8Decoder * decoder,
437     gboolean is_live)
438 {
439   /* Prefer to zero latency for live pipeline */
440   if (is_live)
441     return 0;
442
443   /* NVCODEC SDK uses 4 frame delay for better throughput performance */
444   return 4;
445 }
446
447 typedef struct
448 {
449   GstCaps *sink_caps;
450   GstCaps *src_caps;
451   guint cuda_device_id;
452   gboolean is_default;
453 } GstNvVp8DecClassData;
454
455 static void
456 gst_nv_vp8_dec_subclass_init (gpointer klass, GstNvVp8DecClassData * cdata)
457 {
458   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
459   GstNvVp8DecClass *nvdec_class = (GstNvVp8DecClass *) (klass);
460   gchar *long_name;
461
462   if (cdata->is_default) {
463     long_name = g_strdup_printf ("NVDEC VP8 Stateless Decoder");
464   } else {
465     long_name = g_strdup_printf ("NVDEC VP8 Stateless Decoder with device %d",
466         cdata->cuda_device_id);
467   }
468
469   gst_element_class_set_metadata (element_class, long_name,
470       "Codec/Decoder/Video/Hardware",
471       "NVIDIA VP8 video decoder", "Seungha Yang <seungha@centricular.com>");
472   g_free (long_name);
473
474   gst_element_class_add_pad_template (element_class,
475       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
476           cdata->sink_caps));
477   gst_element_class_add_pad_template (element_class,
478       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
479           cdata->src_caps));
480
481   nvdec_class->cuda_device_id = cdata->cuda_device_id;
482
483   gst_caps_unref (cdata->sink_caps);
484   gst_caps_unref (cdata->src_caps);
485   g_free (cdata);
486 }
487
488 void
489 gst_nv_vp8_dec_register (GstPlugin * plugin, guint device_id, guint rank,
490     GstCaps * sink_caps, GstCaps * src_caps, gboolean is_primary)
491 {
492   GTypeQuery type_query;
493   GTypeInfo type_info = { 0, };
494   GType subtype;
495   gchar *type_name;
496   gchar *feature_name;
497   GstNvVp8DecClassData *cdata;
498   gboolean is_default = TRUE;
499
500   /**
501    * element-nvvp8sldec:
502    *
503    * Since: 1.20
504    */
505
506   cdata = g_new0 (GstNvVp8DecClassData, 1);
507   cdata->sink_caps = gst_caps_ref (sink_caps);
508   cdata->src_caps = gst_caps_ref (src_caps);
509   cdata->cuda_device_id = device_id;
510
511   g_type_query (GST_TYPE_NV_VP8_DEC, &type_query);
512   memset (&type_info, 0, sizeof (type_info));
513   type_info.class_size = type_query.class_size;
514   type_info.instance_size = type_query.instance_size;
515   type_info.class_init = (GClassInitFunc) gst_nv_vp8_dec_subclass_init;
516   type_info.class_data = cdata;
517
518   if (is_primary) {
519     type_name = g_strdup ("GstNvVP8StatelessPrimaryDec");
520     feature_name = g_strdup ("nvvp8dec");
521   } else {
522     type_name = g_strdup ("GstNvVP8StatelessDec");
523     feature_name = g_strdup ("nvvp8sldec");
524   }
525
526   if (g_type_from_name (type_name) != 0) {
527     g_free (type_name);
528     g_free (feature_name);
529     if (is_primary) {
530       type_name =
531           g_strdup_printf ("GstNvVP8StatelessPrimaryDevice%dDec", device_id);
532       feature_name = g_strdup_printf ("nvvp8device%ddec", device_id);
533     } else {
534       type_name = g_strdup_printf ("GstNvVP8StatelessDevice%dDec", device_id);
535       feature_name = g_strdup_printf ("nvvp8sldevice%ddec", device_id);
536     }
537
538     is_default = FALSE;
539   }
540
541   cdata->is_default = is_default;
542   subtype = g_type_register_static (GST_TYPE_NV_VP8_DEC,
543       type_name, &type_info, 0);
544
545   /* make lower rank than default device */
546   if (rank > 0 && !is_default)
547     rank--;
548
549   if (!gst_element_register (plugin, feature_name, rank, subtype))
550     GST_WARNING ("Failed to register plugin '%s'", type_name);
551
552   g_free (type_name);
553   g_free (feature_name);
554 }