@@ -29,7 +29,7 @@ struct h265_annexbtomp4_handle_t
2929 size_t capacity ;
3030};
3131
32- int mpeg4_h264_read_ue (const uint8_t * data , size_t bytes , size_t * offset , uint8_t * value );
32+ int mpeg4_h264_read_ue (const uint8_t * data , size_t bytes , size_t * offset , uint32_t * value );
3333
3434static size_t hevc_rbsp_decode (const uint8_t * nalu , size_t bytes , uint8_t * sodb , size_t len )
3535{
@@ -127,13 +127,17 @@ static uint8_t hevc_vps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
127127
128128static uint8_t hevc_sps_id (const uint8_t * rbsp , size_t bytes , struct mpeg4_hevc_t * hevc , uint8_t * ptr , size_t len , uint8_t * vps )
129129{
130+ int ptl_bytes ;
130131 size_t n ;
131132 size_t sodb ;
132- uint8_t sps ;
133+ uint32_t sps ;
134+ uint32_t chroma_format ;
135+ uint32_t bit_depth_luma_minus8 ;
136+ uint32_t bit_depth_chroma_minus8 ;
133137 uint8_t sps_max_sub_layers_minus1 ;
134138 uint8_t sps_temporal_id_nesting_flag ;
135139 uint8_t conformance_window_flag ;
136- uint8_t value ;
140+ uint32_t value ;
137141
138142 sodb = hevc_rbsp_decode (rbsp , bytes , ptr , len );
139143 if (sodb < 12 + 3 )
@@ -142,15 +146,17 @@ static uint8_t hevc_sps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
142146 * vps = ptr [2 ] >> 4 ; // 2-nalu type
143147 sps_max_sub_layers_minus1 = (ptr [2 ] >> 1 ) & 0x07 ;
144148 sps_temporal_id_nesting_flag = ptr [2 ] & 0x01 ;
145- n = hevc_profile_tier_level (ptr + 3 , sodb - 3 , sps_max_sub_layers_minus1 , hevc );
146- if (n <= 0 )
149+ ptl_bytes = hevc_profile_tier_level (ptr + 3 , sodb - 3 , sps_max_sub_layers_minus1 , hevc );
150+ if (ptl_bytes <= 0 )
147151 return 0xFF ;
148152
149- n = (n + 3 ) * 8 ;
153+ n = (( size_t ) ptl_bytes + 3 ) * 8 ;
150154 if (mpeg4_h264_read_ue (ptr , sodb , & n , & sps ) < 0
151- || mpeg4_h264_read_ue (ptr , sodb , & n , & hevc -> chromaFormat ) < 0 )
155+ || mpeg4_h264_read_ue (ptr , sodb , & n , & chroma_format ) < 0
156+ || sps >= 16 || chroma_format > 3 )
152157 return 0xFF ;
153- if (3 == hevc -> chromaFormat )
158+ hevc -> chromaFormat = (uint8_t )chroma_format ;
159+ if (3 == chroma_format )
154160 {
155161 if (n / 8 >= sodb )
156162 return 0xFF ;
@@ -170,28 +176,47 @@ static uint8_t hevc_sps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
170176 || mpeg4_h264_read_ue (ptr , sodb , & n , & value ) < 0 ) // conf_win_bottom_offset
171177 return 0xFF ;
172178 }
173- if (mpeg4_h264_read_ue (ptr , sodb , & n , & hevc -> bitDepthLumaMinus8 ) < 0
174- || mpeg4_h264_read_ue (ptr , sodb , & n , & hevc -> bitDepthChromaMinus8 ) < 0 )
179+ if (mpeg4_h264_read_ue (ptr , sodb , & n , & bit_depth_luma_minus8 ) < 0
180+ || mpeg4_h264_read_ue (ptr , sodb , & n , & bit_depth_chroma_minus8 ) < 0
181+ || bit_depth_luma_minus8 > 7 || bit_depth_chroma_minus8 > 7 )
175182 return 0xFF ;
183+ hevc -> bitDepthLumaMinus8 = (uint8_t )bit_depth_luma_minus8 ;
184+ hevc -> bitDepthChromaMinus8 = (uint8_t )bit_depth_chroma_minus8 ;
176185
177186 // TODO: vui_parameters
178187 //mp4->hevc->min_spatial_segmentation_idc; // min_spatial_segmentation_idc
179- return sps ;
188+ return (uint8_t )sps ;
189+ }
190+
191+ static void hevc_sps_apply (struct mpeg4_hevc_t * hevc , const struct mpeg4_hevc_t * parsed )
192+ {
193+ hevc -> general_profile_space = parsed -> general_profile_space ;
194+ hevc -> general_tier_flag = parsed -> general_tier_flag ;
195+ hevc -> general_profile_idc = parsed -> general_profile_idc ;
196+ hevc -> general_profile_compatibility_flags = parsed -> general_profile_compatibility_flags ;
197+ hevc -> general_constraint_indicator_flags = parsed -> general_constraint_indicator_flags ;
198+ hevc -> general_level_idc = parsed -> general_level_idc ;
199+ hevc -> chromaFormat = parsed -> chromaFormat ;
200+ hevc -> bitDepthLumaMinus8 = parsed -> bitDepthLumaMinus8 ;
201+ hevc -> bitDepthChromaMinus8 = parsed -> bitDepthChromaMinus8 ;
180202}
181203
182204static uint8_t hevc_pps_id (const uint8_t * rbsp , size_t bytes , struct mpeg4_hevc_t * hevc , uint8_t * ptr , size_t len , uint8_t * sps )
183205{
184- uint8_t pps ;
206+ uint32_t pps ;
207+ uint32_t spsid ;
185208 size_t sodb ;
186209 size_t offset = 2 * 8 ; // 2-nalu type
187210 sodb = hevc_rbsp_decode (rbsp , bytes , ptr , len );
188211 if (sodb < 3 )
189212 return 0xFF ;
190213 (void )hevc ;
191214 if (mpeg4_h264_read_ue (ptr , sodb , & offset , & pps ) < 0
192- || mpeg4_h264_read_ue (ptr , sodb , & offset , sps ) < 0 )
215+ || mpeg4_h264_read_ue (ptr , sodb , & offset , & spsid ) < 0
216+ || pps >= 64 || spsid >= 16 )
193217 return 0xFF ;
194- return pps ;
218+ * sps = (uint8_t )spsid ;
219+ return (uint8_t )pps ;
195220}
196221
197222static void mpeg4_hevc_remove (struct mpeg4_hevc_t * hevc , uint8_t * ptr , size_t bytes , const uint8_t * end )
@@ -273,25 +298,40 @@ static int h265_vps_copy(struct mpeg4_hevc_t* hevc, const uint8_t* nalu, size_t
273298static int h265_sps_copy (struct mpeg4_hevc_t * hevc , const uint8_t * nalu , size_t bytes )
274299{
275300 int i ;
301+ int r ;
276302 uint8_t spsid ;
303+ uint8_t spsid2 ;
277304 uint8_t vpsid , vpsid2 ;
305+ struct mpeg4_hevc_t parsed ;
306+ struct mpeg4_hevc_t parsed2 ;
278307
279308 if (bytes < 13 + 2 )
280309 {
281310 assert (0 );
282311 return -1 ; // invalid length
283312 }
284313
285- spsid = hevc_sps_id (nalu , bytes , hevc , hevc -> data + hevc -> off , sizeof (hevc -> data ) - hevc -> off , & vpsid );
314+ spsid = hevc_sps_id (nalu , bytes , & parsed , hevc -> data + hevc -> off , sizeof (hevc -> data ) - hevc -> off , & vpsid );
286315 if (0xFF == spsid )
287316 return -1 ;
288317 for (i = 0 ; i < hevc -> numOfArrays ; i ++ )
289318 {
290- if (H265_NAL_SPS == hevc -> nalu [i ].type && spsid == hevc_sps_id (hevc -> nalu [i ].data , hevc -> nalu [i ].bytes , hevc , hevc -> data + hevc -> off , sizeof (hevc -> data ) - hevc -> off , & vpsid2 ) && vpsid == vpsid2 )
291- return mpeg4_hevc_update2 (hevc , i , nalu , bytes );
319+ if (H265_NAL_SPS != hevc -> nalu [i ].type )
320+ continue ;
321+ spsid2 = hevc_sps_id (hevc -> nalu [i ].data , hevc -> nalu [i ].bytes , & parsed2 , hevc -> data + hevc -> off , sizeof (hevc -> data ) - hevc -> off , & vpsid2 );
322+ if (spsid == spsid2 && vpsid == vpsid2 )
323+ {
324+ r = mpeg4_hevc_update2 (hevc , i , nalu , bytes );
325+ if (r >= 0 )
326+ hevc_sps_apply (hevc , & parsed );
327+ return r ;
328+ }
292329 }
293330
294- return mpeg4_hevc_add (hevc , H265_NAL_SPS , nalu , bytes );
331+ r = mpeg4_hevc_add (hevc , H265_NAL_SPS , nalu , bytes );
332+ if (r >= 0 )
333+ hevc_sps_apply (hevc , & parsed );
334+ return r ;
295335}
296336
297337static int h265_pps_copy (struct mpeg4_hevc_t * hevc , const uint8_t * nalu , size_t bytes )
@@ -476,12 +516,15 @@ void hevc_annexbtomp4_test(void)
476516 const uint8_t vps [] = { 0x40 , 0x01 , 0x0c , 0x01 , 0xff , 0xff , 0x01 , 0x60 , 0x00 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x03 , 0x00 , 0x78 , 0x9d , 0xc0 , 0x90 };
477517 const uint8_t sps [] = { 0x42 , 0x01 , 0x01 , 0x01 , 0x60 , 0x00 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x03 , 0x00 , 0x78 , 0xa0 , 0x03 , 0xc0 , 0x80 , 0x32 , 0x16 , 0x59 , 0xde , 0x49 , 0x1b , 0x6b , 0x80 , 0x40 , 0x00 , 0x00 , 0xfa , 0x00 , 0x00 , 0x17 , 0x70 , 0x02 };
478518 const uint8_t pps [] = { 0x44 , 0x01 , 0xc1 , 0x73 , 0xd1 , 0x89 };
519+ const uint8_t truncated_ptl_sps [] = { 0x42 , 0x01 , 0x02 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff };
520+ const uint8_t truncated_sps [] = { 0x42 , 0x01 , 0x01 , 0x01 , 0x60 , 0x00 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x03 , 0x00 , 0x78 };
479521 const uint8_t incomplete_pps [] = { 0x44 , 0x01 , 0x01 };
480522 const uint8_t annexb [] = { 0x00 , 0x00 , 0x00 , 0x01 , 0x4e , 0x01 , 0x06 , 0x01 , 0xd0 , 0x80 , 0x00 , 0x00 , 0x00 , 0x01 , 0x40 , 0x01 , 0x0c , 0x01 , 0xff , 0xff , 0x01 , 0x60 , 0x00 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x03 , 0x00 , 0x78 , 0x9d , 0xc0 , 0x90 , 0x00 , 0x00 , 0x00 , 0x01 , 0x42 , 0x01 , 0x01 , 0x01 , 0x60 , 0x00 , 0x00 , 0x03 , 0x00 , 0x80 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x03 , 0x00 , 0x78 , 0xa0 , 0x03 , 0xc0 , 0x80 , 0x32 , 0x16 , 0x59 , 0xde , 0x49 , 0x1b , 0x6b , 0x80 , 0x40 , 0x00 , 0x00 , 0xfa , 0x00 , 0x00 , 0x17 , 0x70 , 0x02 , 0x00 , 0x00 , 0x00 , 0x01 , 0x44 , 0x01 , 0xc1 , 0x73 , 0xd1 , 0x89 };
481523 uint8_t output [512 ];
482524 int vcl , update ;
483525
484526 struct mpeg4_hevc_t hevc ;
527+ struct mpeg4_hevc_t before ;
485528 memset (& hevc , 0 , sizeof (hevc ));
486529 assert (h265_annexbtomp4 (& hevc , annexb , sizeof (annexb ), output , sizeof (output ), & vcl , & update ) > 0 );
487530 assert (3 == hevc .numOfArrays && vcl == 0 && update == 1 );
@@ -492,5 +535,21 @@ void hevc_annexbtomp4_test(void)
492535 memset (& hevc , 0 , sizeof (hevc ));
493536 assert (mpeg4_hevc_update (& hevc , incomplete_pps , sizeof (incomplete_pps )) < 0 );
494537 assert (0 == hevc .numOfArrays && 0 == hevc .off );
538+
539+ memset (& hevc , 0x5a , offsetof(struct mpeg4_hevc_t , numOfArrays ));
540+ hevc .numOfArrays = 0 ;
541+ hevc .off = 0 ;
542+ before = hevc ;
543+ assert (mpeg4_hevc_update (& hevc , truncated_ptl_sps , sizeof (truncated_ptl_sps )) < 0 );
544+ assert (0 == memcmp (& before , & hevc , offsetof(struct mpeg4_hevc_t , numOfArrays )));
545+ assert (0 == hevc .numOfArrays && 0 == hevc .off );
546+
547+ memset (& hevc , 0x5a , offsetof(struct mpeg4_hevc_t , numOfArrays ));
548+ hevc .numOfArrays = 0 ;
549+ hevc .off = 0 ;
550+ before = hevc ;
551+ assert (mpeg4_hevc_update (& hevc , truncated_sps , sizeof (truncated_sps )) < 0 );
552+ assert (0 == memcmp (& before , & hevc , offsetof(struct mpeg4_hevc_t , numOfArrays )));
553+ assert (0 == hevc .numOfArrays && 0 == hevc .off );
495554}
496555#endif
0 commit comments