mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-17 22:06:41 +00:00
vdpau: add beginning of h264 decoder
This commit is contained in:
parent
0490cb89c6
commit
686d2d2303
10 changed files with 2961 additions and 3 deletions
|
@ -11,6 +11,7 @@ libgstvdpau_la_SOURCES = \
|
||||||
mpeg/gstvdpmpegdec.c \
|
mpeg/gstvdpmpegdec.c \
|
||||||
h264/gstnalreader.c \
|
h264/gstnalreader.c \
|
||||||
h264/gsth264parser.c \
|
h264/gsth264parser.c \
|
||||||
|
h264/gstvdph264frame.c \
|
||||||
h264/gstvdph264dec.c
|
h264/gstvdph264dec.c
|
||||||
|
|
||||||
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
||||||
|
@ -32,4 +33,5 @@ noinst_HEADERS = \
|
||||||
mpeg/gstvdpmpegdec.h \
|
mpeg/gstvdpmpegdec.h \
|
||||||
h264/gstnalreader.h \
|
h264/gstnalreader.h \
|
||||||
h264/gsth264parser.h \
|
h264/gsth264parser.h \
|
||||||
|
h264/gstvdph264frame.h \
|
||||||
h264/gstvdph264dec.h
|
h264/gstvdph264dec.h
|
|
@ -23,9 +23,10 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#define GST_TYPE_VIDEO_FRAME (gst_video_frame_get_type())
|
#define GST_TYPE_VIDEO_FRAME (gst_video_frame_get_type())
|
||||||
#define GST_IS_VIDEO_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_FRAME))
|
#define GST_IS_VIDEO_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_FRAME))
|
||||||
#define GST_VIDEO_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_FRAME, GstVideoFrame))
|
#define GST_VIDEO_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_FRAME, GstVideoFrame))
|
||||||
|
#define GST_VIDEO_FRAME_CAST(obj) ((GstVideoFrame *)obj)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstVideoFrameFlag:
|
* GstVideoFrameFlag:
|
||||||
|
|
1184
sys/vdpau/h264/gsth264parser.c
Normal file
1184
sys/vdpau/h264/gsth264parser.c
Normal file
File diff suppressed because it is too large
Load diff
411
sys/vdpau/h264/gsth264parser.h
Normal file
411
sys/vdpau/h264/gsth264parser.h
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GST_H264_PARSER_H_
|
||||||
|
#define _GST_H264_PARSER_H_
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_NAL_UNKNOWN = 0,
|
||||||
|
GST_NAL_SLICE = 1,
|
||||||
|
GST_NAL_SLICE_DPA = 2,
|
||||||
|
GST_NAL_SLICE_DPB = 3,
|
||||||
|
GST_NAL_SLICE_DPC = 4,
|
||||||
|
GST_NAL_SLICE_IDR = 5,
|
||||||
|
GST_NAL_SEI = 6,
|
||||||
|
GST_NAL_SPS = 7,
|
||||||
|
GST_NAL_PPS = 8,
|
||||||
|
GST_NAL_AU_DELIMITER = 9,
|
||||||
|
GST_NAL_SEQ_END = 10,
|
||||||
|
GST_NAL_STREAM_END = 11,
|
||||||
|
GST_NAL_FILTER_DATA = 12
|
||||||
|
} GstNalUnitType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_H264_P_SLICE,
|
||||||
|
GST_H264_B_SLICE,
|
||||||
|
GST_H264_I_SLICE,
|
||||||
|
GST_H264_SP_SLICE,
|
||||||
|
GST_H264_SI_SLICE,
|
||||||
|
GST_H264_S_P_SLICE,
|
||||||
|
GST_H264_S_B_SLICE,
|
||||||
|
GST_H264_S_I_SLICE,
|
||||||
|
GST_H264_S_SP_SLICE,
|
||||||
|
GST_H264_S_SI_SLICE
|
||||||
|
} GstH264SliceType;
|
||||||
|
|
||||||
|
#define GST_H264_IS_P_SLICE(type) ((type % 5) == GST_H264_P_SLICE)
|
||||||
|
#define GST_H264_IS_B_SLICE(type) ((type % 5) == GST_H264_B_SLICE)
|
||||||
|
#define GST_H264_IS_I_SLICE(type) ((type % 5) == GST_H264_I_SLICE)
|
||||||
|
#define GST_H264_IS_SP_SLICE(type) ((type % 5) == GST_H264_SP_SLICE)
|
||||||
|
#define GST_H264_IS_SI_SLICE(type) ((type % 5) == GST_H264_SI_SLICE)
|
||||||
|
|
||||||
|
typedef struct _GstNalUnit GstNalUnit;
|
||||||
|
|
||||||
|
typedef struct _GstH264HRDParameters GstH264HRDParameters;
|
||||||
|
typedef struct _GstH264VUIParameters GstH264VUIParameters;
|
||||||
|
typedef struct _GstH264Sequence GstH264Sequence;
|
||||||
|
|
||||||
|
typedef struct _GstH264Picture GstH264Picture;
|
||||||
|
|
||||||
|
typedef struct _GstH264DecRefPicMarking GstH264DecRefPicMarking;
|
||||||
|
typedef struct _GstH264PredWeightTable GstH264PredWeightTable;
|
||||||
|
typedef struct _GstH264Slice GstH264Slice;
|
||||||
|
|
||||||
|
typedef struct _GstH264ClockTimestamp GstH264ClockTimestamp;
|
||||||
|
typedef struct _GstH264PicTiming GstH264PicTiming;
|
||||||
|
typedef struct _GstH264BufferingPeriod GstH264BufferingPeriod;
|
||||||
|
typedef struct _GstH264SEIMessage GstH264SEIMessage;
|
||||||
|
|
||||||
|
struct _GstNalUnit
|
||||||
|
{
|
||||||
|
guint16 ref_idc;
|
||||||
|
guint16 type;
|
||||||
|
|
||||||
|
/* calculated values */
|
||||||
|
guint8 IdrPicFlag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264HRDParameters
|
||||||
|
{
|
||||||
|
guint8 cpb_cnt_minus1;
|
||||||
|
guint8 bit_rate_scale;
|
||||||
|
guint8 cpb_size_scale;
|
||||||
|
|
||||||
|
guint32 bit_rate_value_minus1[32];
|
||||||
|
guint32 cpb_size_value_minus1[32];
|
||||||
|
guint8 cbr_flag[32];
|
||||||
|
|
||||||
|
guint8 initial_cpb_removal_delay_length_minus1;
|
||||||
|
guint8 cpb_removal_delay_length_minus1;
|
||||||
|
guint8 dpb_output_delay_length_minus1;
|
||||||
|
guint8 time_offset_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264VUIParameters
|
||||||
|
{
|
||||||
|
guint8 aspect_ratio_idc;
|
||||||
|
/* if aspect_ratio_idc == 255 */
|
||||||
|
guint16 sar_width;
|
||||||
|
guint16 sar_height;
|
||||||
|
|
||||||
|
guint8 overscan_info_present_flag;
|
||||||
|
/* if overscan_info_present_flag */
|
||||||
|
guint8 overscan_appropriate_flag;
|
||||||
|
|
||||||
|
guint8 video_format;
|
||||||
|
guint8 video_full_range_flag;
|
||||||
|
guint8 colour_description_present_flag;
|
||||||
|
guint8 colour_primaries;
|
||||||
|
guint8 transfer_characteristics;
|
||||||
|
guint8 matrix_coefficients;
|
||||||
|
|
||||||
|
guint8 chroma_sample_loc_type_top_field;
|
||||||
|
guint8 chroma_sample_loc_type_bottom_field;
|
||||||
|
|
||||||
|
guint8 timing_info_present_flag;
|
||||||
|
/* if timing_info_present_flag */
|
||||||
|
guint32 num_units_in_tick;
|
||||||
|
guint32 time_scale;
|
||||||
|
guint8 fixed_frame_rate_flag;
|
||||||
|
|
||||||
|
guint8 nal_hrd_parameters_present_flag;
|
||||||
|
/* if nal_hrd_parameters_present_flag */
|
||||||
|
GstH264HRDParameters nal_hrd_parameters;
|
||||||
|
|
||||||
|
guint8 vcl_hrd_parameters_present_flag;
|
||||||
|
/* if nal_hrd_parameters_present_flag */
|
||||||
|
GstH264HRDParameters vcl_hrd_parameters;
|
||||||
|
|
||||||
|
guint8 low_delay_hrd_flag;
|
||||||
|
guint8 pic_struct_present_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264Sequence
|
||||||
|
{
|
||||||
|
gint id;
|
||||||
|
|
||||||
|
guint8 profile_idc;
|
||||||
|
guint8 constraint_set0_flag;
|
||||||
|
guint8 constraint_set1_flag;
|
||||||
|
guint8 constraint_set2_flag;
|
||||||
|
guint8 constraint_set3_flag;
|
||||||
|
guint8 level_idc;
|
||||||
|
|
||||||
|
guint8 chroma_format_idc;
|
||||||
|
guint8 separate_colour_plane_flag;
|
||||||
|
guint8 bit_depth_luma_minus8;
|
||||||
|
guint8 bit_depth_chroma_minus8;
|
||||||
|
guint8 qpprime_y_zero_transform_bypass_flag;
|
||||||
|
|
||||||
|
guint8 scaling_matrix_present_flag;
|
||||||
|
guint8 scaling_lists_4x4[6][16];
|
||||||
|
guint8 scaling_lists_8x8[6][64];
|
||||||
|
|
||||||
|
guint8 log2_max_frame_num_minus4;
|
||||||
|
guint8 pic_order_cnt_type;
|
||||||
|
|
||||||
|
/* if pic_order_cnt_type == 0 */
|
||||||
|
guint8 log2_max_pic_order_cnt_lsb_minus4;
|
||||||
|
|
||||||
|
/* else if pic_order_cnt_type == 1 */
|
||||||
|
guint8 delta_pic_order_always_zero_flag;
|
||||||
|
gint32 offset_for_non_ref_pic;
|
||||||
|
gint32 offset_for_top_to_bottom_field;
|
||||||
|
guint8 num_ref_frames_in_pic_order_cnt_cycle;
|
||||||
|
gint32 offset_for_ref_frame[255];
|
||||||
|
|
||||||
|
guint32 num_ref_frames;
|
||||||
|
guint8 gaps_in_frame_num_value_allowed_flag;
|
||||||
|
guint32 pic_width_in_mbs_minus1;
|
||||||
|
guint32 pic_height_in_map_units_minus1;
|
||||||
|
guint8 frame_mbs_only_flag;
|
||||||
|
|
||||||
|
/* if !frame_mbs_only_flag */
|
||||||
|
guint8 mb_adaptive_frame_field_flag;
|
||||||
|
|
||||||
|
guint8 direct_8x8_inference_flag;
|
||||||
|
|
||||||
|
guint32 frame_crop_left_offset;
|
||||||
|
guint32 frame_crop_right_offset;
|
||||||
|
guint32 frame_crop_top_offset;
|
||||||
|
guint32 frame_crop_bottom_offset;
|
||||||
|
|
||||||
|
guint8 vui_parameters_present_flag;
|
||||||
|
/* if vui_parameters_present_flag */
|
||||||
|
GstH264VUIParameters vui_parameters;
|
||||||
|
|
||||||
|
/* calculated values */
|
||||||
|
guint8 ChromaArrayType;
|
||||||
|
guint32 MaxFrameNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264Picture
|
||||||
|
{
|
||||||
|
gint id;
|
||||||
|
|
||||||
|
GstH264Sequence *sequence;
|
||||||
|
|
||||||
|
guint8 entropy_coding_mode_flag;
|
||||||
|
guint8 pic_order_present_flag;
|
||||||
|
|
||||||
|
guint32 num_slice_groups_minus1;
|
||||||
|
|
||||||
|
/* if num_slice_groups_minus1 > 0 */
|
||||||
|
guint8 slice_group_map_type;
|
||||||
|
/* and if slice_group_map_type == 0 */
|
||||||
|
guint32 run_length_minus1[8];
|
||||||
|
/* or if slice_group_map_type == 2 */
|
||||||
|
guint32 top_left[8];
|
||||||
|
guint32 bottom_right[8];
|
||||||
|
/* or if slice_group_map_type == (3, 4, 5) */
|
||||||
|
guint8 slice_group_change_direction_flag;
|
||||||
|
guint32 slice_group_change_rate_minus1;
|
||||||
|
/* or if slice_group_map_type == 6 */
|
||||||
|
guint32 pic_size_in_map_units_minus1;
|
||||||
|
guint8 *slice_group_id;
|
||||||
|
|
||||||
|
guint8 num_ref_idx_l0_active_minus1;
|
||||||
|
guint8 num_ref_idx_l1_active_minus1;
|
||||||
|
guint8 weighted_pred_flag;
|
||||||
|
guint8 weighted_bipred_idc;
|
||||||
|
gint8 pic_init_qp_minus26;
|
||||||
|
gint8 pic_init_qs_minus26;
|
||||||
|
gint8 chroma_qp_index_offset;
|
||||||
|
guint8 deblocking_filter_control_present_flag;
|
||||||
|
guint8 constrained_intra_pred_flag;
|
||||||
|
guint8 redundant_pic_cnt_present_flag;
|
||||||
|
|
||||||
|
guint8 transform_8x8_mode_flag;
|
||||||
|
|
||||||
|
guint8 scaling_matrix_present_flag;
|
||||||
|
/* if scaling_matrix_present_flag == 1 */
|
||||||
|
guint8 scaling_lists_4x4[6][16];
|
||||||
|
guint8 scaling_lists_8x8[6][64];
|
||||||
|
|
||||||
|
guint8 second_chroma_qp_index_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264DecRefPicMarking
|
||||||
|
{
|
||||||
|
/* if slice->nal_unit.IdrPicFlag */
|
||||||
|
guint8 no_output_of_prior_pics_flag;
|
||||||
|
guint8 long_term_reference_flag;
|
||||||
|
|
||||||
|
/* else */
|
||||||
|
guint8 adaptive_ref_pic_marking_mode_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264PredWeightTable
|
||||||
|
{
|
||||||
|
guint8 luma_log2_weight_denom;
|
||||||
|
guint8 chroma_log2_weight_denom;
|
||||||
|
|
||||||
|
guint8 luma_weight_l0[32];
|
||||||
|
guint8 luma_offset_l0[32];
|
||||||
|
|
||||||
|
/* if seq->ChromaArrayType != 0 */
|
||||||
|
guint8 chroma_weight_l0[32][2];
|
||||||
|
guint8 chroma_offset_l0[32][2];
|
||||||
|
|
||||||
|
/* if slice->slice_type % 5 == 1 */
|
||||||
|
guint8 luma_weight_l1[32];
|
||||||
|
guint8 luma_offset_l1[32];
|
||||||
|
/* and if seq->ChromaArrayType != 0 */
|
||||||
|
guint8 chroma_weight_l1[32][2];
|
||||||
|
guint8 chroma_offset_l1[32][2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264Slice
|
||||||
|
{
|
||||||
|
GstNalUnit nal_unit;
|
||||||
|
|
||||||
|
guint32 first_mb_in_slice;
|
||||||
|
guint32 type;
|
||||||
|
|
||||||
|
GstH264Picture *picture;
|
||||||
|
|
||||||
|
/* if seq->separate_colour_plane_flag */
|
||||||
|
guint8 colour_plane_id;
|
||||||
|
|
||||||
|
guint16 frame_num;
|
||||||
|
|
||||||
|
guint8 field_pic_flag;
|
||||||
|
guint8 bottom_field_flag;
|
||||||
|
|
||||||
|
/* if nal_unit.type == 5 */
|
||||||
|
guint16 idr_pic_id;
|
||||||
|
|
||||||
|
/* if seq->pic_order_cnt_type == 0 */
|
||||||
|
guint16 pic_order_cnt_lsb;
|
||||||
|
gint32 delta_pic_order_cnt_bottom;
|
||||||
|
|
||||||
|
gint32 delta_pic_order_cnt[2];
|
||||||
|
guint8 redundant_pic_cnt;
|
||||||
|
|
||||||
|
/* if slice_type == B_SLICE */
|
||||||
|
guint8 direct_spatial_mv_pred_flag;
|
||||||
|
|
||||||
|
guint8 num_ref_idx_l0_active_minus1;
|
||||||
|
guint8 num_ref_idx_l1_active_minus1;
|
||||||
|
|
||||||
|
GstH264PredWeightTable pred_weight_table;
|
||||||
|
/* if nal_unit.ref_idc != 0 */
|
||||||
|
GstH264DecRefPicMarking dec_ref_pic_marking;
|
||||||
|
|
||||||
|
/* calculated values */
|
||||||
|
guint32 MaxPicNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264ClockTimestamp
|
||||||
|
{
|
||||||
|
guint8 ct_type;
|
||||||
|
guint8 nuit_field_based_flag;
|
||||||
|
guint8 counting_type;
|
||||||
|
guint8 discontinuity_flag;
|
||||||
|
guint8 cnt_dropped_flag;
|
||||||
|
guint8 n_frames;
|
||||||
|
|
||||||
|
guint8 seconds_flag;
|
||||||
|
guint8 seconds_value;
|
||||||
|
|
||||||
|
guint8 minutes_flag;
|
||||||
|
guint8 minutes_value;
|
||||||
|
|
||||||
|
guint8 hours_flag;
|
||||||
|
guint8 hours_value;
|
||||||
|
|
||||||
|
guint32 time_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264PicTiming
|
||||||
|
{
|
||||||
|
guint8 cpb_removal_delay;
|
||||||
|
guint8 dpb_output_delay;
|
||||||
|
|
||||||
|
guint8 pic_struct_present_flag;
|
||||||
|
/* if pic_struct_present_flag */
|
||||||
|
guint8 pic_struct;
|
||||||
|
|
||||||
|
guint8 clock_timestamp_flag[3];
|
||||||
|
GstH264ClockTimestamp clock_timestamp[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264BufferingPeriod
|
||||||
|
{
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
|
||||||
|
/* seq->vui_parameters->nal_hrd_parameters_present_flag */
|
||||||
|
guint8 nal_initial_cpb_removal_delay[32];
|
||||||
|
guint8 nal_initial_cpb_removal_delay_offset[32];
|
||||||
|
|
||||||
|
/* seq->vui_parameters->vcl_hrd_parameters_present_flag */
|
||||||
|
guint8 vcl_initial_cpb_removal_delay[32];
|
||||||
|
guint8 vcl_initial_cpb_removal_delay_offset[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264SEIMessage
|
||||||
|
{
|
||||||
|
guint32 payloadType;
|
||||||
|
|
||||||
|
union {
|
||||||
|
GstH264BufferingPeriod buffering_period;
|
||||||
|
GstH264PicTiming pic_timing;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GST_TYPE_H264_PARSER (gst_h264_parser_get_type ())
|
||||||
|
#define GST_H264_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_H264_PARSER, GstH264Parser))
|
||||||
|
#define GST_H264_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_H264_PARSER, GstH264ParserClass))
|
||||||
|
#define GST_IS_H264_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_H264_PARSER))
|
||||||
|
#define GST_IS_H264_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_H264_PARSER))
|
||||||
|
#define GST_H264_PARSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_H264_PARSER, GstH264ParserClass))
|
||||||
|
|
||||||
|
typedef struct _GstH264ParserClass GstH264ParserClass;
|
||||||
|
typedef struct _GstH264Parser GstH264Parser;
|
||||||
|
|
||||||
|
struct _GstH264ParserClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstH264Parser
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GHashTable *sequences;
|
||||||
|
GHashTable *pictures;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_h264_parser_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GstH264Sequence *gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data, guint size);
|
||||||
|
GstH264Picture *gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data, guint size);
|
||||||
|
gboolean gst_h264_parser_parse_slice_header (GstH264Parser * parser, GstH264Slice * slice, guint8 * data, guint size, GstNalUnit nal_unit);
|
||||||
|
gboolean gst_h264_parser_parse_sei_message (GstH264Parser * parser, GstH264Sequence *seq, GstH264SEIMessage * sei, guint8 * data, guint size);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _GST_H264_PARSER_H_ */
|
503
sys/vdpau/h264/gstnalreader.c
Normal file
503
sys/vdpau/h264/gstnalreader.c
Normal file
|
@ -0,0 +1,503 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gstnalreader.h"
|
||||||
|
|
||||||
|
static gboolean gst_nal_reader_read (GstNalReader * reader, guint nbits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:gstnalreader
|
||||||
|
* @short_description: Bit reader which automatically skips
|
||||||
|
* emulation_prevention bytes
|
||||||
|
*
|
||||||
|
* #GstNalReader provides a bit reader which automatically skips
|
||||||
|
* emulation_prevention bytes. It provides functions for reading any number of bits
|
||||||
|
* into 8, 16, 32 and 64 bit variables. It also provides functions for reading
|
||||||
|
* Exp-Golomb values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_new:
|
||||||
|
* @data: Data from which the #GstNalReader should read
|
||||||
|
* @size: Size of @data in bytes
|
||||||
|
*
|
||||||
|
* Create a new #GstNalReader instance, which will read from @data.
|
||||||
|
*
|
||||||
|
* Returns: a new #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
GstNalReader *
|
||||||
|
gst_nal_reader_new (const guint8 * data, guint size)
|
||||||
|
{
|
||||||
|
GstNalReader *ret = g_slice_new0 (GstNalReader);
|
||||||
|
|
||||||
|
ret->data = data;
|
||||||
|
ret->size = size;
|
||||||
|
|
||||||
|
ret->first_byte = 0xff;
|
||||||
|
ret->cache = 0xffffffff;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_new_from_buffer:
|
||||||
|
* @buffer: Buffer from which the #GstNalReader should read
|
||||||
|
*
|
||||||
|
* Create a new #GstNalReader instance, which will read from the
|
||||||
|
* #GstBuffer @buffer.
|
||||||
|
*
|
||||||
|
* Returns: a new #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
GstNalReader *
|
||||||
|
gst_nal_reader_new_from_buffer (const GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
|
||||||
|
|
||||||
|
return gst_nal_reader_new (GST_BUFFER_DATA (buffer),
|
||||||
|
GST_BUFFER_SIZE (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_free:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Frees a #GstNalReader instance, which was previously allocated by
|
||||||
|
* gst_nal_reader_new() or gst_nal_reader_new_from_buffer().
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_nal_reader_free (GstNalReader * reader)
|
||||||
|
{
|
||||||
|
g_return_if_fail (reader != NULL);
|
||||||
|
|
||||||
|
g_slice_free (GstNalReader, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_init:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @data: Data from which the #GstNalReader should read
|
||||||
|
* @size: Size of @data in bytes
|
||||||
|
*
|
||||||
|
* Initializes a #GstNalReader instance to read from @data. This function
|
||||||
|
* can be called on already initialized instances.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_nal_reader_init (GstNalReader * reader, const guint8 * data, guint size)
|
||||||
|
{
|
||||||
|
g_return_if_fail (reader != NULL);
|
||||||
|
|
||||||
|
reader->data = data;
|
||||||
|
reader->size = size;
|
||||||
|
|
||||||
|
reader->byte = 0;
|
||||||
|
reader->bits_in_cache = 0;
|
||||||
|
/* fill with something other than 0 to detect emulation prevention bytes */
|
||||||
|
reader->first_byte = 0xff;
|
||||||
|
reader->cache = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_init_from_buffer:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @buffer: Buffer from which the #GstNalReader should read
|
||||||
|
*
|
||||||
|
* Initializes a #GstNalReader instance to read from @buffer. This function
|
||||||
|
* can be called on already initialized instances.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_nal_reader_init_from_buffer (GstNalReader * reader,
|
||||||
|
const GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GST_IS_BUFFER (buffer));
|
||||||
|
|
||||||
|
gst_nal_reader_init (reader, GST_BUFFER_DATA (buffer),
|
||||||
|
GST_BUFFER_SIZE (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_skip:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @nbits: the number of bits to skip
|
||||||
|
*
|
||||||
|
* Skips @nbits bits of the #GstNalReader instance.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if @nbits bits could be skipped, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_skip (GstNalReader * reader, guint nbits)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_nal_reader_read (reader, nbits)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
reader->bits_in_cache -= nbits;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_skip_to_byte:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Skips until the next byte.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_skip_to_byte (GstNalReader * reader)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
|
||||||
|
if (reader->bits_in_cache == 0) {
|
||||||
|
if (G_LIKELY ((reader->size - reader->byte) > 0))
|
||||||
|
reader->byte++;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader->bits_in_cache = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_pos:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Returns the current position of a GstNalReader instance in bits.
|
||||||
|
*
|
||||||
|
* Returns: The current position in bits
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
gst_nal_reader_get_pos (const GstNalReader * reader)
|
||||||
|
{
|
||||||
|
return reader->byte * 8 - reader->bits_in_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_remaining:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
*
|
||||||
|
* Returns the remaining number of bits of a GstNalReader instance.
|
||||||
|
*
|
||||||
|
* Returns: The remaining number of bits.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
gst_nal_reader_get_remaining (const GstNalReader * reader)
|
||||||
|
{
|
||||||
|
return (reader->size - reader->byte) * 8 + reader->bits_in_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_bits_uint8:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint8 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val and update the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_bits_uint16:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint16 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val and update the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_bits_uint32:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint32 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val and update the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_bits_uint64:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint64 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val and update the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_bits_uint8:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint8 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val but keep the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_bits_uint16:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint16 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val but keep the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_bits_uint32:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint32 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val but keep the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_bits_uint64:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint64 to store the result
|
||||||
|
* @nbits: number of bits to read
|
||||||
|
*
|
||||||
|
* Read @nbits bits into @val but keep the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_nal_reader_read (GstNalReader * reader, guint nbits)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (reader->byte * 8 + (nbits - reader->bits_in_cache) >
|
||||||
|
reader->size * 8))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (reader->bits_in_cache < nbits) {
|
||||||
|
guint8 byte;
|
||||||
|
gboolean check_three_byte;
|
||||||
|
|
||||||
|
check_three_byte = TRUE;
|
||||||
|
next_byte:
|
||||||
|
if (G_UNLIKELY (reader->byte >= reader->size))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
byte = reader->data[reader->byte++];
|
||||||
|
|
||||||
|
/* check if the byte is a emulation_prevention_three_byte */
|
||||||
|
if (check_three_byte && byte == 0x03 && reader->first_byte == 0x00 &&
|
||||||
|
((reader->cache & 0xff) == 0)) {
|
||||||
|
/* next byte goes unconditionally to the cache, even if it's 0x03 */
|
||||||
|
check_three_byte = FALSE;
|
||||||
|
goto next_byte;
|
||||||
|
}
|
||||||
|
reader->cache = (reader->cache << 8) | reader->first_byte;
|
||||||
|
reader->first_byte = byte;
|
||||||
|
reader->bits_in_cache += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GST_NAL_READER_READ_BITS(bits) \
|
||||||
|
gboolean \
|
||||||
|
gst_nal_reader_get_bits_uint##bits (GstNalReader *reader, guint##bits *val, guint nbits) \
|
||||||
|
{ \
|
||||||
|
guint shift; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE); \
|
||||||
|
g_return_val_if_fail (val != NULL, FALSE); \
|
||||||
|
g_return_val_if_fail (nbits <= bits, FALSE); \
|
||||||
|
\
|
||||||
|
if (!gst_nal_reader_read (reader, nbits)) \
|
||||||
|
return FALSE; \
|
||||||
|
\
|
||||||
|
/* bring the required bits down and truncate */ \
|
||||||
|
shift = reader->bits_in_cache - nbits; \
|
||||||
|
*val = reader->first_byte >> shift; \
|
||||||
|
\
|
||||||
|
*val |= reader->cache << (8 - shift); \
|
||||||
|
/* mask out required bits */ \
|
||||||
|
if (nbits < bits) \
|
||||||
|
*val &= ((guint##bits)1 << nbits) - 1; \
|
||||||
|
\
|
||||||
|
reader->bits_in_cache = shift; \
|
||||||
|
\
|
||||||
|
return TRUE; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
gboolean \
|
||||||
|
gst_nal_reader_peek_bits_uint##bits (const GstNalReader *reader, guint##bits *val, guint nbits) \
|
||||||
|
{ \
|
||||||
|
GstNalReader tmp; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE); \
|
||||||
|
tmp = *reader; \
|
||||||
|
return gst_nal_reader_get_bits_uint##bits (&tmp, val, nbits); \
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_NAL_READER_READ_BITS (8);
|
||||||
|
GST_NAL_READER_READ_BITS (16);
|
||||||
|
GST_NAL_READER_READ_BITS (32);
|
||||||
|
GST_NAL_READER_READ_BITS (64);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_ue:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint32 to store the result
|
||||||
|
*
|
||||||
|
* Reads an unsigned Exp-Golomb value into val
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_get_ue (GstNalReader * reader, guint32 * val)
|
||||||
|
{
|
||||||
|
guint i = 0;
|
||||||
|
guint8 bit;
|
||||||
|
guint32 value;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_nal_reader_get_bits_uint8 (reader, &bit, 1)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (bit == 0) {
|
||||||
|
i++;
|
||||||
|
if G_UNLIKELY
|
||||||
|
((!gst_nal_reader_get_bits_uint8 (reader, &bit, 1)))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail (i <= 32, FALSE);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_nal_reader_get_bits_uint32 (reader, &value, i)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*val = (1 << i) - 1 + value;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_ue:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #guint32 to store the result
|
||||||
|
*
|
||||||
|
* Read an unsigned Exp-Golomb value into val but keep the current position
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_peek_ue (const GstNalReader * reader, guint32 * val)
|
||||||
|
{
|
||||||
|
GstNalReader tmp;
|
||||||
|
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
|
||||||
|
tmp = *reader;
|
||||||
|
return gst_nal_reader_get_ue (&tmp, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_get_e:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #gint32 to store the result
|
||||||
|
*
|
||||||
|
* Reads a signed Exp-Golomb value into val
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_get_se (GstNalReader * reader, gint32 * val)
|
||||||
|
{
|
||||||
|
guint32 value;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_nal_reader_get_ue (reader, &value)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (value % 2)
|
||||||
|
*val = -(value / 2);
|
||||||
|
else
|
||||||
|
*val = value / 2;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_nal_reader_peek_se:
|
||||||
|
* @reader: a #GstNalReader instance
|
||||||
|
* @val: Pointer to a #gint32 to store the result
|
||||||
|
*
|
||||||
|
* Read a signed Exp-Golomb value into val but keep the current position
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_nal_reader_peek_se (const GstNalReader * reader, gint32 * val)
|
||||||
|
{
|
||||||
|
GstNalReader tmp;
|
||||||
|
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
|
||||||
|
tmp = *reader;
|
||||||
|
return gst_nal_reader_get_se (&tmp, val);
|
||||||
|
}
|
99
sys/vdpau/h264/gstnalreader.h
Normal file
99
sys/vdpau/h264/gstnalreader.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_NAL_READER_H__
|
||||||
|
#define __GST_NAL_READER_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstNalReader GstNalReader;
|
||||||
|
|
||||||
|
struct _GstNalReader
|
||||||
|
{
|
||||||
|
const guint8 *data;
|
||||||
|
guint size;
|
||||||
|
|
||||||
|
guint byte; /* Byte position */
|
||||||
|
guint bits_in_cache; /* bitpos in the cache of next bit */
|
||||||
|
guint8 first_byte;
|
||||||
|
guint64 cache; /* cached bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
GstNalReader *gst_nal_reader_new (const guint8 *data, guint size);
|
||||||
|
GstNalReader *gst_nal_reader_new_from_buffer (const GstBuffer *buffer);
|
||||||
|
void gst_nal_reader_free (GstNalReader * reader);
|
||||||
|
|
||||||
|
void gst_nal_reader_init (GstNalReader * reader, const guint8 * data, guint size);
|
||||||
|
void gst_nal_reader_init_from_buffer (GstNalReader * reader, const GstBuffer * buffer);
|
||||||
|
|
||||||
|
gboolean gst_nal_reader_skip (GstNalReader *reader, guint nbits);
|
||||||
|
gboolean gst_nal_reader_skip_to_byte (GstNalReader *reader);
|
||||||
|
|
||||||
|
guint gst_nal_reader_get_pos (const GstNalReader * reader);
|
||||||
|
guint gst_nal_reader_get_remaining (const GstNalReader *reader);
|
||||||
|
|
||||||
|
gboolean gst_nal_reader_get_bits_uint8 (GstNalReader *reader, guint8 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_get_bits_uint16 (GstNalReader *reader, guint16 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_get_bits_uint32 (GstNalReader *reader, guint32 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_get_bits_uint64 (GstNalReader *reader, guint64 *val, guint nbits);
|
||||||
|
|
||||||
|
gboolean gst_nal_reader_peek_bits_uint8 (const GstNalReader *reader, guint8 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_peek_bits_uint16 (const GstNalReader *reader, guint16 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_peek_bits_uint32 (const GstNalReader *reader, guint32 *val, guint nbits);
|
||||||
|
gboolean gst_nal_reader_peek_bits_uint64 (const GstNalReader *reader, guint64 *val, guint nbits);
|
||||||
|
|
||||||
|
gboolean gst_nal_reader_get_ue (GstNalReader *reader, guint32 *val);
|
||||||
|
gboolean gst_nal_reader_peek_ue (const GstNalReader *reader, guint32 *val);
|
||||||
|
|
||||||
|
gboolean gst_nal_reader_get_se (GstNalReader *reader, gint32 *val);
|
||||||
|
gboolean gst_nal_reader_peek_se (const GstNalReader *reader, gint32 *val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_NAL_READER_INIT:
|
||||||
|
* @data: Data from which the #GstNalReader should read
|
||||||
|
* @size: Size of @data in bytes
|
||||||
|
*
|
||||||
|
* A #GstNalReader must be initialized with this macro, before it can be
|
||||||
|
* used. This macro can used be to initialize a variable, but it cannot
|
||||||
|
* be assigned to a variable. In that case you have to use
|
||||||
|
* gst_bit_reader_init().
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
#define GST_NAL_READER_INIT(data, size) {data, size, 0, 0, 0xff, 0xffffffffff}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_NAL_READER_INIT_FROM_BUFFER:
|
||||||
|
* @buffer: Buffer from which the #GstNalReader should read
|
||||||
|
*
|
||||||
|
* A #GstNalReader must be initialized with this macro, before it can be
|
||||||
|
* used. This macro can used be to initialize a variable, but it cannot
|
||||||
|
* be assigned to a variable. In that case you have to use
|
||||||
|
* gst_bit_reader_init().
|
||||||
|
*
|
||||||
|
* Since: 0.10.22
|
||||||
|
*/
|
||||||
|
#define GST_NAL_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0, 0, 0xff, 0xffffffffff}
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_NAL_READER_H__ */
|
533
sys/vdpau/h264/gstvdph264dec.c
Normal file
533
sys/vdpau/h264/gstvdph264dec.c
Normal file
|
@ -0,0 +1,533 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
|
#include <gst/base/gstbitreader.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../gstvdp/gstvdpvideosrcpad.h"
|
||||||
|
|
||||||
|
#include "gstvdph264frame.h"
|
||||||
|
|
||||||
|
#include "gstvdph264dec.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_vdp_h264_dec_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_vdp_h264_dec_debug
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE (GST_BASE_VIDEO_DECODER_SINK_NAME,
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("video/x-h264, " "parsed = (boolean) false")
|
||||||
|
);
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_vdp_h264_dec_debug, "vdpauh264dec", 0, \
|
||||||
|
"VDPAU h264 decoder");
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstVdpH264Dec, gst_vdp_h264_dec, GstBaseVideoDecoder,
|
||||||
|
GST_TYPE_BASE_VIDEO_DECODER, DEBUG_INIT);
|
||||||
|
|
||||||
|
#define SYNC_CODE_SIZE 3
|
||||||
|
|
||||||
|
#define READ_UINT8(reader, val, nbits) { \
|
||||||
|
if (!gst_bit_reader_get_bits_uint8 (reader, &val, nbits)) { \
|
||||||
|
GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
|
||||||
|
return FALSE; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_UINT16(reader, val, nbits) { \
|
||||||
|
if (!gst_bit_reader_get_bits_uint16 (reader, &val, nbits)) { \
|
||||||
|
GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
|
||||||
|
return FALSE; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIP(reader, nbits) { \
|
||||||
|
if (!gst_bit_reader_skip (reader, nbits)) { \
|
||||||
|
GST_WARNING ("failed to skip nbits: %d", nbits); \
|
||||||
|
return FALSE; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_h264_dec_set_sink_caps (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec;
|
||||||
|
GstStructure *structure;
|
||||||
|
const GValue *value;
|
||||||
|
|
||||||
|
h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
/* packetized video has a codec_data */
|
||||||
|
if ((value = gst_structure_get_value (structure, "codec_data"))) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstBitReader reader;
|
||||||
|
guint8 version;
|
||||||
|
guint8 n_sps, n_pps;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (h264_dec, "have packetized h264");
|
||||||
|
h264_dec->packetized = TRUE;
|
||||||
|
|
||||||
|
buf = gst_value_get_buffer (value);
|
||||||
|
GST_MEMDUMP ("avcC:", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||||
|
|
||||||
|
/* parse the avcC data */
|
||||||
|
if (GST_BUFFER_SIZE (buf) < 7) {
|
||||||
|
GST_ERROR_OBJECT (h264_dec, "avcC size %u < 7", GST_BUFFER_SIZE (buf));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_bit_reader_init_from_buffer (&reader, buf);
|
||||||
|
|
||||||
|
READ_UINT8 (&reader, version, 8);
|
||||||
|
if (version != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
SKIP (&reader, 30);
|
||||||
|
|
||||||
|
READ_UINT8 (&reader, h264_dec->nal_length_size, 2);
|
||||||
|
h264_dec->nal_length_size += 1;
|
||||||
|
GST_DEBUG_OBJECT (h264_dec, "nal length %u", h264_dec->nal_length_size);
|
||||||
|
|
||||||
|
SKIP (&reader, 3);
|
||||||
|
|
||||||
|
READ_UINT8 (&reader, n_sps, 5);
|
||||||
|
for (i = 0; i < n_sps; i++) {
|
||||||
|
guint16 sps_length;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
READ_UINT16 (&reader, sps_length, 16);
|
||||||
|
sps_length -= 1;
|
||||||
|
SKIP (&reader, 8);
|
||||||
|
|
||||||
|
data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
|
||||||
|
if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, sps_length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
SKIP (&reader, sps_length * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
READ_UINT8 (&reader, n_pps, 8);
|
||||||
|
for (i = 0; i < n_pps; i++) {
|
||||||
|
guint16 pps_length;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
READ_UINT16 (&reader, pps_length, 16);
|
||||||
|
pps_length -= 1;
|
||||||
|
SKIP (&reader, 8);
|
||||||
|
|
||||||
|
data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
|
||||||
|
if (!gst_h264_parser_parse_picture (h264_dec->parser, data, pps_length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
SKIP (&reader, pps_length * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_h264_dec_shape_output (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstBuffer * buf)
|
||||||
|
{
|
||||||
|
GstVdpVideoSrcPad *vdp_pad;
|
||||||
|
|
||||||
|
vdp_pad =
|
||||||
|
(GstVdpVideoSrcPad *) GST_BASE_VIDEO_DECODER_SRC_PAD (base_video_decoder);
|
||||||
|
|
||||||
|
return gst_vdp_video_src_pad_push (vdp_pad, GST_VDP_VIDEO_BUFFER (buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstVideoFrame * frame, GstClockTimeDiff deadline)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame *h264_frame;
|
||||||
|
|
||||||
|
GST_DEBUG ("handle_frame");
|
||||||
|
|
||||||
|
h264_frame = (GstVdpH264Frame *) frame;
|
||||||
|
|
||||||
|
GST_DEBUG ("frame_num: %d", h264_frame->slice_hdr.frame_num);
|
||||||
|
GST_DEBUG ("pic_order_cnt_type: %d",
|
||||||
|
h264_frame->slice_hdr.picture->sequence->pic_order_cnt_type);
|
||||||
|
GST_DEBUG ("pic_order_cnt_lsb: %d", h264_frame->slice_hdr.pic_order_cnt_lsb);
|
||||||
|
GST_DEBUG ("delta_pic_order_cnt_bottom: %d",
|
||||||
|
h264_frame->slice_hdr.delta_pic_order_cnt_bottom);
|
||||||
|
|
||||||
|
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
gst_vdp_h264_dec_scan_for_sync (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstAdapter * adapter)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
gint m;
|
||||||
|
|
||||||
|
if (h264_dec->packetized)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
m = gst_adapter_masked_scan_uint32 (adapter, 0xffffff00, 0x00000100,
|
||||||
|
0, gst_adapter_available (adapter));
|
||||||
|
if (m == -1)
|
||||||
|
return gst_adapter_available (adapter) - SYNC_CODE_SIZE;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstBaseVideoDecoderScanResult
|
||||||
|
gst_vdp_h264_dec_scan_for_packet_end (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstAdapter * adapter, guint * size, gboolean at_eos)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
guint avail;
|
||||||
|
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
if (avail < h264_dec->nal_length_size)
|
||||||
|
return GST_BASE_VIDEO_DECODER_SCAN_RESULT_NEED_DATA;
|
||||||
|
|
||||||
|
if (h264_dec->packetized) {
|
||||||
|
guint8 *data;
|
||||||
|
gint i;
|
||||||
|
guint32 nal_length;
|
||||||
|
|
||||||
|
data = g_slice_alloc (h264_dec->nal_length_size);
|
||||||
|
gst_adapter_copy (adapter, data, 0, h264_dec->nal_length_size);
|
||||||
|
for (i = 0; i < h264_dec->nal_length_size; i++)
|
||||||
|
nal_length = (nal_length << 8) | data[i];
|
||||||
|
|
||||||
|
g_slice_free1 (h264_dec->nal_length_size, data);
|
||||||
|
|
||||||
|
nal_length += h264_dec->nal_length_size;
|
||||||
|
|
||||||
|
/* check for invalid NALU sizes, assume the size if the available bytes
|
||||||
|
* when something is fishy */
|
||||||
|
if (nal_length <= 1 || nal_length > avail) {
|
||||||
|
nal_length = avail - h264_dec->nal_length_size;
|
||||||
|
GST_DEBUG ("fixing invalid NALU size to %u", nal_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = nal_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
guint8 *data;
|
||||||
|
guint32 start_code;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
data = g_slice_alloc (SYNC_CODE_SIZE);
|
||||||
|
gst_adapter_copy (adapter, data, 0, SYNC_CODE_SIZE);
|
||||||
|
start_code = ((data[0] << 16) && (data[1] << 8) && data[2]);
|
||||||
|
g_slice_free1 (SYNC_CODE_SIZE, data);
|
||||||
|
|
||||||
|
GST_DEBUG ("start_code: %d", start_code);
|
||||||
|
if (start_code == 0x000001)
|
||||||
|
return GST_BASE_VIDEO_DECODER_SCAN_RESULT_LOST_SYNC;
|
||||||
|
|
||||||
|
n = gst_adapter_masked_scan_uint32 (adapter, 0xffffff00, 0x00000100,
|
||||||
|
SYNC_CODE_SIZE, avail - SYNC_CODE_SIZE);
|
||||||
|
if (n == -1)
|
||||||
|
return GST_BASE_VIDEO_DECODER_SCAN_RESULT_NEED_DATA;
|
||||||
|
|
||||||
|
*size = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG ("NAL size: %d", *size);
|
||||||
|
|
||||||
|
return GST_BASE_VIDEO_DECODER_SCAN_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstBuffer * buf, gboolean at_eos)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
GstBitReader reader;
|
||||||
|
GstNalUnit nal_unit;
|
||||||
|
guint8 forbidden_zero_bit;
|
||||||
|
|
||||||
|
guint8 *data;
|
||||||
|
guint size;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
GstVideoFrame *frame;
|
||||||
|
|
||||||
|
GST_MEMDUMP ("data", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||||
|
|
||||||
|
gst_bit_reader_init_from_buffer (&reader, buf);
|
||||||
|
|
||||||
|
/* skip nal_length or sync code */
|
||||||
|
gst_bit_reader_skip (&reader, h264_dec->nal_length_size * 8);
|
||||||
|
|
||||||
|
if (!gst_bit_reader_get_bits_uint8 (&reader, &forbidden_zero_bit, 1))
|
||||||
|
goto invalid_packet;
|
||||||
|
if (forbidden_zero_bit != 0) {
|
||||||
|
GST_WARNING ("forbidden_zero_bit != 0");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_bit_reader_get_bits_uint16 (&reader, &nal_unit.ref_idc, 2))
|
||||||
|
goto invalid_packet;
|
||||||
|
GST_DEBUG ("nal_ref_idc: %u", nal_unit.ref_idc);
|
||||||
|
|
||||||
|
/* read nal_unit_type */
|
||||||
|
if (!gst_bit_reader_get_bits_uint16 (&reader, &nal_unit.type, 5))
|
||||||
|
goto invalid_packet;
|
||||||
|
|
||||||
|
GST_DEBUG ("nal_unit_type: %u", nal_unit.type);
|
||||||
|
if (nal_unit.type == 14 || nal_unit.type == 20) {
|
||||||
|
if (!gst_bit_reader_skip (&reader, 24))
|
||||||
|
goto invalid_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8;
|
||||||
|
size = gst_bit_reader_get_remaining (&reader) / 8;
|
||||||
|
|
||||||
|
i = size - 1;
|
||||||
|
while (size >= 0 && data[i] == 0x00) {
|
||||||
|
size--;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = gst_base_video_decoder_get_current_frame (base_video_decoder);
|
||||||
|
|
||||||
|
/* does this mark the beginning of a new access unit */
|
||||||
|
if (nal_unit.type == GST_NAL_AU_DELIMITER)
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
|
||||||
|
if (nal_unit.type == GST_NAL_SPS || nal_unit.type == GST_NAL_PPS ||
|
||||||
|
nal_unit.type == GST_NAL_SEI ||
|
||||||
|
(nal_unit.type >= 14 && nal_unit.type <= 18))
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nal_unit.type >= GST_NAL_SLICE && nal_unit.type <= GST_NAL_SLICE_IDR) {
|
||||||
|
GstH264Slice slice;
|
||||||
|
|
||||||
|
if (!gst_h264_parser_parse_slice_header (h264_dec->parser, &slice, data,
|
||||||
|
size, nal_unit))
|
||||||
|
goto invalid_packet;
|
||||||
|
|
||||||
|
if (slice.redundant_pic_cnt == 0) {
|
||||||
|
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
|
||||||
|
GstH264Slice *p_slice;
|
||||||
|
guint8 pic_order_cnt_type, p_pic_order_cnt_type;
|
||||||
|
|
||||||
|
p_slice = &(GST_VDP_H264_FRAME_CAST (frame)->slice_hdr);
|
||||||
|
pic_order_cnt_type = slice.picture->sequence->pic_order_cnt_type;
|
||||||
|
p_pic_order_cnt_type = p_slice->picture->sequence->pic_order_cnt_type;
|
||||||
|
|
||||||
|
if (slice.frame_num != p_slice->frame_num)
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
else if (slice.picture != p_slice->picture)
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
else if (slice.bottom_field_flag != p_slice->bottom_field_flag)
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
else if (nal_unit.ref_idc != p_slice->nal_unit.ref_idc &&
|
||||||
|
(nal_unit.ref_idc == 0 || p_slice->nal_unit.ref_idc == 0))
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
else if ((pic_order_cnt_type == 0 && p_pic_order_cnt_type == 0) &&
|
||||||
|
(slice.pic_order_cnt_lsb != p_slice->pic_order_cnt_lsb ||
|
||||||
|
slice.delta_pic_order_cnt_bottom !=
|
||||||
|
p_slice->delta_pic_order_cnt_bottom))
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
|
||||||
|
else if ((p_pic_order_cnt_type == 1 && p_pic_order_cnt_type == 1) &&
|
||||||
|
(slice.delta_pic_order_cnt[0] != p_slice->delta_pic_order_cnt[0] ||
|
||||||
|
slice.delta_pic_order_cnt[1] !=
|
||||||
|
p_slice->delta_pic_order_cnt[1]))
|
||||||
|
gst_base_video_decoder_have_frame (base_video_decoder, &frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
|
||||||
|
if (GST_H264_IS_I_SLICE (slice.type)
|
||||||
|
|| GST_H264_IS_SI_SLICE (slice.type))
|
||||||
|
GST_VIDEO_FRAME_FLAG_SET (frame, GST_VIDEO_FRAME_FLAG_KEYFRAME);
|
||||||
|
|
||||||
|
GST_VDP_H264_FRAME_CAST (frame)->slice_hdr = slice;
|
||||||
|
GST_VIDEO_FRAME_FLAG_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_vdp_h264_frame_add_slice ((GstVdpH264Frame *) frame, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nal_unit.type == GST_NAL_SPS) {
|
||||||
|
if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, size))
|
||||||
|
goto invalid_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nal_unit.type == GST_NAL_PPS) {
|
||||||
|
if (!gst_h264_parser_parse_picture (h264_dec->parser, data, size))
|
||||||
|
goto invalid_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nal_unit.type == GST_NAL_SEI) {
|
||||||
|
GstH264Sequence *seq;
|
||||||
|
GstH264SEIMessage sei;
|
||||||
|
|
||||||
|
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY))
|
||||||
|
seq = GST_VDP_H264_FRAME_CAST (frame)->slice_hdr.picture->sequence;
|
||||||
|
else
|
||||||
|
seq = NULL;
|
||||||
|
|
||||||
|
if (!gst_h264_parser_parse_sei_message (h264_dec->parser, seq, &sei, data,
|
||||||
|
size))
|
||||||
|
goto invalid_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
invalid_packet:
|
||||||
|
GST_WARNING ("Invalid packet size!");
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVideoFrame *
|
||||||
|
gst_vdp_h264_dec_create_frame (GstBaseVideoDecoder * base_video_decoder)
|
||||||
|
{
|
||||||
|
return GST_VIDEO_FRAME_CAST (gst_vdp_h264_frame_new ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstPad *
|
||||||
|
gst_vdp_h264_dec_create_srcpad (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstBaseVideoDecoderClass * base_video_decoder_class)
|
||||||
|
{
|
||||||
|
GstPadTemplate *pad_template;
|
||||||
|
GstVdpVideoSrcPad *vdp_pad;
|
||||||
|
|
||||||
|
pad_template = gst_element_class_get_pad_template
|
||||||
|
(GST_ELEMENT_CLASS (base_video_decoder_class),
|
||||||
|
GST_BASE_VIDEO_DECODER_SRC_NAME);
|
||||||
|
|
||||||
|
vdp_pad = gst_vdp_video_src_pad_new (pad_template,
|
||||||
|
GST_BASE_VIDEO_DECODER_SRC_NAME);
|
||||||
|
|
||||||
|
return GST_PAD (vdp_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_h264_dec_flush (GstBaseVideoDecoder * base_video_decoder)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_h264_dec_start (GstBaseVideoDecoder * base_video_decoder)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
|
h264_dec->packetized = FALSE;
|
||||||
|
h264_dec->nal_length_size = SYNC_CODE_SIZE;
|
||||||
|
h264_dec->parser = g_object_new (GST_TYPE_H264_PARSER, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_h264_dec_stop (GstBaseVideoDecoder * base_video_decoder)
|
||||||
|
{
|
||||||
|
GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder);
|
||||||
|
|
||||||
|
g_object_unref (h264_dec->parser);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_base_init (gpointer g_class)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||||
|
|
||||||
|
GstCaps *src_caps;
|
||||||
|
GstPadTemplate *src_template;
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (element_class,
|
||||||
|
"VDPAU H264 Decoder",
|
||||||
|
"Decoder",
|
||||||
|
"Decode h264 stream with vdpau",
|
||||||
|
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
|
||||||
|
src_caps = gst_vdp_video_buffer_get_caps (TRUE, VDP_CHROMA_TYPE_420);
|
||||||
|
src_template = gst_pad_template_new (GST_BASE_VIDEO_DECODER_SRC_NAME,
|
||||||
|
GST_PAD_SRC, GST_PAD_ALWAYS, src_caps);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class, src_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_init (GstVdpH264Dec * h264_dec, GstVdpH264DecClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_dec_class_init (GstVdpH264DecClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GstBaseVideoDecoderClass *base_video_decoder_class =
|
||||||
|
GST_BASE_VIDEO_DECODER_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_vdp_h264_dec_finalize;
|
||||||
|
|
||||||
|
base_video_decoder_class->start = gst_vdp_h264_dec_start;
|
||||||
|
base_video_decoder_class->stop = gst_vdp_h264_dec_stop;
|
||||||
|
base_video_decoder_class->flush = gst_vdp_h264_dec_flush;
|
||||||
|
|
||||||
|
base_video_decoder_class->create_srcpad = gst_vdp_h264_dec_create_srcpad;
|
||||||
|
base_video_decoder_class->set_sink_caps = gst_vdp_h264_dec_set_sink_caps;
|
||||||
|
|
||||||
|
base_video_decoder_class->scan_for_sync = gst_vdp_h264_dec_scan_for_sync;
|
||||||
|
base_video_decoder_class->scan_for_packet_end =
|
||||||
|
gst_vdp_h264_dec_scan_for_packet_end;
|
||||||
|
base_video_decoder_class->parse_data = gst_vdp_h264_dec_parse_data;
|
||||||
|
|
||||||
|
base_video_decoder_class->handle_frame = gst_vdp_h264_dec_handle_frame;
|
||||||
|
base_video_decoder_class->create_frame = gst_vdp_h264_dec_create_frame;
|
||||||
|
|
||||||
|
base_video_decoder_class->shape_output = gst_vdp_h264_dec_shape_output;
|
||||||
|
}
|
61
sys/vdpau/h264/gstvdph264dec.h
Normal file
61
sys/vdpau/h264/gstvdph264dec.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_VDP_H264_DEC_H__
|
||||||
|
#define __GST_VDP_H264_DEC_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "../basevideodecoder/gstbasevideodecoder.h"
|
||||||
|
|
||||||
|
#include "gsth264parser.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_VDP_H264_DEC (gst_vdp_h264_dec_get_type())
|
||||||
|
#define GST_VDP_H264_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_H264_DEC,GstVdpH264Dec))
|
||||||
|
#define GST_VDP_H264_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_H264_DEC,GstVdpH264DecClass))
|
||||||
|
#define GST_VDP_H264_DEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_VDP_H264_DEC,GstVdpH264DecClass))
|
||||||
|
#define GST_IS_VDP_H264_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_H264_DEC))
|
||||||
|
#define GST_IS_VDP_H264_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_H264_DEC))
|
||||||
|
#define GST_VDP_H264_DEC_CAST(obj) ((GstVdpH264Dec *)(obj))
|
||||||
|
|
||||||
|
typedef struct _GstVdpH264Dec GstVdpH264Dec;
|
||||||
|
typedef struct _GstVdpH264DecClass GstVdpH264DecClass;
|
||||||
|
|
||||||
|
|
||||||
|
struct _GstVdpH264Dec {
|
||||||
|
GstBaseVideoDecoder base_video_decoder;
|
||||||
|
|
||||||
|
GstBuffer *codec_data;
|
||||||
|
gboolean packetized;
|
||||||
|
guint8 nal_length_size;
|
||||||
|
GstH264Parser *parser;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVdpH264DecClass {
|
||||||
|
GstBaseVideoDecoderClass base_video_decoder_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_vdp_h264_dec_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_VDP_H264_DEC_H__ */
|
104
sys/vdpau/h264/gstvdph264frame.c
Normal file
104
sys/vdpau/h264/gstvdph264frame.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstvdph264frame.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_vdp_h264_frame_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_vdp_h264_frame_debug
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_vdp_h264_frame_debug, "gstvdph264frame", 0, "Video Frame");
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_vdp_h264_frame_add_slice (GstVdpH264Frame * h264_frame, GstBuffer * buf)
|
||||||
|
{
|
||||||
|
gst_buffer_ref (buf);
|
||||||
|
g_ptr_array_add (h264_frame->slices, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstVdpH264Frame *
|
||||||
|
gst_vdp_h264_frame_new (void)
|
||||||
|
{
|
||||||
|
GstVdpH264Frame *frame;
|
||||||
|
|
||||||
|
frame = (GstVdpH264Frame *) gst_mini_object_new (GST_TYPE_VDP_H264_FRAME);
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObjectClass *gst_vdp_h264_frame_parent_class;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_frame_finalize (GstVdpH264Frame * h264_frame)
|
||||||
|
{
|
||||||
|
g_ptr_array_unref (h264_frame->slices);
|
||||||
|
|
||||||
|
GST_MINI_OBJECT_CLASS (gst_vdp_h264_frame_parent_class)->finalize
|
||||||
|
(GST_MINI_OBJECT (h264_frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_frame_init (GstVdpH264Frame * h264_frame, gpointer g_class)
|
||||||
|
{
|
||||||
|
h264_frame->slices = g_ptr_array_new_with_free_func (
|
||||||
|
(GDestroyNotify) gst_buffer_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_h264_frame_class_init (gpointer g_class, gpointer class_data)
|
||||||
|
{
|
||||||
|
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
||||||
|
|
||||||
|
gst_vdp_h264_frame_parent_class = g_type_class_peek_parent (g_class);
|
||||||
|
|
||||||
|
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
||||||
|
gst_vdp_h264_frame_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_vdp_h264_frame_get_type (void)
|
||||||
|
{
|
||||||
|
static GType _gst_vdp_h264_frame_type = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (_gst_vdp_h264_frame_type == 0)) {
|
||||||
|
static const GTypeInfo info = {
|
||||||
|
sizeof (GstVdpH264FrameClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
gst_vdp_h264_frame_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstVdpH264Frame),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_vdp_h264_frame_init,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
_gst_vdp_h264_frame_type = g_type_register_static (GST_TYPE_VIDEO_FRAME,
|
||||||
|
"GstVdpH264Frame", &info, 0);
|
||||||
|
|
||||||
|
DEBUG_INIT ();
|
||||||
|
}
|
||||||
|
return _gst_vdp_h264_frame_type;
|
||||||
|
}
|
60
sys/vdpau/h264/gstvdph264frame.h
Normal file
60
sys/vdpau/h264/gstvdph264frame.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GST_VDP_H264_FRAME_H_
|
||||||
|
#define _GST_VDP_H264_FRAME_H_
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "../basevideodecoder/gstvideoframe.h"
|
||||||
|
|
||||||
|
#include "gsth264parser.h"
|
||||||
|
|
||||||
|
#define GST_TYPE_VDP_H264_FRAME (gst_vdp_h264_frame_get_type())
|
||||||
|
#define GST_IS_VDP_H264_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_H264_FRAME))
|
||||||
|
#define GST_VDP_H264_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_H264_FRAME, GstVdpH264Frame))
|
||||||
|
#define GST_VDP_H264_FRAME_CAST(obj) ((GstVdpH264Frame *)obj)
|
||||||
|
|
||||||
|
#define GST_VDP_H264_FRAME_GOT_PRIMARY GST_VIDEO_FRAME_FLAG_LAST
|
||||||
|
|
||||||
|
typedef struct _GstVdpH264Frame GstVdpH264Frame;
|
||||||
|
typedef struct _GstVdpH264FrameClass GstVdpH264FrameClass;
|
||||||
|
|
||||||
|
struct _GstVdpH264Frame
|
||||||
|
{
|
||||||
|
GstVideoFrame video_frame;
|
||||||
|
|
||||||
|
GstH264Slice slice_hdr;
|
||||||
|
|
||||||
|
GPtrArray *slices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVdpH264FrameClass
|
||||||
|
{
|
||||||
|
GstVideoFrameClass video_frame_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
void gst_vdp_h264_frame_add_slice (GstVdpH264Frame *h264_frame, GstBuffer *buf);
|
||||||
|
|
||||||
|
GstVdpH264Frame *gst_vdp_h264_frame_new (void);
|
||||||
|
|
||||||
|
GType gst_vdp_h264_frame_get_type (void);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue