• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2020 Nicolas Dufresne <nicolas.dufresne@collabora.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 "gstv4l2codecallocator.h"
25 #include "gstv4l2codech264dec.h"
26 #include "gstv4l2codecpool.h"
27 #include "gstv4l2format.h"
28 #include "linux/v4l2-controls.h"
29 
30 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
31 
32 #define V4L2_MIN_KERNEL_VER_MAJOR 5
33 #define V4L2_MIN_KERNEL_VER_MINOR 11
34 #define V4L2_MIN_KERNEL_VERSION KERNEL_VERSION(V4L2_MIN_KERNEL_VER_MAJOR, V4L2_MIN_KERNEL_VER_MINOR, 0)
35 
36 GST_DEBUG_CATEGORY_STATIC (v4l2_h264dec_debug);
37 #define GST_CAT_DEFAULT v4l2_h264dec_debug
38 
39 enum
40 {
41   PROP_0,
42   PROP_LAST = PROP_0
43 };
44 
45 static GstStaticPadTemplate sink_template =
46 GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
47     GST_PAD_SINK, GST_PAD_ALWAYS,
48     GST_STATIC_CAPS ("video/x-h264, "
49         "stream-format=(string) { avc, avc3, byte-stream }, "
50         "alignment=(string) au")
51     );
52 
53 static GstStaticPadTemplate src_template =
54 GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
55     GST_PAD_SRC, GST_PAD_ALWAYS,
56     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)));
57 
58 struct _GstV4l2CodecH264Dec
59 {
60   GstH264Decoder parent;
61   GstV4l2Decoder *decoder;
62   GstVideoCodecState *output_state;
63   GstVideoInfo vinfo;
64   gint display_width;
65   gint display_height;
66   gint coded_width;
67   gint coded_height;
68   guint bitdepth;
69   guint chroma_format_idc;
70   guint num_slices;
71   gboolean first_slice;
72 
73   GstV4l2CodecAllocator *sink_allocator;
74   GstV4l2CodecAllocator *src_allocator;
75   GstV4l2CodecPool *src_pool;
76   gint min_pool_size;
77   gboolean has_videometa;
78   gboolean need_negotiation;
79   gboolean interlaced;
80   gboolean need_sequence;
81   gboolean copy_frames;
82   gboolean scaling_matrix_present;
83 
84   struct v4l2_ctrl_h264_sps sps;
85   struct v4l2_ctrl_h264_pps pps;
86   struct v4l2_ctrl_h264_scaling_matrix scaling_matrix;
87   struct v4l2_ctrl_h264_decode_params decode_params;
88   struct v4l2_ctrl_h264_pred_weights pred_weight;
89   GArray *slice_params;
90 
91   enum v4l2_stateless_h264_decode_mode decode_mode;
92   enum v4l2_stateless_h264_start_code start_code;
93 
94   GstMemory *bitstream;
95   GstMapInfo bitstream_map;
96 };
97 
98 G_DEFINE_ABSTRACT_TYPE (GstV4l2CodecH264Dec, gst_v4l2_codec_h264_dec,
99     GST_TYPE_H264_DECODER);
100 
101 #define parent_class gst_v4l2_codec_h264_dec_parent_class
102 
103 static gboolean
is_frame_based(GstV4l2CodecH264Dec * self)104 is_frame_based (GstV4l2CodecH264Dec * self)
105 {
106   return self->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED;
107 }
108 
109 static gboolean
is_slice_based(GstV4l2CodecH264Dec * self)110 is_slice_based (GstV4l2CodecH264Dec * self)
111 {
112   return self->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED;
113 }
114 
115 static gboolean
needs_start_codes(GstV4l2CodecH264Dec * self)116 needs_start_codes (GstV4l2CodecH264Dec * self)
117 {
118   return self->start_code == V4L2_STATELESS_H264_START_CODE_ANNEX_B;
119 }
120 
121 static gboolean
gst_v4l2_decoder_h264_api_check(GstV4l2Decoder * decoder)122 gst_v4l2_decoder_h264_api_check (GstV4l2Decoder * decoder)
123 {
124   guint i, ret_size;
125   /* *INDENT-OFF* */
126   #define SET_ID(cid) .id = (cid), .name = #cid
127   struct
128   {
129     const gchar *name;
130     unsigned int id;
131     unsigned int size;
132     gboolean optional;
133   } controls[] = {
134     {
135       SET_ID (V4L2_CID_STATELESS_H264_SPS),
136       .size = sizeof(struct v4l2_ctrl_h264_sps),
137     }, {
138       SET_ID (V4L2_CID_STATELESS_H264_PPS),
139       .size = sizeof(struct v4l2_ctrl_h264_pps),
140     }, {
141       SET_ID (V4L2_CID_STATELESS_H264_SCALING_MATRIX),
142       .size = sizeof(struct v4l2_ctrl_h264_scaling_matrix),
143       .optional = TRUE,
144     }, {
145       SET_ID (V4L2_CID_STATELESS_H264_DECODE_PARAMS),
146       .size = sizeof(struct v4l2_ctrl_h264_decode_params),
147     }, {
148       SET_ID (V4L2_CID_STATELESS_H264_SLICE_PARAMS),
149       .size = sizeof(struct v4l2_ctrl_h264_slice_params),
150       .optional = TRUE,
151     }, {
152       SET_ID (V4L2_CID_STATELESS_H264_PRED_WEIGHTS),
153       .size = sizeof(struct v4l2_ctrl_h264_pred_weights),
154       .optional = TRUE,
155     }
156   };
157   #undef SET_ID
158   /* *INDENT-ON* */
159 
160   /*
161    * Compatibility check: make sure the pointer controls are
162    * the right size.
163    */
164   for (i = 0; i < G_N_ELEMENTS (controls); i++) {
165     gboolean control_found;
166 
167     control_found = gst_v4l2_decoder_query_control_size (decoder,
168         controls[i].id, &ret_size);
169 
170     if (!controls[i].optional && !control_found) {
171       GST_WARNING ("Driver is missing %s support.", controls[i].name);
172       return FALSE;
173     }
174 
175     if (control_found && ret_size != controls[i].size) {
176       GST_WARNING ("%s control size mismatch: got %d bytes but %d expected.",
177           controls[i].name, ret_size, controls[i].size);
178       return FALSE;
179     }
180   }
181 
182   return TRUE;
183 }
184 
185 static gboolean
gst_v4l2_codec_h264_dec_open(GstVideoDecoder * decoder)186 gst_v4l2_codec_h264_dec_open (GstVideoDecoder * decoder)
187 {
188   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
189 
190   /* *INDENT-OFF* */
191   struct v4l2_ext_control control[] = {
192     {
193       .id = V4L2_CID_STATELESS_H264_DECODE_MODE,
194     },
195     {
196       .id = V4L2_CID_STATELESS_H264_START_CODE,
197     },
198   };
199   /* *INDENT-ON* */
200 
201   if (!gst_v4l2_decoder_open (self->decoder)) {
202     GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE,
203         ("Failed to open H264 decoder"),
204         ("gst_v4l2_decoder_open() failed: %s", g_strerror (errno)));
205     return FALSE;
206   }
207 
208   if (!gst_v4l2_decoder_get_controls (self->decoder, control,
209           G_N_ELEMENTS (control))) {
210     GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE,
211         ("Driver did not report framing and start code method."),
212         ("gst_v4l2_decoder_get_controls() failed: %s", g_strerror (errno)));
213     return FALSE;
214   }
215 
216   self->decode_mode = control[0].value;
217   self->start_code = control[1].value;
218 
219   GST_INFO_OBJECT (self, "Opened H264 %s decoder %s",
220       is_frame_based (self) ? "frame based" : "slice based",
221       needs_start_codes (self) ? "using start-codes" : "without start-codes");
222   gst_h264_decoder_set_process_ref_pic_lists (GST_H264_DECODER (self),
223       is_slice_based (self));
224 
225   return TRUE;
226 }
227 
228 static gboolean
gst_v4l2_codec_h264_dec_close(GstVideoDecoder * decoder)229 gst_v4l2_codec_h264_dec_close (GstVideoDecoder * decoder)
230 {
231   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
232   gst_v4l2_decoder_close (self->decoder);
233   return TRUE;
234 }
235 
236 static void
gst_v4l2_codec_h264_dec_reset_allocation(GstV4l2CodecH264Dec * self)237 gst_v4l2_codec_h264_dec_reset_allocation (GstV4l2CodecH264Dec * self)
238 {
239   if (self->sink_allocator) {
240     gst_v4l2_codec_allocator_detach (self->sink_allocator);
241     g_clear_object (&self->sink_allocator);
242   }
243 
244   if (self->src_allocator) {
245     gst_v4l2_codec_allocator_detach (self->src_allocator);
246     g_clear_object (&self->src_allocator);
247     g_clear_object (&self->src_pool);
248   }
249 }
250 
251 static gboolean
gst_v4l2_codec_h264_dec_stop(GstVideoDecoder * decoder)252 gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder)
253 {
254   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
255 
256   gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
257   gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
258 
259   gst_v4l2_codec_h264_dec_reset_allocation (self);
260 
261   if (self->output_state)
262     gst_video_codec_state_unref (self->output_state);
263   self->output_state = NULL;
264 
265   return GST_VIDEO_DECODER_CLASS (parent_class)->stop (decoder);
266 }
267 
268 static gint
get_pixel_bitdepth(GstV4l2CodecH264Dec * self)269 get_pixel_bitdepth (GstV4l2CodecH264Dec * self)
270 {
271   gint depth;
272 
273   switch (self->chroma_format_idc) {
274     case 0:
275       /* 4:0:0 */
276       depth = self->bitdepth;
277       break;
278     case 1:
279       /* 4:2:0 */
280       depth = self->bitdepth + self->bitdepth / 2;
281       break;
282     case 2:
283       /* 4:2:2 */
284       depth = 2 * self->bitdepth;
285       break;
286     case 3:
287       /* 4:4:4 */
288       depth = 3 * self->bitdepth;
289       break;
290     default:
291       GST_WARNING_OBJECT (self, "Unsupported chroma format %i",
292           self->chroma_format_idc);
293       depth = 0;
294       break;
295   }
296 
297   return depth;
298 }
299 
300 static gboolean
gst_v4l2_codec_h264_dec_negotiate(GstVideoDecoder * decoder)301 gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
302 {
303   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
304   GstH264Decoder *h264dec = GST_H264_DECODER (decoder);
305   /* *INDENT-OFF* */
306   struct v4l2_ext_control control[] = {
307     {
308       .id = V4L2_CID_STATELESS_H264_SPS,
309       .ptr = &self->sps,
310       .size = sizeof (self->sps),
311     },
312   };
313   /* *INDENT-ON* */
314   GstCaps *filter, *caps;
315 
316   /* Ignore downstream renegotiation request. */
317   if (!self->need_negotiation)
318     return TRUE;
319   self->need_negotiation = FALSE;
320 
321   GST_DEBUG_OBJECT (self, "Negotiate");
322 
323   gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
324   gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
325 
326   gst_v4l2_codec_h264_dec_reset_allocation (self);
327 
328   if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_H264_SLICE,
329           self->coded_width, self->coded_height, get_pixel_bitdepth (self))) {
330     GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
331         ("Failed to configure H264 decoder"),
332         ("gst_v4l2_decoder_set_sink_fmt() failed: %s", g_strerror (errno)));
333     gst_v4l2_decoder_close (self->decoder);
334     return FALSE;
335   }
336 
337   if (!gst_v4l2_decoder_set_controls (self->decoder, NULL, control,
338           G_N_ELEMENTS (control))) {
339     GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
340         ("Driver does not support the selected stream."), (NULL));
341     return FALSE;
342   }
343 
344   filter = gst_v4l2_decoder_enum_src_formats (self->decoder);
345   if (!filter) {
346     GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
347         ("No supported decoder output formats"), (NULL));
348     return FALSE;
349   }
350   GST_DEBUG_OBJECT (self, "Supported output formats: %" GST_PTR_FORMAT, filter);
351 
352   caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
353   gst_caps_unref (filter);
354   GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
355 
356   if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
357     GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
358         ("Unsupported bitdepth/chroma format"),
359         ("No support for %ux%u %ubit chroma IDC %i", self->coded_width,
360             self->coded_height, self->bitdepth, self->chroma_format_idc));
361     gst_caps_unref (caps);
362     return FALSE;
363   }
364   gst_caps_unref (caps);
365 
366   if (self->output_state)
367     gst_video_codec_state_unref (self->output_state);
368 
369   self->output_state =
370       gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
371       self->vinfo.finfo->format, self->display_width,
372       self->display_height, h264dec->input_state);
373 
374   if (self->interlaced)
375     self->output_state->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
376 
377   self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
378 
379   if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
380     if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) {
381       GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
382           ("Could not enable the decoder driver."),
383           ("VIDIOC_STREAMON(SINK) failed: %s", g_strerror (errno)));
384       return FALSE;
385     }
386 
387     if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SRC)) {
388       GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
389           ("Could not enable the decoder driver."),
390           ("VIDIOC_STREAMON(SRC) failed: %s", g_strerror (errno)));
391       return FALSE;
392     }
393 
394     return TRUE;
395   }
396 
397   return FALSE;
398 }
399 
400 static gboolean
gst_v4l2_codec_h264_dec_decide_allocation(GstVideoDecoder * decoder,GstQuery * query)401 gst_v4l2_codec_h264_dec_decide_allocation (GstVideoDecoder * decoder,
402     GstQuery * query)
403 {
404   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
405   guint min = 0, num_bitstream;
406 
407   self->has_videometa = gst_query_find_allocation_meta (query,
408       GST_VIDEO_META_API_TYPE, NULL);
409 
410   g_clear_object (&self->src_pool);
411   g_clear_object (&self->src_allocator);
412 
413   if (gst_query_get_n_allocation_pools (query) > 0)
414     gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
415 
416   min = MAX (2, min);
417 
418   num_bitstream = 1 +
419       MAX (1, gst_v4l2_decoder_get_render_delay (self->decoder));
420 
421   self->sink_allocator = gst_v4l2_codec_allocator_new (self->decoder,
422       GST_PAD_SINK, num_bitstream);
423   if (!self->sink_allocator) {
424     GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
425         ("Not enough memory to allocate sink buffers."), (NULL));
426     return FALSE;
427   }
428 
429   self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder,
430       GST_PAD_SRC, self->min_pool_size + min + 4);
431   if (!self->src_allocator) {
432     GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
433         ("Not enough memory to allocate source buffers."), (NULL));
434     g_clear_object (&self->sink_allocator);
435     return FALSE;
436   }
437 
438   self->src_pool = gst_v4l2_codec_pool_new (self->src_allocator, &self->vinfo);
439 
440   /* Our buffer pool is internal, we will let the base class create a video
441    * pool, and use it if we are running out of buffers or if downstream does
442    * not support GstVideoMeta */
443   return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
444       (decoder, query);
445 }
446 
447 static void
gst_v4l2_codec_h264_dec_fill_sequence(GstV4l2CodecH264Dec * self,const GstH264SPS * sps)448 gst_v4l2_codec_h264_dec_fill_sequence (GstV4l2CodecH264Dec * self,
449     const GstH264SPS * sps)
450 {
451   gint i;
452 
453   /* *INDENT-OFF* */
454   self->sps = (struct v4l2_ctrl_h264_sps) {
455     .profile_idc = sps->profile_idc,
456     .constraint_set_flags = (sps->constraint_set0_flag)
457         | (sps->constraint_set1_flag << 1) | (sps->constraint_set2_flag << 2)
458         | (sps->constraint_set3_flag << 3) | (sps->constraint_set4_flag << 4)
459         | (sps->constraint_set5_flag << 5),
460     .level_idc = sps->level_idc,
461     .seq_parameter_set_id = sps->id,
462     .chroma_format_idc = sps->chroma_format_idc,
463     .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
464     .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
465     .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4,
466     .pic_order_cnt_type = sps->pic_order_cnt_type,
467     .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
468     .max_num_ref_frames = sps->num_ref_frames,
469     .num_ref_frames_in_pic_order_cnt_cycle = sps->num_ref_frames_in_pic_order_cnt_cycle,
470     .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
471     .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
472     .pic_width_in_mbs_minus1 = sps->pic_width_in_mbs_minus1,
473     .pic_height_in_map_units_minus1 = sps->pic_height_in_map_units_minus1,
474     .flags = (sps->separate_colour_plane_flag ? V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE : 0)
475         | (sps->qpprime_y_zero_transform_bypass_flag ? V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS : 0)
476         | (sps->delta_pic_order_always_zero_flag ? V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO : 0)
477         | (sps->gaps_in_frame_num_value_allowed_flag ? V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED : 0)
478         | (sps->frame_mbs_only_flag ? V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY : 0)
479         | (sps->mb_adaptive_frame_field_flag ? V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD : 0)
480         | (sps->direct_8x8_inference_flag ? V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE : 0),
481   };
482   /* *INDENT-ON* */
483 
484   for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
485     self->sps.offset_for_ref_frame[i] = sps->offset_for_ref_frame[i];
486 }
487 
488 static void
gst_v4l2_codec_h264_dec_fill_pps(GstV4l2CodecH264Dec * self,GstH264PPS * pps)489 gst_v4l2_codec_h264_dec_fill_pps (GstV4l2CodecH264Dec * self, GstH264PPS * pps)
490 {
491   /* *INDENT-OFF* */
492   self->pps = (struct v4l2_ctrl_h264_pps) {
493     .pic_parameter_set_id = pps->id,
494     .seq_parameter_set_id = pps->sequence->id,
495     .num_slice_groups_minus1 = pps->num_slice_groups_minus1,
496     .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_active_minus1,
497     .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_active_minus1,
498     .weighted_bipred_idc = pps->weighted_bipred_idc,
499     .pic_init_qp_minus26 = pps->pic_init_qp_minus26,
500     .pic_init_qs_minus26 = pps->pic_init_qs_minus26,
501     .chroma_qp_index_offset = pps->chroma_qp_index_offset,
502     .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset,
503     .flags = 0
504         | (pps->entropy_coding_mode_flag ? V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE : 0)
505         | (pps->pic_order_present_flag ? V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT : 0)
506         | (pps->weighted_pred_flag ? V4L2_H264_PPS_FLAG_WEIGHTED_PRED : 0)
507         | (pps->deblocking_filter_control_present_flag ? V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT : 0)
508         | (pps->constrained_intra_pred_flag ? V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED : 0)
509         | (pps->redundant_pic_cnt_present_flag ? V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT : 0)
510         | (pps->transform_8x8_mode_flag ? V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE : 0)
511         | (self->scaling_matrix_present ? V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT : 0),
512   };
513   /* *INDENT-ON* */
514 }
515 
516 static void
gst_v4l2_codec_h264_dec_fill_scaling_matrix(GstV4l2CodecH264Dec * self,GstH264PPS * pps)517 gst_v4l2_codec_h264_dec_fill_scaling_matrix (GstV4l2CodecH264Dec * self,
518     GstH264PPS * pps)
519 {
520   gint i, n;
521 
522   for (i = 0; i < G_N_ELEMENTS (pps->scaling_lists_4x4); i++)
523     gst_h264_quant_matrix_4x4_get_raster_from_zigzag (self->
524         scaling_matrix.scaling_list_4x4[i], pps->scaling_lists_4x4[i]);
525 
526   /* Avoid uninitialize data passed into ioctl() */
527   memset (self->scaling_matrix.scaling_list_8x8, 0,
528       sizeof (self->scaling_matrix.scaling_list_8x8));
529 
530   /* We need the first 2 entries (Y intra and Y inter for YCbCr 4:2:2 and
531    * less, and the full 6 entries for 4:4:4, see Table 7-2 of the spec for
532    * more details */
533   n = (pps->sequence->chroma_format_idc == 3) ? 6 : 2;
534   for (i = 0; i < n; i++)
535     gst_h264_quant_matrix_8x8_get_raster_from_zigzag (self->
536         scaling_matrix.scaling_list_8x8[i], pps->scaling_lists_8x8[i]);
537 }
538 
539 static void
gst_v4l2_codec_h264_dec_fill_decoder_params(GstV4l2CodecH264Dec * self,GstH264SliceHdr * slice_hdr,GstH264Picture * picture,GstH264Dpb * dpb)540 gst_v4l2_codec_h264_dec_fill_decoder_params (GstV4l2CodecH264Dec * self,
541     GstH264SliceHdr * slice_hdr, GstH264Picture * picture, GstH264Dpb * dpb)
542 {
543   GArray *refs = gst_h264_dpb_get_pictures_all (dpb);
544   gint i, entry_id = 0;
545 
546   /* *INDENT-OFF* */
547   self->decode_params = (struct v4l2_ctrl_h264_decode_params) {
548     .nal_ref_idc = picture->nal_ref_idc,
549     .frame_num = slice_hdr->frame_num,
550     .idr_pic_id = slice_hdr->idr_pic_id,
551     .pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb,
552     .delta_pic_order_cnt_bottom = slice_hdr->delta_pic_order_cnt_bottom,
553     .delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt[0],
554     .delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt[1],
555     .dec_ref_pic_marking_bit_size = slice_hdr->dec_ref_pic_marking.bit_size,
556     .pic_order_cnt_bit_size = slice_hdr->pic_order_cnt_bit_size,
557     .slice_group_change_cycle = slice_hdr->slice_group_change_cycle,
558     .flags = (picture->idr ? V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC : 0) |
559              (slice_hdr->field_pic_flag ? V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC : 0) |
560              (slice_hdr->bottom_field_flag ? V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD : 0),
561   };
562 
563   switch (picture->field) {
564     case GST_H264_PICTURE_FIELD_FRAME:
565       self->decode_params.top_field_order_cnt = picture->top_field_order_cnt;
566       self->decode_params.bottom_field_order_cnt =
567         picture->bottom_field_order_cnt;
568       break;
569     case GST_H264_PICTURE_FIELD_TOP_FIELD:
570       self->decode_params.top_field_order_cnt = picture->top_field_order_cnt;
571       self->decode_params.bottom_field_order_cnt = 0;
572       break;
573     case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
574       self->decode_params.top_field_order_cnt = 0;
575       self->decode_params.bottom_field_order_cnt =
576           picture->bottom_field_order_cnt;
577       break;
578   }
579 
580   for (i = 0; i < refs->len; i++) {
581     GstH264Picture *ref_pic = g_array_index (refs, GstH264Picture *, i);
582     gint pic_num = ref_pic->pic_num;
583     gint frame_num = ref_pic->frame_num;
584     struct v4l2_h264_dpb_entry *entry;
585 
586     /* Skip non-reference as they are not useful to decoding */
587     if (!GST_H264_PICTURE_IS_REF (ref_pic))
588       continue;
589 
590     /* The second field picture will be handled differently */
591     if (ref_pic->second_field)
592       continue;
593 
594     /* V4L2 uAPI uses pic_num for both PicNum and LongTermPicNum, and
595      * frame_num for both FrameNum and LongTermFrameIdx */
596     if (GST_H264_PICTURE_IS_LONG_TERM_REF (ref_pic)) {
597       pic_num = ref_pic->long_term_pic_num;
598       frame_num = ref_pic->long_term_frame_idx;
599     }
600 
601     entry = &self->decode_params.dpb[entry_id++];
602     *entry = (struct v4l2_h264_dpb_entry) {
603       /*
604        * The reference is multiplied by 1000 because it's was set as micro
605        * seconds and this TS is nanosecond.
606        */
607       .reference_ts = (guint64) ref_pic->system_frame_number * 1000,
608       .frame_num = frame_num,
609       .pic_num = pic_num,
610       .flags = V4L2_H264_DPB_ENTRY_FLAG_VALID
611           | (GST_H264_PICTURE_IS_REF (ref_pic) ? V4L2_H264_DPB_ENTRY_FLAG_ACTIVE : 0)
612           | (GST_H264_PICTURE_IS_LONG_TERM_REF (ref_pic) ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0),
613     };
614 
615     switch (ref_pic->field) {
616       case GST_H264_PICTURE_FIELD_FRAME:
617         entry->top_field_order_cnt = ref_pic->top_field_order_cnt;
618         entry->bottom_field_order_cnt = ref_pic->bottom_field_order_cnt;
619         entry->fields = V4L2_H264_FRAME_REF;
620         break;
621       case GST_H264_PICTURE_FIELD_TOP_FIELD:
622         entry->top_field_order_cnt = ref_pic->top_field_order_cnt;
623         entry->fields = V4L2_H264_TOP_FIELD_REF;
624 
625         if (ref_pic->other_field) {
626           entry->bottom_field_order_cnt =
627               ref_pic->other_field->bottom_field_order_cnt;
628           entry->fields |= V4L2_H264_BOTTOM_FIELD_REF;
629         } else {
630           entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD;
631         }
632         break;
633       case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
634         entry->bottom_field_order_cnt = ref_pic->bottom_field_order_cnt;
635         entry->fields = V4L2_H264_BOTTOM_FIELD_REF;
636 
637         if (ref_pic->other_field) {
638           entry->top_field_order_cnt =
639             ref_pic->other_field->top_field_order_cnt;
640           entry->fields |= V4L2_H264_TOP_FIELD_REF;
641         } else {
642           entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD;
643         }
644         break;
645     }
646   }
647   /* *INDENT-ON* */
648 
649   g_array_unref (refs);
650 }
651 
652 static void
gst_v4l2_codec_h264_dec_fill_pred_weight(GstV4l2CodecH264Dec * self,GstH264SliceHdr * slice_hdr)653 gst_v4l2_codec_h264_dec_fill_pred_weight (GstV4l2CodecH264Dec * self,
654     GstH264SliceHdr * slice_hdr)
655 {
656   gint i, j;
657 
658   /* *INDENT-OFF* */
659   self->pred_weight = (struct v4l2_ctrl_h264_pred_weights) {
660     .luma_log2_weight_denom = slice_hdr->pred_weight_table.luma_log2_weight_denom,
661     .chroma_log2_weight_denom = slice_hdr->pred_weight_table.chroma_log2_weight_denom,
662   };
663   /* *INDENT-ON* */
664 
665   for (i = 0; i <= slice_hdr->num_ref_idx_l0_active_minus1; i++) {
666     self->pred_weight.weight_factors[0].luma_weight[i] =
667         slice_hdr->pred_weight_table.luma_weight_l0[i];
668     self->pred_weight.weight_factors[0].luma_offset[i] =
669         slice_hdr->pred_weight_table.luma_offset_l0[i];
670   }
671 
672   if (slice_hdr->pps->sequence->chroma_array_type != 0) {
673     for (i = 0; i <= slice_hdr->num_ref_idx_l0_active_minus1; i++) {
674       for (j = 0; j < 2; j++) {
675         self->pred_weight.weight_factors[0].chroma_weight[i][j] =
676             slice_hdr->pred_weight_table.chroma_weight_l0[i][j];
677         self->pred_weight.weight_factors[0].chroma_offset[i][j] =
678             slice_hdr->pred_weight_table.chroma_offset_l0[i][j];
679       }
680     }
681   }
682 
683   /* Skip l1 if this is not a B-Frames. */
684   if (slice_hdr->type % 5 != GST_H264_B_SLICE)
685     return;
686 
687   for (i = 0; i <= slice_hdr->num_ref_idx_l1_active_minus1; i++) {
688     self->pred_weight.weight_factors[1].luma_weight[i] =
689         slice_hdr->pred_weight_table.luma_weight_l1[i];
690     self->pred_weight.weight_factors[1].luma_offset[i] =
691         slice_hdr->pred_weight_table.luma_offset_l1[i];
692   }
693 
694   if (slice_hdr->pps->sequence->chroma_array_type != 0) {
695     for (i = 0; i <= slice_hdr->num_ref_idx_l1_active_minus1; i++) {
696       for (j = 0; j < 2; j++) {
697         self->pred_weight.weight_factors[1].chroma_weight[i][j] =
698             slice_hdr->pred_weight_table.chroma_weight_l1[i][j];
699         self->pred_weight.weight_factors[1].chroma_offset[i][j] =
700             slice_hdr->pred_weight_table.chroma_offset_l1[i][j];
701       }
702     }
703   }
704 }
705 
706 static guint
get_slice_header_bit_size(GstH264Slice * slice)707 get_slice_header_bit_size (GstH264Slice * slice)
708 {
709   return 8 * slice->nalu.header_bytes + slice->header.header_size
710       - 8 * slice->header.n_emulation_prevention_bytes;
711 }
712 
713 static void
gst_v4l2_codec_h264_dec_fill_slice_params(GstV4l2CodecH264Dec * self,GstH264Slice * slice)714 gst_v4l2_codec_h264_dec_fill_slice_params (GstV4l2CodecH264Dec * self,
715     GstH264Slice * slice)
716 {
717   gint n = self->num_slices++;
718   gsize slice_size = slice->nalu.size;
719   struct v4l2_ctrl_h264_slice_params *params;
720 
721   /* Ensure array is large enough */
722   if (self->slice_params->len < self->num_slices)
723     g_array_set_size (self->slice_params, self->slice_params->len * 2);
724 
725   if (needs_start_codes (self))
726     slice_size += 3;
727 
728   /* *INDENT-OFF* */
729   params = &g_array_index (self->slice_params, struct v4l2_ctrl_h264_slice_params, n);
730   *params = (struct v4l2_ctrl_h264_slice_params) {
731     .header_bit_size = get_slice_header_bit_size (slice),
732     .first_mb_in_slice = slice->header.first_mb_in_slice,
733     .slice_type = slice->header.type % 5,
734     .colour_plane_id = slice->header.colour_plane_id,
735     .redundant_pic_cnt = slice->header.redundant_pic_cnt,
736     .cabac_init_idc = slice->header.cabac_init_idc,
737     .slice_qp_delta = slice->header.slice_qp_delta,
738     .slice_qs_delta = slice->header.slice_qs_delta,
739     .disable_deblocking_filter_idc = slice->header.disable_deblocking_filter_idc,
740     .slice_alpha_c0_offset_div2 = slice->header.slice_alpha_c0_offset_div2,
741     .slice_beta_offset_div2 = slice->header.slice_beta_offset_div2,
742     .num_ref_idx_l0_active_minus1 = slice->header.num_ref_idx_l0_active_minus1,
743     .num_ref_idx_l1_active_minus1 = slice->header.num_ref_idx_l1_active_minus1,
744     .flags = (slice->header.direct_spatial_mv_pred_flag ? V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED : 0) |
745              (slice->header.sp_for_switch_flag ? V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH : 0),
746   };
747   /* *INDENT-ON* */
748 }
749 
750 static guint8
lookup_dpb_index(struct v4l2_h264_dpb_entry dpb[16],GstH264Picture * ref_pic)751 lookup_dpb_index (struct v4l2_h264_dpb_entry dpb[16], GstH264Picture * ref_pic)
752 {
753   guint64 ref_ts;
754   gint i;
755 
756   /* Reference list may have wholes in case a ref is missing, we should mark
757    * the whole and avoid moving items in the list */
758   if (!ref_pic)
759     return 0xff;
760 
761   /* DPB entries only stores first field in a merged fashion */
762   if (ref_pic->second_field && ref_pic->other_field)
763     ref_pic = ref_pic->other_field;
764 
765   ref_ts = (guint64) ref_pic->system_frame_number * 1000;
766   for (i = 0; i < 16; i++) {
767     if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE
768         && dpb[i].reference_ts == ref_ts)
769       return i;
770   }
771 
772   return 0xff;
773 }
774 
775 static guint
_get_v4l2_fields_ref(GstH264Picture * ref_pic,gboolean merge)776 _get_v4l2_fields_ref (GstH264Picture * ref_pic, gboolean merge)
777 {
778   if (merge && ref_pic->other_field)
779     return V4L2_H264_FRAME_REF;
780 
781   switch (ref_pic->field) {
782     case GST_H264_PICTURE_FIELD_FRAME:
783       return V4L2_H264_FRAME_REF;
784       break;
785     case GST_H264_PICTURE_FIELD_TOP_FIELD:
786       return V4L2_H264_TOP_FIELD_REF;
787       break;
788     case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
789       return V4L2_H264_BOTTOM_FIELD_REF;
790       break;
791   }
792 
793   return V4L2_H264_FRAME_REF;
794 }
795 
796 static void
gst_v4l2_codec_h264_dec_fill_references(GstV4l2CodecH264Dec * self,gboolean cur_is_frame,GArray * ref_pic_list0,GArray * ref_pic_list1)797 gst_v4l2_codec_h264_dec_fill_references (GstV4l2CodecH264Dec * self,
798     gboolean cur_is_frame, GArray * ref_pic_list0, GArray * ref_pic_list1)
799 {
800   struct v4l2_ctrl_h264_slice_params *slice_params;
801   gint i;
802 
803   slice_params = &g_array_index (self->slice_params,
804       struct v4l2_ctrl_h264_slice_params, 0);
805 
806   memset (slice_params->ref_pic_list0, 0xff,
807       sizeof (slice_params->ref_pic_list0));
808   memset (slice_params->ref_pic_list1, 0xff,
809       sizeof (slice_params->ref_pic_list1));
810 
811   for (i = 0; i < ref_pic_list0->len; i++) {
812     GstH264Picture *ref_pic =
813         g_array_index (ref_pic_list0, GstH264Picture *, i);
814     slice_params->ref_pic_list0[i].index =
815         lookup_dpb_index (self->decode_params.dpb, ref_pic);
816     slice_params->ref_pic_list0[i].fields =
817         _get_v4l2_fields_ref (ref_pic, cur_is_frame);
818   }
819 
820   for (i = 0; i < ref_pic_list1->len; i++) {
821     GstH264Picture *ref_pic =
822         g_array_index (ref_pic_list1, GstH264Picture *, i);
823     slice_params->ref_pic_list1[i].index =
824         lookup_dpb_index (self->decode_params.dpb, ref_pic);
825     slice_params->ref_pic_list1[i].fields =
826         _get_v4l2_fields_ref (ref_pic, cur_is_frame);
827   }
828 }
829 
830 static GstFlowReturn
gst_v4l2_codec_h264_dec_new_sequence(GstH264Decoder * decoder,const GstH264SPS * sps,gint max_dpb_size)831 gst_v4l2_codec_h264_dec_new_sequence (GstH264Decoder * decoder,
832     const GstH264SPS * sps, gint max_dpb_size)
833 {
834   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
835   gint crop_width = sps->width;
836   gint crop_height = sps->height;
837   gboolean negotiation_needed = FALSE;
838   gboolean interlaced;
839 
840   if (self->vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN)
841     negotiation_needed = TRUE;
842 
843   /* TODO check if CREATE_BUFS is supported, and simply grow the pool */
844   if (self->min_pool_size < max_dpb_size) {
845     self->min_pool_size = max_dpb_size;
846     negotiation_needed = TRUE;
847   }
848 
849   if (sps->frame_cropping_flag) {
850     crop_width = sps->crop_rect_width;
851     crop_height = sps->crop_rect_height;
852   }
853 
854   /* TODO Check if current buffers are large enough, and reuse them */
855   if (self->display_width != crop_width || self->display_height != crop_height
856       || self->coded_width != sps->width || self->coded_height != sps->height) {
857     self->display_width = crop_width;
858     self->display_height = crop_height;
859     self->coded_width = sps->width;
860     self->coded_height = sps->height;
861     negotiation_needed = TRUE;
862     GST_INFO_OBJECT (self, "Resolution changed to %dx%d (%ix%i)",
863         self->display_width, self->display_height,
864         self->coded_width, self->coded_height);
865   }
866 
867   interlaced = !sps->frame_mbs_only_flag;
868   if (self->interlaced != interlaced) {
869     self->interlaced = interlaced;
870 
871     negotiation_needed = TRUE;
872     GST_INFO_OBJECT (self, "Interlaced mode changed to %d", interlaced);
873   }
874 
875   if (self->bitdepth != sps->bit_depth_luma_minus8 + 8) {
876     self->bitdepth = sps->bit_depth_luma_minus8 + 8;
877     negotiation_needed = TRUE;
878     GST_INFO_OBJECT (self, "Bitdepth changed to %u", self->bitdepth);
879   }
880 
881   if (self->chroma_format_idc != sps->chroma_format_idc) {
882     self->chroma_format_idc = sps->chroma_format_idc;
883     negotiation_needed = TRUE;
884     GST_INFO_OBJECT (self, "Chroma format changed to %i",
885         self->chroma_format_idc);
886   }
887 
888   gst_v4l2_codec_h264_dec_fill_sequence (self, sps);
889   self->need_sequence = TRUE;
890 
891   if (negotiation_needed) {
892     self->need_negotiation = TRUE;
893     if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
894       GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
895       return GST_FLOW_NOT_NEGOTIATED;
896     }
897   }
898 
899   /* Check if we can zero-copy buffers */
900   if (!self->has_videometa) {
901     GstVideoInfo ref_vinfo;
902     gint i;
903 
904     gst_video_info_set_format (&ref_vinfo, GST_VIDEO_INFO_FORMAT (&self->vinfo),
905         self->display_width, self->display_height);
906 
907     for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->vinfo); i++) {
908       if (self->vinfo.stride[i] != ref_vinfo.stride[i] ||
909           self->vinfo.offset[i] != ref_vinfo.offset[i]) {
910         GST_WARNING_OBJECT (self,
911             "GstVideoMeta support required, copying frames.");
912         self->copy_frames = TRUE;
913         break;
914       }
915     }
916   } else {
917     self->copy_frames = FALSE;
918   }
919 
920   return GST_FLOW_OK;
921 }
922 
923 static gboolean
gst_v4l2_codec_h264_dec_ensure_bitstream(GstV4l2CodecH264Dec * self)924 gst_v4l2_codec_h264_dec_ensure_bitstream (GstV4l2CodecH264Dec * self)
925 {
926   if (self->bitstream)
927     goto done;
928 
929   self->bitstream = gst_v4l2_codec_allocator_alloc (self->sink_allocator);
930 
931   if (!self->bitstream) {
932     GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
933         ("Not enough memory to decode H264 stream."), (NULL));
934     return FALSE;
935   }
936 
937   if (!gst_memory_map (self->bitstream, &self->bitstream_map, GST_MAP_WRITE)) {
938     GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
939         ("Could not access bitstream memory for writing"), (NULL));
940     g_clear_pointer (&self->bitstream, gst_memory_unref);
941     return FALSE;
942   }
943 
944 done:
945   /* We use this field to track how much we have written */
946   self->bitstream_map.size = 0;
947 
948   return TRUE;
949 }
950 
951 static GstFlowReturn
gst_v4l2_codec_h264_dec_start_picture(GstH264Decoder * decoder,GstH264Picture * picture,GstH264Slice * slice,GstH264Dpb * dpb)952 gst_v4l2_codec_h264_dec_start_picture (GstH264Decoder * decoder,
953     GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb)
954 {
955   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
956 
957   /* FIXME base class should not call us if negotiation failed */
958   if (!self->sink_allocator)
959     return GST_FLOW_NOT_NEGOTIATED;
960 
961   if (!gst_v4l2_codec_h264_dec_ensure_bitstream (self))
962     return GST_FLOW_ERROR;
963 
964   /*
965    * Scaling matrix is present if there's one provided
966    * by either the SPS or the PPS. This flag must be
967    * set to true or false, before filling the PPS V4L2 control.
968    */
969   self->scaling_matrix_present =
970       slice->header.pps->sequence->scaling_matrix_present_flag ||
971       slice->header.pps->pic_scaling_matrix_present_flag;
972 
973   gst_v4l2_codec_h264_dec_fill_pps (self, slice->header.pps);
974 
975   if (self->scaling_matrix_present)
976     gst_v4l2_codec_h264_dec_fill_scaling_matrix (self, slice->header.pps);
977 
978   gst_v4l2_codec_h264_dec_fill_decoder_params (self, &slice->header, picture,
979       dpb);
980 
981   self->first_slice = TRUE;
982 
983   return GST_FLOW_OK;
984 }
985 
986 static gboolean
gst_v4l2_codec_h264_dec_copy_output_buffer(GstV4l2CodecH264Dec * self,GstVideoCodecFrame * codec_frame)987 gst_v4l2_codec_h264_dec_copy_output_buffer (GstV4l2CodecH264Dec * self,
988     GstVideoCodecFrame * codec_frame)
989 {
990   GstVideoFrame src_frame;
991   GstVideoFrame dest_frame;
992   GstVideoInfo dest_vinfo;
993   GstBuffer *buffer;
994 
995   gst_video_info_set_format (&dest_vinfo, GST_VIDEO_INFO_FORMAT (&self->vinfo),
996       self->display_width, self->display_height);
997 
998   buffer = gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
999   if (!buffer)
1000     goto fail;
1001 
1002   if (!gst_video_frame_map (&src_frame, &self->vinfo,
1003           codec_frame->output_buffer, GST_MAP_READ))
1004     goto fail;
1005 
1006   if (!gst_video_frame_map (&dest_frame, &dest_vinfo, buffer, GST_MAP_WRITE)) {
1007     gst_video_frame_unmap (&dest_frame);
1008     goto fail;
1009   }
1010 
1011   /* gst_video_frame_copy can crop this, but does not know, so let make it
1012    * think it's all right */
1013   GST_VIDEO_INFO_WIDTH (&src_frame.info) = self->display_width;
1014   GST_VIDEO_INFO_HEIGHT (&src_frame.info) = self->display_height;
1015 
1016   if (!gst_video_frame_copy (&dest_frame, &src_frame)) {
1017     gst_video_frame_unmap (&src_frame);
1018     gst_video_frame_unmap (&dest_frame);
1019     goto fail;
1020   }
1021 
1022   gst_video_frame_unmap (&src_frame);
1023   gst_video_frame_unmap (&dest_frame);
1024   gst_buffer_replace (&codec_frame->output_buffer, buffer);
1025   gst_buffer_unref (buffer);
1026 
1027   return TRUE;
1028 
1029 fail:
1030   GST_ERROR_OBJECT (self, "Failed copy output buffer.");
1031   return FALSE;
1032 }
1033 
1034 static GstFlowReturn
gst_v4l2_codec_h264_dec_output_picture(GstH264Decoder * decoder,GstVideoCodecFrame * frame,GstH264Picture * picture)1035 gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder,
1036     GstVideoCodecFrame * frame, GstH264Picture * picture)
1037 {
1038   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1039   GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
1040   GstV4l2Request *request = gst_h264_picture_get_user_data (picture);
1041   gint ret;
1042 
1043   GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number);
1044 
1045   ret = gst_v4l2_request_set_done (request);
1046   if (ret == 0) {
1047     GST_ELEMENT_ERROR (self, STREAM, DECODE,
1048         ("Decoding frame %u took too long", picture->system_frame_number),
1049         (NULL));
1050     goto error;
1051   } else if (ret < 0) {
1052     GST_ELEMENT_ERROR (self, STREAM, DECODE,
1053         ("Decoding request failed: %s", g_strerror (errno)), (NULL));
1054     goto error;
1055   }
1056   g_return_val_if_fail (frame->output_buffer, GST_FLOW_ERROR);
1057 
1058   if (gst_v4l2_request_failed (request)) {
1059     GST_ELEMENT_ERROR (self, STREAM, DECODE,
1060         ("Failed to decode frame %u", picture->system_frame_number), (NULL));
1061     goto error;
1062   }
1063 
1064   /* Hold on reference buffers for the rest of the picture lifetime */
1065   gst_h264_picture_set_user_data (picture,
1066       gst_buffer_ref (frame->output_buffer), (GDestroyNotify) gst_buffer_unref);
1067 
1068   if (self->copy_frames)
1069     gst_v4l2_codec_h264_dec_copy_output_buffer (self, frame);
1070 
1071   gst_h264_picture_unref (picture);
1072 
1073   return gst_video_decoder_finish_frame (vdec, frame);
1074 
1075 error:
1076   gst_video_decoder_drop_frame (vdec, frame);
1077   gst_h264_picture_unref (picture);
1078 
1079   return GST_FLOW_ERROR;
1080 }
1081 
1082 static void
gst_v4l2_codec_h264_dec_reset_picture(GstV4l2CodecH264Dec * self)1083 gst_v4l2_codec_h264_dec_reset_picture (GstV4l2CodecH264Dec * self)
1084 {
1085   if (self->bitstream) {
1086     if (self->bitstream_map.memory)
1087       gst_memory_unmap (self->bitstream, &self->bitstream_map);
1088     g_clear_pointer (&self->bitstream, gst_memory_unref);
1089     self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT;
1090   }
1091 
1092   self->num_slices = 0;
1093 }
1094 
1095 static gboolean
gst_v4l2_codec_h264_dec_ensure_output_buffer(GstV4l2CodecH264Dec * self,GstVideoCodecFrame * frame)1096 gst_v4l2_codec_h264_dec_ensure_output_buffer (GstV4l2CodecH264Dec * self,
1097     GstVideoCodecFrame * frame)
1098 {
1099   GstBuffer *buffer;
1100   GstFlowReturn flow_ret;
1101 
1102   if (frame->output_buffer)
1103     return TRUE;
1104 
1105   flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool),
1106       &buffer, NULL);
1107   if (flow_ret != GST_FLOW_OK) {
1108     if (flow_ret == GST_FLOW_FLUSHING)
1109       GST_DEBUG_OBJECT (self, "Frame decoding aborted, we are flushing.");
1110     else
1111       GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
1112           ("No more picture buffer available."), (NULL));
1113     return FALSE;
1114   }
1115 
1116   frame->output_buffer = buffer;
1117   return TRUE;
1118 }
1119 
1120 static gboolean
gst_v4l2_codec_h264_dec_submit_bitstream(GstV4l2CodecH264Dec * self,GstH264Picture * picture,guint flags)1121 gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self,
1122     GstH264Picture * picture, guint flags)
1123 {
1124   GstV4l2Request *prev_request, *request = NULL;
1125   gsize bytesused;
1126   gboolean ret = FALSE;
1127   guint count = 0;
1128 
1129   /* *INDENT-OFF* */
1130   /* Reserve space for controls */
1131   struct v4l2_ext_control control[] = {
1132     { }, /* SPS */
1133     { }, /* PPS */
1134     { }, /* DECODE_PARAMS */
1135     { }, /* SLICE_PARAMS */
1136     { }, /* SCALING_MATRIX */
1137     { }, /* PRED_WEIGHTS */
1138   };
1139   /* *INDENT-ON* */
1140 
1141   prev_request = gst_h264_picture_get_user_data (picture);
1142 
1143   bytesused = self->bitstream_map.size;
1144   gst_memory_unmap (self->bitstream, &self->bitstream_map);
1145   self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT;
1146   gst_memory_resize (self->bitstream, 0, bytesused);
1147 
1148   if (prev_request) {
1149     request = gst_v4l2_decoder_alloc_sub_request (self->decoder, prev_request,
1150         self->bitstream);
1151   } else {
1152     GstVideoCodecFrame *frame;
1153 
1154     frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
1155         picture->system_frame_number);
1156     g_return_val_if_fail (frame, FALSE);
1157 
1158     if (!gst_v4l2_codec_h264_dec_ensure_output_buffer (self, frame))
1159       goto done;
1160 
1161     request = gst_v4l2_decoder_alloc_request (self->decoder,
1162         picture->system_frame_number, self->bitstream, frame->output_buffer);
1163 
1164     gst_video_codec_frame_unref (frame);
1165   }
1166 
1167   if (!request) {
1168     GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
1169         ("Failed to allocate a media request object."), (NULL));
1170     goto done;
1171   }
1172 
1173   if (self->need_sequence) {
1174     control[count].id = V4L2_CID_STATELESS_H264_SPS;
1175     control[count].ptr = &self->sps;
1176     control[count].size = sizeof (self->sps);
1177     count++;
1178     self->need_sequence = FALSE;
1179   }
1180 
1181   if (self->first_slice) {
1182     control[count].id = V4L2_CID_STATELESS_H264_PPS;
1183     control[count].ptr = &self->pps;
1184     control[count].size = sizeof (self->pps);
1185     count++;
1186 
1187     if (self->scaling_matrix_present) {
1188       control[count].id = V4L2_CID_STATELESS_H264_SCALING_MATRIX;
1189       control[count].ptr = &self->scaling_matrix;
1190       control[count].size = sizeof (self->scaling_matrix);
1191       count++;
1192     }
1193 
1194     control[count].id = V4L2_CID_STATELESS_H264_DECODE_PARAMS;
1195     control[count].ptr = &self->decode_params;
1196     control[count].size = sizeof (self->decode_params);
1197     count++;
1198 
1199     self->first_slice = FALSE;
1200   }
1201 
1202   /* If it's not slice-based then it doesn't support per-slice controls. */
1203   if (is_slice_based (self)) {
1204     control[count].id = V4L2_CID_STATELESS_H264_SLICE_PARAMS;
1205     control[count].ptr = self->slice_params->data;
1206     control[count].size = g_array_get_element_size (self->slice_params)
1207         * self->num_slices;
1208     count++;
1209 
1210     control[count].id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS;
1211     control[count].ptr = &self->pred_weight;
1212     control[count].size = sizeof (self->pred_weight);
1213     count++;
1214   }
1215 
1216   if (!gst_v4l2_decoder_set_controls (self->decoder, request, control, count)) {
1217     GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
1218         ("Driver did not accept the bitstream parameters."), (NULL));
1219     goto done;
1220   }
1221 
1222   if (!gst_v4l2_request_queue (request, flags)) {
1223     GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
1224         ("Driver did not accept the decode request."), (NULL));
1225     goto done;
1226   }
1227 
1228   gst_h264_picture_set_user_data (picture, g_steal_pointer (&request),
1229       (GDestroyNotify) gst_v4l2_request_unref);
1230   ret = TRUE;
1231 
1232 done:
1233   if (request)
1234     gst_v4l2_request_unref (request);
1235 
1236   gst_v4l2_codec_h264_dec_reset_picture (self);
1237 
1238   return ret;
1239 }
1240 
1241 static GstFlowReturn
gst_v4l2_codec_h264_dec_decode_slice(GstH264Decoder * decoder,GstH264Picture * picture,GstH264Slice * slice,GArray * ref_pic_list0,GArray * ref_pic_list1)1242 gst_v4l2_codec_h264_dec_decode_slice (GstH264Decoder * decoder,
1243     GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
1244     GArray * ref_pic_list1)
1245 {
1246   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1247   gsize sc_off = 0;
1248   gsize nal_size;
1249   guint8 *bitstream_data;
1250 
1251   if (is_slice_based (self)) {
1252     if (self->bitstream_map.size) {
1253       /* In slice mode, we submit the pending slice asking the accelerator to
1254        * hold on the picture */
1255       if (!gst_v4l2_codec_h264_dec_submit_bitstream (self, picture,
1256               V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF)
1257           || !gst_v4l2_codec_h264_dec_ensure_bitstream (self))
1258         return GST_FLOW_ERROR;
1259     }
1260 
1261     gst_v4l2_codec_h264_dec_fill_slice_params (self, slice);
1262     gst_v4l2_codec_h264_dec_fill_pred_weight (self, &slice->header);
1263     gst_v4l2_codec_h264_dec_fill_references (self,
1264         GST_H264_PICTURE_IS_FRAME (picture), ref_pic_list0, ref_pic_list1);
1265   }
1266 
1267   bitstream_data = self->bitstream_map.data + self->bitstream_map.size;
1268 
1269   if (needs_start_codes (self))
1270     sc_off = 3;
1271   nal_size = sc_off + slice->nalu.size;
1272 
1273   if (self->bitstream_map.size + nal_size > self->bitstream_map.maxsize) {
1274     GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT,
1275         ("Not enough space to send all slice of an H264 frame."), (NULL));
1276     return GST_FLOW_ERROR;
1277   }
1278 
1279   if (needs_start_codes (self)) {
1280     bitstream_data[0] = 0x00;
1281     bitstream_data[1] = 0x00;
1282     bitstream_data[2] = 0x01;
1283   }
1284 
1285   memcpy (bitstream_data + sc_off, slice->nalu.data + slice->nalu.offset,
1286       slice->nalu.size);
1287   self->bitstream_map.size += nal_size;
1288 
1289   return GST_FLOW_OK;
1290 }
1291 
1292 static GstFlowReturn
gst_v4l2_codec_h264_dec_end_picture(GstH264Decoder * decoder,GstH264Picture * picture)1293 gst_v4l2_codec_h264_dec_end_picture (GstH264Decoder * decoder,
1294     GstH264Picture * picture)
1295 {
1296   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1297   guint flags = 0;
1298 
1299   /* Hold on the output frame if this is first field of a pair */
1300   if (picture->field != GST_H264_PICTURE_FIELD_FRAME && !picture->second_field)
1301     flags = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
1302 
1303   if (!gst_v4l2_codec_h264_dec_submit_bitstream (self, picture, flags))
1304     return GST_FLOW_ERROR;
1305 
1306   return GST_FLOW_OK;
1307 }
1308 
1309 static GstFlowReturn
gst_v4l2_codec_h264_dec_new_field_picture(GstH264Decoder * decoder,const GstH264Picture * first_field,GstH264Picture * second_field)1310 gst_v4l2_codec_h264_dec_new_field_picture (GstH264Decoder * decoder,
1311     const GstH264Picture * first_field, GstH264Picture * second_field)
1312 {
1313   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1314   GstV4l2Request *request =
1315       gst_h264_picture_get_user_data ((GstH264Picture *) first_field);
1316 
1317   if (!request) {
1318     GST_WARNING_OBJECT (self,
1319         "First picture does not have an associated request");
1320     return GST_FLOW_OK;
1321   }
1322 
1323   GST_DEBUG_OBJECT (self, "Assigned request %p to second field.", request);
1324 
1325   /* Associate the previous request with the new picture so that
1326    * submit_bitstream can create sub-request */
1327   gst_h264_picture_set_user_data (second_field, gst_v4l2_request_ref (request),
1328       (GDestroyNotify) gst_v4l2_request_unref);
1329 
1330   return GST_FLOW_OK;
1331 }
1332 
1333 static guint
gst_v4l2_codec_h264_dec_get_preferred_output_delay(GstH264Decoder * decoder,gboolean live)1334 gst_v4l2_codec_h264_dec_get_preferred_output_delay (GstH264Decoder * decoder,
1335     gboolean live)
1336 {
1337   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1338   guint delay;
1339 
1340   if (live)
1341     delay = 0;
1342   else
1343     /* Just one for now, perhaps we can make this configurable in the future. */
1344     delay = 1;
1345 
1346   gst_v4l2_decoder_set_render_delay (self->decoder, delay);
1347 
1348   return delay;
1349 }
1350 
1351 static void
gst_v4l2_codec_h264_dec_set_flushing(GstV4l2CodecH264Dec * self,gboolean flushing)1352 gst_v4l2_codec_h264_dec_set_flushing (GstV4l2CodecH264Dec * self,
1353     gboolean flushing)
1354 {
1355   if (self->sink_allocator)
1356     gst_v4l2_codec_allocator_set_flushing (self->sink_allocator, flushing);
1357   if (self->src_allocator)
1358     gst_v4l2_codec_allocator_set_flushing (self->src_allocator, flushing);
1359 }
1360 
1361 static gboolean
gst_v4l2_codec_h264_dec_flush(GstVideoDecoder * decoder)1362 gst_v4l2_codec_h264_dec_flush (GstVideoDecoder * decoder)
1363 {
1364   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1365 
1366   GST_DEBUG_OBJECT (self, "Flushing decoder state.");
1367 
1368   gst_v4l2_decoder_flush (self->decoder);
1369   gst_v4l2_codec_h264_dec_set_flushing (self, FALSE);
1370 
1371   return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder);
1372 }
1373 
1374 static gboolean
gst_v4l2_codec_h264_dec_sink_event(GstVideoDecoder * decoder,GstEvent * event)1375 gst_v4l2_codec_h264_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
1376 {
1377   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
1378 
1379   switch (GST_EVENT_TYPE (event)) {
1380     case GST_EVENT_FLUSH_START:
1381       GST_DEBUG_OBJECT (self, "flush start");
1382       gst_v4l2_codec_h264_dec_set_flushing (self, TRUE);
1383       break;
1384     default:
1385       break;
1386   }
1387 
1388   return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
1389 }
1390 
1391 static GstStateChangeReturn
gst_v4l2_codec_h264_dec_change_state(GstElement * element,GstStateChange transition)1392 gst_v4l2_codec_h264_dec_change_state (GstElement * element,
1393     GstStateChange transition)
1394 {
1395   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (element);
1396 
1397   if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
1398     gst_v4l2_codec_h264_dec_set_flushing (self, TRUE);
1399 
1400   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1401 }
1402 
1403 static void
gst_v4l2_codec_h264_dec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1404 gst_v4l2_codec_h264_dec_set_property (GObject * object, guint prop_id,
1405     const GValue * value, GParamSpec * pspec)
1406 {
1407   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (object);
1408   GObject *dec = G_OBJECT (self->decoder);
1409 
1410   switch (prop_id) {
1411     default:
1412       gst_v4l2_decoder_set_property (dec, prop_id - PROP_LAST, value, pspec);
1413       break;
1414   }
1415 }
1416 
1417 static void
gst_v4l2_codec_h264_dec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1418 gst_v4l2_codec_h264_dec_get_property (GObject * object, guint prop_id,
1419     GValue * value, GParamSpec * pspec)
1420 {
1421   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (object);
1422   GObject *dec = G_OBJECT (self->decoder);
1423 
1424   switch (prop_id) {
1425     default:
1426       gst_v4l2_decoder_get_property (dec, prop_id - PROP_LAST, value, pspec);
1427       break;
1428   }
1429 }
1430 
1431 static void
gst_v4l2_codec_h264_dec_init(GstV4l2CodecH264Dec * self)1432 gst_v4l2_codec_h264_dec_init (GstV4l2CodecH264Dec * self)
1433 {
1434 }
1435 
1436 static void
gst_v4l2_codec_h264_dec_subinit(GstV4l2CodecH264Dec * self,GstV4l2CodecH264DecClass * klass)1437 gst_v4l2_codec_h264_dec_subinit (GstV4l2CodecH264Dec * self,
1438     GstV4l2CodecH264DecClass * klass)
1439 {
1440   self->decoder = gst_v4l2_decoder_new (klass->device);
1441   gst_video_info_init (&self->vinfo);
1442   self->slice_params = g_array_sized_new (FALSE, TRUE,
1443       sizeof (struct v4l2_ctrl_h264_slice_params), 4);
1444 }
1445 
1446 static void
gst_v4l2_codec_h264_dec_dispose(GObject * object)1447 gst_v4l2_codec_h264_dec_dispose (GObject * object)
1448 {
1449   GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (object);
1450 
1451   g_clear_object (&self->decoder);
1452   g_clear_pointer (&self->slice_params, g_array_unref);
1453 
1454   G_OBJECT_CLASS (parent_class)->dispose (object);
1455 }
1456 
1457 static void
gst_v4l2_codec_h264_dec_class_init(GstV4l2CodecH264DecClass * klass)1458 gst_v4l2_codec_h264_dec_class_init (GstV4l2CodecH264DecClass * klass)
1459 {
1460 }
1461 
1462 static void
gst_v4l2_codec_h264_dec_subclass_init(GstV4l2CodecH264DecClass * klass,GstV4l2CodecDevice * device)1463 gst_v4l2_codec_h264_dec_subclass_init (GstV4l2CodecH264DecClass * klass,
1464     GstV4l2CodecDevice * device)
1465 {
1466   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1467   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
1468   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
1469   GstH264DecoderClass *h264decoder_class = GST_H264_DECODER_CLASS (klass);
1470 
1471   gobject_class->set_property = gst_v4l2_codec_h264_dec_set_property;
1472   gobject_class->get_property = gst_v4l2_codec_h264_dec_get_property;
1473   gobject_class->dispose = gst_v4l2_codec_h264_dec_dispose;
1474 
1475   gst_element_class_set_static_metadata (element_class,
1476       "V4L2 Stateless H.264 Video Decoder",
1477       "Codec/Decoder/Video/Hardware",
1478       "A V4L2 based H.264 video decoder",
1479       "Nicolas Dufresne <nicolas.dufresne@collabora.com>");
1480 
1481   gst_element_class_add_static_pad_template (element_class, &sink_template);
1482   gst_element_class_add_static_pad_template (element_class, &src_template);
1483   element_class->change_state =
1484       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_change_state);
1485 
1486   decoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_open);
1487   decoder_class->close = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_close);
1488   decoder_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_stop);
1489   decoder_class->negotiate =
1490       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_negotiate);
1491   decoder_class->decide_allocation =
1492       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_decide_allocation);
1493   decoder_class->flush = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_flush);
1494   decoder_class->sink_event =
1495       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_sink_event);
1496 
1497   h264decoder_class->new_sequence =
1498       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_new_sequence);
1499   h264decoder_class->output_picture =
1500       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_output_picture);
1501   h264decoder_class->start_picture =
1502       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_start_picture);
1503   h264decoder_class->decode_slice =
1504       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_decode_slice);
1505   h264decoder_class->end_picture =
1506       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_end_picture);
1507   h264decoder_class->new_field_picture =
1508       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_new_field_picture);
1509   h264decoder_class->get_preferred_output_delay =
1510       GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_get_preferred_output_delay);
1511 
1512   klass->device = device;
1513   gst_v4l2_decoder_install_properties (gobject_class, PROP_LAST, device);
1514 }
1515 
1516 void
gst_v4l2_codec_h264_dec_register(GstPlugin * plugin,GstV4l2Decoder * decoder,GstV4l2CodecDevice * device,guint rank)1517 gst_v4l2_codec_h264_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
1518     GstV4l2CodecDevice * device, guint rank)
1519 {
1520   GstCaps *src_caps;
1521   guint version;
1522 
1523   GST_DEBUG_CATEGORY_INIT (v4l2_h264dec_debug, "v4l2codecs-h264dec", 0,
1524       "V4L2 stateless h264 decoder");
1525 
1526   if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_H264_SLICE,
1527           320, 240, 8))
1528     return;
1529   src_caps = gst_v4l2_decoder_enum_src_formats (decoder);
1530 
1531   if (gst_caps_is_empty (src_caps)) {
1532     GST_WARNING ("Not registering H264 decoder since it produces no "
1533         "supported format");
1534     goto done;
1535   }
1536 
1537   version = gst_v4l2_decoder_get_version (decoder);
1538   if (version < V4L2_MIN_KERNEL_VERSION)
1539     GST_WARNING ("V4L2 API v%u.%u too old, at least v%u.%u required",
1540         (version >> 16) & 0xff, (version >> 8) & 0xff,
1541         V4L2_MIN_KERNEL_VER_MAJOR, V4L2_MIN_KERNEL_VER_MINOR);
1542 
1543   if (!gst_v4l2_decoder_h264_api_check (decoder)) {
1544     GST_WARNING ("Not registering H264 decoder as it failed ABI check.");
1545     goto done;
1546   }
1547 
1548   gst_v4l2_decoder_register (plugin,
1549       GST_TYPE_V4L2_CODEC_H264_DEC,
1550       (GClassInitFunc) gst_v4l2_codec_h264_dec_subclass_init,
1551       gst_mini_object_ref (GST_MINI_OBJECT (device)),
1552       (GInstanceInitFunc) gst_v4l2_codec_h264_dec_subinit,
1553       "v4l2sl%sh264dec", device, rank, NULL);
1554 
1555 done:
1556   gst_caps_unref (src_caps);
1557 }
1558