From 725e4ada3062c80623abf51477dfdc73fe294f3f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Thomas=20Balling=20S=C3=B8rensen?= Date: Tue, 20 Jul 2010 14:25:28 +0200 Subject: [PATCH] Made some decoding function for mpeg2-decoding --- src/gallium/auxiliary/vl/vl_compositor.c | 4 +- src/gallium/include/pipe/p_defines.h | 1 + src/gallium/include/pipe/p_video_state.h | 1 + src/gallium/state_trackers/vdpau/Makefile | 3 +- src/gallium/state_trackers/vdpau/decode.c | 185 ++++++++++++++++++ src/gallium/state_trackers/vdpau/device.c | 2 +- src/gallium/state_trackers/vdpau/query.c | 63 +++++- src/gallium/state_trackers/vdpau/surface.c | 89 ++++++--- .../state_trackers/vdpau/vdpau_private.h | 45 ++++- 9 files changed, 345 insertions(+), 48 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index 0640b1a4565..415dc92555f 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -627,8 +627,8 @@ void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float pipe_buffer_map(compositor->pipe, compositor->fs_const_buf, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, &buf_transfer), - mat, - sizeof(struct fragment_shader_consts) + mat, + sizeof(struct fragment_shader_consts) ); pipe_buffer_unmap(compositor->pipe, compositor->fs_const_buf, diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 28318183183..26ba7b8002a 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -474,6 +474,7 @@ enum pipe_video_codec enum pipe_video_profile { + PIPE_VIDEO_PROFILE_UNKNOWN, PIPE_VIDEO_PROFILE_MPEG1, PIPE_VIDEO_PROFILE_MPEG2_SIMPLE, PIPE_VIDEO_PROFILE_MPEG2_MAIN, diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 5eb96352139..1450f3488f9 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -74,6 +74,7 @@ enum pipe_mpeg12_dct_type PIPE_MPEG12_DCT_TYPE_FRAME }; + struct pipe_macroblock { enum pipe_video_codec codec; diff --git a/src/gallium/state_trackers/vdpau/Makefile b/src/gallium/state_trackers/vdpau/Makefile index 53378a9c1ff..a1b83abc6dd 100644 --- a/src/gallium/state_trackers/vdpau/Makefile +++ b/src/gallium/state_trackers/vdpau/Makefile @@ -15,7 +15,8 @@ C_SOURCES = htab.c \ ftab.c \ device.c \ query.c \ - surface.c + surface.c \ + decode.c include ../../Makefile.template diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c index b85185d0ad0..8daf7a47f97 100644 --- a/src/gallium/state_trackers/vdpau/decode.c +++ b/src/gallium/state_trackers/vdpau/decode.c @@ -26,4 +26,189 @@ **************************************************************************/ #include "vdpau_private.h" +#include +#include +VdpStatus +vlVdpDecoderCreate ( VdpDevice device, + VdpDecoderProfile profile, + uint32_t width, uint32_t height, + uint32_t max_references, + VdpDecoder *decoder +) +{ + enum pipe_video_profile p_profile; + VdpStatus ret; + vlVdpDecoder *vldecoder; + + if (!decoder) + return VDP_STATUS_INVALID_POINTER; + + if (!(width && height)) + return VDP_STATUS_INVALID_VALUE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) { + ret = VDP_STATUS_INVALID_HANDLE; + goto inv_device; + } + + vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); + if (!vldecoder) { + ret = VDP_STATUS_RESOURCES; + goto no_decoder; + } + + vldecoder->vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vldecoder->vlscreen) + ret = VDP_STATUS_RESOURCES; + goto no_screen; + + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + ret = VDP_STATUS_INVALID_DECODER_PROFILE; + goto inv_profile; + } + + // TODO: Define max_references. Used mainly for H264 + + vldecoder->chroma_format = p_profile; + vldecoder->device = dev; + + *decoder = vlAddDataHTAB(vldecoder); + if (*decoder == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + + no_handle: + FREE(vldecoder); + inv_profile: + no_screen: + no_decoder: + inv_device: + return ret; +} + +VdpStatus +vlVdpDecoderDestroy (VdpDecoder decoder +) +{ + vlVdpDecoder *vldecoder; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) { + return VDP_STATUS_INVALID_HANDLE; + } + + if (vldecoder->vctx) + vl_video_destroy(vldecoder->vctx); + + if (vldecoder->vlscreen) + vl_screen_destroy(vldecoder->vlscreen); + + FREE(vldecoder); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpCreateSurface (vlVdpDecoder *vldecoder, + vlVdpSurface *vlsurf +) +{ + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderRenderMpeg2 (vlVdpDecoder *vldecoder, + vlVdpSurface *vlsurf, + VdpPictureInfoMPEG1Or2 *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers + ) +{ + struct pipe_video_context *vpipe; + vlVdpSurface *t_vdp_surf; + vlVdpSurface *p_vdp_surf; + vlVdpSurface *f_vdp_surf; + struct pipe_surface *t_surf; + struct pipe_surface *p_surf; + struct pipe_surface *f_surf; + uint32_t num_macroblocks; + + vpipe = vldecoder->vctx->vpipe; + t_vdp_surf = vlsurf; + p_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference); + if (p_vdp_surf) + return VDP_STATUS_INVALID_HANDLE; + + f_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference); + if (f_vdp_surf) + return VDP_STATUS_INVALID_HANDLE; + + /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ + if (p_vdp_surf == VDP_INVALID_HANDLE) p_vdp_surf = NULL; + if (f_vdp_surf == VDP_INVALID_HANDLE) f_vdp_surf = NULL; + + vlVdpCreateSurface(vldecoder,t_vdp_surf); + + num_macroblocks = picture_info->slice_count; + struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks]; + + /*VdpMacroBlocksToPipe(vpipe->screen, macroblocks, blocks, first_macroblock, + num_macroblocks, pipe_macroblocks);*/ + + vpipe->set_decode_target(vpipe,t_surf); + /*vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks, + &pipe_macroblocks->base, &target_surface_priv->render_fence);*/ +} + +VdpStatus +vlVdpDecoderRender (VdpDecoder decoder, + VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers +) +{ + vlVdpDecoder *vldecoder; + vlVdpSurface *vlsurf; + VdpStatus ret; + + if (!(picture_info && bitstream_buffers)) + return VDP_STATUS_INVALID_POINTER; + + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); + if (!vlsurf) + return VDP_STATUS_INVALID_HANDLE; + + if (vlsurf->device != vldecoder->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + if (vlsurf->chroma_format != vldecoder->chroma_format) + return VDP_STATUS_INVALID_CHROMA_TYPE; + + // TODO: Right now only mpeg2 is supported. + switch (vldecoder->vctx->vpipe->profile) { + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + ret = vlVdpDecoderRenderMpeg2(vldecoder,vlsurf,(VdpPictureInfoMPEG1Or2 *)picture_info, + bitstream_buffer_count,bitstream_buffers); + break; + default: + return VDP_STATUS_INVALID_DECODER_PROFILE; + } + assert(0); + + return ret; +} \ No newline at end of file diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c index ba91e16a43f..111b15c619f 100644 --- a/src/gallium/state_trackers/vdpau/device.c +++ b/src/gallium/state_trackers/vdpau/device.c @@ -48,7 +48,7 @@ vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, VdpGe goto no_htab; } - dev = CALLOC(0, sizeof(vlVdpDevice)); + dev = CALLOC(1, sizeof(vlVdpDevice)); if (!dev) { ret = VDP_STATUS_RESOURCES; goto no_dev; diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c index 71793cc8ad5..eb7cfbcdd36 100644 --- a/src/gallium/state_trackers/vdpau/query.c +++ b/src/gallium/state_trackers/vdpau/query.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -56,6 +57,7 @@ VdpStatus vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) { + struct vl_screen *vlscreen; uint32_t max_2d_texture_level; VdpStatus ret; @@ -66,9 +68,8 @@ vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chrom if (!dev) return VDP_STATUS_INVALID_HANDLE; - if (!dev->vlscreen) - dev->vlscreen = vl_screen_create(dev->display, dev->screen); - if (!dev->vlscreen) + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) return VDP_STATUS_RESOURCES; /* XXX: Current limits */ @@ -78,7 +79,7 @@ vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chrom goto no_sup; } - max_2d_texture_level = dev->vlscreen->pscreen->get_param( dev->vlscreen->pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS ); + max_2d_texture_level = vlscreen->pscreen->get_param( vlscreen->pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS ); if (!max_2d_texture_level) { ret = VDP_STATUS_RESOURCES; goto no_sup; @@ -87,6 +88,8 @@ vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chrom /* I am not quite sure if it is max_2d_texture_level-1 or just max_2d_texture_level */ *max_width = *max_height = pow(2,max_2d_texture_level-1); + vl_screen_destroy(vlscreen); + return VDP_STATUS_OK; no_sup: return ret; @@ -97,6 +100,8 @@ vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaTyp VdpYCbCrFormat bits_ycbcr_format, VdpBool *is_supported) { + struct vl_screen *vlscreen; + if (!is_supported) return VDP_STATUS_INVALID_POINTER; @@ -104,18 +109,19 @@ vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaTyp if (!dev) return VDP_STATUS_INVALID_HANDLE; - if (!dev->vlscreen) - dev->vlscreen = vl_screen_create(dev->display, dev->screen); - if (!dev->vlscreen) + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) return VDP_STATUS_RESOURCES; if (bits_ycbcr_format != VDP_YCBCR_FORMAT_Y8U8V8A8) - *is_supported = dev->vlscreen->pscreen->is_format_supported(dev->vlscreen->pscreen, + *is_supported = vlscreen->pscreen->is_format_supported(vlscreen->pscreen, FormatToPipe(bits_ycbcr_format), PIPE_TEXTURE_2D, PIPE_BIND_RENDER_TARGET, PIPE_TEXTURE_GEOM_NON_SQUARE ); + vl_screen_destroy(vlscreen); + return VDP_STATUS_OK; } @@ -124,10 +130,49 @@ vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, uint32_t *max_width, uint32_t *max_height) { + enum pipe_video_profile p_profile; + uint32_t max_decode_width; + uint32_t max_decode_height; + uint32_t max_2d_texture_level; + struct vl_screen *vlscreen; + if (!(is_supported && max_level && max_macroblocks && max_width && max_height)) return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlscreen = vl_screen_create(dev->display, dev->screen); + if (!vlscreen) + return VDP_STATUS_RESOURCES; - return VDP_STATUS_NO_IMPLEMENTATION; + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + if (p_profile != PIPE_VIDEO_PROFILE_MPEG2_SIMPLE && p_profile != PIPE_VIDEO_PROFILE_MPEG2_MAIN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + /* XXX hack, need to implement something more sane when the decoders have been implemented */ + max_2d_texture_level = vlscreen->pscreen->get_param( vlscreen->pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS ); + max_decode_width = max_decode_height = pow(2,max_2d_texture_level-2); + if (!(max_decode_width && max_decode_height)) + return VDP_STATUS_RESOURCES; + + *is_supported = true; + *max_width = max_decode_width; + *max_height = max_decode_height; + *max_level = 16; + *max_macroblocks = (max_decode_width/16) * (max_decode_height/16); + + vl_screen_destroy(vlscreen); + + return VDP_STATUS_OK; } VdpStatus diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c index 2de2ee222c1..18fe788f870 100644 --- a/src/gallium/state_trackers/vdpau/surface.c +++ b/src/gallium/state_trackers/vdpau/surface.c @@ -29,6 +29,7 @@ #include #include #include +#include VdpStatus vlVdpVideoSurfaceCreate(VdpDevice device, @@ -52,37 +53,20 @@ vlVdpVideoSurfaceCreate(VdpDevice device, goto no_htab; } - p_surf = CALLOC(0, sizeof(p_surf)); + p_surf = CALLOC(1, sizeof(p_surf)); if (!p_surf) { ret = VDP_STATUS_RESOURCES; goto no_res; } - p_surf->psurface = CALLOC(0,sizeof(struct pipe_surface)); - if (!p_surf->psurface) { - ret = VDP_STATUS_RESOURCES; - goto no_surf; - } - vlVdpDevice *dev = vlGetDataHTAB(device); if (!dev) { ret = VDP_STATUS_INVALID_HANDLE; goto inv_device; } - if (!dev->vlscreen) - dev->vlscreen = vl_screen_create(dev->display, dev->screen); - if (!dev->vlscreen) { - ret = VDP_STATUS_RESOURCES; - goto inv_device; - } - - p_surf->psurface->height = height; - p_surf->psurface->width = width; - p_surf->psurface->level = 0; - p_surf->psurface->usage = PIPE_USAGE_DEFAULT; p_surf->chroma_format = FormatToPipe(chroma_type); - p_surf->vlscreen = dev->vlscreen; + p_surf->device = dev; *surface = vlAddDataHTAB(p_surf); if (*surface == 0) { @@ -113,9 +97,12 @@ vlVdpVideoSurfaceDestroy ( VdpVideoSurface surface ) if (!p_surf) return VDP_STATUS_INVALID_HANDLE; - if (p_surf->psurface) - p_surf->vlscreen->pscreen->tex_surface_destroy(p_surf->psurface); - + if (p_surf->psurface) { + if (p_surf->psurface->texture) { + if (p_surf->psurface->texture->screen) + p_surf->psurface->texture->screen->tex_surface_destroy(p_surf->psurface); + } + } FREE(p_surf); return VDP_STATUS_OK; } @@ -130,21 +117,17 @@ vlVdpVideoSurfaceGetParameters ( VdpVideoSurface surface, if (!(width && height && chroma_type)) return VDP_STATUS_INVALID_POINTER; - - if (!vlCreateHTAB()) - return VDP_STATUS_RESOURCES; - - + vlVdpSurface *p_surf = vlGetDataHTAB(surface); if (!p_surf) return VDP_STATUS_INVALID_HANDLE; - if (!(p_surf->psurface && p_surf->chroma_format)) - return VDP_STATUS_INVALID_HANDLE; + if (!(p_surf->chroma_format > 0 && p_surf->chroma_format < 3)) + return VDP_STATUS_INVALID_CHROMA_TYPE; - *width = p_surf->psurface->width; - *height = p_surf->psurface->height; + *width = p_surf->width; + *height = p_surf->height; *chroma_type = PipeToType(p_surf->chroma_format); return VDP_STATUS_OK; @@ -157,6 +140,50 @@ vlVdpVideoSurfaceGetBitsYCbCr ( VdpVideoSurface surface, uint32_t const *destination_pitches ) { + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (!p_surf->psurface) + return VDP_STATUS_RESOURCES; + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfacePutBitsYCbCr ( VdpVideoSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches +) +{ + uint32_t size_surface_bytes; + const struct util_format_description *format_desc; + enum pipe_format pformat = FormatToPipe(source_ycbcr_format); + + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + + //size_surface_bytes = ( source_pitches[0] * p_surf->height util_format_get_blockheight(pformat) ); + /*util_format_translate(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_x, unsigned dst_y, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height);*/ + + return VDP_STATUS_NO_IMPLEMENTATION; } diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h index 27793892185..566c99266ed 100644 --- a/src/gallium/state_trackers/vdpau/vdpau_private.h +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -116,21 +117,54 @@ static VdpYCbCrFormat PipeToFormat(enum pipe_format p_format) return -1; } +static enum pipe_video_profile ProfileToPipe(VdpDecoderProfile vdpau_profile) +{ + switch (vdpau_profile) { + case VDP_DECODER_PROFILE_MPEG1: + return PIPE_VIDEO_PROFILE_MPEG1; + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: + return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; + case VDP_DECODER_PROFILE_MPEG2_MAIN: + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + case VDP_DECODER_PROFILE_H264_BASELINE: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case VDP_DECODER_PROFILE_H264_MAIN: /* Not defined in p_format.h */ + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case VDP_DECODER_PROFILE_H264_HIGH: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + default: + PIPE_VIDEO_PROFILE_UNKNOWN; + } + + return -1; +} + typedef struct { void *display; int screen; - struct vl_screen *vlscreen; - struct vl_context *vctx; } vlVdpDevice; typedef struct { - struct vl_screen *vlscreen; + vlVdpDevice *device; + uint32_t width; + uint32_t height; + uint32_t pitch; struct pipe_surface *psurface; - enum pipe_video_chroma_format chroma_format; + enum pipe_format format; + enum pipe_video_chroma_format chroma_format; + uint8_t *data; } vlVdpSurface; +typedef struct +{ + vlVdpDevice *device; + struct vl_screen *vlscreen; + struct vl_context *vctx; + enum pipe_video_chroma_format chroma_format; +} vlVdpDecoder; + typedef uint32_t vlHandle; boolean vlCreateHTAB(void); @@ -160,5 +194,8 @@ VdpVideoSurfaceDestroy vlVdpVideoSurfaceDestroy; VdpVideoSurfaceGetParameters vlVdpVideoSurfaceGetParameters; VdpVideoSurfaceGetBitsYCbCr vlVdpVideoSurfaceGetBitsYCbCr; VdpVideoSurfacePutBitsYCbCr vlVdpVideoSurfacePutBitsYCbCr; +VdpDecoderCreate vlVdpDecoderCreate; +VdpDecoderDestroy vlVdpDecoderDestroy; +VdpDecoderRender vlVdpDecoderRender; #endif // VDPAU_PRIVATE_H \ No newline at end of file -- 2.30.2