mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
vdpau: add mpeg4 part2 decoder
This commit is contained in:
parent
49ce307cb7
commit
8612a936ec
8 changed files with 1374 additions and 2 deletions
|
@ -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
|
||||
h264/gstvdph264dec.h \
|
||||
mpeg4/mpeg4util.h \
|
||||
mpeg4/gstmpeg4frame.h \
|
||||
mpeg4/gstvdpmpeg4dec.h
|
||||
|
|
|
@ -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",
|
||||
|
|
109
sys/vdpau/mpeg4/gstmpeg4frame.c
Normal file
109
sys/vdpau/mpeg4/gstmpeg4frame.c
Normal file
|
@ -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;
|
||||
}
|
64
sys/vdpau/mpeg4/gstmpeg4frame.h
Normal file
64
sys/vdpau/mpeg4/gstmpeg4frame.h
Normal file
|
@ -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
|
483
sys/vdpau/mpeg4/gstvdpmpeg4dec.c
Normal file
483
sys/vdpau/mpeg4/gstvdpmpeg4dec.c
Normal file
|
@ -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)
|
||||
{
|
||||
}
|
62
sys/vdpau/mpeg4/gstvdpmpeg4dec.h
Normal file
62
sys/vdpau/mpeg4/gstvdpmpeg4dec.h
Normal file
|
@ -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__ */
|
466
sys/vdpau/mpeg4/mpeg4util.c
Normal file
466
sys/vdpau/mpeg4/mpeg4util.c
Normal file
|
@ -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;
|
||||
}
|
179
sys/vdpau/mpeg4/mpeg4util.h
Normal file
179
sys/vdpau/mpeg4/mpeg4util.h
Normal file
|
@ -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__ */
|
Loading…
Reference in a new issue