diff options
-rw-r--r-- | sys/vdpau/Makefile.am | 10 | ||||
-rw-r--r-- | sys/vdpau/gstvdpau.c | 3 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/gstmpeg4frame.c | 109 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/gstmpeg4frame.h | 64 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/gstvdpmpeg4dec.c | 483 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/gstvdpmpeg4dec.h | 62 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/mpeg4util.c | 466 | ||||
-rw-r--r-- | sys/vdpau/mpeg4/mpeg4util.h | 179 |
8 files changed, 1374 insertions, 2 deletions
diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 658183eeb..dabba0896 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -13,7 +13,10 @@ libgstvdpau_la_SOURCES = \ h264/gsth264parser.c \ h264/gsth264frame.c \ h264/gsth264dpb.c \ - h264/gstvdph264dec.c + h264/gstvdph264dec.c \ + mpeg4/mpeg4util.c \ + mpeg4/gstmpeg4frame.c \ + mpeg4/gstvdpmpeg4dec.c libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) @@ -36,4 +39,7 @@ noinst_HEADERS = \ h264/gsth264parser.h \ h264/gsth264frame.h \ h264/gsth264dpb.h \ - h264/gstvdph264dec.h
\ No newline at end of file + h264/gstvdph264dec.h \ + mpeg4/mpeg4util.h \ + mpeg4/gstmpeg4frame.h \ + mpeg4/gstvdpmpeg4dec.h diff --git a/sys/vdpau/gstvdpau.c b/sys/vdpau/gstvdpau.c index 5a8383c75..a8bd629d7 100644 --- a/sys/vdpau/gstvdpau.c +++ b/sys/vdpau/gstvdpau.c @@ -9,6 +9,7 @@ #include "mpeg/gstvdpmpegdec.h" #include "h264/gstvdph264dec.h" +#include "mpeg4/gstvdpmpeg4dec.h" #include "gstvdpvideopostprocess.h" #include "gstvdpsink.h" @@ -23,6 +24,8 @@ vdpau_init (GstPlugin * vdpau_plugin) GST_RANK_NONE, GST_TYPE_VDP_MPEG_DEC); gst_element_register (vdpau_plugin, "vdpauh264dec", GST_RANK_NONE, GST_TYPE_VDP_H264_DEC); + gst_element_register (vdpau_plugin, "vdpaumpeg4dec", + GST_RANK_NONE, GST_TYPE_VDP_MPEG4_DEC); gst_element_register (vdpau_plugin, "vdpauvideopostprocess", GST_RANK_NONE, GST_TYPE_VDP_VIDEO_POST_PROCESS); gst_element_register (vdpau_plugin, "vdpausink", diff --git a/sys/vdpau/mpeg4/gstmpeg4frame.c b/sys/vdpau/mpeg4/gstmpeg4frame.c new file mode 100644 index 000000000..26ac896c1 --- /dev/null +++ b/sys/vdpau/mpeg4/gstmpeg4frame.c @@ -0,0 +1,109 @@ +/* +* GStreamer +* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public +* License along with this library; if not, write to the +* Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstmpeg4frame.h" + +GST_DEBUG_CATEGORY_STATIC (gst_mpeg4_frame_debug); +#define GST_CAT_DEFAULT gst_mpeg4_frame_debug + +#define DEBUG_INIT(bla) \ +GST_DEBUG_CATEGORY_INIT (gst_mpeg4_frame_debug, "gstmpeg4frame", 0, "Mpeg4 Frame"); + +GstMpeg4Frame * +gst_mpeg4_frame_new (void) +{ + GstMpeg4Frame *frame; + + frame = (GstMpeg4Frame *) gst_mini_object_new (GST_TYPE_MPEG4_FRAME); + + return frame; +} + +static GObjectClass *gst_mpeg4_frame_parent_class; + +static void +gst_mpeg4_frame_finalize (GstMpeg4Frame * mpeg4_frame) +{ + if (mpeg4_frame->vos_buf) + gst_buffer_unref (mpeg4_frame->vos_buf); + + if (mpeg4_frame->vo_buf) + gst_buffer_unref (mpeg4_frame->vo_buf); + + if (mpeg4_frame->vol_buf) + gst_buffer_unref (mpeg4_frame->vol_buf); + + if (mpeg4_frame->gov_buf) + gst_buffer_unref (mpeg4_frame->gov_buf); + + if (mpeg4_frame->vop_buf) + gst_buffer_unref (mpeg4_frame->vop_buf); + + + GST_MINI_OBJECT_CLASS (gst_mpeg4_frame_parent_class)->finalize + (GST_MINI_OBJECT (mpeg4_frame)); +} + +static void +gst_mpeg4_frame_init (GstMpeg4Frame * mpeg4_frame, gpointer g_class) +{ +} + +static void +gst_mpeg4_frame_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + gst_mpeg4_frame_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_mpeg4_frame_finalize; +} + + +GType +gst_mpeg4_frame_get_type (void) +{ + static GType _gst_mpeg4_frame_type = 0; + + if (G_UNLIKELY (_gst_mpeg4_frame_type == 0)) { + static const GTypeInfo info = { + sizeof (GstMpeg4FrameClass), + NULL, + NULL, + gst_mpeg4_frame_class_init, + NULL, + NULL, + sizeof (GstMpeg4Frame), + 0, + (GInstanceInitFunc) gst_mpeg4_frame_init, + NULL + }; + _gst_mpeg4_frame_type = g_type_register_static (GST_TYPE_VIDEO_FRAME, + "GstMpeg4Frame", &info, 0); + + DEBUG_INIT (); + } + return _gst_mpeg4_frame_type; +} diff --git a/sys/vdpau/mpeg4/gstmpeg4frame.h b/sys/vdpau/mpeg4/gstmpeg4frame.h new file mode 100644 index 000000000..3bcbd05bd --- /dev/null +++ b/sys/vdpau/mpeg4/gstmpeg4frame.h @@ -0,0 +1,64 @@ +/* +* GStreamer +* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public +* License along with this library; if not, write to the +* Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifndef _GST_MPEG4_FRAME_H_ +#define _GST_MPEG4_FRAME_H_ + +#include <gst/gst.h> + +#include "../basevideodecoder/gstvideoframe.h" + +#include "mpeg4util.h" + +#define GST_TYPE_MPEG4_FRAME (gst_mpeg4_frame_get_type()) +#define GST_IS_MPEG4_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPEG4_FRAME)) +#define GST_MPEG4_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPEG4_FRAME, GstMpeg4Frame)) +#define GST_MPEG4_FRAME_CAST(obj) ((GstMpeg4Frame *)obj) + +#define GST_MPEG4_FRAME_GOT_PRIMARY GST_VIDEO_FRAME_FLAG_LAST + +typedef struct _GstMpeg4Frame GstMpeg4Frame; +typedef struct _GstMpeg4FrameClass GstMpeg4FrameClass; + +struct _GstMpeg4Frame +{ + GstVideoFrame video_frame; + + GstBuffer *vos_buf; + GstBuffer *vo_buf; + GstBuffer *vol_buf; + GstBuffer *gov_buf; + GstBuffer *vop_buf; + + GstClockTime vop_time; +}; + +struct _GstMpeg4FrameClass +{ + GstVideoFrameClass video_frame_class; +}; + + + +GstMpeg4Frame *gst_mpeg4_frame_new (void); + +GType gst_mpeg4_frame_get_type (void); + +#endif
\ No newline at end of file diff --git a/sys/vdpau/mpeg4/gstvdpmpeg4dec.c b/sys/vdpau/mpeg4/gstvdpmpeg4dec.c new file mode 100644 index 000000000..abb5f43a3 --- /dev/null +++ b/sys/vdpau/mpeg4/gstvdpmpeg4dec.c @@ -0,0 +1,483 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-vdpaumpeg4dec + * + * FIXME:Describe vdpaumpeg4dec here. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch -v -m fakesrc ! vdpaumpeg4dec ! fakesink silent=TRUE + * ]| + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gst/gst.h> +#include <vdpau/vdpau.h> +#include <string.h> + +#include "gstvdpmpeg4dec.h" + +GST_DEBUG_CATEGORY (gst_vdp_mpeg4_dec_debug); +#define GST_CAT_DEFAULT gst_vdp_mpeg4_dec_debug + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) 4, " + "systemstream = (boolean) false; " + "video/x-divx, divxversion = (int) [4, 5]; " "video/x-xvid")); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg4_dec_debug, "vdpaumpeg4dec", 0, \ + "VDPAU mpeg4 decoder"); + +GST_BOILERPLATE_FULL (GstVdpMpeg4Dec, gst_vdp_mpeg4_dec, + GstVdpDecoder, GST_TYPE_VDP_DECODER, DEBUG_INIT); + +#define SYNC_CODE_SIZE 3 + +static VdpPictureInfoMPEG4Part2 +gst_vdp_mpeg4_dec_fill_info (GstVdpMpeg4Dec * mpeg4_dec, + GstMpeg4Frame * mpeg4_frame, Mpeg4VideoObjectPlane * vop) +{ + Mpeg4VideoObjectLayer *vol; + VdpPictureInfoMPEG4Part2 info; + + vol = &mpeg4_dec->vol; + + info.forward_reference = VDP_INVALID_HANDLE; + info.backward_reference = VDP_INVALID_HANDLE; + + /* forward reference */ + if (vop->coding_type != I_VOP && mpeg4_dec->f_frame) { + info.forward_reference = + GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME (mpeg4_dec-> + f_frame)->src_buffer)->surface; + } + + if (vop->coding_type == B_VOP) { + guint32 p_field_period; + gint32 trd, trb; + + p_field_period = mpeg4_dec->f_frame->vop_time / mpeg4_dec->tframe; + + trd = + 2 * (mpeg4_dec->b_frame->vop_time / mpeg4_dec->tframe - p_field_period); + trb = 2 * (mpeg4_frame->vop_time / mpeg4_dec->tframe - p_field_period); + + info.trd[0] = trd; + info.trd[1] = trd; + info.trb[0] = trb; + info.trb[1] = trb; + + /* backward reference */ + if (mpeg4_dec->b_frame) { + info.forward_reference = + GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME (mpeg4_dec-> + f_frame)->src_buffer)->surface; + } + } + + memcpy (info.intra_quantizer_matrix, vol->intra_quant_mat, 64); + memcpy (info.non_intra_quantizer_matrix, vol->non_intra_quant_mat, 64); + + info.vop_time_increment_resolution = vol->vop_time_increment_resolution; + info.resync_marker_disable = vol->resync_marker_disable; + info.interlaced = vol->interlaced; + info.quant_type = vol->quant_type; + info.quarter_sample = vol->quarter_sample; + /* FIXME: support short video header */ + info.short_video_header = FALSE; + + info.vop_coding_type = vop->coding_type; + info.vop_fcode_forward = vop->fcode_forward; + info.vop_fcode_backward = vop->fcode_backward; + info.rounding_control = vop->rounding_type; + info.alternate_vertical_scan_flag = vop->alternate_vertical_scan_flag; + info.top_field_first = vop->top_field_first; + + return info; +} + +static gboolean +gst_vdp_mpeg4_dec_handle_configuration (GstVdpMpeg4Dec * mpeg4_dec, + GstMpeg4Frame * mpeg4_frame) +{ + Mpeg4VisualObjectSequence vos; + Mpeg4VisualObject vo; + Mpeg4VideoObjectLayer vol; + + GstVideoState state; + guint8 profile_indication; + VdpDecoderProfile profile; + + GstFlowReturn ret; + + if (mpeg4_dec->is_configured) + return GST_FLOW_OK; + + if (!mpeg4_frame->vos_buf || !mpeg4_frame->vo_buf || !mpeg4_frame->vol_buf) + goto skip_frame; + + if (!mpeg4_util_parse_VOS (mpeg4_frame->vos_buf, &vos)) + goto skip_frame; + + if (!mpeg4_util_parse_VO (mpeg4_frame->vo_buf, &vo)) + goto skip_frame; + + if (!mpeg4_util_parse_VOL (mpeg4_frame->vol_buf, &vo, &vol)) + goto skip_frame; + + state = gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER (mpeg4_dec)); + + state.width = vol.width; + state.height = vol.height; + + if (vol.fixed_vop_rate) { + state.fps_n = vol.vop_time_increment_resolution; + state.fps_d = vol.fixed_vop_time_increment; + } + + state.par_n = vol.par_n; + state.par_d = vol.par_d; + + gst_base_video_decoder_set_state (GST_BASE_VIDEO_DECODER (mpeg4_dec), state); + + profile_indication = vos.profile_and_level_indication >> 4; + switch (profile_indication) { + case 0x0: + profile = VDP_DECODER_PROFILE_MPEG4_PART2_SP; + break; + + case 0xf: + profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; + break; + + default: + goto unsupported_profile; + } + ret = gst_vdp_decoder_init_decoder (GST_VDP_DECODER (mpeg4_dec), profile, 2); + if (ret != GST_FLOW_OK) + return ret; + + mpeg4_dec->vol = vol; + mpeg4_dec->is_configured = TRUE; + + return GST_FLOW_OK; + +skip_frame: + GST_WARNING ("Skipping frame since we're not configured yet"); + gst_base_video_decoder_skip_frame (GST_BASE_VIDEO_DECODER (mpeg4_dec), + GST_VIDEO_FRAME (mpeg4_frame)); + return GST_FLOW_CUSTOM_ERROR; + +unsupported_profile: + GST_ELEMENT_ERROR (mpeg4_dec, STREAM, WRONG_TYPE, + ("vdpaumpeg4dec doesn't support this streams profile"), + ("profile_and_level_indication: %d", vos.profile_and_level_indication)); + return GST_FLOW_ERROR; +} + +static GstFlowReturn +gst_vdp_mpeg4_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder, + GstVideoFrame * frame, GstClockTimeDiff deadline) +{ + GstVdpMpeg4Dec *mpeg4_dec = GST_VDP_MPEG4_DEC (base_video_decoder); + + GstMpeg4Frame *mpeg4_frame; + GstFlowReturn ret; + + Mpeg4VideoObjectLayer *vol; + Mpeg4VideoObjectPlane vop; + + VdpPictureInfoMPEG4Part2 info; + VdpBitstreamBuffer bufs[1]; + GstVdpVideoBuffer *video_buf; + + mpeg4_frame = GST_MPEG4_FRAME (frame); + + ret = gst_vdp_mpeg4_dec_handle_configuration (mpeg4_dec, mpeg4_frame); + if (ret != GST_FLOW_OK) + return ret; + + vol = &mpeg4_dec->vol; + if (!mpeg4_util_parse_VOP (mpeg4_frame->vop_buf, vol, &vop)) { + gst_base_video_decoder_skip_frame (base_video_decoder, frame); + return GST_FLOW_CUSTOM_ERROR; + } + + /* calculate vop time */ + mpeg4_frame->vop_time = vop.modulo_time_base * GST_SECOND + + gst_util_uint64_scale (vop.time_increment, GST_SECOND, + vol->vop_time_increment_resolution); + GST_DEBUG ("vop_time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (mpeg4_frame->vop_time)); + + if (mpeg4_dec->tframe == GST_CLOCK_TIME_NONE && vop.coding_type == B_VOP) + mpeg4_dec->tframe = mpeg4_frame->vop_time - mpeg4_dec->f_frame->vop_time; + + if (vop.coding_type != B_VOP) { + if (mpeg4_dec->b_frame) { + + gst_base_video_decoder_finish_frame (base_video_decoder, + GST_VIDEO_FRAME_CAST (mpeg4_dec->b_frame)); + + if (mpeg4_dec->f_frame) + gst_video_frame_unref (GST_VIDEO_FRAME_CAST (mpeg4_dec->f_frame)); + + mpeg4_dec->f_frame = mpeg4_dec->b_frame; + mpeg4_dec->b_frame = NULL; + } + } + + info = gst_vdp_mpeg4_dec_fill_info (mpeg4_dec, mpeg4_frame, &vop); + bufs[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + bufs[0].bitstream = GST_BUFFER_DATA (mpeg4_frame->vop_buf); + bufs[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg4_frame->vop_buf); + + ret = gst_vdp_decoder_render (GST_VDP_DECODER (base_video_decoder), + (VdpPictureInfo *) & info, 1, bufs, &video_buf); + if (ret != GST_FLOW_OK) { + gst_base_video_decoder_skip_frame (base_video_decoder, frame); + return ret; + } + + frame->src_buffer = GST_BUFFER_CAST (video_buf); + + if (vop.coding_type == B_VOP) + ret = gst_base_video_decoder_finish_frame (base_video_decoder, frame); + else { + gst_video_frame_ref (GST_VIDEO_FRAME_CAST (mpeg4_frame)); + mpeg4_dec->b_frame = mpeg4_frame; + ret = GST_FLOW_OK; + } + + return ret; +} + +static GstFlowReturn +gst_vdp_mpeg4_dec_parse_data (GstBaseVideoDecoder * base_video_decoder, + GstBuffer * buf, gboolean at_eos) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + guint8 start_code; + GstMpeg4Frame *mpeg4_frame; + + GstFlowReturn ret = GST_FLOW_OK; + + /* start code prefix */ + SKIP (&reader, 24); + + /* start_code */ + READ_UINT8 (&reader, start_code, 8); + + mpeg4_frame = + GST_MPEG4_FRAME_CAST (gst_base_video_decoder_get_current_frame + (base_video_decoder)); + + /* collect packages */ + if (start_code == MPEG4_PACKET_VOS) { + if (mpeg4_frame->vop_buf) + ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, + (GstVideoFrame **) & mpeg4_frame); + + gst_buffer_replace (&mpeg4_frame->vos_buf, buf); + } + + else if (start_code == MPEG4_PACKET_EVOS) { + if (mpeg4_frame->vop_buf) + ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, + (GstVideoFrame **) & mpeg4_frame); + } + + else if (start_code == MPEG4_PACKET_VO) + gst_buffer_replace (&mpeg4_frame->vo_buf, buf); + + else if (start_code >= MPEG4_PACKET_VOL_MIN && + start_code <= MPEG4_PACKET_VOL_MAX) + gst_buffer_replace (&mpeg4_frame->vol_buf, buf); + + else if (start_code == MPEG4_PACKET_GOV) { + if (mpeg4_frame->vop_buf) + ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, + (GstVideoFrame **) & mpeg4_frame); + + gst_buffer_replace (&mpeg4_frame->gov_buf, buf); + } + + else if (start_code == MPEG4_PACKET_VOP) { + if (mpeg4_frame->vop_buf) + ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, + (GstVideoFrame **) & mpeg4_frame); + + mpeg4_frame->vop_buf = buf; + } + + else + gst_buffer_unref (buf); + + + if (at_eos && mpeg4_frame->vop_buf) + ret = gst_base_video_decoder_have_frame (base_video_decoder, TRUE, + (GstVideoFrame **) & mpeg4_frame); + + return ret; + +error: + gst_buffer_unref (buf); + GST_WARNING ("error parsing packet"); + return GST_FLOW_OK; +} + +static gint +gst_vdp_mpeg4_dec_scan_for_sync (GstBaseVideoDecoder * base_video_decoder, + GstAdapter * adapter) +{ + gint m; + + m = gst_adapter_masked_scan_uint32 (adapter, 0xffffff00, 0x00000100, 0, + gst_adapter_available (adapter)); + if (m == -1) + return gst_adapter_available (adapter) - SYNC_CODE_SIZE; + + return m; +} + +static GstBaseVideoDecoderScanResult +gst_vdp_mpeg4_dec_scan_for_packet_end (GstBaseVideoDecoder * base_video_decoder, + GstAdapter * adapter, guint * size, gboolean at_eos) +{ + guint8 *data; + guint32 sync_code; + + data = g_slice_alloc (SYNC_CODE_SIZE); + gst_adapter_copy (adapter, data, 0, SYNC_CODE_SIZE); + sync_code = ((data[0] << 16) | (data[1] << 8) | data[2]); + + if (sync_code != 0x000001) + return GST_BASE_VIDEO_DECODER_SCAN_RESULT_LOST_SYNC; + + *size = gst_adapter_masked_scan_uint32 (adapter, 0xffffff00, 0x00000100, + SYNC_CODE_SIZE, gst_adapter_available (adapter) - SYNC_CODE_SIZE); + + if (*size == -1) + return GST_BASE_VIDEO_DECODER_SCAN_RESULT_NEED_DATA; + + return GST_BASE_VIDEO_DECODER_SCAN_RESULT_OK; +} + +static GstVideoFrame * +gst_vdp_mpeg4_dec_create_frame (GstBaseVideoDecoder * base_video_decoder) +{ + return GST_VIDEO_FRAME_CAST (gst_mpeg4_frame_new ()); +} + +static gboolean +gst_vdp_mpeg4_dec_flush (GstBaseVideoDecoder * base_video_decoder) +{ + GstVdpMpeg4Dec *mpeg4_dec = GST_VDP_MPEG4_DEC (base_video_decoder); + + if (mpeg4_dec->b_frame) { + gst_video_frame_unref (GST_VIDEO_FRAME_CAST (mpeg4_dec->b_frame)); + mpeg4_dec->b_frame = NULL; + } + + if (mpeg4_dec->f_frame) { + gst_video_frame_unref (GST_VIDEO_FRAME_CAST (mpeg4_dec->f_frame)); + mpeg4_dec->f_frame = NULL; + } + + return TRUE; +} + +static gboolean +gst_vdp_mpeg4_dec_start (GstBaseVideoDecoder * base_video_decoder) +{ + GstVdpMpeg4Dec *mpeg4_dec = GST_VDP_MPEG4_DEC (base_video_decoder); + + mpeg4_dec->is_configured = FALSE; + mpeg4_dec->tframe = GST_CLOCK_TIME_NONE; + + mpeg4_dec->b_frame = NULL; + mpeg4_dec->f_frame = NULL; + + return GST_BASE_VIDEO_DECODER_CLASS + (parent_class)->start (base_video_decoder); +} + +static gboolean +gst_vdp_mpeg4_dec_stop (GstBaseVideoDecoder * base_video_decoder) +{ + return GST_BASE_VIDEO_DECODER_CLASS (parent_class)->stop (base_video_decoder); +} + +static void +gst_vdp_mpeg4_dec_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "VDPAU Mpeg4 Decoder", + "Decoder", + "Decode mpeg4 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)); +} + +/* initialize the vdpaumpeg4decoder's class */ +static void +gst_vdp_mpeg4_dec_class_init (GstVdpMpeg4DecClass * klass) +{ + GstBaseVideoDecoderClass *base_video_decoder_class; + + base_video_decoder_class = GST_BASE_VIDEO_DECODER_CLASS (klass); + + base_video_decoder_class->start = gst_vdp_mpeg4_dec_start; + base_video_decoder_class->stop = gst_vdp_mpeg4_dec_stop; + base_video_decoder_class->flush = gst_vdp_mpeg4_dec_flush; + + base_video_decoder_class->create_frame = gst_vdp_mpeg4_dec_create_frame; + + base_video_decoder_class->scan_for_sync = gst_vdp_mpeg4_dec_scan_for_sync; + base_video_decoder_class->scan_for_packet_end = + gst_vdp_mpeg4_dec_scan_for_packet_end; + base_video_decoder_class->parse_data = gst_vdp_mpeg4_dec_parse_data; + + base_video_decoder_class->handle_frame = gst_vdp_mpeg4_dec_handle_frame; +} + +static void +gst_vdp_mpeg4_dec_init (GstVdpMpeg4Dec * mpeg4_dec, + GstVdpMpeg4DecClass * gclass) +{ +} diff --git a/sys/vdpau/mpeg4/gstvdpmpeg4dec.h b/sys/vdpau/mpeg4/gstvdpmpeg4dec.h new file mode 100644 index 000000000..7aa8f5a8d --- /dev/null +++ b/sys/vdpau/mpeg4/gstvdpmpeg4dec.h @@ -0,0 +1,62 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_VDP_MPEG4_DEC_H__ +#define __GST_VDP_MPEG4_DEC_H__ + +#include <gst/gst.h> + +#include "../gstvdp/gstvdpdecoder.h" + +#include "mpeg4util.h" +#include "gstmpeg4frame.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDP_MPEG4_DEC (gst_vdp_mpeg4_dec_get_type()) +#define GST_VDP_MPEG4_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG4_DEC,GstVdpMpeg4Dec)) +#define GST_VDP_MPEG4_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG4_DEC,GstVdpMpeg4DecClass)) +#define GST_IS_VDP_MPEG4_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG4_DEC)) +#define GST_IS_VDP_MPEG4_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG4_DEC)) + +typedef struct _GstVdpMpeg4Dec GstVdpMpeg4Dec; +typedef struct _GstVdpMpeg4DecClass GstVdpMpeg4DecClass; + +struct _GstVdpMpeg4Dec +{ + GstVdpDecoder vdp_decoder; + + gboolean is_configured; + Mpeg4VideoObjectLayer vol; + GstClockTime tframe; + + GstMpeg4Frame *f_frame, *b_frame; +}; + +struct _GstVdpMpeg4DecClass +{ + GstVdpDecoderClass vdp_decoder_class; +}; + +GType gst_vdp_mpeg4_dec_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDP_MPEG4_DEC_H__ */ diff --git a/sys/vdpau/mpeg4/mpeg4util.c b/sys/vdpau/mpeg4/mpeg4util.c new file mode 100644 index 000000000..d7e57b639 --- /dev/null +++ b/sys/vdpau/mpeg4/mpeg4util.c @@ -0,0 +1,466 @@ +/* +* GStreamer +* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public +* License along with this library; if not, write to the +* Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "mpeg4util.h" + +GST_DEBUG_CATEGORY_EXTERN (gst_vdp_mpeg4_dec_debug); +#define GST_CAT_DEFAULT gst_vdp_mpeg4_dec_debug + +const guint8 default_intra_quant_mat[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45 +}; + +const guint8 default_non_intra_quant_mat[64] = { + 6, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33, +}; + +const guint8 mpeg4_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 +}; + +gboolean +mpeg4_util_parse_VOP (GstBuffer * buf, Mpeg4VideoObjectLayer * vol, + Mpeg4VideoObjectPlane * vop) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + + guint8 vop_start_code; + guint8 modulo_time_base; + + /* set default values */ + vop->modulo_time_base = 0; + vop->rounding_type = 0; + + /* start code prefix */ + SKIP (&reader, 24); + + READ_UINT8 (&reader, vop_start_code, 8); + if (vop_start_code != MPEG4_PACKET_VOP) + goto wrong_start_code; + + READ_UINT8 (&reader, vop->coding_type, 2); + + READ_UINT8 (&reader, modulo_time_base, 1); + while (modulo_time_base) { + vop->modulo_time_base++; + + READ_UINT8 (&reader, modulo_time_base, 1); + } + + /* marker bit */ + SKIP (&reader, 1); + READ_UINT16 (&reader, vop->time_increment, vol->vop_time_increment_bits); + /* marker bit */ + SKIP (&reader, 1); + + READ_UINT8 (&reader, vop->coded, 1); + if (!vop->coded) + return TRUE; + + if (vop->coding_type == P_VOP) + READ_UINT8 (&reader, vop->rounding_type, 1); + + READ_UINT8 (&reader, vop->intra_dc_vlc_thr, 3); + + if (vol->interlaced) { + READ_UINT8 (&reader, vop->top_field_first, 1); + READ_UINT8 (&reader, vop->alternate_vertical_scan_flag, 1); + } + + READ_UINT16 (&reader, vop->quant, vol->quant_precision); + + if (vop->coding_type != I_VOP) { + READ_UINT8 (&reader, vop->fcode_forward, 3); + CHECK_ALLOWED (vop->fcode_forward, 1, 7); + } + + if (vop->coding_type == B_VOP) { + READ_UINT8 (&reader, vop->fcode_backward, 3); + CHECK_ALLOWED (vop->fcode_backward, 1, 7); + } + + return TRUE; + +error: + GST_WARNING ("error parsing \"Video Object Plane\""); + return FALSE; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + goto error; +} + +gboolean +mpeg4_util_parse_GOV (GstBuffer * buf, Mpeg4GroupofVideoObjectPlane * gov) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + + guint8 gov_start_code; + + /* start code prefix */ + SKIP (&reader, 24); + + READ_UINT8 (&reader, gov_start_code, 8); + if (gov_start_code != MPEG4_PACKET_GOV) + goto wrong_start_code; + + READ_UINT8 (&reader, gov->hours, 5); + READ_UINT8 (&reader, gov->minutes, 6); + /* marker bit */ + SKIP (&reader, 1); + READ_UINT8 (&reader, gov->seconds, 6); + + READ_UINT8 (&reader, gov->closed, 1); + READ_UINT8 (&reader, gov->broken_link, 1); + + return TRUE; + +error: + GST_WARNING ("error parsing \"Group of Video Object Plane\""); + return FALSE; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + goto error; +} + +static void +mpeg4_util_par_from_info (guint8 aspect_ratio_info, guint8 * par_n, + guint8 * par_d) +{ + switch (aspect_ratio_info) { + case 0x02: + *par_n = 12; + *par_d = 11; + break; + case 0x03: + *par_n = 10; + *par_d = 11; + break; + case 0x04: + *par_n = 16; + *par_d = 11; + break; + case 0x05: + *par_n = 40; + *par_d = 33; + break; + + case 0x01: + default: + *par_n = 1; + *par_d = 1; + } +} + +static gboolean +mpeg4_util_parse_quant (GstBitReader * reader, guint8 quant_mat[64], + const guint8 default_quant_mat[64]) +{ + guint8 load_quant_mat; + + READ_UINT8 (reader, load_quant_mat, 1); + if (load_quant_mat) { + guint i; + guint8 val; + + val = 1; + for (i = 0; i < 64; i++) { + + if (val != 0) + READ_UINT8 (reader, val, 8); + + if (val == 0) { + if (i == 0) + goto invalid_quant_mat; + quant_mat[mpeg4_zigzag_8x8[i]] = quant_mat[mpeg4_zigzag_8x8[i - 1]]; + } else + quant_mat[mpeg4_zigzag_8x8[i]] = val; + } + } else + memcpy (quant_mat, default_quant_mat, 64); + + return TRUE; + +error: + GST_WARNING ("error parsing quant matrix"); + return FALSE; + +invalid_quant_mat: + GST_WARNING ("the first value should be non zero"); + goto error; +} + +gboolean +mpeg4_util_parse_VOL (GstBuffer * buf, Mpeg4VisualObject * vo, + Mpeg4VideoObjectLayer * vol) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + + guint8 video_object_layer_start_code; + guint8 aspect_ratio_info; + guint8 control_parameters; + guint8 not_8_bit; + + /* set default values */ + vol->verid = vo->verid; + vol->priority = vo->priority; + + vol->low_delay = FALSE; + vol->chroma_format = 1; + vol->vbv_parameters = FALSE; + vol->quant_precision = 5; + vol->bits_per_pixel = 8; + vol->quarter_sample = FALSE; + + /* start code prefix */ + SKIP (&reader, 24); + + READ_UINT8 (&reader, video_object_layer_start_code, 8); + if (!(video_object_layer_start_code >= MPEG4_PACKET_VOL_MIN && + video_object_layer_start_code <= MPEG4_PACKET_VOL_MAX)) + goto wrong_start_code; + + READ_UINT8 (&reader, vol->random_accesible_vol, 1); + READ_UINT8 (&reader, vol->video_object_type_indication, 8); + + READ_UINT8 (&reader, vol->is_object_layer_identifier, 1); + if (vol->is_object_layer_identifier) { + READ_UINT8 (&reader, vol->verid, 4); + READ_UINT8 (&reader, vol->priority, 3); + } + + READ_UINT8 (&reader, aspect_ratio_info, 4); + if (aspect_ratio_info != 0xff) + mpeg4_util_par_from_info (aspect_ratio_info, &vol->par_n, &vol->par_d); + + else { + READ_UINT8 (&reader, vol->par_n, 8); + CHECK_ALLOWED (vol->par_n, 1, 255); + READ_UINT8 (&reader, vol->par_d, 8); + CHECK_ALLOWED (vol->par_d, 1, 255); + } + + READ_UINT8 (&reader, control_parameters, 1); + if (control_parameters) { + READ_UINT8 (&reader, vol->chroma_format, 2); + READ_UINT8 (&reader, vol->low_delay, 1); + + READ_UINT8 (&reader, vol->vbv_parameters, 1); + if (vol->vbv_parameters) { + guint16 first_half, latter_half; + guint8 latter_part; + + READ_UINT16 (&reader, first_half, 15); + SKIP (&reader, 1); + READ_UINT16 (&reader, latter_half, 15); + SKIP (&reader, 1); + vol->bit_rate = (first_half << 15) | latter_half; + + READ_UINT16 (&reader, first_half, 15); + SKIP (&reader, 1); + READ_UINT8 (&reader, latter_part, 3); + SKIP (&reader, 1); + vol->vbv_buffer_size = (first_half << 15) | latter_part; + } + } + + READ_UINT8 (&reader, vol->shape, 2); + if (vol->shape != 0x0) + goto invalid_shape; + + /* marker_bit */ + SKIP (&reader, 1); + READ_UINT16 (&reader, vol->vop_time_increment_resolution, 16); + CHECK_ALLOWED (vol->vop_time_increment_resolution, 1, G_MAXUINT16); + vol->vop_time_increment_bits = + g_bit_storage (vol->vop_time_increment_resolution); + /* marker_bit */ + SKIP (&reader, 1); + + READ_UINT8 (&reader, vol->fixed_vop_rate, 1); + if (vol->fixed_vop_rate) + READ_UINT16 (&reader, vol->fixed_vop_time_increment, + vol->vop_time_increment_bits); + + /* marker bit */ + SKIP (&reader, 1); + READ_UINT16 (&reader, vol->width, 13); + /* marker bit */ + SKIP (&reader, 1); + READ_UINT16 (&reader, vol->height, 13); + /* marker bit */ + SKIP (&reader, 1); + + READ_UINT8 (&reader, vol->interlaced, 1); + READ_UINT8 (&reader, vol->obmc_disable, 1); + + if (vol->verid == 0x1) { + READ_UINT8 (&reader, vol->sprite_enable, 1); + } else + READ_UINT8 (&reader, vol->sprite_enable, 2); + + if (vol->sprite_enable != 0x0) + goto invalid_sprite_enable; + + READ_UINT8 (&reader, not_8_bit, 1); + if (not_8_bit) { + READ_UINT8 (&reader, vol->quant_precision, 4); + CHECK_ALLOWED (vol->quant_precision, 3, 9); + + READ_UINT8 (&reader, vol->bits_per_pixel, 4); + CHECK_ALLOWED (vol->bits_per_pixel, 4, 12); + } + + + READ_UINT8 (&reader, vol->quant_type, 1); + if (vol->quant_type) { + if (!mpeg4_util_parse_quant (&reader, vol->intra_quant_mat, + default_intra_quant_mat)) + goto error; + + if (!mpeg4_util_parse_quant (&reader, vol->non_intra_quant_mat, + default_non_intra_quant_mat)) + goto error; + } + + if (vol->verid != 0x1) + READ_UINT8 (&reader, vol->quarter_sample, 1); + + READ_UINT8 (&reader, vol->complexity_estimation_disable, 1); + if (!vol->complexity_estimation_disable) + goto complexity_estimation_error; + + READ_UINT8 (&reader, vol->resync_marker_disable, 1); + + return TRUE; + +error: + GST_WARNING ("error parsing \"Video Object Layer\""); + return FALSE; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + goto error; + +invalid_shape: + GST_WARNING ("we only support rectangular shape"); + goto error; + +invalid_sprite_enable: + GST_WARNING ("we only support sprite_enable == 0"); + goto error; + +complexity_estimation_error: + GST_WARNING ("don't support complexity estimation"); + goto error; +} + +gboolean +mpeg4_util_parse_VO (GstBuffer * buf, Mpeg4VisualObject * vo) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + + guint8 visual_object_start_code; + guint8 is_visual_object_identifier; + + /* set defualt values */ + vo->verid = 0x1; + vo->priority = 1; + + /* start code prefix */ + SKIP (&reader, 24); + + READ_UINT8 (&reader, visual_object_start_code, 8); + if (visual_object_start_code != MPEG4_PACKET_VO) + goto wrong_start_code; + + READ_UINT8 (&reader, is_visual_object_identifier, 1); + if (is_visual_object_identifier) { + READ_UINT8 (&reader, vo->verid, 4); + READ_UINT8 (&reader, vo->priority, 3); + } + + READ_UINT8 (&reader, vo->type, 4); + + return TRUE; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + return FALSE; + +error: + GST_WARNING ("error parsing \"Visual Object\""); + return FALSE; +} + +gboolean +mpeg4_util_parse_VOS (GstBuffer * buf, Mpeg4VisualObjectSequence * vos) +{ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + + guint8 visual_object_sequence_start_code; + + /* start code prefix */ + SKIP (&reader, 24); + + READ_UINT8 (&reader, visual_object_sequence_start_code, 8); + if (visual_object_sequence_start_code != MPEG4_PACKET_VOS) + goto wrong_start_code; + + READ_UINT8 (&reader, vos->profile_and_level_indication, 8); + + return TRUE; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + return FALSE; + +error: + GST_WARNING ("error parsing \"Visual Object\""); + return FALSE; +} diff --git a/sys/vdpau/mpeg4/mpeg4util.h b/sys/vdpau/mpeg4/mpeg4util.h new file mode 100644 index 000000000..a069003b1 --- /dev/null +++ b/sys/vdpau/mpeg4/mpeg4util.h @@ -0,0 +1,179 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_MPEG4UTIL_H__ +#define __GST_MPEG4UTIL_H__ + +#include <gst/gst.h> +#include <gst/base/gstbitreader.h> + +#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_bit_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_bit_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_bit_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_bit_reader_get_bits_uint64 (reader, &val, nbits)) { \ + GST_WARNING ("failed to read uint64, nbits: %d", nbits); \ + goto error; \ + } \ +} + +#define SKIP(reader, nbits) { \ + if (!gst_bit_reader_skip (reader, nbits)) { \ + GST_WARNING ("failed to skip nbits: %d", nbits); \ + goto error; \ + } \ +} + +typedef struct _Mpeg4VisualObjectSequence Mpeg4VisualObjectSequence; +typedef struct _Mpeg4VisualObject Mpeg4VisualObject; +typedef struct _Mpeg4VideoObjectLayer Mpeg4VideoObjectLayer; +typedef struct _Mpeg4GroupofVideoObjectPlane Mpeg4GroupofVideoObjectPlane; +typedef struct _Mpeg4VideoObjectPlane Mpeg4VideoObjectPlane; + +#define MPEG4_PACKET_VOL_MIN 0x20 +#define MPEG4_PACKET_VOL_MAX 0x2f + +#define MPEG4_PACKET_VOS 0xb0 +#define MPEG4_PACKET_EVOS 0xb1 +#define MPEG4_PACKET_GOV 0xb3 +#define MPEG4_PACKET_VO 0xb5 +#define MPEG4_PACKET_VOP 0xb6 + +#define I_VOP 0x0 +#define P_VOP 0x1 +#define B_VOP 0x2 +#define S_VOP 0x3 + +struct _Mpeg4VisualObjectSequence { + guint8 profile_and_level_indication; +}; + +struct _Mpeg4VisualObject { + guint8 verid; + guint8 priority; + guint8 type; +}; + +struct _Mpeg4VideoObjectLayer { + guint8 random_accesible_vol; + guint8 video_object_type_indication; + + guint8 is_object_layer_identifier; + /* if is_object_layer_identifier */ + guint8 verid; + guint8 priority; + + guint8 par_n; + guint8 par_d; + + guint8 chroma_format; + guint8 low_delay; + guint8 vbv_parameters; + /* if vbv_parameters */ + guint32 bit_rate; + guint32 vbv_buffer_size; + + guint8 shape; + + guint16 vop_time_increment_resolution; + guint8 vop_time_increment_bits; + guint8 fixed_vop_rate; + /* if fixed_vop_rate */ + guint16 fixed_vop_time_increment; + + guint16 width; + guint16 height; + guint8 interlaced; + guint8 obmc_disable; + + guint8 sprite_enable; + + guint8 quant_precision; + guint8 bits_per_pixel; + + guint8 quant_type; + guint8 intra_quant_mat[64]; + guint8 non_intra_quant_mat[64]; + + guint8 quarter_sample; + guint8 complexity_estimation_disable; + guint8 resync_marker_disable; +}; + +struct _Mpeg4GroupofVideoObjectPlane { + guint8 hours; + guint8 minutes; + guint8 seconds; + + guint8 closed; + guint8 broken_link; +}; + +struct _Mpeg4VideoObjectPlane { + guint8 coding_type; + guint8 modulo_time_base; + guint16 time_increment; + + guint8 coded; + guint8 rounding_type; + guint8 intra_dc_vlc_thr; + + guint8 top_field_first; + guint8 alternate_vertical_scan_flag; + + guint16 quant; + + guint8 fcode_forward; + guint8 fcode_backward; +}; + +gboolean mpeg4_util_parse_VOP (GstBuffer *buf, Mpeg4VideoObjectLayer *vol, Mpeg4VideoObjectPlane *vop); +gboolean mpeg4_util_parse_GOV (GstBuffer *buf, Mpeg4GroupofVideoObjectPlane *gov); +gboolean mpeg4_util_parse_VOL (GstBuffer *buf, Mpeg4VisualObject *vo, Mpeg4VideoObjectLayer *vol); +gboolean mpeg4_util_parse_VO (GstBuffer *buf, Mpeg4VisualObject *vo); +gboolean mpeg4_util_parse_VOS (GstBuffer *buf, Mpeg4VisualObjectSequence *vos); + +#endif /* __GST_MPEG4UTIL_H__ */
\ No newline at end of file |