Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2010 Thomas Balling Sørensen. |
||
4 | * All Rights Reserved. |
||
5 | * |
||
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: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice (including the |
||
15 | * next paragraph) shall be included in all copies or substantial portions |
||
16 | * of the Software. |
||
17 | * |
||
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. |
||
25 | * |
||
26 | **************************************************************************/ |
||
27 | |||
28 | #include "util/u_memory.h" |
||
29 | #include "util/u_math.h" |
||
30 | #include "util/u_debug.h" |
||
31 | #include "util/u_video.h" |
||
32 | |||
33 | #include "vl/vl_vlc.h" |
||
34 | |||
35 | #include "vdpau_private.h" |
||
36 | |||
37 | /** |
||
38 | * Create a VdpDecoder. |
||
39 | */ |
||
40 | VdpStatus |
||
41 | vlVdpDecoderCreate(VdpDevice device, |
||
42 | VdpDecoderProfile profile, |
||
43 | uint32_t width, uint32_t height, |
||
44 | uint32_t max_references, |
||
45 | VdpDecoder *decoder) |
||
46 | { |
||
47 | enum pipe_video_profile p_profile; |
||
48 | struct pipe_context *pipe; |
||
49 | struct pipe_screen *screen; |
||
50 | vlVdpDevice *dev; |
||
51 | vlVdpDecoder *vldecoder; |
||
52 | VdpStatus ret; |
||
53 | bool supported; |
||
54 | |||
55 | if (!decoder) |
||
56 | return VDP_STATUS_INVALID_POINTER; |
||
57 | *decoder = 0; |
||
58 | |||
59 | if (!(width && height)) |
||
60 | return VDP_STATUS_INVALID_VALUE; |
||
61 | |||
62 | p_profile = ProfileToPipe(profile); |
||
63 | if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) |
||
64 | return VDP_STATUS_INVALID_DECODER_PROFILE; |
||
65 | |||
66 | dev = vlGetDataHTAB(device); |
||
67 | if (!dev) |
||
68 | return VDP_STATUS_INVALID_HANDLE; |
||
69 | |||
70 | pipe = dev->context; |
||
71 | screen = dev->vscreen->pscreen; |
||
72 | |||
73 | pipe_mutex_lock(dev->mutex); |
||
74 | |||
75 | supported = screen->get_video_param |
||
76 | ( |
||
77 | screen, |
||
78 | p_profile, |
||
79 | PIPE_VIDEO_CAP_SUPPORTED |
||
80 | ); |
||
81 | if (!supported) { |
||
82 | pipe_mutex_unlock(dev->mutex); |
||
83 | return VDP_STATUS_INVALID_DECODER_PROFILE; |
||
84 | } |
||
85 | |||
86 | vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); |
||
87 | if (!vldecoder) { |
||
88 | pipe_mutex_unlock(dev->mutex); |
||
89 | return VDP_STATUS_RESOURCES; |
||
90 | } |
||
91 | |||
92 | vldecoder->device = dev; |
||
93 | |||
94 | vldecoder->decoder = pipe->create_video_decoder |
||
95 | ( |
||
96 | pipe, p_profile, |
||
97 | PIPE_VIDEO_ENTRYPOINT_BITSTREAM, |
||
98 | PIPE_VIDEO_CHROMA_FORMAT_420, |
||
99 | width, height, max_references, |
||
100 | false |
||
101 | ); |
||
102 | |||
103 | if (!vldecoder->decoder) { |
||
104 | ret = VDP_STATUS_ERROR; |
||
105 | goto error_decoder; |
||
106 | } |
||
107 | |||
108 | *decoder = vlAddDataHTAB(vldecoder); |
||
109 | if (*decoder == 0) { |
||
110 | ret = VDP_STATUS_ERROR; |
||
111 | goto error_handle; |
||
112 | } |
||
113 | pipe_mutex_unlock(dev->mutex); |
||
114 | |||
115 | return VDP_STATUS_OK; |
||
116 | |||
117 | error_handle: |
||
118 | vldecoder->decoder->destroy(vldecoder->decoder); |
||
119 | |||
120 | error_decoder: |
||
121 | pipe_mutex_unlock(dev->mutex); |
||
122 | FREE(vldecoder); |
||
123 | return ret; |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Destroy a VdpDecoder. |
||
128 | */ |
||
129 | VdpStatus |
||
130 | vlVdpDecoderDestroy(VdpDecoder decoder) |
||
131 | { |
||
132 | vlVdpDecoder *vldecoder; |
||
133 | |||
134 | vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); |
||
135 | if (!vldecoder) |
||
136 | return VDP_STATUS_INVALID_HANDLE; |
||
137 | |||
138 | pipe_mutex_lock(vldecoder->device->mutex); |
||
139 | vldecoder->decoder->destroy(vldecoder->decoder); |
||
140 | pipe_mutex_unlock(vldecoder->device->mutex); |
||
141 | |||
142 | vlRemoveDataHTAB(decoder); |
||
143 | FREE(vldecoder); |
||
144 | |||
145 | return VDP_STATUS_OK; |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Retrieve the parameters used to create a VdpBitmapSurface. |
||
150 | */ |
||
151 | VdpStatus |
||
152 | vlVdpDecoderGetParameters(VdpDecoder decoder, |
||
153 | VdpDecoderProfile *profile, |
||
154 | uint32_t *width, |
||
155 | uint32_t *height) |
||
156 | { |
||
157 | vlVdpDecoder *vldecoder; |
||
158 | |||
159 | vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); |
||
160 | if (!vldecoder) |
||
161 | return VDP_STATUS_INVALID_HANDLE; |
||
162 | |||
163 | *profile = PipeToProfile(vldecoder->decoder->profile); |
||
164 | *width = vldecoder->decoder->width; |
||
165 | *height = vldecoder->decoder->height; |
||
166 | |||
167 | return VDP_STATUS_OK; |
||
168 | } |
||
169 | |||
170 | static VdpStatus |
||
171 | vlVdpGetReferenceFrame(VdpVideoSurface handle, struct pipe_video_buffer **ref_frame) |
||
172 | { |
||
173 | vlVdpSurface *surface; |
||
174 | |||
175 | /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ |
||
176 | if (handle == VDP_INVALID_HANDLE) { |
||
177 | *ref_frame = NULL; |
||
178 | return VDP_STATUS_OK; |
||
179 | } |
||
180 | |||
181 | surface = vlGetDataHTAB(handle); |
||
182 | if (!surface) |
||
183 | return VDP_STATUS_INVALID_HANDLE; |
||
184 | |||
185 | *ref_frame = surface->video_buffer; |
||
186 | if (!*ref_frame) |
||
187 | return VDP_STATUS_INVALID_HANDLE; |
||
188 | |||
189 | return VDP_STATUS_OK; |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Decode a mpeg 1/2 video. |
||
194 | */ |
||
195 | static VdpStatus |
||
196 | vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc *picture, |
||
197 | VdpPictureInfoMPEG1Or2 *picture_info) |
||
198 | { |
||
199 | VdpStatus r; |
||
200 | |||
201 | VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n"); |
||
202 | |||
203 | r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); |
||
204 | if (r != VDP_STATUS_OK) |
||
205 | return r; |
||
206 | |||
207 | r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); |
||
208 | if (r != VDP_STATUS_OK) |
||
209 | return r; |
||
210 | |||
211 | picture->picture_coding_type = picture_info->picture_coding_type; |
||
212 | picture->picture_structure = picture_info->picture_structure; |
||
213 | picture->frame_pred_frame_dct = picture_info->frame_pred_frame_dct; |
||
214 | picture->q_scale_type = picture_info->q_scale_type; |
||
215 | picture->alternate_scan = picture_info->alternate_scan; |
||
216 | picture->intra_vlc_format = picture_info->intra_vlc_format; |
||
217 | picture->concealment_motion_vectors = picture_info->concealment_motion_vectors; |
||
218 | picture->intra_dc_precision = picture_info->intra_dc_precision; |
||
219 | picture->f_code[0][0] = picture_info->f_code[0][0] - 1; |
||
220 | picture->f_code[0][1] = picture_info->f_code[0][1] - 1; |
||
221 | picture->f_code[1][0] = picture_info->f_code[1][0] - 1; |
||
222 | picture->f_code[1][1] = picture_info->f_code[1][1] - 1; |
||
223 | picture->num_slices = picture_info->slice_count; |
||
224 | picture->top_field_first = picture_info->top_field_first; |
||
225 | picture->full_pel_forward_vector = picture_info->full_pel_forward_vector; |
||
226 | picture->full_pel_backward_vector = picture_info->full_pel_backward_vector; |
||
227 | picture->intra_matrix = picture_info->intra_quantizer_matrix; |
||
228 | picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; |
||
229 | |||
230 | return VDP_STATUS_OK; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Decode a mpeg 4 video. |
||
235 | */ |
||
236 | static VdpStatus |
||
237 | vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc *picture, |
||
238 | VdpPictureInfoMPEG4Part2 *picture_info) |
||
239 | { |
||
240 | VdpStatus r; |
||
241 | unsigned i; |
||
242 | |||
243 | VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); |
||
244 | |||
245 | r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); |
||
246 | if (r != VDP_STATUS_OK) |
||
247 | return r; |
||
248 | |||
249 | r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); |
||
250 | if (r != VDP_STATUS_OK) |
||
251 | return r; |
||
252 | |||
253 | for (i = 0; i < 2; ++i) { |
||
254 | picture->trd[i] = picture_info->trd[i]; |
||
255 | picture->trb[i] = picture_info->trb[i]; |
||
256 | } |
||
257 | picture->vop_time_increment_resolution = picture_info->vop_time_increment_resolution; |
||
258 | picture->vop_coding_type = picture_info->vop_coding_type; |
||
259 | picture->vop_fcode_forward = picture_info->vop_fcode_forward; |
||
260 | picture->vop_fcode_backward = picture_info->vop_fcode_backward; |
||
261 | picture->resync_marker_disable = picture_info->resync_marker_disable; |
||
262 | picture->interlaced = picture_info->interlaced; |
||
263 | picture->quant_type = picture_info->quant_type; |
||
264 | picture->quarter_sample = picture_info->quarter_sample; |
||
265 | picture->short_video_header = picture_info->short_video_header; |
||
266 | picture->rounding_control = picture_info->rounding_control; |
||
267 | picture->alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; |
||
268 | picture->top_field_first = picture_info->top_field_first; |
||
269 | picture->intra_matrix = picture_info->intra_quantizer_matrix; |
||
270 | picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; |
||
271 | |||
272 | return VDP_STATUS_OK; |
||
273 | } |
||
274 | |||
275 | static VdpStatus |
||
276 | vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc *picture, |
||
277 | VdpPictureInfoVC1 *picture_info) |
||
278 | { |
||
279 | VdpStatus r; |
||
280 | |||
281 | VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding VC-1\n"); |
||
282 | |||
283 | r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); |
||
284 | if (r != VDP_STATUS_OK) |
||
285 | return r; |
||
286 | |||
287 | r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); |
||
288 | if (r != VDP_STATUS_OK) |
||
289 | return r; |
||
290 | |||
291 | picture->slice_count = picture_info->slice_count; |
||
292 | picture->picture_type = picture_info->picture_type; |
||
293 | picture->frame_coding_mode = picture_info->frame_coding_mode; |
||
294 | picture->postprocflag = picture_info->postprocflag; |
||
295 | picture->pulldown = picture_info->pulldown; |
||
296 | picture->interlace = picture_info->interlace; |
||
297 | picture->tfcntrflag = picture_info->tfcntrflag; |
||
298 | picture->finterpflag = picture_info->finterpflag; |
||
299 | picture->psf = picture_info->psf; |
||
300 | picture->dquant = picture_info->dquant; |
||
301 | picture->panscan_flag = picture_info->panscan_flag; |
||
302 | picture->refdist_flag = picture_info->refdist_flag; |
||
303 | picture->quantizer = picture_info->quantizer; |
||
304 | picture->extended_mv = picture_info->extended_mv; |
||
305 | picture->extended_dmv = picture_info->extended_dmv; |
||
306 | picture->overlap = picture_info->overlap; |
||
307 | picture->vstransform = picture_info->vstransform; |
||
308 | picture->loopfilter = picture_info->loopfilter; |
||
309 | picture->fastuvmc = picture_info->fastuvmc; |
||
310 | picture->range_mapy_flag = picture_info->range_mapy_flag; |
||
311 | picture->range_mapy = picture_info->range_mapy; |
||
312 | picture->range_mapuv_flag = picture_info->range_mapuv_flag; |
||
313 | picture->range_mapuv = picture_info->range_mapuv; |
||
314 | picture->multires = picture_info->multires; |
||
315 | picture->syncmarker = picture_info->syncmarker; |
||
316 | picture->rangered = picture_info->rangered; |
||
317 | picture->maxbframes = picture_info->maxbframes; |
||
318 | picture->deblockEnable = picture_info->deblockEnable; |
||
319 | picture->pquant = picture_info->pquant; |
||
320 | |||
321 | return VDP_STATUS_OK; |
||
322 | } |
||
323 | |||
324 | static VdpStatus |
||
325 | vlVdpDecoderRenderH264(struct pipe_h264_picture_desc *picture, |
||
326 | VdpPictureInfoH264 *picture_info) |
||
327 | { |
||
328 | unsigned i; |
||
329 | |||
330 | VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding H264\n"); |
||
331 | |||
332 | picture->slice_count = picture_info->slice_count; |
||
333 | picture->field_order_cnt[0] = picture_info->field_order_cnt[0]; |
||
334 | picture->field_order_cnt[1] = picture_info->field_order_cnt[1]; |
||
335 | picture->is_reference = picture_info->is_reference; |
||
336 | picture->frame_num = picture_info->frame_num; |
||
337 | picture->field_pic_flag = picture_info->field_pic_flag; |
||
338 | picture->bottom_field_flag = picture_info->bottom_field_flag; |
||
339 | picture->num_ref_frames = picture_info->num_ref_frames; |
||
340 | picture->mb_adaptive_frame_field_flag = picture_info->mb_adaptive_frame_field_flag; |
||
341 | picture->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag; |
||
342 | picture->weighted_pred_flag = picture_info->weighted_pred_flag; |
||
343 | picture->weighted_bipred_idc = picture_info->weighted_bipred_idc; |
||
344 | picture->frame_mbs_only_flag = picture_info->frame_mbs_only_flag; |
||
345 | picture->transform_8x8_mode_flag = picture_info->transform_8x8_mode_flag; |
||
346 | picture->chroma_qp_index_offset = picture_info->chroma_qp_index_offset; |
||
347 | picture->second_chroma_qp_index_offset = picture_info->second_chroma_qp_index_offset; |
||
348 | picture->pic_init_qp_minus26 = picture_info->pic_init_qp_minus26; |
||
349 | picture->num_ref_idx_l0_active_minus1 = picture_info->num_ref_idx_l0_active_minus1; |
||
350 | picture->num_ref_idx_l1_active_minus1 = picture_info->num_ref_idx_l1_active_minus1; |
||
351 | picture->log2_max_frame_num_minus4 = picture_info->log2_max_frame_num_minus4; |
||
352 | picture->pic_order_cnt_type = picture_info->pic_order_cnt_type; |
||
353 | picture->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4; |
||
354 | picture->delta_pic_order_always_zero_flag = picture_info->delta_pic_order_always_zero_flag; |
||
355 | picture->direct_8x8_inference_flag = picture_info->direct_8x8_inference_flag; |
||
356 | picture->entropy_coding_mode_flag = picture_info->entropy_coding_mode_flag; |
||
357 | picture->pic_order_present_flag = picture_info->pic_order_present_flag; |
||
358 | picture->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag; |
||
359 | picture->redundant_pic_cnt_present_flag = picture_info->redundant_pic_cnt_present_flag; |
||
360 | |||
361 | memcpy(picture->scaling_lists_4x4, picture_info->scaling_lists_4x4, 6*16); |
||
362 | memcpy(picture->scaling_lists_8x8, picture_info->scaling_lists_8x8, 2*64); |
||
363 | |||
364 | for (i = 0; i < 16; ++i) { |
||
365 | VdpStatus ret = vlVdpGetReferenceFrame |
||
366 | ( |
||
367 | picture_info->referenceFrames[i].surface, |
||
368 | &picture->ref[i] |
||
369 | ); |
||
370 | if (ret != VDP_STATUS_OK) |
||
371 | return ret; |
||
372 | |||
373 | picture->is_long_term[i] = picture_info->referenceFrames[i].is_long_term; |
||
374 | picture->top_is_reference[i] = picture_info->referenceFrames[i].top_is_reference; |
||
375 | picture->bottom_is_reference[i] = picture_info->referenceFrames[i].bottom_is_reference; |
||
376 | picture->field_order_cnt_list[i][0] = picture_info->referenceFrames[i].field_order_cnt[0]; |
||
377 | picture->field_order_cnt_list[i][1] = picture_info->referenceFrames[i].field_order_cnt[1]; |
||
378 | picture->frame_num_list[i] = picture_info->referenceFrames[i].frame_idx; |
||
379 | } |
||
380 | |||
381 | return VDP_STATUS_OK; |
||
382 | } |
||
383 | |||
384 | static void |
||
385 | vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[]) |
||
386 | { |
||
387 | static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D }; |
||
388 | struct vl_vlc vlc; |
||
389 | unsigned i; |
||
390 | |||
391 | /* search the first 64 bytes for a startcode */ |
||
392 | vl_vlc_init(&vlc, *num_buffers, buffers, sizes); |
||
393 | for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= 32; ++i) { |
||
394 | uint32_t value = vl_vlc_peekbits(&vlc, 32); |
||
395 | if (value == 0x0000010D || |
||
396 | value == 0x0000010C || |
||
397 | value == 0x0000010B) |
||
398 | return; |
||
399 | vl_vlc_eatbits(&vlc, 8); |
||
400 | vl_vlc_fillbits(&vlc); |
||
401 | } |
||
402 | |||
403 | /* none found, ok add one manually */ |
||
404 | VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n"); |
||
405 | for (i = *num_buffers; i > 0; --i) { |
||
406 | buffers[i] = buffers[i - 1]; |
||
407 | sizes[i] = sizes[i - 1]; |
||
408 | } |
||
409 | ++(*num_buffers); |
||
410 | buffers[0] = vc1_startcode; |
||
411 | sizes[0] = 4; |
||
412 | } |
||
413 | |||
414 | /** |
||
415 | * Decode a compressed field/frame and render the result into a VdpVideoSurface. |
||
416 | */ |
||
417 | VdpStatus |
||
418 | vlVdpDecoderRender(VdpDecoder decoder, |
||
419 | VdpVideoSurface target, |
||
420 | VdpPictureInfo const *picture_info, |
||
421 | uint32_t bitstream_buffer_count, |
||
422 | VdpBitstreamBuffer const *bitstream_buffers) |
||
423 | { |
||
424 | const void * buffers[bitstream_buffer_count + 1]; |
||
425 | unsigned sizes[bitstream_buffer_count + 1]; |
||
426 | vlVdpDecoder *vldecoder; |
||
427 | vlVdpSurface *vlsurf; |
||
428 | VdpStatus ret; |
||
429 | struct pipe_screen *screen; |
||
430 | struct pipe_video_decoder *dec; |
||
431 | bool buffer_support[2]; |
||
432 | unsigned i; |
||
433 | union { |
||
434 | struct pipe_picture_desc base; |
||
435 | struct pipe_mpeg12_picture_desc mpeg12; |
||
436 | struct pipe_mpeg4_picture_desc mpeg4; |
||
437 | struct pipe_vc1_picture_desc vc1; |
||
438 | struct pipe_h264_picture_desc h264; |
||
439 | } desc; |
||
440 | |||
441 | if (!(picture_info && bitstream_buffers)) |
||
442 | return VDP_STATUS_INVALID_POINTER; |
||
443 | |||
444 | vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); |
||
445 | if (!vldecoder) |
||
446 | return VDP_STATUS_INVALID_HANDLE; |
||
447 | dec = vldecoder->decoder; |
||
448 | screen = dec->context->screen; |
||
449 | |||
450 | vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); |
||
451 | if (!vlsurf) |
||
452 | return VDP_STATUS_INVALID_HANDLE; |
||
453 | |||
454 | if (vlsurf->device != vldecoder->device) |
||
455 | return VDP_STATUS_HANDLE_DEVICE_MISMATCH; |
||
456 | |||
457 | if (vlsurf->video_buffer != NULL && vlsurf->video_buffer->chroma_format != dec->chroma_format) |
||
458 | // TODO: Recreate decoder with correct chroma |
||
459 | return VDP_STATUS_INVALID_CHROMA_TYPE; |
||
460 | |||
461 | pipe_mutex_lock(vlsurf->device->mutex); |
||
462 | |||
463 | buffer_support[0] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); |
||
464 | buffer_support[1] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_INTERLACED); |
||
465 | |||
466 | if (vlsurf->video_buffer == NULL || |
||
467 | !screen->is_video_format_supported(screen, vlsurf->video_buffer->buffer_format, dec->profile) || |
||
468 | !buffer_support[vlsurf->video_buffer->interlaced]) { |
||
469 | |||
470 | /* destroy the old one */ |
||
471 | if (vlsurf->video_buffer) |
||
472 | vlsurf->video_buffer->destroy(vlsurf->video_buffer); |
||
473 | |||
474 | /* set the buffer format to the prefered one */ |
||
475 | vlsurf->templat.buffer_format = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERED_FORMAT); |
||
476 | |||
477 | /* also set interlacing to decoders preferences */ |
||
478 | vlsurf->templat.interlaced = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERS_INTERLACED); |
||
479 | |||
480 | /* and recreate the video buffer */ |
||
481 | vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, &vlsurf->templat); |
||
482 | |||
483 | /* still no luck? get me out of here... */ |
||
484 | if (!vlsurf->video_buffer) { |
||
485 | pipe_mutex_unlock(vlsurf->device->mutex); |
||
486 | return VDP_STATUS_NO_IMPLEMENTATION; |
||
487 | } |
||
488 | vlVdpVideoSurfaceClear(vlsurf); |
||
489 | } |
||
490 | |||
491 | for (i = 0; i < bitstream_buffer_count; ++i) { |
||
492 | buffers[i] = bitstream_buffers[i].bitstream; |
||
493 | sizes[i] = bitstream_buffers[i].bitstream_bytes; |
||
494 | } |
||
495 | |||
496 | memset(&desc, 0, sizeof(desc)); |
||
497 | desc.base.profile = dec->profile; |
||
498 | switch (u_reduce_video_profile(dec->profile)) { |
||
499 | case PIPE_VIDEO_CODEC_MPEG12: |
||
500 | ret = vlVdpDecoderRenderMpeg12(&desc.mpeg12, (VdpPictureInfoMPEG1Or2 *)picture_info); |
||
501 | break; |
||
502 | case PIPE_VIDEO_CODEC_MPEG4: |
||
503 | ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2 *)picture_info); |
||
504 | break; |
||
505 | case PIPE_VIDEO_CODEC_VC1: |
||
506 | if (dec->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) |
||
507 | vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers, sizes); |
||
508 | ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1 *)picture_info); |
||
509 | break; |
||
510 | case PIPE_VIDEO_CODEC_MPEG4_AVC: |
||
511 | ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 *)picture_info); |
||
512 | break; |
||
513 | default: |
||
514 | pipe_mutex_unlock(vlsurf->device->mutex); |
||
515 | return VDP_STATUS_INVALID_DECODER_PROFILE; |
||
516 | } |
||
517 | |||
518 | if (ret != VDP_STATUS_OK) { |
||
519 | pipe_mutex_unlock(vlsurf->device->mutex); |
||
520 | return ret; |
||
521 | } |
||
522 | |||
523 | dec->begin_frame(dec, vlsurf->video_buffer, &desc.base); |
||
524 | dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes); |
||
525 | dec->end_frame(dec, vlsurf->video_buffer, &desc.base); |
||
526 | pipe_mutex_unlock(vlsurf->device->mutex); |
||
527 | return ret; |
||
528 | }>>>> |