| 1 | diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
|
|---|
| 2 | index 3e45c60..5e337de 100644
|
|---|
| 3 | --- a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
|
|---|
| 4 | +++ b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
|
|---|
| 5 | @@ -98,7 +98,7 @@ H264Parser::H264Parser(void)
|
|---|
| 6 | rbsp_buffer_size = 0;
|
|---|
| 7 |
|
|---|
| 8 | Reset();
|
|---|
| 9 | - I_is_keyframe = true;
|
|---|
| 10 | + I_is_keyframe = false;
|
|---|
| 11 | au_contains_keyframe_message = false;
|
|---|
| 12 | }
|
|---|
| 13 |
|
|---|
| 14 | @@ -116,14 +116,14 @@ void H264Parser::Reset(void)
|
|---|
| 15 | prev_pic_parameter_set_id = pic_parameter_set_id = -1;
|
|---|
| 16 | prev_field_pic_flag = field_pic_flag = -1;
|
|---|
| 17 | prev_bottom_field_flag = bottom_field_flag = -1;
|
|---|
| 18 | - prev_nal_ref_idc = nal_ref_idc = 0;
|
|---|
| 19 | + prev_nal_ref_idc = nal_ref_idc = 111; // != [0|1|2|3]
|
|---|
| 20 | prev_pic_order_cnt_type = pic_order_cnt_type =
|
|---|
| 21 | prev_pic_order_cnt_lsb = pic_order_cnt_lsb = 0;
|
|---|
| 22 | prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0;
|
|---|
| 23 | prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0;
|
|---|
| 24 | prev_delta_pic_order_cnt[1] = delta_pic_order_cnt[1] = 0;
|
|---|
| 25 | prev_nal_unit_type = nal_unit_type = UNKNOWN;
|
|---|
| 26 | - prev_idr_pic_id = idr_pic_id = 0;
|
|---|
| 27 | + prev_idr_pic_id = idr_pic_id = 111; // != [0|1|2|3]
|
|---|
| 28 |
|
|---|
| 29 | log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0;
|
|---|
| 30 | seq_parameter_set_id = 0;
|
|---|
| 31 | @@ -401,6 +401,7 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes,
|
|---|
| 32 | const uint8_t *startP = bytes;
|
|---|
| 33 | const uint8_t *endP;
|
|---|
| 34 | bool found_start_code;
|
|---|
| 35 | + bool good_nal_unit;
|
|---|
| 36 |
|
|---|
| 37 | state_changed = false;
|
|---|
| 38 | on_frame = false;
|
|---|
| 39 | @@ -474,23 +475,41 @@ uint32_t H264Parser::addBytes(const uint8_t *bytes,
|
|---|
| 40 | nal_unit_type = sync_accumulator & 0x1f;
|
|---|
| 41 | nal_ref_idc = (sync_accumulator >> 5) & 0x3;
|
|---|
| 42 |
|
|---|
| 43 | - if (nal_unit_type == SPS || nal_unit_type == PPS ||
|
|---|
| 44 | - nal_unit_type == SEI || NALisSlice(nal_unit_type))
|
|---|
| 45 | - {
|
|---|
| 46 | - /* This is a NAL we need to parse. We may have the body
|
|---|
| 47 | - * of it in the part of the stream past to us this call,
|
|---|
| 48 | - * or we may get the rest in subsequent calls to addBytes.
|
|---|
| 49 | - * Either way, we set have_unfinished_NAL, so that we
|
|---|
| 50 | - * start filling the rbsp buffer */
|
|---|
| 51 | - have_unfinished_NAL = true;
|
|---|
| 52 | - }
|
|---|
| 53 | - else if (nal_unit_type == AU_DELIMITER ||
|
|---|
| 54 | - (nal_unit_type > SPS_EXT &&
|
|---|
| 55 | - nal_unit_type < AUXILIARY_SLICE))
|
|---|
| 56 | +/* nal_ref_idc shall be equal to 0 for all NAL units having nal_unit_type equal to 6, 9, 10, 11, or 12.
|
|---|
| 57 | + */
|
|---|
| 58 | + good_nal_unit = true;
|
|---|
| 59 | + if (nal_ref_idc && (nal_unit_type == SEI || (nal_unit_type >= AU_DELIMITER &&
|
|---|
| 60 | + nal_unit_type <= FILLER_DATA)) )
|
|---|
| 61 | + good_nal_unit = false;
|
|---|
| 62 | +
|
|---|
| 63 | +/* nal_ref_idc shall not be equal to 0 for NAL units with nal_unit_type equal to 5
|
|---|
| 64 | + */
|
|---|
| 65 | + if (!nal_ref_idc && (nal_unit_type == SLICE_IDR))
|
|---|
| 66 | + good_nal_unit = false;
|
|---|
| 67 | +
|
|---|
| 68 | + if (good_nal_unit)
|
|---|
| 69 | {
|
|---|
| 70 | - set_AU_pending();
|
|---|
| 71 | + if (nal_unit_type == SPS || nal_unit_type == PPS ||
|
|---|
| 72 | + nal_unit_type == SEI || NALisSlice(nal_unit_type))
|
|---|
| 73 | + {
|
|---|
| 74 | + /* This is a NAL we need to parse. We may have the body
|
|---|
| 75 | + * of it in the part of the stream past to us this call,
|
|---|
| 76 | + * or we may get the rest in subsequent calls to addBytes.
|
|---|
| 77 | + * Either way, we set have_unfinished_NAL, so that we
|
|---|
| 78 | + * start filling the rbsp buffer */
|
|---|
| 79 | + have_unfinished_NAL = true;
|
|---|
| 80 | + }
|
|---|
| 81 | + else if (nal_unit_type == AU_DELIMITER ||
|
|---|
| 82 | + (nal_unit_type > SPS_EXT &&
|
|---|
| 83 | + nal_unit_type < AUXILIARY_SLICE))
|
|---|
| 84 | + {
|
|---|
| 85 | + set_AU_pending();
|
|---|
| 86 | + }
|
|---|
| 87 | }
|
|---|
| 88 | - }
|
|---|
| 89 | + else
|
|---|
| 90 | + LOG(VB_GENERAL, LOG_ERR,
|
|---|
| 91 | + "H264Parser::addbytes: malformed NAL units");
|
|---|
| 92 | + } //found start code
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | return startP - bytes;
|
|---|
| 96 | @@ -523,6 +542,9 @@ void H264Parser::processRBSP(bool rbsp_complete)
|
|---|
| 97 |
|
|---|
| 98 | set_AU_pending();
|
|---|
| 99 |
|
|---|
| 100 | + if (!seen_sps)
|
|---|
| 101 | + SPS_offset = pkt_offset;
|
|---|
| 102 | +
|
|---|
| 103 | decode_SPS(&gb);
|
|---|
| 104 | }
|
|---|
| 105 | else if (nal_unit_type == PPS)
|
|---|
| 106 | @@ -576,6 +598,8 @@ void H264Parser::processRBSP(bool rbsp_complete)
|
|---|
| 107 | */
|
|---|
| 108 | bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 109 | {
|
|---|
| 110 | + uint first_mb_in_slice;
|
|---|
| 111 | +
|
|---|
| 112 | is_keyframe = false;
|
|---|
| 113 |
|
|---|
| 114 | if (log2_max_frame_num == 0 || pic_order_present_flag == -1)
|
|---|
| 115 | @@ -601,8 +625,7 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 116 | that precedes the current slice in decoding order and has the
|
|---|
| 117 | same value of colour_plane_id.
|
|---|
| 118 | */
|
|---|
| 119 | - //uint first_mb_in_slice = get_ue_golomb(gb);
|
|---|
| 120 | - get_ue_golomb(gb); // Replaced above line
|
|---|
| 121 | + first_mb_in_slice = get_ue_golomb_long(gb);
|
|---|
| 122 |
|
|---|
| 123 | /*
|
|---|
| 124 | slice_type specifies the coding type of the slice according to
|
|---|
| 125 | @@ -611,8 +634,10 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 126 | When nal_unit_type is equal to 5 (IDR picture), slice_type shall
|
|---|
| 127 | be equal to 2, 4, 7, or 9 (I or SI)
|
|---|
| 128 | */
|
|---|
| 129 | - slice_type = get_ue_golomb(gb);
|
|---|
| 130 | + slice_type = get_ue_golomb_31(gb);
|
|---|
| 131 |
|
|---|
| 132 | + /* s->pict_type = golomb_to_pict_type[slice_type % 5];
|
|---|
| 133 | + */
|
|---|
| 134 | /*
|
|---|
| 135 | pic_parameter_set_id specifies the picture parameter set in
|
|---|
| 136 | use. The value of pic_parameter_set_id shall be in the range of
|
|---|
| 137 | @@ -642,6 +667,8 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 138 | bitstream....
|
|---|
| 139 |
|
|---|
| 140 | If the current picture is an IDR picture, frame_num shall be equal to 0.
|
|---|
| 141 | +
|
|---|
| 142 | + When max_num_ref_frames is equal to 0, slice_type shall be equal to 2, 4, 7, or 9.
|
|---|
| 143 | */
|
|---|
| 144 |
|
|---|
| 145 | frame_num = get_bits(gb, log2_max_frame_num);
|
|---|
| 146 | @@ -683,9 +710,10 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 147 | {
|
|---|
| 148 | idr_pic_id = get_ue_golomb(gb);
|
|---|
| 149 | is_keyframe = true;
|
|---|
| 150 | + I_is_keyframe = true;
|
|---|
| 151 | }
|
|---|
| 152 | else
|
|---|
| 153 | - is_keyframe |= I_is_keyframe && isKeySlice(slice_type);
|
|---|
| 154 | + is_keyframe = isKeySlice(slice_type);
|
|---|
| 155 | /*
|
|---|
| 156 | pic_order_cnt_lsb specifies the picture order count modulo
|
|---|
| 157 | MaxPicOrderCntLsb for the top field of a coded frame or for a coded
|
|---|
| 158 | @@ -702,7 +730,7 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 159 | {
|
|---|
| 160 | pic_order_cnt_lsb = get_bits(gb, log2_max_pic_order_cnt_lsb);
|
|---|
| 161 |
|
|---|
| 162 | - if (pic_order_present_flag && !field_pic_flag)
|
|---|
| 163 | + if ((pic_order_present_flag == 1) && !field_pic_flag)
|
|---|
| 164 | delta_pic_order_cnt_bottom = get_se_golomb(gb);
|
|---|
| 165 | else
|
|---|
| 166 | delta_pic_order_cnt_bottom = 0;
|
|---|
| 167 | @@ -731,13 +759,17 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 168 | {
|
|---|
| 169 | delta_pic_order_cnt[0] = get_se_golomb(gb);
|
|---|
| 170 |
|
|---|
| 171 | - if (pic_order_present_flag && !field_pic_flag)
|
|---|
| 172 | + if ((pic_order_present_flag == 1) && !field_pic_flag)
|
|---|
| 173 | delta_pic_order_cnt[1] = get_se_golomb(gb);
|
|---|
| 174 | - else
|
|---|
| 175 | + }
|
|---|
| 176 | + else
|
|---|
| 177 | + {
|
|---|
| 178 | + if (pic_order_cnt_type == 1)
|
|---|
| 179 | + {
|
|---|
| 180 | delta_pic_order_cnt[1] = 0;
|
|---|
| 181 | - }
|
|---|
| 182 | - else
|
|---|
| 183 | - delta_pic_order_cnt[0] = 0;
|
|---|
| 184 | + delta_pic_order_cnt[0] = 0;
|
|---|
| 185 | + }
|
|---|
| 186 | + }
|
|---|
| 187 |
|
|---|
| 188 | /*
|
|---|
| 189 | redundant_pic_cnt shall be equal to 0 for slices and slice data
|
|---|
| 190 | @@ -760,10 +792,13 @@ bool H264Parser::decode_Header(GetBitContext *gb)
|
|---|
| 191 | void H264Parser::decode_SPS(GetBitContext * gb)
|
|---|
| 192 | {
|
|---|
| 193 | int profile_idc;
|
|---|
| 194 | + int lastScale;
|
|---|
| 195 | + int nextScale;
|
|---|
| 196 | + int deltaScale;
|
|---|
| 197 |
|
|---|
| 198 | seen_sps = true;
|
|---|
| 199 |
|
|---|
| 200 | - profile_idc = get_bits(gb, 8); // profile_idc
|
|---|
| 201 | + profile_idc = get_bits(gb, 8);
|
|---|
| 202 | get_bits1(gb); // constraint_set0_flag
|
|---|
| 203 | get_bits1(gb); // constraint_set1_flag
|
|---|
| 204 | get_bits1(gb); // constraint_set2_flag
|
|---|
| 205 | @@ -772,9 +807,11 @@ void H264Parser::decode_SPS(GetBitContext * gb)
|
|---|
| 206 | get_bits(gb, 8); // level_idc
|
|---|
| 207 | get_ue_golomb(gb); // sps_id
|
|---|
| 208 |
|
|---|
| 209 | - if (profile_idc >= 100)
|
|---|
| 210 | + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
|
|---|
| 211 | + profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
|
|---|
| 212 | + profile_idc == 86 || profile_idc == 118 || profile_idc == 128 )
|
|---|
| 213 | { // high profile
|
|---|
| 214 | - if ((chroma_format_idc = get_ue_golomb(gb)) == 3) // chroma_format_idc
|
|---|
| 215 | + if ((chroma_format_idc = get_ue_golomb(gb)) == 3)
|
|---|
| 216 | separate_colour_plane_flag = (get_bits1(gb) == 1);
|
|---|
| 217 |
|
|---|
| 218 | get_ue_golomb(gb); // bit_depth_luma_minus8
|
|---|
| 219 | @@ -785,12 +822,18 @@ void H264Parser::decode_SPS(GetBitContext * gb)
|
|---|
| 220 | {
|
|---|
| 221 | for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); ++idx)
|
|---|
| 222 | {
|
|---|
| 223 | - if (get_bits1(gb)) // Scaling list presnent
|
|---|
| 224 | + if (get_bits1(gb)) // Scaling list present
|
|---|
| 225 | {
|
|---|
| 226 | + lastScale = nextScale = 8;
|
|---|
| 227 | int sl_n = ((idx < 6) ? 16 : 64);
|
|---|
| 228 | - for(int sl_i = 0; sl_i < sl_n; sl_i++)
|
|---|
| 229 | + for(int sl_i = 0; sl_i < sl_n; ++sl_i)
|
|---|
| 230 | {
|
|---|
| 231 | - get_se_golomb(gb);
|
|---|
| 232 | + if (nextScale != 0)
|
|---|
| 233 | + {
|
|---|
| 234 | + deltaScale = get_se_golomb(gb);
|
|---|
| 235 | + nextScale = (lastScale + deltaScale + 256) % 256;
|
|---|
| 236 | + }
|
|---|
| 237 | + lastScale = (nextScale == 0) ? lastScale : nextScale;
|
|---|
| 238 | }
|
|---|
| 239 | }
|
|---|
| 240 | }
|
|---|
| 241 | @@ -809,6 +852,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
|
|---|
| 242 | int offset_for_non_ref_pic;
|
|---|
| 243 | int offset_for_top_to_bottom_field;
|
|---|
| 244 | uint tmp;
|
|---|
| 245 | + bool gaps_in_frame_num_allowed_flag;
|
|---|
| 246 |
|
|---|
| 247 | /*
|
|---|
| 248 | pic_order_cnt_type specifies the method to decode picture order
|
|---|
| 249 | @@ -886,8 +930,7 @@ void H264Parser::decode_SPS(GetBitContext * gb)
|
|---|
| 250 | decoding process in case of an inferred gap between values of
|
|---|
| 251 | frame_num as specified in subclause 8.2.5.2.
|
|---|
| 252 | */
|
|---|
| 253 | - //bool gaps_in_frame_num_allowed_flag = get_bits1(gb);
|
|---|
| 254 | - get_bits1(gb); // Replaced above line
|
|---|
| 255 | + gaps_in_frame_num_allowed_flag = get_bits1(gb);
|
|---|
| 256 |
|
|---|
| 257 | /*
|
|---|
| 258 | pic_width_in_mbs_minus1 plus 1 specifies the width of each
|
|---|
| 259 | @@ -1040,20 +1083,28 @@ void H264Parser::decode_SEI(GetBitContext *gb)
|
|---|
| 260 | bool broken_link_flag = false;
|
|---|
| 261 | int changing_group_slice_idc = -1;
|
|---|
| 262 |
|
|---|
| 263 | - int type = 0, size = 0;
|
|---|
| 264 | + int type = 0, size = 0, tmp_byte = 0;
|
|---|
| 265 |
|
|---|
| 266 | /* A message requires at least 2 bytes, and then
|
|---|
| 267 | * there's the stop bit plus alignment, so there
|
|---|
| 268 | * can be no message in less than 24 bits */
|
|---|
| 269 | while (get_bits_left(gb) >= 24)
|
|---|
| 270 | {
|
|---|
| 271 | - do {
|
|---|
| 272 | - type += show_bits(gb, 8);
|
|---|
| 273 | - } while (get_bits(gb, 8) == 255);
|
|---|
| 274 | + tmp_byte = get_bits(gb, 8);
|
|---|
| 275 | + while (tmp_byte == 255)
|
|---|
| 276 | + {
|
|---|
| 277 | + type += 255;
|
|---|
| 278 | + tmp_byte = get_bits(gb, 8);
|
|---|
| 279 | + }
|
|---|
| 280 | + type += get_bits(gb, 8); //last_payload_type_byte
|
|---|
| 281 |
|
|---|
| 282 | - do {
|
|---|
| 283 | - size += show_bits(gb, 8);
|
|---|
| 284 | - } while (get_bits(gb, 8) == 255);
|
|---|
| 285 | + tmp_byte = get_bits(gb, 8);
|
|---|
| 286 | + while (tmp_byte == 255)
|
|---|
| 287 | + {
|
|---|
| 288 | + size += 255;
|
|---|
| 289 | + tmp_byte = get_bits(gb, 8);
|
|---|
| 290 | + }
|
|---|
| 291 | + size += get_bits(gb, 8); //last_payload_size_byte
|
|---|
| 292 |
|
|---|
| 293 | switch (type)
|
|---|
| 294 | {
|
|---|
| 295 | @@ -1063,6 +1114,8 @@ void H264Parser::decode_SEI(GetBitContext *gb)
|
|---|
| 296 | broken_link_flag = get_bits1(gb);
|
|---|
| 297 | changing_group_slice_idc = get_bits(gb, 2);
|
|---|
| 298 | au_contains_keyframe_message = (recovery_frame_cnt == 0);
|
|---|
| 299 | + if ((size - 12) > 0)
|
|---|
| 300 | + skip_bits(gb, (size - 12) * 8);
|
|---|
| 301 | return;
|
|---|
| 302 |
|
|---|
| 303 | default:
|
|---|
| 304 | diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.h b/mythtv/libs/libmythtv/mpeg/H264Parser.h
|
|---|
| 305 | index 9c984e0..7b750f2 100644
|
|---|
| 306 | --- a/mythtv/libs/libmythtv/mpeg/H264Parser.h
|
|---|
| 307 | +++ b/mythtv/libs/libmythtv/mpeg/H264Parser.h
|
|---|
| 308 | @@ -60,7 +60,7 @@ class H264Parser {
|
|---|
| 309 | // ITU-T Rec. H.264 table 7-1
|
|---|
| 310 | enum NAL_unit_type {
|
|---|
| 311 | UNKNOWN = 0,
|
|---|
| 312 | - SLICE = 1,
|
|---|
| 313 | + SLICE = 1, // 1 - 5 are VCL NAL units
|
|---|
| 314 | SLICE_DPA = 2,
|
|---|
| 315 | SLICE_DPB = 3,
|
|---|
| 316 | SLICE_DPC = 4,
|
|---|
| 317 | @@ -73,11 +73,15 @@ class H264Parser {
|
|---|
| 318 | END_STREAM = 11,
|
|---|
| 319 | FILLER_DATA = 12,
|
|---|
| 320 | SPS_EXT = 13,
|
|---|
| 321 | - AUXILIARY_SLICE = 19
|
|---|
| 322 | + NALU_prefix = 14,
|
|---|
| 323 | + SPS_subset = 15,
|
|---|
| 324 | + AUXILIARY_SLICE = 19,
|
|---|
| 325 | + SLICE_EXTENSION = 20
|
|---|
| 326 | };
|
|---|
| 327 |
|
|---|
| 328 | enum SEI_type {
|
|---|
| 329 | SEI_TYPE_PIC_TIMING = 1,
|
|---|
| 330 | + SEI_FILLER_PAYLOAD = 3,
|
|---|
| 331 | SEI_TYPE_USER_DATA_UNREGISTERED = 5,
|
|---|
| 332 | SEI_TYPE_RECOVERY_POINT = 6
|
|---|
| 333 | };
|
|---|
| 334 | @@ -147,7 +151,9 @@ class H264Parser {
|
|---|
| 335 |
|
|---|
| 336 | uint64_t frameAUstreamOffset(void) const {return frame_start_offset;}
|
|---|
| 337 | uint64_t keyframeAUstreamOffset(void) const {return keyframe_start_offset;}
|
|---|
| 338 | + uint64_t SPSstreamOffset(void) const {return SPS_offset;}
|
|---|
| 339 |
|
|---|
| 340 | +// == NAL_type AU_delimiter: primary_pic_type = 5
|
|---|
| 341 | static int isKeySlice(uint slice_type)
|
|---|
| 342 | {
|
|---|
| 343 | return (slice_type == SLICE_I ||
|
|---|
| 344 | @@ -164,6 +170,7 @@ class H264Parser {
|
|---|
| 345 | }
|
|---|
| 346 |
|
|---|
| 347 | void use_I_forKeyframes(bool val) { I_is_keyframe = val; }
|
|---|
| 348 | + bool using_I_forKeyframes(void) const { return I_is_keyframe; }
|
|---|
| 349 |
|
|---|
| 350 | uint32_t GetTimeScale(void) const { return timeScale; }
|
|---|
| 351 |
|
|---|
| 352 | @@ -172,6 +179,10 @@ class H264Parser {
|
|---|
| 353 | void parse_SPS(uint8_t *sps, uint32_t sps_size,
|
|---|
| 354 | bool& interlaced, int32_t& max_ref_frames);
|
|---|
| 355 |
|
|---|
| 356 | + bool seen_SPS(void) const { return seen_sps; }
|
|---|
| 357 | +
|
|---|
| 358 | + bool found_AU(void) const { return AU_pending; }
|
|---|
| 359 | +
|
|---|
| 360 | private:
|
|---|
| 361 | enum constants {EXTENDED_SAR = 255};
|
|---|
| 362 |
|
|---|
| 363 | @@ -247,6 +258,7 @@ class H264Parser {
|
|---|
| 364 | bool fixedRate;
|
|---|
| 365 |
|
|---|
| 366 | uint64_t pkt_offset, AU_offset, frame_start_offset, keyframe_start_offset;
|
|---|
| 367 | + uint64_t SPS_offset;
|
|---|
| 368 | bool on_frame, on_key_frame;
|
|---|
| 369 | };
|
|---|
| 370 |
|
|---|
| 371 | diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
|
|---|
| 372 | index e25774d..2cd7efc 100644
|
|---|
| 373 | --- a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
|
|---|
| 374 | +++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
|
|---|
| 375 | @@ -38,6 +38,18 @@ extern "C" {
|
|---|
| 376 |
|
|---|
| 377 | const uint DTVRecorder::kMaxKeyFrameDistance = 80;
|
|---|
| 378 |
|
|---|
| 379 | +const uint seen_kf_limit = 4; // hdpvr kf at 2sec/120frames
|
|---|
| 380 | +
|
|---|
| 381 | /** \class DTVRecorder
|
|---|
| 382 | * \brief This is a specialization of RecorderBase used to
|
|---|
| 383 | * handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams.
|
|---|
| 384 | @@ -55,16 +67,17 @@ DTVRecorder::DTVRecorder(TVRec *rec) :
|
|---|
| 385 | _start_code(0xffffffff), _first_keyframe(-1),
|
|---|
| 386 | _last_gop_seen(0), _last_seq_seen(0),
|
|---|
| 387 | _last_keyframe_seen(0),
|
|---|
| 388 | _audio_bytes_remaining(0), _video_bytes_remaining(0),
|
|---|
| 389 | _other_bytes_remaining(0),
|
|---|
| 390 | + _skip_bytes_remaining(0),
|
|---|
| 391 | // MPEG2 parser information
|
|---|
| 392 | _progressive_sequence(0),
|
|---|
| 393 | _repeat_pict(0),
|
|---|
| 394 | // H.264 support
|
|---|
| 395 | _pes_synced(false),
|
|---|
| 396 | _seen_sps(false),
|
|---|
| 397 | + _seen_kf_count(0),
|
|---|
| 398 | // settings
|
|---|
| 399 | - _wait_for_keyframe_option(true),
|
|---|
| 400 | + _wait_for_keyframe_option(true), // is wait_for_SPS for H264
|
|---|
| 401 | _has_written_other_keyframe(false),
|
|---|
| 402 | // state
|
|---|
| 403 | _error(),
|
|---|
| 404 | @@ -171,7 +184,7 @@ void DTVRecorder::ResetForNewFile(void)
|
|---|
| 405 | LOG(VB_RECORD, LOG_INFO, LOC + "ResetForNewFile(void)");
|
|---|
| 406 | QMutexLocker locker(&positionMapLock);
|
|---|
| 407 |
|
|---|
| 408 | - // _seen_psp and m_h264_parser should
|
|---|
| 409 | + // _seen_sps and m_h264_parser should
|
|---|
| 410 | // not be reset here. This will only be called just as
|
|---|
| 411 | // we're seeing the first packet of a new keyframe for
|
|---|
| 412 | // writing to the new file and anything that makes the
|
|---|
| 413 | @@ -179,15 +192,12 @@ void DTVRecorder::ResetForNewFile(void)
|
|---|
| 414 | // send significant amounts of good data to /dev/null.
|
|---|
| 415 | // -- Daniel Kristjansson 2011-02-26
|
|---|
| 416 |
|
|---|
| 417 | - _start_code = 0xffffffff;
|
|---|
| 418 | _first_keyframe = -1;
|
|---|
| 419 | _has_written_other_keyframe = false;
|
|---|
| 420 | _last_keyframe_seen = 0;
|
|---|
| 421 | _last_gop_seen = 0;
|
|---|
| 422 | _last_seq_seen = 0;
|
|---|
| 423 | _audio_bytes_remaining = 0;
|
|---|
| 424 | _video_bytes_remaining = 0;
|
|---|
| 425 | _other_bytes_remaining = 0;
|
|---|
| 426 | + _skip_bytes_remaining = 0;
|
|---|
| 427 | //_recording
|
|---|
| 428 | _error = QString();
|
|---|
| 429 |
|
|---|
| 430 | @@ -195,7 +205,9 @@ void DTVRecorder::ResetForNewFile(void)
|
|---|
| 431 | _repeat_pict = 0;
|
|---|
| 432 |
|
|---|
| 433 | //_pes_synced
|
|---|
| 434 | - //_seen_sps
|
|---|
| 435 | + _seen_sps = false;
|
|---|
| 436 | + _seen_seq = false;
|
|---|
| 437 | +
|
|---|
| 438 | positionMap.clear();
|
|---|
| 439 | positionMapDelta.clear();
|
|---|
| 440 | durationMap.clear();
|
|---|
| 441 | @@ -231,8 +243,6 @@ void DTVRecorder::Reset(void)
|
|---|
| 442 | LOG(VB_RECORD, LOG_INFO, LOC + "Reset(void)");
|
|---|
| 443 | ResetForNewFile();
|
|---|
| 444 |
|
|---|
| 445 | - _start_code = 0xffffffff;
|
|---|
| 446 | -
|
|---|
| 447 | if (curRecording)
|
|---|
| 448 | {
|
|---|
| 449 | curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
|
|---|
| 450 | @@ -276,9 +286,8 @@ void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert)
|
|---|
| 451 | {
|
|---|
| 452 | if (!insert) // PAT/PMT may need inserted in front of any buffered data
|
|---|
| 453 | {
|
|---|
| 454 | - // delay until first GOP to avoid decoder crash on res change
|
|---|
| 455 | - if (!_buffer_packets && _wait_for_keyframe_option &&
|
|---|
| 456 | - _first_keyframe < 0)
|
|---|
| 457 | + // delay until first SPS/GOP to avoid decoder crash on res change
|
|---|
| 458 | + if (!_buffer_packets && !_seen_sps)
|
|---|
| 459 | return;
|
|---|
| 460 |
|
|---|
| 461 | if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
|
|---|
| 462 | @@ -419,16 +428,20 @@ bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
|
|---|
| 463 | // looking for first byte of MPEG start code (3 bytes 0 0 1)
|
|---|
| 464 | // otherwise, pick up search where we left off.
|
|---|
| 465 | const bool payloadStart = tspacket->PayloadStart();
|
|---|
| 466 | - _start_code = (payloadStart) ? 0xffffffff : _start_code;
|
|---|
| 467 | + if (payloadStart)
|
|---|
| 468 | + {
|
|---|
| 469 | + _seen_sps = false;
|
|---|
| 470 | + if (!_wait_for_keyframe_option)
|
|---|
| 471 | + _seen_sps = true;
|
|---|
| 472 | + }
|
|---|
| 473 |
|
|---|
| 474 | // Just make these local for efficiency reasons (gcc not so smart..)
|
|---|
| 475 | const uint maxKFD = kMaxKeyFrameDistance;
|
|---|
| 476 |
|
|---|
| 477 | void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts)
|
|---|
| 478 | @@ -718,6 +788,7 @@ bool DTVRecorder::FindAudioKeyframes(const TSPacket*)
|
|---|
| 479 | _audio_timer.start();
|
|---|
| 480 |
|
|---|
| 481 | _buffer_packets = false;
|
|---|
| 482 | + _seen_sps = true; // unblock BufferedWrite()
|
|---|
| 483 | _frames_seen_count++;
|
|---|
| 484 |
|
|---|
| 485 | if (1 == (_frames_seen_count & 0x7))
|
|---|
| 486 | @@ -815,6 +886,7 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
|---|
| 487 | // reset PES sync state
|
|---|
| 488 | _pes_synced = false;
|
|---|
| 489 | _start_code = 0xffffffff;
|
|---|
| 490 | + _seen_sps = false;
|
|---|
| 491 | }
|
|---|
| 492 |
|
|---|
| 493 | uint aspectRatio = 0;
|
|---|
| 494 | @@ -898,30 +970,49 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
|---|
| 495 | uint32_t bytes_used = m_h264_parser.addBytes
|
|---|
| 496 | (tspacket->data() + i, TSPacket::kSize - i,
|
|---|
| 497 | ringBuffer->GetWritePosition());
|
|---|
| 498 | - i += (bytes_used - 1);
|
|---|
| 499 |
|
|---|
| 500 | - if (m_h264_parser.stateChanged())
|
|---|
| 501 | + // 3 states:
|
|---|
| 502 | + // no SPS & no keyframes seen -> clear buffer
|
|---|
| 503 | + // no SPS & keyframes seen -> count keyframes, don't clear buffer
|
|---|
| 504 | + // if (keyframe count >= limit) then set seen_SPS
|
|---|
| 505 | + // SPS seen -> don't clear buffer, buffer_pkts false (write to file)
|
|---|
| 506 | + if (!_seen_sps)
|
|---|
| 507 | + {
|
|---|
| 508 | + if(!_wait_for_keyframe_option || m_h264_parser.seen_SPS())
|
|---|
| 509 | + _seen_sps = true;
|
|---|
| 510 | + if (m_h264_parser.onKeyFrameStart())
|
|---|
| 511 | + ++_seen_kf_count;
|
|---|
| 512 | + if (_seen_kf_count >= seen_kf_limit)
|
|---|
| 513 | + _seen_sps = true;
|
|---|
| 514 | + }
|
|---|
| 515 | + if (m_h264_parser.stateChanged() && _seen_sps)
|
|---|
| 516 | {
|
|---|
| 517 | if (m_h264_parser.onFrameStart() &&
|
|---|
| 518 | m_h264_parser.FieldType() != H264Parser::FIELD_BOTTOM)
|
|---|
| 519 | {
|
|---|
| 520 | hasKeyFrame = m_h264_parser.onKeyFrameStart();
|
|---|
| 521 | hasFrame = true;
|
|---|
| 522 | - _seen_sps |= hasKeyFrame;
|
|---|
| 523 | -
|
|---|
| 524 | width = m_h264_parser.pictureWidth();
|
|---|
| 525 | height = m_h264_parser.pictureHeight();
|
|---|
| 526 | aspectRatio = m_h264_parser.aspectRatio();
|
|---|
| 527 | m_h264_parser.getFrameRate(frameRate);
|
|---|
| 528 | }
|
|---|
| 529 | }
|
|---|
| 530 | +
|
|---|
| 531 | + i += (bytes_used - 1);
|
|---|
| 532 | } // for (; i < TSPacket::kSize; ++i)
|
|---|
| 533 |
|
|---|
| 534 | // _buffer_packets will only be true if a payload start has been seen
|
|---|
| 535 | - if (hasKeyFrame && (_buffer_packets || _first_keyframe >= 0))
|
|---|
| 536 | + if (_seen_sps)
|
|---|
| 537 | + _buffer_packets = false;
|
|---|
| 538 | + else
|
|---|
| 539 | + if (_seen_kf_count < seen_kf_limit)
|
|---|
| 540 | + _payload_buffer.clear();
|
|---|
| 541 | +
|
|---|
| 542 | + if (hasKeyFrame)
|
|---|
| 543 | {
|
|---|
| 544 | LOG(VB_RECORD, LOG_DEBUG, LOC + QString
|
|---|
| 545 | - ("Keyframe @ %1 + %2 = %3 AU %4")
|
|---|
| 546 | + ("H264Keyframe @ %1 + %2 = %3 AU %4")
|
|---|
| 547 | .arg(ringBuffer->GetWritePosition())
|
|---|
| 548 | .arg(_payload_buffer.size())
|
|---|
| 549 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
|
|---|
| 550 | @@ -934,22 +1025,15 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
|---|
| 551 | if (hasFrame)
|
|---|
| 552 | {
|
|---|
| 553 | LOG(VB_RECORD, LOG_DEBUG, LOC + QString
|
|---|
| 554 | - ("Frame @ %1 + %2 = %3 AU %4")
|
|---|
| 555 | + ("H264Frame @ %1 + %2 = %3 AU %4")
|
|---|
| 556 | .arg(ringBuffer->GetWritePosition())
|
|---|
| 557 | .arg(_payload_buffer.size())
|
|---|
| 558 | .arg(ringBuffer->GetWritePosition() + _payload_buffer.size())
|
|---|
| 559 | - .arg(m_h264_parser.keyframeAUstreamOffset()));
|
|---|
| 560 | + .arg(m_h264_parser.frameAUstreamOffset()));
|
|---|
| 561 |
|
|---|
| 562 | - _buffer_packets = false; // We now know if this is a keyframe
|
|---|
| 563 | _frames_seen_count++;
|
|---|
| 564 | - if (!_wait_for_keyframe_option || _first_keyframe >= 0)
|
|---|
| 565 | + if (_first_keyframe >= 0)
|
|---|
| 566 | UpdateFramesWritten();
|
|---|
| 567 | - else
|
|---|
| 568 | - {
|
|---|
| 569 | - /* Found a frame that is not a keyframe, and we want to
|
|---|
| 570 | - * start on a keyframe */
|
|---|
| 571 | - _payload_buffer.clear();
|
|---|
| 572 | - }
|
|---|
| 573 | }
|
|---|
| 574 |
|
|---|
| 575 | if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
|
|---|
| 576 | @@ -971,12 +1055,12 @@ bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
|
|---|
| 577 | QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
|
|---|
| 578 | .arg( m_h264_parser.GetTimeScale() )
|
|---|
| 579 | .arg( m_h264_parser.GetUnitsInTick() )
|
|---|
| 580 | - .arg( frameRate.toDouble() * 1000 ) );
|
|---|
| 581 | + .arg( frameRate.toDouble() ) );
|
|---|
| 582 | m_frameRate = frameRate;
|
|---|
| 583 | FrameRateChange(frameRate.toDouble() * 1000, _frames_written_count);
|
|---|
| 584 | }
|
|---|
| 585 |
|
|---|
| 586 | - return _seen_sps;
|
|---|
| 587 | + return hasKeyFrame;
|
|---|
| 588 | }
|
|---|
| 589 |
|
|---|
| 590 | /** \fn DTVRecorder::HandleH264Keyframe(void)
|
|---|
| 591 | @@ -991,15 +1075,9 @@ void DTVRecorder::HandleH264Keyframe(void)
|
|---|
| 592 | uint64_t startpos;
|
|---|
| 593 | uint64_t frameNum = _frames_written_count;
|
|---|
| 594 |
|
|---|
| 595 | - if (_first_keyframe < 0)
|
|---|
| 596 | - {
|
|---|
| 597 | - _first_keyframe = frameNum;
|
|---|
| 598 | - startpos = 0;
|
|---|
| 599 | - }
|
|---|
| 600 | - else
|
|---|
| 601 | - startpos = m_h264_parser.keyframeAUstreamOffset();
|
|---|
| 602 | + startpos = m_h264_parser.keyframeAUstreamOffset();
|
|---|
| 603 |
|
|---|
| 604 | - // Add key frame to position map
|
|---|
| 605 | + // Add keyframe to position map
|
|---|
| 606 | positionMapLock.lock();
|
|---|
| 607 | if (!positionMap.contains(frameNum))
|
|---|
| 608 | {
|
|---|
| 609 | @@ -1008,14 +1086,27 @@ void DTVRecorder::HandleH264Keyframe(void)
|
|---|
| 610 | durationMap[frameNum] = _total_duration + 0.5;
|
|---|
| 611 | durationMapDelta[frameNum] = _total_duration + 0.5;
|
|---|
| 612 | }
|
|---|
| 613 | + if ((_first_keyframe < 0) && !positionMap.contains(0))
|
|---|
| 614 | + {
|
|---|
| 615 | + positionMapDelta[0] = 0;
|
|---|
| 616 | + positionMap[0] = 0;
|
|---|
| 617 | + durationMap[0] = 0.5;
|
|---|
| 618 | + durationMapDelta[0] = 0.5;
|
|---|
| 619 | + }
|
|---|
| 620 | positionMapLock.unlock();
|
|---|
| 621 | +
|
|---|
| 622 | + if (_first_keyframe < 0)
|
|---|
| 623 | + {
|
|---|
| 624 | + _first_keyframe = frameNum;
|
|---|
| 625 | + }
|
|---|
| 626 | }
|
|---|
| 627 |
|
|---|
| 628 |
|
|---|
| 629 | void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)
|
|---|
| 630 | @@ -1328,6 +1523,7 @@ bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
|
|---|
| 631 | if (_input_pmt && _has_no_av)
|
|---|
| 632 | {
|
|---|
| 633 | FindOtherKeyframes(&tspacket);
|
|---|
| 634 | + _seen_sps = true; // unblock BufferedWrite()
|
|---|
| 635 | _buffer_packets = false;
|
|---|
| 636 | }
|
|---|
| 637 | else
|
|---|
| 638 | @@ -1383,11 +1579,11 @@ bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
|
|---|
| 639 | return ProcessAVTSPacket(tspacket);
|
|---|
| 640 | }
|
|---|
| 641 |
|
|---|
| 642 | -/// Common code for processing either audio or video packets
|
|---|
| 643 | +/// Common code for processing either audio or video packets (mpeg2 or h264)
|
|---|
| 644 | bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
|
|---|
| 645 | {
|
|---|
| 646 | - // Sync recording start to first keyframe
|
|---|
| 647 | - if (_wait_for_keyframe_option && _first_keyframe < 0)
|
|---|
| 648 | + // Sync recording start to first SPS / keyframe
|
|---|
| 649 | + if (!_seen_sps && _first_keyframe < 0)
|
|---|
| 650 | {
|
|---|
| 651 | if (_buffer_packets)
|
|---|
| 652 | BufferedWrite(tspacket);
|
|---|
| 653 | diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.h b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
|
|---|
| 654 | index 51cbb0c..42d8735 100644
|
|---|
| 655 | --- a/mythtv/libs/libmythtv/recorders/dtvrecorder.h
|
|---|
| 656 | +++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
|
|---|
| 657 | @@ -110,7 +110,7 @@ class DTVRecorder :
|
|---|
| 658 | void HandleH264Keyframe(void);
|
|---|
| 659 |
|
|---|
| 660 | // MPEG2 PS support (Hauppauge PVR-x50/PVR-500)
|
|---|
| 661 | void FindPSKeyFrames(const uint8_t *buffer, uint len);
|
|---|
| 662 |
|
|---|
| 663 | // For handling other (non audio/video) packets
|
|---|
| 664 | bool FindOtherKeyframes(const TSPacket *tspacket);
|
|---|
| 665 | @@ -136,6 +136,11 @@ class DTVRecorder :
|
|---|
| 666 | unsigned int _audio_bytes_remaining;
|
|---|
| 667 | unsigned int _video_bytes_remaining;
|
|---|
| 668 | unsigned int _other_bytes_remaining;
|
|---|
| 669 | + int _skip_bytes_remaining;
|
|---|
| 670 | +
|
|---|
| 671 | + // MPEGPS parser information
|
|---|
| 672 | + bool _seen_seq;
|
|---|
| 673 | + bool _next_frame_isKey;
|
|---|
| 674 |
|
|---|
| 675 | // MPEG2 parser information
|
|---|
| 676 | int _progressive_sequence;
|
|---|
| 677 | @@ -144,6 +149,7 @@ class DTVRecorder :
|
|---|
| 678 | // H.264 support
|
|---|
| 679 | bool _pes_synced;
|
|---|
| 680 | bool _seen_sps;
|
|---|
| 681 | + int _seen_kf_count;
|
|---|
| 682 | H264Parser m_h264_parser;
|
|---|
| 683 |
|
|---|
| 684 | /// Wait for the a GOP/SEQ-start before sending data
|
|---|
| 685 |
|
|---|