diff options
author | Edward Hervey <bilboed@bilboed.com> | 2012-09-20 19:03:11 +0200 |
---|---|---|
committer | Edward Hervey <edward@collabora.com> | 2013-03-31 19:05:31 +0200 |
commit | e3c71c65fe86b9810024980f19a422016eaf0b3c (patch) | |
tree | 52186abdca4d52f464abb15bb4f80fa2ddf7f6c8 /sys/vdpau/h264 | |
parent | 2296296a51450c2db5581a09b9707a95fa149153 (diff) |
vdpau: Port to 1.0
New base class for vdpau decoders
* mpeg2 ported and activated
* h264 ported but deactivated
* Uses GstMpegVideo meta
Diffstat (limited to 'sys/vdpau/h264')
-rw-r--r-- | sys/vdpau/h264/gsth264dpb.c | 50 | ||||
-rw-r--r-- | sys/vdpau/h264/gsth264dpb.h | 25 | ||||
-rw-r--r-- | sys/vdpau/h264/gsth264frame.c | 105 | ||||
-rw-r--r-- | sys/vdpau/h264/gsth264frame.h | 65 | ||||
-rw-r--r-- | sys/vdpau/h264/gsth264parser.c | 1253 | ||||
-rw-r--r-- | sys/vdpau/h264/gsth264parser.h | 420 | ||||
-rw-r--r-- | sys/vdpau/h264/gstnalreader.c | 503 | ||||
-rw-r--r-- | sys/vdpau/h264/gstnalreader.h | 99 | ||||
-rw-r--r-- | sys/vdpau/h264/gstvdph264dec.c | 822 | ||||
-rw-r--r-- | sys/vdpau/h264/gstvdph264dec.h | 20 |
10 files changed, 305 insertions, 3057 deletions
diff --git a/sys/vdpau/h264/gsth264dpb.c b/sys/vdpau/h264/gsth264dpb.c index a557673a8b..9676315fe3 100644 --- a/sys/vdpau/h264/gsth264dpb.c +++ b/sys/vdpau/h264/gsth264dpb.c @@ -19,6 +19,7 @@ */ #include "gsth264dpb.h" +#include "gstvdpvideomemory.h" /* Properties */ enum @@ -32,8 +33,8 @@ GST_DEBUG_CATEGORY_STATIC (h264dpb_debug); #define GST_CAT_DEFAULT h264dpb_debug #define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (h264dpb_debug, "h264dpb", 0, \ - "H264 DPB"); + GST_DEBUG_CATEGORY_INIT (h264dpb_debug, "vdph264dpb", 0, \ + "VDPAU H264 DPB"); G_DEFINE_TYPE_WITH_CODE (GstH264DPB, gst_h264_dpb, G_TYPE_OBJECT, DEBUG_INIT); @@ -47,10 +48,11 @@ gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb, frames = dpb->frames; for (i = 0; i < dpb->n_frames; i++) { GstH264Frame *frame = frames[i]; + GstVdpVideoMemory *vmem = + (GstVdpVideoMemory *) gst_buffer_get_memory (frame->frame-> + output_buffer, 0); - reference_frames[i].surface = - GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)->src_buffer)-> - surface; + reference_frames[i].surface = vmem->surface; reference_frames[i].is_long_term = frame->is_long_term; reference_frames[i].top_is_reference = frame->is_reference; @@ -62,8 +64,12 @@ gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb, for (i = dpb->n_frames; i < 16; i++) { reference_frames[i].surface = VDP_INVALID_HANDLE; + reference_frames[i].is_long_term = FALSE; reference_frames[i].top_is_reference = VDP_FALSE; reference_frames[i].bottom_is_reference = VDP_FALSE; + reference_frames[i].field_order_cnt[0] = 0; + reference_frames[i].field_order_cnt[1] = 0; + reference_frames[i].frame_idx = 0; } } @@ -74,7 +80,7 @@ gst_h264_dpb_remove (GstH264DPB * dpb, guint idx) guint i; frames = dpb->frames; - gst_video_frame_unref (GST_VIDEO_FRAME_CAST (frames[idx])); + gst_video_codec_frame_unref (frames[idx]->frame); dpb->n_frames--; for (i = idx; i < dpb->n_frames; i++) @@ -87,7 +93,7 @@ gst_h264_dpb_output (GstH264DPB * dpb, guint idx) GstFlowReturn ret; GstH264Frame *frame = dpb->frames[idx]; - gst_video_frame_ref (GST_VIDEO_FRAME_CAST (frame)); + gst_video_codec_frame_ref (frame->frame); ret = dpb->output (dpb, frame, dpb->user_data); frame->output_needed = FALSE; @@ -132,7 +138,7 @@ gst_h264_dpb_bump (GstH264DPB * dpb, guint poc, GstFlowReturn * ret) GstFlowReturn gst_h264_dpb_add (GstH264DPB * dpb, GstH264Frame * h264_frame) { - GstFlowReturn ret; + GstFlowReturn ret = GST_FLOW_OK; GST_DEBUG ("add frame with poc: %d", h264_frame->poc); @@ -141,18 +147,13 @@ gst_h264_dpb_add (GstH264DPB * dpb, GstH264Frame * h264_frame) h264_frame->is_reference = FALSE; if (h264_frame->is_reference) { - - ret = GST_FLOW_OK; while (dpb->n_frames == dpb->max_frames) { - if (!gst_h264_dpb_bump (dpb, G_MAXUINT, &ret)) { - GST_ERROR_OBJECT (dpb, "Couldn't make room in DPB"); - return GST_FLOW_OK; - } + if (!gst_h264_dpb_bump (dpb, G_MAXUINT, &ret)) + goto no_room; } + GST_DEBUG ("Storing frame in slot %d", dpb->n_frames); dpb->frames[dpb->n_frames++] = h264_frame; - } - - else { + } else { while (gst_h264_dpb_bump (dpb, h264_frame->poc, &ret)) { if (ret != GST_FLOW_OK) return ret; @@ -162,13 +163,19 @@ gst_h264_dpb_add (GstH264DPB * dpb, GstH264Frame * h264_frame) } return ret; + + /* ERRORS */ +no_room: + { + GST_ERROR_OBJECT (dpb, "Couldn't make room in DPB"); + return GST_FLOW_OK; + } } void gst_h264_dpb_flush (GstH264DPB * dpb, gboolean output) { GstFlowReturn ret; - GstVideoFrame **frames; guint i; GST_DEBUG ("flush"); @@ -176,9 +183,8 @@ gst_h264_dpb_flush (GstH264DPB * dpb, gboolean output) if (output) while (gst_h264_dpb_bump (dpb, G_MAXUINT, &ret)); - frames = (GstVideoFrame **) dpb->frames; for (i = 0; i < dpb->n_frames; i++) - gst_video_frame_unref (frames[i]); + gst_video_codec_frame_unref (dpb->frames[i]->frame); dpb->n_frames = 0; @@ -383,12 +389,10 @@ static void gst_h264_dpb_finalize (GObject * object) { GstH264DPB *dpb = GST_H264_DPB (object); - GstVideoFrame **frames; guint i; - frames = (GstVideoFrame **) dpb->frames; for (i = 0; i < dpb->n_frames; i++) - gst_video_frame_unref (frames[i]); + gst_video_codec_frame_unref (dpb->frames[i]->frame); G_OBJECT_CLASS (gst_h264_dpb_parent_class)->finalize (object); } diff --git a/sys/vdpau/h264/gsth264dpb.h b/sys/vdpau/h264/gsth264dpb.h index a68904c5ae..81956390d8 100644 --- a/sys/vdpau/h264/gsth264dpb.h +++ b/sys/vdpau/h264/gsth264dpb.h @@ -22,16 +22,15 @@ #define _GST_H264_DPB_H_ #include <glib-object.h> +#include <vdpau/vdpau.h> -#include "../gstvdp/gstvdpvideobuffer.h" - -#include "gsth264frame.h" +#include <gst/video/video.h> +#include <gst/codecparsers/gsth264meta.h> G_BEGIN_DECLS #define MAX_DPB_SIZE 16 - #define GST_TYPE_H264_DPB (gst_h264_dpb_get_type ()) #define GST_H264_DPB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_H264_DPB, GstH264DPB)) #define GST_H264_DPB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_H264_DPB, GstH264DPBClass)) @@ -42,21 +41,33 @@ G_BEGIN_DECLS typedef struct _GstH264DPB GstH264DPB; typedef struct _GstH264DPBClass GstH264DPBClass; +typedef struct _GstH264Frame +{ + GstVideoCodecFrame *frame; + + guint poc; + guint16 frame_idx; + gboolean is_reference; + gboolean is_long_term; + gboolean output_needed; +} GstH264Frame; + + typedef GstFlowReturn (*GstH264DPBOutputFunc) (GstH264DPB *dpb, GstH264Frame *h264_frame, gpointer user_data); struct _GstH264DPB { GObject parent_instance; - /* private */ + /* private */ GstH264Frame *frames[MAX_DPB_SIZE]; guint n_frames; guint max_frames; gint max_longterm_frame_idx; - GstH264DPBOutputFunc output; - gpointer user_data; + GstH264DPBOutputFunc output; + gpointer user_data; }; struct _GstH264DPBClass diff --git a/sys/vdpau/h264/gsth264frame.c b/sys/vdpau/h264/gsth264frame.c deleted file mode 100644 index e13d7c9174..0000000000 --- a/sys/vdpau/h264/gsth264frame.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -* 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., 51 Franklin St, Fifth Floor, -* Boston, MA 02110-1301, USA. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gsth264frame.h" - -GST_DEBUG_CATEGORY_STATIC (gst_h264_frame_debug); -#define GST_CAT_DEFAULT gst_h264_frame_debug - -#define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_h264_frame_debug, "gsth264frame", 0, "H264 Frame"); - -void -gst_h264_frame_add_slice (GstH264Frame * h264_frame, GstBuffer * buf) -{ - gst_buffer_ref (buf); - g_ptr_array_add (h264_frame->slices, buf); -} - -GstH264Frame * -gst_h264_frame_new (void) -{ - GstH264Frame *frame; - - frame = (GstH264Frame *) gst_mini_object_new (GST_TYPE_H264_FRAME); - - return frame; -} - -static GObjectClass *gst_h264_frame_parent_class; - -static void -gst_h264_frame_finalize (GstH264Frame * h264_frame) -{ - g_ptr_array_foreach (h264_frame->slices, (GFunc) gst_buffer_unref, NULL); - - g_ptr_array_unref (h264_frame->slices); - - GST_MINI_OBJECT_CLASS (gst_h264_frame_parent_class)->finalize - (GST_MINI_OBJECT (h264_frame)); -} - -static void -gst_h264_frame_init (GstH264Frame * h264_frame, gpointer g_class) -{ - h264_frame->slices = g_ptr_array_new (); -} - -static void -gst_h264_frame_class_init (gpointer g_class, gpointer class_data) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); - - gst_h264_frame_parent_class = g_type_class_peek_parent (g_class); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - gst_h264_frame_finalize; -} - - -GType -gst_h264_frame_get_type (void) -{ - static GType _gst_h264_frame_type = 0; - - if (G_UNLIKELY (_gst_h264_frame_type == 0)) { - static const GTypeInfo info = { - sizeof (GstH264FrameClass), - NULL, - NULL, - gst_h264_frame_class_init, - NULL, - NULL, - sizeof (GstH264Frame), - 0, - (GInstanceInitFunc) gst_h264_frame_init, - NULL - }; - _gst_h264_frame_type = g_type_register_static (GST_TYPE_VIDEO_FRAME, - "GstH264Frame", &info, 0); - - DEBUG_INIT (); - } - return _gst_h264_frame_type; -} diff --git a/sys/vdpau/h264/gsth264frame.h b/sys/vdpau/h264/gsth264frame.h deleted file mode 100644 index 10c185a5b8..0000000000 --- a/sys/vdpau/h264/gsth264frame.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -* 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., 51 Franklin St, Fifth Floor, -* Boston, MA 02110-1301, USA. -*/ - -#ifndef _GST_H264_FRAME_H_ -#define _GST_H264_FRAME_H_ - -#include <gst/gst.h> - -#include "../basevideodecoder/gstvideoframe.h" - -#include "gsth264parser.h" - -#define GST_TYPE_H264_FRAME (gst_h264_frame_get_type()) -#define GST_IS_H264_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_H264_FRAME)) -#define GST_H264_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_H264_FRAME, GstH264Frame)) -#define GST_H264_FRAME_CAST(obj) ((GstH264Frame *)obj) - -#define GST_H264_FRAME_GOT_PRIMARY GST_VIDEO_FRAME_FLAG_LAST - -typedef struct _GstH264Frame GstH264Frame; -typedef struct _GstH264FrameClass GstH264FrameClass; - -struct _GstH264Frame -{ - GstVideoFrame video_frame; - - GstH264Slice slice_hdr; - GPtrArray *slices; - - guint poc; - guint16 frame_idx; - gboolean is_reference; - gboolean is_long_term; - gboolean output_needed; -}; - -struct _GstH264FrameClass -{ - GstVideoFrameClass video_frame_class; -}; - -void gst_h264_frame_add_slice (GstH264Frame *h264_frame, GstBuffer *buf); - -GstH264Frame *gst_h264_frame_new (void); - -GType gst_h264_frame_get_type (void); - -#endif
\ No newline at end of file diff --git a/sys/vdpau/h264/gsth264parser.c b/sys/vdpau/h264/gsth264parser.c deleted file mode 100644 index 2b7c73e56b..0000000000 --- a/sys/vdpau/h264/gsth264parser.c +++ /dev/null @@ -1,1253 +0,0 @@ -/* 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <string.h> - -#include "gstnalreader.h" - -#include "gsth264parser.h" - -/* default scaling_lists according to Table 7-2 */ -const guint8 default_4x4_intra[16] = - { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, - 32, 37, 37, 42 -}; - -const guint8 default_4x4_inter[16] = - { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, - 27, 30, 30, 34 -}; - -const guint8 default_8x8_intra[64] = - { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, - 18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, - 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, 33, - 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 -}; - -const guint8 default_8x8_inter[64] = - { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, - 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, - 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 28, - 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 -}; - -const guint8 zigzag_8x8[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - -const guint8 zigzag_4x4[16] = { - 0, 1, 4, 8, - 5, 2, 3, 6, - 9, 12, 13, 10, - 7, 11, 14, 15, -}; - -#define CHECK_ALLOWED(val, min, max) { \ - if (val < min || val > max) { \ - GST_WARNING ("value not in allowed range. value: %d, range %d-%d", \ - val, min, max); \ - goto error; \ - } \ -} - -#define READ_UINT8(reader, val, nbits) { \ - if (!gst_nal_reader_get_bits_uint8 (reader, &val, nbits)) { \ - GST_WARNING ("failed to read uint8, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT16(reader, val, nbits) { \ - if (!gst_nal_reader_get_bits_uint16 (reader, &val, nbits)) { \ - GST_WARNING ("failed to read uint16, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT32(reader, val, nbits) { \ - if (!gst_nal_reader_get_bits_uint32 (reader, &val, nbits)) { \ - GST_WARNING ("failed to read uint32, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT64(reader, val, nbits) { \ - if (!gst_nal_reader_get_bits_uint64 (reader, &val, nbits)) { \ - GST_WARNING ("failed to read uint32, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UE(reader, val) { \ - if (!gst_nal_reader_get_ue (reader, &val)) { \ - GST_WARNING ("failed to read UE"); \ - goto error; \ - } \ -} - -#define READ_UE_ALLOWED(reader, val, min, max) { \ - guint32 tmp; \ - READ_UE (reader, tmp); \ - CHECK_ALLOWED (tmp, min, max); \ - val = tmp; \ -} - -#define READ_SE(reader, val) { \ - if (!gst_nal_reader_get_se (reader, &val)) { \ - GST_WARNING ("failed to read SE"); \ - goto error; \ - } \ -} - -#define READ_SE_ALLOWED(reader, val, min, max) { \ - gint32 tmp; \ - READ_SE (reader, tmp); \ - CHECK_ALLOWED (tmp, min, max); \ - val = tmp; \ -} - -GST_DEBUG_CATEGORY_STATIC (h264parser_debug); -#define GST_CAT_DEFAULT h264parser_debug - -#define _do_init \ - GST_DEBUG_CATEGORY_INIT (h264parser_debug, "h264parser", 0, \ - "H264 parser"); - -G_DEFINE_TYPE_WITH_CODE (GstH264Parser, gst_h264_parser, G_TYPE_OBJECT, - _do_init); - -static void -gst_h264_sequence_free (void *data) -{ - g_slice_free (GstH264Sequence, data); -} - -static gboolean -gst_h264_parse_hrd_parameters (GstH264HRDParameters * hrd, - GstNalReader * reader) -{ - guint SchedSelIdx; - - GST_DEBUG ("parsing \"HRD Parameters\""); - - READ_UE_ALLOWED (reader, hrd->cpb_cnt_minus1, 0, 31); - READ_UINT8 (reader, hrd->bit_rate_scale, 4); - READ_UINT8 (reader, hrd->cpb_size_scale, 4); - - for (SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - READ_UE (reader, hrd->bit_rate_value_minus1[SchedSelIdx]); - READ_UE (reader, hrd->cpb_size_value_minus1[SchedSelIdx]); - } - - READ_UINT8 (reader, hrd->initial_cpb_removal_delay_length_minus1, 5); - READ_UINT8 (reader, hrd->cpb_removal_delay_length_minus1, 5); - READ_UINT8 (reader, hrd->dpb_output_delay_length_minus1, 5); - READ_UINT8 (reader, hrd->time_offset_length, 5); - - return TRUE; - -error: - GST_WARNING ("error parsing \"HRD Parameters\""); - return FALSE; - -} - -static gboolean -gst_h264_parse_vui_parameters (GstH264VUIParameters * vui, - GstNalReader * reader) -{ - guint8 aspect_ratio_info_present_flag; - guint8 video_signal_type_present_flag; - guint8 chroma_loc_info_present_flag; - - GST_DEBUG ("parsing \"VUI Parameters\""); - - /* set default values for fields that might not be present in the bitstream - and have valid defaults */ - vui->aspect_ratio_idc = 0; - vui->video_format = 5; - vui->video_full_range_flag = 0; - vui->colour_primaries = 2; - vui->transfer_characteristics = 2; - vui->matrix_coefficients = 2; - vui->chroma_sample_loc_type_top_field = 0; - vui->chroma_sample_loc_type_bottom_field = 0; - vui->low_delay_hrd_flag = 0; - - READ_UINT8 (reader, aspect_ratio_info_present_flag, 1); - if (aspect_ratio_info_present_flag) { - READ_UINT8 (reader, vui->aspect_ratio_idc, 8); - if (vui->aspect_ratio_idc == 255) { - READ_UINT16 (reader, vui->sar_width, 16); - READ_UINT16 (reader, vui->sar_height, 16); - } - } - - READ_UINT8 (reader, vui->overscan_info_present_flag, 1); - if (vui->overscan_info_present_flag) - READ_UINT8 (reader, vui->overscan_appropriate_flag, 1); - - READ_UINT8 (reader, video_signal_type_present_flag, 1); - if (video_signal_type_present_flag) { - guint8 colour_description_present_flag; - - READ_UINT8 (reader, vui->video_format, 3); - READ_UINT8 (reader, vui->video_full_range_flag, 1); - READ_UINT8 (reader, colour_description_present_flag, 1); - if (colour_description_present_flag) { - READ_UINT8 (reader, vui->colour_primaries, 8); - READ_UINT8 (reader, vui->transfer_characteristics, 8); - READ_UINT8 (reader, vui->matrix_coefficients, 8); - } - } - - READ_UINT8 (reader, chroma_loc_info_present_flag, 1); - if (chroma_loc_info_present_flag) { - READ_UE_ALLOWED (reader, vui->chroma_sample_loc_type_top_field, 0, 5); - READ_UE_ALLOWED (reader, vui->chroma_sample_loc_type_bottom_field, 0, 5); - } - - READ_UINT8 (reader, vui->timing_info_present_flag, 1); - if (vui->timing_info_present_flag) { - READ_UINT32 (reader, vui->num_units_in_tick, 32); - if (vui->num_units_in_tick == 0) - GST_WARNING - ("num_units_in_tick = 0 detected in stream (incompliant to H.264 E.2.1)."); - - READ_UINT32 (reader, vui->time_scale, 32); - if (vui->time_scale == 0) - GST_WARNING - ("time_scale = 0 detected in stream (incompliant to H.264 E.2.1)."); - - READ_UINT8 (reader, vui->fixed_frame_rate_flag, 1); - } - - READ_UINT8 (reader, vui->nal_hrd_parameters_present_flag, 1); - if (vui->nal_hrd_parameters_present_flag) { - if (!gst_h264_parse_hrd_parameters (&vui->nal_hrd_parameters, reader)) - goto error; - } - - READ_UINT8 (reader, vui->vcl_hrd_parameters_present_flag, 1); - if (vui->vcl_hrd_parameters_present_flag) { - if (!gst_h264_parse_hrd_parameters (&vui->vcl_hrd_parameters, reader)) - goto error; - } - - if (vui->nal_hrd_parameters_present_flag || - vui->vcl_hrd_parameters_present_flag) - READ_UINT8 (reader, vui->low_delay_hrd_flag, 1); - - READ_UINT8 (reader, vui->pic_struct_present_flag, 1); - - return TRUE; - -error: - GST_WARNING ("error parsing \"VUI Parameters\""); - return FALSE; -} - -static gboolean -gst_h264_parser_parse_scaling_list (GstNalReader * reader, - guint8 scaling_lists_4x4[6][16], guint8 scaling_lists_8x8[6][64], - const guint8 fallback_4x4_inter[16], const guint8 fallback_4x4_intra[16], - const guint8 fallback_8x8_inter[64], const guint8 fallback_8x8_intra[64], - guint8 n_lists) -{ - guint i; - - GST_DEBUG ("parsing scaling lists"); - - for (i = 0; i < 12; i++) { - gboolean use_default = FALSE; - - if (i < n_lists) { - guint8 scaling_list_present_flag; - - READ_UINT8 (reader, scaling_list_present_flag, 1); - if (scaling_list_present_flag) { - guint8 *scaling_list; - const guint8 *scan; - guint size; - guint j; - guint8 last_scale, next_scale; - - if (i < 6) { - scaling_list = scaling_lists_4x4[i]; - scan = zigzag_4x4; - size = 16; - } else { - scaling_list = scaling_lists_8x8[i - 6]; - scan = zigzag_8x8; - size = 64; - } - - last_scale = 8; - next_scale = 8; - for (j = 0; j < size; j++) { - if (next_scale != 0) { - gint32 delta_scale; - - READ_SE (reader, delta_scale); - next_scale = (last_scale + delta_scale) & 0xff; - } - if (j == 0 && next_scale == 0) { - use_default = TRUE; - break; - } - last_scale = scaling_list[scan[j]] = - (next_scale == 0) ? last_scale : next_scale; - } - } else - use_default = TRUE; - } else - use_default = TRUE; - - if (use_default) { - switch (i) { - case 0: - memcpy (scaling_lists_4x4[0], fallback_4x4_intra, 16); - break; - case 1: - memcpy (scaling_lists_4x4[1], scaling_lists_4x4[0], 16); - break; - case 2: - memcpy (scaling_lists_4x4[2], scaling_lists_4x4[1], 16); - break; - case 3: - memcpy (scaling_lists_4x4[3], fallback_4x4_inter, 16); - break; - case 4: - memcpy (scaling_lists_4x4[4], scaling_lists_4x4[3], 16); - break; - case 5: - memcpy (scaling_lists_4x4[5], scaling_lists_4x4[4], 16); - break; - case 6: - memcpy (scaling_lists_8x8[0], fallback_8x8_intra, 64); - break; - case 7: - memcpy (scaling_lists_8x8[1], fallback_8x8_inter, 64); - break; - case 8: - memcpy (scaling_lists_8x8[2], scaling_lists_8x8[0], 64); - break; - case 9: - memcpy (scaling_lists_8x8[3], scaling_lists_8x8[1], 64); - break; - case 10: - memcpy (scaling_lists_8x8[4], scaling_lists_8x8[2], 64); - break; - case 11: - memcpy (scaling_lists_8x8[5], scaling_lists_8x8[3], 64); - break; - - default: - break; - } - } - } - - return TRUE; - -error: - - GST_WARNING ("error parsing scaling lists"); - return FALSE; -} - -GstH264Sequence * -gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data, - guint size) -{ - GstNalReader reader = GST_NAL_READER_INIT (data, size); - GstH264Sequence *seq; - guint8 frame_cropping_flag; - - g_return_val_if_fail (GST_IS_H264_PARSER (parser), NULL); - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (size > 0, NULL); - - GST_DEBUG ("parsing \"Sequence parameter set\""); - - seq = g_slice_new (GstH264Sequence); - - /* set default values for fields that might not be present in the bitstream - and have valid defaults */ - seq->chroma_format_idc = 1; - seq->separate_colour_plane_flag = 0; - seq->bit_depth_luma_minus8 = 0; - seq->bit_depth_chroma_minus8 = 0; - memset (seq->scaling_lists_4x4, 16, 96); - memset (seq->scaling_lists_8x8, 16, 384); - seq->mb_adaptive_frame_field_flag = 0; - seq->frame_crop_left_offset = 0; - seq->frame_crop_right_offset = 0; - seq->frame_crop_top_offset = 0; - seq->frame_crop_bottom_offset = 0; - - READ_UINT8 (&reader, seq->profile_idc, 8); - READ_UINT8 (&reader, seq->constraint_set0_flag, 1); - READ_UINT8 (&reader, seq->constraint_set1_flag, 1); - READ_UINT8 (&reader, seq->constraint_set2_flag, 1); - READ_UINT8 (&reader, seq->constraint_set3_flag, 1); - - /* skip reserved_zero_4bits */ - if (!gst_nal_reader_skip (&reader, 4)) - goto error; - - READ_UINT8 (&reader, seq->level_idc, 8); - - READ_UE_ALLOWED (&reader, seq->id, 0, 31); - - if (seq->profile_idc == 100 || seq->profile_idc == 110 || - seq->profile_idc == 122 || seq->profile_idc == 244 || - seq->profile_idc == 44 || seq->profile_idc == 83 || - seq->profile_idc == 86) { - READ_UE_ALLOWED (&reader, seq->chroma_format_idc, 0, 3); - if (seq->chroma_format_idc == 3) - READ_UINT8 (&reader, seq->separate_colour_plane_flag, 1); - - READ_UE_ALLOWED (&reader, seq->bit_depth_luma_minus8, 0, 6); - READ_UE_ALLOWED (&reader, seq->bit_depth_chroma_minus8, 0, 6); - READ_UINT8 (&reader, seq->qpprime_y_zero_transform_bypass_flag, 1); - - READ_UINT8 (&reader, seq->scaling_matrix_present_flag, 1); - if (seq->scaling_matrix_present_flag) { - guint8 n_lists; - - n_lists = (seq->chroma_format_idc != 3) ? 8 : 12; - if (!gst_h264_parser_parse_scaling_list (&reader, - seq->scaling_lists_4x4, seq->scaling_lists_8x8, - default_4x4_inter, default_4x4_intra, - default_8x8_inter, default_8x8_intra, n_lists)) - goto error; - } - } - - READ_UE_ALLOWED (&reader, seq->log2_max_frame_num_minus4, 0, 12); - /* calculate MaxFrameNum */ - seq->MaxFrameNum = 1 << (seq->log2_max_frame_num_minus4 + 4); - - READ_UE_ALLOWED (&reader, seq->pic_order_cnt_type, 0, 2); - if (seq->pic_order_cnt_type == 0) { - READ_UE_ALLOWED (&reader, seq->log2_max_pic_order_cnt_lsb_minus4, 0, 12); - } else if (seq->pic_order_cnt_type == 1) { - guint i; - - READ_UINT8 (&reader, seq->delta_pic_order_always_zero_flag, 1); - READ_SE (&reader, seq->offset_for_non_ref_pic); - READ_SE (&reader, seq->offset_for_top_to_bottom_field); - READ_UE_ALLOWED (&reader, seq->num_ref_frames_in_pic_order_cnt_cycle, 0, - 255); - for (i = 0; i < seq->num_ref_frames_in_pic_order_cnt_cycle; i++) - READ_SE (&reader, seq->offset_for_ref_frame[i]); - } - - READ_UE (&reader, seq->num_ref_frames); - READ_UINT8 (&reader, seq->gaps_in_frame_num_value_allowed_flag, 1); - READ_UE (&reader, seq->pic_width_in_mbs_minus1); - READ_UE (&reader, seq->pic_height_in_map_units_minus1); - READ_UINT8 (&reader, seq->frame_mbs_only_flag, 1); - - if (!seq->frame_mbs_only_flag) - READ_UINT8 (&reader, seq->mb_adaptive_frame_field_flag, 1); - - READ_UINT8 (&reader, seq->direct_8x8_inference_flag, 1); - READ_UINT8 (&reader, frame_cropping_flag, 1); - if (frame_cropping_flag) { - READ_UE (&reader, seq->frame_crop_left_offset); - READ_UE (&reader, seq->frame_crop_right_offset); - READ_UE (&reader, seq->frame_crop_top_offset); - READ_UE (&reader, seq->frame_crop_bottom_offset); - } - - READ_UINT8 (&reader, seq->vui_parameters_present_flag, 1); - if (seq->vui_parameters_present_flag) { - if (!gst_h264_parse_vui_parameters (&seq->vui_parameters, &reader)) - goto error; - } - - /* calculate ChromaArrayType */ - if (seq->separate_colour_plane_flag) - seq->ChromaArrayType = 0; - else - seq->ChromaArrayType = seq->chroma_format_idc; - - GST_DEBUG ("adding sequence parameter set with id: %d to hash table", - seq->id); - g_hash_table_replace (parser->sequences, &seq->id, seq); - return seq; - -error: - GST_WARNING ("error parsing \"Sequence parameter set\""); - - gst_h264_sequence_free (seq); - return NULL; -} - -static void -gst_h264_picture_free (void *data) -{ - GstH264Picture *pic = (GstH264Picture *) data; - - if (pic->slice_group_id) - g_free (pic->slice_group_id); - - g_slice_free (GstH264Picture, data); -} - -static gboolean -gst_h264_parser_more_data (GstNalReader * reader) -{ - guint remaining; - - remaining = gst_nal_reader_get_remaining (reader); - if (remaining == 0) - return FALSE; - - if (remaining <= 8) { - guint8 rbsp_stop_one_bit; - - if (!gst_nal_reader_peek_bits_uint8 (reader, &rbsp_stop_one_bit, 1)) - return FALSE; - - if (rbsp_stop_one_bit == 1) { - guint8 zero_bits; - - if (remaining == 1) - return FALSE; - - if (!gst_nal_reader_peek_bits_uint8 (reader, &zero_bits, remaining)) - return FALSE; - - if ((zero_bits - (1 << (remaining - 1))) == 0) - return FALSE; - } - } - - return TRUE; -} - -GstH264Picture * -gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data, - guint size) -{ - GstNalReader reader = GST_NAL_READER_INIT (data, size); - GstH264Picture *pic; - gint seq_parameter_set_id; - GstH264Sequence *seq; - guint8 pic_scaling_matrix_present_flag; - - g_return_val_if_fail (GST_IS_H264_PARSER (parser), NULL); - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (size > 0, NULL); - - GST_DEBUG ("parsing \"Picture parameter set\""); - - pic = g_slice_new (GstH264Picture); - - READ_UE_ALLOWED (&reader, pic->id, 0, 255); - READ_UE_ALLOWED (&reader, seq_parameter_set_id, 0, 31); - seq = g_hash_table_lookup (parser->sequences, &seq_parameter_set_id); - if (!seq) { - GST_WARNING ("couldn't find associated sequence parameter set with id: %d", - seq_parameter_set_id); - goto error; - } - pic->sequence = seq; - - /* set default values for fields that might not be present in the bitstream - and have valid defaults */ - pic->slice_group_id = NULL; - pic->transform_8x8_mode_flag = 0; - memcpy (&pic->scaling_lists_4x4, &seq->scaling_lists_4x4, 96); - memcpy (&pic->scaling_lists_8x8, &seq->scaling_lists_8x8, 384); - - READ_UINT8 (&reader, pic->entropy_coding_mode_flag, 1); - READ_UINT8 (&reader, pic->pic_order_present_flag, 1); - READ_UE_ALLOWED (&reader, pic->num_slice_groups_minus1, 0, 7); - if (pic->num_slice_groups_minus1 > 0) { - READ_UE_ALLOWED (&reader, pic->slice_group_map_type, 0, 6); - if (pic->slice_group_map_type == 0) { - gint i; - - for (i = 0; i <= pic->num_slice_groups_minus1; i++) - READ_UE (&reader, pic->run_length_minus1[i]); - } else if (pic->slice_group_map_type == 2) { - gint i; - - for (i = 0; i <= pic->num_slice_groups_minus1; i++) { - READ_UE (&reader, pic->top_left[i]); - READ_UE (&reader, pic->bottom_right[i]); - } - } else if (pic->slice_group_map_type >= 3 && pic->slice_group_map_type <= 5) { - READ_UINT8 (&reader, pic->slice_group_change_direction_flag, 1); - READ_UE (&reader, pic->slice_group_change_rate_minus1); - } else if (pic->slice_group_map_type == 6) { - gint bits; - gint i; - - READ_UE (&reader, pic->pic_size_in_map_units_minus1); - bits = g_bit_storage (pic->num_slice_groups_minus1); - - pic->slice_group_id = - g_new (guint8, pic->pic_size_in_map_units_minus1 + 1); - for (i = 0; i <= pic->pic_size_in_map_units_minus1; i++) - READ_UINT8 (&reader, pic->slice_group_id[i], bits); - } - } - - READ_UE_ALLOWED (&reader, pic->num_ref_idx_l0_active_minus1, 0, 31); - READ_UE_ALLOWED (&reader, pic->num_ref_idx_l1_active_minus1, 0, 31); - READ_UINT8 (&reader, pic->weighted_pred_flag, 1); - READ_UINT8 (&reader, pic->weighted_bipred_idc, 2); - READ_SE_ALLOWED (&reader, pic->pic_init_qp_minus26, -26, 25); - READ_SE_ALLOWED (&reader, pic->pic_init_qs_minus26, -26, 25); - READ_SE_ALLOWED (&reader, pic->chroma_qp_index_offset, -12, 12); - pic->second_chroma_qp_index_offset = pic->chroma_qp_index_offset; - READ_UINT8 (&reader, pic->deblocking_filter_control_present_flag, 1); - READ_UINT8 (&reader, pic->constrained_intra_pred_flag, 1); - READ_UINT8 (&reader, pic->redundant_pic_cnt_present_flag, 1); - - if (!gst_h264_parser_more_data (&reader)) - goto done; - - READ_UINT8 (&reader, pic->transform_8x8_mode_flag, 1); - - READ_UINT8 (&reader, pic_scaling_matrix_present_flag, 1); - if (pic_scaling_matrix_present_flag) { - guint8 n_lists; - - n_lists = 6 + ((seq->chroma_format_idc != 3) ? 2 : 6) * - pic->transform_8x8_mode_flag; - - if (seq->scaling_matrix_present_flag) { - if (!gst_h264_parser_parse_scaling_list (&reader, - pic->scaling_lists_4x4, pic->scaling_lists_8x8, - seq->scaling_lists_4x4[0], seq->scaling_lists_4x4[3], - seq->scaling_lists_8x8[0], seq->scaling_lists_8x8[3], n_lists)) - goto error; - } else { - if (!gst_h264_parser_parse_scaling_list (&reader, - pic->scaling_lists_4x4, pic->scaling_lists_8x8, - default_4x4_inter, default_4x4_intra, - default_8x8_inter, default_8x8_intra, n_lists)) - goto error; - } - } - - READ_SE_ALLOWED (&reader, pic->second_chroma_qp_index_offset, -12, 12); - -done: - GST_DEBUG ("adding picture parameter set with id: %d to hash table", pic->id); - g_hash_table_replace (parser->pictures, &pic->id, pic); - return pic; - -error: - GST_WARNING ("error parsing \"Picture parameter set\""); - - gst_h264_picture_free (pic); - return NULL; -} - -static gboolean -gst_h264_slice_parse_pred_weight_table (GstH264Slice * slice, - GstNalReader * reader, - const GstH264Sequence * seq, const GstH264Picture * pic) -{ - GstH264PredWeightTable *p; - gint i; - - GST_DEBUG ("parsing \"Prediction weight table\""); - - p = &slice->pred_weight_table; - - READ_UE_ALLOWED (reader, p->luma_log2_weight_denom, 0, 7); - /* set default values */ - memset (p->luma_weight_l0, 1 << p->luma_log2_weight_denom, 32); - memset (p->luma_offset_l0, 0, 32); - - if (seq->ChromaArrayType != 0) { - READ_UE_ALLOWED (reader, p->chroma_log2_weight_denom, 0, 7); - /* set default values */ - memset (p->chroma_weight_l0, 1 << p->chroma_log2_weight_denom, 64); - memset (p->chroma_offset_l0, 0, 64); - } - - for (i = 0; i <= slice->num_ref_idx_l0_active_minus1; i++) { - guint8 luma_weight_l0_flag; - - READ_UINT8 (reader, luma_weight_l0_flag, 1); - if (luma_weight_l0_flag) { - READ_SE_ALLOWED (reader, p->luma_weight_l0[i], -128, 127); - READ_SE_ALLOWED (reader, p->luma_offset_l0[i], -128, 127); - } - if (seq->ChromaArrayType != 0) { - guint8 chroma_weight_l0_flag; - gint j; - - READ_UINT8 (reader, chroma_weight_l0_flag, 1); - if (chroma_weight_l0_flag) { - for (j = 0; j < 2; j++) { - READ_SE_ALLOWED (reader, p->chroma_weight_l0[i][j], -128, 127); - READ_SE_ALLOWED (reader, p->chroma_offset_l0[i][j], -128, 127); - } - } - } - } - - if (GST_H264_IS_B_SLICE (slice->type)) { - for (i = 0; i <= slice->num_ref_idx_l1_active_minus1; i++) { - guint8 luma_weight_l1_flag; - - READ_UINT8 (reader, luma_weight_l1_flag, 1); - if (luma_weight_l1_flag) { - READ_SE_ALLOWED (reader, p->luma_weight_l1[i], -128, 127); - READ_SE_ALLOWED (reader, p->luma_offset_l1[i], -128, 127); - } - if (seq->ChromaArrayType != 0) { - guint8 chroma_weight_l1_flag; - gint j; - - READ_UINT8 (reader, chroma_weight_l1_flag, 1); - if (chroma_weight_l1_flag) { - for (j = 0; j < 2; j++) { - READ_SE_ALLOWED (reader, p->chroma_weight_l1[i][j], -128, 127); - READ_SE_ALLOWED (reader, p->chroma_offset_l1[i][j], -128, 127); - } - } - } - } - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Prediction weight table\""); - return FALSE; -} - -static gboolean -gst_h264_slice_parse_ref_pic_list_reordering (GstH264Slice * slice, - GstNalReader * reader) -{ - GST_DEBUG ("parsing \"Reference picture list reordering\""); - - if (!GST_H264_IS_I_SLICE (slice->type) && !GST_H264_IS_SI_SLICE (slice->type)) { - guint8 ref_pic_list_reordering_flag_l0; - guint8 reordering_of_pic_nums_idc; - - READ_UINT8 (reader, ref_pic_list_reordering_flag_l0, 1); - if (ref_pic_list_reordering_flag_l0) - do { - READ_UE_ALLOWED (reader, reordering_of_pic_nums_idc, 0, 3); - if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) { - guint32 abs_diff_pic_num_minus1 G_GNUC_UNUSED; - - READ_UE_ALLOWED (reader, abs_diff_pic_num_minus1, 0, - slice->MaxPicNum - 1); - } else if (reordering_of_pic_nums_idc == 2) { - guint32 long_term_pic_num; - - READ_UE (reader, long_term_pic_num); - } - } while (reordering_of_pic_nums_idc != 3); - } - - if (GST_H264_IS_B_SLICE (slice->type)) { - guint8 ref_pic_list_reordering_flag_l1; - guint8 reordering_of_pic_nums_idc; - - READ_UINT8 (reader, ref_pic_list_reordering_flag_l1, 1); - if (ref_pic_list_reordering_flag_l1) - do { - READ_UE_ALLOWED (reader, reordering_of_pic_nums_idc, 0, 3); - if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) { - guint32 abs_diff_num_minus1; - READ_UE (reader, abs_diff_num_minus1); - } else if (reordering_of_pic_nums_idc == 2) { - guint32 long_term_pic_num; - - READ_UE (reader, long_term_pic_num); - } - } while (reordering_of_pic_nums_idc != 3); - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Reference picture list reordering\""); - return FALSE; -} - -static gboolean -gst_h264_slice_parse_dec_ref_pic_marking (GstH264Slice * slice, - GstNalReader * reader) -{ - GstH264DecRefPicMarking *m; - - GST_DEBUG ("parsing \"Decoded reference picture marking\""); - - m = &slice->dec_ref_pic_marking; - - if (slice->nal_unit.IdrPicFlag) { - READ_UINT8 (reader, m->no_output_of_prior_pics_flag, 1); - READ_UINT8 (reader, m->long_term_reference_flag, 1); - } else { - READ_UINT8 (reader, m->adaptive_ref_pic_marking_mode_flag, 1); - if (m->adaptive_ref_pic_marking_mode_flag) { - guint8 memory_management_control_operation; - - m->n_ref_pic_marking = 0; - while (1) { - READ_UE_ALLOWED (reader, memory_management_control_operation, 0, 6); - if (memory_management_control_operation == 0) - break; - - m->ref_pic_marking[m-> - n_ref_pic_marking].memory_management_control_operation = - memory_management_control_operation; - - if (memory_management_control_operation == 1 || - memory_management_control_operation == 3) - READ_UE (reader, - m->ref_pic_marking[m-> - n_ref_pic_marking].difference_of_pic_nums_minus1); - - if (memory_management_control_operation == 2) - READ_UE (reader, - m->ref_pic_marking[m->n_ref_pic_marking].long_term_pic_num); - - if (memory_management_control_operation == 3 || - memory_management_control_operation == 6) - READ_UE (reader, - m->ref_pic_marking[m->n_ref_pic_marking].long_term_frame_idx); - - if (memory_management_control_operation == 4) - READ_UE (reader, - m->ref_pic_marking[m-> - n_ref_pic_marking].max_long_term_frame_idx_plus1); - - m->n_ref_pic_marking++; - } - } - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Decoded reference picture marking\""); - return FALSE; -} - -gboolean -gst_h264_parser_parse_slice_header (GstH264Parser * parser, - GstH264Slice * slice, guint8 * data, guint size, GstNalUnit nal_unit) -{ - GstNalReader reader = GST_NAL_READER_INIT (data, size); - gint pic_parameter_set_id; - GstH264Picture *pic; - GstH264Sequence *seq; - - g_return_val_if_fail (GST_IS_H264_PARSER (parser), FALSE); - g_return_val_if_fail (slice != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (size > 0, FALSE); - - GST_DEBUG ("parsing \"Slice header\""); - - memcpy (&slice->nal_unit, &nal_unit, sizeof (GstNalUnit)); - - READ_UE (&reader, slice->first_mb_in_slice); - READ_UE (&reader, slice->type); - - READ_UE_ALLOWED (&reader, pic_parameter_set_id, 0, 255); - pic = g_hash_table_lookup (parser->pictures, &pic_parameter_set_id); - if (!pic) { - GST_WARNING ("couldn't find associated picture parameter set with id: %d", - pic_parameter_set_id); - goto error; - } - slice->picture = pic; - seq = pic->sequence; - - /* set default values for fields that might not be present in the bitstream - and have valid defaults */ - slice->field_pic_flag = 0; - slice->bottom_field_flag = 0; - slice->delta_pic_order_cnt_bottom = 0; - slice->delta_pic_order_cnt[0] = 0; - slice->delta_pic_order_cnt[1] = 0; - slice->redundant_pic_cnt = 0; - slice->num_ref_idx_l0_active_minus1 = pic->num_ref_idx_l0_active_minus1; - slice->num_ref_idx_l1_active_minus1 = pic->num_ref_idx_l1_active_minus1; - - if (seq->separate_colour_plane_flag) - READ_UINT8 (&reader, slice->colour_plane_id, 2); - - READ_UINT16 (&reader, slice->frame_num, seq->log2_max_frame_num_minus4 + 4); - - if (!seq->frame_mbs_only_flag) { - READ_UINT8 (&reader, slice->field_pic_flag, 1); - if (slice->field_pic_flag) - READ_UINT8 (&reader, slice->bottom_field_flag, 1); - } - - /* calculate MaxPicNum */ - if (slice->field_pic_flag) - slice->MaxPicNum = seq->MaxFrameNum; - else - slice->MaxPicNum = 2 * seq->MaxFrameNum; - - if (nal_unit.type == 5) - READ_UE_ALLOWED (&reader, slice->idr_pic_id, 0, 65535); - - if (seq->pic_order_cnt_type == 0) { - READ_UINT16 (&reader, slice->pic_order_cnt_lsb, - seq->log2_max_pic_order_cnt_lsb_minus4 + 4); - if (pic->pic_order_present_flag && !slice->field_pic_flag) - READ_SE (&reader, slice->delta_pic_order_cnt_bottom); - } - - if (seq->pic_order_cnt_type == 1 && !seq->delta_pic_order_always_zero_flag) { - READ_SE (&reader, slice->delta_pic_order_cnt[0]); - if (pic->pic_order_present_flag && !slice->field_pic_flag) - READ_SE (&reader, slice->delta_pic_order_cnt[1]); - } - - if (pic->redundant_pic_cnt_present_flag) - READ_UE_ALLOWED (&reader, slice->redundant_pic_cnt, 0, 127); - - if (GST_H264_IS_B_SLICE (slice->type)) - READ_UINT8 (&reader, slice->direct_spatial_mv_pred_flag, 1); - - if (GST_H264_IS_P_SLICE (slice->type) || - GST_H264_IS_SP_SLICE (slice->type) || GST_H264_IS_B_SLICE (slice->type)) { - guint8 num_ref_idx_active_override_flag; - - READ_UINT8 (&reader, num_ref_idx_active_override_flag, 1); - if (num_ref_idx_active_override_flag) { - READ_UE_ALLOWED (&reader, slice->num_ref_idx_l0_active_minus1, 0, 31); - - if (GST_H264_IS_B_SLICE (slice->type)) - READ_UE_ALLOWED (&reader, slice->num_ref_idx_l1_active_minus1, 0, 31); - } - } - - if (!gst_h264_slice_parse_ref_pic_list_reordering (slice, &reader)) - return FALSE; - - if ((pic->weighted_pred_flag && (GST_H264_IS_P_SLICE (slice->type) || - GST_H264_IS_SP_SLICE (slice->type))) - || (pic->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE (slice->type))) { - if (!gst_h264_slice_parse_pred_weight_table (slice, &reader, seq, pic)) - return FALSE; - } - - if (nal_unit.ref_idc != 0) { - if (!gst_h264_slice_parse_dec_ref_pic_marking (slice, &reader)) - return FALSE; - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Slice header\""); - return FALSE; -} - -static gboolean -gst_h264_parser_parse_buffering_period (GstH264Parser * parser, - GstH264BufferingPeriod * per, guint8 * data, guint size) -{ - GstNalReader reader = GST_NAL_READER_INIT (data, size); - - GstH264Sequence *seq; - guint8 seq_parameter_set_id; - - GST_DEBUG ("parsing \"Buffering period\""); - - READ_UE_ALLOWED (&reader, seq_parameter_set_id, 0, 31); - seq = g_hash_table_lookup (parser->sequences, &seq_parameter_set_id); - if (!seq) { - GST_WARNING ("couldn't find associated sequence parameter set with id: %d", - seq_parameter_set_id); - goto error; - } - per->seq = seq; - - if (seq->vui_parameters_present_flag) { - GstH264VUIParameters *vui = &seq->vui_parameters; - - if (vui->nal_hrd_parameters_present_flag) { - GstH264HRDParameters *hrd = &vui->nal_hrd_parameters; - guint8 SchedSelIdx; - - for (SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - READ_UINT8 (&reader, per->nal_initial_cpb_removal_delay[SchedSelIdx], - 5); - READ_UINT8 (&reader, - per->nal_initial_cpb_removal_delay_offset[SchedSelIdx], 5); - } - } - - if (vui->vcl_hrd_parameters_present_flag) { - GstH264HRDParameters *hrd = &vui->vcl_hrd_parameters; - guint8 SchedSelIdx; - - for (SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - READ_UINT8 (&reader, per->vcl_initial_cpb_removal_delay[SchedSelIdx], - 5); - READ_UINT8 (&reader, - per->vcl_initial_cpb_removal_delay_offset[SchedSelIdx], 5); - } - } - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Buffering period\""); - return FALSE; -} - -static gboolean -gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim, - GstH264VUIParameters * vui, GstNalReader * reader) -{ - guint8 full_timestamp_flag; - guint8 time_offset_length; - - GST_DEBUG ("parsing \"Clock timestamp\""); - - /* defalt values */ - tim->time_offset = 0; - - READ_UINT8 (reader, tim->ct_type, 2); - READ_UINT8 (reader, tim->nuit_field_based_flag, 1); - READ_UINT8 (reader, tim->counting_type, 5); - READ_UINT8 (reader, full_timestamp_flag, 1); - READ_UINT8 (reader, tim->discontinuity_flag, 1); - READ_UINT8 (reader, tim->cnt_dropped_flag, 1); - READ_UINT8 (reader, tim->n_frames, 8); - - if (full_timestamp_flag) { - tim->seconds_flag = TRUE; - READ_UINT8 (reader, tim->seconds_value, 6); - - tim->minutes_flag = TRUE; - READ_UINT8 (reader, tim->minutes_value, 6); - - tim->hours_flag = TRUE; - READ_UINT8 (reader, tim->hours_value, 5); - } else { - READ_UINT8 (reader, tim->seconds_flag, 1); - if (tim->seconds_flag) { - READ_UINT8 (reader, tim->seconds_value, 6); - READ_UINT8 (reader, tim->minutes_flag, 1); - if (tim->minutes_flag) { - READ_UINT8 (reader, tim->minutes_value, 6); - READ_UINT8 (reader, tim->hours_flag, 1); - if (tim->hours_flag) - READ_UINT8 (reader, tim->hours_value, 5); - } - } - } - - time_offset_length = 0; - if (vui->nal_hrd_parameters_present_flag) - time_offset_length = vui->nal_hrd_parameters.time_offset_length; - else if (vui->vcl_hrd_parameters_present_flag) - time_offset_length = vui->vcl_hrd_parameters.time_offset_length; - - if (time_offset_length > 0) - READ_UINT32 (reader, tim->time_offset, time_offset_length); - -error: - GST_WARNING ("error parsing \"Clock timestamp\""); - return FALSE; -} - -static gboolean -gst_h264_parser_parse_pic_timing (GstH264Parser * parser, GstH264Sequence * seq, - GstH264PicTiming * tim, guint8 * data, guint size) -{ - GstNalReader reader = GST_NAL_READER_INIT (data, size); - - GST_DEBUG ("parsing \"Picture timing\""); - - if (!seq) { - GST_WARNING ("didn't get the associated sequence paramater set for the " - "current access unit"); - goto error; - } - - /* default values */ - memset (tim->clock_timestamp_flag, 0, 3); - - if (seq->vui_parameters_present_flag) { - GstH264VUIParameters *vui = &seq->vui_parameters; - - if (vui->nal_hrd_parameters_present_flag) { - READ_UINT8 (&reader, tim->cpb_removal_delay, - vui->nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1); - READ_UINT8 (&reader, tim->dpb_output_delay, - vui->nal_hrd_parameters.dpb_output_delay_length_minus1 + 1); - } else if (vui->nal_hrd_parameters_present_flag) { - READ_UINT8 (&reader, tim->cpb_removal_delay, - vui->vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1); - READ_UINT8 (&reader, tim->dpb_output_delay, - vui->vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1); - } - - if (vui->pic_struct_present_flag) { - const guint8 num_clock_ts_table[9] = { - 1, 1, 1, 2, 2, 3, 3, 2, 3 - }; - guint8 NumClockTs; - guint i; - - READ_UINT8 (&reader, tim->pic_struct, 4); - CHECK_ALLOWED (tim->pic_struct, 0, 8); - - NumClockTs = num_clock_ts_table[tim->pic_struct]; - for (i = 0; i < NumClockTs; i++) { - READ_UINT8 (&reader, tim->clock_timestamp_flag[i], 1); - if (tim->clock_timestamp_flag[i]) { - if (!gst_h264_parse_clock_timestamp (&tim->clock_timestamp[i], vui, - &reader)) - goto error; - } - } - } - } - - return TRUE; - -error: - GST_WARNING ("error parsing \"Picture timing\""); - return FALSE; -} - -gboolean -gst_h264_parser_parse_sei_message (GstH264Parser * parser, - GstH264Sequence * seq, GstH264SEIMessage * sei, guint8 * data, guint size) -{ - GstNalReader reader; - - guint32 payloadSize; - guint8 payload_type_byte, payload_size_byte; - - guint8 *payload_data; - guint remaining, payload_size; - gboolean res; - - g_return_val_if_fail (GST_IS_H264_PARSER (parser), FALSE); - g_return_val_if_fail (sei != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (size > 0, FALSE); - - GST_DEBUG ("parsing \"Sei message\""); - - gst_nal_reader_init (&reader, data, size); - - sei->payloadType = 0; - do { - READ_UINT8 (&reader, payload_type_byte, 8); - sei->payloadType += payload_type_byte; - } - while (payload_type_byte == 0xff); - - payloadSize = 0; - do { - READ_UINT8 (&reader, payload_size_byte, 8); - payloadSize += payload_size_byte; - } - while (payload_size_byte == 0xff); - - payload_data = data + gst_nal_reader_get_pos (&reader) * 8; - remaining = gst_nal_reader_get_remaining (&reader) * 8; - payload_size = payloadSize < remaining ? payloadSize : remaining; - - if (sei->payloadType == 0) - res = - gst_h264_parser_parse_buffering_period (parser, - &sei->buffering_period, payload_data, payload_size); - else if (sei->payloadType == 1) - res = gst_h264_parser_parse_pic_timing (parser, seq, &sei->pic_timing, - payload_data, payload_size); - else - res = TRUE; - - return res; - -error: - GST_WARNING ("error parsing \"Sei message\""); - return FALSE; -} - -#undef CHECK_ALLOWED -#undef READ_UINT8 -#undef READ_UINT16 -#undef READ_UINT32 -#undef READ_UINT64 -#undef READ_UE -#undef READ_UE_ALLOWED -#undef READ_SE -#undef READ_SE_ALLOWED - -static void -gst_h264_parser_init (GstH264Parser * object) -{ - GstH264Parser *parser = GST_H264_PARSER (object); - - parser->sequences = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, - gst_h264_sequence_free); - parser->pictures = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, - gst_h264_picture_free); -} - -static void -gst_h264_parser_finalize (GObject * object) -{ - GstH264Parser *parser = GST_H264_PARSER (object); - - g_hash_table_destroy (parser->sequences); - g_hash_table_destroy (parser->pictures); - - G_OBJECT_CLASS (gst_h264_parser_parent_class)->finalize (object); -} - -static void -gst_h264_parser_class_init (GstH264ParserClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = gst_h264_parser_finalize; -} diff --git a/sys/vdpau/h264/gsth264parser.h b/sys/vdpau/h264/gsth264parser.h deleted file mode 100644 index f55c25881a..0000000000 --- a/sys/vdpau/h264/gsth264parser.h +++ /dev/null @@ -1,420 +0,0 @@ -/* 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, 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 _GstH264RefPicMarking GstH264RefPicMarking; -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; - - 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_lists_4x4[6][16]; - guint8 scaling_lists_8x8[6][64]; - - guint8 second_chroma_qp_index_offset; -}; - -struct _GstH264RefPicMarking -{ - guint8 memory_management_control_operation; - - guint32 difference_of_pic_nums_minus1; - guint32 long_term_pic_num; - guint32 long_term_frame_idx; - guint32 max_long_term_frame_idx_plus1; -}; - -struct _GstH264DecRefPicMarking -{ - /* if slice->nal_unit.IdrPicFlag */ - guint8 no_output_of_prior_pics_flag; - guint8 long_term_reference_flag; - - guint8 adaptive_ref_pic_marking_mode_flag; - GstH264RefPicMarking ref_pic_marking[10]; - guint8 n_ref_pic_marking; -}; - -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_ */ diff --git a/sys/vdpau/h264/gstnalreader.c b/sys/vdpau/h264/gstnalreader.c deleted file mode 100644 index b9b9d236d4..0000000000 --- a/sys/vdpau/h264/gstnalreader.c +++ /dev/null @@ -1,503 +0,0 @@ -/* 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, 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 = 0xff; - - 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 = 0xff; -} - -/** - * 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_se: - * @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) + 1; - 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); -} diff --git a/sys/vdpau/h264/gstnalreader.h b/sys/vdpau/h264/gstnalreader.h deleted file mode 100644 index 353f650189..0000000000 --- a/sys/vdpau/h264/gstnalreader.h +++ /dev/null @@ -1,99 +0,0 @@ -/* 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, 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, 0xff} - -/** - * 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, 0xff} - -G_END_DECLS - -#endif /* __GST_NAL_READER_H__ */ diff --git a/sys/vdpau/h264/gstvdph264dec.c b/sys/vdpau/h264/gstvdph264dec.c index 08774d60e5..e5d26ce5b0 100644 --- a/sys/vdpau/h264/gstvdph264dec.c +++ b/sys/vdpau/h264/gstvdph264dec.c @@ -22,156 +22,49 @@ #include "config.h" #endif -#include <gst/base/gstadapter.h> -#include <gst/base/gstbitreader.h> +#include <gst/codecparsers/gsth264parser.h> +#include <gst/codecparsers/gsth264meta.h> #include <string.h> -#include "gsth264frame.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_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME, GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-h264, " "interlaced = (boolean) false") + GST_STATIC_CAPS ("video/x-h264,stream-format=byte-stream,alignment=au") ); -#define DEBUG_INIT(bla) \ +#define DEBUG_INIT \ GST_DEBUG_CATEGORY_INIT (gst_vdp_h264_dec_debug, "vdpauh264dec", 0, \ "VDPAU h264 decoder"); -GST_BOILERPLATE_FULL (GstVdpH264Dec, gst_vdp_h264_dec, GstVdpDecoder, - GST_TYPE_VDP_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; -} +#define gst_vdp_h264_dec_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstVdpH264Dec, gst_vdp_h264_dec, GST_TYPE_VDP_DECODER, + DEBUG_INIT); static GstFlowReturn gst_vdp_h264_dec_output (GstH264DPB * dpb, GstH264Frame * h264_frame, gpointer user_data) { - GstBaseVideoDecoder *base_video_decoder = (GstBaseVideoDecoder *) user_data; + GstVideoDecoder *video_decoder = (GstVideoDecoder *) user_data; GST_DEBUG ("poc: %d", h264_frame->poc); - return gst_base_video_decoder_finish_frame (base_video_decoder, - GST_VIDEO_FRAME_CAST (h264_frame)); + return gst_video_decoder_finish_frame (video_decoder, h264_frame->frame); } static guint -gst_vdp_h264_dec_calculate_poc (GstVdpH264Dec * h264_dec, GstH264Slice * slice) +gst_vdp_h264_dec_calculate_poc (GstVdpH264Dec * h264_dec, + GstH264SliceHdr * slice) { - GstH264Picture *pic; - GstH264Sequence *seq; + GstH264SPS *seq; guint poc = 0; - pic = slice->picture; - seq = pic->sequence; + seq = slice->pps->sequence; if (seq->pic_order_cnt_type == 0) { guint32 max_poc_cnt_lsb = 1 << (seq->log2_max_pic_order_cnt_lsb_minus4 + 4); @@ -196,12 +89,8 @@ gst_vdp_h264_dec_calculate_poc (GstVdpH264Dec * h264_dec, GstH264Slice * slice) static void gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec, - GstH264Frame * h264_frame) + GstH264Frame * h264_frame, GstH264SliceHdr * slice) { - GstH264Slice *slice; - - slice = &h264_frame->slice_hdr; - h264_frame->poc = gst_vdp_h264_dec_calculate_poc (h264_dec, slice); h264_frame->output_needed = TRUE; @@ -209,9 +98,9 @@ gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec, h264_frame->frame_idx = slice->frame_num; /* is reference */ - if (slice->nal_unit.ref_idc == 0) + if (slice->nalu_ref_idc == 0) h264_frame->is_reference = FALSE; - else if (slice->nal_unit.IdrPicFlag) { + else if (slice->slice_type == GST_H264_NAL_SLICE_IDR) { h264_frame->is_reference = TRUE; if (slice->dec_ref_pic_marking.long_term_reference_flag) { h264_frame->is_long_term = TRUE; @@ -237,38 +126,17 @@ gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec, } -static gboolean -gst_vdp_h264_dec_calculate_par (GstH264VUIParameters * vui, guint16 * par_n, - guint16 * par_d) -{ - guint16 aspect[16][2] = { {1, 1}, {12, 11}, {10, 11}, {16, 11}, {40, 33}, - {24, 11}, {20, 11}, {32, 11}, {80, 33}, {18, 11}, {15, 11}, {64, 33}, - {160, 99}, {4, 3}, {3, 2}, {2, 1} - }; - - if (vui->aspect_ratio_idc >= 1 && vui->aspect_ratio_idc <= 16) { - *par_n = aspect[vui->aspect_ratio_idc - 1][0]; - *par_d = aspect[vui->aspect_ratio_idc - 1][1]; - return TRUE; - } else if (vui->aspect_ratio_idc == 255) { - *par_n = vui->sar_height; - *par_d = vui->sar_width; - return TRUE; - } - - return FALSE; -} - static GstFlowReturn -gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstH264Frame * h264_frame) +gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstVideoCodecFrame * frame, + GstH264SliceHdr * slice) { - GstH264Slice *slice; - GstH264Sequence *seq; + GstH264SPS *seq; + + GST_DEBUG_OBJECT (h264_dec, "Handling IDR slice"); h264_dec->poc_msb = 0; h264_dec->prev_poc_lsb = 0; - slice = &h264_frame->slice_hdr; if (slice->dec_ref_pic_marking.no_output_of_prior_pics_flag) gst_h264_dpb_flush (h264_dec->dpb, FALSE); else @@ -279,48 +147,31 @@ gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstH264Frame * h264_frame) else g_object_set (h264_dec->dpb, "max-longterm-frame-idx", -1, NULL); - seq = slice->picture->sequence; - if (seq != h264_dec->sequence) { - GstVideoState state; + seq = slice->pps->sequence; + if (seq->id != h264_dec->current_sps) { + GstVideoCodecState *state; VdpDecoderProfile profile; GstFlowReturn ret; - state = - gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER (h264_dec)); - - state.width = (seq->pic_width_in_mbs_minus1 + 1) * 16 - - 2 * seq->frame_crop_right_offset; + GST_DEBUG_OBJECT (h264_dec, "Sequence changed !"); - state.height = (2 - seq->frame_mbs_only_flag) * - (seq->pic_height_in_map_units_minus1 + 1) * 16; - if (seq->frame_mbs_only_flag) - state.height -= 2 * seq->frame_crop_bottom_offset; - else - state.height -= 4 * seq->frame_crop_bottom_offset; + state = + gst_video_decoder_set_output_state (GST_VIDEO_DECODER (h264_dec), + GST_VIDEO_FORMAT_YV12, seq->width, seq->height, h264_dec->input_state); /* calculate framerate if we haven't got one */ - if (state.fps_n == 0 && seq->vui_parameters_present_flag) { - GstH264VUIParameters *vui; - guint16 par_n, par_d; - - vui = &seq->vui_parameters; - - if (gst_vdp_h264_dec_calculate_par (vui, &par_n, &par_d)) { - state.par_n = par_n; - state.par_d = par_d; - } - - if (vui->timing_info_present_flag && vui->fixed_frame_rate_flag) { - state.fps_n = vui->time_scale; - state.fps_d = vui->num_units_in_tick; - - if (seq->frame_mbs_only_flag) - state.fps_d *= 2; - } + if (state->info.fps_n == 0) { + state->info.fps_n = seq->fps_num; + state->info.fps_d = seq->fps_den; + } + if (state->info.par_n == 0 && seq->vui_parameters_present_flag) { + state->info.par_n = seq->vui_parameters.par_n; + state->info.par_d = seq->vui_parameters.par_d; } - gst_base_video_decoder_set_state (GST_BASE_VIDEO_DECODER (h264_dec), state); + if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (h264_dec))) + goto nego_fail; switch (seq->profile_idc) { case 66: @@ -336,197 +187,118 @@ gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstH264Frame * h264_frame) break; default: - GST_ELEMENT_ERROR (h264_dec, STREAM, WRONG_TYPE, - ("vdpauh264dec doesn't support this streams profile"), - ("profile_idc: %d", seq->profile_idc)); - return GST_FLOW_ERROR; + goto profile_not_suported; } ret = gst_vdp_decoder_init_decoder (GST_VDP_DECODER (h264_dec), profile, - seq->num_ref_frames); + seq->num_ref_frames, h264_dec->input_state); if (ret != GST_FLOW_OK) return ret; g_object_set (h264_dec->dpb, "num-ref-frames", seq->num_ref_frames, NULL); - h264_dec->sequence = seq; + h264_dec->current_sps = seq->id; } return GST_FLOW_OK; + +profile_not_suported: + { + GST_ELEMENT_ERROR (h264_dec, STREAM, WRONG_TYPE, + ("vdpauh264dec doesn't support this streams profile"), + ("profile_idc: %d", seq->profile_idc)); + return GST_FLOW_ERROR; + } + +nego_fail: + { + GST_ERROR_OBJECT (h264_dec, "Negotiation failed"); + return GST_FLOW_NOT_NEGOTIATED; + } } -static VdpPictureInfoH264 -gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec, GstH264Frame * h264_frame) +static void +gst_vdp_h264_dec_fill_info (VdpPictureInfoH264 * info, GstVdpH264Dec * h264_dec, + GstH264Frame * h264_frame, GstH264SliceHdr * slice) { - GstH264Slice *slice; - GstH264Picture *pic; - GstH264Sequence *seq; - VdpPictureInfoH264 info; + GstH264PPS *pic; + GstH264SPS *seq; - slice = &h264_frame->slice_hdr; - pic = slice->picture; + pic = slice->pps; seq = pic->sequence; - info.slice_count = h264_frame->slices->len; + GST_DEBUG_OBJECT (h264_dec, "Filling info"); /* FIXME: we only handle frames for now */ - info.field_order_cnt[0] = h264_frame->poc; - info.field_order_cnt[1] = h264_frame->poc; - - info.is_reference = h264_frame->is_reference; - info.frame_num = slice->frame_num; - - info.field_pic_flag = slice->field_pic_flag; - info.bottom_field_flag = slice->bottom_field_flag; - info.num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1; - info.num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1; - - info.num_ref_frames = seq->num_ref_frames; - info.frame_mbs_only_flag = seq->frame_mbs_only_flag; - info.mb_adaptive_frame_field_flag = seq->mb_adaptive_frame_field_flag; - info.log2_max_frame_num_minus4 = seq->log2_max_frame_num_minus4; - info.pic_order_cnt_type = seq->pic_order_cnt_type; - info.log2_max_pic_order_cnt_lsb_minus4 = + info->field_order_cnt[0] = h264_frame->poc; + info->field_order_cnt[1] = h264_frame->poc; + + info->is_reference = h264_frame->is_reference; + info->frame_num = slice->frame_num; + + info->field_pic_flag = slice->field_pic_flag; + info->bottom_field_flag = slice->bottom_field_flag; + info->num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1; + info->num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1; + + info->num_ref_frames = seq->num_ref_frames; + info->mb_adaptive_frame_field_flag = seq->mb_adaptive_frame_field_flag; + info->frame_mbs_only_flag = seq->frame_mbs_only_flag; + info->log2_max_frame_num_minus4 = seq->log2_max_frame_num_minus4; + info->pic_order_cnt_type = seq->pic_order_cnt_type; + info->log2_max_pic_order_cnt_lsb_minus4 = seq->log2_max_pic_order_cnt_lsb_minus4; - info.delta_pic_order_always_zero_flag = seq->delta_pic_order_always_zero_flag; - info.direct_8x8_inference_flag = seq->direct_8x8_inference_flag; - - - info.constrained_intra_pred_flag = pic->constrained_intra_pred_flag; - info.weighted_pred_flag = pic->weighted_pred_flag; - info.weighted_bipred_idc = pic->weighted_bipred_idc; - info.transform_8x8_mode_flag = pic->transform_8x8_mode_flag; - info.chroma_qp_index_offset = pic->chroma_qp_index_offset; - info.second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset; - info.pic_init_qp_minus26 = pic->pic_init_qp_minus26; - info.entropy_coding_mode_flag = pic->entropy_coding_mode_flag; - info.pic_order_present_flag = pic->pic_order_present_flag; - info.deblocking_filter_control_present_flag = + info->delta_pic_order_always_zero_flag = + seq->delta_pic_order_always_zero_flag; + info->direct_8x8_inference_flag = seq->direct_8x8_inference_flag; + + info->constrained_intra_pred_flag = pic->constrained_intra_pred_flag; + info->weighted_pred_flag = pic->weighted_pred_flag; + info->weighted_bipred_idc = pic->weighted_bipred_idc; + info->transform_8x8_mode_flag = pic->transform_8x8_mode_flag; + info->chroma_qp_index_offset = pic->chroma_qp_index_offset; + info->second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset; + info->pic_init_qp_minus26 = pic->pic_init_qp_minus26; + info->entropy_coding_mode_flag = pic->entropy_coding_mode_flag; + info->pic_order_present_flag = pic->pic_order_present_flag; + info->deblocking_filter_control_present_flag = pic->deblocking_filter_control_present_flag; - info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag; - - memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96); - memcpy (&info.scaling_lists_8x8, &pic->scaling_lists_8x8, 128); + info->redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag; - gst_h264_dpb_fill_reference_frames (h264_dec->dpb, info.referenceFrames); + memcpy (&info->scaling_lists_4x4, &pic->scaling_lists_4x4, 96); + memcpy (&info->scaling_lists_8x8, &pic->scaling_lists_8x8, 128); - return info; + gst_h264_dpb_fill_reference_frames (h264_dec->dpb, info->referenceFrames); } static VdpBitstreamBuffer * gst_vdp_h264_dec_create_bitstream_buffers (GstVdpH264Dec * h264_dec, - GstH264Frame * h264_frame, guint * n_bufs) + GstH264Meta * meta, GstMapInfo * info) { VdpBitstreamBuffer *bufs; + guint i; + gsize offset = 0; - if (h264_dec->packetized) { - guint i; + bufs = g_new (VdpBitstreamBuffer, meta->num_slices); - bufs = g_new (VdpBitstreamBuffer, h264_frame->slices->len * 2); - *n_bufs = h264_frame->slices->len * 2; - - for (i = 0; i < h264_frame->slices->len; i++) { - static const guint8 start_code[] = { 0x00, 0x00, 0x01 }; - guint idx; - GstBuffer *buf; - - idx = i * 2; - bufs[idx].bitstream = start_code; - bufs[idx].bitstream_bytes = 3; - bufs[idx].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - - idx = idx + 1; - buf = GST_BUFFER_CAST (g_ptr_array_index (h264_frame->slices, i)); - bufs[idx].bitstream = GST_BUFFER_DATA (buf) + h264_dec->nal_length_size; - bufs[idx].bitstream_bytes = GST_BUFFER_SIZE (buf) - - h264_dec->nal_length_size; - bufs[idx].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - } - } - - else { - guint i; - - bufs = g_new (VdpBitstreamBuffer, h264_frame->slices->len); - *n_bufs = h264_frame->slices->len; - - for (i = 0; i < h264_frame->slices->len; i++) { - GstBuffer *buf; - - buf = GST_BUFFER_CAST (g_ptr_array_index (h264_frame->slices, i)); - bufs[i].bitstream = GST_BUFFER_DATA (buf); - bufs[i].bitstream_bytes = GST_BUFFER_SIZE (buf); - bufs[i].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - } + for (i = 0; i < meta->num_slices; i++) { + bufs[i].bitstream = info->data + offset; + if (i == meta->num_slices) + offset = info->size; + else + offset = meta->slice_offsets[i + 1]; + bufs[i].bitstream_bytes = offset - meta->slice_offsets[i]; + bufs[i].struct_version = VDP_BITSTREAM_BUFFER_VERSION; } return bufs; } static GstFlowReturn -gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder, - GstVideoFrame * frame, GstClockTimeDiff deadline) +gst_vdp_h264_dec_handle_dpb (GstVdpH264Dec * h264_dec, + GstH264Frame * h264_frame, GstH264SliceHdr * slice) { - GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); - - GstH264Frame *h264_frame; - GstH264Slice *slice; - GstH264Picture *pic G_GNUC_UNUSED; - GstH264Sequence *seq G_GNUC_UNUSED; - - GstFlowReturn ret; - GstVdpVideoBuffer *outbuf; - VdpPictureInfoH264 info; - VdpBitstreamBuffer *bufs; - guint n_bufs; - - GST_DEBUG ("handle_frame"); - - h264_frame = GST_H264_FRAME_CAST (frame); - - slice = &h264_frame->slice_hdr; - pic = slice->picture; - seq = pic->sequence; - - - if (slice->nal_unit.IdrPicFlag) { - ret = gst_vdp_h264_dec_idr (h264_dec, h264_frame); - - if (ret == GST_FLOW_OK) - h264_dec->got_idr = TRUE; - else { - gst_base_video_decoder_skip_frame (base_video_decoder, frame); - return GST_FLOW_OK; - } - } - - /* check if we've got a IDR frame yet */ - if (!h264_dec->got_idr) { - gst_base_video_decoder_skip_frame (base_video_decoder, frame); - return GST_FLOW_OK; - } - - - gst_vdp_h264_dec_init_frame_info (h264_dec, h264_frame); - - info = gst_vdp_h264_dec_fill_info (h264_dec, h264_frame); - bufs = gst_vdp_h264_dec_create_bitstream_buffers (h264_dec, h264_frame, - &n_bufs); - - ret = gst_vdp_decoder_render (GST_VDP_DECODER (h264_dec), - (VdpPictureInfo *) & info, n_bufs, bufs, &outbuf); - g_free (bufs); - - if (ret != GST_FLOW_OK) { - gst_base_video_decoder_skip_frame (base_video_decoder, frame); - return ret; - } - - frame->src_buffer = GST_BUFFER_CAST (outbuf); - - - /* DPB handling */ - if (slice->nal_unit.ref_idc != 0 && !slice->nal_unit.IdrPicFlag) { + if (slice->nalu_ref_idc != 0 && slice->slice_type != GST_H264_NAL_SLICE_IDR) { if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { GstH264RefPicMarking *marking; guint i; @@ -586,242 +358,148 @@ gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder, } return gst_h264_dpb_add (h264_dec->dpb, h264_frame); + } -static gint -gst_vdp_h264_dec_scan_for_sync (GstBaseVideoDecoder * base_video_decoder, - GstAdapter * adapter) +static void +gst_h264_frame_free (GstH264Frame * frame) { - 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; + g_slice_free (GstH264Frame, frame); } -static GstBaseVideoDecoderScanResult -gst_vdp_h264_dec_scan_for_packet_end (GstBaseVideoDecoder * base_video_decoder, - GstAdapter * adapter, guint * size, gboolean at_eos) +static GstFlowReturn +gst_vdp_h264_dec_handle_frame (GstVideoDecoder * video_decoder, + GstVideoCodecFrame * frame) { - 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 = 0; + GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (video_decoder); + GstH264Meta *h264_meta; + GstH264Frame *h264_frame; + GList *tmp; + GstFlowReturn ret; + VdpPictureInfoH264 info; + VdpBitstreamBuffer *bufs; + GstH264SliceHdr *first_slice; + guint i; + GstMapInfo map; - 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]; + GST_DEBUG ("handle_frame"); - g_slice_free1 (h264_dec->nal_length_size, data); + h264_meta = gst_buffer_get_h264_meta (frame->input_buffer); + if (G_UNLIKELY (h264_meta == NULL)) + goto no_h264_meta; - nal_length += h264_dec->nal_length_size; + if (G_UNLIKELY (h264_meta->num_slices == 0)) + goto no_slices; - /* 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); + /* Handle PPS/SPS/SEI if present */ + if (h264_meta->sps) { + for (tmp = h264_meta->sps; tmp; tmp = tmp->next) { + GstH264SPS *sps = (GstH264SPS *) tmp->data; + GST_LOG_OBJECT (h264_dec, "Storing SPS %d", sps->id); + h264_dec->sps[sps->id] = g_slice_dup (GstH264SPS, sps); } - - *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; + if (h264_meta->pps) { + for (tmp = h264_meta->pps; tmp; tmp = tmp->next) { + GstH264PPS *pps = (GstH264PPS *) tmp->data; + GST_LOG_OBJECT (h264_dec, "Storing PPS %d", pps->id); + h264_dec->pps[pps->id] = g_slice_dup (GstH264PPS, pps); + /* Adjust pps pointer */ + h264_dec->pps[pps->id]->sequence = h264_dec->sps[pps->sps_id]; + } } - 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, GstVideoFrame * frame) -{ - GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); - GstBitReader reader; - GstNalUnit nal_unit; - guint8 forbidden_zero_bit; + first_slice = &h264_meta->slices[0]; - guint8 *data; - guint size; - gint i; + if (!h264_dec->got_idr && first_slice->slice_type != GST_H264_NAL_SLICE_IDR) + goto no_idr; - GstFlowReturn ret = GST_FLOW_OK; + /* Handle slices */ + for (i = 0; i < h264_meta->num_slices; i++) { + GstH264SliceHdr *slice = &h264_meta->slices[i]; - GST_MEMDUMP ("data", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + GST_LOG_OBJECT (h264_dec, "Handling slice #%d", i); + slice->pps = h264_dec->pps[slice->pps_id]; + } - gst_bit_reader_init_from_buffer (&reader, buf); + if (first_slice->slice_type == GST_H264_NAL_SLICE_IDR) { + ret = gst_vdp_h264_dec_idr (h264_dec, frame, first_slice); + if (ret == GST_FLOW_OK) + h264_dec->got_idr = TRUE; + else + goto skip_frame; + } - if (gst_bit_reader_get_remaining (&reader) < - h264_dec->nal_length_size * 8 + 7) - goto invalid_packet; + h264_frame = g_slice_new0 (GstH264Frame); + gst_video_codec_frame_set_user_data (frame, h264_frame, + (GDestroyNotify) gst_h264_frame_free); - /* skip nal_length or sync code */ - gst_bit_reader_skip_unchecked (&reader, h264_dec->nal_length_size * 8); + gst_vdp_h264_dec_init_frame_info (h264_dec, h264_frame, first_slice); + h264_frame->frame = frame; + gst_vdp_h264_dec_fill_info (&info, h264_dec, h264_frame, first_slice); + info.slice_count = h264_meta->num_slices; - forbidden_zero_bit = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1); + if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) + goto map_fail; + bufs = gst_vdp_h264_dec_create_bitstream_buffers (h264_dec, h264_meta, &map); - if (forbidden_zero_bit != 0) { - GST_WARNING ("forbidden_zero_bit != 0"); - return GST_FLOW_ERROR; - } + ret = gst_vdp_decoder_render (GST_VDP_DECODER (h264_dec), + (VdpPictureInfo *) & info, h264_meta->num_slices, bufs, frame); + g_free (bufs); + gst_buffer_unmap (frame->input_buffer, &map); - nal_unit.ref_idc = gst_bit_reader_get_bits_uint16_unchecked (&reader, 2); - GST_DEBUG ("nal_ref_idc: %u", nal_unit.ref_idc); + if (ret != GST_FLOW_OK) + goto render_fail; - /* read nal_unit_type */ - nal_unit.type = gst_bit_reader_get_bits_uint16_unchecked (&reader, 5); + /* DPB handling */ + return gst_vdp_h264_dec_handle_dpb (h264_dec, h264_frame, first_slice); - 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; + /* EARLY exit */ +no_idr: + { + GST_DEBUG_OBJECT (video_decoder, "Didn't see a IDR yet, skipping frame"); + return gst_video_decoder_finish_frame (video_decoder, frame); } - nal_unit.IdrPicFlag = (nal_unit.type == 5 ? 1 : 0); - - data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8; - size = gst_bit_reader_get_remaining (&reader) / 8; - i = size - 1; - while ((gint) size > 0 && data[i] == 0x00) { - size--; - i--; +skip_frame: + { + GST_DEBUG_OBJECT (video_decoder, "Skipping frame"); + return gst_video_decoder_finish_frame (video_decoder, frame); } - if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_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 == GST_NAL_AU_DELIMITER || - (nal_unit.type >= 14 && nal_unit.type <= 18)) - ret = - gst_base_video_decoder_have_frame (base_video_decoder, FALSE, &frame); + /* ERRORS */ +no_h264_meta: + { + GST_ERROR_OBJECT (video_decoder, "Input buffer doesn't have GstH264Meta"); + return GST_FLOW_ERROR; } - 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_H264_FRAME_GOT_PRIMARY)) { - GstH264Slice *p_slice; - guint8 pic_order_cnt_type, p_pic_order_cnt_type; - gboolean finish_frame = FALSE; - - p_slice = &(GST_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) - finish_frame = TRUE; - - else if (slice.picture != p_slice->picture) - finish_frame = TRUE; - - else if (slice.bottom_field_flag != p_slice->bottom_field_flag) - finish_frame = TRUE; - - else if (nal_unit.ref_idc != p_slice->nal_unit.ref_idc && - (nal_unit.ref_idc == 0 || p_slice->nal_unit.ref_idc == 0)) - finish_frame = TRUE; - - 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)) - finish_frame = TRUE; - - 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])) - finish_frame = TRUE; - - if (finish_frame) - ret = - gst_base_video_decoder_have_frame (base_video_decoder, FALSE, - &frame); - - } - - if (!GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_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_H264_FRAME_CAST (frame)->slice_hdr = slice; - GST_VIDEO_FRAME_FLAG_SET (frame, GST_H264_FRAME_GOT_PRIMARY); - } - } - gst_h264_frame_add_slice ((GstH264Frame *) frame, buf); +no_slices: + { + GST_ERROR_OBJECT (video_decoder, "Input buffer doesn't have any slices"); + return GST_FLOW_ERROR; } - if (nal_unit.type == GST_NAL_SPS) { - if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, size)) - goto invalid_packet; +map_fail: + { + GST_ERROR_OBJECT (video_decoder, "Failed to map input buffer for READ"); + return GST_FLOW_ERROR; } - if (nal_unit.type == GST_NAL_PPS) { - if (!gst_h264_parser_parse_picture (h264_dec->parser, data, size)) - goto invalid_packet; +render_fail: + { + GST_ERROR_OBJECT (video_decoder, "Failed to render : %s", + gst_flow_get_name (ret)); + gst_video_decoder_drop_frame (video_decoder, frame); + return ret; } - - gst_buffer_unref (buf); - return ret; - -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_h264_frame_new ()); -} static gboolean -gst_vdp_h264_dec_flush (GstBaseVideoDecoder * base_video_decoder) +gst_vdp_h264_dec_reset (GstVideoDecoder * video_decoder, gboolean hard) { - GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); + GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (video_decoder); h264_dec->got_idr = FALSE; gst_h264_dpb_flush (h264_dec->dpb, FALSE); @@ -830,75 +508,75 @@ gst_vdp_h264_dec_flush (GstBaseVideoDecoder * base_video_decoder) } static gboolean -gst_vdp_h264_dec_start (GstBaseVideoDecoder * base_video_decoder) +gst_vdp_h264_dec_start (GstVideoDecoder * video_decoder) { - GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); - - h264_dec->packetized = FALSE; - h264_dec->nal_length_size = SYNC_CODE_SIZE; + GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (video_decoder); h264_dec->got_idr = FALSE; - h264_dec->sequence = NULL; - - h264_dec->parser = g_object_new (GST_TYPE_H264_PARSER, NULL); + h264_dec->current_sps = -1; + h264_dec->got_idr = FALSE; h264_dec->dpb = g_object_new (GST_TYPE_H264_DPB, NULL); gst_h264_dpb_set_output_func (h264_dec->dpb, gst_vdp_h264_dec_output, h264_dec); - return GST_BASE_VIDEO_DECODER_CLASS - (parent_class)->start (base_video_decoder); + return GST_VIDEO_DECODER_CLASS (parent_class)->start (video_decoder); } static gboolean -gst_vdp_h264_dec_stop (GstBaseVideoDecoder * base_video_decoder) +gst_vdp_h264_dec_stop (GstVideoDecoder * video_decoder) { - GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); + GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (video_decoder); - g_object_unref (h264_dec->parser); g_object_unref (h264_dec->dpb); - return GST_BASE_VIDEO_DECODER_CLASS (parent_class)->stop (base_video_decoder); + return GST_VIDEO_DECODER_CLASS (parent_class)->stop (video_decoder); } -static void -gst_vdp_h264_dec_base_init (gpointer g_class) +static gboolean +gst_vdp_h264_dec_set_format (GstVideoDecoder * video_decoder, + GstVideoCodecState * state) { - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (video_decoder); - gst_element_class_set_static_metadata (element_class, - "VDPAU H264 Decoder", - "Decoder", - "Decode h264 stream with vdpau", - "Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>"); + if (h264_dec->input_state) + gst_video_codec_state_unref (h264_dec->input_state); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); + h264_dec->input_state = gst_video_codec_state_ref (state); + + GST_FIXME_OBJECT (video_decoder, "Do something when receiving input state ?"); + + return TRUE; } static void -gst_vdp_h264_dec_init (GstVdpH264Dec * h264_dec, GstVdpH264DecClass * klass) +gst_vdp_h264_dec_init (GstVdpH264Dec * h264_dec) { } static void gst_vdp_h264_dec_class_init (GstVdpH264DecClass * klass) { - GstBaseVideoDecoderClass *base_video_decoder_class; + GstElementClass *element_class; + GstVideoDecoderClass *video_decoder_class; - base_video_decoder_class = GST_BASE_VIDEO_DECODER_CLASS (klass); + element_class = GST_ELEMENT_CLASS (klass); + video_decoder_class = GST_VIDEO_DECODER_CLASS (klass); - 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; + gst_element_class_set_static_metadata (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)); - base_video_decoder_class->set_sink_caps = gst_vdp_h264_dec_set_sink_caps; + video_decoder_class->start = gst_vdp_h264_dec_start; + video_decoder_class->stop = gst_vdp_h264_dec_stop; + video_decoder_class->reset = gst_vdp_h264_dec_reset; - 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; + video_decoder_class->set_format = gst_vdp_h264_dec_set_format; - base_video_decoder_class->handle_frame = gst_vdp_h264_dec_handle_frame; - base_video_decoder_class->create_frame = gst_vdp_h264_dec_create_frame; + video_decoder_class->handle_frame = gst_vdp_h264_dec_handle_frame; } diff --git a/sys/vdpau/h264/gstvdph264dec.h b/sys/vdpau/h264/gstvdph264dec.h index a067a09f89..07074338c5 100644 --- a/sys/vdpau/h264/gstvdph264dec.h +++ b/sys/vdpau/h264/gstvdph264dec.h @@ -22,10 +22,9 @@ #define __GST_VDP_H264_DEC_H__ #include <gst/gst.h> +#include <gst/codecparsers/gsth264parser.h> -#include "../gstvdp/gstvdpdecoder.h" - -#include "gsth264parser.h" +#include "../gstvdpdecoder.h" #include "gsth264dpb.h" G_BEGIN_DECLS @@ -45,16 +44,17 @@ typedef struct _GstVdpH264DecClass GstVdpH264DecClass; struct _GstVdpH264Dec { GstVdpDecoder vdp_decoder; - gboolean packetized; - guint8 nal_length_size; - - GstH264Parser *parser; GstH264DPB *dpb; + GstH264SPS *sps[GST_H264_MAX_SPS_COUNT]; + GstH264PPS *pps[GST_H264_MAX_PPS_COUNT]; + + /* Current SPS being used. Default:-1 */ + gint current_sps; - GstH264Sequence *sequence; gboolean got_idr; - VdpDecoder decoder; + GstVideoCodecState *input_state; + guint poc_msb; guint prev_poc_lsb; }; @@ -67,4 +67,4 @@ GType gst_vdp_h264_dec_get_type (void); G_END_DECLS -#endif /* __GST_VDP_H264_DEC_H__ */
\ No newline at end of file +#endif /* __GST_VDP_H264_DEC_H__ */ |