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