• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Gstreamer
2  * Copyright (C) <2011> Intel Corporation
3  * Copyright (C) <2011> Collabora Ltd.
4  * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 #include <gst/check/gstcheck.h>
22 #include <gst/codecparsers/gsth264parser.h>
23 
24 static guint8 slice_dpa[] = {
25   0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x03, 0x00,
26   0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00,
27   0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00,
28   0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00,
29   0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00,
30   0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00,
31   0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00,
32   0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x2e, 0x00,
33   0x2f, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00,
34   0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00,
35   0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00,
36   0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00,
37   0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00,
38   0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00,
39   0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00,
40   0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00,
41   0x5f, 0x00, 0x60, 0x00, 0x61, 0x01, 0x04, 0x00, 0xc4, 0x00, 0xa6, 0x00,
42   0xc5, 0x00, 0xab, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xd8, 0x00, 0xc6, 0x00,
43   0xe4, 0x00, 0xbe, 0x00, 0xb0, 0x00, 0xe6, 0x00, 0xb6, 0x00, 0xb7, 0x00,
44   0xb4, 0x00, 0xb5, 0x00, 0x87, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xd9, 0x00,
45   0x8c, 0x00, 0xe5, 0x00, 0xbf, 0x00, 0xb1, 0x00, 0xe7, 0x00, 0xbb, 0x00,
46   0xa3, 0x00, 0x84, 0x00, 0x85, 0x00, 0xbd, 0x00, 0x96, 0x00, 0xe8, 0x00,
47   0x86, 0x00, 0x8e, 0x00, 0x8b, 0x00, 0x9d, 0x00, 0xa9, 0x00, 0x8a, 0x01,
48   0x05, 0x00, 0x83, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x8d, 0x00, 0x97, 0x00,
49   0x88, 0x00, 0xde, 0x00, 0xf1, 0x00, 0x9e, 0x00, 0xaa, 0x00, 0xf5, 0x00,
50   0xf4, 0x00, 0xf6, 0x00, 0xa2, 0x00, 0xad, 0x00, 0xc9, 0x00, 0xc7, 0x00,
51   0xae, 0x00, 0x62, 0x00, 0x63, 0x00, 0x90, 0x00, 0x64, 0x00, 0xcb, 0x00,
52   0x65, 0x00, 0xc8, 0x00, 0xca, 0x00, 0xcf, 0x00, 0xcc, 0x00, 0xcd, 0x00,
53   0xce, 0x00, 0xe9, 0x00, 0x66, 0x00, 0xd3, 0x00, 0xd0, 0x00, 0xd1, 0x00,
54   0xaf, 0x00, 0x67, 0x00, 0x91, 0x00, 0xd6, 0x00, 0xd4, 0x00, 0xd5, 0x00,
55   0x68, 0x00, 0xeb, 0x00, 0xed, 0x00, 0x89, 0x00, 0x6a, 0x00, 0x69, 0x00,
56   0x6b, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x6e, 0x00, 0xa0, 0x00, 0x6f, 0x00,
57   0x71, 0x00, 0x70, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x74, 0x00,
58   0x76, 0x00, 0x77, 0x00, 0xea, 0x00, 0x78, 0x00, 0x7a, 0x00, 0x79, 0x00,
59   0x7b, 0x00, 0x7d, 0x00, 0x7c, 0x00, 0xa1, 0x00, 0x7f, 0x00, 0x7e, 0x00,
60   0x80, 0x00, 0x81, 0x00, 0xec, 0x00, 0xee, 0x00, 0xba, 0x01, 0x06, 0x00,
61   0xef, 0x00, 0xe1, 0x00, 0xe0, 0x00, 0xdc, 0x01, 0x07, 0x01, 0x08, 0x01,
62   0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x00, 0xdb, 0x00, 0xe2, 0x01,
63   0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x00,
64   0xdf, 0x01, 0x13, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x00,
65   0xfd, 0x00, 0xff, 0x01, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1b, 0x01,
66   0x1c, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01,
67   0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, 0x00, 0xfe, 0x01,
68   0x00, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x01,
69   0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x01, 0x31, 0x00,
70   0xe3, 0x00, 0xd7, 0x01, 0x32, 0x00, 0xf8, 0x00, 0xf9, 0x01, 0x33, 0x01,
71   0x34, 0x01, 0x35, 0x01, 0x36, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01,
72   0x3a, 0x01, 0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01,
73   0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01, 0x44, 0x01, 0x45, 0x01,
74   0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4b, 0x01,
75   0x4c, 0x00, 0x08, 0x05, 0x2e, 0x6e, 0x75, 0x6c, 0x6c, 0x0c, 0x76, 0x69,
76   0x73, 0x69, 0x62, 0x6c, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x04, 0x45,
77   0x75, 0x72, 0x6f, 0x06, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x62,
78   0x75, 0x6c, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x74, 0x68, 0x06, 0x53, 0x61,
79   0x63, 0x75, 0x74, 0x65, 0x06, 0x54, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06,
80   0x5a, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x73, 0x61, 0x63, 0x75, 0x74,
81   0x65, 0x06, 0x74, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x7a, 0x61, 0x63,
82   0x75, 0x74, 0x65, 0x07, 0x41, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07,
83   0x61, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x0c, 0x73, 0x63, 0x6f, 0x6d,
84   0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x53, 0x63, 0x6f,
85   0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x5a, 0x64,
86   0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x4c, 0x63, 0x61,
87   0x72, 0x6f, 0x6e, 0x06, 0x6c, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0a, 0x7a,
88   0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x52, 0x61,
89   0x63, 0x75, 0x74, 0x65, 0x06, 0x41, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06,
90   0x4c, 0x61, 0x63, 0x75, 0x74, 0x65, 0x07, 0x45, 0x6f, 0x67, 0x6f, 0x6e,
91   0x65, 0x6b, 0x06, 0x45, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x44, 0x63,
92   0x61, 0x72, 0x6f, 0x6e, 0x07, 0x44, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e,
93   0x06, 0x4e, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x4e, 0x63, 0x61, 0x72,
94   0x6f, 0x6e, 0x0d, 0x4f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d,
95   0x6c, 0x61, 0x75, 0x74, 0x06, 0x52, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x05,
96   0x55, 0x72, 0x69, 0x6e, 0x67, 0x09, 0x6e, 0x75, 0x6e, 0x67, 0x61, 0x64,
97   0x65, 0x73, 0x68, 0x0d, 0x55, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75,
98   0x6d, 0x6c, 0x61, 0x75, 0x74, 0x0c, 0x54, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
99   0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x72, 0x61, 0x63, 0x75, 0x74,
100   0x65, 0x06, 0x61, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x6c, 0x61, 0x63,
101   0x75, 0x74, 0x65, 0x07, 0x65, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x06,
102   0x65, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x64, 0x63, 0x61, 0x72, 0x6f,
103   0x6e, 0x07, 0x64, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x6e, 0x61,
104   0x63, 0x75, 0x74, 0x65, 0x06, 0x6e, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0d,
105   0x6f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75,
106   0x74, 0x06, 0x72, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x05, 0x75, 0x72, 0x69,
107   0x6e, 0x67, 0x0d, 0x75, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d,
108   0x6c, 0x61, 0x75, 0x74, 0x0c, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
109   0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x49, 0x64, 0x6f, 0x74, 0x61, 0x63,
110   0x63, 0x65, 0x6e, 0x74, 0x0c, 0x52, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
111   0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
112   0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x49, 0x6f, 0x67, 0x6f, 0x6e,
113   0x65, 0x6b, 0x07, 0x41, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x45,
114   0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x45, 0x64, 0x6f, 0x74, 0x61,
115   0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x47, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
116   0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x4b, 0x63, 0x6f, 0x6d, 0x6d,
117   0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x49, 0x6d, 0x61, 0x63,
118   0x72, 0x6f, 0x6e, 0x0c, 0x4c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63,
119   0x63, 0x65, 0x6e, 0x74, 0x0c, 0x4e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
120   0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x4f, 0x6d, 0x61, 0x63, 0x72, 0x6f,
121   0x6e, 0x07, 0x55, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x55, 0x6d,
122   0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x69, 0x6f, 0x67, 0x6f, 0x6e, 0x65,
123   0x6b, 0x07, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x65, 0x6d,
124   0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x65, 0x64, 0x6f, 0x74, 0x61, 0x63,
125   0x63, 0x65, 0x6e, 0x74, 0x0c, 0x67, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
126   0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6b, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
127   0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x69, 0x6d, 0x61, 0x63, 0x72,
128   0x6f, 0x6e, 0x0c, 0x6c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63,
129   0x65, 0x6e, 0x74, 0x0c, 0x6e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63,
130   0x63, 0x65, 0x6e, 0x74, 0x07, 0x6f, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e,
131   0x07, 0x75, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x75, 0x6d, 0x61,
132   0x63, 0x72, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02
133 };
134 
135 /* IDR slice, SEQ_END, IDR slice, STREAM_END */
136 static guint8 slice_eoseq_slice[] = {
137   0x00, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00,
138   0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
139   0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1,
140   0x00, 0x00, 0x00, 0x01, 0x0a,
141   0x00, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00,
142   0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
143   0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1,
144   0x00, 0x00, 0x00, 0x01, 0x0b
145 };
146 
GST_START_TEST(test_h264_parse_slice_dpa)147 GST_START_TEST (test_h264_parse_slice_dpa)
148 {
149   GstH264ParserResult res;
150   GstH264NalUnit nalu;
151 
152   GstH264NalParser *parser = gst_h264_nal_parser_new ();
153 
154   res = gst_h264_parser_identify_nalu (parser, slice_dpa, 0,
155       sizeof (slice_dpa), &nalu);
156 
157   assert_equals_int (res, GST_H264_PARSER_OK);
158   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_DPA);
159 
160   gst_h264_nal_parser_free (parser);
161 }
162 
163 GST_END_TEST;
164 
GST_START_TEST(test_h264_parse_slice_eoseq_slice)165 GST_START_TEST (test_h264_parse_slice_eoseq_slice)
166 {
167   GstH264ParserResult res;
168   GstH264NalUnit nalu;
169   GstH264NalParser *const parser = gst_h264_nal_parser_new ();
170   const guint8 *buf = slice_eoseq_slice;
171   guint n, buf_size = sizeof (slice_eoseq_slice);
172 
173   res = gst_h264_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
174 
175   assert_equals_int (res, GST_H264_PARSER_OK);
176   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_IDR);
177   assert_equals_int (nalu.size, 20);
178 
179   n = nalu.offset + nalu.size;
180   buf += n;
181   buf_size -= n;
182 
183   res = gst_h264_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
184 
185   assert_equals_int (res, GST_H264_PARSER_OK);
186   assert_equals_int (nalu.type, GST_H264_NAL_SEQ_END);
187   assert_equals_int (nalu.size, 1);
188 
189   n = nalu.offset + nalu.size;
190   buf += n;
191   buf_size -= n;
192 
193   res = gst_h264_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
194 
195   assert_equals_int (res, GST_H264_PARSER_OK);
196   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_IDR);
197   assert_equals_int (nalu.size, 20);
198 
199   n = nalu.offset + nalu.size;
200   buf += n;
201   buf_size -= n;
202 
203   res = gst_h264_parser_identify_nalu (parser, buf, 0, buf_size, &nalu);
204 
205   assert_equals_int (res, GST_H264_PARSER_OK);
206   assert_equals_int (nalu.type, GST_H264_NAL_STREAM_END);
207   assert_equals_int (nalu.size, 1);
208 
209   gst_h264_nal_parser_free (parser);
210 }
211 
212 GST_END_TEST;
213 
GST_START_TEST(test_h264_parse_slice_5bytes)214 GST_START_TEST (test_h264_parse_slice_5bytes)
215 {
216   GstH264ParserResult res;
217   GstH264NalUnit nalu;
218   GstH264NalParser *const parser = gst_h264_nal_parser_new ();
219   const guint8 *buf = slice_eoseq_slice;
220 
221   res = gst_h264_parser_identify_nalu (parser, buf, 0, 5, &nalu);
222 
223   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
224   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_IDR);
225   assert_equals_int (nalu.size, 1);
226 
227   gst_h264_nal_parser_free (parser);
228 }
229 
230 GST_END_TEST;
231 
GST_START_TEST(test_h264_parse_identify_nalu_avc)232 GST_START_TEST (test_h264_parse_identify_nalu_avc)
233 {
234   GstH264ParserResult res;
235   GstH264NalUnit nalu;
236   GstH264NalParser *const parser = gst_h264_nal_parser_new ();
237   /* Skip 3 bytes for the start code */
238   const gsize nal_size = sizeof (slice_dpa) - 3;
239   const gsize buf_size = 4 + nal_size;
240   guint8 *buf = g_new (guint8, buf_size);
241 
242   memcpy (buf + 4, slice_dpa + 3, nal_size);
243 
244   GST_WRITE_UINT16_BE (buf + 2, nal_size);
245   res = gst_h264_parser_identify_nalu_avc (parser, buf, 2, buf_size, 2, &nalu);
246 
247   assert_equals_int (res, GST_H264_PARSER_OK);
248   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_DPA);
249   assert_equals_int (nalu.offset, 4);
250   assert_equals_int (nalu.size, nal_size);
251 
252   GST_WRITE_UINT32_BE (buf, nal_size);
253   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
254 
255   assert_equals_int (res, GST_H264_PARSER_OK);
256   assert_equals_int (nalu.type, GST_H264_NAL_SLICE_DPA);
257   assert_equals_int (nalu.offset, 4);
258   assert_equals_int (nalu.size, nal_size);
259 
260   GST_WRITE_UINT32_BE (buf, G_MAXUINT32);
261   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
262 
263   assert_equals_int (res, GST_H264_PARSER_BROKEN_DATA);
264 
265   GST_WRITE_UINT32_BE (buf, G_MAXUINT32 - 2);
266   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
267 
268   assert_equals_int (res, GST_H264_PARSER_BROKEN_DATA);
269 
270   GST_WRITE_UINT32_BE (buf, G_MAXUINT32 - 3);
271   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
272 
273   assert_equals_int (res, GST_H264_PARSER_BROKEN_DATA);
274 
275   GST_WRITE_UINT32_BE (buf, G_MAXUINT32 - 4);
276   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
277 
278   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
279 
280   GST_WRITE_UINT32_BE (buf, G_MAXUINT32 - 6);
281   res = gst_h264_parser_identify_nalu_avc (parser, buf, 0, buf_size, 4, &nalu);
282 
283   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
284 
285   g_free (buf);
286   gst_h264_nal_parser_free (parser);
287 }
288 
289 GST_END_TEST;
290 
291 static guint8 nalu_sps_with_vui[] = {
292   0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x28,
293   0xac, 0xd9, 0x40, 0x78, 0x04, 0x4f, 0xde, 0x03,
294   0xd2, 0x02, 0x02, 0x02, 0x80, 0x00, 0x01, 0xf4,
295   0x80, 0x00, 0x75, 0x30, 0x4f, 0x8b, 0x16, 0xcb
296 };
297 
298 static guint8 nalu_sei_pic_timing[] = {
299   0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x01, 0x32, 0x80
300 };
301 
302 static guint8 nalu_chained_sei[] = {
303   0x00, 0x00, 0x01, 0x06, 0x01, 0x02, 0x32, 0x80,
304   0x06, 0x01, 0xc4, 0x80
305 };
306 
307 /* Content light level information SEI message */
308 static guint8 h264_sei_cll[] = {
309   0x00, 0x00, 0x00, 0x01, 0x06, 0x90, 0x04, 0x03, 0xe8, 0x01, 0x90, 0x80
310 };
311 
312 /* Mastering display colour volume information SEI message */
313 static guint8 h264_sei_mdcv[] = {
314   0x00, 0x00, 0x00, 0x01, 0x06, 0x89, 0x18, 0x84,
315   0xd0, 0x3e, 0x80, 0x33, 0x90, 0x86, 0xc4, 0x1d,
316   0x4c, 0x0b, 0xb8, 0x3d, 0x13, 0x40, 0x42, 0x00,
317   0x98, 0x96, 0x80, 0x00, 0x00, 0x03, 0x00, 0x01,
318   0x80
319 };
320 
321 /* closed caption data */
322 static guint8 h264_sei_user_data_registered[] = {
323   0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x47, 0xb5, 0x00, 0x31, 0x47, 0x41,
324   0x39, 0x34, 0x03, 0xd4,
325   0xff, 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00,
326   0x00, 0xfa, 0x00, 0x00,
327   0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
328   0xfa, 0x00, 0x00, 0xfa,
329   0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
330   0x00, 0x00, 0xfa, 0x00,
331   0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
332   0x00, 0xff, 0x80
333 };
334 
335 /* frame packing, side-by-side */
336 static guint8 h264_sei_frame_packing[] = {
337   0x00, 0x00, 0x00, 0x01, 0x06, 0x2d, 0x07, 0x81, 0x81, 0x00, 0x00, 0x03,
338   0x00, 0x01, 0x20, 0x80
339 };
340 
GST_START_TEST(test_h264_parse_invalid_sei)341 GST_START_TEST (test_h264_parse_invalid_sei)
342 {
343   GstH264ParserResult res;
344   GstH264NalUnit nalu;
345   GstH264NalParser *const parser = gst_h264_nal_parser_new ();
346   const guint8 *buf = nalu_sps_with_vui;
347   GArray *seis = NULL;
348   GstH264SEIMessage *sei;
349 
350   /* First try parsing the SEI, which will fail because there's no SPS yet */
351   res =
352       gst_h264_parser_identify_nalu (parser, nalu_sei_pic_timing, 0,
353       sizeof (nalu_sei_pic_timing), &nalu);
354   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
355   assert_equals_int (nalu.type, GST_H264_NAL_SEI);
356 
357   res = gst_h264_parser_parse_sei (parser, &nalu, &seis);
358   assert_equals_int (res, GST_H264_PARSER_BROKEN_LINK);
359   g_array_free (seis, TRUE);
360 
361   /* Inject SPS */
362   res =
363       gst_h264_parser_identify_nalu (parser, buf, 0, sizeof (nalu_sps_with_vui),
364       &nalu);
365   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
366   assert_equals_int (nalu.type, GST_H264_NAL_SPS);
367   assert_equals_int (nalu.size, 28);
368 
369   res = gst_h264_parser_parse_nal (parser, &nalu);
370   assert_equals_int (res, GST_H264_PARSER_OK);
371 
372   /* Parse the SEI again */
373   res =
374       gst_h264_parser_identify_nalu (parser, nalu_sei_pic_timing, 0,
375       sizeof (nalu_sei_pic_timing), &nalu);
376   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
377   assert_equals_int (nalu.type, GST_H264_NAL_SEI);
378 
379   res = gst_h264_parser_parse_sei (parser, &nalu, &seis);
380   assert_equals_int (res, GST_H264_PARSER_OK);
381   fail_if (seis == NULL);
382   assert_equals_int (seis->len, 1);
383   g_array_free (seis, TRUE);
384 
385   /* Parse NALU with 2 chained SEI */
386   res =
387       gst_h264_parser_identify_nalu (parser, nalu_chained_sei, 0,
388       sizeof (nalu_chained_sei), &nalu);
389   assert_equals_int (res, GST_H264_PARSER_NO_NAL_END);
390   assert_equals_int (nalu.type, GST_H264_NAL_SEI);
391 
392   res = gst_h264_parser_parse_sei (parser, &nalu, &seis);
393   assert_equals_int (res, GST_H264_PARSER_OK);
394   fail_if (seis == NULL);
395   assert_equals_int (seis->len, 2);
396   sei = &g_array_index (seis, GstH264SEIMessage, 0);
397   assert_equals_int (sei->payloadType, GST_H264_SEI_PIC_TIMING);
398 
399   sei = &g_array_index (seis, GstH264SEIMessage, 1);
400   assert_equals_int (sei->payloadType, GST_H264_SEI_RECOVERY_POINT);
401 
402   g_array_free (seis, TRUE);
403 
404   gst_h264_nal_parser_free (parser);
405 }
406 
407 GST_END_TEST;
408 
409 typedef gboolean (*SEICheckFunc) (gconstpointer a, gconstpointer b);
410 
411 static gboolean
check_sei_user_data_registered(const GstH264RegisteredUserData * a,const GstH264RegisteredUserData * b)412 check_sei_user_data_registered (const GstH264RegisteredUserData * a,
413     const GstH264RegisteredUserData * b)
414 {
415   if (a->country_code != b->country_code)
416     return FALSE;
417 
418   if ((a->country_code == 0xff) &&
419       (a->country_code_extension != b->country_code_extension))
420     return FALSE;
421 
422   if (a->size != b->size)
423     return FALSE;
424 
425   return !memcmp (a->data, b->data, a->size);
426 }
427 
428 static gboolean
check_sei_frame_packing(const GstH264FramePacking * a,const GstH264FramePacking * b)429 check_sei_frame_packing (const GstH264FramePacking * a,
430     const GstH264FramePacking * b)
431 {
432   if ((a->frame_packing_id != b->frame_packing_id) ||
433       (a->frame_packing_cancel_flag != b->frame_packing_cancel_flag))
434     return FALSE;
435 
436   if (!a->frame_packing_cancel_flag) {
437     if ((a->frame_packing_type != b->frame_packing_type) ||
438         (a->quincunx_sampling_flag != b->quincunx_sampling_flag) ||
439         (a->content_interpretation_type != b->content_interpretation_type) ||
440         (a->spatial_flipping_flag != b->spatial_flipping_flag) ||
441         (a->frame0_flipped_flag != b->frame0_flipped_flag) ||
442         (a->field_views_flag != b->field_views_flag) ||
443         (a->current_frame_is_frame0_flag != b->current_frame_is_frame0_flag) ||
444         (a->frame0_self_contained_flag != b->frame0_self_contained_flag) ||
445         (a->frame1_self_contained_flag != b->frame1_self_contained_flag))
446       return FALSE;
447 
448     if (!a->quincunx_sampling_flag &&
449         a->frame_packing_type != GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING) {
450       if ((a->frame0_grid_position_x != b->frame0_grid_position_x) ||
451           (a->frame0_grid_position_y != b->frame0_grid_position_y) ||
452           (a->frame1_grid_position_x != b->frame1_grid_position_x) ||
453           (a->frame1_grid_position_y != b->frame1_grid_position_y))
454         return FALSE;
455     }
456 
457     if (a->frame_packing_repetition_period !=
458         b->frame_packing_repetition_period)
459       return FALSE;
460   }
461 
462   return TRUE;
463 }
464 
465 static gboolean
check_sei_mdcv(const GstH264MasteringDisplayColourVolume * a,const GstH264MasteringDisplayColourVolume * b)466 check_sei_mdcv (const GstH264MasteringDisplayColourVolume * a,
467     const GstH264MasteringDisplayColourVolume * b)
468 {
469   gint i;
470   for (i = 0; i < 3; i++) {
471     if (a->display_primaries_x[i] != b->display_primaries_x[i] ||
472         a->display_primaries_y[i] != b->display_primaries_y[i])
473       return FALSE;
474   }
475 
476   return (a->white_point_x == b->white_point_x) &&
477       (a->white_point_y == b->white_point_y) &&
478       (a->max_display_mastering_luminance == b->max_display_mastering_luminance)
479       && (a->min_display_mastering_luminance ==
480       b->min_display_mastering_luminance);
481 }
482 
483 static gboolean
check_sei_cll(const GstH264ContentLightLevel * a,const GstH264ContentLightLevel * b)484 check_sei_cll (const GstH264ContentLightLevel * a,
485     const GstH264ContentLightLevel * b)
486 {
487   return (a->max_content_light_level == b->max_content_light_level) &&
488       (a->max_pic_average_light_level == b->max_pic_average_light_level);
489 }
490 
491 static gboolean
check_sei_pic_timing(const GstH264PicTiming * a,const GstH264PicTiming * b)492 check_sei_pic_timing (const GstH264PicTiming * a, const GstH264PicTiming * b)
493 {
494   if (a->CpbDpbDelaysPresentFlag != b->CpbDpbDelaysPresentFlag)
495     return FALSE;
496 
497   if (a->CpbDpbDelaysPresentFlag) {
498     if (a->cpb_removal_delay != b->cpb_removal_delay ||
499         a->cpb_removal_delay_length_minus1 != b->cpb_removal_delay_length_minus1
500         || a->dpb_output_delay != b->dpb_output_delay
501         || a->dpb_output_delay_length_minus1 !=
502         b->dpb_output_delay_length_minus1)
503       return FALSE;
504   }
505 
506   if (a->pic_struct_present_flag != b->pic_struct_present_flag)
507     return FALSE;
508 
509   if (a->pic_struct_present_flag) {
510     const guint8 num_clock_ts_table[9] = {
511       1, 1, 1, 2, 2, 3, 3, 2, 3
512     };
513     guint8 num_clock_num_ts;
514     guint i;
515 
516     if (a->pic_struct != b->pic_struct)
517       return FALSE;
518 
519     if (a->time_offset_length != b->time_offset_length)
520       return FALSE;
521 
522     num_clock_num_ts = num_clock_ts_table[a->pic_struct];
523 
524     for (i = 0; i < num_clock_num_ts; i++) {
525       if (a->clock_timestamp_flag[i] != b->clock_timestamp_flag[i])
526         return FALSE;
527 
528       if (a->clock_timestamp_flag[i]) {
529         const GstH264ClockTimestamp *ta = &a->clock_timestamp[i];
530         const GstH264ClockTimestamp *tb = &b->clock_timestamp[i];
531 
532         if (ta->ct_type != tb->ct_type ||
533             ta->nuit_field_based_flag != tb->nuit_field_based_flag ||
534             ta->counting_type != tb->counting_type ||
535             ta->discontinuity_flag != tb->discontinuity_flag ||
536             ta->cnt_dropped_flag != tb->cnt_dropped_flag ||
537             ta->n_frames != tb->n_frames)
538           return FALSE;
539 
540         if (ta->full_timestamp_flag) {
541           if (ta->seconds_value != tb->seconds_value ||
542               ta->minutes_value != tb->minutes_value ||
543               ta->hours_value != tb->hours_value)
544             return FALSE;
545         } else {
546           if (ta->seconds_flag != tb->seconds_flag)
547             return FALSE;
548 
549           if (ta->seconds_flag) {
550             if (ta->seconds_value != tb->seconds_value ||
551                 ta->minutes_flag != tb->minutes_flag)
552               return FALSE;
553 
554             if (ta->minutes_flag) {
555               if (ta->minutes_value != tb->minutes_value ||
556                   ta->hours_flag != tb->hours_flag)
557                 return FALSE;
558 
559               if (ta->hours_flag) {
560                 if (ta->hours_value != tb->hours_value)
561                   return FALSE;
562               }
563             }
564           }
565         }
566 
567         if (ta->time_offset != tb->time_offset)
568           return FALSE;
569       }
570     }
571   }
572 
573   return TRUE;
574 }
575 
GST_START_TEST(test_h264_create_sei)576 GST_START_TEST (test_h264_create_sei)
577 {
578   GstH264NalParser *parser;
579   GstH264ParserResult parse_ret;
580   GstH264NalUnit nalu;
581   GArray *msg_array = NULL;
582   GstMemory *mem;
583   gint i;
584   GstMapInfo info;
585   struct
586   {
587     guint8 *raw_data;
588     guint len;
589     GstH264SEIPayloadType type;
590     GstH264SEIMessage parsed_message;
591     SEICheckFunc check_func;
592   } test_list[] = {
593     /* *INDENT-OFF* */
594     {h264_sei_user_data_registered, G_N_ELEMENTS (h264_sei_user_data_registered),
595         GST_H264_SEI_REGISTERED_USER_DATA, {0,},
596         (SEICheckFunc) check_sei_user_data_registered},
597     {h264_sei_frame_packing, G_N_ELEMENTS (h264_sei_frame_packing),
598         GST_H264_SEI_FRAME_PACKING, {0,},
599         (SEICheckFunc) check_sei_frame_packing},
600     {h264_sei_mdcv, G_N_ELEMENTS (h264_sei_mdcv),
601         GST_H264_SEI_MASTERING_DISPLAY_COLOUR_VOLUME, {0,},
602         (SEICheckFunc) check_sei_mdcv},
603     {h264_sei_cll, G_N_ELEMENTS (h264_sei_cll),
604         GST_H264_SEI_CONTENT_LIGHT_LEVEL, {0,},
605         (SEICheckFunc) check_sei_cll},
606     {nalu_sei_pic_timing, G_N_ELEMENTS (nalu_sei_pic_timing),
607         GST_H264_SEI_PIC_TIMING, {0,},
608         (SEICheckFunc) check_sei_pic_timing},
609     /* *INDENT-ON* */
610   };
611 
612   parser = gst_h264_nal_parser_new ();
613 
614   /* inject SPS for picture timing sei */
615   parse_ret =
616       gst_h264_parser_identify_nalu_unchecked (parser, nalu_sps_with_vui, 0,
617       sizeof (nalu_sps_with_vui), &nalu);
618   assert_equals_int (parse_ret, GST_H264_PARSER_OK);
619   assert_equals_int (nalu.type, GST_H264_NAL_SPS);
620   assert_equals_int (nalu.size, 28);
621 
622   parse_ret = gst_h264_parser_parse_nal (parser, &nalu);
623   assert_equals_int (parse_ret, GST_H264_PARSER_OK);
624 
625   /* test single sei message per sei nal unit */
626   for (i = 0; i < G_N_ELEMENTS (test_list); i++) {
627     gsize nal_size;
628 
629     parse_ret = gst_h264_parser_identify_nalu_unchecked (parser,
630         test_list[i].raw_data, 0, test_list[i].len, &nalu);
631     assert_equals_int (parse_ret, GST_H264_PARSER_OK);
632     assert_equals_int (nalu.type, GST_H264_NAL_SEI);
633 
634     parse_ret = gst_h264_parser_parse_sei (parser, &nalu, &msg_array);
635     assert_equals_int (parse_ret, GST_H264_PARSER_OK);
636     assert_equals_int (msg_array->len, 1);
637 
638     /* test bytestream */
639     mem = gst_h264_create_sei_memory (4, msg_array);
640     fail_unless (mem != NULL);
641     fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
642     GST_MEMDUMP ("created sei nal", info.data, info.size);
643     GST_MEMDUMP ("original sei nal", test_list[i].raw_data, test_list[i].len);
644     assert_equals_int (info.size, test_list[i].len);
645     fail_if (memcmp (info.data, test_list[i].raw_data, test_list[i].len));
646     gst_memory_unmap (mem, &info);
647     gst_memory_unref (mem);
648 
649     /* test packetized */
650     mem = gst_h264_create_sei_memory_avc (4, msg_array);
651     fail_unless (mem != NULL);
652     fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
653     assert_equals_int (info.size, test_list[i].len);
654     fail_if (memcmp (info.data + 4, test_list[i].raw_data + 4,
655             test_list[i].len - 4));
656     nal_size = GST_READ_UINT32_BE (info.data);
657     assert_equals_int (nal_size, info.size - 4);
658     gst_memory_unmap (mem, &info);
659     gst_memory_unref (mem);
660 
661     /* store parsed SEI for following tests */
662     test_list[i].parsed_message =
663         g_array_index (msg_array, GstH264SEIMessage, 0);
664     if (test_list[i].type == GST_H264_SEI_REGISTERED_USER_DATA) {
665       GstH264RegisteredUserData *dst_rud =
666           &test_list[i].parsed_message.payload.registered_user_data;
667       const GstH264SEIMessage *src_msg =
668           &g_array_index (msg_array, GstH264SEIMessage, 0);
669       const GstH264RegisteredUserData *src_rud =
670           &src_msg->payload.registered_user_data;
671 
672       dst_rud->data = g_malloc (src_rud->size);
673       memcpy ((guint8 *) dst_rud->data, src_rud->data, src_rud->size);
674     }
675     g_array_unref (msg_array);
676   }
677 
678   /* test multiple SEI messages in a nal unit */
679   msg_array = g_array_new (FALSE, FALSE, sizeof (GstH264SEIMessage));
680   for (i = 0; i < G_N_ELEMENTS (test_list); i++)
681     g_array_append_val (msg_array, test_list[i].parsed_message);
682 
683   mem = gst_h264_create_sei_memory (4, msg_array);
684   fail_unless (mem != NULL);
685   g_array_unref (msg_array);
686 
687   /* parse sei message from buffer */
688   fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
689   parse_ret = gst_h264_parser_identify_nalu_unchecked (parser,
690       info.data, 0, info.size, &nalu);
691   assert_equals_int (parse_ret, GST_H264_PARSER_OK);
692   assert_equals_int (nalu.type, GST_H264_NAL_SEI);
693   parse_ret = gst_h264_parser_parse_sei (parser, &nalu, &msg_array);
694   gst_memory_unmap (mem, &info);
695   gst_memory_unref (mem);
696 
697   assert_equals_int (parse_ret, GST_H264_PARSER_OK);
698   assert_equals_int (msg_array->len, G_N_ELEMENTS (test_list));
699   for (i = 0; i < msg_array->len; i++) {
700     GstH264SEIMessage *msg = &g_array_index (msg_array, GstH264SEIMessage, i);
701 
702     assert_equals_int (msg->payloadType, test_list[i].type);
703     fail_unless (test_list[i].check_func (&msg->payload,
704             &test_list[i].parsed_message.payload));
705   }
706 
707   /* clean up */
708   for (i = 0; i < G_N_ELEMENTS (test_list); i++)
709     gst_h264_sei_clear (&test_list[i].parsed_message);
710 
711   g_array_unref (msg_array);
712   gst_h264_nal_parser_free (parser);
713 }
714 
715 GST_END_TEST;
716 
717 static Suite *
h264parser_suite(void)718 h264parser_suite (void)
719 {
720   Suite *s = suite_create ("H264 Parser library");
721 
722   TCase *tc_chain = tcase_create ("general");
723 
724   suite_add_tcase (s, tc_chain);
725   tcase_add_test (tc_chain, test_h264_parse_slice_dpa);
726   tcase_add_test (tc_chain, test_h264_parse_slice_eoseq_slice);
727   tcase_add_test (tc_chain, test_h264_parse_slice_5bytes);
728   tcase_add_test (tc_chain, test_h264_parse_identify_nalu_avc);
729   tcase_add_test (tc_chain, test_h264_parse_invalid_sei);
730   tcase_add_test (tc_chain, test_h264_create_sei);
731 
732   return s;
733 }
734 
735 GST_CHECK_MAIN (h264parser);
736