| 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 | 10 |
| 11 #include "webrtc/modules/rtp_rtcp/source/h264_sps_parser.h" | 11 #include "webrtc/modules/rtp_rtcp/source/h264_sps_parser.h" |
| 12 | 12 |
| 13 #include "webrtc/base/bytebuffer.h" | 13 #include "webrtc/base/bytebuffer.h" |
| 14 #include "webrtc/base/bitbuffer.h" | 14 #include "webrtc/base/bitbuffer.h" |
| 15 #include "webrtc/system_wrappers/interface/logging.h" | 15 #include "webrtc/system_wrappers/interface/logging.h" |
| 16 | 16 |
| 17 #define RETURN_FALSE_ON_FAIL(x) \ | 17 #define RETURN_FALSE_ON_FAIL(x) \ |
| 18 if (!(x)) { \ | 18 if (!(x)) { \ |
| 19 return false; \ | 19 return false; \ |
| 20 } | 20 } |
| 21 | 21 |
| 22 namespace webrtc { | 22 namespace webrtc { |
| 23 | 23 |
| 24 H264SpsParser::H264SpsParser(const uint8* sps, size_t byte_length) | 24 H264SpsParser::H264SpsParser(const uint8_t* sps, size_t byte_length) |
| 25 : sps_(sps), byte_length_(byte_length), width_(), height_() { | 25 : sps_(sps), byte_length_(byte_length), width_(), height_() { |
| 26 } | 26 } |
| 27 | 27 |
| 28 bool H264SpsParser::Parse() { | 28 bool H264SpsParser::Parse() { |
| 29 // General note: this is based off the 02/2014 version of the H.264 standard. | 29 // General note: this is based off the 02/2014 version of the H.264 standard. |
| 30 // You can find it on this page: | 30 // You can find it on this page: |
| 31 // http://www.itu.int/rec/T-REC-H.264 | 31 // http://www.itu.int/rec/T-REC-H.264 |
| 32 | 32 |
| 33 const char* sps_bytes = reinterpret_cast<const char*>(sps_); | 33 const char* sps_bytes = reinterpret_cast<const char*>(sps_); |
| 34 // First, parse out rbsp, which is basically the source buffer minus emulation | 34 // First, parse out rbsp, which is basically the source buffer minus emulation |
| (...skipping 20 matching lines...) Expand all Loading... |
| 55 // Now, we need to use a bit buffer to parse through the actual AVC SPS | 55 // Now, we need to use a bit buffer to parse through the actual AVC SPS |
| 56 // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the | 56 // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the |
| 57 // H.264 standard for a complete description. | 57 // H.264 standard for a complete description. |
| 58 // Since we only care about resolution, we ignore the majority of fields, but | 58 // Since we only care about resolution, we ignore the majority of fields, but |
| 59 // we still have to actively parse through a lot of the data, since many of | 59 // we still have to actively parse through a lot of the data, since many of |
| 60 // the fields have variable size. | 60 // the fields have variable size. |
| 61 // We're particularly interested in: | 61 // We're particularly interested in: |
| 62 // chroma_format_idc -> affects crop units | 62 // chroma_format_idc -> affects crop units |
| 63 // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16). | 63 // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16). |
| 64 // frame_crop_*_offset -> crop information | 64 // frame_crop_*_offset -> crop information |
| 65 rtc::BitBuffer parser(reinterpret_cast<const uint8*>(rbsp_buffer.Data()), | 65 rtc::BitBuffer parser(reinterpret_cast<const uint8_t*>(rbsp_buffer.Data()), |
| 66 rbsp_buffer.Length()); | 66 rbsp_buffer.Length()); |
| 67 | 67 |
| 68 // The golomb values we have to read, not just consume. | 68 // The golomb values we have to read, not just consume. |
| 69 uint32 golomb_ignored; | 69 uint32_t golomb_ignored; |
| 70 | 70 |
| 71 // separate_colour_plane_flag is optional (assumed 0), but has implications | 71 // separate_colour_plane_flag is optional (assumed 0), but has implications |
| 72 // about the ChromaArrayType, which modifies how we treat crop coordinates. | 72 // about the ChromaArrayType, which modifies how we treat crop coordinates. |
| 73 uint32 separate_colour_plane_flag = 0; | 73 uint32_t separate_colour_plane_flag = 0; |
| 74 // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is | 74 // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is |
| 75 // 0. It defaults to 1, when not specified. | 75 // 0. It defaults to 1, when not specified. |
| 76 uint32 chroma_format_idc = 1; | 76 uint32_t chroma_format_idc = 1; |
| 77 | 77 |
| 78 // profile_idc: u(8). We need it to determine if we need to read/skip chroma | 78 // profile_idc: u(8). We need it to determine if we need to read/skip chroma |
| 79 // formats. | 79 // formats. |
| 80 uint8 profile_idc; | 80 uint8_t profile_idc; |
| 81 RETURN_FALSE_ON_FAIL(parser.ReadUInt8(&profile_idc)); | 81 RETURN_FALSE_ON_FAIL(parser.ReadUInt8(&profile_idc)); |
| 82 // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits | 82 // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits |
| 83 // 1 bit each for the flags + 2 bits = 8 bits = 1 byte. | 83 // 1 bit each for the flags + 2 bits = 8 bits = 1 byte. |
| 84 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); | 84 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| 85 // level_idc: u(8) | 85 // level_idc: u(8) |
| 86 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); | 86 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); |
| 87 // seq_parameter_set_id: ue(v) | 87 // seq_parameter_set_id: ue(v) |
| 88 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 88 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 89 // See if profile_idc has chroma format information. | 89 // See if profile_idc has chroma format information. |
| 90 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || | 90 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || |
| 91 profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || | 91 profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || |
| 92 profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || | 92 profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || |
| 93 profile_idc == 138 || profile_idc == 139 || profile_idc == 134) { | 93 profile_idc == 138 || profile_idc == 139 || profile_idc == 134) { |
| 94 // chroma_format_idc: ue(v) | 94 // chroma_format_idc: ue(v) |
| 95 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&chroma_format_idc)); | 95 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&chroma_format_idc)); |
| 96 if (chroma_format_idc == 3) { | 96 if (chroma_format_idc == 3) { |
| 97 // separate_colour_plane_flag: u(1) | 97 // separate_colour_plane_flag: u(1) |
| 98 RETURN_FALSE_ON_FAIL(parser.ReadBits(&separate_colour_plane_flag, 1)); | 98 RETURN_FALSE_ON_FAIL(parser.ReadBits(&separate_colour_plane_flag, 1)); |
| 99 } | 99 } |
| 100 // bit_depth_luma_minus8: ue(v) | 100 // bit_depth_luma_minus8: ue(v) |
| 101 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 101 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 102 // bit_depth_chroma_minus8: ue(v) | 102 // bit_depth_chroma_minus8: ue(v) |
| 103 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 103 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 104 // qpprime_y_zero_transform_bypass_flag: u(1) | 104 // qpprime_y_zero_transform_bypass_flag: u(1) |
| 105 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); | 105 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| 106 // seq_scaling_matrix_present_flag: u(1) | 106 // seq_scaling_matrix_present_flag: u(1) |
| 107 uint32 seq_scaling_matrix_present_flag; | 107 uint32_t seq_scaling_matrix_present_flag; |
| 108 RETURN_FALSE_ON_FAIL(parser.ReadBits(&seq_scaling_matrix_present_flag, 1)); | 108 RETURN_FALSE_ON_FAIL(parser.ReadBits(&seq_scaling_matrix_present_flag, 1)); |
| 109 if (seq_scaling_matrix_present_flag) { | 109 if (seq_scaling_matrix_present_flag) { |
| 110 // seq_scaling_list_present_flags. Either 8 or 12, depending on | 110 // seq_scaling_list_present_flags. Either 8 or 12, depending on |
| 111 // chroma_format_idc. | 111 // chroma_format_idc. |
| 112 uint32 seq_scaling_list_present_flags; | 112 uint32_t seq_scaling_list_present_flags; |
| 113 if (chroma_format_idc != 3) { | 113 if (chroma_format_idc != 3) { |
| 114 RETURN_FALSE_ON_FAIL( | 114 RETURN_FALSE_ON_FAIL( |
| 115 parser.ReadBits(&seq_scaling_list_present_flags, 8)); | 115 parser.ReadBits(&seq_scaling_list_present_flags, 8)); |
| 116 } else { | 116 } else { |
| 117 RETURN_FALSE_ON_FAIL( | 117 RETURN_FALSE_ON_FAIL( |
| 118 parser.ReadBits(&seq_scaling_list_present_flags, 12)); | 118 parser.ReadBits(&seq_scaling_list_present_flags, 12)); |
| 119 } | 119 } |
| 120 // We don't support reading the sequence scaling list, and we don't really | 120 // We don't support reading the sequence scaling list, and we don't really |
| 121 // see/use them in practice, so we'll just reject the full sps if we see | 121 // see/use them in practice, so we'll just reject the full sps if we see |
| 122 // any provided. | 122 // any provided. |
| 123 if (seq_scaling_list_present_flags > 0) { | 123 if (seq_scaling_list_present_flags > 0) { |
| 124 LOG(LS_WARNING) << "SPS contains scaling lists, which are unsupported."; | 124 LOG(LS_WARNING) << "SPS contains scaling lists, which are unsupported."; |
| 125 return false; | 125 return false; |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 // log2_max_frame_num_minus4: ue(v) | 129 // log2_max_frame_num_minus4: ue(v) |
| 130 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 130 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 131 // pic_order_cnt_type: ue(v) | 131 // pic_order_cnt_type: ue(v) |
| 132 uint32 pic_order_cnt_type; | 132 uint32_t pic_order_cnt_type; |
| 133 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_order_cnt_type)); | 133 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_order_cnt_type)); |
| 134 if (pic_order_cnt_type == 0) { | 134 if (pic_order_cnt_type == 0) { |
| 135 // log2_max_pic_order_cnt_lsb_minus4: ue(v) | 135 // log2_max_pic_order_cnt_lsb_minus4: ue(v) |
| 136 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 136 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 137 } else if (pic_order_cnt_type == 1) { | 137 } else if (pic_order_cnt_type == 1) { |
| 138 // delta_pic_order_always_zero_flag: u(1) | 138 // delta_pic_order_always_zero_flag: u(1) |
| 139 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); | 139 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| 140 // offset_for_non_ref_pic: se(v) | 140 // offset_for_non_ref_pic: se(v) |
| 141 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 141 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 142 // offset_for_top_to_bottom_field: se(v) | 142 // offset_for_top_to_bottom_field: se(v) |
| 143 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 143 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 144 // num_ref_frames_in_pic_order_cnt_cycle: ue(v) | 144 // num_ref_frames_in_pic_order_cnt_cycle: ue(v) |
| 145 uint32 num_ref_frames_in_pic_order_cnt_cycle; | 145 uint32_t num_ref_frames_in_pic_order_cnt_cycle; |
| 146 RETURN_FALSE_ON_FAIL( | 146 RETURN_FALSE_ON_FAIL( |
| 147 parser.ReadExponentialGolomb(&num_ref_frames_in_pic_order_cnt_cycle)); | 147 parser.ReadExponentialGolomb(&num_ref_frames_in_pic_order_cnt_cycle)); |
| 148 for (size_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { | 148 for (size_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { |
| 149 // offset_for_ref_frame[i]: se(v) | 149 // offset_for_ref_frame[i]: se(v) |
| 150 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 150 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 // max_num_ref_frames: ue(v) | 153 // max_num_ref_frames: ue(v) |
| 154 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); | 154 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); |
| 155 // gaps_in_frame_num_value_allowed_flag: u(1) | 155 // gaps_in_frame_num_value_allowed_flag: u(1) |
| 156 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); | 156 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| 157 // | 157 // |
| 158 // IMPORTANT ONES! Now we're getting to resolution. First we read the pic | 158 // IMPORTANT ONES! Now we're getting to resolution. First we read the pic |
| 159 // width/height in macroblocks (16x16), which gives us the base resolution, | 159 // width/height in macroblocks (16x16), which gives us the base resolution, |
| 160 // and then we continue on until we hit the frame crop offsets, which are used | 160 // and then we continue on until we hit the frame crop offsets, which are used |
| 161 // to signify resolutions that aren't multiples of 16. | 161 // to signify resolutions that aren't multiples of 16. |
| 162 // | 162 // |
| 163 // pic_width_in_mbs_minus1: ue(v) | 163 // pic_width_in_mbs_minus1: ue(v) |
| 164 uint32 pic_width_in_mbs_minus1; | 164 uint32_t pic_width_in_mbs_minus1; |
| 165 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_width_in_mbs_minus1)); | 165 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_width_in_mbs_minus1)); |
| 166 // pic_height_in_map_units_minus1: ue(v) | 166 // pic_height_in_map_units_minus1: ue(v) |
| 167 uint32 pic_height_in_map_units_minus1; | 167 uint32_t pic_height_in_map_units_minus1; |
| 168 RETURN_FALSE_ON_FAIL( | 168 RETURN_FALSE_ON_FAIL( |
| 169 parser.ReadExponentialGolomb(&pic_height_in_map_units_minus1)); | 169 parser.ReadExponentialGolomb(&pic_height_in_map_units_minus1)); |
| 170 // frame_mbs_only_flag: u(1) | 170 // frame_mbs_only_flag: u(1) |
| 171 uint32 frame_mbs_only_flag; | 171 uint32_t frame_mbs_only_flag; |
| 172 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_mbs_only_flag, 1)); | 172 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_mbs_only_flag, 1)); |
| 173 if (!frame_mbs_only_flag) { | 173 if (!frame_mbs_only_flag) { |
| 174 // mb_adaptive_frame_field_flag: u(1) | 174 // mb_adaptive_frame_field_flag: u(1) |
| 175 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); | 175 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| 176 } | 176 } |
| 177 // direct_8x8_inference_flag: u(1) | 177 // direct_8x8_inference_flag: u(1) |
| 178 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); | 178 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); |
| 179 // | 179 // |
| 180 // MORE IMPORTANT ONES! Now we're at the frame crop information. | 180 // MORE IMPORTANT ONES! Now we're at the frame crop information. |
| 181 // | 181 // |
| 182 // frame_cropping_flag: u(1) | 182 // frame_cropping_flag: u(1) |
| 183 uint32 frame_cropping_flag; | 183 uint32_t frame_cropping_flag; |
| 184 uint32 frame_crop_left_offset = 0; | 184 uint32_t frame_crop_left_offset = 0; |
| 185 uint32 frame_crop_right_offset = 0; | 185 uint32_t frame_crop_right_offset = 0; |
| 186 uint32 frame_crop_top_offset = 0; | 186 uint32_t frame_crop_top_offset = 0; |
| 187 uint32 frame_crop_bottom_offset = 0; | 187 uint32_t frame_crop_bottom_offset = 0; |
| 188 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_cropping_flag, 1)); | 188 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_cropping_flag, 1)); |
| 189 if (frame_cropping_flag) { | 189 if (frame_cropping_flag) { |
| 190 // frame_crop_{left, right, top, bottom}_offset: ue(v) | 190 // frame_crop_{left, right, top, bottom}_offset: ue(v) |
| 191 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_left_offset)); | 191 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_left_offset)); |
| 192 RETURN_FALSE_ON_FAIL( | 192 RETURN_FALSE_ON_FAIL( |
| 193 parser.ReadExponentialGolomb(&frame_crop_right_offset)); | 193 parser.ReadExponentialGolomb(&frame_crop_right_offset)); |
| 194 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_top_offset)); | 194 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_top_offset)); |
| 195 RETURN_FALSE_ON_FAIL( | 195 RETURN_FALSE_ON_FAIL( |
| 196 parser.ReadExponentialGolomb(&frame_crop_bottom_offset)); | 196 parser.ReadExponentialGolomb(&frame_crop_bottom_offset)); |
| 197 } | 197 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 223 // Subtract the crop for each dimension. | 223 // Subtract the crop for each dimension. |
| 224 width -= (frame_crop_left_offset + frame_crop_right_offset); | 224 width -= (frame_crop_left_offset + frame_crop_right_offset); |
| 225 height -= (frame_crop_top_offset + frame_crop_bottom_offset); | 225 height -= (frame_crop_top_offset + frame_crop_bottom_offset); |
| 226 | 226 |
| 227 width_ = width; | 227 width_ = width; |
| 228 height_ = height; | 228 height_ = height; |
| 229 return true; | 229 return true; |
| 230 } | 230 } |
| 231 | 231 |
| 232 } // namespace webrtc | 232 } // namespace webrtc |
| OLD | NEW |