state_trackers/vdpau: Add support for MPEG4 Part 2
authorMaarten Lankhorst <m.b.lankhorst@gmail.com>
Mon, 31 Oct 2011 10:45:37 +0000 (11:45 +0100)
committerChristian König <deathsimple@vodafone.de>
Thu, 3 Nov 2011 12:52:01 +0000 (13:52 +0100)
Just the support patch, no decoder implements it currently.

Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
src/gallium/include/pipe/p_video_state.h
src/gallium/state_trackers/vdpau/decode.c

index 53da1d85119a0beda30c22961e4e1e9f46576127..0530b4a21adf358e12d6107b31266f6f49eb99c3 100644 (file)
@@ -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
index 2b23dfde9c55f10c57705ddd43c449c53c62f0c5..c39c365cc8d867b16b47c76bef703eabb0aabe97 100644 (file)
@@ -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;
 }