2 * Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "gstqsvallocator.h"
26 GST_DEBUG_CATEGORY_EXTERN (gst_qsv_allocator_debug);
27 #define GST_CAT_DEFAULT gst_qsv_allocator_debug
29 /* Both d3d11 and va use (GST_MAP_FLAG_LAST << 1) value
31 #define GST_MAP_QSV (GST_MAP_FLAG_LAST << 1)
37 GstQsvAllocator *allocator;
45 GstQsvMemoryType mem_type;
46 GstMapFlags map_flags;
49 GST_DEFINE_MINI_OBJECT_TYPE (GstQsvFrame, gst_qsv_frame);
52 _gst_qsv_frame_free (GstQsvFrame * frame)
54 g_mutex_clear (&frame->lock);
55 gst_clear_buffer (&frame->buffer);
56 gst_clear_object (&frame->allocator);
61 gst_qsv_frame_new (void)
65 self = g_new0 (GstQsvFrame, 1);
66 g_mutex_init (&self->lock);
68 gst_mini_object_init (GST_MINI_OBJECT_CAST (self), 0,
69 GST_TYPE_QSV_FRAME, nullptr, nullptr,
70 (GstMiniObjectFreeFunction) _gst_qsv_frame_free);
76 gst_qsv_frame_peek_buffer (GstQsvFrame * frame)
78 g_return_val_if_fail (GST_IS_QSV_FRAME (frame), nullptr);
84 gst_qsv_frame_set_buffer (GstQsvFrame * frame, GstBuffer * buffer)
86 g_return_val_if_fail (GST_IS_QSV_FRAME (frame), FALSE);
88 g_mutex_lock (&frame->lock);
89 if (frame->buffer == buffer) {
90 g_mutex_unlock (&frame->lock);
94 if (frame->map_count > 0) {
95 GST_ERROR ("frame is locked");
96 g_mutex_unlock (&frame->lock);
101 gst_clear_buffer (&frame->buffer);
102 frame->buffer = buffer;
103 g_mutex_unlock (&frame->lock);
108 struct _GstQsvAllocatorPrivate
110 GstAtomicQueue *queue;
112 mfxFrameAllocator allocator;
113 mfxFrameAllocResponse response;
114 guint16 extra_alloc_size;
115 gboolean dummy_alloc;
118 #define gst_qsv_allocator_parent_class parent_class
119 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstQsvAllocator,
120 gst_qsv_allocator, GST_TYPE_OBJECT);
122 static void gst_qsv_allocator_finalize (GObject * object);
123 static mfxStatus gst_qsv_allocator_alloc (mfxHDL pthis,
124 mfxFrameAllocRequest * request, mfxFrameAllocResponse * response);
125 static mfxStatus gst_qsv_allocator_lock (mfxHDL pthis, mfxMemId mid,
127 static mfxStatus gst_qsv_allocator_unlock (mfxHDL pthis, mfxMemId mid,
129 static mfxStatus gst_qsv_allocator_get_hdl (mfxHDL pthis, mfxMemId mid,
131 static mfxStatus gst_qsv_allocator_free (mfxHDL pthis,
132 mfxFrameAllocResponse * response);
133 static GstBuffer *gst_qsv_allocator_download_default (GstQsvAllocator * self,
134 const GstVideoInfo * info, gboolean force_copy, GstQsvFrame * frame,
135 GstBufferPool * pool);
138 gst_qsv_allocator_class_init (GstQsvAllocatorClass * klass)
140 GObjectClass *object_class = G_OBJECT_CLASS (klass);
142 object_class->finalize = gst_qsv_allocator_finalize;
144 klass->download = GST_DEBUG_FUNCPTR (gst_qsv_allocator_download_default);
148 gst_qsv_allocator_init (GstQsvAllocator * self)
150 GstQsvAllocatorPrivate *priv;
152 priv = self->priv = (GstQsvAllocatorPrivate *)
153 gst_qsv_allocator_get_instance_private (self);
155 priv->queue = gst_atomic_queue_new (16);
157 priv->allocator.pthis = self;
158 priv->allocator.Alloc = gst_qsv_allocator_alloc;
159 priv->allocator.Lock = gst_qsv_allocator_lock;
160 priv->allocator.Unlock = gst_qsv_allocator_unlock;
161 priv->allocator.GetHDL = gst_qsv_allocator_get_hdl;
162 priv->allocator.Free = gst_qsv_allocator_free;
166 gst_qsv_allocator_finalize (GObject * object)
168 GstQsvAllocator *self = GST_QSV_ALLOCATOR (object);
169 GstQsvAllocatorPrivate *priv = self->priv;
172 GST_DEBUG_OBJECT (object, "finalize");
174 while ((frame = (GstQsvFrame *) gst_atomic_queue_pop (priv->queue)))
175 gst_qsv_frame_unref (frame);
177 gst_atomic_queue_unref (priv->queue);
178 gst_qsv_allocator_free ((mfxHDL) self, &priv->response);
180 G_OBJECT_CLASS (parent_class)->finalize (object);
184 gst_qsv_allocator_alloc_default (GstQsvAllocator * self, gboolean dummy_alloc,
185 mfxFrameAllocRequest * request, mfxFrameAllocResponse * response)
187 GstQsvFrame **mids = nullptr;
189 GstVideoAlignment align;
190 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
193 GstStructure *config;
195 /* Something unexpected and went wrong */
196 if ((request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) == 0) {
197 GST_ERROR_OBJECT (self,
198 "MFX is requesting system memory, type 0x%x", request->Type);
199 return MFX_ERR_UNSUPPORTED;
202 switch (request->Info.FourCC) {
203 case MFX_FOURCC_NV12:
204 format = GST_VIDEO_FORMAT_NV12;
206 case MFX_FOURCC_P010:
207 format = GST_VIDEO_FORMAT_P010_10LE;
209 case MFX_FOURCC_AYUV:
210 format = GST_VIDEO_FORMAT_VUYA;
212 case MFX_FOURCC_Y410:
213 format = GST_VIDEO_FORMAT_Y410;
216 /* TODO: add more formats */
220 if (format == GST_VIDEO_FORMAT_UNKNOWN) {
221 GST_ERROR_OBJECT (self, "Unknown MFX format fourcc %" GST_FOURCC_FORMAT,
222 GST_FOURCC_ARGS (request->Info.FourCC));
224 return MFX_ERR_UNSUPPORTED;
227 mids = g_new0 (GstQsvFrame *, request->NumFrameSuggested);
228 response->NumFrameActual = request->NumFrameSuggested;
230 gst_video_info_set_format (&info,
231 format, request->Info.CropW, request->Info.CropH);
234 for (guint i = 0; i < request->NumFrameSuggested; i++) {
235 mids[i] = gst_qsv_allocator_acquire_frame (self,
236 GST_QSV_SYSTEM_MEMORY, &info, nullptr, nullptr);
239 response->mids = (mfxMemId *) mids;
244 caps = gst_video_info_to_caps (&info);
246 GST_ERROR_OBJECT (self, "Failed to convert video-info to caps");
247 return MFX_ERR_UNSUPPORTED;
250 gst_video_alignment_reset (&align);
251 align.padding_right = request->Info.Width - request->Info.CropW;
252 align.padding_bottom = request->Info.Height - request->Info.CropH;
254 pool = gst_video_buffer_pool_new ();
255 config = gst_buffer_pool_get_config (pool);
256 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
257 gst_buffer_pool_config_add_option (config,
258 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
259 gst_buffer_pool_config_set_video_alignment (config, &align);
260 gst_buffer_pool_config_set_params (config, caps, GST_VIDEO_INFO_SIZE (&info),
262 gst_caps_unref (caps);
263 gst_buffer_pool_set_config (pool, config);
264 gst_buffer_pool_set_active (pool, TRUE);
266 for (guint i = 0; i < request->NumFrameSuggested; i++) {
269 if (gst_buffer_pool_acquire_buffer (pool, &buffer, nullptr) != GST_FLOW_OK) {
270 GST_ERROR_OBJECT (self, "Failed to allocate texture buffer");
271 gst_buffer_pool_set_active (pool, FALSE);
272 gst_object_unref (pool);
276 mids[i] = gst_qsv_allocator_acquire_frame (self,
277 GST_QSV_SYSTEM_MEMORY, &info, buffer, nullptr);
280 gst_buffer_pool_set_active (pool, FALSE);
281 gst_object_unref (pool);
283 response->mids = (mfxMemId *) mids;
289 for (guint i = 0; i < response->NumFrameActual; i++)
290 gst_clear_qsv_frame (&mids[i]);
295 response->NumFrameActual = 0;
297 return MFX_ERR_MEMORY_ALLOC;
301 gst_qsv_allocator_copy_cached_response (GstQsvAllocator * self,
302 mfxFrameAllocResponse * dst, mfxFrameAllocResponse * src)
306 if (src->NumFrameActual == 0)
309 mids = g_new0 (GstQsvFrame *, src->NumFrameActual);
311 for (guint i = 0; i < src->NumFrameActual; i++) {
312 GstQsvFrame *frame = (GstQsvFrame *) src->mids[i];
314 mids[i] = gst_qsv_frame_ref (frame);
317 dst->NumFrameActual = src->NumFrameActual;
318 dst->mids = (mfxMemId *) mids;
324 gst_qsv_allocator_alloc (mfxHDL pthis,
325 mfxFrameAllocRequest * request, mfxFrameAllocResponse * response)
327 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
328 GstQsvAllocatorPrivate *priv = self->priv;
329 GstQsvAllocatorClass *klass;
331 mfxFrameAllocRequest req = *request;
332 gboolean dummy_alloc = priv->dummy_alloc;
334 GST_INFO_OBJECT (self, "Alloc, Request Type: 0x%x, %dx%d (%dx%d)",
335 req.Type, req.Info.Width, req.Info.Height,
336 req.Info.CropW, req.Info.CropH);
338 /* Apply extra_alloc_size only for GST internal use case */
339 if ((request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) != 0)
340 req.NumFrameSuggested += priv->extra_alloc_size;
342 if (req.Info.CropW == 0 || req.Info.CropH == 0) {
343 req.Info.CropW = req.Info.Width;
344 req.Info.CropH = req.Info.Height;
347 if (request->Info.FourCC == MFX_FOURCC_P8 ||
348 (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) == 0) {
352 GST_INFO_OBJECT (self, "Dummy alloc %d", dummy_alloc);
354 if ((request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) != 0) {
355 status = gst_qsv_allocator_alloc_default (self,
356 dummy_alloc, &req, response);
358 klass = GST_QSV_ALLOCATOR_GET_CLASS (self);
359 g_assert (klass->alloc);
361 status = klass->alloc (self, dummy_alloc, &req, response);
364 if (status != MFX_ERR_NONE)
367 /* Cache this respons so that this can be accessible from GST side */
369 gst_qsv_allocator_free ((mfxHDL) self, &priv->response);
370 gst_qsv_allocator_copy_cached_response (self, &priv->response, response);
377 gst_qsv_allocator_lock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
379 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
380 GstQsvFrame *frame = (GstQsvFrame *) mid;
383 GST_TRACE_OBJECT (self, "Lock mfxMemId %p", mid);
385 g_mutex_lock (&frame->lock);
386 if (!frame->buffer) {
387 GST_ERROR_OBJECT (self, "MemId %p doesn't hold buffer", mid);
388 g_mutex_unlock (&frame->lock);
389 return MFX_ERR_LOCK_MEMORY;
392 if (frame->map_count == 0) {
393 gst_video_frame_map (&frame->frame, &frame->info, frame->buffer,
398 stride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame->frame, 0);
400 /* FIXME: check and handle other formats */
401 switch (GST_VIDEO_INFO_FORMAT (&frame->info)) {
402 case GST_VIDEO_FORMAT_NV12:
403 case GST_VIDEO_FORMAT_P010_10LE:
404 ptr->Pitch = (mfxU16) stride;
405 ptr->Y = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
406 ptr->UV = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 1);
408 case GST_VIDEO_FORMAT_VUYA:
409 ptr->PitchHigh = (mfxU16) (stride / (1 << 16));
410 ptr->PitchLow = (mfxU16) (stride % (1 << 16));
411 ptr->V = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
416 case GST_VIDEO_FORMAT_Y410:
417 ptr->PitchHigh = (mfxU16) (stride / (1 << 16));
418 ptr->PitchLow = (mfxU16) (stride % (1 << 16));
419 ptr->Y410 = (mfxY410 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
425 g_mutex_unlock (&frame->lock);
431 gst_qsv_allocator_unlock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
433 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
434 GstQsvFrame *frame = (GstQsvFrame *) mid;
436 GST_TRACE_OBJECT (self, "Unlock mfxMemId %p", mid);
438 g_mutex_lock (&frame->lock);
440 if (frame->map_count > 0) {
443 if (frame->map_count == 0)
444 gst_video_frame_unmap (&frame->frame);
446 GST_WARNING_OBJECT (self, "Unlock request for non-locked memory");
449 g_mutex_unlock (&frame->lock);
455 gst_qsv_allocator_get_hdl (mfxHDL pthis, mfxMemId mid, mfxHDL * handle)
457 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
458 GstQsvFrame *frame = GST_QSV_FRAME_CAST (mid);
461 if (!GST_QSV_MEM_TYPE_IS_VIDEO (frame->mem_type)) {
462 GST_ERROR_OBJECT (self, "Unexpected call");
463 return MFX_ERR_UNSUPPORTED;
466 g_mutex_lock (&frame->lock);
467 if (!frame->buffer) {
468 GST_ERROR_OBJECT (self, "MemId %p doesn't hold buffer", mid);
469 g_mutex_unlock (&frame->lock);
471 return MFX_ERR_UNSUPPORTED;
474 g_assert ((frame->map_flags & GST_MAP_QSV) != 0);
475 if (!gst_buffer_map (frame->buffer, &map_info, frame->map_flags)) {
476 GST_ERROR_OBJECT (self, "Failed to map buffer");
477 g_mutex_unlock (&frame->lock);
479 return MFX_ERR_UNSUPPORTED;
482 GST_TRACE_OBJECT (self, "Get handle for mfxMemId %p", mid);
485 mfxHDLPair *pair = (mfxHDLPair *) handle;
486 pair->first = (mfxHDL) map_info.data;
488 /* GstD3D11 will fill user_data[0] with subresource index */
489 pair->second = (mfxHDL) map_info.user_data[0];
491 *handle = (mfxHDL) map_info.data;
494 /* XXX: Ideally we should unmap only when this surface is unlocked... */
495 gst_buffer_unmap (frame->buffer, &map_info);
496 g_mutex_unlock (&frame->lock);
502 gst_qsv_allocator_free (mfxHDL pthis, mfxFrameAllocResponse * response)
504 GstQsvFrame **frames = (GstQsvFrame **) response->mids;
506 for (guint i = 0; i < response->NumFrameActual; i++)
507 gst_clear_qsv_frame (&frames[i]);
509 g_clear_pointer (&response->mids, g_free);
510 response->NumFrameActual = 0;
516 gst_qsv_frame_release (GstQsvFrame * frame)
518 GstQsvAllocator *allocator = frame->allocator;
520 g_mutex_lock (&frame->lock);
521 if (frame->map_count > 0) {
522 GST_WARNING_OBJECT (allocator, "Releasing mapped frame %p", frame);
523 gst_video_frame_unmap (&frame->frame);
525 frame->map_count = 0;
526 gst_clear_buffer (&frame->buffer);
527 g_mutex_unlock (&frame->lock);
529 GST_MINI_OBJECT_CAST (frame)->dispose = nullptr;
530 frame->allocator = nullptr;
532 GST_TRACE_OBJECT (allocator, "Moving frame %p back to pool", frame);
534 gst_atomic_queue_push (allocator->priv->queue, frame);
535 gst_object_unref (allocator);
539 gst_qsv_frame_dispose (GstQsvFrame * frame)
541 g_assert (frame->allocator);
543 gst_qsv_frame_ref (frame);
544 gst_qsv_frame_release (frame);
550 gst_qsv_allocator_upload_default (GstQsvAllocator * allocator,
551 const GstVideoInfo * info, GstBuffer * buffer, GstBufferPool * pool)
554 GstFlowReturn flow_ret;
555 GstVideoFrame src_frame, dst_frame;
557 flow_ret = gst_buffer_pool_acquire_buffer (pool, &dst_buf, nullptr);
558 if (flow_ret != GST_FLOW_OK) {
559 GST_WARNING ("Failed to acquire buffer from pool, return %s",
560 gst_flow_get_name (flow_ret));
564 gst_video_frame_map (&src_frame, info, buffer, GST_MAP_READ);
565 gst_video_frame_map (&dst_frame, info, dst_buf, GST_MAP_WRITE);
567 if (GST_VIDEO_FRAME_WIDTH (&src_frame) == GST_VIDEO_FRAME_WIDTH (&dst_frame)
568 && GST_VIDEO_FRAME_HEIGHT (&src_frame) ==
569 GST_VIDEO_FRAME_HEIGHT (&dst_frame)) {
570 gst_video_frame_unmap (&src_frame);
571 gst_video_frame_unmap (&dst_frame);
573 gst_buffer_unref (dst_buf);
574 return gst_buffer_ref (buffer);
577 for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) {
578 guint src_width_in_bytes, src_height;
579 guint dst_width_in_bytes, dst_height;
580 guint width_in_bytes, height;
581 guint src_stride, dst_stride;
582 guint8 *src_data, *dst_data;
584 src_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&src_frame, i) *
585 GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
586 src_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
587 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&src_frame, i);
589 dst_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&dst_frame, i) *
590 GST_VIDEO_FRAME_COMP_PSTRIDE (&dst_frame, i);
591 dst_height = GST_VIDEO_FRAME_COMP_HEIGHT (&dst_frame, i);
592 dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&dst_frame, i);
594 width_in_bytes = MIN (src_width_in_bytes, dst_width_in_bytes);
595 height = MIN (src_height, dst_height);
597 src_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&src_frame, i);
598 dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&dst_frame, i);
600 for (guint j = 0; j < height; j++) {
601 memcpy (dst_data, src_data, width_in_bytes);
602 dst_data += dst_stride;
603 src_data += src_stride;
607 gst_video_frame_unmap (&dst_frame);
608 gst_video_frame_unmap (&src_frame);
614 * gst_qsv_allocator_acquire_frame:
615 * @allocator: a #GstQsvAllocator
616 * @mem_type: a memory type
617 * @info: a #GstVideoInfo
618 * @buffer: (nullable) (transfer full): a #GstBuffer
619 * @pool: (nullable): a #GstBufferPool
621 * Uploads @buffer to video memory if required, and wraps GstBuffer using
622 * #GstQsvFrame object so that QSV API can access native memory handle
623 * via mfxFrameAllocator interface.
625 * Returns: a #GstQsvFrame object
628 gst_qsv_allocator_acquire_frame (GstQsvAllocator * allocator,
629 GstQsvMemoryType mem_type, const GstVideoInfo * info, GstBuffer * buffer,
630 GstBufferPool * pool)
632 GstQsvAllocatorPrivate *priv;
634 guint32 map_flags = 0;
636 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
638 if (GST_QSV_MEM_TYPE_IS_SYSTEM (mem_type) &&
639 GST_QSV_MEM_TYPE_IS_VIDEO (mem_type)) {
640 GST_ERROR_OBJECT (allocator, "Invalid memory type");
644 if (GST_QSV_MEM_TYPE_IS_VIDEO (mem_type)) {
645 map_flags = GST_MAP_QSV;
647 if ((mem_type & GST_QSV_ENCODER_IN_MEMORY) != 0) {
648 map_flags |= GST_MAP_READ;
649 } else if ((mem_type & GST_QSV_DECODER_OUT_MEMORY) != 0) {
650 map_flags |= GST_MAP_WRITE;
652 GST_ERROR_OBJECT (allocator,
653 "Unknown read/write access for video memory");
656 } else if ((mem_type & GST_QSV_ENCODER_IN_MEMORY) != 0) {
657 map_flags = GST_MAP_READ;
659 map_flags = GST_MAP_READWRITE;
662 priv = allocator->priv;
663 frame = (GstQsvFrame *) gst_atomic_queue_pop (priv->queue);
666 frame = gst_qsv_frame_new ();
668 frame->mem_type = mem_type;
669 frame->map_flags = (GstMapFlags) map_flags;
673 frame->buffer = buffer;
675 GstBuffer *upload_buf;
677 frame->allocator = (GstQsvAllocator *) gst_object_ref (allocator);
678 GST_MINI_OBJECT_CAST (frame)->dispose =
679 (GstMiniObjectDisposeFunction) gst_qsv_frame_dispose;
681 if (GST_QSV_MEM_TYPE_IS_SYSTEM (mem_type)) {
682 upload_buf = gst_qsv_allocator_upload_default (allocator, info, buffer,
685 GstQsvAllocatorClass *klass;
687 klass = GST_QSV_ALLOCATOR_GET_CLASS (allocator);
688 g_assert (klass->upload);
690 upload_buf = klass->upload (allocator, info, buffer, pool);
693 gst_buffer_unref (buffer);
696 GST_WARNING_OBJECT (allocator, "Failed to upload buffer");
697 gst_qsv_frame_unref (frame);
702 frame->buffer = upload_buf;
709 gst_qsv_allocator_download_default (GstQsvAllocator * self,
710 const GstVideoInfo * info, gboolean force_copy, GstQsvFrame * frame,
711 GstBufferPool * pool)
713 GstBuffer *buffer = nullptr;
715 GstVideoFrame dst_frame;
720 GST_TRACE_OBJECT (self, "Download");
723 return gst_buffer_ref (frame->buffer);
725 ret = gst_buffer_pool_acquire_buffer (pool, &buffer, nullptr);
726 if (ret != GST_FLOW_OK) {
727 GST_WARNING_OBJECT (self, "Failed to acquire buffer");
731 /* Use gst_qsv_allocator_lock() instead of gst_video_frame_map() to avoid
732 * redundant map if it's already locked by driver, already locked by driver
733 * sounds unsafe situaltion though */
734 status = gst_qsv_allocator_lock ((mfxHDL) self, (mfxMemId) frame, &dummy);
735 if (status != MFX_ERR_NONE) {
736 gst_buffer_unref (buffer);
737 GST_ERROR_OBJECT (self, "Failed to lock frame");
741 if (!gst_video_frame_map (&dst_frame, &frame->info, buffer, GST_MAP_WRITE)) {
742 gst_qsv_allocator_unlock ((mfxHDL) self, (mfxMemId) frame, &dummy);
743 gst_buffer_unref (buffer);
744 GST_ERROR_OBJECT (self, "Failed to map output buffer");
748 copy_ret = gst_video_frame_copy (&dst_frame, &frame->frame);
749 gst_qsv_allocator_unlock ((mfxHDL) self, (mfxMemId) frame, &dummy);
750 gst_video_frame_unmap (&dst_frame);
753 GST_ERROR_OBJECT (self, "Failed to copy frame");
754 gst_buffer_unref (buffer);
762 gst_qsv_allocator_download_frame (GstQsvAllocator * allocator,
763 gboolean force_copy, GstQsvFrame * frame, GstBufferPool * pool)
765 GstQsvAllocatorClass *klass;
767 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
768 g_return_val_if_fail (GST_IS_QSV_FRAME (frame), nullptr);
769 g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), nullptr);
771 if (GST_QSV_MEM_TYPE_IS_SYSTEM (frame->mem_type)) {
772 return gst_qsv_allocator_download_default (allocator, &frame->info,
773 force_copy, frame, pool);
776 klass = GST_QSV_ALLOCATOR_GET_CLASS (allocator);
777 g_assert (klass->download);
779 return klass->download (allocator, &frame->info, force_copy, frame, pool);
783 gst_qsv_allocator_get_allocator_handle (GstQsvAllocator * allocator)
785 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
787 return &allocator->priv->allocator;
791 gst_qsv_allocator_get_cached_response (GstQsvAllocator * allocator,
792 mfxFrameAllocResponse * response)
794 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), FALSE);
796 return gst_qsv_allocator_copy_cached_response (allocator,
797 response, &allocator->priv->response);
801 gst_qsv_allocator_set_options (GstQsvAllocator * allocator,
802 guint16 extra_alloc_size, gboolean dummy_alloc)
804 g_return_if_fail (GST_IS_QSV_ALLOCATOR (allocator));
806 allocator->priv->extra_alloc_size = extra_alloc_size;
807 allocator->priv->dummy_alloc = dummy_alloc;