Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 #include "webrtc/common_video/h264/h264_bitstream_parser.h" | 10 #include "webrtc/common_video/h264/h264_bitstream_parser.h" |
| 11 | 11 |
| 12 #include <memory> | 12 #include <memory> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "webrtc/base/bitbuffer.h" | 15 #include "webrtc/base/bitbuffer.h" |
| 16 #include "webrtc/base/bytebuffer.h" | 16 #include "webrtc/base/bytebuffer.h" |
| 17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 | 18 |
| 19 #include "webrtc/common_video/h264/h264_common.h" | 19 #include "webrtc/common_video/h264/h264_common.h" |
| 20 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
| 21 | 21 |
| 22 namespace webrtc { | 22 namespace webrtc { |
| 23 | 23 |
| 24 #define RETURN_FALSE_ON_FAIL(x) \ | 24 #define RETURN_ON_FAIL(x, res) \ |
| 25 if (!(x)) { \ | 25 if (!(x)) { \ |
| 26 LOG_F(LS_ERROR) << "FAILED: " #x; \ | 26 LOG_F(LS_ERROR) << "FAILED: " #x; \ |
| 27 return false; \ | 27 return res; \ |
| 28 } | 28 } |
| 29 | 29 |
| 30 #define RETURN_INV_ON_FAIL(x) RETURN_ON_FAIL(x, kInvalidStream) | |
|
pbos-webrtc
2016/11/03 16:25:25
I think you can s/INV/INVALID_STREAM/g
| |
| 31 | |
| 30 H264BitstreamParser::H264BitstreamParser() {} | 32 H264BitstreamParser::H264BitstreamParser() {} |
| 31 H264BitstreamParser::~H264BitstreamParser() {} | 33 H264BitstreamParser::~H264BitstreamParser() {} |
| 32 | 34 |
| 33 bool H264BitstreamParser::ParseNonParameterSetNalu(const uint8_t* source, | 35 H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( |
| 34 size_t source_length, | 36 const uint8_t* source, |
| 35 uint8_t nalu_type) { | 37 size_t source_length, |
| 36 RTC_CHECK(sps_); | 38 uint8_t nalu_type) { |
| 37 RTC_CHECK(pps_); | 39 if (!sps_ || !pps_) |
| 40 return kInvalidStream; | |
| 41 | |
| 38 last_slice_qp_delta_ = rtc::Optional<int32_t>(); | 42 last_slice_qp_delta_ = rtc::Optional<int32_t>(); |
| 39 std::unique_ptr<rtc::Buffer> slice_rbsp( | 43 std::unique_ptr<rtc::Buffer> slice_rbsp( |
| 40 H264::ParseRbsp(source, source_length)); | 44 H264::ParseRbsp(source, source_length)); |
| 45 if (slice_rbsp->size() < H264::kNaluTypeSize) | |
| 46 return kInvalidStream; | |
| 47 | |
| 41 rtc::BitBuffer slice_reader(slice_rbsp->data() + H264::kNaluTypeSize, | 48 rtc::BitBuffer slice_reader(slice_rbsp->data() + H264::kNaluTypeSize, |
| 42 slice_rbsp->size() - H264::kNaluTypeSize); | 49 slice_rbsp->size() - H264::kNaluTypeSize); |
| 43 // Check to see if this is an IDR slice, which has an extra field to parse | 50 // Check to see if this is an IDR slice, which has an extra field to parse |
| 44 // out. | 51 // out. |
| 45 bool is_idr = (source[0] & 0x0F) == H264::NaluType::kIdr; | 52 bool is_idr = (source[0] & 0x0F) == H264::NaluType::kIdr; |
| 46 uint8_t nal_ref_idc = (source[0] & 0x60) >> 5; | 53 uint8_t nal_ref_idc = (source[0] & 0x60) >> 5; |
| 47 uint32_t golomb_tmp; | 54 uint32_t golomb_tmp; |
| 48 uint32_t bits_tmp; | 55 uint32_t bits_tmp; |
| 49 | 56 |
| 50 // first_mb_in_slice: ue(v) | 57 // first_mb_in_slice: ue(v) |
| 51 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 58 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 52 // slice_type: ue(v) | 59 // slice_type: ue(v) |
| 53 uint32_t slice_type; | 60 uint32_t slice_type; |
| 54 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type)); | 61 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type)); |
| 55 // slice_type's 5..9 range is used to indicate that all slices of a picture | 62 // slice_type's 5..9 range is used to indicate that all slices of a picture |
| 56 // have the same value of slice_type % 5, we don't care about that, so we map | 63 // have the same value of slice_type % 5, we don't care about that, so we map |
| 57 // to the corresponding 0..4 range. | 64 // to the corresponding 0..4 range. |
| 58 slice_type %= 5; | 65 slice_type %= 5; |
| 59 // pic_parameter_set_id: ue(v) | 66 // pic_parameter_set_id: ue(v) |
| 60 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 67 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 61 if (sps_->separate_colour_plane_flag == 1) { | 68 if (sps_->separate_colour_plane_flag == 1) { |
| 62 // colour_plane_id | 69 // colour_plane_id |
| 63 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2)); | 70 RETURN_INV_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2)); |
| 64 } | 71 } |
| 65 // frame_num: u(v) | 72 // frame_num: u(v) |
| 66 // Represented by log2_max_frame_num_minus4 + 4 bits. | 73 // Represented by log2_max_frame_num_minus4 + 4 bits. |
| 67 RETURN_FALSE_ON_FAIL( | 74 RETURN_INV_ON_FAIL( |
| 68 slice_reader.ReadBits(&bits_tmp, sps_->log2_max_frame_num_minus4 + 4)); | 75 slice_reader.ReadBits(&bits_tmp, sps_->log2_max_frame_num_minus4 + 4)); |
| 69 uint32_t field_pic_flag = 0; | 76 uint32_t field_pic_flag = 0; |
| 70 if (sps_->frame_mbs_only_flag == 0) { | 77 if (sps_->frame_mbs_only_flag == 0) { |
| 71 // field_pic_flag: u(1) | 78 // field_pic_flag: u(1) |
| 72 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1)); | 79 RETURN_INV_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1)); |
| 73 if (field_pic_flag != 0) { | 80 if (field_pic_flag != 0) { |
| 74 // bottom_field_flag: u(1) | 81 // bottom_field_flag: u(1) |
| 75 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1)); | 82 RETURN_INV_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1)); |
| 76 } | 83 } |
| 77 } | 84 } |
| 78 if (is_idr) { | 85 if (is_idr) { |
| 79 // idr_pic_id: ue(v) | 86 // idr_pic_id: ue(v) |
| 80 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 87 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 81 } | 88 } |
| 82 // pic_order_cnt_lsb: u(v) | 89 // pic_order_cnt_lsb: u(v) |
| 83 // Represented by sps_.log2_max_pic_order_cnt_lsb_minus4 + 4 bits. | 90 // Represented by sps_.log2_max_pic_order_cnt_lsb_minus4 + 4 bits. |
| 84 if (sps_->pic_order_cnt_type == 0) { | 91 if (sps_->pic_order_cnt_type == 0) { |
| 85 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits( | 92 RETURN_INV_ON_FAIL(slice_reader.ReadBits( |
| 86 &bits_tmp, sps_->log2_max_pic_order_cnt_lsb_minus4 + 4)); | 93 &bits_tmp, sps_->log2_max_pic_order_cnt_lsb_minus4 + 4)); |
| 87 if (pps_->bottom_field_pic_order_in_frame_present_flag && | 94 if (pps_->bottom_field_pic_order_in_frame_present_flag && |
| 88 field_pic_flag == 0) { | 95 field_pic_flag == 0) { |
| 89 // delta_pic_order_cnt_bottom: se(v) | 96 // delta_pic_order_cnt_bottom: se(v) |
| 90 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 97 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 91 } | 98 } |
| 92 } | 99 } |
| 93 if (sps_->pic_order_cnt_type == 1 && | 100 if (sps_->pic_order_cnt_type == 1 && |
| 94 !sps_->delta_pic_order_always_zero_flag) { | 101 !sps_->delta_pic_order_always_zero_flag) { |
| 95 // delta_pic_order_cnt[0]: se(v) | 102 // delta_pic_order_cnt[0]: se(v) |
| 96 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 103 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 97 if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) { | 104 if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) { |
| 98 // delta_pic_order_cnt[1]: se(v) | 105 // delta_pic_order_cnt[1]: se(v) |
| 99 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 106 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 100 } | 107 } |
| 101 } | 108 } |
| 102 if (pps_->redundant_pic_cnt_present_flag) { | 109 if (pps_->redundant_pic_cnt_present_flag) { |
| 103 // redundant_pic_cnt: ue(v) | 110 // redundant_pic_cnt: ue(v) |
| 104 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 111 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 105 } | 112 } |
| 106 if (slice_type == H264::SliceType::kB) { | 113 if (slice_type == H264::SliceType::kB) { |
| 107 // direct_spatial_mv_pred_flag: u(1) | 114 // direct_spatial_mv_pred_flag: u(1) |
| 108 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1)); | 115 RETURN_INV_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1)); |
| 109 } | 116 } |
| 110 switch (slice_type) { | 117 switch (slice_type) { |
| 111 case H264::SliceType::kP: | 118 case H264::SliceType::kP: |
| 112 case H264::SliceType::kB: | 119 case H264::SliceType::kB: |
| 113 case H264::SliceType::kSp: | 120 case H264::SliceType::kSp: |
| 114 uint32_t num_ref_idx_active_override_flag; | 121 uint32_t num_ref_idx_active_override_flag; |
| 115 // num_ref_idx_active_override_flag: u(1) | 122 // num_ref_idx_active_override_flag: u(1) |
| 116 RETURN_FALSE_ON_FAIL( | 123 RETURN_INV_ON_FAIL( |
| 117 slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1)); | 124 slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1)); |
| 118 if (num_ref_idx_active_override_flag != 0) { | 125 if (num_ref_idx_active_override_flag != 0) { |
| 119 // num_ref_idx_l0_active_minus1: ue(v) | 126 // num_ref_idx_l0_active_minus1: ue(v) |
| 120 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 127 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 121 if (slice_type == H264::SliceType::kB) { | 128 if (slice_type == H264::SliceType::kB) { |
| 122 // num_ref_idx_l1_active_minus1: ue(v) | 129 // num_ref_idx_l1_active_minus1: ue(v) |
| 123 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); | 130 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 124 } | 131 } |
| 125 } | 132 } |
| 126 break; | 133 break; |
| 127 default: | 134 default: |
| 128 break; | 135 break; |
| 129 } | 136 } |
| 130 // assume nal_unit_type != 20 && nal_unit_type != 21: | 137 // assume nal_unit_type != 20 && nal_unit_type != 21: |
| 131 RTC_CHECK_NE(nalu_type, 20); | 138 if (nalu_type == 20 || nalu_type == 21) { |
| 132 RTC_CHECK_NE(nalu_type, 21); | 139 LOG(LS_ERROR) << "Unsupported nal unit type."; |
| 140 return kUnsupportedStream; | |
| 141 } | |
| 133 // if (nal_unit_type == 20 || nal_unit_type == 21) | 142 // if (nal_unit_type == 20 || nal_unit_type == 21) |
| 134 // ref_pic_list_mvc_modification() | 143 // ref_pic_list_mvc_modification() |
| 135 // else | 144 // else |
| 136 { | 145 { |
| 137 // ref_pic_list_modification(): | 146 // ref_pic_list_modification(): |
| 138 // |slice_type| checks here don't use named constants as they aren't named | 147 // |slice_type| checks here don't use named constants as they aren't named |
| 139 // in the spec for this segment. Keeping them consistent makes it easier to | 148 // in the spec for this segment. Keeping them consistent makes it easier to |
| 140 // verify that they are both the same. | 149 // verify that they are both the same. |
| 141 if (slice_type % 5 != 2 && slice_type % 5 != 4) { | 150 if (slice_type % 5 != 2 && slice_type % 5 != 4) { |
| 142 // ref_pic_list_modification_flag_l0: u(1) | 151 // ref_pic_list_modification_flag_l0: u(1) |
| 143 uint32_t ref_pic_list_modification_flag_l0; | 152 uint32_t ref_pic_list_modification_flag_l0; |
| 144 RETURN_FALSE_ON_FAIL( | 153 RETURN_INV_ON_FAIL( |
| 145 slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1)); | 154 slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1)); |
| 146 if (ref_pic_list_modification_flag_l0) { | 155 if (ref_pic_list_modification_flag_l0) { |
| 147 uint32_t modification_of_pic_nums_idc; | 156 uint32_t modification_of_pic_nums_idc; |
| 148 do { | 157 do { |
| 149 // modification_of_pic_nums_idc: ue(v) | 158 // modification_of_pic_nums_idc: ue(v) |
| 150 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb( | 159 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb( |
| 151 &modification_of_pic_nums_idc)); | 160 &modification_of_pic_nums_idc)); |
| 152 if (modification_of_pic_nums_idc == 0 || | 161 if (modification_of_pic_nums_idc == 0 || |
| 153 modification_of_pic_nums_idc == 1) { | 162 modification_of_pic_nums_idc == 1) { |
| 154 // abs_diff_pic_num_minus1: ue(v) | 163 // abs_diff_pic_num_minus1: ue(v) |
| 155 RETURN_FALSE_ON_FAIL( | 164 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 156 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 157 } else if (modification_of_pic_nums_idc == 2) { | 165 } else if (modification_of_pic_nums_idc == 2) { |
| 158 // long_term_pic_num: ue(v) | 166 // long_term_pic_num: ue(v) |
| 159 RETURN_FALSE_ON_FAIL( | 167 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 160 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 161 } | 168 } |
| 162 } while (modification_of_pic_nums_idc != 3); | 169 } while (modification_of_pic_nums_idc != 3); |
| 163 } | 170 } |
| 164 } | 171 } |
| 165 if (slice_type % 5 == 1) { | 172 if (slice_type % 5 == 1) { |
| 166 // ref_pic_list_modification_flag_l1: u(1) | 173 // ref_pic_list_modification_flag_l1: u(1) |
| 167 uint32_t ref_pic_list_modification_flag_l1; | 174 uint32_t ref_pic_list_modification_flag_l1; |
| 168 RETURN_FALSE_ON_FAIL( | 175 RETURN_INV_ON_FAIL( |
| 169 slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1)); | 176 slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1)); |
| 170 if (ref_pic_list_modification_flag_l1) { | 177 if (ref_pic_list_modification_flag_l1) { |
| 171 uint32_t modification_of_pic_nums_idc; | 178 uint32_t modification_of_pic_nums_idc; |
| 172 do { | 179 do { |
| 173 // modification_of_pic_nums_idc: ue(v) | 180 // modification_of_pic_nums_idc: ue(v) |
| 174 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb( | 181 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb( |
| 175 &modification_of_pic_nums_idc)); | 182 &modification_of_pic_nums_idc)); |
| 176 if (modification_of_pic_nums_idc == 0 || | 183 if (modification_of_pic_nums_idc == 0 || |
| 177 modification_of_pic_nums_idc == 1) { | 184 modification_of_pic_nums_idc == 1) { |
| 178 // abs_diff_pic_num_minus1: ue(v) | 185 // abs_diff_pic_num_minus1: ue(v) |
| 179 RETURN_FALSE_ON_FAIL( | 186 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 180 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 181 } else if (modification_of_pic_nums_idc == 2) { | 187 } else if (modification_of_pic_nums_idc == 2) { |
| 182 // long_term_pic_num: ue(v) | 188 // long_term_pic_num: ue(v) |
| 183 RETURN_FALSE_ON_FAIL( | 189 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 184 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 185 } | 190 } |
| 186 } while (modification_of_pic_nums_idc != 3); | 191 } while (modification_of_pic_nums_idc != 3); |
| 187 } | 192 } |
| 188 } | 193 } |
| 189 } | 194 } |
| 190 // TODO(pbos): Do we need support for pred_weight_table()? | 195 // TODO(pbos): Do we need support for pred_weight_table()? |
| 191 RTC_CHECK( | 196 if ((pps_->weighted_pred_flag && (slice_type == H264::SliceType::kP || |
| 192 !((pps_->weighted_pred_flag && (slice_type == H264::SliceType::kP || | 197 slice_type == H264::SliceType::kSp)) || |
| 193 slice_type == H264::SliceType::kSp)) || | 198 (pps_->weighted_bipred_idc == 1 && slice_type == H264::SliceType::kB)) { |
| 194 (pps_->weighted_bipred_idc != 0 && slice_type == H264::SliceType::kB))) | 199 LOG(LS_ERROR) << "Streams with pred_weight_table unsupported."; |
| 195 << "Missing support for pred_weight_table()."; | 200 return kUnsupportedStream; |
| 201 } | |
| 196 // if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) || | 202 // if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) || |
| 197 // (weighted_bipred_idc == 1 && slice_type == B)) { | 203 // (weighted_bipred_idc == 1 && slice_type == B)) { |
| 198 // pred_weight_table() | 204 // pred_weight_table() |
| 199 // } | 205 // } |
| 200 if (nal_ref_idc != 0) { | 206 if (nal_ref_idc != 0) { |
| 201 // dec_ref_pic_marking(): | 207 // dec_ref_pic_marking(): |
| 202 if (is_idr) { | 208 if (is_idr) { |
| 203 // no_output_of_prior_pics_flag: u(1) | 209 // no_output_of_prior_pics_flag: u(1) |
| 204 // long_term_reference_flag: u(1) | 210 // long_term_reference_flag: u(1) |
| 205 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2)); | 211 RETURN_INV_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2)); |
| 206 } else { | 212 } else { |
| 207 // adaptive_ref_pic_marking_mode_flag: u(1) | 213 // adaptive_ref_pic_marking_mode_flag: u(1) |
| 208 uint32_t adaptive_ref_pic_marking_mode_flag; | 214 uint32_t adaptive_ref_pic_marking_mode_flag; |
| 209 RETURN_FALSE_ON_FAIL( | 215 RETURN_INV_ON_FAIL( |
| 210 slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1)); | 216 slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1)); |
| 211 if (adaptive_ref_pic_marking_mode_flag) { | 217 if (adaptive_ref_pic_marking_mode_flag) { |
| 212 uint32_t memory_management_control_operation; | 218 uint32_t memory_management_control_operation; |
| 213 do { | 219 do { |
| 214 // memory_management_control_operation: ue(v) | 220 // memory_management_control_operation: ue(v) |
| 215 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb( | 221 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb( |
| 216 &memory_management_control_operation)); | 222 &memory_management_control_operation)); |
| 217 if (memory_management_control_operation == 1 || | 223 if (memory_management_control_operation == 1 || |
| 218 memory_management_control_operation == 3) { | 224 memory_management_control_operation == 3) { |
| 219 // difference_of_pic_nums_minus1: ue(v) | 225 // difference_of_pic_nums_minus1: ue(v) |
| 220 RETURN_FALSE_ON_FAIL( | 226 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 221 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 222 } | 227 } |
| 223 if (memory_management_control_operation == 2) { | 228 if (memory_management_control_operation == 2) { |
| 224 // long_term_pic_num: ue(v) | 229 // long_term_pic_num: ue(v) |
| 225 RETURN_FALSE_ON_FAIL( | 230 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 226 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 227 } | 231 } |
| 228 if (memory_management_control_operation == 3 || | 232 if (memory_management_control_operation == 3 || |
| 229 memory_management_control_operation == 6) { | 233 memory_management_control_operation == 6) { |
| 230 // long_term_frame_idx: ue(v) | 234 // long_term_frame_idx: ue(v) |
| 231 RETURN_FALSE_ON_FAIL( | 235 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 232 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 233 } | 236 } |
| 234 if (memory_management_control_operation == 4) { | 237 if (memory_management_control_operation == 4) { |
| 235 // max_long_term_frame_idx_plus1: ue(v) | 238 // max_long_term_frame_idx_plus1: ue(v) |
| 236 RETURN_FALSE_ON_FAIL( | 239 RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp)); |
| 237 slice_reader.ReadExponentialGolomb(&golomb_tmp)); | |
| 238 } | 240 } |
| 239 } while (memory_management_control_operation != 0); | 241 } while (memory_management_control_operation != 0); |
| 240 } | 242 } |
| 241 } | 243 } |
| 242 } | 244 } |
| 243 // cabac not supported: entropy_coding_mode_flag == 0 asserted above. | 245 // cabac not supported: entropy_coding_mode_flag == 0 asserted above. |
| 244 // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI) | 246 // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI) |
| 245 // cabac_init_idc | 247 // cabac_init_idc |
| 246 int32_t last_slice_qp_delta; | 248 int32_t last_slice_qp_delta; |
| 247 RETURN_FALSE_ON_FAIL( | 249 RETURN_INV_ON_FAIL( |
| 248 slice_reader.ReadSignedExponentialGolomb(&last_slice_qp_delta)); | 250 slice_reader.ReadSignedExponentialGolomb(&last_slice_qp_delta)); |
| 249 last_slice_qp_delta_ = rtc::Optional<int32_t>(last_slice_qp_delta); | 251 last_slice_qp_delta_ = rtc::Optional<int32_t>(last_slice_qp_delta); |
| 250 return true; | 252 return kOk; |
| 251 } | 253 } |
| 252 | 254 |
| 253 void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { | 255 void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { |
| 254 H264::NaluType nalu_type = H264::ParseNaluType(slice[0]); | 256 H264::NaluType nalu_type = H264::ParseNaluType(slice[0]); |
| 255 switch (nalu_type) { | 257 switch (nalu_type) { |
| 256 case H264::NaluType::kSps: { | 258 case H264::NaluType::kSps: { |
| 257 sps_ = SpsParser::ParseSps(slice + H264::kNaluTypeSize, | 259 sps_ = SpsParser::ParseSps(slice + H264::kNaluTypeSize, |
| 258 length - H264::kNaluTypeSize); | 260 length - H264::kNaluTypeSize); |
| 259 if (!sps_) | 261 if (!sps_) |
| 260 FATAL() << "Unable to parse SPS from H264 bitstream."; | 262 LOG(LS_WARNING) << "Unable to parse SPS from H264 bitstream."; |
| 261 break; | 263 break; |
| 262 } | 264 } |
| 263 case H264::NaluType::kPps: { | 265 case H264::NaluType::kPps: { |
| 264 pps_ = PpsParser::ParsePps(slice + H264::kNaluTypeSize, | 266 pps_ = PpsParser::ParsePps(slice + H264::kNaluTypeSize, |
| 265 length - H264::kNaluTypeSize); | 267 length - H264::kNaluTypeSize); |
| 266 if (!pps_) | 268 if (!pps_) |
| 267 FATAL() << "Unable to parse PPS from H264 bitstream."; | 269 LOG(LS_WARNING) << "Unable to parse PPS from H264 bitstream."; |
| 268 break; | 270 break; |
| 269 } | 271 } |
| 270 default: | 272 default: |
| 271 RTC_CHECK(ParseNonParameterSetNalu(slice, length, nalu_type)) | 273 Result res = ParseNonParameterSetNalu(slice, length, nalu_type); |
| 272 << "Failed to parse picture slice."; | 274 if (res != kOk) |
| 275 LOG(LS_INFO) << "Failed to parse bitstream. Error: " << res; | |
|
magjed_webrtc
2016/11/03 21:27:48
nit: I think we should do at least LS_WARNING here
| |
| 273 break; | 276 break; |
| 274 } | 277 } |
| 275 } | 278 } |
| 276 | 279 |
| 277 void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream, | 280 void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream, |
| 278 size_t length) { | 281 size_t length) { |
| 279 std::vector<H264::NaluIndex> nalu_indices = | 282 std::vector<H264::NaluIndex> nalu_indices = |
| 280 H264::FindNaluIndices(bitstream, length); | 283 H264::FindNaluIndices(bitstream, length); |
| 281 RTC_CHECK(!nalu_indices.empty()); | |
| 282 for (const H264::NaluIndex& index : nalu_indices) | 284 for (const H264::NaluIndex& index : nalu_indices) |
| 283 ParseSlice(&bitstream[index.payload_start_offset], index.payload_size); | 285 ParseSlice(&bitstream[index.payload_start_offset], index.payload_size); |
| 284 } | 286 } |
| 285 | 287 |
| 286 bool H264BitstreamParser::GetLastSliceQp(int* qp) const { | 288 bool H264BitstreamParser::GetLastSliceQp(int* qp) const { |
| 287 if (!last_slice_qp_delta_ || !pps_) | 289 if (!last_slice_qp_delta_ || !pps_) |
| 288 return false; | 290 return false; |
| 289 *qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_; | 291 *qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_; |
| 290 return true; | 292 return true; |
| 291 } | 293 } |
| 292 | 294 |
| 293 } // namespace webrtc | 295 } // namespace webrtc |
| OLD | NEW |