1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/avstring.h"
20 #include "libavutil/display.h"
21 #include "libavutil/common.h"
22 #include "libavutil/opt.h"
23 
24 #include "bsf.h"
25 #include "bsf_internal.h"
26 #include "cbs.h"
27 #include "cbs_bsf.h"
28 #include "cbs_h264.h"
29 #include "h264.h"
30 #include "h264_levels.h"
31 #include "h264_sei.h"
32 
33 enum {
34     FLIP_HORIZONTAL = 1,
35     FLIP_VERTICAL   = 2,
36 };
37 
38 enum {
39     LEVEL_UNSET = -2,
40     LEVEL_AUTO  = -1,
41 };
42 
43 typedef struct H264MetadataContext {
44     CBSBSFContext common;
45 
46     int done_first_au;
47 
48     int aud;
49     H264RawAUD aud_nal;
50 
51     AVRational sample_aspect_ratio;
52 
53     int overscan_appropriate_flag;
54 
55     int video_format;
56     int video_full_range_flag;
57     int colour_primaries;
58     int transfer_characteristics;
59     int matrix_coefficients;
60 
61     int chroma_sample_loc_type;
62 
63     AVRational tick_rate;
64     int fixed_frame_rate_flag;
65     int zero_new_constraint_set_flags;
66 
67     int crop_left;
68     int crop_right;
69     int crop_top;
70     int crop_bottom;
71 
72     const char *sei_user_data;
73     SEIRawUserDataUnregistered sei_user_data_payload;
74 
75     int delete_filler;
76 
77     int display_orientation;
78     double rotate;
79     int flip;
80     H264RawSEIDisplayOrientation display_orientation_payload;
81 
82     int level;
83 } H264MetadataContext;
84 
85 
h264_metadata_insert_aud(AVBSFContext *bsf, CodedBitstreamFragment *au)86 static int h264_metadata_insert_aud(AVBSFContext *bsf,
87                                     CodedBitstreamFragment *au)
88 {
89     H264MetadataContext *ctx = bsf->priv_data;
90     int primary_pic_type_mask = 0xff;
91     int err, i, j;
92 
93     static const int primary_pic_type_table[] = {
94         0x084, // 2, 7
95         0x0a5, // 0, 2, 5, 7
96         0x0e7, // 0, 1, 2, 5, 6, 7
97         0x210, // 4, 9
98         0x318, // 3, 4, 8, 9
99         0x294, // 2, 4, 7, 9
100         0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9
101         0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
102     };
103 
104     for (i = 0; i < au->nb_units; i++) {
105         if (au->units[i].type == H264_NAL_SLICE ||
106             au->units[i].type == H264_NAL_IDR_SLICE) {
107             H264RawSlice *slice = au->units[i].content;
108             for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) {
109                 if (!(primary_pic_type_table[j] &
110                       (1 << slice->header.slice_type)))
111                     primary_pic_type_mask &= ~(1 << j);
112             }
113         }
114     }
115     for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++)
116         if (primary_pic_type_mask & (1 << j))
117             break;
118     if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) {
119         av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: "
120                "invalid slice types?\n");
121         return AVERROR_INVALIDDATA;
122     }
123 
124     ctx->aud_nal = (H264RawAUD) {
125         .nal_unit_header.nal_unit_type = H264_NAL_AUD,
126         .primary_pic_type = j,
127     };
128 
129     err = ff_cbs_insert_unit_content(au, 0, H264_NAL_AUD,
130                                      &ctx->aud_nal, NULL);
131     if (err < 0) {
132         av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
133         return err;
134     }
135 
136     return 0;
137 }
138 
h264_metadata_update_sps(AVBSFContext *bsf, H264RawSPS *sps)139 static int h264_metadata_update_sps(AVBSFContext *bsf,
140                                     H264RawSPS *sps)
141 {
142     H264MetadataContext *ctx = bsf->priv_data;
143     int need_vui = 0;
144     int crop_unit_x, crop_unit_y;
145 
146     if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) {
147         // Table E-1.
148         static const AVRational sar_idc[] = {
149             {   0,  0 }, // Unspecified (never written here).
150             {   1,  1 }, {  12, 11 }, {  10, 11 }, {  16, 11 },
151             {  40, 33 }, {  24, 11 }, {  20, 11 }, {  32, 11 },
152             {  80, 33 }, {  18, 11 }, {  15, 11 }, {  64, 33 },
153             { 160, 99 }, {   4,  3 }, {   3,  2 }, {   2,  1 },
154         };
155         int num, den, i;
156 
157         av_reduce(&num, &den, ctx->sample_aspect_ratio.num,
158                   ctx->sample_aspect_ratio.den, 65535);
159 
160         for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) {
161             if (num == sar_idc[i].num &&
162                 den == sar_idc[i].den)
163                 break;
164         }
165         if (i == FF_ARRAY_ELEMS(sar_idc)) {
166             sps->vui.aspect_ratio_idc = 255;
167             sps->vui.sar_width  = num;
168             sps->vui.sar_height = den;
169         } else {
170             sps->vui.aspect_ratio_idc = i;
171         }
172         sps->vui.aspect_ratio_info_present_flag = 1;
173         need_vui = 1;
174     }
175 
176 #define SET_VUI_FIELD(field) do { \
177         if (ctx->field >= 0) { \
178             sps->vui.field = ctx->field; \
179             need_vui = 1; \
180         } \
181     } while (0)
182 
183     if (ctx->overscan_appropriate_flag >= 0) {
184         SET_VUI_FIELD(overscan_appropriate_flag);
185         sps->vui.overscan_info_present_flag = 1;
186     }
187 
188     if (ctx->video_format             >= 0 ||
189         ctx->video_full_range_flag    >= 0 ||
190         ctx->colour_primaries         >= 0 ||
191         ctx->transfer_characteristics >= 0 ||
192         ctx->matrix_coefficients      >= 0) {
193 
194         SET_VUI_FIELD(video_format);
195 
196         SET_VUI_FIELD(video_full_range_flag);
197 
198         if (ctx->colour_primaries         >= 0 ||
199             ctx->transfer_characteristics >= 0 ||
200             ctx->matrix_coefficients      >= 0) {
201 
202             SET_VUI_FIELD(colour_primaries);
203             SET_VUI_FIELD(transfer_characteristics);
204             SET_VUI_FIELD(matrix_coefficients);
205 
206             sps->vui.colour_description_present_flag = 1;
207         }
208         sps->vui.video_signal_type_present_flag = 1;
209     }
210 
211     if (ctx->chroma_sample_loc_type >= 0) {
212         sps->vui.chroma_sample_loc_type_top_field =
213             ctx->chroma_sample_loc_type;
214         sps->vui.chroma_sample_loc_type_bottom_field =
215             ctx->chroma_sample_loc_type;
216         sps->vui.chroma_loc_info_present_flag = 1;
217         need_vui = 1;
218     }
219 
220     if (ctx->tick_rate.num && ctx->tick_rate.den) {
221         int num, den;
222 
223         av_reduce(&num, &den, ctx->tick_rate.num, ctx->tick_rate.den,
224                   UINT32_MAX > INT_MAX ? UINT32_MAX : INT_MAX);
225 
226         sps->vui.time_scale        = num;
227         sps->vui.num_units_in_tick = den;
228 
229         sps->vui.timing_info_present_flag = 1;
230         need_vui = 1;
231     }
232     SET_VUI_FIELD(fixed_frame_rate_flag);
233     if (ctx->zero_new_constraint_set_flags) {
234         sps->constraint_set4_flag = 0;
235         sps->constraint_set5_flag = 0;
236     }
237 
238     if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) {
239         crop_unit_x = 1;
240         crop_unit_y = 2 - sps->frame_mbs_only_flag;
241     } else {
242         crop_unit_x = 1 + (sps->chroma_format_idc < 3);
243         crop_unit_y = (1 + (sps->chroma_format_idc < 2)) *
244                        (2 - sps->frame_mbs_only_flag);
245     }
246 #define CROP(border, unit) do { \
247         if (ctx->crop_ ## border >= 0) { \
248             if (ctx->crop_ ## border % unit != 0) { \
249                 av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \
250                        "must be a multiple of %d.\n", #border, unit); \
251                 return AVERROR(EINVAL); \
252             } \
253             sps->frame_crop_ ## border ## _offset = \
254                   ctx->crop_ ## border / unit; \
255             sps->frame_cropping_flag = 1; \
256         } \
257     } while (0)
258     CROP(left,   crop_unit_x);
259     CROP(right,  crop_unit_x);
260     CROP(top,    crop_unit_y);
261     CROP(bottom, crop_unit_y);
262 #undef CROP
263 
264     if (ctx->level != LEVEL_UNSET) {
265         int level_idc;
266 
267         if (ctx->level == LEVEL_AUTO) {
268             const H264LevelDescriptor *desc;
269             int64_t bit_rate;
270             int width, height, dpb_frames;
271             int framerate;
272 
273             if (sps->vui.nal_hrd_parameters_present_flag) {
274                 bit_rate = (sps->vui.nal_hrd_parameters.bit_rate_value_minus1[0] + 1) *
275                     (INT64_C(1) << (sps->vui.nal_hrd_parameters.bit_rate_scale + 6));
276             } else if (sps->vui.vcl_hrd_parameters_present_flag) {
277                 bit_rate = (sps->vui.vcl_hrd_parameters.bit_rate_value_minus1[0] + 1) *
278                     (INT64_C(1) << (sps->vui.vcl_hrd_parameters.bit_rate_scale + 6));
279                 // Adjust for VCL vs. NAL limits.
280                 bit_rate = bit_rate * 6 / 5;
281             } else {
282                 bit_rate = 0;
283             }
284 
285             // Don't use max_dec_frame_buffering if it is only inferred.
286             dpb_frames = sps->vui.bitstream_restriction_flag ?
287                 sps->vui.max_dec_frame_buffering : H264_MAX_DPB_FRAMES;
288 
289             width  = 16 * (sps->pic_width_in_mbs_minus1 + 1);
290             height = 16 * (sps->pic_height_in_map_units_minus1 + 1) *
291                 (2 - sps->frame_mbs_only_flag);
292 
293             if (sps->vui.timing_info_present_flag)
294                 framerate = sps->vui.time_scale / sps->vui.num_units_in_tick / 2;
295             else
296                 framerate = 0;
297 
298             desc = ff_h264_guess_level(sps->profile_idc, bit_rate, framerate,
299                                        width, height, dpb_frames);
300             if (desc) {
301                 level_idc = desc->level_idc;
302             } else {
303                 av_log(bsf, AV_LOG_WARNING, "Stream does not appear to "
304                        "conform to any level: using level 6.2.\n");
305                 level_idc = 62;
306             }
307         } else {
308             level_idc = ctx->level;
309         }
310 
311         if (level_idc == 9) {
312             if (sps->profile_idc == 66 ||
313                 sps->profile_idc == 77 ||
314                 sps->profile_idc == 88) {
315                 sps->level_idc = 11;
316                 sps->constraint_set3_flag = 1;
317             } else {
318                 sps->level_idc = 9;
319             }
320         } else {
321             sps->level_idc = level_idc;
322         }
323     }
324 
325     if (need_vui)
326         sps->vui_parameters_present_flag = 1;
327 
328     return 0;
329 }
330 
h264_metadata_handle_display_orientation(AVBSFContext *bsf, AVPacket *pkt, CodedBitstreamFragment *au, int seek_point)331 static int h264_metadata_handle_display_orientation(AVBSFContext *bsf,
332                                                     AVPacket *pkt,
333                                                     CodedBitstreamFragment *au,
334                                                     int seek_point)
335 {
336     H264MetadataContext *ctx = bsf->priv_data;
337     SEIRawMessage *message;
338     int err;
339 
340     message = NULL;
341     while (ff_cbs_sei_find_message(ctx->common.output, au,
342                                    SEI_TYPE_DISPLAY_ORIENTATION,
343                                    &message) == 0) {
344         H264RawSEIDisplayOrientation *disp = message->payload;
345         double angle = disp->anticlockwise_rotation * 180.0 / 65536.0;
346         int32_t *matrix;
347 
348         matrix = av_malloc(9 * sizeof(int32_t));
349         if (!matrix)
350             return AVERROR(ENOMEM);
351 
352         /* av_display_rotation_set() expects the angle in the clockwise
353          * direction, hence the first minus.
354          * The below code applies the flips after the rotation, yet
355          * the H.2645 specs require flipping to be applied first.
356          * Because of R O(phi) = O(-phi) R (where R is flipping around
357          * an arbitatry axis and O(phi) is the proper rotation by phi)
358          * we can create display matrices as desired by negating
359          * the degree once for every flip applied. */
360         angle = -angle * (1 - 2 * !!disp->hor_flip) * (1 - 2 * !!disp->ver_flip);
361 
362         av_display_rotation_set(matrix, angle);
363         av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip);
364 
365         // If there are multiple display orientation messages in an
366         // access unit, then the last one added to the packet (i.e.
367         // the first one in the access unit) will prevail.
368         err = av_packet_add_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX,
369                                       (uint8_t*)matrix,
370                                       9 * sizeof(int32_t));
371         if (err < 0) {
372             av_log(bsf, AV_LOG_ERROR, "Failed to attach extracted "
373                    "displaymatrix side data to packet.\n");
374             av_free(matrix);
375             return AVERROR(ENOMEM);
376         }
377     }
378 
379     if (ctx->display_orientation == BSF_ELEMENT_REMOVE ||
380         ctx->display_orientation == BSF_ELEMENT_INSERT) {
381         ff_cbs_sei_delete_message_type(ctx->common.output, au,
382                                        SEI_TYPE_DISPLAY_ORIENTATION);
383     }
384 
385     if (ctx->display_orientation == BSF_ELEMENT_INSERT) {
386         H264RawSEIDisplayOrientation *disp =
387             &ctx->display_orientation_payload;
388         uint8_t *data;
389         size_t size;
390         int write = 0;
391 
392         data = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size);
393         if (data && size >= 9 * sizeof(int32_t)) {
394             int32_t matrix[9];
395             double dmatrix[9];
396             int hflip, vflip, i;
397             double scale_x, scale_y, angle;
398 
399             memcpy(matrix, data, sizeof(matrix));
400 
401             for (i = 0; i < 9; i++)
402                 dmatrix[i] = matrix[i] / 65536.0;
403 
404             // Extract scale factors.
405             scale_x = hypot(dmatrix[0], dmatrix[3]);
406             scale_y = hypot(dmatrix[1], dmatrix[4]);
407 
408             // Select flips to make the main diagonal positive.
409             hflip = dmatrix[0] < 0.0;
410             vflip = dmatrix[4] < 0.0;
411             if (hflip)
412                 scale_x = -scale_x;
413             if (vflip)
414                 scale_y = -scale_y;
415 
416             // Rescale.
417             for (i = 0; i < 9; i += 3) {
418                 dmatrix[i]     /= scale_x;
419                 dmatrix[i + 1] /= scale_y;
420             }
421 
422             // Extract rotation.
423             angle = atan2(dmatrix[3], dmatrix[0]);
424 
425             if (!(angle >= -M_PI && angle <= M_PI) ||
426                 matrix[2] != 0.0 || matrix[5] != 0.0 ||
427                 matrix[6] != 0.0 || matrix[7] != 0.0) {
428                 av_log(bsf, AV_LOG_WARNING, "Input display matrix is not "
429                        "representable in H.264 parameters.\n");
430             } else {
431                 disp->hor_flip = hflip;
432                 disp->ver_flip = vflip;
433                 disp->anticlockwise_rotation =
434                     (uint16_t)rint((angle >= 0.0 ? angle
435                                                  : angle + 2 * M_PI) *
436                                    32768.0 / M_PI);
437                 write = 1;
438             }
439         }
440 
441         if (seek_point) {
442             if (!isnan(ctx->rotate)) {
443                 disp->anticlockwise_rotation =
444                     (uint16_t)rint((ctx->rotate >= 0.0 ? ctx->rotate
445                                                        : ctx->rotate + 360.0) *
446                                    65536.0 / 360.0);
447                 write = 1;
448             }
449             if (ctx->flip) {
450                 disp->hor_flip = !!(ctx->flip & FLIP_HORIZONTAL);
451                 disp->ver_flip = !!(ctx->flip & FLIP_VERTICAL);
452                 write = 1;
453             }
454         }
455 
456         if (write) {
457             disp->display_orientation_repetition_period = 1;
458 
459             err = ff_cbs_sei_add_message(ctx->common.output, au, 1,
460                                          SEI_TYPE_DISPLAY_ORIENTATION,
461                                          disp, NULL);
462             if (err < 0) {
463                 av_log(bsf, AV_LOG_ERROR, "Failed to add display orientation "
464                        "SEI message to access unit.\n");
465                 return err;
466             }
467         }
468     }
469 
470     return 0;
471 }
472 
h264_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, CodedBitstreamFragment *au)473 static int h264_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
474                                          CodedBitstreamFragment *au)
475 {
476     H264MetadataContext *ctx = bsf->priv_data;
477     int err, i, has_sps, seek_point;
478 
479     // If an AUD is present, it must be the first NAL unit.
480     if (au->nb_units && au->units[0].type == H264_NAL_AUD) {
481         if (ctx->aud == BSF_ELEMENT_REMOVE)
482             ff_cbs_delete_unit(au, 0);
483     } else {
484         if (pkt && ctx->aud == BSF_ELEMENT_INSERT) {
485             err = h264_metadata_insert_aud(bsf, au);
486             if (err < 0)
487                 return err;
488         }
489     }
490 
491     has_sps = 0;
492     for (i = 0; i < au->nb_units; i++) {
493         if (au->units[i].type == H264_NAL_SPS) {
494             err = h264_metadata_update_sps(bsf, au->units[i].content);
495             if (err < 0)
496                 return err;
497             has_sps = 1;
498         }
499     }
500 
501     if (pkt) {
502         // The current packet should be treated as a seek point for metadata
503         // insertion if any of:
504         // - It is the first packet in the stream.
505         // - It contains an SPS, indicating that a sequence might start here.
506         // - It is marked as containing a key frame.
507         seek_point = !ctx->done_first_au || has_sps ||
508             (pkt->flags & AV_PKT_FLAG_KEY);
509     } else {
510         seek_point = 0;
511     }
512 
513     if (ctx->sei_user_data && seek_point) {
514         err = ff_cbs_sei_add_message(ctx->common.output, au, 1,
515                                      SEI_TYPE_USER_DATA_UNREGISTERED,
516                                      &ctx->sei_user_data_payload, NULL);
517         if (err < 0) {
518             av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
519                    "message to access unit.\n");
520             return err;
521         }
522     }
523 
524     if (ctx->delete_filler) {
525         for (i = au->nb_units - 1; i >= 0; i--) {
526             if (au->units[i].type == H264_NAL_FILLER_DATA) {
527                 ff_cbs_delete_unit(au, i);
528                 continue;
529             }
530         }
531 
532         ff_cbs_sei_delete_message_type(ctx->common.output, au,
533                                        SEI_TYPE_FILLER_PAYLOAD);
534     }
535 
536     if (pkt && ctx->display_orientation != BSF_ELEMENT_PASS) {
537         err = h264_metadata_handle_display_orientation(bsf, pkt, au,
538                                                        seek_point);
539         if (err < 0)
540             return err;
541     }
542 
543     if (pkt)
544         ctx->done_first_au = 1;
545 
546     return 0;
547 }
548 
549 static const CBSBSFType h264_metadata_type = {
550     .codec_id        = AV_CODEC_ID_H264,
551     .fragment_name   = "access unit",
552     .unit_name       = "NAL unit",
553     .update_fragment = &h264_metadata_update_fragment,
554 };
555 
h264_metadata_init(AVBSFContext *bsf)556 static int h264_metadata_init(AVBSFContext *bsf)
557 {
558     H264MetadataContext *ctx = bsf->priv_data;
559 
560     if (ctx->sei_user_data) {
561         SEIRawUserDataUnregistered *udu = &ctx->sei_user_data_payload;
562         int i, j;
563 
564         // Parse UUID.  It must be a hex string of length 32, possibly
565         // containing '-'s between hex digits (which we ignore).
566         for (i = j = 0; j < 32 && i < 64 && ctx->sei_user_data[i]; i++) {
567             int c, v;
568             c = ctx->sei_user_data[i];
569             if (c == '-') {
570                 continue;
571             } else if (av_isxdigit(c)) {
572                 c = av_tolower(c);
573                 v = (c <= '9' ? c - '0' : c - 'a' + 10);
574             } else {
575                 break;
576             }
577             if (j & 1)
578                 udu->uuid_iso_iec_11578[j / 2] |= v;
579             else
580                 udu->uuid_iso_iec_11578[j / 2] = v << 4;
581             ++j;
582         }
583         if (j == 32 && ctx->sei_user_data[i] == '+') {
584             udu->data = (uint8_t*)ctx->sei_user_data + i + 1;
585             udu->data_length = strlen(udu->data) + 1;
586         } else {
587             av_log(bsf, AV_LOG_ERROR, "Invalid user data: "
588                    "must be \"UUID+string\".\n");
589             return AVERROR(EINVAL);
590         }
591     }
592 
593     return ff_cbs_bsf_generic_init(bsf, &h264_metadata_type);
594 }
595 
596 #define OFFSET(x) offsetof(H264MetadataContext, x)
597 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
598 static const AVOption h264_metadata_options[] = {
599     BSF_ELEMENT_OPTIONS_PIR("aud", "Access Unit Delimiter NAL units",
600                             aud, FLAGS),
601 
602     { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)",
603         OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL,
604         { .dbl = 0.0 }, 0, 65535, FLAGS },
605 
606     { "overscan_appropriate_flag", "Set VUI overscan appropriate flag",
607         OFFSET(overscan_appropriate_flag), AV_OPT_TYPE_INT,
608         { .i64 = -1 }, -1, 1, FLAGS },
609 
610     { "video_format", "Set video format (table E-2)",
611         OFFSET(video_format), AV_OPT_TYPE_INT,
612         { .i64 = -1 }, -1, 7, FLAGS},
613     { "video_full_range_flag", "Set video full range flag",
614         OFFSET(video_full_range_flag), AV_OPT_TYPE_INT,
615         { .i64 = -1 }, -1, 1, FLAGS },
616     { "colour_primaries", "Set colour primaries (table E-3)",
617         OFFSET(colour_primaries), AV_OPT_TYPE_INT,
618         { .i64 = -1 }, -1, 255, FLAGS },
619     { "transfer_characteristics", "Set transfer characteristics (table E-4)",
620         OFFSET(transfer_characteristics), AV_OPT_TYPE_INT,
621         { .i64 = -1 }, -1, 255, FLAGS },
622     { "matrix_coefficients", "Set matrix coefficients (table E-5)",
623         OFFSET(matrix_coefficients), AV_OPT_TYPE_INT,
624         { .i64 = -1 }, -1, 255, FLAGS },
625 
626     { "chroma_sample_loc_type", "Set chroma sample location type (figure E-1)",
627         OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT,
628         { .i64 = -1 }, -1, 5, FLAGS },
629 
630     { "tick_rate", "Set VUI tick rate (time_scale / num_units_in_tick)",
631         OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL,
632         { .dbl = 0.0 }, 0, UINT_MAX, FLAGS },
633     { "fixed_frame_rate_flag", "Set VUI fixed frame rate flag",
634         OFFSET(fixed_frame_rate_flag), AV_OPT_TYPE_INT,
635         { .i64 = -1 }, -1, 1, FLAGS },
636     { "zero_new_constraint_set_flags", "Set constraint_set4_flag / constraint_set5_flag to zero",
637         OFFSET(zero_new_constraint_set_flags), AV_OPT_TYPE_BOOL,
638         { .i64 = 0 }, 0, 1, FLAGS },
639 
640     { "crop_left", "Set left border crop offset",
641         OFFSET(crop_left), AV_OPT_TYPE_INT,
642         { .i64 = -1 }, -1, H264_MAX_WIDTH, FLAGS },
643     { "crop_right", "Set right border crop offset",
644         OFFSET(crop_right), AV_OPT_TYPE_INT,
645         { .i64 = -1 }, -1, H264_MAX_WIDTH, FLAGS },
646     { "crop_top", "Set top border crop offset",
647         OFFSET(crop_top), AV_OPT_TYPE_INT,
648         { .i64 = -1 }, -1, H264_MAX_HEIGHT, FLAGS },
649     { "crop_bottom", "Set bottom border crop offset",
650         OFFSET(crop_bottom), AV_OPT_TYPE_INT,
651         { .i64 = -1 }, -1, H264_MAX_HEIGHT, FLAGS },
652 
653     { "sei_user_data", "Insert SEI user data (UUID+string)",
654         OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
655 
656     { "delete_filler", "Delete all filler (both NAL and SEI)",
657         OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS},
658 
659     BSF_ELEMENT_OPTIONS_PIRE("display_orientation",
660                              "Display orientation SEI",
661                              display_orientation, FLAGS),
662 
663     { "rotate", "Set rotation in display orientation SEI (anticlockwise angle in degrees)",
664         OFFSET(rotate), AV_OPT_TYPE_DOUBLE,
665         { .dbl = NAN }, -360.0, +360.0, FLAGS },
666     { "flip", "Set flip in display orientation SEI",
667         OFFSET(flip), AV_OPT_TYPE_FLAGS,
668         { .i64 = 0 }, 0, FLIP_HORIZONTAL | FLIP_VERTICAL, FLAGS, "flip" },
669     { "horizontal", "Set hor_flip",
670         0, AV_OPT_TYPE_CONST,
671         { .i64 = FLIP_HORIZONTAL }, .flags = FLAGS, .unit = "flip" },
672     { "vertical",   "Set ver_flip",
673         0, AV_OPT_TYPE_CONST,
674         { .i64 = FLIP_VERTICAL },   .flags = FLAGS, .unit = "flip" },
675 
676     { "level", "Set level (table A-1)",
677         OFFSET(level), AV_OPT_TYPE_INT,
678         { .i64 = LEVEL_UNSET }, LEVEL_UNSET, 0xff, FLAGS, "level" },
679     { "auto", "Attempt to guess level from stream properties",
680         0, AV_OPT_TYPE_CONST,
681         { .i64 = LEVEL_AUTO }, .flags = FLAGS, .unit = "level" },
682 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
683         { .i64 = value },      .flags = FLAGS, .unit = "level"
684     { LEVEL("1",   10) },
685     { LEVEL("1b",   9) },
686     { LEVEL("1.1", 11) },
687     { LEVEL("1.2", 12) },
688     { LEVEL("1.3", 13) },
689     { LEVEL("2",   20) },
690     { LEVEL("2.1", 21) },
691     { LEVEL("2.2", 22) },
692     { LEVEL("3",   30) },
693     { LEVEL("3.1", 31) },
694     { LEVEL("3.2", 32) },
695     { LEVEL("4",   40) },
696     { LEVEL("4.1", 41) },
697     { LEVEL("4.2", 42) },
698     { LEVEL("5",   50) },
699     { LEVEL("5.1", 51) },
700     { LEVEL("5.2", 52) },
701     { LEVEL("6",   60) },
702     { LEVEL("6.1", 61) },
703     { LEVEL("6.2", 62) },
704 #undef LEVEL
705 
706     { NULL }
707 };
708 
709 static const AVClass h264_metadata_class = {
710     .class_name = "h264_metadata_bsf",
711     .item_name  = av_default_item_name,
712     .option     = h264_metadata_options,
713     .version    = LIBAVUTIL_VERSION_INT,
714 };
715 
716 static const enum AVCodecID h264_metadata_codec_ids[] = {
717     AV_CODEC_ID_H264, AV_CODEC_ID_NONE,
718 };
719 
720 const FFBitStreamFilter ff_h264_metadata_bsf = {
721     .p.name         = "h264_metadata",
722     .p.codec_ids    = h264_metadata_codec_ids,
723     .p.priv_class   = &h264_metadata_class,
724     .priv_data_size = sizeof(H264MetadataContext),
725     .init           = &h264_metadata_init,
726     .close          = &ff_cbs_bsf_generic_close,
727     .filter         = &ff_cbs_bsf_generic_filter,
728 };
729