Skip to content

Commit 707422d

Browse files
committed
h264_stream: compat with 444 subsampling
Sync the h264_stream source with [upstream] (commit 70124d30) because the decoding of 4:4:4 subsampled H.264 video fails. Problematic stream can be generated with: ``` docker run --rm -it --network=host bluenviron/mediamtx ffmpeg -re -f lavfi -i smptebars=s=1920x1080 -pix_fmt yuv444p \ -vcodec libx264 -f rtsp rtsp://localhost:8554/mystream ``` For that the read_seq_parameter_set_rbsp() called on PPS NALU from SDP (sprop-parameter-sets) gave completly wrong resolution 16x160 - evidently the header was misinterpreted. The code is taken mostly unmodified (just internal functions set static in prototype). debug_sps() not updated (no longer compiles so commented out). [upstream]: https://github.com/aizvorski/h264bitstream
1 parent e41ab00 commit 707422d

File tree

4 files changed

+131
-133
lines changed

4 files changed

+131
-133
lines changed

src/rtp/rtpdec_h264.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -477,12 +477,7 @@ width_height_from_h264_sps(int *widthOut, int *heightOut, unsigned char *data,
477477
/* nal->forbidden_zero_bit */ bs_skip_u(b, 1);
478478
/* nal->nal_ref_idc = */ bs_read_u(b, 2);
479479
/* nal->nal_unit_type = */ bs_read_u(b, 5);
480-
if(read_seq_parameter_set_rbsp(sps,b) < 0){
481-
bs_free(b);
482-
free(rbsp_buf);
483-
free(sps);
484-
return -1;
485-
}
480+
read_seq_parameter_set_rbsp(sps,b);
486481
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
487482
height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16;
488483
//NOTE: frame_mbs_only_flag = 1 --> only progressive frames

src/utils/h264_stream.c

Lines changed: 75 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,34 @@
1-
/*
1+
/*
22
* h264bitstream - a library for reading and writing H.264 video
33
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
44
* Copyright (C) 2008-2011 Avail-TVN
5+
* Copyright (C) 2012 Alex Izvorski
56
*
67
* Written by Alex Izvorski <[email protected]> and Alex Giladi <[email protected]>
7-
*
8+
*
89
* This library is free software; you can redistribute it and/or
910
* modify it under the terms of the GNU Lesser General Public
1011
* License as published by the Free Software Foundation; either
1112
* version 2.1 of the License, or (at your option) any later version.
12-
*
13+
*
1314
* This library is distributed in the hope that it will be useful,
1415
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1516
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1617
* Lesser General Public License for more details.
17-
*
18+
*
1819
* You should have received a copy of the GNU Lesser General Public
1920
* License along with this library; if not, write to the Free Software
2021
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2122
*/
2223

23-
#ifdef HAVE_CONFIG_H
24-
#include "config.h"
25-
#include "config_unix.h"
26-
#include "config_win32.h"
27-
#endif // defined HAVE_CONFIG_H
2824

2925
#include <stdint.h>
30-
#include <stdio.h>
3126
#include <stdlib.h>
27+
#include <stdio.h>
3228

33-
#include "debug.h"
29+
#include "bs.h"
3430
#include "h264_stream.h"
31+
// #include "h264_sei.h"
3532

3633
/***************************** reading ******************************/
3734

@@ -103,27 +100,39 @@ int nal_to_rbsp(const uint8_t* nal_buf, int* nal_size, uint8_t* rbsp_buf, int* r
103100
return j;
104101
}
105102

106-
//7.3.2.1 Sequence parameter set RBSP syntax
107-
int read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b) {
103+
static void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag );
104+
static void read_vui_parameters(sps_t* sps, bs_t* b);
105+
static void read_hrd_parameters(hrd_t* hrd, bs_t* b);
108106

