mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 10:10:32 +00:00
typefind: Add typefinder for VVC/H.266
H.266 NAL unit header syntax [1] is similar to H.265 NAL unit header syntax[2]: ``` H.265 H.266 +---------------+---------------+ +---------------+---------------+ |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |F| NALType | LayerId | TID | |F|U| LayerId | NALType | TID | +-------------+-----------+-----+ +-------------+-----------------+ Where * F: `forbidden_zero_bit`: f(1) * U: `nuh_reserved_zero_bit`: u(1) only H.266 * LayerId: `nuh_layer_id`: u(6) * NALType: `nal_unit_type`: u(6) in H.265 and u(5) in H.266 * TID: `nuh_temporal_id_plus1`: u(3) ``` NAL unit types have different values: | NALType | H.265 | H.266 | |----------|------------------------------------|---------------------------| | VPS | HEVC_NAL_VPS(32) | VVC_VPS_NUT(14) | | SPS | HEVC_NAL_SPS(33) | VVC_SPS_NUT(15) | | PPS | HEVC_NAL_PPS(34) | VVC_PPS_NUT(16) | | IRAP | BLA_W_LP(19)..HEVC_NAL_CRA_NUT(21) | IDR_W_RADL(7)..CRA_NUT(9) | Implementation of `h266_video_type_find` is based on `h265_video_type_find` with next differences: - NAL unit header syntax for H.265 and H.266 - Diff NAL unit types values - Avoid checking nuh_layer_id is zero. H.266 conformance test suite[3] contains examples with more than one layer. This typefind was tested with H.266 conformance test suite [3]. Also, with the help of fluster[4], with H.264 and H.265 conformance test suites to avoid regresions. Pending test vectors to fix: - 8b422_H_Sony_4 - DEBLOCKING_E_Ericsson_3 [1] https://www.itu.int/rec/T-REC-H.266 [2] https://www.itu.int/rec/T-REC-H.265 [3] https://www.itu.int/wftp3/av-arch/jvet-site/bitstream_exchange/VVC/draft_conformance/draft6/ [4] https://github.com/fluendo/fluster/ Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7339>
This commit is contained in:
parent
5d25ab1306
commit
dc4dd415f0
3 changed files with 98 additions and 0 deletions
|
@ -3028,6 +3028,100 @@ h265_video_type_find (GstTypeFind * tf, gpointer unused)
|
|||
}
|
||||
}
|
||||
|
||||
/*** video/x-h266 H266 elementary video stream ***/
|
||||
|
||||
static GstStaticCaps h266_video_caps =
|
||||
GST_STATIC_CAPS ("video/x-h266,stream-format=byte-stream");
|
||||
|
||||
#define H266_VIDEO_CAPS gst_static_caps_get(&h266_video_caps)
|
||||
|
||||
#define H266_MAX_PROBE_LENGTH (128 * 1024) /* 128kB for HD should be enough. */
|
||||
|
||||
static void
|
||||
h266_video_type_find (GstTypeFind * tf, gpointer unused)
|
||||
{
|
||||
DataScanCtx c = { 0, NULL, 0 };
|
||||
|
||||
/* Stream consists of: a series of sync codes (00 00 00 01) followed
|
||||
* by NALs
|
||||
*/
|
||||
gboolean seen_irap = FALSE;
|
||||
gboolean seen_vps = FALSE;
|
||||
gboolean seen_sps = FALSE;
|
||||
gboolean seen_pps = FALSE;
|
||||
int nuh, nut;
|
||||
int good = 0;
|
||||
int bad = 0;
|
||||
|
||||
while (c.offset < H266_MAX_PROBE_LENGTH) {
|
||||
if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 5)))
|
||||
break;
|
||||
|
||||
if (IS_MPEG_HEADER (c.data)) {
|
||||
/* forbidden_zero_bit(1) | nuh_reserved_zero_bit(1) | nuh_layer_id(6) */
|
||||
nuh = c.data[3] & 0xc0;
|
||||
/* nal_unit_type(5) | nuh_temporal_id_plus1(3) */
|
||||
nut = c.data[4] & 0xf8;
|
||||
|
||||
/* if forbidden bit and nuh_reserved_zero_bit are different to 0 won't be h266 */
|
||||
if (nuh) {
|
||||
bad++;
|
||||
break;
|
||||
}
|
||||
nut = nut >> 3;
|
||||
|
||||
/* if nuh_temporal_id_plus1 is zero then it won't be h266 */
|
||||
if (!(c.data[4] & 0x07)) {
|
||||
bad++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* collect statistics about the NAL types */
|
||||
if ((nut >= 0 && nut <= 27)) {
|
||||
if (nut == 14)
|
||||
seen_vps = TRUE;
|
||||
else if (nut == 15)
|
||||
seen_sps = TRUE;
|
||||
else if (nut == 16)
|
||||
seen_pps = TRUE;
|
||||
else if (nut >= 7 && nut <= 9) {
|
||||
/* BLA, IDR and CRA pictures are belongs to be IRAP picture */
|
||||
/* we are not counting the reserved IRAP pictures (22 and 23) to good */
|
||||
seen_irap = TRUE;
|
||||
}
|
||||
|
||||
good++;
|
||||
} else if (nut >= 27) {
|
||||
/* reserved values are counting as bad */
|
||||
bad++;
|
||||
}
|
||||
|
||||
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, vps:%d, irap:%d", good, bad,
|
||||
seen_pps, seen_sps, seen_vps, seen_irap);
|
||||
|
||||
if (seen_sps && seen_pps && seen_irap && good >= 10 && bad < 4) {
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H266_VIDEO_CAPS);
|
||||
return;
|
||||
}
|
||||
|
||||
data_scan_ctx_advance (tf, &c, 5);
|
||||
}
|
||||
data_scan_ctx_advance (tf, &c, 1);
|
||||
}
|
||||
|
||||
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, vps:%d, irap:%d", good, bad,
|
||||
seen_pps, seen_sps, seen_vps, seen_irap);
|
||||
|
||||
if (good >= 2 && bad == 0) {
|
||||
GstTypeFindProbability probability = GST_TYPE_FIND_POSSIBLE;
|
||||
|
||||
if (seen_pps && seen_sps && seen_vps)
|
||||
probability = GST_TYPE_FIND_LIKELY;
|
||||
|
||||
gst_type_find_suggest (tf, probability, H266_VIDEO_CAPS);
|
||||
}
|
||||
}
|
||||
|
||||
/*** video/mpeg video stream ***/
|
||||
|
||||
static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
|
||||
|
@ -6742,6 +6836,8 @@ GST_TYPE_FIND_REGISTER_DEFINE (h264_video, "video/x-h264", GST_RANK_PRIMARY,
|
|||
h264_video_type_find, "h264,x264,264", H264_VIDEO_CAPS, NULL, NULL);
|
||||
GST_TYPE_FIND_REGISTER_DEFINE (h265_video, "video/x-h265", GST_RANK_PRIMARY,
|
||||
h265_video_type_find, "h265,x265,265", H265_VIDEO_CAPS, NULL, NULL);
|
||||
GST_TYPE_FIND_REGISTER_DEFINE (h266_video, "video/x-h266", GST_RANK_PRIMARY,
|
||||
h266_video_type_find, "h266,266", H266_VIDEO_CAPS, NULL, NULL);
|
||||
GST_TYPE_FIND_REGISTER_DEFINE (nuv, "video/x-nuv", GST_RANK_SECONDARY,
|
||||
nuv_type_find, "nuv", NUV_CAPS, NULL, NULL);
|
||||
/* ISO formats */
|
||||
|
|
|
@ -126,6 +126,7 @@ plugin_init (GstPlugin * plugin)
|
|||
GST_TYPE_FIND_REGISTER (h263_video, plugin);
|
||||
GST_TYPE_FIND_REGISTER (h264_video, plugin);
|
||||
GST_TYPE_FIND_REGISTER (h265_video, plugin);
|
||||
GST_TYPE_FIND_REGISTER (h266_video, plugin);
|
||||
GST_TYPE_FIND_REGISTER (nuv, plugin);
|
||||
/* ISO formats */
|
||||
GST_TYPE_FIND_REGISTER (m4a, plugin);
|
||||
|
|
|
@ -120,6 +120,7 @@ GST_TYPE_FIND_REGISTER_DECLARE (mpeg4_video);
|
|||
GST_TYPE_FIND_REGISTER_DECLARE (h263_video);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (h264_video);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (h265_video);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (h266_video);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (nuv);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (m4a);
|
||||
GST_TYPE_FIND_REGISTER_DECLARE (q3gp);
|
||||
|
|
Loading…
Reference in a new issue