1 /**************************************************************************
2 *
3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4 * Copyright 2014 Advanced Micro Devices, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "pipe/p_video_codec.h"
30
31 #include "util/u_handle_table.h"
32 #include "util/u_video.h"
33 #include "util/u_memory.h"
34
35 #include "vl/vl_vlc.h"
36 #include "vl/vl_winsys.h"
37
38 #include "va_private.h"
39
40 VAStatus
vlVaBeginPicture(VADriverContextP ctx,VAContextID context_id,VASurfaceID render_target)41 vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target)
42 {
43 vlVaDriver *drv;
44 vlVaContext *context;
45 vlVaSurface *surf;
46
47 if (!ctx)
48 return VA_STATUS_ERROR_INVALID_CONTEXT;
49
50 drv = VL_VA_DRIVER(ctx);
51 if (!drv)
52 return VA_STATUS_ERROR_INVALID_CONTEXT;
53
54 mtx_lock(&drv->mutex);
55 context = handle_table_get(drv->htab, context_id);
56 if (!context) {
57 mtx_unlock(&drv->mutex);
58 return VA_STATUS_ERROR_INVALID_CONTEXT;
59 }
60
61 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) {
62 context->desc.mpeg12.intra_matrix = NULL;
63 context->desc.mpeg12.non_intra_matrix = NULL;
64 }
65
66 surf = handle_table_get(drv->htab, render_target);
67 mtx_unlock(&drv->mutex);
68 if (!surf || !surf->buffer)
69 return VA_STATUS_ERROR_INVALID_SURFACE;
70
71 context->target_id = render_target;
72 surf->ctx = context_id;
73 context->target = surf->buffer;
74 context->mjpeg.sampling_factor = 0;
75
76 if (!context->decoder) {
77
78 /* VPP */
79 if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN &&
80 context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
81 context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
82 context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
83 context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM &&
84 context->target->buffer_format != PIPE_FORMAT_NV12 &&
85 context->target->buffer_format != PIPE_FORMAT_P010 &&
86 context->target->buffer_format != PIPE_FORMAT_P016)
87 return VA_STATUS_ERROR_UNIMPLEMENTED;
88
89 return VA_STATUS_SUCCESS;
90 }
91
92 if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE)
93 context->needs_begin_frame = true;
94
95 return VA_STATUS_SUCCESS;
96 }
97
98 void
vlVaGetReferenceFrame(vlVaDriver * drv,VASurfaceID surface_id,struct pipe_video_buffer ** ref_frame)99 vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id,
100 struct pipe_video_buffer **ref_frame)
101 {
102 vlVaSurface *surf = handle_table_get(drv->htab, surface_id);
103 if (surf)
104 *ref_frame = surf->buffer;
105 else
106 *ref_frame = NULL;
107 }
108
109 static VAStatus
handlePictureParameterBuffer(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)110 handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
111 {
112 VAStatus vaStatus = VA_STATUS_SUCCESS;
113 enum pipe_video_format format =
114 u_reduce_video_profile(context->templat.profile);
115
116 switch (format) {
117 case PIPE_VIDEO_FORMAT_MPEG12:
118 vlVaHandlePictureParameterBufferMPEG12(drv, context, buf);
119 break;
120
121 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
122 vlVaHandlePictureParameterBufferH264(drv, context, buf);
123 break;
124
125 case PIPE_VIDEO_FORMAT_VC1:
126 vlVaHandlePictureParameterBufferVC1(drv, context, buf);
127 break;
128
129 case PIPE_VIDEO_FORMAT_MPEG4:
130 vlVaHandlePictureParameterBufferMPEG4(drv, context, buf);
131 break;
132
133 case PIPE_VIDEO_FORMAT_HEVC:
134 vlVaHandlePictureParameterBufferHEVC(drv, context, buf);
135 break;
136
137 case PIPE_VIDEO_FORMAT_JPEG:
138 vlVaHandlePictureParameterBufferMJPEG(drv, context, buf);
139 break;
140
141 case PIPE_VIDEO_FORMAT_VP9:
142 vlVaHandlePictureParameterBufferVP9(drv, context, buf);
143 break;
144
145 default:
146 break;
147 }
148
149 /* Create the decoder once max_references is known. */
150 if (!context->decoder) {
151 if (!context->target)
152 return VA_STATUS_ERROR_INVALID_CONTEXT;
153
154 if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC)
155 context->templat.level = u_get_h264_level(context->templat.width,
156 context->templat.height, &context->templat.max_references);
157
158 context->decoder = drv->pipe->create_video_codec(drv->pipe,
159 &context->templat);
160
161 if (!context->decoder)
162 return VA_STATUS_ERROR_ALLOCATION_FAILED;
163
164 context->needs_begin_frame = true;
165 }
166
167 if (format == PIPE_VIDEO_FORMAT_VP9) {
168 context->decoder->width =
169 context->desc.vp9.picture_parameter.frame_width;
170 context->decoder->height =
171 context->desc.vp9.picture_parameter.frame_height;
172 }
173
174 return vaStatus;
175 }
176
177 static void
handleIQMatrixBuffer(vlVaContext * context,vlVaBuffer * buf)178 handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf)
179 {
180 switch (u_reduce_video_profile(context->templat.profile)) {
181 case PIPE_VIDEO_FORMAT_MPEG12:
182 vlVaHandleIQMatrixBufferMPEG12(context, buf);
183 break;
184
185 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
186 vlVaHandleIQMatrixBufferH264(context, buf);
187 break;
188
189 case PIPE_VIDEO_FORMAT_MPEG4:
190 vlVaHandleIQMatrixBufferMPEG4(context, buf);
191 break;
192
193 case PIPE_VIDEO_FORMAT_HEVC:
194 vlVaHandleIQMatrixBufferHEVC(context, buf);
195 break;
196
197 case PIPE_VIDEO_FORMAT_JPEG:
198 vlVaHandleIQMatrixBufferMJPEG(context, buf);
199 break;
200
201 default:
202 break;
203 }
204 }
205
206 static void
handleSliceParameterBuffer(vlVaContext * context,vlVaBuffer * buf)207 handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf)
208 {
209 switch (u_reduce_video_profile(context->templat.profile)) {
210 case PIPE_VIDEO_FORMAT_MPEG12:
211 vlVaHandleSliceParameterBufferMPEG12(context, buf);
212 break;
213
214 case PIPE_VIDEO_FORMAT_VC1:
215 vlVaHandleSliceParameterBufferVC1(context, buf);
216 break;
217
218 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
219 vlVaHandleSliceParameterBufferH264(context, buf);
220 break;
221
222 case PIPE_VIDEO_FORMAT_MPEG4:
223 vlVaHandleSliceParameterBufferMPEG4(context, buf);
224 break;
225
226 case PIPE_VIDEO_FORMAT_HEVC:
227 vlVaHandleSliceParameterBufferHEVC(context, buf);
228 break;
229
230 case PIPE_VIDEO_FORMAT_JPEG:
231 vlVaHandleSliceParameterBufferMJPEG(context, buf);
232 break;
233
234 case PIPE_VIDEO_FORMAT_VP9:
235 vlVaHandleSliceParameterBufferVP9(context, buf);
236 break;
237
238 default:
239 break;
240 }
241 }
242
243 static unsigned int
bufHasStartcode(vlVaBuffer * buf,unsigned int code,unsigned int bits)244 bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits)
245 {
246 struct vl_vlc vlc = {0};
247 int i;
248
249 /* search the first 64 bytes for a startcode */
250 vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size);
251 for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) {
252 if (vl_vlc_peekbits(&vlc, bits) == code)
253 return 1;
254 vl_vlc_eatbits(&vlc, 8);
255 vl_vlc_fillbits(&vlc);
256 }
257
258 return 0;
259 }
260
261 static void
handleVAProtectedSliceDataBufferType(vlVaContext * context,vlVaBuffer * buf)262 handleVAProtectedSliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
263 {
264 uint8_t* encrypted_data = (uint8_t*) buf->data;
265
266 unsigned int drm_key_size = 56 * 4;
267
268 context->desc.base.decrypt_key = CALLOC(1, drm_key_size);
269 memcpy(context->desc.base.decrypt_key, encrypted_data, drm_key_size);
270 context->desc.base.protected_playback = true;
271 }
272
273 static void
handleVASliceDataBufferType(vlVaContext * context,vlVaBuffer * buf)274 handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
275 {
276 enum pipe_video_format format = u_reduce_video_profile(context->templat.profile);
277 unsigned num_buffers = 0;
278 void * const *buffers[3];
279 unsigned sizes[3];
280 static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 };
281 static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 };
282 static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d };
283 static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 };
284
285 format = u_reduce_video_profile(context->templat.profile);
286 if (!context->desc.base.protected_playback) {
287 switch (format) {
288 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
289 if (bufHasStartcode(buf, 0x000001, 24))
290 break;
291
292 buffers[num_buffers] = (void *const)&start_code_h264;
293 sizes[num_buffers++] = sizeof(start_code_h264);
294 break;
295 case PIPE_VIDEO_FORMAT_HEVC:
296 if (bufHasStartcode(buf, 0x000001, 24))
297 break;
298
299 buffers[num_buffers] = (void *const)&start_code_h265;
300 sizes[num_buffers++] = sizeof(start_code_h265);
301 break;
302 case PIPE_VIDEO_FORMAT_VC1:
303 if (bufHasStartcode(buf, 0x0000010d, 32) ||
304 bufHasStartcode(buf, 0x0000010c, 32) ||
305 bufHasStartcode(buf, 0x0000010b, 32))
306 break;
307
308 if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) {
309 buffers[num_buffers] = (void *const)&start_code_vc1;
310 sizes[num_buffers++] = sizeof(start_code_vc1);
311 }
312 break;
313 case PIPE_VIDEO_FORMAT_MPEG4:
314 if (bufHasStartcode(buf, 0x000001, 24))
315 break;
316
317 vlVaDecoderFixMPEG4Startcode(context);
318 buffers[num_buffers] = (void *)context->mpeg4.start_code;
319 sizes[num_buffers++] = context->mpeg4.start_code_size;
320 break;
321 case PIPE_VIDEO_FORMAT_JPEG:
322 vlVaGetJpegSliceHeader(context);
323 buffers[num_buffers] = (void *)context->mjpeg.slice_header;
324 sizes[num_buffers++] = context->mjpeg.slice_header_size;
325 break;
326 case PIPE_VIDEO_FORMAT_VP9:
327 vlVaDecoderVP9BitstreamHeader(context, buf);
328 break;
329 default:
330 break;
331 }
332 }
333
334 if (context->desc.base.protected_playback && PIPE_VIDEO_FORMAT_VP9 == format){
335 vlVaDecoderVP9BitstreamHeader(context, buf);
336 buffers[num_buffers] = buf->data + context->desc.vp9.picture_parameter.frame_header_length_in_bytes;
337 sizes[num_buffers] = buf->size - context->desc.vp9.picture_parameter.frame_header_length_in_bytes;
338 ++num_buffers;
339 } else {
340 buffers[num_buffers] = buf->data;
341 sizes[num_buffers] = buf->size;
342 ++num_buffers;
343 }
344
345 if (format == PIPE_VIDEO_FORMAT_JPEG) {
346 buffers[num_buffers] = (void *const)&eoi_jpeg;
347 sizes[num_buffers++] = sizeof(eoi_jpeg);
348 }
349
350 if (context->needs_begin_frame) {
351 context->decoder->begin_frame(context->decoder, context->target,
352 &context->desc.base);
353 context->needs_begin_frame = false;
354 }
355 context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base,
356 num_buffers, (const void * const*)buffers, sizes);
357 }
358
359 static VAStatus
handleVAEncMiscParameterTypeRateControl(vlVaContext * context,VAEncMiscParameterBuffer * misc)360 handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc)
361 {
362 VAStatus status = VA_STATUS_SUCCESS;
363
364 switch (u_reduce_video_profile(context->templat.profile)) {
365 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
366 status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc);
367 break;
368
369 case PIPE_VIDEO_FORMAT_HEVC:
370 status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc);
371 break;
372
373 default:
374 break;
375 }
376
377 return status;
378 }
379
380 static VAStatus
handleVAEncMiscParameterTypeFrameRate(vlVaContext * context,VAEncMiscParameterBuffer * misc)381 handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc)
382 {
383 VAStatus status = VA_STATUS_SUCCESS;
384
385 switch (u_reduce_video_profile(context->templat.profile)) {
386 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
387 status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc);
388 break;
389
390 case PIPE_VIDEO_FORMAT_HEVC:
391 status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc);
392 break;
393
394 default:
395 break;
396 }
397
398 return status;
399 }
400
401 static VAStatus
handleVAEncSequenceParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)402 handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
403 {
404 VAStatus status = VA_STATUS_SUCCESS;
405
406 switch (u_reduce_video_profile(context->templat.profile)) {
407 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
408 status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf);
409 break;
410
411 case PIPE_VIDEO_FORMAT_HEVC:
412 status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf);
413 break;
414
415 default:
416 break;
417 }
418
419 return status;
420 }
421
422 static VAStatus
handleVAEncMiscParameterBufferType(vlVaContext * context,vlVaBuffer * buf)423 handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
424 {
425 VAStatus vaStatus = VA_STATUS_SUCCESS;
426 VAEncMiscParameterBuffer *misc;
427 misc = buf->data;
428
429 switch (misc->type) {
430 case VAEncMiscParameterTypeRateControl:
431 vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc);
432 break;
433
434 case VAEncMiscParameterTypeFrameRate:
435 vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc);
436 break;
437
438 default:
439 break;
440 }
441
442 return vaStatus;
443 }
444
445 static VAStatus
handleVAEncPictureParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)446 handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
447 {
448 VAStatus status = VA_STATUS_SUCCESS;
449
450 switch (u_reduce_video_profile(context->templat.profile)) {
451 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
452 status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf);
453 break;
454
455 case PIPE_VIDEO_FORMAT_HEVC:
456 status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf);
457 break;
458
459 default:
460 break;
461 }
462
463 return status;
464 }
465
466 static VAStatus
handleVAEncSliceParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)467 handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
468 {
469 VAStatus status = VA_STATUS_SUCCESS;
470
471 switch (u_reduce_video_profile(context->templat.profile)) {
472 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
473 status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf);
474 break;
475
476 case PIPE_VIDEO_FORMAT_HEVC:
477 status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf);
478 break;
479
480 default:
481 break;
482 }
483
484 return status;
485 }
486
487 static VAStatus
handleVAEncPackedHeaderParameterBufferType(vlVaContext * context,vlVaBuffer * buf)488 handleVAEncPackedHeaderParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
489 {
490 VAStatus status = VA_STATUS_SUCCESS;
491
492 switch (u_reduce_video_profile(context->templat.profile)) {
493 case PIPE_VIDEO_FORMAT_HEVC:
494 break;
495
496 default:
497 return VA_STATUS_ERROR_UNIMPLEMENTED;
498 }
499
500 VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)buf->data;
501 if (param->type == VAEncPackedHeaderSequence)
502 context->packed_header_type = param->type;
503 else
504 status = VA_STATUS_ERROR_UNIMPLEMENTED;
505
506 return status;
507 }
508
509 static VAStatus
handleVAEncPackedHeaderDataBufferType(vlVaContext * context,vlVaBuffer * buf)510 handleVAEncPackedHeaderDataBufferType(vlVaContext *context, vlVaBuffer *buf)
511 {
512 VAStatus status = VA_STATUS_SUCCESS;
513
514 if (context->packed_header_type != VAEncPackedHeaderSequence)
515 return VA_STATUS_ERROR_UNIMPLEMENTED;
516
517 switch (u_reduce_video_profile(context->templat.profile)) {
518 case PIPE_VIDEO_FORMAT_HEVC:
519 status = vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(context, buf);
520 break;
521
522 default:
523 break;
524 }
525
526 return status;
527 }
528
529 VAStatus
vlVaRenderPicture(VADriverContextP ctx,VAContextID context_id,VABufferID * buffers,int num_buffers)530 vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers)
531 {
532 vlVaDriver *drv;
533 vlVaContext *context;
534 VAStatus vaStatus = VA_STATUS_SUCCESS;
535
536 unsigned i;
537
538 if (!ctx)
539 return VA_STATUS_ERROR_INVALID_CONTEXT;
540
541 drv = VL_VA_DRIVER(ctx);
542 if (!drv)
543 return VA_STATUS_ERROR_INVALID_CONTEXT;
544
545 mtx_lock(&drv->mutex);
546 context = handle_table_get(drv->htab, context_id);
547 if (!context) {
548 mtx_unlock(&drv->mutex);
549 return VA_STATUS_ERROR_INVALID_CONTEXT;
550 }
551
552 /* Always process VAProtectedSliceDataBufferType first because it changes the state */
553 for (i = 0; i < num_buffers; ++i) {
554 vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]);
555 if (!buf) {
556 mtx_unlock(&drv->mutex);
557 return VA_STATUS_ERROR_INVALID_BUFFER;
558 }
559
560 if (buf->type == VAProtectedSliceDataBufferType)
561 handleVAProtectedSliceDataBufferType(context, buf);
562 }
563
564 for (i = 0; i < num_buffers; ++i) {
565 vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]);
566
567 switch (buf->type) {
568 case VAPictureParameterBufferType:
569 vaStatus = handlePictureParameterBuffer(drv, context, buf);
570 break;
571
572 case VAIQMatrixBufferType:
573 handleIQMatrixBuffer(context, buf);
574 break;
575
576 case VASliceParameterBufferType:
577 handleSliceParameterBuffer(context, buf);
578 break;
579
580 case VASliceDataBufferType:
581 handleVASliceDataBufferType(context, buf);
582 break;
583
584 case VAProcPipelineParameterBufferType:
585 vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf);
586 break;
587
588 case VAEncSequenceParameterBufferType:
589 vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf);
590 break;
591
592 case VAEncMiscParameterBufferType:
593 vaStatus = handleVAEncMiscParameterBufferType(context, buf);
594 break;
595
596 case VAEncPictureParameterBufferType:
597 vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf);
598 break;
599
600 case VAEncSliceParameterBufferType:
601 vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf);
602 break;
603
604 case VAHuffmanTableBufferType:
605 vlVaHandleHuffmanTableBufferType(context, buf);
606 break;
607
608 case VAEncPackedHeaderParameterBufferType:
609 handleVAEncPackedHeaderParameterBufferType(context, buf);
610 break;
611 case VAEncPackedHeaderDataBufferType:
612 handleVAEncPackedHeaderDataBufferType(context, buf);
613 break;
614
615 default:
616 break;
617 }
618 }
619 mtx_unlock(&drv->mutex);
620
621 return vaStatus;
622 }
623
624 VAStatus
vlVaEndPicture(VADriverContextP ctx,VAContextID context_id)625 vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
626 {
627 vlVaDriver *drv;
628 vlVaContext *context;
629 vlVaBuffer *coded_buf;
630 vlVaSurface *surf;
631 void *feedback;
632 struct pipe_screen *screen;
633 bool supported;
634 bool realloc = false;
635 enum pipe_format format;
636
637 if (!ctx)
638 return VA_STATUS_ERROR_INVALID_CONTEXT;
639
640 drv = VL_VA_DRIVER(ctx);
641 if (!drv)
642 return VA_STATUS_ERROR_INVALID_CONTEXT;
643
644 mtx_lock(&drv->mutex);
645 context = handle_table_get(drv->htab, context_id);
646 mtx_unlock(&drv->mutex);
647 if (!context)
648 return VA_STATUS_ERROR_INVALID_CONTEXT;
649
650 if (!context->decoder) {
651 if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN)
652 return VA_STATUS_ERROR_INVALID_CONTEXT;
653
654 /* VPP */
655 return VA_STATUS_SUCCESS;
656 }
657
658 mtx_lock(&drv->mutex);
659 surf = handle_table_get(drv->htab, context->target_id);
660 context->mpeg4.frame_num++;
661
662 screen = context->decoder->context->screen;
663 supported = screen->get_video_param(screen, context->decoder->profile,
664 context->decoder->entrypoint,
665 surf->buffer->interlaced ?
666 PIPE_VIDEO_CAP_SUPPORTS_INTERLACED :
667 PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
668
669 if (!supported) {
670 surf->templat.interlaced = screen->get_video_param(screen,
671 context->decoder->profile,
672 context->decoder->entrypoint,
673 PIPE_VIDEO_CAP_PREFERS_INTERLACED);
674 realloc = true;
675 }
676
677 format = screen->get_video_param(screen, context->decoder->profile,
678 PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
679 PIPE_VIDEO_CAP_PREFERED_FORMAT);
680
681 if (surf->buffer->buffer_format != format &&
682 surf->buffer->buffer_format == PIPE_FORMAT_NV12) {
683 /* check originally as NV12 only */
684 surf->templat.buffer_format = format;
685 realloc = true;
686 }
687
688 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG &&
689 surf->buffer->buffer_format == PIPE_FORMAT_NV12) {
690 if (context->mjpeg.sampling_factor == 0x211111 ||
691 context->mjpeg.sampling_factor == 0x221212) {
692 surf->templat.buffer_format = PIPE_FORMAT_YUYV;
693 realloc = true;
694 } else if (context->mjpeg.sampling_factor != 0x221111) {
695 /* Not NV12 either */
696 mtx_unlock(&drv->mutex);
697 return VA_STATUS_ERROR_INVALID_SURFACE;
698 }
699 }
700
701 if ((surf->templat.bind & PIPE_BIND_PROTECTED) != context->desc.base.protected_playback) {
702 if (context->desc.base.protected_playback) {
703 surf->templat.bind |= PIPE_BIND_PROTECTED;
704 }
705 else
706 surf->templat.bind &= ~PIPE_BIND_PROTECTED;
707 realloc = true;
708 }
709
710 if (realloc) {
711 struct pipe_video_buffer *old_buf = surf->buffer;
712
713 if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) {
714 mtx_unlock(&drv->mutex);
715 return VA_STATUS_ERROR_ALLOCATION_FAILED;
716 }
717
718 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
719 if (old_buf->interlaced) {
720 struct u_rect src_rect, dst_rect;
721
722 dst_rect.x0 = src_rect.x0 = 0;
723 dst_rect.y0 = src_rect.y0 = 0;
724 dst_rect.x1 = src_rect.x1 = surf->templat.width;
725 dst_rect.y1 = src_rect.y1 = surf->templat.height;
726 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
727 old_buf, surf->buffer,
728 &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE);
729 } else {
730 /* Can't convert from progressive to interlaced yet */
731 mtx_unlock(&drv->mutex);
732 return VA_STATUS_ERROR_INVALID_SURFACE;
733 }
734 }
735
736 old_buf->destroy(old_buf);
737 context->target = surf->buffer;
738 }
739
740 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
741 coded_buf = context->coded_buf;
742 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
743 getEncParamPresetH264(context);
744 context->desc.h264enc.frame_num_cnt++;
745 } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
746 getEncParamPresetH265(context);
747 context->decoder->begin_frame(context->decoder, context->target, &context->desc.base);
748 context->decoder->encode_bitstream(context->decoder, context->target,
749 coded_buf->derived_surface.resource, &feedback);
750 surf->feedback = feedback;
751 surf->coded_buf = coded_buf;
752 }
753
754 context->decoder->end_frame(context->decoder, context->target, &context->desc.base);
755 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE &&
756 u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
757 int idr_period = context->desc.h264enc.gop_size / context->gop_coeff;
758 int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num;
759 surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt;
760 surf->force_flushed = false;
761 if (context->first_single_submitted) {
762 context->decoder->flush(context->decoder);
763 context->first_single_submitted = false;
764 surf->force_flushed = true;
765 }
766 if (p_remain_in_idr == 1) {
767 if ((context->desc.h264enc.frame_num_cnt % 2) != 0) {
768 context->decoder->flush(context->decoder);
769 context->first_single_submitted = true;
770 }
771 else
772 context->first_single_submitted = false;
773 surf->force_flushed = true;
774 }
775 } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE &&
776 u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
777 context->desc.h265enc.frame_num++;
778 mtx_unlock(&drv->mutex);
779 return VA_STATUS_SUCCESS;
780 }
781