1 /*
2 * gstvaapiencoder_mpeg2.c - MPEG-2 encoder
3 *
4 * Copyright (C) 2012-2014 Intel Corporation
5 * Author: Guangxin Xu <guangxin.xu@intel.com>
6 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1
11 * of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA
22 */
23
24 #include <math.h>
25 #include "sysdeps.h"
26 #include <gst/base/gstbitwriter.h>
27 #include "gstvaapicompat.h"
28 #include "gstvaapiencoder_mpeg2.h"
29 #include "gstvaapiencoder_mpeg2_priv.h"
30 #include "gstvaapiutils_mpeg2_priv.h"
31 #include "gstvaapicodedbufferproxy_priv.h"
32 #include "gstvaapicontext.h"
33 #include "gstvaapisurface.h"
34 #include "gstvaapidisplay_priv.h"
35
36 #define DEBUG 1
37 #include "gstvaapidebug.h"
38
39 /* Define default rate control mode ("constant-qp") */
40 #define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
41
42 /* Supported set of VA rate controls, within this implementation */
43 #define SUPPORTED_RATECONTROLS \
44 (GST_VAAPI_RATECONTROL_MASK (CQP) | \
45 GST_VAAPI_RATECONTROL_MASK (CBR))
46
47 /* Supported set of tuning options, within this implementation */
48 #define SUPPORTED_TUNE_OPTIONS \
49 (GST_VAAPI_ENCODER_TUNE_MASK (NONE))
50
51 /* Supported set of VA packed headers, within this implementation */
52 #define SUPPORTED_PACKED_HEADERS \
53 (VA_ENC_PACKED_HEADER_SEQUENCE | \
54 VA_ENC_PACKED_HEADER_PICTURE)
55
56 static gboolean
57 gst_bit_writer_write_sps (GstBitWriter * bitwriter,
58 const VAEncSequenceParameterBufferMPEG2 * seq_param);
59
60 static gboolean
61 gst_bit_writer_write_pps (GstBitWriter * bitwriter,
62 const VAEncPictureParameterBufferMPEG2 * pic_param);
63
64 static void clear_references (GstVaapiEncoderMpeg2 * encoder);
65
66 static void push_reference (GstVaapiEncoderMpeg2 * encoder,
67 GstVaapiSurfaceProxy * ref);
68
69 /* Derives the profile supported by the underlying hardware */
70 static gboolean
ensure_hw_profile(GstVaapiEncoderMpeg2 * encoder)71 ensure_hw_profile (GstVaapiEncoderMpeg2 * encoder)
72 {
73 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
74 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
75 GstVaapiProfile profile, profiles[2];
76 guint i, num_profiles = 0;
77
78 profiles[num_profiles++] = encoder->profile;
79 switch (encoder->profile) {
80 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
81 profiles[num_profiles++] = GST_VAAPI_PROFILE_MPEG2_MAIN;
82 break;
83 default:
84 break;
85 }
86
87 profile = GST_VAAPI_PROFILE_UNKNOWN;
88 for (i = 0; i < num_profiles; i++) {
89 if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
90 profile = profiles[i];
91 break;
92 }
93 }
94 if (profile == GST_VAAPI_PROFILE_UNKNOWN)
95 goto error_unsupported_profile;
96
97 GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
98 return TRUE;
99
100 /* ERRORS */
101 error_unsupported_profile:
102 {
103 GST_ERROR ("unsupported HW profile %s",
104 gst_vaapi_profile_get_name (encoder->profile));
105 return FALSE;
106 }
107 }
108
109 /* Derives the minimum profile from the active coding tools */
110 static gboolean
ensure_profile(GstVaapiEncoderMpeg2 * encoder)111 ensure_profile (GstVaapiEncoderMpeg2 * encoder)
112 {
113 GstVaapiProfile profile;
114
115 /* Always start from "simple" profile for maximum compatibility */
116 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
117
118 /* Main profile coding tools */
119 if (encoder->ip_period > 0)
120 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
121
122 encoder->profile = profile;
123 encoder->profile_idc = gst_vaapi_utils_mpeg2_get_profile_idc (profile);
124 return TRUE;
125 }
126
127 /* Derives the minimum level from the current configuration */
128 static gboolean
ensure_level(GstVaapiEncoderMpeg2 * encoder)129 ensure_level (GstVaapiEncoderMpeg2 * encoder)
130 {
131 const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
132 const guint fps = (vip->fps_n + vip->fps_d - 1) / vip->fps_d;
133 const guint bitrate = GST_VAAPI_ENCODER_CAST (encoder)->bitrate;
134 const GstVaapiMPEG2LevelLimits *limits_table;
135 guint i, num_limits, num_samples;
136
137 num_samples = gst_util_uint64_scale_int_ceil (vip->width * vip->height,
138 vip->fps_n, vip->fps_d);
139
140 limits_table = gst_vaapi_utils_mpeg2_get_level_limits_table (&num_limits);
141 for (i = 0; i < num_limits; i++) {
142 const GstVaapiMPEG2LevelLimits *const limits = &limits_table[i];
143 if (vip->width <= limits->horizontal_size_value &&
144 vip->height <= limits->vertical_size_value &&
145 fps <= limits->frame_rate_value &&
146 num_samples <= limits->sample_rate &&
147 (!bitrate || bitrate <= limits->bit_rate))
148 break;
149 }
150 if (i == num_limits)
151 goto error_unsupported_level;
152
153 encoder->level = limits_table[i].level;
154 encoder->level_idc = limits_table[i].level_idc;
155 return TRUE;
156
157 /* ERRORS */
158 error_unsupported_level:
159 {
160 GST_ERROR ("failed to find a suitable level matching codec config");
161 return FALSE;
162 }
163 }
164
165 /* Derives the profile and level that suits best to the configuration */
166 static GstVaapiEncoderStatus
ensure_profile_and_level(GstVaapiEncoderMpeg2 * encoder)167 ensure_profile_and_level (GstVaapiEncoderMpeg2 * encoder)
168 {
169 if (!ensure_profile (encoder))
170 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
171
172 if (!ensure_level (encoder))
173 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
174
175 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
176 }
177
178 static gboolean
ensure_bitrate(GstVaapiEncoderMpeg2 * encoder)179 ensure_bitrate (GstVaapiEncoderMpeg2 * encoder)
180 {
181 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
182
183 /* Default compression: 64 bits per macroblock */
184 switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
185 case GST_VAAPI_RATECONTROL_CBR:
186 if (!base_encoder->bitrate)
187 base_encoder->bitrate =
188 gst_util_uint64_scale (GST_VAAPI_ENCODER_WIDTH (encoder) *
189 GST_VAAPI_ENCODER_HEIGHT (encoder),
190 GST_VAAPI_ENCODER_FPS_N (encoder),
191 GST_VAAPI_ENCODER_FPS_D (encoder)) / 4 / 1000;
192 break;
193 default:
194 base_encoder->bitrate = 0;
195 break;
196 }
197 return TRUE;
198 }
199
200 static gboolean
fill_sequence(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncSequence * sequence)201 fill_sequence (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncSequence * sequence)
202 {
203 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
204 VAEncSequenceParameterBufferMPEG2 *const seq_param = sequence->param;
205
206 memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferMPEG2));
207
208 seq_param->intra_period = base_encoder->keyframe_period;
209 seq_param->ip_period = encoder->ip_period;
210 seq_param->picture_width = GST_VAAPI_ENCODER_WIDTH (encoder);
211 seq_param->picture_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
212
213 if (base_encoder->bitrate > 0)
214 seq_param->bits_per_second = base_encoder->bitrate * 1000;
215 else
216 seq_param->bits_per_second = 0;
217
218 if (GST_VAAPI_ENCODER_FPS_D (encoder))
219 seq_param->frame_rate =
220 GST_VAAPI_ENCODER_FPS_N (encoder) / GST_VAAPI_ENCODER_FPS_D (encoder);
221 else
222 seq_param->frame_rate = 0;
223
224 seq_param->aspect_ratio_information = 1;
225 seq_param->vbv_buffer_size = 3; /* B = 16 * 1024 * vbv_buffer_size */
226
227 seq_param->sequence_extension.bits.profile_and_level_indication =
228 (encoder->profile_idc << 4) | encoder->level_idc;
229 seq_param->sequence_extension.bits.progressive_sequence = 1; /* progressive frame-pictures */
230 seq_param->sequence_extension.bits.chroma_format =
231 gst_vaapi_utils_mpeg2_get_chroma_format_idc
232 (GST_VAAPI_CHROMA_TYPE_YUV420);
233 seq_param->sequence_extension.bits.low_delay = 0; /* FIXME */
234 seq_param->sequence_extension.bits.frame_rate_extension_n = 0; /* FIXME */
235 seq_param->sequence_extension.bits.frame_rate_extension_d = 0;
236
237 seq_param->gop_header.bits.time_code = (1 << 12); /* bit12: marker_bit */
238 seq_param->gop_header.bits.closed_gop = 0;
239 seq_param->gop_header.bits.broken_link = 0;
240
241 return TRUE;
242 }
243
244 static VAEncPictureType
get_va_enc_picture_type(GstVaapiPictureType type)245 get_va_enc_picture_type (GstVaapiPictureType type)
246 {
247 switch (type) {
248 case GST_VAAPI_PICTURE_TYPE_I:
249 return VAEncPictureTypeIntra;
250 case GST_VAAPI_PICTURE_TYPE_P:
251 return VAEncPictureTypePredictive;
252 case GST_VAAPI_PICTURE_TYPE_B:
253 return VAEncPictureTypeBidirectional;
254 default:
255 return -1;
256 }
257 return -1;
258 }
259
260 static gboolean
fill_picture(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture,GstVaapiCodedBuffer * codedbuf,GstVaapiSurfaceProxy * surface)261 fill_picture (GstVaapiEncoderMpeg2 * encoder,
262 GstVaapiEncPicture * picture,
263 GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
264 {
265 VAEncPictureParameterBufferMPEG2 *const pic_param = picture->param;
266 guint8 f_code_x, f_code_y;
267
268 memset (pic_param, 0, sizeof (VAEncPictureParameterBufferMPEG2));
269
270 pic_param->reconstructed_picture =
271 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
272 pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
273 pic_param->picture_type = get_va_enc_picture_type (picture->type);
274 pic_param->temporal_reference = picture->frame_num & (1024 - 1);
275 pic_param->vbv_delay = 0xFFFF;
276
277 f_code_x = 0xf;
278 f_code_y = 0xf;
279 if (pic_param->picture_type != VAEncPictureTypeIntra) {
280 switch (encoder->level) {
281 case GST_VAAPI_LEVEL_MPEG2_LOW:
282 f_code_x = 7;
283 f_code_y = 4;
284 break;
285 case GST_VAAPI_LEVEL_MPEG2_MAIN:
286 f_code_x = 8;
287 f_code_y = 5;
288 break;
289 default: /* High-1440 and High levels */
290 f_code_x = 9;
291 f_code_y = 5;
292 break;
293 }
294 }
295
296 if (pic_param->picture_type == VAEncPictureTypeIntra) {
297 pic_param->f_code[0][0] = 0xf;
298 pic_param->f_code[0][1] = 0xf;
299 pic_param->f_code[1][0] = 0xf;
300 pic_param->f_code[1][1] = 0xf;
301 pic_param->forward_reference_picture = VA_INVALID_SURFACE;
302 pic_param->backward_reference_picture = VA_INVALID_SURFACE;
303 } else if (pic_param->picture_type == VAEncPictureTypePredictive) {
304 pic_param->f_code[0][0] = f_code_x;
305 pic_param->f_code[0][1] = f_code_y;
306 pic_param->f_code[1][0] = 0xf;
307 pic_param->f_code[1][1] = 0xf;
308 pic_param->forward_reference_picture =
309 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->forward);
310 pic_param->backward_reference_picture = VA_INVALID_SURFACE;
311 } else if (pic_param->picture_type == VAEncPictureTypeBidirectional) {
312 pic_param->f_code[0][0] = f_code_x;
313 pic_param->f_code[0][1] = f_code_y;
314 pic_param->f_code[1][0] = f_code_x;
315 pic_param->f_code[1][1] = f_code_y;
316 pic_param->forward_reference_picture =
317 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->forward);
318 pic_param->backward_reference_picture =
319 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->backward);
320 } else {
321 g_assert (0);
322 }
323
324 pic_param->picture_coding_extension.bits.intra_dc_precision = 0; /* 8bits */
325 pic_param->picture_coding_extension.bits.picture_structure = 3; /* frame picture */
326 pic_param->picture_coding_extension.bits.top_field_first = 0;
327 pic_param->picture_coding_extension.bits.frame_pred_frame_dct = 1; /* FIXME */
328 pic_param->picture_coding_extension.bits.concealment_motion_vectors = 0;
329 pic_param->picture_coding_extension.bits.q_scale_type = 0;
330 pic_param->picture_coding_extension.bits.intra_vlc_format = 0;
331 pic_param->picture_coding_extension.bits.alternate_scan = 0;
332 pic_param->picture_coding_extension.bits.repeat_first_field = 0;
333 pic_param->picture_coding_extension.bits.progressive_frame = 1;
334 pic_param->picture_coding_extension.bits.composite_display_flag = 0;
335
336 return TRUE;
337 }
338
339 static gboolean
set_sequence_packed_header(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture,GstVaapiEncSequence * sequence)340 set_sequence_packed_header (GstVaapiEncoderMpeg2 * encoder,
341 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
342 {
343 GstVaapiEncPackedHeader *packed_seq;
344 GstBitWriter writer;
345 VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
346 const VAEncSequenceParameterBufferMPEG2 *const seq_param = sequence->param;
347 guint32 data_bit_size;
348 guint8 *data;
349
350 gst_bit_writer_init_with_size (&writer, 128, FALSE);
351 if (encoder->new_gop)
352 gst_bit_writer_write_sps (&writer, seq_param);
353 g_assert (GST_BIT_WRITER_BIT_SIZE (&writer) % 8 == 0);
354 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&writer);
355 data = GST_BIT_WRITER_DATA (&writer);
356
357 packed_header_param_buffer.type = VAEncPackedHeaderSequence;
358 packed_header_param_buffer.bit_length = data_bit_size;
359 packed_header_param_buffer.has_emulation_bytes = 0;
360
361 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
362 &packed_header_param_buffer, sizeof (packed_header_param_buffer),
363 data, (data_bit_size + 7) / 8);
364 g_assert (packed_seq);
365
366 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
367 gst_vaapi_codec_object_replace (&packed_seq, NULL);
368 gst_bit_writer_reset (&writer);
369
370 return TRUE;
371 }
372
373 static gboolean
set_picture_packed_header(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture)374 set_picture_packed_header (GstVaapiEncoderMpeg2 * encoder,
375 GstVaapiEncPicture * picture)
376 {
377 GstVaapiEncPackedHeader *packed_pic;
378 GstBitWriter writer;
379 VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
380 const VAEncPictureParameterBufferMPEG2 *const pic_param = picture->param;
381 guint32 data_bit_size;
382 guint8 *data;
383
384 gst_bit_writer_init_with_size (&writer, 128, FALSE);
385 gst_bit_writer_write_pps (&writer, pic_param);
386 g_assert (GST_BIT_WRITER_BIT_SIZE (&writer) % 8 == 0);
387 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&writer);
388 data = GST_BIT_WRITER_DATA (&writer);
389
390 packed_header_param_buffer.type = VAEncPackedHeaderPicture;
391 packed_header_param_buffer.bit_length = data_bit_size;
392 packed_header_param_buffer.has_emulation_bytes = 0;
393
394 packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
395 &packed_header_param_buffer, sizeof (packed_header_param_buffer),
396 data, (data_bit_size + 7) / 8);
397 g_assert (packed_pic);
398
399 gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
400 gst_vaapi_codec_object_replace (&packed_pic, NULL);
401 gst_bit_writer_reset (&writer);
402
403 return TRUE;
404 }
405
406 static gboolean
ensure_sequence(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture)407 ensure_sequence (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncPicture * picture)
408 {
409 GstVaapiEncSequence *sequence;
410
411 g_assert (picture);
412 sequence = GST_VAAPI_ENC_SEQUENCE_NEW (MPEG2, encoder);
413 g_assert (sequence);
414 if (!sequence)
415 goto error;
416
417 if (!fill_sequence (encoder, sequence))
418 goto error;
419
420 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
421 VA_ENC_PACKED_HEADER_SEQUENCE)
422 && picture->type == GST_VAAPI_PICTURE_TYPE_I
423 && !set_sequence_packed_header (encoder, picture, sequence))
424 goto error;
425 gst_vaapi_enc_picture_set_sequence (picture, sequence);
426 gst_vaapi_codec_object_replace (&sequence, NULL);
427 return TRUE;
428
429 /* ERRORS */
430 error:
431 {
432 gst_vaapi_codec_object_replace (&sequence, NULL);
433 return FALSE;
434 }
435 }
436
437 static gboolean
ensure_picture(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture,GstVaapiCodedBufferProxy * codedbuf_proxy,GstVaapiSurfaceProxy * surface)438 ensure_picture (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncPicture * picture,
439 GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
440 {
441 GstVaapiCodedBuffer *const codedbuf =
442 GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
443
444 if (!fill_picture (encoder, picture, codedbuf, surface))
445 return FALSE;
446
447 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
448 VA_ENC_PACKED_HEADER_PICTURE)
449 && !set_picture_packed_header (encoder, picture)) {
450 GST_ERROR ("set picture packed header failed");
451 return FALSE;
452 }
453 return TRUE;
454 }
455
456 static gboolean
ensure_control_rate_params(GstVaapiEncoderMpeg2 * encoder)457 ensure_control_rate_params (GstVaapiEncoderMpeg2 * encoder)
458 {
459 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
460
461 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
462 return TRUE;
463
464 /* RateControl params */
465 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).initial_qp = encoder->cqp;
466
467 /* *INDENT-OFF* */
468 /* HRD params */
469 GST_VAAPI_ENCODER_VA_HRD (encoder) = (VAEncMiscParameterHRD) {
470 .buffer_size = base_encoder->bitrate * 1000 * 8,
471 .initial_buffer_fullness = base_encoder->bitrate * 1000 * 4,
472 };
473 /* *INDENT-ON* */
474
475 return TRUE;
476 }
477
478 static gboolean
set_misc_parameters(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture)479 set_misc_parameters (GstVaapiEncoderMpeg2 * encoder,
480 GstVaapiEncPicture * picture)
481 {
482 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
483
484 if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
485 return FALSE;
486 if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
487 return FALSE;
488 return TRUE;
489 }
490
491 static gboolean
fill_slices(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture)492 fill_slices (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncPicture * picture)
493 {
494 VAEncSliceParameterBufferMPEG2 *slice_param;
495 GstVaapiEncSlice *slice;
496 guint width_in_mbs, height_in_mbs;
497 guint i_slice;
498
499 g_assert (picture);
500
501 width_in_mbs = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
502 height_in_mbs = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
503
504 for (i_slice = 0; i_slice < height_in_mbs; ++i_slice) {
505 slice = GST_VAAPI_ENC_SLICE_NEW (MPEG2, encoder);
506 g_assert (slice && slice->param_id != VA_INVALID_ID);
507 slice_param = slice->param;
508
509 memset (slice_param, 0, sizeof (VAEncSliceParameterBufferMPEG2));
510
511 slice_param->macroblock_address = i_slice * width_in_mbs;
512 slice_param->num_macroblocks = width_in_mbs;
513 slice_param->is_intra_slice = (picture->type == GST_VAAPI_PICTURE_TYPE_I);
514 slice_param->quantiser_scale_code = encoder->cqp / 2;
515
516 gst_vaapi_enc_picture_add_slice (picture, slice);
517 gst_vaapi_codec_object_replace (&slice, NULL);
518 }
519 return TRUE;
520 }
521
522 static gboolean
ensure_slices(GstVaapiEncoderMpeg2 * encoder,GstVaapiEncPicture * picture)523 ensure_slices (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncPicture * picture)
524 {
525 g_assert (picture);
526
527 if (!fill_slices (encoder, picture))
528 return FALSE;
529
530 return TRUE;
531 }
532
533 static GstVaapiEncoderStatus
gst_vaapi_encoder_mpeg2_encode(GstVaapiEncoder * base_encoder,GstVaapiEncPicture * picture,GstVaapiCodedBufferProxy * codedbuf)534 gst_vaapi_encoder_mpeg2_encode (GstVaapiEncoder * base_encoder,
535 GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
536 {
537 GstVaapiEncoderMpeg2 *const encoder =
538 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
539 GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
540 GstVaapiSurfaceProxy *reconstruct = NULL;
541
542 reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
543
544 g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
545
546 if (!ensure_sequence (encoder, picture))
547 goto error;
548 if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
549 goto error;
550 if (!set_misc_parameters (encoder, picture))
551 goto error;
552 if (!ensure_slices (encoder, picture))
553 goto error;
554 if (!gst_vaapi_enc_picture_encode (picture))
555 goto error;
556 if (picture->type != GST_VAAPI_PICTURE_TYPE_B) {
557 if (encoder->new_gop)
558 clear_references (encoder);
559 push_reference (encoder, reconstruct);
560 } else if (reconstruct)
561 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
562 reconstruct);
563
564 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
565
566 /* ERRORS */
567 error:
568 {
569 if (reconstruct)
570 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
571 reconstruct);
572 return ret;
573 }
574 }
575
576 static GstVaapiEncoderStatus
gst_vaapi_encoder_mpeg2_flush(GstVaapiEncoder * base_encoder)577 gst_vaapi_encoder_mpeg2_flush (GstVaapiEncoder * base_encoder)
578 {
579 GstVaapiEncoderMpeg2 *const encoder =
580 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
581 GstVaapiEncPicture *pic;
582
583 while (!g_queue_is_empty (&encoder->b_frames)) {
584 pic = g_queue_pop_head (&encoder->b_frames);
585 gst_vaapi_enc_picture_unref (pic);
586 }
587 g_queue_clear (&encoder->b_frames);
588
589 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
590 }
591
592 static GstVaapiEncoderStatus
gst_vaapi_encoder_mpeg2_reordering(GstVaapiEncoder * base_encoder,GstVideoCodecFrame * frame,GstVaapiEncPicture ** output)593 gst_vaapi_encoder_mpeg2_reordering (GstVaapiEncoder * base_encoder,
594 GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
595 {
596 GstVaapiEncoderMpeg2 *const encoder =
597 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
598 GstVaapiEncPicture *picture = NULL;
599 GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
600
601 if (!frame) {
602 if (g_queue_is_empty (&encoder->b_frames) && encoder->dump_frames) {
603 push_reference (encoder, NULL);
604 encoder->dump_frames = FALSE;
605 }
606 if (!encoder->dump_frames) {
607 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
608 }
609 picture = g_queue_pop_head (&encoder->b_frames);
610 g_assert (picture);
611 goto end;
612 }
613
614 picture = GST_VAAPI_ENC_PICTURE_NEW (MPEG2, encoder, frame);
615 if (!picture) {
616 GST_WARNING ("create MPEG2 picture failed, frame timestamp:%"
617 GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
618 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
619 }
620
621 if (encoder->frame_num >= base_encoder->keyframe_period) {
622 encoder->frame_num = 0;
623 clear_references (encoder);
624 }
625 if (encoder->frame_num == 0) {
626 picture->type = GST_VAAPI_PICTURE_TYPE_I;
627 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
628 encoder->new_gop = TRUE;
629 } else {
630 encoder->new_gop = FALSE;
631 if ((encoder->frame_num % (encoder->ip_period + 1)) == 0 ||
632 encoder->frame_num == base_encoder->keyframe_period - 1) {
633 picture->type = GST_VAAPI_PICTURE_TYPE_P;
634 encoder->dump_frames = TRUE;
635 } else {
636 picture->type = GST_VAAPI_PICTURE_TYPE_B;
637 status = GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
638 }
639 }
640 picture->frame_num = encoder->frame_num++;
641
642 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
643 g_queue_push_tail (&encoder->b_frames, picture);
644 picture = NULL;
645 }
646
647 end:
648 *output = picture;
649 return status;
650 }
651
652 static GstVaapiEncoderStatus
set_context_info(GstVaapiEncoder * base_encoder)653 set_context_info (GstVaapiEncoder * base_encoder)
654 {
655 GstVaapiEncoderMpeg2 *const encoder =
656 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
657 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
658
659 /* Maximum sizes for common headers (in bytes) */
660 enum
661 {
662 MAX_SEQ_HDR_SIZE = 140,
663 MAX_SEQ_EXT_SIZE = 10,
664 MAX_GOP_SIZE = 8,
665 MAX_PIC_HDR_SIZE = 10,
666 MAX_PIC_EXT_SIZE = 11,
667 MAX_SLICE_HDR_SIZE = 8,
668 };
669
670 if (!ensure_hw_profile (encoder))
671 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
672
673 base_encoder->num_ref_frames = 2;
674
675 /* Only YUV 4:2:0 formats are supported for now. This means that we
676 have a limit of 4608 bits per macroblock. */
677 base_encoder->codedbuf_size = (GST_ROUND_UP_16 (vip->width) *
678 GST_ROUND_UP_16 (vip->height) / 256) * 576;
679
680 /* Account for Sequence, GOP, and Picture headers */
681 /* XXX: exclude unused Sequence Display Extension, Sequence Scalable
682 Extension, Quantization Matrix Extension, Picture Display Extension,
683 Picture Temporal Scalable Extension, Picture Spatial Scalable
684 Extension */
685 base_encoder->codedbuf_size += MAX_SEQ_HDR_SIZE + MAX_SEQ_EXT_SIZE +
686 MAX_GOP_SIZE + MAX_PIC_HDR_SIZE + MAX_PIC_EXT_SIZE;
687
688 /* Account for Slice headers. We use one slice per line of macroblock */
689 base_encoder->codedbuf_size += (GST_ROUND_UP_16 (vip->height) / 16) *
690 MAX_SLICE_HDR_SIZE;
691
692 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
693 }
694
695 static GstVaapiEncoderStatus
gst_vaapi_encoder_mpeg2_reconfigure(GstVaapiEncoder * base_encoder)696 gst_vaapi_encoder_mpeg2_reconfigure (GstVaapiEncoder * base_encoder)
697 {
698 GstVaapiEncoderMpeg2 *const encoder =
699 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
700 GstVaapiEncoderStatus status;
701
702 if (encoder->ip_period > base_encoder->keyframe_period) {
703 encoder->ip_period = base_encoder->keyframe_period - 1;
704 }
705
706 status = ensure_profile_and_level (encoder);
707 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
708 return status;
709
710 if (!ensure_bitrate (encoder))
711 goto error;
712 ensure_control_rate_params (encoder);
713 return set_context_info (base_encoder);
714
715 /* ERRORS */
716 error:
717 {
718 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
719 }
720 }
721
722 static gboolean
gst_vaapi_encoder_mpeg2_init(GstVaapiEncoder * base_encoder)723 gst_vaapi_encoder_mpeg2_init (GstVaapiEncoder * base_encoder)
724 {
725 GstVaapiEncoderMpeg2 *const encoder =
726 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
727
728 /* re-ordering */
729 g_queue_init (&encoder->b_frames);
730
731 return TRUE;
732 }
733
734 static void
clear_ref(GstVaapiEncoderMpeg2 * encoder,GstVaapiSurfaceProxy ** ref)735 clear_ref (GstVaapiEncoderMpeg2 * encoder, GstVaapiSurfaceProxy ** ref)
736 {
737 if (*ref) {
738 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), *ref);
739 *ref = NULL;
740 }
741 }
742
743 static void
clear_references(GstVaapiEncoderMpeg2 * encoder)744 clear_references (GstVaapiEncoderMpeg2 * encoder)
745 {
746 clear_ref (encoder, &encoder->forward);
747 clear_ref (encoder, &encoder->backward);
748 }
749
750 static void
push_reference(GstVaapiEncoderMpeg2 * encoder,GstVaapiSurfaceProxy * ref)751 push_reference (GstVaapiEncoderMpeg2 * encoder, GstVaapiSurfaceProxy * ref)
752 {
753 if (encoder->backward) {
754 clear_ref (encoder, &encoder->forward);
755 encoder->forward = encoder->backward;
756 encoder->backward = NULL;
757 }
758 if (encoder->forward)
759 encoder->backward = ref;
760 else
761 encoder->forward = ref;
762 }
763
764 static void
gst_vaapi_encoder_mpeg2_finalize(GstVaapiEncoder * base_encoder)765 gst_vaapi_encoder_mpeg2_finalize (GstVaapiEncoder * base_encoder)
766 {
767 /* free private buffers */
768 GstVaapiEncoderMpeg2 *const encoder =
769 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
770 GstVaapiEncPicture *pic;
771
772 clear_references (encoder);
773
774 while (!g_queue_is_empty (&encoder->b_frames)) {
775 pic = g_queue_pop_head (&encoder->b_frames);
776 gst_vaapi_enc_picture_unref (pic);
777 }
778 g_queue_clear (&encoder->b_frames);
779 }
780
781 static GstVaapiEncoderStatus
gst_vaapi_encoder_mpeg2_set_property(GstVaapiEncoder * base_encoder,gint prop_id,const GValue * value)782 gst_vaapi_encoder_mpeg2_set_property (GstVaapiEncoder * base_encoder,
783 gint prop_id, const GValue * value)
784 {
785 GstVaapiEncoderMpeg2 *const encoder =
786 GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder);
787
788 switch (prop_id) {
789 case GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER:
790 encoder->cqp = g_value_get_uint (value);
791 break;
792 case GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES:
793 encoder->ip_period = g_value_get_uint (value);
794 break;
795 default:
796 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
797 }
798 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
799 }
800
801 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (MPEG2);
802
803 static inline const GstVaapiEncoderClass *
gst_vaapi_encoder_mpeg2_class(void)804 gst_vaapi_encoder_mpeg2_class (void)
805 {
806 static const GstVaapiEncoderClass GstVaapiEncoderMpeg2Class = {
807 GST_VAAPI_ENCODER_CLASS_INIT (Mpeg2, mpeg2),
808 .set_property = gst_vaapi_encoder_mpeg2_set_property,
809 };
810 return &GstVaapiEncoderMpeg2Class;
811 }
812
813 /**
814 * gst_vaapi_encoder_mpeg2_new:
815 * @display: a #GstVaapiDisplay
816 *
817 * Creates a new #GstVaapiEncoder for MPEG-2 encoding.
818 *
819 * Return value: the newly allocated #GstVaapiEncoder object
820 */
821 GstVaapiEncoder *
gst_vaapi_encoder_mpeg2_new(GstVaapiDisplay * display)822 gst_vaapi_encoder_mpeg2_new (GstVaapiDisplay * display)
823 {
824 return gst_vaapi_encoder_new (gst_vaapi_encoder_mpeg2_class (), display);
825 }
826
827 /**
828 * gst_vaapi_encoder_mpeg2_get_default_properties:
829 *
830 * Determines the set of common and MPEG-2 specific encoder properties.
831 * The caller owns an extra reference to the resulting array of
832 * #GstVaapiEncoderPropInfo elements, so it shall be released with
833 * g_ptr_array_unref() after usage.
834 *
835 * Return value: the set of encoder properties for #GstVaapiEncoderMpeg2,
836 * or %NULL if an error occurred.
837 */
838 GPtrArray *
gst_vaapi_encoder_mpeg2_get_default_properties(void)839 gst_vaapi_encoder_mpeg2_get_default_properties (void)
840 {
841 const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_mpeg2_class ();
842 GPtrArray *props;
843
844 props = gst_vaapi_encoder_properties_get_default (klass);
845 if (!props)
846 return NULL;
847
848 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
849 GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER,
850 g_param_spec_uint ("quantizer",
851 "Constant Quantizer",
852 "Constant quantizer (if rate-control mode is CQP)",
853 2, 62, 8, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
854
855 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
856 GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES,
857 g_param_spec_uint ("max-bframes", "Max B-Frames",
858 "Number of B-frames between I and P",
859 0, 16, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
860
861 return props;
862 }
863
864 static struct
865 {
866 int code;
867 float value;
868 } frame_rate_tab[] = {
869 /* *INDENT-OFF* */
870 { 1, 23.976 },
871 { 2, 24.0 },
872 { 3, 25.0 },
873 { 4, 29.97 },
874 { 5, 30 },
875 { 6, 50 },
876 { 7, 59.94 },
877 { 8, 60 }
878 /* *INDENT-ON* */
879 };
880
881 static int
find_frame_rate_code(const VAEncSequenceParameterBufferMPEG2 * seq_param)882 find_frame_rate_code (const VAEncSequenceParameterBufferMPEG2 * seq_param)
883 {
884 unsigned int ndelta, delta = -1;
885 int code = 1, i;
886 float frame_rate_value = seq_param->frame_rate *
887 (seq_param->sequence_extension.bits.frame_rate_extension_d + 1) /
888 (seq_param->sequence_extension.bits.frame_rate_extension_n + 1);
889
890 for (i = 0; i < G_N_ELEMENTS (frame_rate_tab); i++) {
891
892 ndelta = fabsf (1000 * frame_rate_tab[i].value - 1000 * frame_rate_value);
893 if (ndelta < delta) {
894 code = frame_rate_tab[i].code;
895 delta = ndelta;
896 }
897 }
898 return code;
899 }
900
901 static gboolean
gst_bit_writer_write_sps(GstBitWriter * bitwriter,const VAEncSequenceParameterBufferMPEG2 * seq_param)902 gst_bit_writer_write_sps (GstBitWriter * bitwriter,
903 const VAEncSequenceParameterBufferMPEG2 * seq_param)
904 {
905 gst_bit_writer_put_bits_uint32 (bitwriter, START_CODE_SEQ, 32);
906 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->picture_width, 12);
907 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->picture_height, 12);
908 gst_bit_writer_put_bits_uint32 (bitwriter,
909 seq_param->aspect_ratio_information, 4);
910 gst_bit_writer_put_bits_uint32 (bitwriter, find_frame_rate_code (seq_param), 4); /* frame_rate_code */
911 gst_bit_writer_put_bits_uint32 (bitwriter, (seq_param->bits_per_second + 399) / 400, 18); /* the low 18 bits of bit_rate */
912 gst_bit_writer_put_bits_uint32 (bitwriter, 1, 1); /* marker_bit */
913 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->vbv_buffer_size, 10);
914 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* constraint_parameter_flag, always 0 for MPEG-2 */
915 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* load_intra_quantiser_matrix */
916 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* load_non_intra_quantiser_matrix */
917
918 gst_bit_writer_align_bytes (bitwriter, 0);
919
920 gst_bit_writer_put_bits_uint32 (bitwriter, START_CODE_EXT, 32);
921 gst_bit_writer_put_bits_uint32 (bitwriter, 1, 4); /* sequence_extension id */
922 gst_bit_writer_put_bits_uint32 (bitwriter,
923 seq_param->sequence_extension.bits.profile_and_level_indication, 8);
924 gst_bit_writer_put_bits_uint32 (bitwriter,
925 seq_param->sequence_extension.bits.progressive_sequence, 1);
926 gst_bit_writer_put_bits_uint32 (bitwriter,
927 seq_param->sequence_extension.bits.chroma_format, 2);
928 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->picture_width >> 12, 2);
929 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->picture_height >> 12,
930 2);
931 gst_bit_writer_put_bits_uint32 (bitwriter, ((seq_param->bits_per_second + 399) / 400) >> 18, 12); /* bit_rate_extension */
932 gst_bit_writer_put_bits_uint32 (bitwriter, 1, 1); /* marker_bit */
933 gst_bit_writer_put_bits_uint32 (bitwriter, seq_param->vbv_buffer_size >> 10,
934 8);
935 gst_bit_writer_put_bits_uint32 (bitwriter,
936 seq_param->sequence_extension.bits.low_delay, 1);
937 gst_bit_writer_put_bits_uint32 (bitwriter,
938 seq_param->sequence_extension.bits.frame_rate_extension_n, 2);
939 gst_bit_writer_put_bits_uint32 (bitwriter,
940 seq_param->sequence_extension.bits.frame_rate_extension_d, 5);
941
942 gst_bit_writer_align_bytes (bitwriter, 0);
943
944 /* gop header */
945 gst_bit_writer_put_bits_uint32 (bitwriter, START_CODE_GOP, 32);
946 gst_bit_writer_put_bits_uint32 (bitwriter,
947 seq_param->gop_header.bits.time_code, 25);
948 gst_bit_writer_put_bits_uint32 (bitwriter,
949 seq_param->gop_header.bits.closed_gop, 1);
950 gst_bit_writer_put_bits_uint32 (bitwriter,
951 seq_param->gop_header.bits.broken_link, 1);
952
953 gst_bit_writer_align_bytes (bitwriter, 0);
954
955 return TRUE;
956 }
957
958 static gboolean
gst_bit_writer_write_pps(GstBitWriter * bitwriter,const VAEncPictureParameterBufferMPEG2 * pic_param)959 gst_bit_writer_write_pps (GstBitWriter * bitwriter,
960 const VAEncPictureParameterBufferMPEG2 * pic_param)
961 {
962 gst_bit_writer_put_bits_uint32 (bitwriter, START_CODE_PICUTRE, 32);
963 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->temporal_reference, 10);
964 gst_bit_writer_put_bits_uint32 (bitwriter,
965 pic_param->picture_type == VAEncPictureTypeIntra ? 1 :
966 pic_param->picture_type == VAEncPictureTypePredictive ? 2 : 3, 3);
967 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->vbv_delay, 16);
968
969 if (pic_param->picture_type == VAEncPictureTypePredictive ||
970 pic_param->picture_type == VAEncPictureTypeBidirectional) {
971 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* full_pel_forward_vector, always 0 for MPEG-2 */
972 gst_bit_writer_put_bits_uint32 (bitwriter, 7, 3); /* forward_f_code, always 7 for MPEG-2 */
973 }
974
975 if (pic_param->picture_type == VAEncPictureTypeBidirectional) {
976 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* full_pel_backward_vector, always 0 for MPEG-2 */
977 gst_bit_writer_put_bits_uint32 (bitwriter, 7, 3); /* backward_f_code, always 7 for MPEG-2 */
978 }
979
980 gst_bit_writer_put_bits_uint32 (bitwriter, 0, 1); /* extra_bit_picture, 0 */
981
982 gst_bit_writer_align_bytes (bitwriter, 0);
983
984 gst_bit_writer_put_bits_uint32 (bitwriter, START_CODE_EXT, 32);
985 gst_bit_writer_put_bits_uint32 (bitwriter, 8, 4); /* Picture Coding Extension ID: 8 */
986 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->f_code[0][0], 4);
987 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->f_code[0][1], 4);
988 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->f_code[1][0], 4);
989 gst_bit_writer_put_bits_uint32 (bitwriter, pic_param->f_code[1][1], 4);
990
991 gst_bit_writer_put_bits_uint32 (bitwriter,
992 pic_param->picture_coding_extension.bits.intra_dc_precision, 2);
993 gst_bit_writer_put_bits_uint32 (bitwriter,
994 pic_param->picture_coding_extension.bits.picture_structure, 2);
995 gst_bit_writer_put_bits_uint32 (bitwriter,
996 pic_param->picture_coding_extension.bits.top_field_first, 1);
997 gst_bit_writer_put_bits_uint32 (bitwriter,
998 pic_param->picture_coding_extension.bits.frame_pred_frame_dct, 1);
999 gst_bit_writer_put_bits_uint32 (bitwriter,
1000 pic_param->picture_coding_extension.bits.concealment_motion_vectors, 1);
1001 gst_bit_writer_put_bits_uint32 (bitwriter,
1002 pic_param->picture_coding_extension.bits.q_scale_type, 1);
1003 gst_bit_writer_put_bits_uint32 (bitwriter,
1004 pic_param->picture_coding_extension.bits.intra_vlc_format, 1);
1005 gst_bit_writer_put_bits_uint32 (bitwriter,
1006 pic_param->picture_coding_extension.bits.alternate_scan, 1);
1007 gst_bit_writer_put_bits_uint32 (bitwriter,
1008 pic_param->picture_coding_extension.bits.repeat_first_field, 1);
1009 gst_bit_writer_put_bits_uint32 (bitwriter, 1, 1); /* always chroma 420 */
1010 gst_bit_writer_put_bits_uint32 (bitwriter,
1011 pic_param->picture_coding_extension.bits.progressive_frame, 1);
1012 gst_bit_writer_put_bits_uint32 (bitwriter,
1013 pic_param->picture_coding_extension.bits.composite_display_flag, 1);
1014
1015 gst_bit_writer_align_bytes (bitwriter, 0);
1016
1017 return TRUE;
1018 }
1019