LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/common_video/h264 - sps_parser.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 76 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
       3             :  *
       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
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/common_video/h264/sps_parser.h"
      12             : 
      13             : #include <memory>
      14             : 
      15             : #include "webrtc/common_video/h264/h264_common.h"
      16             : #include "webrtc/base/bitbuffer.h"
      17             : #include "webrtc/base/bytebuffer.h"
      18             : #include "webrtc/base/logging.h"
      19             : 
      20             : typedef rtc::Optional<webrtc::SpsParser::SpsState> OptionalSps;
      21             : 
      22             : #define RETURN_EMPTY_ON_FAIL(x) \
      23             :   if (!(x)) {                   \
      24             :     return OptionalSps();       \
      25             :   }
      26             : 
      27             : namespace webrtc {
      28             : 
      29             : // General note: this is based off the 02/2014 version of the H.264 standard.
      30             : // You can find it on this page:
      31             : // http://www.itu.int/rec/T-REC-H.264
      32             : 
      33             : // Unpack RBSP and parse SPS state from the supplied buffer.
      34           0 : rtc::Optional<SpsParser::SpsState> SpsParser::ParseSps(const uint8_t* data,
      35             :                                                        size_t length) {
      36           0 :   std::unique_ptr<rtc::Buffer> unpacked_buffer = H264::ParseRbsp(data, length);
      37           0 :   rtc::BitBuffer bit_buffer(unpacked_buffer->data(), unpacked_buffer->size());
      38           0 :   return ParseSpsUpToVui(&bit_buffer);
      39             : }
      40             : 
      41           0 : rtc::Optional<SpsParser::SpsState> SpsParser::ParseSpsUpToVui(
      42             :     rtc::BitBuffer* buffer) {
      43             :   // Now, we need to use a bit buffer to parse through the actual AVC SPS
      44             :   // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the
      45             :   // H.264 standard for a complete description.
      46             :   // Since we only care about resolution, we ignore the majority of fields, but
      47             :   // we still have to actively parse through a lot of the data, since many of
      48             :   // the fields have variable size.
      49             :   // We're particularly interested in:
      50             :   // chroma_format_idc -> affects crop units
      51             :   // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16).
      52             :   // frame_crop_*_offset -> crop information
      53             : 
      54           0 :   SpsState sps;
      55             : 
      56             :   // The golomb values we have to read, not just consume.
      57             :   uint32_t golomb_ignored;
      58             : 
      59             :   // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is
      60             :   // 0. It defaults to 1, when not specified.
      61           0 :   uint32_t chroma_format_idc = 1;
      62             : 
      63             :   // profile_idc: u(8). We need it to determine if we need to read/skip chroma
      64             :   // formats.
      65             :   uint8_t profile_idc;
      66           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadUInt8(&profile_idc));
      67             :   // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits
      68             :   // 1 bit each for the flags + 2 bits = 8 bits = 1 byte.
      69           0 :   RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1));
      70             :   // level_idc: u(8)
      71           0 :   RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1));
      72             :   // seq_parameter_set_id: ue(v)
      73           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&sps.id));
      74           0 :   sps.separate_colour_plane_flag = 0;
      75             :   // See if profile_idc has chroma format information.
      76           0 :   if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
      77           0 :       profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
      78           0 :       profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
      79           0 :       profile_idc == 138 || profile_idc == 139 || profile_idc == 134) {
      80             :     // chroma_format_idc: ue(v)
      81           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&chroma_format_idc));
      82           0 :     if (chroma_format_idc == 3) {
      83             :       // separate_colour_plane_flag: u(1)
      84           0 :       RETURN_EMPTY_ON_FAIL(
      85             :           buffer->ReadBits(&sps.separate_colour_plane_flag, 1));
      86             :     }
      87             :     // bit_depth_luma_minus8: ue(v)
      88           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored));
      89             :     // bit_depth_chroma_minus8: ue(v)
      90           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored));
      91             :     // qpprime_y_zero_transform_bypass_flag: u(1)
      92           0 :     RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1));
      93             :     // seq_scaling_matrix_present_flag: u(1)
      94             :     uint32_t seq_scaling_matrix_present_flag;
      95           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&seq_scaling_matrix_present_flag, 1));
      96           0 :     if (seq_scaling_matrix_present_flag) {
      97             :       // seq_scaling_list_present_flags. Either 8 or 12, depending on
      98             :       // chroma_format_idc.
      99             :       uint32_t seq_scaling_list_present_flags;
     100           0 :       if (chroma_format_idc != 3) {
     101           0 :         RETURN_EMPTY_ON_FAIL(
     102             :             buffer->ReadBits(&seq_scaling_list_present_flags, 8));
     103             :       } else {
     104           0 :         RETURN_EMPTY_ON_FAIL(
     105             :             buffer->ReadBits(&seq_scaling_list_present_flags, 12));
     106             :       }
     107             :       // We don't support reading the sequence scaling list, and we don't really
     108             :       // see/use them in practice, so we'll just reject the full sps if we see
     109             :       // any provided.
     110           0 :       if (seq_scaling_list_present_flags > 0) {
     111           0 :         LOG(LS_WARNING) << "SPS contains scaling lists, which are unsupported.";
     112           0 :         return OptionalSps();
     113             :       }
     114             :     }
     115             :   }
     116             :   // log2_max_frame_num_minus4: ue(v)
     117           0 :   RETURN_EMPTY_ON_FAIL(
     118             :       buffer->ReadExponentialGolomb(&sps.log2_max_frame_num_minus4));
     119             :   // pic_order_cnt_type: ue(v)
     120           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&sps.pic_order_cnt_type));
     121           0 :   if (sps.pic_order_cnt_type == 0) {
     122             :     // log2_max_pic_order_cnt_lsb_minus4: ue(v)
     123           0 :     RETURN_EMPTY_ON_FAIL(
     124             :         buffer->ReadExponentialGolomb(&sps.log2_max_pic_order_cnt_lsb_minus4));
     125           0 :   } else if (sps.pic_order_cnt_type == 1) {
     126             :     // delta_pic_order_always_zero_flag: u(1)
     127           0 :     RETURN_EMPTY_ON_FAIL(
     128             :         buffer->ReadBits(&sps.delta_pic_order_always_zero_flag, 1));
     129             :     // offset_for_non_ref_pic: se(v)
     130           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored));
     131             :     // offset_for_top_to_bottom_field: se(v)
     132           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored));
     133             :     // num_ref_frames_in_pic_order_cnt_cycle: ue(v)
     134             :     uint32_t num_ref_frames_in_pic_order_cnt_cycle;
     135           0 :     RETURN_EMPTY_ON_FAIL(
     136             :         buffer->ReadExponentialGolomb(&num_ref_frames_in_pic_order_cnt_cycle));
     137           0 :     for (size_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
     138             :       // offset_for_ref_frame[i]: se(v)
     139           0 :       RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored));
     140             :     }
     141             :   }
     142             :   // max_num_ref_frames: ue(v)
     143           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&sps.max_num_ref_frames));
     144             :   // gaps_in_frame_num_value_allowed_flag: u(1)
     145           0 :   RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1));
     146             :   //
     147             :   // IMPORTANT ONES! Now we're getting to resolution. First we read the pic
     148             :   // width/height in macroblocks (16x16), which gives us the base resolution,
     149             :   // and then we continue on until we hit the frame crop offsets, which are used
     150             :   // to signify resolutions that aren't multiples of 16.
     151             :   //
     152             :   // pic_width_in_mbs_minus1: ue(v)
     153             :   uint32_t pic_width_in_mbs_minus1;
     154           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&pic_width_in_mbs_minus1));
     155             :   // pic_height_in_map_units_minus1: ue(v)
     156             :   uint32_t pic_height_in_map_units_minus1;
     157           0 :   RETURN_EMPTY_ON_FAIL(
     158             :       buffer->ReadExponentialGolomb(&pic_height_in_map_units_minus1));
     159             :   // frame_mbs_only_flag: u(1)
     160           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sps.frame_mbs_only_flag, 1));
     161           0 :   if (!sps.frame_mbs_only_flag) {
     162             :     // mb_adaptive_frame_field_flag: u(1)
     163           0 :     RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1));
     164             :   }
     165             :   // direct_8x8_inference_flag: u(1)
     166           0 :   RETURN_EMPTY_ON_FAIL(buffer->ConsumeBits(1));
     167             :   //
     168             :   // MORE IMPORTANT ONES! Now we're at the frame crop information.
     169             :   //
     170             :   // frame_cropping_flag: u(1)
     171             :   uint32_t frame_cropping_flag;
     172           0 :   uint32_t frame_crop_left_offset = 0;
     173           0 :   uint32_t frame_crop_right_offset = 0;
     174           0 :   uint32_t frame_crop_top_offset = 0;
     175           0 :   uint32_t frame_crop_bottom_offset = 0;
     176           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&frame_cropping_flag, 1));
     177           0 :   if (frame_cropping_flag) {
     178             :     // frame_crop_{left, right, top, bottom}_offset: ue(v)
     179           0 :     RETURN_EMPTY_ON_FAIL(
     180             :         buffer->ReadExponentialGolomb(&frame_crop_left_offset));
     181           0 :     RETURN_EMPTY_ON_FAIL(
     182             :         buffer->ReadExponentialGolomb(&frame_crop_right_offset));
     183           0 :     RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&frame_crop_top_offset));
     184           0 :     RETURN_EMPTY_ON_FAIL(
     185             :         buffer->ReadExponentialGolomb(&frame_crop_bottom_offset));
     186             :   }
     187             :   // vui_parameters_present_flag: u(1)
     188           0 :   RETURN_EMPTY_ON_FAIL(buffer->ReadBits(&sps.vui_params_present, 1));
     189             : 
     190             :   // Far enough! We don't use the rest of the SPS.
     191             : 
     192             :   // Start with the resolution determined by the pic_width/pic_height fields.
     193           0 :   sps.width = 16 * (pic_width_in_mbs_minus1 + 1);
     194           0 :   sps.height =
     195           0 :       16 * (2 - sps.frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1);
     196             : 
     197             :   // Figure out the crop units in pixels. That's based on the chroma format's
     198             :   // sampling, which is indicated by chroma_format_idc.
     199           0 :   if (sps.separate_colour_plane_flag || chroma_format_idc == 0) {
     200           0 :     frame_crop_bottom_offset *= (2 - sps.frame_mbs_only_flag);
     201           0 :     frame_crop_top_offset *= (2 - sps.frame_mbs_only_flag);
     202           0 :   } else if (!sps.separate_colour_plane_flag && chroma_format_idc > 0) {
     203             :     // Width multipliers for formats 1 (4:2:0) and 2 (4:2:2).
     204           0 :     if (chroma_format_idc == 1 || chroma_format_idc == 2) {
     205           0 :       frame_crop_left_offset *= 2;
     206           0 :       frame_crop_right_offset *= 2;
     207             :     }
     208             :     // Height multipliers for format 1 (4:2:0).
     209           0 :     if (chroma_format_idc == 1) {
     210           0 :       frame_crop_top_offset *= 2;
     211           0 :       frame_crop_bottom_offset *= 2;
     212             :     }
     213             :   }
     214             :   // Subtract the crop for each dimension.
     215           0 :   sps.width -= (frame_crop_left_offset + frame_crop_right_offset);
     216           0 :   sps.height -= (frame_crop_top_offset + frame_crop_bottom_offset);
     217             : 
     218           0 :   return OptionalSps(sps);
     219             : }
     220             : 
     221             : }  // namespace webrtc

Generated by: LCOV version 1.13