From f70ddb66050244bdc0833d7cdc6c1b2e64f425ff Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 29 Mar 2009 15:28:06 +0200 Subject: vdpau: create VdpDecoder in set_caps add more functions for parsing mpeg --- sys/vdpau/gstvdpaudecoder.c | 128 ++++++++++++++++++++++++++++------------ sys/vdpau/gstvdpaudecoder.h | 15 +++-- sys/vdpau/gstvdpaumpegdecoder.c | 25 ++++++-- sys/vdpau/gstvdpaumpegdecoder.h | 2 +- sys/vdpau/mpegutil.c | 115 ++++++++++++++++++++++++++++++++++++ sys/vdpau/mpegutil.h | 39 +++++++++++- 6 files changed, 276 insertions(+), 48 deletions(-) (limited to 'sys/vdpau') diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 007837f4..c13b0173 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -26,10 +26,8 @@ #include #include -#include -#include - #include "gstvdpaudecoder.h" +#include GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); #define GST_CAT_DEFAULT gst_vdpaudecoder_debug @@ -173,8 +171,9 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get VDPAU capabilites"), - ("Could not query video surface capabilities")); + ("Could not get query VDPAU video surface capabilites"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); return NULL; } @@ -191,8 +190,9 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get VDPAU capabilites"), - ("Could not query video surface ycbcr capabilities")); + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); return NULL; } @@ -220,15 +220,45 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) static gboolean gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) { - Display *display; - int screen; - VdpauFunctions *f; + gint screen; VdpStatus status; + gint i; + VdpauFunctions *f; GstCaps *caps; + typedef struct + { + int id; + void *func; + } VdpFunction; + + VdpFunction vdp_function[] = { + {VDP_FUNC_ID_DEVICE_DESTROY, &dec->functions->vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, + &dec->functions->vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, + &dec->functions->vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &dec->functions->vdp_video_surface_query_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + &dec->functions->vdp_video_surface_query_ycbcr_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + &dec->functions->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, + &dec->functions->vdp_video_surface_get_parameters}, + {VDP_FUNC_ID_DECODER_CREATE, &dec->functions->vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &dec->functions->vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &dec->functions->vdp_decoder_destroy}, + {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &dec->functions->vdp_decoder_query_capabilities}, + {VDP_FUNC_ID_DECODER_GET_PARAMETERS, + &dec->functions->vdp_decoder_get_parameters}, + {0, NULL} + }; + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ - display = XOpenDisplay (dec->display); - if (!display) { + dec->display = XOpenDisplay (dec->display_name); + if (!dec->display) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not open display")); return FALSE; @@ -236,55 +266,78 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) f = dec->functions; - screen = DefaultScreen (display); + screen = DefaultScreen (dec->display); status = - vdp_device_create_x11 (display, screen, &dec->device, + vdp_device_create_x11 (dec->display, screen, &dec->device, &f->vdp_get_proc_address); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not create VDPAU device")); - XCloseDisplay (display); + XCloseDisplay (dec->display); + dec->display = NULL; return FALSE; } - XCloseDisplay (display); - - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - (void **) &f->vdp_video_surface_query_capabilities); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - (void **) &f->vdp_video_surface_query_ycbcr_capabilities); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_DEVICE_DESTROY, (void **) &f->vdp_device_destroy); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - (void **) &f->vdp_video_surface_get_bits_ycbcr); - caps = gst_vdpaudecoder_get_vdpau_support (dec); - if (!caps) { - f->vdp_device_destroy (dec->device); - dec->device = 0; - return FALSE; + status = f->vdp_get_proc_address (dec->device, + VDP_FUNC_ID_GET_ERROR_STRING, (void **) &f->vdp_get_error_string); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could'nt get function pointer from vdpau"), + ("Couldn't get vdp_get_error_string function pointer")); + goto error; } + for (i = 0; vdp_function[i].func != NULL; i++) { + status = f->vdp_get_proc_address (dec->device, + vdp_function[i].id, vdp_function[i].func); + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could not get function pointer from vdpau"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + goto error; + } + } + + caps = gst_vdpaudecoder_get_vdpau_support (dec); + if (!caps) + goto error; + dec->src_caps = caps; return TRUE; + +error: + f->vdp_device_destroy (dec->device); + dec->device = VDP_INVALID_HANDLE; + + return FALSE; + } static GstStateChangeReturn gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) { GstVdpauDecoder *dec; + VdpauFunctions *f; dec = GST_VDPAU_DECODER (element); + f = dec->functions; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_vdpaudecoder_init_vdpau (dec)) return GST_STATE_CHANGE_FAILURE; break; + case GST_STATE_CHANGE_READY_TO_NULL: + f->vdp_device_destroy (dec->device); + XCloseDisplay (dec->display); + + dec->device = VDP_INVALID_HANDLE; + dec->display = NULL; + break; default: break; } @@ -403,8 +456,9 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) static void gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) { + dec->display_name = NULL; dec->display = NULL; - dec->device = 0; + dec->device = VDP_INVALID_HANDLE; dec->silent = FALSE; dec->src_caps = NULL; @@ -433,8 +487,8 @@ gst_vdpaudecoder_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DISPLAY: - g_free (dec->display); - dec->display = g_value_dup_string (value); + g_free (dec->display_name); + dec->display_name = g_value_dup_string (value); break; case PROP_SILENT: dec->silent = g_value_get_boolean (value); @@ -453,7 +507,7 @@ gst_vdpaudecoder_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DISPLAY: - g_value_set_string (value, dec->display); + g_value_set_string (value, dec->display_name); break; case PROP_SILENT: g_value_set_boolean (value, dec->silent); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 2c1a274f..5cd83042 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -25,6 +25,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -43,7 +44,8 @@ typedef struct _VdpauFunctions VdpauFunctions; struct _GstVdpauDecoder { GstElement element; - gchar *display; + gchar *display_name; + Display *display; VdpDevice device; VdpauFunctions *functions; @@ -66,17 +68,22 @@ struct _GstVdpauDecoderClass { }; struct _VdpauFunctions { + VdpDeviceDestroy *vdp_device_destroy; VdpGetProcAddress *vdp_get_proc_address; - + VdpGetErrorString *vdp_get_error_string; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - VdpDeviceDestroy *vdp_device_destroy; - VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; + VdpDecoderGetParameters *vdp_decoder_get_parameters; }; GType gst_vdpaudecoder_get_type (void); diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index e5da459f..6ff9b42a 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -104,13 +104,16 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) GstVdpauMpegDecoder *mpeg_dec; GstStructure *structure; gint version; + VdpDecoderProfile profile; + VdpauFunctions *f; + VdpStatus status; mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "mpegversion", &version); if (version == 1) - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG1; + profile = VDP_DECODER_PROFILE_MPEG1; else { const GValue *value; @@ -123,14 +126,24 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); switch (hdr.profile) { case 5: - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; default: - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; break; } } + f = dec->functions; + status = f->vdp_decoder_create (dec->device, profile, dec->width, + dec->height, 2, &mpeg_dec->decoder); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not create vdpau decoder"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + return FALSE; + } return TRUE; } @@ -174,10 +187,12 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) } static void -gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * filter, +gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, GstVdpauMpegDecoderClass * gclass) { - filter->silent = FALSE; + mpeg_dec->silent = FALSE; + + mpeg_dec->decoder = VDP_INVALID_HANDLE; } static void diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 830cc671..0207ce31 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -66,7 +66,7 @@ struct _GstVdpauMpegDecoder gboolean silent; - VdpDecoderProfile profile; + VdpDecoder decoder; }; struct _GstVdpauMpegDecoderClass diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 274fa853..aa77a426 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -18,8 +18,41 @@ * Boston, MA 02111-1307, USA. */ +#include + #include "mpegutil.h" +/* default intra quant matrix, in zig-zag order */ +static const guint8 default_intra_quantizer_matrix[64] = { + 8, + 16, 16, + 19, 16, 19, + 22, 22, 22, 22, + 22, 22, 26, 24, 26, + 27, 27, 27, 26, 26, 26, + 26, 27, 27, 27, 29, 29, 29, + 34, 34, 34, 29, 29, 29, 27, 27, + 29, 29, 32, 32, 34, 34, 37, + 38, 37, 35, 35, 34, 35, + 38, 38, 40, 40, 40, + 48, 48, 46, 46, + 56, 56, 58, + 69, 69, + 83 +}; + +guint8 mpeg2_scan[64] = { + /* Zig-Zag scan pattern */ + 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 +}; + guint8 bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; guint32 @@ -133,6 +166,7 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) /* Parse a Sequence Extension */ guint8 horiz_size_ext, vert_size_ext; guint8 fps_n_ext, fps_d_ext; + gint i, offset; if (G_UNLIKELY ((end - data) < 6)) /* need at least 10 bytes, minus 4 for the start code 000001b5 */ @@ -148,6 +182,23 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) hdr->fps_d *= (fps_d_ext + 1); hdr->width += (horiz_size_ext << 12); hdr->height += (vert_size_ext << 12); + + if (read_bits (data + 7, 6, 1)) { + for (i = 0; i < 64; i++) + hdr->intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 7 + i, 7, 8); + offset = 64; + } else + memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, + 64); + + if (read_bits (data + 7 + offset, 7, 1)) { + for (i = 0; i < 64; i++) + hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 8 + offset + i, 0, 8); + } else + memset (hdr->non_intra_quantizer_matrix, 0, 64); + break; } default: @@ -225,3 +276,67 @@ mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) return TRUE; } + +gboolean +mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY ((end - data) < 6)) + return FALSE; /* Packet too small */ + + code = GST_READ_UINT32_BE (data); + if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE))) + return FALSE; + + /* Skip the start code */ + data += 4; + + hdr->pic_type = (data[1] >> 3) & 0x07; + if (hdr->pic_type == 0 || hdr->pic_type > 4) + return FALSE; /* Corrupted picture packet */ + + if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { + if (G_UNLIKELY ((end - data) < 7)) + return FALSE; /* packet too small */ + + hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); + hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); + + if (hdr->pic_type == B_FRAME) { + hdr->full_pel_backward_vector = read_bits (data + 4, 1, 1); + hdr->f_code[1][0] = hdr->f_code[1][1] = read_bits (data + 4, 2, 3); + } + } else { + hdr->full_pel_forward_vector = 0; + hdr->full_pel_backward_vector = 0; + } + + return TRUE; +} + +gboolean +mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, + guint8 * end) +{ + if (G_UNLIKELY ((end - data) < 7)) + return FALSE; /* Packet too small */ + + if (G_UNLIKELY (read_bits (data, 0, 4) != MPEG_PACKET_EXT_PICTURE_CODING)) + return FALSE; + + ext->f_code[0][0] = read_bits (data, 4, 4); + ext->f_code[0][1] = read_bits (data + 1, 0, 4); + ext->f_code[1][0] = read_bits (data + 1, 4, 4); + ext->f_code[1][1] = read_bits (data + 2, 0, 4); + + ext->intra_dc_precision = read_bits (data + 2, 4, 2); + ext->picture_structure = read_bits (data + 2, 6, 2); + ext->top_field_first = read_bits (data + 3, 0, 1); + ext->frame_pred_frame_dct = read_bits (data + 3, 1, 1); + ext->concealment_motion_vectors = read_bits (data + 3, 2, 1); + ext->q_scale_type = read_bits (data + 3, 3, 1); + ext->intra_vlc_format = read_bits (data + 3, 4, 1); + + return TRUE; +} diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index f0f8aca0..929e4fbb 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -24,6 +24,8 @@ #include typedef struct MPEGSeqHdr MPEGSeqHdr; +typedef struct MPEGPictureHdr MPEGPictureHdr; +typedef struct MPEGPictureExt MPEGPictureExt; /* Packet ID codes for different packet types we * care about */ @@ -40,6 +42,12 @@ typedef struct MPEGSeqHdr MPEGSeqHdr; #define MPEG_PACKET_EXT_SEQUENCE 0x01 #define MPEG_PACKET_EXT_SEQUENCE_DISPLAY 0x02 #define MPEG_PACKET_EXT_QUANT_MATRIX 0x03 +#define MPEG_PACKET_EXT_PICTURE_CODING 0x08 + +/* frame types */ +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 struct MPEGSeqHdr { @@ -55,9 +63,38 @@ struct MPEGSeqHdr /* mpeg2 decoder profile */ gint profile; + + guint8 intra_quantizer_matrix[64]; + guint8 non_intra_quantizer_matrix[64]; +}; + +struct MPEGPictureHdr +{ + guint8 pic_type; + + guint8 full_pel_forward_vector, full_pel_backward_vector; + + guint8 f_code[2][2]; +}; + +struct MPEGPictureExt +{ + guint8 f_code[2][2]; + + guint8 intra_dc_precision; + guint8 picture_structure; + guint8 top_field_first; + guint8 frame_pred_frame_dct; + guint8 concealment_motion_vectors; + guint8 q_scale_type; + guint8 intra_vlc_format; }; gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, - guint8 *data, guint8 *end); + guint8 *data, guint8 *end); + +gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end); + +gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, guint8 *data, guint8 *end); #endif -- cgit v1.2.1