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
34#include "vl/vl_vlc.h"
35#include "vl/vl_winsys.h"
36
37#include "va_private.h"
38
39VAStatus
40vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target)
41{
42   vlVaDriver *drv;
43   vlVaContext *context;
44   vlVaSurface *surf;
45
46   if (!ctx)
47      return VA_STATUS_ERROR_INVALID_CONTEXT;
48
49   drv = VL_VA_DRIVER(ctx);
50   if (!drv)
51      return VA_STATUS_ERROR_INVALID_CONTEXT;
52
53   mtx_lock(&drv->mutex);
54   context = handle_table_get(drv->htab, context_id);
55   if (!context) {
56      mtx_unlock(&drv->mutex);
57      return VA_STATUS_ERROR_INVALID_CONTEXT;
58   }
59
60   if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) {
61      context->desc.mpeg12.intra_matrix = NULL;
62      context->desc.mpeg12.non_intra_matrix = NULL;
63   }
64
65   surf = handle_table_get(drv->htab, render_target);
66   mtx_unlock(&drv->mutex);
67   if (!surf || !surf->buffer)
68      return VA_STATUS_ERROR_INVALID_SURFACE;
69
70   context->target_id = render_target;
71   surf->ctx = context_id;
72   context->target = surf->buffer;
73   context->mjpeg.sampling_factor = 0;
74
75   if (!context->decoder) {
76
77      /* VPP */
78      if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN &&
79          context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
80          context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
81          context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
82          context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM &&
83          context->target->buffer_format != PIPE_FORMAT_NV12 &&
84          context->target->buffer_format != PIPE_FORMAT_P016)
85         return VA_STATUS_ERROR_UNIMPLEMENTED;
86
87      return VA_STATUS_SUCCESS;
88   }
89
90   if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE)
91      context->needs_begin_frame = true;
92
93   return VA_STATUS_SUCCESS;
94}
95
96void
97vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id,
98                      struct pipe_video_buffer **ref_frame)
99{
100   vlVaSurface *surf = handle_table_get(drv->htab, surface_id);
101   if (surf)
102      *ref_frame = surf->buffer;
103   else
104      *ref_frame = NULL;
105}
106
107static VAStatus
108handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
109{
110   VAStatus vaStatus = VA_STATUS_SUCCESS;
111
112   switch (u_reduce_video_profile(context->templat.profile)) {
113   case PIPE_VIDEO_FORMAT_MPEG12:
114      vlVaHandlePictureParameterBufferMPEG12(drv, context, buf);
115      break;
116
117   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
118      vlVaHandlePictureParameterBufferH264(drv, context, buf);
119      break;
120
121   case PIPE_VIDEO_FORMAT_VC1:
122      vlVaHandlePictureParameterBufferVC1(drv, context, buf);
123      break;
124
125   case PIPE_VIDEO_FORMAT_MPEG4:
126      vlVaHandlePictureParameterBufferMPEG4(drv, context, buf);
127      break;
128
129  case PIPE_VIDEO_FORMAT_HEVC:
130      vlVaHandlePictureParameterBufferHEVC(drv, context, buf);
131      break;
132
133  case PIPE_VIDEO_FORMAT_JPEG:
134      vlVaHandlePictureParameterBufferMJPEG(drv, context, buf);
135      break;
136
137  case PIPE_VIDEO_FORMAT_VP9:
138      vlVaHandlePictureParameterBufferVP9(drv, context, buf);
139      break;
140
141   default:
142      break;
143   }
144
145   /* Create the decoder once max_references is known. */
146   if (!context->decoder) {
147      enum pipe_video_format format =
148         u_reduce_video_profile(context->templat.profile);
149
150      if (!context->target)
151         return VA_STATUS_ERROR_INVALID_CONTEXT;
152
153      if (context->templat.max_references == 0 &&
154         format != PIPE_VIDEO_FORMAT_JPEG)
155         return VA_STATUS_ERROR_INVALID_BUFFER;
156
157      if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC)
158         context->templat.level = u_get_h264_level(context->templat.width,
159            context->templat.height, &context->templat.max_references);
160
161      context->decoder = drv->pipe->create_video_codec(drv->pipe,
162         &context->templat);
163
164      if (!context->decoder)
165         return VA_STATUS_ERROR_ALLOCATION_FAILED;
166
167      context->needs_begin_frame = true;
168   }
169
170   return vaStatus;
171}
172
173static void
174handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf)
175{
176   switch (u_reduce_video_profile(context->templat.profile)) {
177   case PIPE_VIDEO_FORMAT_MPEG12:
178      vlVaHandleIQMatrixBufferMPEG12(context, buf);
179      break;
180
181   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
182      vlVaHandleIQMatrixBufferH264(context, buf);
183      break;
184
185   case PIPE_VIDEO_FORMAT_MPEG4:
186      vlVaHandleIQMatrixBufferMPEG4(context, buf);
187      break;
188
189   case PIPE_VIDEO_FORMAT_HEVC:
190      vlVaHandleIQMatrixBufferHEVC(context, buf);
191      break;
192
193   case PIPE_VIDEO_FORMAT_JPEG:
194      vlVaHandleIQMatrixBufferMJPEG(context, buf);
195      break;
196
197   default:
198      break;
199   }
200}
201
202static void
203handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf)
204{
205   switch (u_reduce_video_profile(context->templat.profile)) {
206   case PIPE_VIDEO_FORMAT_MPEG12:
207      vlVaHandleSliceParameterBufferMPEG12(context, buf);
208      break;
209
210   case PIPE_VIDEO_FORMAT_VC1:
211      vlVaHandleSliceParameterBufferVC1(context, buf);
212      break;
213
214   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
215      vlVaHandleSliceParameterBufferH264(context, buf);
216      break;
217
218   case PIPE_VIDEO_FORMAT_MPEG4:
219      vlVaHandleSliceParameterBufferMPEG4(context, buf);
220      break;
221
222   case PIPE_VIDEO_FORMAT_HEVC:
223      vlVaHandleSliceParameterBufferHEVC(context, buf);
224      break;
225
226   case PIPE_VIDEO_FORMAT_JPEG:
227      vlVaHandleSliceParameterBufferMJPEG(context, buf);
228      break;
229
230   case PIPE_VIDEO_FORMAT_VP9:
231      vlVaHandleSliceParameterBufferVP9(context, buf);
232      break;
233
234   default:
235      break;
236   }
237}
238
239static unsigned int
240bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits)
241{
242   struct vl_vlc vlc = {0};
243   int i;
244
245   /* search the first 64 bytes for a startcode */
246   vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size);
247   for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) {
248      if (vl_vlc_peekbits(&vlc, bits) == code)
249         return 1;
250      vl_vlc_eatbits(&vlc, 8);
251      vl_vlc_fillbits(&vlc);
252   }
253
254   return 0;
255}
256
257static void
258handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
259{
260   enum pipe_video_format format;
261   unsigned num_buffers = 0;
262   void * const *buffers[3];
263   unsigned sizes[3];
264   static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 };
265   static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 };
266   static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d };
267   static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 };
268
269   format = u_reduce_video_profile(context->templat.profile);
270   switch (format) {
271   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
272      if (bufHasStartcode(buf, 0x000001, 24))
273         break;
274
275      buffers[num_buffers] = (void *const)&start_code_h264;
276      sizes[num_buffers++] = sizeof(start_code_h264);
277      break;
278   case PIPE_VIDEO_FORMAT_HEVC:
279      if (bufHasStartcode(buf, 0x000001, 24))
280         break;
281
282      buffers[num_buffers] = (void *const)&start_code_h265;
283      sizes[num_buffers++] = sizeof(start_code_h265);
284      break;
285   case PIPE_VIDEO_FORMAT_VC1:
286      if (bufHasStartcode(buf, 0x0000010d, 32) ||
287          bufHasStartcode(buf, 0x0000010c, 32) ||
288          bufHasStartcode(buf, 0x0000010b, 32))
289         break;
290
291      if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) {
292         buffers[num_buffers] = (void *const)&start_code_vc1;
293         sizes[num_buffers++] = sizeof(start_code_vc1);
294      }
295      break;
296   case PIPE_VIDEO_FORMAT_MPEG4:
297      if (bufHasStartcode(buf, 0x000001, 24))
298         break;
299
300      vlVaDecoderFixMPEG4Startcode(context);
301      buffers[num_buffers] = (void *)context->mpeg4.start_code;
302      sizes[num_buffers++] = context->mpeg4.start_code_size;
303      break;
304   case PIPE_VIDEO_FORMAT_JPEG:
305      vlVaGetJpegSliceHeader(context);
306      buffers[num_buffers] = (void *)context->mjpeg.slice_header;
307      sizes[num_buffers++] = context->mjpeg.slice_header_size;
308      break;
309   case PIPE_VIDEO_FORMAT_VP9:
310      vlVaDecoderVP9BitstreamHeader(context, buf);
311      break;
312   default:
313      break;
314   }
315
316   buffers[num_buffers] = buf->data;
317   sizes[num_buffers] = buf->size;
318   ++num_buffers;
319
320   if (format == PIPE_VIDEO_FORMAT_JPEG) {
321      buffers[num_buffers] = (void *const)&eoi_jpeg;
322      sizes[num_buffers++] = sizeof(eoi_jpeg);
323   }
324
325   if (context->needs_begin_frame) {
326      context->decoder->begin_frame(context->decoder, context->target,
327         &context->desc.base);
328      context->needs_begin_frame = false;
329   }
330   context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base,
331      num_buffers, (const void * const*)buffers, sizes);
332}
333
334static VAStatus
335handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc)
336{
337   VAStatus status = VA_STATUS_SUCCESS;
338
339   switch (u_reduce_video_profile(context->templat.profile)) {
340   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
341      status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc);
342      break;
343
344   case PIPE_VIDEO_FORMAT_HEVC:
345      status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc);
346      break;
347
348   default:
349      break;
350   }
351
352   return status;
353}
354
355static VAStatus
356handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc)
357{
358   VAStatus status = VA_STATUS_SUCCESS;
359
360   switch (u_reduce_video_profile(context->templat.profile)) {
361   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
362      status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc);
363      break;
364
365   case PIPE_VIDEO_FORMAT_HEVC:
366      status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc);
367      break;
368
369   default:
370      break;
371   }
372
373   return status;
374}
375
376static VAStatus
377handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
378{
379   VAStatus status = VA_STATUS_SUCCESS;
380
381   switch (u_reduce_video_profile(context->templat.profile)) {
382   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
383      status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf);
384      break;
385
386   case PIPE_VIDEO_FORMAT_HEVC:
387      status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf);
388      break;
389
390   default:
391      break;
392   }
393
394   return status;
395}
396
397static VAStatus
398handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
399{
400   VAStatus vaStatus = VA_STATUS_SUCCESS;
401   VAEncMiscParameterBuffer *misc;
402   misc = buf->data;
403
404   switch (misc->type) {
405   case VAEncMiscParameterTypeRateControl:
406      vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc);
407      break;
408
409   case VAEncMiscParameterTypeFrameRate:
410      vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc);
411      break;
412
413   default:
414      break;
415   }
416
417   return vaStatus;
418}
419
420static VAStatus
421handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
422{
423   VAStatus status = VA_STATUS_SUCCESS;
424
425   switch (u_reduce_video_profile(context->templat.profile)) {
426   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
427      status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf);
428      break;
429
430   case PIPE_VIDEO_FORMAT_HEVC:
431      status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf);
432      break;
433
434   default:
435      break;
436   }
437
438   return status;
439}
440
441static VAStatus
442handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
443{
444   VAStatus status = VA_STATUS_SUCCESS;
445
446   switch (u_reduce_video_profile(context->templat.profile)) {
447   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
448      status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf);
449      break;
450
451   case PIPE_VIDEO_FORMAT_HEVC:
452      status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf);
453      break;
454
455   default:
456      break;
457   }
458
459   return status;
460}
461
462VAStatus
463vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers)
464{
465   vlVaDriver *drv;
466   vlVaContext *context;
467   VAStatus vaStatus = VA_STATUS_SUCCESS;
468
469   unsigned i;
470
471   if (!ctx)
472      return VA_STATUS_ERROR_INVALID_CONTEXT;
473
474   drv = VL_VA_DRIVER(ctx);
475   if (!drv)
476      return VA_STATUS_ERROR_INVALID_CONTEXT;
477
478   mtx_lock(&drv->mutex);
479   context = handle_table_get(drv->htab, context_id);
480   if (!context) {
481      mtx_unlock(&drv->mutex);
482      return VA_STATUS_ERROR_INVALID_CONTEXT;
483   }
484
485   for (i = 0; i < num_buffers; ++i) {
486      vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]);
487      if (!buf) {
488         mtx_unlock(&drv->mutex);
489         return VA_STATUS_ERROR_INVALID_BUFFER;
490      }
491
492      switch (buf->type) {
493      case VAPictureParameterBufferType:
494         vaStatus = handlePictureParameterBuffer(drv, context, buf);
495         break;
496
497      case VAIQMatrixBufferType:
498         handleIQMatrixBuffer(context, buf);
499         break;
500
501      case VASliceParameterBufferType:
502         handleSliceParameterBuffer(context, buf);
503         break;
504
505      case VASliceDataBufferType:
506         handleVASliceDataBufferType(context, buf);
507         break;
508      case VAProcPipelineParameterBufferType:
509         vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf);
510         break;
511
512      case VAEncSequenceParameterBufferType:
513         vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf);
514         break;
515
516      case VAEncMiscParameterBufferType:
517         vaStatus = handleVAEncMiscParameterBufferType(context, buf);
518         break;
519
520      case VAEncPictureParameterBufferType:
521         vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf);
522         break;
523
524      case VAEncSliceParameterBufferType:
525         vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf);
526         break;
527
528      case VAHuffmanTableBufferType:
529         vlVaHandleHuffmanTableBufferType(context, buf);
530         break;
531
532      default:
533         break;
534      }
535   }
536   mtx_unlock(&drv->mutex);
537
538   return vaStatus;
539}
540
541VAStatus
542vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
543{
544   vlVaDriver *drv;
545   vlVaContext *context;
546   vlVaBuffer *coded_buf;
547   vlVaSurface *surf;
548   void *feedback;
549   struct pipe_screen *screen;
550   bool supported;
551   bool realloc = false;
552   enum pipe_format format;
553
554   if (!ctx)
555      return VA_STATUS_ERROR_INVALID_CONTEXT;
556
557   drv = VL_VA_DRIVER(ctx);
558   if (!drv)
559      return VA_STATUS_ERROR_INVALID_CONTEXT;
560
561   mtx_lock(&drv->mutex);
562   context = handle_table_get(drv->htab, context_id);
563   mtx_unlock(&drv->mutex);
564   if (!context)
565      return VA_STATUS_ERROR_INVALID_CONTEXT;
566
567   if (!context->decoder) {
568      if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN)
569         return VA_STATUS_ERROR_INVALID_CONTEXT;
570
571      /* VPP */
572      return VA_STATUS_SUCCESS;
573   }
574
575   mtx_lock(&drv->mutex);
576   surf = handle_table_get(drv->htab, context->target_id);
577   context->mpeg4.frame_num++;
578
579   screen = context->decoder->context->screen;
580   supported = screen->get_video_param(screen, context->decoder->profile,
581                                       context->decoder->entrypoint,
582                                       surf->buffer->interlaced ?
583                                       PIPE_VIDEO_CAP_SUPPORTS_INTERLACED :
584                                       PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
585
586   if (!supported) {
587      surf->templat.interlaced = screen->get_video_param(screen,
588                                       context->decoder->profile,
589                                       context->decoder->entrypoint,
590                                       PIPE_VIDEO_CAP_PREFERS_INTERLACED);
591      realloc = true;
592   }
593
594   format = screen->get_video_param(screen, context->decoder->profile,
595                                    PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
596                                    PIPE_VIDEO_CAP_PREFERED_FORMAT);
597
598   if (surf->buffer->buffer_format != format &&
599       surf->buffer->buffer_format == PIPE_FORMAT_NV12) {
600      /* check originally as NV12 only */
601      surf->templat.buffer_format = format;
602      realloc = true;
603   }
604
605   if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG &&
606       surf->buffer->buffer_format == PIPE_FORMAT_NV12) {
607      if (context->mjpeg.sampling_factor == 0x211111 ||
608          context->mjpeg.sampling_factor == 0x221212) {
609         surf->templat.buffer_format = PIPE_FORMAT_YUYV;
610         realloc = true;
611      } else if (context->mjpeg.sampling_factor != 0x221111) {
612         /* Not NV12 either */
613         mtx_unlock(&drv->mutex);
614         return VA_STATUS_ERROR_INVALID_SURFACE;
615      }
616   }
617
618   if (realloc) {
619      struct pipe_video_buffer *old_buf = surf->buffer;
620
621      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) {
622         mtx_unlock(&drv->mutex);
623         return VA_STATUS_ERROR_ALLOCATION_FAILED;
624      }
625
626      if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
627         if (old_buf->interlaced) {
628            struct u_rect src_rect, dst_rect;
629
630            dst_rect.x0 = src_rect.x0 = 0;
631            dst_rect.y0 = src_rect.y0 = 0;
632            dst_rect.x1 = src_rect.x1 = surf->templat.width;
633            dst_rect.y1 = src_rect.y1 = surf->templat.height;
634            vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
635                                         old_buf, surf->buffer,
636                                         &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE);
637         } else {
638            /* Can't convert from progressive to interlaced yet */
639            mtx_unlock(&drv->mutex);
640            return VA_STATUS_ERROR_INVALID_SURFACE;
641         }
642      }
643
644      old_buf->destroy(old_buf);
645      context->target = surf->buffer;
646   }
647
648   if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
649      coded_buf = context->coded_buf;
650      if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
651         getEncParamPresetH264(context);
652         context->desc.h264enc.frame_num_cnt++;
653      } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
654         getEncParamPresetH265(context);
655      context->decoder->begin_frame(context->decoder, context->target, &context->desc.base);
656      context->decoder->encode_bitstream(context->decoder, context->target,
657                                         coded_buf->derived_surface.resource, &feedback);
658      surf->feedback = feedback;
659      surf->coded_buf = coded_buf;
660   }
661
662   context->decoder->end_frame(context->decoder, context->target, &context->desc.base);
663   if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE &&
664      u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
665      int idr_period = context->desc.h264enc.gop_size / context->gop_coeff;
666      int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num;
667      surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt;
668      surf->force_flushed = false;
669      if (context->first_single_submitted) {
670         context->decoder->flush(context->decoder);
671         context->first_single_submitted = false;
672         surf->force_flushed = true;
673      }
674      if (p_remain_in_idr == 1) {
675         if ((context->desc.h264enc.frame_num_cnt % 2) != 0) {
676            context->decoder->flush(context->decoder);
677            context->first_single_submitted = true;
678         }
679         else
680            context->first_single_submitted = false;
681         surf->force_flushed = true;
682      }
683   } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE &&
684              u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
685      context->desc.h265enc.frame_num++;
686   mtx_unlock(&drv->mutex);
687   return VA_STATUS_SUCCESS;
688}
689