107+
//7.3.2.1 Sequence parameter set RBSP syntax
108+
void read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b)
109+
{
109110
int i;
110111

111-
memset(sps, 0, sizeof(sps_t));
112-
112+
if( 1 )
113+
{
114+
memset(sps, 0, sizeof(sps_t));
115+
sps->chroma_format_idc = 1;
116+
}
117+
113118
sps->profile_idc = bs_read_u8(b);
114119
sps->constraint_set0_flag = bs_read_u1(b);
115120
sps->constraint_set1_flag = bs_read_u1(b);
116121
sps->constraint_set2_flag = bs_read_u1(b);
117122
sps->constraint_set3_flag = bs_read_u1(b);
118123
sps->constraint_set4_flag = bs_read_u1(b);
119124
sps->constraint_set5_flag = bs_read_u1(b);
120-
sps->reserved_zero_2bits = bs_read_u(b,2); /* all 0's */
125+
/* reserved_zero_2bits */ bs_skip_u(b, 2);
121126
sps->level_idc = bs_read_u8(b);
122127
sps->seq_parameter_set_id = bs_read_ue(b);
123128

124-
sps->chroma_format_idc = 1;
125129
if( sps->profile_idc == 100 || sps->profile_idc == 110 ||
126-
sps->profile_idc == 122 || sps->profile_idc == 144 )
130+
sps->profile_idc == 122 || sps->profile_idc == 244 ||
131+
sps->profile_idc == 44 || sps->profile_idc == 83 ||
132+
sps->profile_idc == 86 || sps->profile_idc == 118 ||
133+
sps->profile_idc == 128 || sps->profile_idc == 138 ||
134+
sps->profile_idc == 139 || sps->profile_idc == 134
135+
)
127136
{
128137
sps->chroma_format_idc = bs_read_ue(b);
129138
if( sps->chroma_format_idc == 3 )
@@ -136,20 +145,20 @@ int read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b) {
136145
sps->seq_scaling_matrix_present_flag = bs_read_u1(b);
137146
if( sps->seq_scaling_matrix_present_flag )
138147
{
139-
for( i = 0; i < 8; i++ )
148+
for( i = 0; i < ((sps->chroma_format_idc != 3) ? 8 : 12); i++ )
140149
{
141150
sps->seq_scaling_list_present_flag[ i ] = bs_read_u1(b);
142151
if( sps->seq_scaling_list_present_flag[ i ] )
143152
{
144153
if( i < 6 )
145154
{
146155
read_scaling_list( b, sps->ScalingList4x4[ i ], 16,
147-
sps->UseDefaultScalingMatrix4x4Flag[ i ]);
156+
&( sps->UseDefaultScalingMatrix4x4Flag[ i ] ) );
148157
}
149158
else
150159
{
151160
read_scaling_list( b, sps->ScalingList8x8[ i - 6 ], 64,
152-
sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] );
161+
&( sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) );
153162
}
154163
}
155164
}
@@ -195,49 +204,53 @@ int read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b) {
195204
{
196205
read_vui_parameters(sps, b);
197206
}
198-
read_rbsp_trailing_bits(b);
199-
200-
return 0;
201207
}
202208

203-
204209
//7.3.2.1.1 Scaling list syntax
205-
void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int useDefaultScalingMatrixFlag )
210+
void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag )
206211
{
207-
UNUSED(useDefaultScalingMatrixFlag);
208-
int j;
209-
if(scalingList == NULL)
210-
{
211-
return;
212-
}
213-
212+
// NOTE need to be able to set useDefaultScalingMatrixFlag when reading, hence passing as pointer
214213
int lastScale = 8;
215214
int nextScale = 8;
216-
for( j = 0; j < sizeOfScalingList; j++ )
215+
int delta_scale;
216+
for( int j = 0; j < sizeOfScalingList; j++ )
217217
{
218218
if( nextScale != 0 )
219219
{
220-
int delta_scale = bs_read_se(b);
221-
nextScale = ( lastScale + delta_scale + 256 ) % 256;
222-
useDefaultScalingMatrixFlag = ( j == 0 && nextScale == 0 );
220+
if( 0 )
221+
{
222+
nextScale = scalingList[ j ];
223+
if (useDefaultScalingMatrixFlag[0]) { nextScale = 0; }
224+
delta_scale = (nextScale - lastScale) % 256 ;
225+
}
226+
227+
delta_scale = bs_read_se(b);
228+
229+
if( 1 )
230+
{
231+
nextScale = ( lastScale + delta_scale + 256 ) % 256;
232+
useDefaultScalingMatrixFlag[0] = ( j == 0 && nextScale == 0 );
233+
}
234+
}
235+
if( 1 )
236+
{
237+
scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
223238
}
224-
scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
225239
lastScale = scalingList[ j ];
226240
}
227241
}
228242

