1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include <pipe/p_video_context.h>
30 #include <util/u_memory.h>
31 #include <util/u_math.h>
32 #include <util/u_debug.h>
34 #include "vdpau_private.h"
37 vlVdpDecoderCreate(VdpDevice device
,
38 VdpDecoderProfile profile
,
39 uint32_t width
, uint32_t height
,
40 uint32_t max_references
,
43 enum pipe_video_profile p_profile
;
44 struct pipe_video_context
*vpipe
;
46 vlVdpDecoder
*vldecoder
;
50 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating decoder\n");
53 return VDP_STATUS_INVALID_POINTER
;
55 if (!(width
&& height
))
56 return VDP_STATUS_INVALID_VALUE
;
58 p_profile
= ProfileToPipe(profile
);
59 if (p_profile
== PIPE_VIDEO_PROFILE_UNKNOWN
)
60 return VDP_STATUS_INVALID_DECODER_PROFILE
;
62 dev
= vlGetDataHTAB(device
);
64 return VDP_STATUS_INVALID_HANDLE
;
66 vpipe
= dev
->context
->vpipe
;
68 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
70 return VDP_STATUS_RESOURCES
;
72 vldecoder
->device
= dev
;
74 // TODO: Define max_references. Used mainly for H264
75 vldecoder
->decoder
= vpipe
->create_decoder
78 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
79 PIPE_VIDEO_CHROMA_FORMAT_420
,
82 if (!vldecoder
->decoder
) {
83 ret
= VDP_STATUS_ERROR
;
87 vldecoder
->cur_buffer
= 0;
89 for (i
= 0; i
< VL_NUM_DECODE_BUFFERS
; ++i
) {
90 vldecoder
->buffer
[i
] = vldecoder
->decoder
->create_buffer(vldecoder
->decoder
);
91 if (!vldecoder
->buffer
[i
]) {
92 ret
= VDP_STATUS_ERROR
;
97 *decoder
= vlAddDataHTAB(vldecoder
);
99 ret
= VDP_STATUS_ERROR
;
103 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoder created succesfully\n");
105 return VDP_STATUS_OK
;
110 for (i
= 0; i
< VL_NUM_DECODE_BUFFERS
; ++i
)
111 if (vldecoder
->buffer
[i
])
112 vldecoder
->buffer
[i
]->destroy(vldecoder
->buffer
[i
]);
114 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
122 vlVdpDecoderDestroy(VdpDecoder decoder
)
124 vlVdpDecoder
*vldecoder
;
127 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying decoder\n");
129 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
131 return VDP_STATUS_INVALID_HANDLE
;
133 for (i
= 0; i
< VL_NUM_DECODE_BUFFERS
; ++i
)
134 if (vldecoder
->buffer
[i
])
135 vldecoder
->buffer
[i
]->destroy(vldecoder
->buffer
[i
]);
137 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
141 return VDP_STATUS_OK
;
145 vlVdpDecoderGetParameters(VdpDecoder decoder
,
146 VdpDecoderProfile
*profile
,
150 return VDP_STATUS_OK
;
154 vlVdpDecoderRenderMpeg2(struct pipe_video_decoder
*decoder
,
155 struct pipe_video_decode_buffer
*buffer
,
156 struct pipe_video_buffer
*target
,
157 VdpPictureInfoMPEG1Or2
*picture_info
,
158 uint32_t bitstream_buffer_count
,
159 VdpBitstreamBuffer
const *bitstream_buffers
)
161 struct pipe_mpeg12_picture_desc picture
;
162 struct pipe_video_buffer
*ref_frames
[2];
163 unsigned num_ycbcr_blocks
[3] = { 0, 0, 0 };
166 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG2\n");
168 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
169 if (picture_info
->forward_reference
== VDP_INVALID_HANDLE
)
170 ref_frames
[0] = NULL
;
172 ref_frames
[0] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
174 return VDP_STATUS_INVALID_HANDLE
;
177 if (picture_info
->backward_reference
== VDP_INVALID_HANDLE
)
178 ref_frames
[1] = NULL
;
180 ref_frames
[1] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
182 return VDP_STATUS_INVALID_HANDLE
;
185 memset(&picture
, 0, sizeof(picture
));
186 picture
.base
.profile
= decoder
->profile
;
187 picture
.picture_coding_type
= picture_info
->picture_coding_type
;
188 picture
.picture_structure
= picture_info
->picture_structure
;
189 picture
.frame_pred_frame_dct
= picture_info
->frame_pred_frame_dct
;
190 picture
.q_scale_type
= picture_info
->q_scale_type
;
191 picture
.alternate_scan
= picture_info
->alternate_scan
;
192 picture
.intra_dc_precision
= picture_info
->intra_dc_precision
;
193 picture
.intra_vlc_format
= picture_info
->intra_vlc_format
;
194 picture
.concealment_motion_vectors
= picture_info
->concealment_motion_vectors
;
195 picture
.f_code
[0][0] = picture_info
->f_code
[0][0] - 1;
196 picture
.f_code
[0][1] = picture_info
->f_code
[0][1] - 1;
197 picture
.f_code
[1][0] = picture_info
->f_code
[1][0] - 1;
198 picture
.f_code
[1][1] = picture_info
->f_code
[1][1] - 1;
200 picture
.intra_quantizer_matrix
= picture_info
->intra_quantizer_matrix
;
201 picture
.non_intra_quantizer_matrix
= picture_info
->non_intra_quantizer_matrix
;
203 buffer
->begin_frame(buffer
);
205 for (i
= 0; i
< bitstream_buffer_count
; ++i
)
206 buffer
->decode_bitstream(buffer
, bitstream_buffers
[i
].bitstream_bytes
,
207 bitstream_buffers
[i
].bitstream
, &picture
, num_ycbcr_blocks
);
209 buffer
->end_frame(buffer
);
211 decoder
->flush_buffer(buffer
, num_ycbcr_blocks
, ref_frames
, target
);
213 return VDP_STATUS_OK
;
217 vlVdpDecoderRender(VdpDecoder decoder
,
218 VdpVideoSurface target
,
219 VdpPictureInfo
const *picture_info
,
220 uint32_t bitstream_buffer_count
,
221 VdpBitstreamBuffer
const *bitstream_buffers
)
223 vlVdpDecoder
*vldecoder
;
224 vlVdpSurface
*vlsurf
;
226 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding\n");
228 if (!(picture_info
&& bitstream_buffers
))
229 return VDP_STATUS_INVALID_POINTER
;
231 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
233 return VDP_STATUS_INVALID_HANDLE
;
235 vlsurf
= (vlVdpSurface
*)vlGetDataHTAB(target
);
237 return VDP_STATUS_INVALID_HANDLE
;
239 if (vlsurf
->device
!= vldecoder
->device
)
240 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
242 if (vlsurf
->video_buffer
->chroma_format
!= vldecoder
->decoder
->chroma_format
)
243 // TODO: Recreate decoder with correct chroma
244 return VDP_STATUS_INVALID_CHROMA_TYPE
;
246 // TODO: Right now only mpeg2 is supported.
247 switch (vldecoder
->decoder
->profile
) {
248 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE
:
249 case PIPE_VIDEO_PROFILE_MPEG2_MAIN
:
250 ++vldecoder
->cur_buffer
;
251 vldecoder
->cur_buffer
%= VL_NUM_DECODE_BUFFERS
;
252 return vlVdpDecoderRenderMpeg2(vldecoder
->decoder
,
253 vldecoder
->buffer
[vldecoder
->cur_buffer
],
254 vlsurf
->video_buffer
,
255 (VdpPictureInfoMPEG1Or2
*)picture_info
,
256 bitstream_buffer_count
,bitstream_buffers
);
260 return VDP_STATUS_INVALID_DECODER_PROFILE
;