From 12bf452945ae64da69f474298758f9a7c8b94af5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 31 Oct 2011 11:45:37 +0100 Subject: [PATCH] state_trackers/vdpau: Add support for MPEG4 Part 2 Just the support patch, no decoder implements it currently. Signed-off-by: Maarten Lankhorst --- src/gallium/include/pipe/p_video_state.h | 27 +++++++ src/gallium/state_trackers/vdpau/decode.c | 98 ++++++++++++++++++----- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 53da1d85119..0530b4a21ad 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -185,6 +185,33 @@ struct pipe_mpeg12_macroblock unsigned short num_skipped_macroblocks; }; +struct pipe_mpeg4_picture_desc +{ + struct pipe_picture_desc base; + int32_t trd[2]; + int32_t trb[2]; + uint16_t vop_time_increment_resolution; + uint8_t vop_coding_type; + uint8_t vop_fcode_forward; + uint8_t vop_fcode_backward; + uint8_t resync_marker_disable; + uint8_t interlaced; + uint8_t quant_type; + uint8_t quarter_sample; + uint8_t short_video_header; + uint8_t rounding_control; + uint8_t alternate_vertical_scan_flag; + uint8_t top_field_first; +}; + +struct pipe_mpeg4_quant_matrix +{ + struct pipe_quant_matrix base; + + const uint8_t *intra_matrix; + const uint8_t *non_intra_matrix; +}; + #ifdef __cplusplus } #endif diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c index 2b23dfde9c5..c39c365cc8d 100644 --- a/src/gallium/state_trackers/vdpau/decode.c +++ b/src/gallium/state_trackers/vdpau/decode.c @@ -28,6 +28,7 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_debug.h" +#include "util/u_video.h" #include "vdpau_private.h" @@ -201,9 +202,7 @@ vlVdpDecoderGetParameters(VdpDecoder decoder, */ static VdpStatus vlVdpDecoderRenderMpeg12(struct pipe_video_decoder *decoder, - VdpPictureInfoMPEG1Or2 *picture_info, - uint32_t bitstream_buffer_count, - VdpBitstreamBuffer const *bitstream_buffers) + VdpPictureInfoMPEG1Or2 *picture_info) { struct pipe_mpeg12_picture_desc picture; struct pipe_mpeg12_quant_matrix quant; @@ -255,15 +254,62 @@ vlVdpDecoderRenderMpeg12(struct pipe_video_decoder *decoder, quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; decoder->set_quant_matrix(decoder, &quant.base); + return VDP_STATUS_OK; +} + +/** + * Decode a mpeg 1/2 video. + */ +static VdpStatus +vlVdpDecoderRenderMpeg4(struct pipe_video_decoder *decoder, + VdpPictureInfoMPEG4Part2 *picture_info) +{ + struct pipe_mpeg4_picture_desc picture; + struct pipe_mpeg4_quant_matrix quant; + struct pipe_video_buffer *ref_frames[2] = {}; + unsigned i; - decoder->begin_frame(decoder); + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); - for (i = 0; i < bitstream_buffer_count; ++i) - decoder->decode_bitstream(decoder, bitstream_buffers[i].bitstream_bytes, - bitstream_buffers[i].bitstream); + /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ + if (picture_info->forward_reference != VDP_INVALID_HANDLE) { + ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; + if (!ref_frames[0]) + return VDP_STATUS_INVALID_HANDLE; + } + + if (picture_info->backward_reference != VDP_INVALID_HANDLE) { + ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; + if (!ref_frames[1]) + return VDP_STATUS_INVALID_HANDLE; + } + decoder->set_reference_frames(decoder, ref_frames, 2); - decoder->end_frame(decoder); + memset(&picture, 0, sizeof(picture)); + picture.base.profile = decoder->profile; + for (i = 0; i < 2; ++i) { + picture.trd[i] = picture_info->trd[i]; + picture.trb[i] = picture_info->trb[i]; + } + picture.vop_time_increment_resolution = picture_info->vop_time_increment_resolution; + picture.vop_coding_type = picture_info->vop_coding_type; + picture.vop_fcode_forward = picture_info->vop_fcode_forward; + picture.vop_fcode_backward = picture_info->vop_fcode_backward; + picture.resync_marker_disable = picture_info->resync_marker_disable; + picture.interlaced = picture_info->interlaced; + picture.quant_type = picture_info->quant_type; + picture.quarter_sample = picture_info->quarter_sample; + picture.short_video_header = picture_info->short_video_header; + picture.rounding_control = picture_info->rounding_control; + picture.alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; + picture.top_field_first = picture_info->top_field_first; + decoder->set_picture_parameters(decoder, &picture.base); + memset(&quant, 0, sizeof(quant)); + quant.base.codec = PIPE_VIDEO_CODEC_MPEG4; + quant.intra_matrix = picture_info->intra_quantizer_matrix; + quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; + decoder->set_quant_matrix(decoder, &quant.base); return VDP_STATUS_OK; } @@ -279,6 +325,9 @@ vlVdpDecoderRender(VdpDecoder decoder, { vlVdpDecoder *vldecoder; vlVdpSurface *vlsurf; + VdpStatus ret; + struct pipe_video_decoder *dec; + unsigned i; VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding\n"); @@ -288,6 +337,7 @@ vlVdpDecoderRender(VdpDecoder decoder, vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); if (!vldecoder) return VDP_STATUS_INVALID_HANDLE; + dec = vldecoder->decoder; vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); if (!vlsurf) @@ -296,26 +346,34 @@ vlVdpDecoderRender(VdpDecoder decoder, if (vlsurf->device != vldecoder->device) return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - if (vlsurf->video_buffer->chroma_format != vldecoder->decoder->chroma_format) + if (vlsurf->video_buffer->chroma_format != dec->chroma_format) // TODO: Recreate decoder with correct chroma return VDP_STATUS_INVALID_CHROMA_TYPE; - // TODO: Right now only mpeg 1 & 2 videos are supported. - switch (vldecoder->decoder->profile) { - case PIPE_VIDEO_PROFILE_MPEG1: - case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: - case PIPE_VIDEO_PROFILE_MPEG2_MAIN: - ++vldecoder->cur_buffer; - vldecoder->cur_buffer %= vldecoder->num_buffers; + ++vldecoder->cur_buffer; + vldecoder->cur_buffer %= vldecoder->num_buffers; - vldecoder->decoder->set_decode_buffer(vldecoder->decoder, vldecoder->buffers[vldecoder->cur_buffer]); - vldecoder->decoder->set_decode_target(vldecoder->decoder, vlsurf->video_buffer); + dec->set_decode_buffer(dec, vldecoder->buffers[vldecoder->cur_buffer]); + dec->set_decode_target(dec, vlsurf->video_buffer); - return vlVdpDecoderRenderMpeg12(vldecoder->decoder, (VdpPictureInfoMPEG1Or2 *)picture_info, - bitstream_buffer_count, bitstream_buffers); + switch (u_reduce_video_profile(dec->profile)) { + case PIPE_VIDEO_CODEC_MPEG12: + ret = vlVdpDecoderRenderMpeg12(dec, (VdpPictureInfoMPEG1Or2 *)picture_info); + break; + case PIPE_VIDEO_CODEC_MPEG4: + ret = vlVdpDecoderRenderMpeg4(dec, (VdpPictureInfoMPEG4Part2 *)picture_info); break; default: return VDP_STATUS_INVALID_DECODER_PROFILE; } + if (ret != VDP_STATUS_OK) + return ret; + + dec->begin_frame(dec); + for (i = 0; i < bitstream_buffer_count; ++i) + dec->decode_bitstream(dec, bitstream_buffers[i].bitstream_bytes, + bitstream_buffers[i].bitstream); + dec->end_frame(dec); + return ret; } -- 2.30.2