/Play/nal.js
JavaScript | 648 lines | 451 code | 81 blank | 116 comment | 131 complexity | a50e9c99b47a5afae897393b470f8415 MD5 | raw file
Possible License(s): BSD-3-Clause
1var Video = (function() { 2 function constructor() { 3 } 4 return constructor; 5})(); 6 7/** 8 * Represents a video decoder capturing all of its internal state. 9 */ 10var Decoder = (function() { 11 function constructor() { 12 this.SequenceParameterSets = []; 13 this.PictureParameterSets = []; 14 this.Video = new Video(); 15 } 16 17 constructor.prototype = { 18 decode : function(ptr) { 19 var reader = new AnnexBNALUnitReader(ptr); 20 21 var i = 0; 22 do { 23 var nal = reader.readNALUnit(); 24 if (nal != null) { 25 traceln("+ NAL Unit " + (i++)); 26 var unit = nal.createUnit(); 27 traceln("| nal_size: " + (nal.rbsp.length + 1)); 28 traceln("| nal_type: " + nal.nal_type); 29 traceln("| nal_ref_idc: " + nal.nal_ref_idc); 30 if (unit != null) { 31 unit.decode(new Bitstream(nal.rbsp)); 32 // println(unit.toString()); 33 } 34 } 35 } while (nal != null); 36 } 37 }; 38 39 return constructor; 40})(); 41 42 43/* 44 * Represents an Annex B (B) byte stream that encodes NAL Units. In the Annex B 45 * byte stream NAL Units are prefixed by a 3 byte start code prefix. The actual 46 * NAL Unit payload data is interleaved with 'emulation prevention' bytes. 47 */ 48var AnnexBNALUnitReader = (function () { 49 var ptr = null; 50 51 function constructor(ptr) { 52 this.ptr = ptr; 53 } 54 55 constructor.prototype = { 56 57 readNALUnit : function() { 58 if (this.ptr == null) { 59 return null; 60 } 61 var res = this.findNextAnnexBNALUnit(this.ptr); 62 this.ptr = res.next; 63 return new NALUnit(res.nal); 64 }, 65 66 /* 67 * Finds the next NAL unit from an Annex B byte stream. 68 */ 69 findNextAnnexBNALUnit : function findNextAnnexBNALUnit(ptr) { 70 var i = 0, size = ptr.length; 71 72 /* look for start_code_prefix */ 73 while (ptr[i] == 0 && i < size) { 74 i += 1; 75 } 76 if (i >= size) { 77 error("cannot find any start_code_prefix"); 78 } else if (ptr[i] != 0x1) { 79 /* start_code_prefix is not at the beginning, continue */ 80 i = -1; 81 } 82 i++; 83 var j = i, start = i, end = start, foundStartCode = 0; 84 while (!foundStartCode) { 85 /* see 2 consecutive zero bytes */ 86 while ((j + 1 < size) && (ptr[j] != 0 || ptr[j + 1] != 0)) { 87 j += 1; 88 } 89 end = j; /* stop and check for start code */ 90 /* keep reading for zero byte */ 91 while (j + 2 < size && ptr[j + 2] == 0) { 92 j += 1; 93 } 94 if (j + 2 >= size) { 95 size -= start; 96 return { 97 start : start, 98 nal : ptr.subarray(start, start + size), 99 next : null 100 }; 101 } 102 if (ptr[j + 2] == 0x1) { 103 foundStartCode = 1; 104 } else { 105 /* could be emulation code 0x3 */ 106 j += 2; /* continue the search */ 107 } 108 } 109 size = end - start; 110 return { 111 start : start, 112 nal : ptr.subarray(start, start + size), 113 next : ptr.subarray(end) 114 }; 115 } 116 }; 117 118 return constructor; 119})(); 120 121/** 122 * Indicates the type of the NAL Unit. The decoder needs to know how slices are coded. Some information can change from 123 * slice to slice and can be encoded in each slice. Other information such as coding parameters, picture format, size, 124 * type of entropy coder, bit rate, etc. does not change as often and does not need to be retransmitted as often. 125 * 126 * Combinations of coding parameters are stored on both the encoder and decoder side in various tables. 127 * 128 * There are two parameter sets: Picture Parameter Set (PPS) contains information about the slices of one or more 129 * pictures. Sequence Parameter Set (SPS) contains information about the sequence. 130 * 131 * Instantaneous Decoding Refresh (IDR) picture contains only slices with I and SI slice types. IDR pictures invalidate 132 * all reference pictures in the buffer prior to itself and can thus confine drifting errors. IDR pictures are always 133 * the first in a sequence of pictures. 134 * 135 * Baseline Profile and Main Profile does not include NAL Unit Types: 2, 3, 4. 136 */ 137NALU_TYPE = { 138 SLICE : 1, 139 DPA : 2, 140 DPB : 3, 141 DPC : 4, 142 IDR : 5, 143 SEI : 6, 144 145 /** 146 * Sequence Parameter Set 147 */ 148 SPS : 7, 149 150 /** 151 * Picture Parameter Set 152 */ 153 PPS : 8, 154 155 /** 156 * Access Unit Delimiter 157 */ 158 AUD : 9, 159 EOSEQ : 10, 160 EOSTREAM : 11, 161 FILL : 12, 162 PREFIX : 14, 163 SUB_SPS : 15, 164 SLC_EXT : 20, 165 VDRD : 24 166}; 167 168/** 169 * Indicates the importance of the NAL Unit for the reconstruction process. The higher the value the more important the 170 * NAL Unit. For instance, a value of 0 indicates that the NAL Unit is not used as a reference by any other units can be 171 * safely DISCARDED. 172 */ 173NALU_REF_IDC = { 174 NALU_PRIORITY_HIGHEST : 3, 175 NALU_PRIORITY_HIGH : 2, 176 NALU_PRIORITY_LOW : 1, 177 NALU_PRIORITY_DISPOSABLE : 0 178}; 179 180SLICE_TYPE = { 181 /** 182 * Intra prediction (I) and/or prediction from one reference per macroblock partition (P). 183 */ 184 P_SLICE : 0, 185 186 /** 187 * Intra prediction (I), prediction from one reference frame (P) or biprediction from two references (B). 188 */ 189 B_SLICE : 1, 190 191 /** Intra prediction only. */ 192 I_SLICE : 2, 193 SP_SLICE : 3, 194 SI_SLICE : 4, 195 P_ALL_SLICE : 5, 196 B_ALL_SLICE : 6, 197 I_ALL_SLICE : 7, 198 SP_ALL_SLICE : 8, 199 SI_ALL_SLICE : 9 200}; 201 202/** 203 * Represents a NAL (Network Abstraction Layer) Unit 204 * 205 * NAL Unit Header Format: 206 * 207 * forbidden_zero_bit (F): Usually set to 0 at source, set to 1 to indicate 208 * errors in the NAL Unit. 209 * 210 * nal_ref_idc (NRI): Indicates the importance of the NAL Unit, from 0 (low) to 211 * 3 (high). 212 * 213 * nal_unit_type (TYPE): Indicates the type of the NAL Unit. Although this field 214 * encodes 32 possible values, only 12 are used by H.264. 215 * 216 * Payload: A buffer that contains an encapsulated byte sequence payload (EBSP) 217 * which needs to be decoded to a raw byte sequence payload (RBSP) before 218 * further processing. 219 * 220 * <1> <-2-> <-----5-----> <--------- ? ---------> 221 * +---+-----+-------------+-----------------------+ | F | NRI | TYPE | Payload | 222 * +---+-----+-------------+-----------------------+ 223 */ 224var NALUnit = (function () { 225 function constructor(ptr) { 226 var forbidden_zero_bit; 227 if (ptr.length == 0) { 228 unexpected(); 229 } else { 230 forbidden_zero_bit = ptr[0] >> 7; 231 if (forbidden_zero_bit != 0) { 232 unexpected(); 233 } 234 this.nal_ref_idc = (ptr[0] & 0x60) >> 5; 235 this.nal_type = ptr[0] & 0x1F; 236 this.rbsp = ptr.subarray(1, 1 + convertEBSPToRBSP(ptr.subarray(1))); 237 return; 238 } 239 } 240 241 /** 242 * Converts an encapsulated byte sequence payload (EBSP) to a raw byte sequence payload (RBSP). 243 */ 244 function convertEBSPToRBSP(ptr) { 245 var j = 0; 246 var count = 0; 247 var size = ptr.length; 248 for (var i = 0; i < size; i++) { 249 var x = ptr[i]; 250 if (count == 2 && x == 0x03) { 251 i += 1; 252 count = 0; 253 } 254 ptr[j++] = x; 255 if (x == 0x00) { 256 count += 1; 257 } else { 258 count = 0; 259 } 260 } 261 return j; 262 } 263 264 constructor.prototype = { 265 toString : function toString() { 266 return getProperties(this); 267 }, 268 createUnit : function() { 269 switch (this.nal_type) { 270 case NALU_TYPE.SPS: 271 return new SPS(); 272 case NALU_TYPE.PPS: 273 return new PPS(); 274 case NALU_TYPE.SLICE: 275 case NALU_TYPE.IDR: 276 return new Slice(this.nal_type); 277 default: 278 return null; 279 // unexpected(); 280 } 281 } 282 }; 283 284 return constructor; 285})(); 286 287 288 289 290var Slice = (function() { 291 function constructor(nal_unit_type) { 292 this.nal_unit_type = nal_unit_type; 293 this.header = new SliceHeader(); 294 this.data = new SliceData(this.header); 295 } 296 297 constructor.prototype.decode = function (stream) { 298 var header = this.header; 299 var video = decoder.video; 300 301 header.decode(this.nal_unit_type, stream); 302 303 if (this.nal_unit_type == NALU_TYPE.IDR) { 304 // video.prevFrameNumber = 0; 305 } 306 307 // this.data.decode(stream); 308 }; 309 310 constructor.prototype.toString = function () { 311 return "Slice: " + getProperties(this, true); 312 }; 313 314 return constructor; 315})(); 316 317/** 318 * Represents a Slice's Data 319 */ 320var SliceData = (function() { 321 function constructor(header) { 322 this.header = header; 323 } 324 325 constructor.prototype.decode = function (stream) { 326 327 }; 328 329 constructor.prototype.toString = function () { 330 return "Slice Data: " + getProperties(this, true); 331 }; 332 333 return constructor; 334})(); 335 336 337/** 338 * Represents a Slice Header 339 * 340 * Clause 7.4.3 341 */ 342var SliceHeader = (function() { 343 function constructor() { } 344 345 constructor.prototype.decode = function (nal_unit_type, stream) { 346 var video = decoder.Video; 347 348 traceln("| + Slice Header"); 349 this.first_mb_in_slice = stream.uev(); 350 traceln("| | first_mb_in_slice: " + this.first_mb_in_slice); 351 this.slice_type = stream.uev(); 352 traceln("| | slice_type: " + this.slice_type); 353 if (this.first_mb_in_slice != 0) { 354 notImplemented(); 355 } 356 this.pic_parameter_set_id = stream.uev(); 357 traceln("| | pic_parameter_set_id: " + this.pic_parameter_set_id); 358 assertRange(this.pic_parameter_set_id, 0, 255); 359 360 var currentPPS = video.CurrentPPS = decoder.PictureParameterSets[this.pic_parameter_set_id]; 361 if (currentPPS == null) { 362 unexpected("pic_parameter_set_id: " + this.pic_parameter_set_id); 363 } 364 365 var currentSPS = video.CurrentSPS = decoder.SequenceParameterSets[currentPPS.seq_parameter_set_id]; 366 if (currentSPS == null) { 367 unexpected(); 368 } 369 370 if (video.CurrentPPS !== currentPPS) { 371 video.CurrentPPS = currentPPS; 372 373// notImplemented("currentPPS.seq_parameter_set_id: " + currentPPS.seq_parameter_set_id + 374// " != decoder.Video.seq_parameter_set_id: " + decoder.Video.seq_parameter_set_id); 375 } 376 377 /* derived variables from SPS */ 378 video.MaxFrameNum = 1 << (currentSPS.log2_max_frame_num_minus4 + 4); 379 // MC_OPTIMIZE 380 video.PicWidthInMbs = currentSPS.pic_width_in_mbs_minus1 + 1; 381 video.PicWidthInSamplesL = video.PicWidthInMbs * 16; 382 video.PicWidthInSamplesC = video.PicWidthInMbs * 8; 383 video.PicHeightInMapUnits = currentSPS.pic_height_in_map_units_minus1 + 1; 384 video.PicSizeInMapUnits = video.PicWidthInMbs * video.PicHeightInMapUnits; 385 video.FrameHeightInMbs = (2 - currentSPS.frame_mbs_only_flag) * video.PicHeightInMapUnits; 386 387 /* derived from PPS */ 388 video.SliceGroupChangeRate = currentPPS.slice_group_change_rate_minus1 + 1; 389 390 this.frame_num = stream.readBits(currentSPS.log2_max_frame_num_minus4 + 4); 391 traceln("| | frame_num: " + this.frame_num); 392 393 /* Book 5.3.4, if the frame_mbs_only_flag is set to zero, special coding of fields or interlaced video 394 * is enabled. */ 395 if (!currentSPS.frame_mbs_only_flag) { 396 /* Clause 7.4.3, a field_pic_flag set to zero indicates the slice is a coded frame, otherwise it's 397 * a coded field. We don't support interlaced video. */ 398 this.field_pic_flag = stream.readBit(); 399 traceln("| | field_pic_flag: " + this.field_pic_flag); 400 assertFalse (this.field_pic_flag); 401 } 402 403 /* derived variables from slice header */ 404 video.PicHeightInMbs = video.FrameHeightInMbs; 405 video.PicHeightInSamplesL = video.PicHeightInMbs * 16; 406 video.PicHeightInSamplesC = video.PicHeightInMbs * 8; 407 video.PicSizeInMbs = video.PicWidthInMbs * video.PicHeightInMbs; 408 409 if (this.first_mb_in_slice >= video.PicSizeInMbs) { 410 unexpected(); 411 } 412 video.MaxPicNum = video.MaxFrameNum; 413 video.CurrPicNum = this.frame_num; 414 415 if (nal_unit_type == NALU_TYPE.IDR) { 416 if (this.frame_num != 0) { 417 unexpected(); 418 } 419 this.idr_pic_id = stream.uev(); 420 traceln("| | idr_pic_id: " + this.idr_pic_id); 421 } 422 423 this.delta_pic_order_cnt_bottom = 0; /* default value */ 424 this.delta_pic_order_cnt = [0, 0]; 425 426 if (currentSPS.pic_order_cnt_type == 0) { 427 this.pic_order_cnt_lsb = stream.readBits(currentSPS.log2_max_pic_order_cnt_lsb_minus4 + 4); 428 traceln("| | pic_order_cnt_lsb: " + this.pic_order_cnt_lsb); 429 video.MaxPicOrderCntLsb = 1 << (currentSPS.log2_max_pic_order_cnt_lsb_minus4 + 4); 430 if (this.pic_order_cnt_lsb > video.MaxPicOrderCntLsb - 1) { 431 unexpected(); 432 } 433 434 if (currentPPS.pic_order_present_flag) { 435 notImplemented(); 436 this.delta_pic_order_cnt_bottom = stream.sev32(); 437 traceln("| | delta_pic_order_cnt_bottom: " + this.delta_pic_order_cnt_bottom); 438 } 439 } 440 441 if (currentSPS.pic_order_cnt_type == 1 && !currentSPS.delta_pic_order_always_zero_flag) { 442 this.delta_pic_order_cnt[0] = stream.sev32(); 443 traceln("| | delta_pic_order_cnt[0]: " + this.delta_pic_order_cnt[0]); 444 if (currentPPS.pic_order_present_flag) { 445 this.delta_pic_order_cnt[1] = stream.sev32(); 446 traceln("| | delta_pic_order_cnt[1]: " + this.delta_pic_order_cnt[1]); 447 } 448 } 449 450 this.redundant_pic_cnt = 0; /* default value */ 451 if (currentPPS.redundant_pic_cnt_present_flag) { 452 // MC_CHECK 453 this.redundant_pic_cnt = stream.uev(); 454 if (this.redundant_pic_cnt > 127) /* out of range */ 455 unexpected(); 456 457 if (this.redundant_pic_cnt > 0) /* redundant picture */ 458 unexpected(); /* not supported */ 459 } 460 461 this.num_ref_idx_l0_active_minus1 = currentPPS.num_ref_idx_l0_active_minus1; 462 this.num_ref_idx_l1_active_minus1 = currentPPS.num_ref_idx_l1_active_minus1; 463 464 if (this.slice_type == SLICE_TYPE.P_SLICE) { 465 this.num_ref_idx_active_override_flag = stream.readBit(); 466 traceln("| | num_ref_idx_active_override_flag: " + this.num_ref_idx_active_override_flag); 467 if (this.num_ref_idx_active_override_flag) { 468 this.num_ref_idx_l0_active_minus1 = stream.uev(); 469 traceln("| | num_ref_idx_l0_active_minus1: " + this.num_ref_idx_l0_active_minus1); 470 } else { 471 /* the following condition is not allowed if the flag is zero */ 472 if ((slice_type == SLICE_TYPE.P_SLICE) && currentPPS.num_ref_idx_l0_active_minus1 > 15) { 473 unexpected(); /* not allowed */ 474 } 475 } 476 } 477 478 if (this.num_ref_idx_l0_active_minus1 > 15 || this.num_ref_idx_l1_active_minus1 > 15) { 479 unexpected(); /* not allowed */ 480 } 481 482 /* if MbaffFrameFlag =1, 483 max value of index is num_ref_idx_l0_active_minus1 for frame MBs and 484 2*this.num_ref_idx_l0_active_minus1 + 1 for field MBs */ 485 486 this.ref_pic_list_reordering(video, stream); 487 488 if (video.nal_ref_idc) { 489 this.dec_ref_pic_marking(video, stream, this); 490 } 491 492 this.slice_qp_delta = stream.sev(); 493 traceln("| | slice_qp_delta: " + this.slice_qp_delta); 494 495 video.QPy = 26 + currentPPS.pic_init_qp_minus26 + this.slice_qp_delta; 496 if (video.QPy > 51 || video.QPy < 0) { 497 video.QPy = clip(0, 51, video.QPy); 498 } 499 video.QPc = mapQPi2QPc[clip(0, 51, video.QPy + video.CurrentPPS.chroma_qp_index_offset)]; 500 501 video.QPy_div_6 = (video.QPy * 43) >>> 8; 502 video.QPy_mod_6 = video.QPy - 6 * video.QPy_div_6; 503 504 video.QPc_div_6 = (video.QPc * 43) >>> 8; 505 video.QPc_mod_6 = video.QPc - 6 * video.QPc_div_6; 506 507 this.slice_alpha_c0_offset_div2 = 0; 508 this.slice_beta_offset_div_2 = 0; 509 this.disable_deblocking_filter_idc = 0; 510 video.FilterOffsetA = video.FilterOffsetB = 0; 511 512 if (currentPPS.deblocking_filter_control_present_flag) { 513 this.disable_deblocking_filter_idc = stream.uev(); 514 traceln("| | disable_deblocking_filter_idc: " + this.disable_deblocking_filter_idc); 515 if (this.disable_deblocking_filter_idc > 2) { 516 unexpected(); /* out of range */ 517 } 518 if (this.disable_deblocking_filter_idc != 1) { 519 this.slice_alpha_c0_offset_div2 = stream.sev(); 520 traceln("| | slice_alpha_c0_offset_div2: " + this.slice_alpha_c0_offset_div2); 521 if (this.slice_alpha_c0_offset_div2 < -6 || this.slice_alpha_c0_offset_div2 > 6) { 522 unexpected(); 523 } 524 video.FilterOffsetA = this.slice_alpha_c0_offset_div2 << 1; 525 this.slice_beta_offset_div_2 = stream.sev(); 526 traceln("| | slice_beta_offset_div_2: " + this.slice_beta_offset_div_2); 527 if (this.slice_beta_offset_div_2 < -6 || this.slice_beta_offset_div_2 > 6) { 528 unexpected(); 529 } 530 video.FilterOffsetB = this.slice_beta_offset_div_2 << 1; 531 } 532 } 533 534 if (currentPPS.num_slice_groups_minus1 > 0 && 535 currentPPS.slice_group_map_type >= 3 && 536 currentPPS.slice_group_map_type <= 5) { 537 /* Ceil(Log2(PicSizeInMapUnits/(float)SliceGroupChangeRate + 1)) */ 538 temp = video.PicSizeInMapUnits / video.SliceGroupChangeRate; 539 if (video.PicSizeInMapUnits % video.SliceGroupChangeRate) { 540 temp++; 541 } 542 i = 0; 543 temp++; 544 while (temp) 545 { 546 temp >>= 1; 547 i++; 548 } 549 this.slice_group_change_cycle = stream.readBits(i); 550 traceln("| | slice_group_change_cycle: " + this.slice_group_change_cycle); 551 video.MapUnitsInSliceGroup0 = min(this.slice_group_change_cycle * video.SliceGroupChangeRate, video.PicSizeInMapUnits); 552 } 553 }; 554 555 /** 556 * Book 5.3.3.2 557 * Clause 7.3.3.1 558 * 559 * The reference picture list order can be change for the current slice only using this command. The 560 * ref_pic_list_reordering_flag indicates that such an operation should occur. 561 */ 562 constructor.prototype.ref_pic_list_reordering = function(video, stream) { 563 if (this.slice_type != SLICE_TYPE.I_SLICE) { 564 this.ref_pic_list_reordering_flag_l0 = stream.readBit(); 565 traceln("| | ref_pic_list_reordering_flag_l0: " + this.ref_pic_list_reordering_flag_l0); 566 if (this.ref_pic_list_reordering_flag_l0) { 567 traceln("| | + Reference Picture List Reordering Commands"); 568 var i = 0; 569 this.reordering_of_pic_nums_idc_l0 = []; 570 this.abs_diff_pic_num_minus1_l0 = []; 571 do { 572 var res = this.reordering_of_pic_nums_idc_l0[i] = stream.uev(); 573 if (res == 0 || res == 1) { 574 this.abs_diff_pic_num_minus1_l0[i] = stream.uev(); 575 traceln("| | abs_diff_pic_num_minus1_l0[" + i + "]: " + this.abs_diff_pic_num_minus1_l0[i]); 576 assertFalse (res == 0 && this.abs_diff_pic_num_minus1_l0[i] > video.MaxPicNum / 2 - 1); 577 assertFalse (res == 1 && this.abs_diff_pic_num_minus1_l0[i] > video.MaxPicNum / 2 - 2); 578 } else if (res == 2) { 579 this.long_term_pic_num_l0[i] = stream.uev(); 580 traceln("| | long_term_pic_num_l0[" + i + "]: " + this.long_term_pic_num_l0[i]); 581 } 582 i++; 583 } while (this.reordering_of_pic_nums_idc_l0[i - 1] != 3 && i <= this.num_ref_idx_l0_active_minus1 + 1); 584 } 585 } 586 }; 587 588 /** 589 * Clause 7.4.3.3 590 */ 591 constructor.prototype.dec_ref_pic_marking = function(video, stream) { 592 traceln("| | + dec_ref_pic_marking"); 593 if (video.nal_unit_type == NALU_TYPE.IDR) { 594 this.no_output_of_prior_pics_flag = stream.readBit(); 595 traceln("| | | no_output_of_prior_pics_flag: " + this.no_output_of_prior_pics_flag); 596 this.long_term_reference_flag = stream.readBit(); 597 traceln("| | | long_term_reference_flag: " + this.long_term_reference_flag); 598 if (this.long_term_reference_flag == 0) { 599 video.MaxLongTermFrameIdx = -1; 600 } else { 601 video.MaxLongTermFrameIdx = 0; 602 video.LongTermFrameIdx = 0; 603 } 604 } else { 605 this.adaptive_ref_pic_marking_mode_flag = stream.readBit(); 606 traceln("| | | adaptive_ref_pic_marking_mode_flag: " + this.adaptive_ref_pic_marking_mode_flag); 607 if (this.adaptive_ref_pic_marking_mode_flag) { 608 this.memory_management_control_operation = []; 609 this.difference_of_pic_nums_minus1 = []; 610 this.long_term_pic_num = []; 611 this.max_long_term_frame_idx_plus1 = []; 612 var i = 0; 613 do { 614 var res = this.memory_management_control_operation[i] = stream.uev(); 615 traceln("| | | memory_management_control_operation[" + i + "]: " + this.memory_management_control_operation[i]); 616 if (res == 1 || res == 3) { 617 this.difference_of_pic_nums_minus1[i] = stream.uev(); 618 traceln("| | | difference_of_pic_nums_minus1[" + i + "]: " + this.difference_of_pic_nums_minus1[i]); 619 } 620 if (res == 2) { 621 this.long_term_pic_num[i] = stream.uev(); 622 traceln("| | | long_term_pic_num[" + i + "]: " + this.long_term_pic_num[i]); 623 } 624 if (res == 3 || res == 6) { 625 this.long_term_frame_idx[i] = stream.uev(); 626 traceln("| | | long_term_frame_idx[" + i + "]: " + this.long_term_frame_idx[i]); 627 } 628 if (res == 4) { 629 this.max_long_term_frame_idx_plus1[i] = stream.uev(); 630 traceln("| | | max_long_term_frame_idx_plus1[" + i + "]: " + this.max_long_term_frame_idx_plus1[i]); 631 } 632 i++; 633 } while (this.memory_management_control_operation[i - 1] != 0 && i < MAX_DEC_REF_PIC_MARKING); 634 assertFalse(i >= MAX_DEC_REF_PIC_MARKING); 635 } 636 } 637 }; 638 639 constructor.prototype.toString = function () { 640 return "Slice Header: " + getProperties(this, true); 641 }; 642 643 return constructor; 644})(); 645 646 647 648