229243
//Appendix E.1.1 VUI parameters syntax
230244
void read_vui_parameters(sps_t* sps, bs_t* b)
231245
{
232-
233246
sps->vui.aspect_ratio_info_present_flag = bs_read_u1(b);
234247
if( sps->vui.aspect_ratio_info_present_flag )
235248
{
236249
sps->vui.aspect_ratio_idc = bs_read_u8(b);
237250
if( sps->vui.aspect_ratio_idc == SAR_Extended )
238251
{
239-
sps->vui.sar_width = bs_read_u(b,16);
240-
sps->vui.sar_height = bs_read_u(b,16);
252+
sps->vui.sar_width = bs_read_u(b, 16);
253+
sps->vui.sar_height = bs_read_u(b, 16);
241254
}
242255
}
243256
sps->vui.overscan_info_present_flag = bs_read_u1(b);
@@ -248,7 +261,7 @@ void read_vui_parameters(sps_t* sps, bs_t* b)
248261
sps->vui.video_signal_type_present_flag = bs_read_u1(b);
249262
if( sps->vui.video_signal_type_present_flag )
250263
{
251-
sps->vui.video_format = bs_read_u(b,3);
264+
sps->vui.video_format = bs_read_u(b, 3);
252265
sps->vui.video_full_range_flag = bs_read_u1(b);
253266
sps->vui.colour_description_present_flag = bs_read_u1(b);
254267
if( sps->vui.colour_description_present_flag )
@@ -267,19 +280,19 @@ void read_vui_parameters(sps_t* sps, bs_t* b)
267280
sps->vui.timing_info_present_flag = bs_read_u1(b);
268281
if( sps->vui.timing_info_present_flag )
269282
{
270-
sps->vui.num_units_in_tick = bs_read_u(b,32);
271-
sps->vui.time_scale = bs_read_u(b,32);
283+
sps->vui.num_units_in_tick = bs_read_u(b, 32);
284+
sps->vui.time_scale = bs_read_u(b, 32);
272285
sps->vui.fixed_frame_rate_flag = bs_read_u1(b);
273286
}
274287
sps->vui.nal_hrd_parameters_present_flag = bs_read_u1(b);
275288
if( sps->vui.nal_hrd_parameters_present_flag )
276289
{
277-
read_hrd_parameters(sps, b);
290+
read_hrd_parameters(&sps->hrd_nal, b);
278291
}
279292
sps->vui.vcl_hrd_parameters_present_flag = bs_read_u1(b);
280293
if( sps->vui.vcl_hrd_parameters_present_flag )
281294
{
282-
read_hrd_parameters(sps, b);
295+
read_hrd_parameters(&sps->hrd_vcl, b);
283296
}
284297
if( sps->vui.nal_hrd_parameters_present_flag || sps->vui.vcl_hrd_parameters_present_flag )
285298
{
@@ -301,38 +314,28 @@ void read_vui_parameters(sps_t* sps, bs_t* b)
301314

302315

303316
//Appendix E.1.2 HRD parameters syntax
304-
void read_hrd_parameters(sps_t* sps, bs_t* b)
317+
void read_hrd_parameters(hrd_t* hrd, bs_t* b)
305318
{
306-
int SchedSelIdx;
307-
308-
sps->hrd.cpb_cnt_minus1 = bs_read_ue(b);
309-
sps->hrd.bit_rate_scale = bs_read_u(b,4);
310-
sps->hrd.cpb_size_scale = bs_read_u(b,4);
311-
for( SchedSelIdx = 0; SchedSelIdx <= sps->hrd.cpb_cnt_minus1; SchedSelIdx++ )
312-
{
313-
sps->hrd.bit_rate_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
314-
sps->hrd.cpb_size_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
315-
sps->hrd.cbr_flag[ SchedSelIdx ] = bs_read_u1(b);
316-
}
317-
sps->hrd.initial_cpb_removal_delay_length_minus1 = bs_read_u(b,5);
318-
sps->hrd.cpb_removal_delay_length_minus1 = bs_read_u(b,5);
319-
sps->hrd.dpb_output_delay_length_minus1 = bs_read_u(b,5);
320-
sps->hrd.time_offset_length = bs_read_u(b,5);
321-
}
322-
323-
//7.3.2.11 RBSP trailing bits syntax
324-
void read_rbsp_trailing_bits(bs_t* b)
325-
{
326-
/* int rbsp_stop_one_bit = */ bs_read_u1( b ); // equal to 1
327-
328-
while( !bs_byte_aligned(b) )
319+
hrd->cpb_cnt_minus1 = bs_read_ue(b);
320+
hrd->bit_rate_scale = bs_read_u(b, 4);
321+
hrd->cpb_size_scale = bs_read_u(b, 4);
322+
for( int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++ )
329323
{
330-
/* int rbsp_alignment_zero_bit = */ bs_read_u1( b ); // equal to 0
324+
hrd->bit_rate_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
325+
hrd->cpb_size_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
326+
hrd->cbr_flag[ SchedSelIdx ] = bs_read_u1(b);
331327
}
328+
hrd->initial_cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
329+
hrd->cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
330+
hrd->dpb_output_delay_length_minus1 = bs_read_u(b, 5);
331+
hrd->time_offset_length = bs_read_u(b, 5);
332332
}
333333

334334
/***************************** debug ******************************/
335335

336+
// not used in code but useful for debugging, needs to be fixed in order to
337+
// compile
338+
#if 0
336339
void debug_sps(sps_t* sps)
337340
{
338341
printf("======= SPS =======\n");
@@ -429,6 +432,7 @@ void debug_sps(sps_t* sps)
429432
printf(" dpb_output_delay_length_minus1 : %d \n", sps->hrd.dpb_output_delay_length_minus1 );
430433
printf(" time_offset_length : %d \n", sps->hrd.time_offset_length );
431434
}
435+
#endif
432436

433437

434438

0 commit comments

Comments
 (0)