Chromium Code Reviews| Index: content/common/gpu/media/h264_parser.h |
| diff --git a/content/common/gpu/media/h264_parser.h b/content/common/gpu/media/h264_parser.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9d1090e3b8f5a977e981892884b26b56310c8cda |
| --- /dev/null |
| +++ b/content/common/gpu/media/h264_parser.h |
| @@ -0,0 +1,378 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
|
Ami GONE FROM CHROMIUM
2012/03/21 13:16:24
Not part of this CL?
Pawel Osciak
2012/03/21 18:40:35
Yeah, looks like I was misunderstanding how rietve
Ami GONE FROM CHROMIUM
2012/03/22 17:01:36
Addressed this elsewhere, but FWIW it's always a g
|
| +// found in the LICENSE file. |
| +// |
| +// This file contains an implementation of a H264 Annex-B video stream parser. |
| + |
| +#ifndef CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ |
| +#define CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ |
| + |
| +#include <map> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/memory/scoped_ptr.h" |
| + |
| +// For explanations of each struct and its members, see H.264 specification |
| +enum H264NaluType { |
| + kH264NaluUnspecified = 0, |
| + kH264NaluNonIDRSlice = 1, |
| + kH264NaluIDRSlice = 5, |
| + kH264SEIMessage = 6, |
| + kH264NaluSPS = 7, |
| + kH264NaluPPS = 8, |
| + kH264NaluEOSeq = 9, |
| + kH264NaluEOStream = 11, |
| +}; |
| + |
| +struct H264NALU { |
| + uint8* data; // After/without start code |
| + size_t size; // From after start code to start code of next NALU (or EOS) |
| + |
| + uint8 nal_ref_idc; |
| + uint8 nal_unit_type; |
| +}; |
| + |
| +struct H264SPS { |
| + uint8 profile_idc; |
| + uint8 level_idc; |
| + uint32 seq_parameter_set_id; |
| + |
| + uint8 chroma_format_idc; |
| + bool separate_colour_plane_flag; |
| + uint8 bit_depth_luma_minus8; |
| + uint8 bit_depth_chroma_minus8; |
| + bool qpprime_y_zero_transform_bypass_flag; |
| + |
| + bool seq_scaling_matrix_present_flag; |
| + // Changing uint8s below to larger types will break assumptions |
| + // in code that fills default scaling lists |
| + uint8 scaling_list4x4[6][16]; |
| + uint8 scaling_list8x8[6][64]; |
| + |
| + uint8 log2_max_frame_num_minus4; |
| + uint8 pic_order_cnt_type; |
| + uint8 log2_max_pic_order_cnt_lsb_minus4; |
| + bool delta_pic_order_always_zero_flag; |
| + int32 offset_for_non_ref_pic; |
| + int32 offset_for_top_to_bottom_field; |
| + uint8 num_ref_frames_in_pic_order_cnt_cycle; |
| + int32 offset_for_ref_frame[255]; |
| + uint32 max_num_ref_frames; |
| + bool gaps_in_frame_num_value_allowed_flag; |
| + uint32 pic_width_in_mbs_minus1; |
| + uint32 pic_height_in_map_units_minus1; |
| + bool frame_mbs_only_flag; |
| + bool mb_adaptive_frame_field_flag; |
| + bool direct_8x8_inference_flag; |
| + bool frame_cropping_flag; |
| + uint32 frame_crop_left_offset; |
| + uint32 frame_crop_right_offset; |
| + uint32 frame_crop_top_offset; |
| + uint32 frame_crop_bottom_offset; |
| + bool vui_parameters_present_flag; |
| + |
| + uint8 chroma_array_type; |
| +}; |
| + |
| +struct H264PPS { |
| + uint8 pic_parameter_set_id; |
| + uint8 seq_parameter_set_id; |
| + bool entropy_coding_mode_flag; |
| + bool bottom_field_pic_order_in_frame_present_flag; |
| + uint32 num_slice_groups_minus1; |
| + // TODO slice groups not implemented |
| + uint8 num_ref_idx_l0_default_active_minus1; |
| + uint8 num_ref_idx_l1_default_active_minus1; |
| + bool weighted_pred_flag; |
| + uint8 weighted_bipred_idc; |
| + int8 pic_init_qp_minus26; |
| + int8 pic_init_qs_minus26; |
| + int8 chroma_qp_index_offset; |
| + bool deblocking_filter_control_present_flag; |
| + bool constrained_intra_pred_flag; |
| + bool redundant_pic_cnt_present_flag; |
| + |
| + bool transform_8x8_mode_flag; |
| + |
| + bool pic_scaling_matrix_present_flag; |
| + uint8 scaling_list4x4[6][16]; |
| + uint8 scaling_list8x8[6][64]; |
| + |
| + int32 second_chroma_qp_index_offset; |
| +}; |
| + |
| +enum H264SliceType { |
| + kH264PSlice = 0, |
| + kH264BSlice = 1, |
| + kH264ISlice = 2, |
| + kH264SPSlice = 3, |
| + kH264SISlice = 4, |
| +}; |
| + |
| +struct H264ModificationOfPicNum { |
| + uint8 modification_of_pic_nums_idc; |
| + union { |
| + uint32 abs_diff_pic_num_minus1; |
| + uint32 long_term_pic_num; |
| + }; |
| +}; |
| + |
| +struct H264WeightingFactors { |
| + bool luma_weight_flag; |
| + bool chroma_weight_flag; |
| + |
| + int16 luma_weight[32]; |
| + int16 luma_offset[32]; |
| + int16 chroma_weight[32][2]; |
| + int16 chroma_offset[32][2]; |
| +}; |
| + |
| +struct H264DecRefPicMarking { |
| + uint8 memory_mgmnt_control_operation; |
| + uint32 difference_of_pic_nums_minus1; |
| + uint32 long_term_pic_num; |
| + uint32 long_term_frame_idx; |
| + uint32 max_long_term_frame_idx_plus1; |
| +}; |
| + |
| +struct H264SliceHeader { |
| + enum { kRefListSize = 32 }; |
| + enum { kRefListModSize = kRefListSize }; |
| + |
| + bool idr_pic_flag; // from NAL header |
| + uint8 nal_ref_idc; // from NAL header |
| + uint8* nalu_data; // from NAL header |
| + size_t nalu_size; // from NAL header |
| + size_t header_bit_size; // calculated |
| + |
| + uint32 first_mb_in_slice; |
| + uint8 slice_type; |
| + uint8 pic_parameter_set_id; |
| + uint8 colour_plane_id; |
| + uint32 frame_num; |
| + bool field_pic_flag; |
| + bool bottom_field_flag; |
| + uint16 idr_pic_id; |
| + uint32 pic_order_cnt_lsb; |
| + int32 delta_pic_order_cnt_bottom; |
| + int32 delta_pic_order_cnt[2]; |
| + uint8 redundant_pic_cnt; |
| + bool direct_spatial_mv_pred_flag; |
| + |
| + bool num_ref_idx_active_override_flag; |
| + uint8 num_ref_idx_l0_active_minus1; |
| + uint8 num_ref_idx_l1_active_minus1; |
| + bool ref_pic_list_modification_flag_l0; |
| + bool ref_pic_list_modification_flag_l1; |
| + H264ModificationOfPicNum ref_list_l0_modifications[kRefListModSize]; |
| + H264ModificationOfPicNum ref_list_l1_modifications[kRefListModSize]; |
| + |
| + uint8 luma_log2_weight_denom; |
| + uint8 chroma_log2_weight_denom; |
| + |
| + bool luma_weight_l0_flag; |
| + bool chroma_weight_l0_flag; |
| + H264WeightingFactors pred_weight_table_l0; |
| + |
| + bool luma_weight_l1_flag; |
| + bool chroma_weight_l1_flag; |
| + H264WeightingFactors pred_weight_table_l1; |
| + |
| + bool no_output_of_prior_pics_flag; |
| + bool long_term_reference_flag; |
| + |
| + bool adaptive_ref_pic_marking_mode_flag; |
| + H264DecRefPicMarking ref_pic_marking[kRefListSize]; |
| + |
| + uint8 cabac_init_idc; |
| + int32 slice_qp_delta; |
| + bool sp_for_switch_flag; |
| + int32 slice_qs_delta; |
| + uint8 disable_deblocking_filter_idc; |
| + int8 slice_alpha_c0_offset_div2; |
| + int8 slice_beta_offset_div2; |
| +}; |
| + |
| +enum H264SEIType { |
| + kH264SEIRecoveryPoint = 6, |
| +}; |
| + |
| +struct H264SEIRecoveryPoint { |
| + uint32 recovery_frame_cnt; |
| + bool exact_match_flag; |
| + bool broken_link_flag; |
| + uint8 changing_slice_group_idc; |
| +}; |
| + |
| +struct H264SEIMessage { |
| + int32 type; |
| + uint32 payload_size; |
| + union { |
| + H264SEIRecoveryPoint recovery_point; |
| + }; |
| +}; |
| + |
| +static inline bool IsH264PSlice(H264SliceHeader* shdr) { |
| + if (shdr) |
| + return (shdr->slice_type % 5 == kH264PSlice); |
| + return false; |
| +} |
| + |
| +static inline bool IsH264BSlice(H264SliceHeader* shdr) { |
| + if (shdr) |
| + return (shdr->slice_type % 5 == kH264BSlice); |
| + return false; |
| +} |
| + |
| +static inline bool IsH264ISlice(H264SliceHeader* shdr) { |
| + if (shdr) |
| + return (shdr->slice_type % 5 == kH264ISlice); |
| + return false; |
| +} |
| + |
| +static inline bool IsH264SPSlice(H264SliceHeader* shdr) { |
| + if (shdr) |
| + return (shdr->slice_type % 5 == kH264SPSlice); |
| + return false; |
| +} |
| + |
| +static inline bool IsH264SISlice(H264SliceHeader* shdr) { |
| + if (shdr) |
| + return (shdr->slice_type % 5 == kH264SISlice); |
| + return false; |
| +} |
| + |
| +// Class to provide bit-granularity reading of H.264 streams |
| +// This is not a generic bit reader class, as it takes into account |
| +// H.264 stream-specific constraints, such as skipping emulation-prevention |
| +// bytes and stop bits. See spec for more details. |
| +class H264BitReader { |
| + public: |
| + |
| + H264BitReader(); |
| + ~H264BitReader(); |
| + |
| + bool Initialize(uint8* data, size_t size); |
| + |
| + // Read num_bits next bits in stream and return in out |
| + bool ReadBits(int num_bits, uint32 *out); |
| + |
| + // True if any bits left in the stream |
| + size_t NumBitsLeft() { return (bits_in_curr_byte_ + bytes_left_ * 8); } |
| + |
| + // See the definition of more_rbsp_data() in spec. |
| + bool MoreRBSPData(); |
| + |
| + private: |
| + |
| + // Advance to the next byte if we are out of bits in the current byte |
| + bool UpdateCurrByte(); |
| + |
| + // Pointer to the next unread byte in the stream |
| + uint8* data_; |
| + |
| + // Bytes left in the stream (without the current byte) |
| + size_t bytes_left_; |
| + |
| + // Contents of the current byte |
| + uint8 curr_byte_; |
| + |
| + // for emulation prevention three byte detection |
| + uint16 prev_two_bytes_; |
| + int bits_in_curr_byte_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(H264BitReader); |
| +}; |
| + |
| +// Class to parse an Annex-B H.264 stream, |
| +// as specified in chapters 7 and Annex B of the H.264 spec. |
| +class H264Parser { |
| + public: |
| + |
| + enum Result { |
| + kOk, |
| + kInvalidStream, // error in stream |
| + kUnsupportedStream, // stream not supported by the parser |
| + kEOStream, // end of stream |
| + }; |
| + |
| + H264Parser(); |
| + ~H264Parser(); |
| + |
| + void Reset(); |
| + // stream_size in bytes |
| + void SetStream(uint8* stream, size_t stream_size); |
| + |
| + // Read the next stream to find the next NALU, identify it and return |
| + // that information in nalu. This advances the stream to the beginning |
| + // of this NALU, but not past it, so subsequent calls to NALU-specific |
| + // parsing functions (ParseSPS, etc.) will parse this NALU. |
| + // If the caller wishes to skip the current NALU, it can call this function |
| + // again, instead of any NALU-type specific parse functions below. |
| + Result ParseNextNalu(H264NALU* nalu); |
| + |
| + // Nalu-specific parsing functions. |
| + // These should be called after ParseNextNalu(). |
| + |
| + // SPS and PPS are stored in the Parser and the memory for their structures |
| + // is managed by the parser, as they can be reused across NALUs. |
| + // To access any of them, use GetSPS()/GetPPS() using the returned id. |
| + Result ParseSPS(int* sps_id); |
| + Result ParsePPS(int* pps_id); |
| + |
| + // Slice header is not used across NALUs and can be discarded after current |
| + // NALU, so the parser does not store them, nor does it manage their memory. |
| + // Caller has to provide and manage it instead. |
| + Result ParseSliceHeader(H264SliceHeader* shdr, H264NALU* nalu); |
| + |
| + // Return pointer to SPS/PPS with given id or NULL if not present. |
| + // Caller should not attempt to modify/free this memory. |
| + H264SPS* GetSPS(uint8 sps_id); |
| + H264PPS* GetPPS(uint8 pps_id); |
| + |
| + Result ParseSEI(H264SEIMessage* sei_msg); |
| + |
| + private: |
| + |
| + // Exp-Golomb code parsing as specified in chapter 9.1 of the spec. |
| + // Read one unsigned exp-Golomb code from the stream, |
| + Result ReadUE(uint32* val); |
| + |
| + // Read one signed exp-Golomb code from the stream. |
| + Result ReadSE(int32* val); |
| + |
| + Result ScalingList(uint8* scaling_list, int size, bool* use_default); |
| + Result ParseSPSScalingLists(H264SPS* sps); |
| + Result ParsePPSScalingLists(H264SPS* sps, H264PPS* pps); |
| + |
| + Result RefPicListModification(H264SliceHeader* shdr); |
| + Result ParseRefPicListModification(uint8 num_ref_idx_active_minus1, |
| + H264ModificationOfPicNum* ref_list_mods); |
| + |
| + Result ParsePredWeightTable(H264SliceHeader *shdr, H264SPS* sps); |
| + |
| + Result ParseWeightingFactors(H264WeightingFactors* w_facts, |
| + int num_ref_idx_active_minus1, |
| + uint8 chroma_array_type, |
| + uint8 luma_log2_weight_denom, |
| + uint8 chroma_log2_weight_denom); |
| + Result ParseDecRefPicMarking(H264SliceHeader *shdr); |
| + |
| + // Pointer to the current NALU in the stream |
| + uint8* stream_; |
| + |
| + // Bytes left in the stream after the current NALU. |
| + size_t bytes_left_; |
| + |
| + H264BitReader br_; |
| + |
| + typedef std::map<uint8, H264SPS*> SPSById; |
| + typedef std::map<uint8, H264PPS*> PPSById; |
| + SPSById active_SPSes_; |
| + PPSById active_PPSes_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(H264Parser); |
| +}; |
| + |
| +#endif // CONTENT_COMMON_GPU_MEDIA_H264_PARSER_H_ |
| + |