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