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