Ticket #6243: H264Parser-fixes-v1.1.patch
File H264Parser-fixes-v1.1.patch, 12.2 KB (added by , 15 years ago) |
---|
-
libs/libmythtv/mpeg/H264Parser.cpp
old new 3 3 4 4 extern "C" { 5 5 // from libavcodec 6 extern const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state); 6 extern const uint8_t *ff_find_start_code(const uint8_t * p, 7 const uint8_t *end, 8 uint32_t * state); 7 9 #include "avcodec.h" 8 10 } 9 11 … … static const float eps = 1E-5; 88 90 H264Parser::H264Parser(void) 89 91 { 90 92 Reset(); 93 I_is_keyframe = false; 91 94 } 92 95 93 96 void H264Parser::Reset(void) 94 97 { 95 98 state_changed = false; 96 seen_sps = seen_IDR = false; 99 seen_sps = false; 100 is_keyframe = false; 97 101 98 102 sync_accumulator = 0xffffffff; 99 find_AU = false;100 103 AU_pending = false; 101 104 102 NAL_type = UNKNOWN;103 104 105 frame_num = prev_frame_num = -1; 105 106 slice_type = SLICE_UNDEF; 106 107 prev_pic_parameter_set_id = pic_parameter_set_id = -1; … … void H264Parser::Reset(void) 112 113 prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0; 113 114 prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0; 114 115 prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0; 115 prev_nal_unit_type = nal_unit_type = 0;116 prev_nal_unit_type = nal_unit_type = UNKNOWN; 116 117 prev_idr_pic_id = idr_pic_id = 0; 117 118 118 119 log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0; … … void H264Parser::Reset(void) 136 137 137 138 AU_offset = frame_start_offset = keyframe_start_offset = 0; 138 139 on_frame = on_key_frame = false; 139 140 wait_for_IDR = false;141 140 } 142 141 143 142 … … bool H264Parser::new_AU(void) 214 213 { 215 214 // Need previous slice information for comparison 216 215 217 if (NAL_type == AU_DELIMITER || 218 NAL_type == SPS || 219 NAL_type == PPS || 220 NAL_type == SEI || 221 (NAL_type > SPS_EXT && NAL_type < AUXILIARY_SLICE)) 222 result = true; 223 else if (NAL_type != SLICE_IDR && frame_num != prev_frame_num) 216 if (nal_unit_type != SLICE_IDR && frame_num != prev_frame_num) 224 217 result = true; 225 218 else if (prev_pic_parameter_set_id != -1 && 226 219 pic_parameter_set_id != prev_pic_parameter_set_id) … … bool H264Parser::new_AU(void) 230 223 else if ((bottom_field_flag != -1 && prev_bottom_field_flag != -1) && 231 224 bottom_field_flag != prev_bottom_field_flag) 232 225 result = true; 233 else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) &&234 nal_ref_idc != prev_nal_ref_idc)235 result = true;236 226 else if ((pic_order_cnt_type == 0 && prev_pic_order_cnt_type == 0) && 237 227 (pic_order_cnt_lsb != prev_pic_order_cnt_lsb || 238 228 delta_pic_order_cnt_bottom != … … bool H264Parser::new_AU(void) 256 246 prev_pic_parameter_set_id = pic_parameter_set_id; 257 247 prev_field_pic_flag = field_pic_flag; 258 248 prev_bottom_field_flag = bottom_field_flag; 259 prev_nal_ref_idc = nal_ref_idc;260 249 prev_pic_order_cnt_lsb = pic_order_cnt_lsb; 261 250 prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; 262 251 prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; … … uint32_t H264Parser::addBytes(const uint 273 262 { 274 263 const uint8_t *byteP = bytes; 275 264 const uint8_t *endP = bytes + byte_count; 276 265 const uint8_t *nalP; 277 266 uint8_t first_byte; 278 267 279 268 state_changed = false; … … uint32_t H264Parser::addBytes(const uint 305 294 11 End of stream end_of_stream_rbsp( ) 306 295 */ 307 296 first_byte = *(byteP - 1); 308 NAL_type = first_byte & 0x1f;297 nal_unit_type = first_byte & 0x1f; 309 298 nal_ref_idc = (first_byte >> 5) & 0x3; 310 299 311 if (NALisSlice(NAL_type) || NAL_type == SPS || NAL_type == PPS) 300 if (nal_unit_type == SPS || nal_unit_type == PPS || 301 nal_unit_type == SEI || NALisSlice(nal_unit_type)) 312 302 { 313 303 /* 314 304 bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE … … uint32_t H264Parser::addBytes(const uint 318 308 { 319 309 init_get_bits(&gb, byteP, 8 * (endP - byteP)); 320 310 321 if (NAL_type == SPS) 311 if (nal_unit_type == SEI) 312 { 313 nalP = ff_find_start_code(byteP+1, endP, 314 &sync_accumulator) - 8; 315 decode_SEI(&gb, (nalP - byteP) * 8); 316 set_AU_pending(stream_offset); 317 } 318 else if (nal_unit_type == SPS) 319 { 322 320 decode_SPS(&gb); 323 else if (NAL_type == PPS) 321 set_AU_pending(stream_offset); 322 } 323 else if (nal_unit_type == PPS) 324 { 324 325 decode_PPS(&gb); 326 set_AU_pending(stream_offset); 327 } 325 328 else 326 find_AU = decode_Header(&gb); 329 { 330 decode_Header(&gb); 331 if (new_AU()) 332 set_AU_pending(stream_offset); 333 } 327 334 328 335 byteP += (get_bits_count(&gb) / 8); 329 336 } 330 337 } 331 332 if (find_AU && new_AU()) 338 else if (!AU_pending) 333 339 { 334 /* After finding a new AU, don't look for another one 335 until we decode a SLICE */ 336 find_AU = false; 337 AU_pending = true; 338 AU_offset = stream_offset; 340 if (nal_unit_type == AU_DELIMITER || 341 (nal_unit_type > SPS_EXT && 342 nal_unit_type < AUXILIARY_SLICE)) 343 { 344 AU_pending = true; 345 AU_offset = stream_offset; 346 } 347 else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) && 348 nal_ref_idc != prev_nal_ref_idc) 349 { 350 AU_pending = true; 351 AU_offset = stream_offset; 352 } 339 353 } 340 341 if (AU_pending && NALisSlice( NAL_type))354 355 if (AU_pending && NALisSlice(nal_unit_type)) 342 356 { 343 357 /* Once we know the slice type of a new AU, we can 344 358 * determine if it is a keyframe or just a frame */ … … uint32_t H264Parser::addBytes(const uint 349 363 on_frame = true; 350 364 frame_start_offset = AU_offset; 351 365 352 if (is KeySlice(slice_type) && (!wait_for_IDR || seen_IDR))366 if (is_keyframe) 353 367 { 354 368 on_key_frame = true; 355 369 keyframe_start_offset = AU_offset; 370 is_keyframe = false; 356 371 } 357 372 else 358 373 on_key_frame = false; … … uint32_t H264Parser::addBytes(const uint 360 375 else 361 376 on_frame = on_key_frame = false; 362 377 378 prev_nal_ref_idc = nal_ref_idc; 379 363 380 return byteP - bytes; 364 381 } 365 382 } … … bool H264Parser::decode_Header(GetBitCon 440 457 */ 441 458 442 459 frame_num = get_bits(gb, log2_max_frame_num); 443 if (NAL_type == SLICE_IDR || frame_num == 0)444 seen_IDR = true;445 460 446 461 /* 447 462 field_pic_flag equal to 1 specifies that the slice is a slice of a … … bool H264Parser::decode_Header(GetBitCon 475 490 second such IDR access unit. The value of idr_pic_id shall be in 476 491 the range of 0 to 65535, inclusive. 477 492 */ 493 478 494 if (nal_unit_type == SLICE_IDR) 495 { 496 is_keyframe = true; 479 497 idr_pic_id = get_ue_golomb(gb); 498 } 499 else 500 is_keyframe |= (I_is_keyframe && isKeySlice(slice_type)); 480 501 481 502 /* 482 503 pic_order_cnt_lsb specifies the picture order count modulo … … void H264Parser::decode_PPS(GetBitContex 806 827 #endif 807 828 } 808 829 830 void H264Parser::decode_SEI(GetBitContext * gb, int bitlen) 831 { 832 int recovery_frame_cnt = -1; 833 bool exact_match_flag = false; 834 bool broken_link_flag = false; 835 int changing_group_slice_idc = -1; 836 837 while (get_bits_count(gb) < bitlen) 838 { 839 int type = 0, size = 0; 840 841 do { 842 type += show_bits(gb, 8); 843 } while (get_bits(gb, 8) == 255); 844 845 do { 846 size += show_bits(gb, 8); 847 } while (get_bits(gb, 8) == 255); 848 849 switch (type) 850 { 851 case SEI_TYPE_RECOVERY_POINT: 852 recovery_frame_cnt = get_ue_golomb(gb); 853 exact_match_flag = get_bits1(gb); 854 broken_link_flag = get_bits1(gb); 855 changing_group_slice_idc = get_bits(gb, 2); 856 is_keyframe |= (recovery_frame_cnt >= 0); 857 return; 858 859 default: 860 skip_bits(gb, size * 8); 861 break; 862 } 863 864 align_get_bits(gb); 865 } 866 } 867 809 868 void H264Parser::vui_parameters(GetBitContext * gb) 810 869 { 811 870 /* -
libs/libmythtv/mpeg/H264Parser.h
old new class H264Parser { 53 53 AUXILIARY_SLICE = 19 54 54 }; 55 55 56 enum SEI_type { 57 SEI_TYPE_PIC_TIMING = 1, 58 SEI_TYPE_USER_DATA_UNREGISTERED = 5, 59 SEI_TYPE_RECOVERY_POINT = 6 60 }; 61 56 62 /* 57 63 slice_type values in the range 5..9 specify, in addition to the 58 64 coding type of the current slice, that all other slices of the … … class H264Parser { 90 96 91 97 bool stateChanged(void) const { return state_changed; } 92 98 93 // seenIDR implies that a SPS has also been seen 94 bool seenIDR(void) const { return seen_IDR; } 95 uint8_t lastNALtype(void) const { return NAL_type; } 99 uint8_t lastNALtype(void) const { return nal_unit_type; } 96 100 97 101 frame_type FieldType(void) const 98 102 { … … class H264Parser { 130 134 nal_type == SLICE_IDR); 131 135 } 132 136 133 void waitForIDR(bool wait) { wait_for_IDR = wait; }137 void use_I_forKeyframes(bool val) { I_is_keyframe = val; } 134 138 135 139 private: 136 140 enum constants {EXTENDED_SAR = 255}; 137 141 138 bool is_first_VCL_NAL_unit(void); 142 inline void set_AU_pending(const uint64_t & stream_offset) 143 { 144 if (!AU_pending) 145 { 146 AU_pending = true; 147 AU_offset = stream_offset; 148 } 149 } 150 139 151 bool new_AU(void); 140 152 bool decode_Header(GetBitContext *gb); 141 153 void decode_SPS(GetBitContext *gb); 142 154 void decode_PPS(GetBitContext * gb); 155 void decode_SEI(GetBitContext * gb, int len); 143 156 void vui_parameters(GetBitContext * gb); 144 157 145 bool find_AU;146 158 bool AU_pending; 147 159 bool state_changed; 148 160 bool seen_sps; 149 bool seen_IDR; 161 bool is_keyframe; 162 bool I_is_keyframe; 150 163 151 164 uint32_t sync_accumulator; 152 165 GetBitContext gb; 153 166 154 uint8_t NAL_type;155 156 167 int prev_frame_num, frame_num; 157 168 uint slice_type; 158 169 int prev_pic_parameter_set_id, pic_parameter_set_id; … … class H264Parser { 188 199 189 200 uint64_t AU_offset, frame_start_offset, keyframe_start_offset; 190 201 bool on_frame, on_key_frame; 191 192 bool wait_for_IDR;193 202 }; 194 203 195 204 #endif /* H264PARSER_H */ -
libs/libmythtv/mpegrecorder.cpp
old new bool MpegRecorder::OpenV4L2DeviceAsInput 423 423 bzero(_stream_id, sizeof(_stream_id)); 424 424 bzero(_pid_status, sizeof(_pid_status)); 425 425 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 426 m_h264_parser.use_I_forKeyframes(true); 426 427 } 427 428 else 428 429 { … … void MpegRecorder::ResetForNewFile(void) 1373 1374 bzero(_stream_id, sizeof(_stream_id)); 1374 1375 bzero(_pid_status, sizeof(_pid_status)); 1375 1376 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 1376 1377 m_h264_parser.waitForIDR(true);1378 1377 } 1379 1378 1380 1379 void MpegRecorder::Reset(void)