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