• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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