Ticket #6243: H264Parser-fixes.patch
File H264Parser-fixes.patch, 11.5 KB (added by , 15 years ago) |
---|
-
libs/libmythtv/mpeg/H264Parser.cpp
old new 1 1 // MythTV headers 2 2 #include "H264Parser.h" 3 3 4 #define USE_I_FRAME_AS_KEYFRAME 1 5 4 6 extern "C" { 5 7 // from libavcodec 6 extern const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state); 8 extern const uint8_t *ff_find_start_code(const uint8_t * p, 9 const uint8_t *end, 10 uint32_t * state); 7 11 #include "avcodec.h" 8 12 } 9 13 … … H264Parser::H264Parser(void) 93 97 void H264Parser::Reset(void) 94 98 { 95 99 state_changed = false; 96 seen_sps = seen_IDR = false; 100 seen_sps = false; 101 is_IDR = is_keyframe = false; 97 102 98 103 sync_accumulator = 0xffffffff; 99 find_AU = false;100 104 AU_pending = false; 101 105 102 NAL_type = UNKNOWN;103 104 106 frame_num = prev_frame_num = -1; 105 107 slice_type = SLICE_UNDEF; 106 108 prev_pic_parameter_set_id = pic_parameter_set_id = -1; … … void H264Parser::Reset(void) 112 114 prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0; 113 115 prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0; 114 116 prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0; 115 prev_nal_unit_type = nal_unit_type = 0;117 prev_nal_unit_type = nal_unit_type = UNKNOWN; 116 118 prev_idr_pic_id = idr_pic_id = 0; 117 119 118 120 log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0; … … void H264Parser::Reset(void) 136 138 137 139 AU_offset = frame_start_offset = keyframe_start_offset = 0; 138 140 on_frame = on_key_frame = false; 139 140 wait_for_IDR = false;141 141 } 142 142 143 143 … … bool H264Parser::new_AU(void) 214 214 { 215 215 // Need previous slice information for comparison 216 216 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) 217 if (nal_unit_type != SLICE_IDR && frame_num != prev_frame_num) 224 218 result = true; 225 219 else if (prev_pic_parameter_set_id != -1 && 226 220 pic_parameter_set_id != prev_pic_parameter_set_id) … … bool H264Parser::new_AU(void) 230 224 else if ((bottom_field_flag != -1 && prev_bottom_field_flag != -1) && 231 225 bottom_field_flag != prev_bottom_field_flag) 232 226 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 227 else if ((pic_order_cnt_type == 0 && prev_pic_order_cnt_type == 0) && 237 228 (pic_order_cnt_lsb != prev_pic_order_cnt_lsb || 238 229 delta_pic_order_cnt_bottom != … … bool H264Parser::new_AU(void) 256 247 prev_pic_parameter_set_id = pic_parameter_set_id; 257 248 prev_field_pic_flag = field_pic_flag; 258 249 prev_bottom_field_flag = bottom_field_flag; 259 prev_nal_ref_idc = nal_ref_idc;260 250 prev_pic_order_cnt_lsb = pic_order_cnt_lsb; 261 251 prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; 262 252 prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; … … uint32_t H264Parser::addBytes(const uint 273 263 { 274 264 const uint8_t *byteP = bytes; 275 265 const uint8_t *endP = bytes + byte_count; 276 266 const uint8_t *nalP; 277 267 uint8_t first_byte; 278 268 279 269 state_changed = false; … … uint32_t H264Parser::addBytes(const uint 305 295 11 End of stream end_of_stream_rbsp( ) 306 296 */ 307 297 first_byte = *(byteP - 1); 308 NAL_type = first_byte & 0x1f;298 nal_unit_type = first_byte & 0x1f; 309 299 nal_ref_idc = (first_byte >> 5) & 0x3; 310 300 311 if (NALisSlice(NAL_type) || NAL_type == SPS || NAL_type == PPS) 301 if (nal_unit_type == SPS || nal_unit_type == PPS || 302 nal_unit_type == SEI || NALisSlice(nal_unit_type)) 312 303 { 313 304 /* 314 305 bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE … … uint32_t H264Parser::addBytes(const uint 318 309 { 319 310 init_get_bits(&gb, byteP, 8 * (endP - byteP)); 320 311 321 if (NAL_type == SPS) 312 if (nal_unit_type == SEI) 313 { 314 nalP = ff_find_start_code(byteP+1, endP, 315 &sync_accumulator) - 8; 316 decode_SEI(&gb, (nalP - byteP) * 8); 317 set_AU_pending(stream_offset); 318 } 319 else if (nal_unit_type == SPS) 320 { 322 321 decode_SPS(&gb); 323 else if (NAL_type == PPS) 322 set_AU_pending(stream_offset); 323 } 324 else if (nal_unit_type == PPS) 325 { 324 326 decode_PPS(&gb); 327 set_AU_pending(stream_offset); 328 } 325 329 else 326 find_AU = decode_Header(&gb); 330 { 331 decode_Header(&gb); 332 if (new_AU()) 333 set_AU_pending(stream_offset); 334 } 327 335 328 336 byteP += (get_bits_count(&gb) / 8); 329 337 } 330 338 } 331 332 if (find_AU && new_AU()) 339 else if (!AU_pending) 333 340 { 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; 341 if (nal_unit_type == AU_DELIMITER || 342 (nal_unit_type > SPS_EXT && 343 nal_unit_type < AUXILIARY_SLICE)) 344 { 345 AU_pending = true; 346 AU_offset = stream_offset; 347 } 348 else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) && 349 nal_ref_idc != prev_nal_ref_idc) 350 { 351 AU_pending = true; 352 AU_offset = stream_offset; 353 } 339 354 } 340 341 if (AU_pending && NALisSlice( NAL_type))355 356 if (AU_pending && NALisSlice(nal_unit_type)) 342 357 { 343 358 /* Once we know the slice type of a new AU, we can 344 359 * determine if it is a keyframe or just a frame */ … … uint32_t H264Parser::addBytes(const uint 349 364 on_frame = true; 350 365 frame_start_offset = AU_offset; 351 366 352 if (isKeySlice(slice_type) && (!wait_for_IDR || seen_IDR)) 367 #ifdef USE_I_FRAME_AS_KEYFRAME 368 if (is_IDR || is_keyframe || isKeySlice(slice_type)) 369 #else 370 if (is_IDR || is_keyframe) 371 #endif 353 372 { 354 373 on_key_frame = true; 355 374 keyframe_start_offset = AU_offset; 356 375 } 357 376 else 358 377 on_key_frame = false; 378 379 is_IDR = is_keyframe = false; 359 380 } 360 381 else 361 382 on_frame = on_key_frame = false; 362 383 384 prev_nal_ref_idc = nal_ref_idc; 385 363 386 return byteP - bytes; 364 387 } 365 388 } … … bool H264Parser::decode_Header(GetBitCon 440 463 */ 441 464 442 465 frame_num = get_bits(gb, log2_max_frame_num); 443 if (NAL_type == SLICE_IDR || frame_num == 0) 444 seen_IDR = true; 466 is_IDR = (nal_unit_type == SLICE_IDR); 445 467 446 468 /* 447 469 field_pic_flag equal to 1 specifies that the slice is a slice of a … … void H264Parser::decode_PPS(GetBitContex 806 828 #endif 807 829 } 808 830 831 void H264Parser::decode_SEI(GetBitContext * gb, int bitlen) 832 { 833 int recovery_frame_cnt = -1; 834 bool exact_match_flag = false; 835 bool broken_link_flag = false; 836 int changing_group_slice_idc = -1; 837 838 while (get_bits_count(gb) < bitlen) 839 { 840 int type = 0, size = 0; 841 842 do { 843 type += show_bits(gb, 8); 844 } while (get_bits(gb, 8) == 255); 845 846 do { 847 size += show_bits(gb, 8); 848 } while (get_bits(gb, 8) == 255); 849 850 switch (type) 851 { 852 case SEI_TYPE_RECOVERY_POINT: 853 recovery_frame_cnt = get_ue_golomb(gb); 854 exact_match_flag = get_bits1(gb); 855 broken_link_flag = get_bits1(gb); 856 changing_group_slice_idc = get_bits(gb, 2); 857 is_keyframe = (recovery_frame_cnt >= 0); 858 return; 859 860 default: 861 skip_bits(gb, size * 8); 862 break; 863 } 864 865 align_get_bits(gb); 866 } 867 } 868 809 869 void H264Parser::vui_parameters(GetBitContext * gb) 810 870 { 811 871 /* -
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; }134 135 137 private: 136 138 enum constants {EXTENDED_SAR = 255}; 137 139 138 bool is_first_VCL_NAL_unit(void); 140 inline void set_AU_pending(const uint64_t & stream_offset) 141 { 142 if (!AU_pending) 143 { 144 AU_pending = true; 145 AU_offset = stream_offset; 146 } 147 } 148 139 149 bool new_AU(void); 140 150 bool decode_Header(GetBitContext *gb); 141 151 void decode_SPS(GetBitContext *gb); 142 152 void decode_PPS(GetBitContext * gb); 153 void decode_SEI(GetBitContext * gb, int len); 143 154 void vui_parameters(GetBitContext * gb); 144 155 145 bool find_AU;146 156 bool AU_pending; 147 157 bool state_changed; 148 158 bool seen_sps; 149 bool seen_IDR;159 bool is_IDR, is_keyframe; 150 160 151 161 uint32_t sync_accumulator; 152 162 GetBitContext gb; 153 163 154 uint8_t NAL_type;155 156 164 int prev_frame_num, frame_num; 157 165 uint slice_type; 158 166 int prev_pic_parameter_set_id, pic_parameter_set_id; … … class H264Parser { 188 196 189 197 uint64_t AU_offset, frame_start_offset, keyframe_start_offset; 190 198 bool on_frame, on_key_frame; 191 192 bool wait_for_IDR;193 199 }; 194 200 195 201 #endif /* H264PARSER_H */ -
libs/libmythtv/mpegrecorder.cpp
old new void MpegRecorder::ResetForNewFile(void) 1435 1435 bzero(_stream_id, sizeof(_stream_id)); 1436 1436 bzero(_pid_status, sizeof(_pid_status)); 1437 1437 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 1438 1439 m_h264_parser.waitForIDR(true);1440 1438 } 1441 1439 1442 1440 void MpegRecorder::Reset(void)