diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index 50dba86ed0..d271b36998 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -44,6 +44,7 @@ gst_h264_video_quant_matrix_8x8_get_zigzag_from_raster gst_h264_video_quant_matrix_8x8_get_raster_from_zigzag gst_h264_video_quant_matrix_4x4_get_zigzag_from_raster gst_h264_video_quant_matrix_4x4_get_raster_from_zigzag +gst_h264_video_calculate_framerate diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index db5cd8dfa1..a4ae3a618f 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1875,3 +1875,78 @@ gst_h264_video_quant_matrix_4x4_get_raster_from_zigzag (guint8 out_quant[16], for (i = 0; i < 16; i++) out_quant[zigzag_4x4[i]] = quant[i]; } + +/** + * gst_h264_video_calculate_framerate: + * @sps: Current Sequence Parameter Set + * @field_pic_flag: Current @field_pic_flag, obtained from latest slice header + * @pic_struct: @pic_struct value if available, 0 otherwise + * @fps_num: (out): The resulting fps numerator + * @fps_den: (out): The resulting fps denominator + * + * Calculate framerate of a video sequence using @sps VUI information, + * @field_pic_flag from a slice header and @pic_struct from #GstH264PicTiming SEI + * message. + * + * If framerate is variable or can't be determined, @fps_num will be set to 0 + * and @fps_den to 1. + */ +void +gst_h264_video_calculate_framerate (const GstH264SPS * sps, + guint field_pic_flag, guint pic_struct, gint * fps_num, gint * fps_den) +{ + gint num = 0; + gint den = 1; + + /* To calculate framerate, we use this formula: + * time_scale 1 1 + * fps = ----------------- x --------------- x ------------------------ + * num_units_in_tick DeltaTfiDivisor (field_pic_flag ? 2 : 1) + * + * See H264 specification E2.1 for more details. + */ + + if (sps) { + if (sps->vui_parameters_present_flag) { + const GstH264VUIParams *vui = &sps->vui_parameters; + if (vui->timing_info_present_flag && vui->fixed_frame_rate_flag) { + int delta_tfi_divisor = 1; + num = vui->time_scale; + den = vui->num_units_in_tick; + + if (vui->pic_struct_present_flag) { + switch (pic_struct) { + case 1: + case 2: + delta_tfi_divisor = 1; + break; + case 0: + case 3: + case 4: + delta_tfi_divisor = 2; + break; + case 5: + case 6: + delta_tfi_divisor = 3; + break; + case 7: + delta_tfi_divisor = 4; + break; + case 8: + delta_tfi_divisor = 6; + break; + } + } else { + delta_tfi_divisor = field_pic_flag ? 1 : 2; + } + den *= delta_tfi_divisor; + + /* Picture is two fields ? */ + den *= (field_pic_flag ? 2 : 1); + } + } + } + + *fps_num = num; + *fps_den = den; +} diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index dd0b26b0bf..397d9a5e0e 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -781,6 +781,9 @@ void gst_h264_video_quant_matrix_4x4_get_zigzag_from_raster (guint8 out_quant void gst_h264_video_quant_matrix_4x4_get_raster_from_zigzag (guint8 out_quant[16], const guint8 quant[16]); +void gst_h264_video_calculate_framerate (const GstH264SPS * sps, guint field_pic_flag, + guint pic_struct, gint * fps_num, gint * fps_den); + G_END_DECLS #endif