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_ |
+ |