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