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 guint map_flags = (guint) frame->map_flags;
394 map_flags &= ~((guint) GST_MAP_QSV);
396 gst_video_frame_map (&frame->frame, &frame->info, frame->buffer,
397 (GstMapFlags) map_flags);
401 stride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame->frame, 0);
403 /* FIXME: check and handle other formats */
404 switch (GST_VIDEO_INFO_FORMAT (&frame->info)) {
405 case GST_VIDEO_FORMAT_NV12:
406 case GST_VIDEO_FORMAT_P010_10LE:
407 ptr->Pitch = (mfxU16) stride;
408 ptr->Y = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
409 ptr->UV = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 1);
411 case GST_VIDEO_FORMAT_VUYA:
412 ptr->PitchHigh = (mfxU16) (stride / (1 << 16));
413 ptr->PitchLow = (mfxU16) (stride % (1 << 16));
414 ptr->V = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
419 case GST_VIDEO_FORMAT_Y410:
420 ptr->PitchHigh = (mfxU16) (stride / (1 << 16));
421 ptr->PitchLow = (mfxU16) (stride % (1 << 16));
422 ptr->Y410 = (mfxY410 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
424 case GST_VIDEO_FORMAT_BGRA:
425 ptr->Pitch = (mfxU16) stride;
426 ptr->B = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
431 case GST_VIDEO_FORMAT_RGBA:
432 ptr->Pitch = (mfxU16) stride;
433 ptr->R = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0);
442 g_mutex_unlock (&frame->lock);
448 gst_qsv_allocator_unlock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr)
450 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
451 GstQsvFrame *frame = (GstQsvFrame *) mid;
453 GST_TRACE_OBJECT (self, "Unlock mfxMemId %p", mid);
455 g_mutex_lock (&frame->lock);
457 if (frame->map_count > 0) {
460 if (frame->map_count == 0)
461 gst_video_frame_unmap (&frame->frame);
463 GST_WARNING_OBJECT (self, "Unlock request for non-locked memory");
466 g_mutex_unlock (&frame->lock);
468 /* SDK will not re-lock unless we clear data pointer here. It happens
469 * on Linux with BGRA JPEG encoding */
479 gst_qsv_allocator_get_hdl (mfxHDL pthis, mfxMemId mid, mfxHDL * handle)
481 GstQsvAllocator *self = GST_QSV_ALLOCATOR (pthis);
482 GstQsvFrame *frame = GST_QSV_FRAME_CAST (mid);
485 if (!GST_QSV_MEM_TYPE_IS_VIDEO (frame->mem_type)) {
486 GST_ERROR_OBJECT (self, "Unexpected call");
487 return MFX_ERR_UNSUPPORTED;
490 g_mutex_lock (&frame->lock);
491 if (!frame->buffer) {
492 GST_ERROR_OBJECT (self, "MemId %p doesn't hold buffer", mid);
493 g_mutex_unlock (&frame->lock);
495 return MFX_ERR_UNSUPPORTED;
498 g_assert ((frame->map_flags & GST_MAP_QSV) != 0);
499 if (!gst_buffer_map (frame->buffer, &map_info, frame->map_flags)) {
500 GST_ERROR_OBJECT (self, "Failed to map buffer");
501 g_mutex_unlock (&frame->lock);
503 return MFX_ERR_UNSUPPORTED;
506 GST_TRACE_OBJECT (self, "Get handle for mfxMemId %p", mid);
509 mfxHDLPair *pair = (mfxHDLPair *) handle;
510 pair->first = (mfxHDL) map_info.data;
512 /* GstD3D11 will fill user_data[0] with subresource index */
513 pair->second = (mfxHDL) map_info.user_data[0];
515 *handle = (mfxHDL) map_info.data;
518 /* XXX: Ideally we should unmap only when this surface is unlocked... */
519 gst_buffer_unmap (frame->buffer, &map_info);
520 g_mutex_unlock (&frame->lock);
526 gst_qsv_allocator_free (mfxHDL pthis, mfxFrameAllocResponse * response)
528 GstQsvFrame **frames = (GstQsvFrame **) response->mids;
530 for (guint i = 0; i < response->NumFrameActual; i++)
531 gst_clear_qsv_frame (&frames[i]);
533 g_clear_pointer (&response->mids, g_free);
534 response->NumFrameActual = 0;
540 gst_qsv_frame_release (GstQsvFrame * frame)
542 GstQsvAllocator *allocator = frame->allocator;
544 g_mutex_lock (&frame->lock);
545 if (frame->map_count > 0) {
546 GST_WARNING_OBJECT (allocator, "Releasing mapped frame %p", frame);
547 gst_video_frame_unmap (&frame->frame);
549 frame->map_count = 0;
550 gst_clear_buffer (&frame->buffer);
551 g_mutex_unlock (&frame->lock);
553 GST_MINI_OBJECT_CAST (frame)->dispose = nullptr;
554 frame->allocator = nullptr;
556 GST_TRACE_OBJECT (allocator, "Moving frame %p back to pool", frame);
558 gst_atomic_queue_push (allocator->priv->queue, frame);
559 gst_object_unref (allocator);
563 gst_qsv_frame_dispose (GstQsvFrame * frame)
565 g_assert (frame->allocator);
567 gst_qsv_frame_ref (frame);
568 gst_qsv_frame_release (frame);
574 gst_qsv_allocator_upload_default (GstQsvAllocator * allocator,
575 const GstVideoInfo * info, GstBuffer * buffer, GstBufferPool * pool)
578 GstFlowReturn flow_ret;
579 GstVideoFrame src_frame, dst_frame;
581 flow_ret = gst_buffer_pool_acquire_buffer (pool, &dst_buf, nullptr);
582 if (flow_ret != GST_FLOW_OK) {
583 GST_WARNING ("Failed to acquire buffer from pool, return %s",
584 gst_flow_get_name (flow_ret));
588 gst_video_frame_map (&src_frame, info, buffer, GST_MAP_READ);
589 gst_video_frame_map (&dst_frame, info, dst_buf, GST_MAP_WRITE);
591 if (GST_VIDEO_FRAME_WIDTH (&src_frame) == GST_VIDEO_FRAME_WIDTH (&dst_frame)
592 && GST_VIDEO_FRAME_HEIGHT (&src_frame) ==
593 GST_VIDEO_FRAME_HEIGHT (&dst_frame)) {
594 gst_video_frame_unmap (&src_frame);
595 gst_video_frame_unmap (&dst_frame);
597 gst_buffer_unref (dst_buf);
598 return gst_buffer_ref (buffer);
601 for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) {
602 guint src_width_in_bytes, src_height;
603 guint dst_width_in_bytes, dst_height;
604 guint width_in_bytes, height;
605 guint src_stride, dst_stride;
606 guint8 *src_data, *dst_data;
608 src_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&src_frame, i) *
609 GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
610 src_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
611 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&src_frame, i);
613 dst_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&dst_frame, i) *
614 GST_VIDEO_FRAME_COMP_PSTRIDE (&dst_frame, i);
615 dst_height = GST_VIDEO_FRAME_COMP_HEIGHT (&dst_frame, i);
616 dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&dst_frame, i);
618 width_in_bytes = MIN (src_width_in_bytes, dst_width_in_bytes);
619 height = MIN (src_height, dst_height);
621 src_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&src_frame, i);
622 dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&dst_frame, i);
624 for (guint j = 0; j < height; j++) {
625 memcpy (dst_data, src_data, width_in_bytes);
626 dst_data += dst_stride;
627 src_data += src_stride;
631 gst_video_frame_unmap (&dst_frame);
632 gst_video_frame_unmap (&src_frame);
638 * gst_qsv_allocator_acquire_frame:
639 * @allocator: a #GstQsvAllocator
640 * @mem_type: a memory type
641 * @info: a #GstVideoInfo
642 * @buffer: (nullable) (transfer full): a #GstBuffer
643 * @pool: (nullable): a #GstBufferPool
645 * Uploads @buffer to video memory if required, and wraps GstBuffer using
646 * #GstQsvFrame object so that QSV API can access native memory handle
647 * via mfxFrameAllocator interface.
649 * Returns: a #GstQsvFrame object
652 gst_qsv_allocator_acquire_frame (GstQsvAllocator * allocator,
653 GstQsvMemoryType mem_type, const GstVideoInfo * info, GstBuffer * buffer,
654 GstBufferPool * pool)
656 GstQsvAllocatorPrivate *priv;
658 guint32 map_flags = 0;
660 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
662 if (GST_QSV_MEM_TYPE_IS_SYSTEM (mem_type) &&
663 GST_QSV_MEM_TYPE_IS_VIDEO (mem_type)) {
664 GST_ERROR_OBJECT (allocator, "Invalid memory type");
668 if (GST_QSV_MEM_TYPE_IS_VIDEO (mem_type)) {
669 map_flags = GST_MAP_QSV;
671 if ((mem_type & GST_QSV_ENCODER_IN_MEMORY) != 0) {
672 map_flags |= GST_MAP_READ;
673 } else if ((mem_type & GST_QSV_DECODER_OUT_MEMORY) != 0) {
674 map_flags |= GST_MAP_WRITE;
676 GST_ERROR_OBJECT (allocator,
677 "Unknown read/write access for video memory");
680 } else if ((mem_type & GST_QSV_ENCODER_IN_MEMORY) != 0) {
681 map_flags = GST_MAP_READ;
683 map_flags = GST_MAP_READWRITE;
686 priv = allocator->priv;
687 frame = (GstQsvFrame *) gst_atomic_queue_pop (priv->queue);
690 frame = gst_qsv_frame_new ();
692 frame->mem_type = mem_type;
693 frame->map_flags = (GstMapFlags) map_flags;
697 frame->buffer = buffer;
699 GstBuffer *upload_buf;
701 frame->allocator = (GstQsvAllocator *) gst_object_ref (allocator);
702 GST_MINI_OBJECT_CAST (frame)->dispose =
703 (GstMiniObjectDisposeFunction) gst_qsv_frame_dispose;
705 if (GST_QSV_MEM_TYPE_IS_SYSTEM (mem_type)) {
706 upload_buf = gst_qsv_allocator_upload_default (allocator, info, buffer,
709 GstQsvAllocatorClass *klass;
711 klass = GST_QSV_ALLOCATOR_GET_CLASS (allocator);
712 g_assert (klass->upload);
714 upload_buf = klass->upload (allocator, info, buffer, pool);
717 gst_buffer_unref (buffer);
720 GST_WARNING_OBJECT (allocator, "Failed to upload buffer");
721 gst_qsv_frame_unref (frame);
726 frame->buffer = upload_buf;
733 gst_qsv_allocator_download_default (GstQsvAllocator * self,
734 const GstVideoInfo * info, gboolean force_copy, GstQsvFrame * frame,
735 GstBufferPool * pool)
737 GstBuffer *buffer = nullptr;
739 GstVideoFrame dst_frame;
744 GST_TRACE_OBJECT (self, "Download");
747 return gst_buffer_ref (frame->buffer);
749 ret = gst_buffer_pool_acquire_buffer (pool, &buffer, nullptr);
750 if (ret != GST_FLOW_OK) {
751 GST_WARNING_OBJECT (self, "Failed to acquire buffer");
755 /* Use gst_qsv_allocator_lock() instead of gst_video_frame_map() to avoid
756 * redundant map if it's already locked by driver, already locked by driver
757 * sounds unsafe situaltion though */
758 status = gst_qsv_allocator_lock ((mfxHDL) self, (mfxMemId) frame, &dummy);
759 if (status != MFX_ERR_NONE) {
760 gst_buffer_unref (buffer);
761 GST_ERROR_OBJECT (self, "Failed to lock frame");
765 if (!gst_video_frame_map (&dst_frame, &frame->info, buffer, GST_MAP_WRITE)) {
766 gst_qsv_allocator_unlock ((mfxHDL) self, (mfxMemId) frame, &dummy);
767 gst_buffer_unref (buffer);
768 GST_ERROR_OBJECT (self, "Failed to map output buffer");
772 copy_ret = gst_video_frame_copy (&dst_frame, &frame->frame);
773 gst_qsv_allocator_unlock ((mfxHDL) self, (mfxMemId) frame, &dummy);
774 gst_video_frame_unmap (&dst_frame);
777 GST_ERROR_OBJECT (self, "Failed to copy frame");
778 gst_buffer_unref (buffer);
786 gst_qsv_allocator_download_frame (GstQsvAllocator * allocator,
787 gboolean force_copy, GstQsvFrame * frame, GstBufferPool * pool)
789 GstQsvAllocatorClass *klass;
791 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
792 g_return_val_if_fail (GST_IS_QSV_FRAME (frame), nullptr);
793 g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), nullptr);
795 if (GST_QSV_MEM_TYPE_IS_SYSTEM (frame->mem_type)) {
796 return gst_qsv_allocator_download_default (allocator, &frame->info,
797 force_copy, frame, pool);
800 klass = GST_QSV_ALLOCATOR_GET_CLASS (allocator);
801 g_assert (klass->download);
803 return klass->download (allocator, &frame->info, force_copy, frame, pool);
807 gst_qsv_allocator_get_allocator_handle (GstQsvAllocator * allocator)
809 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), nullptr);
811 return &allocator->priv->allocator;
815 gst_qsv_allocator_get_cached_response (GstQsvAllocator * allocator,
816 mfxFrameAllocResponse * response)
818 g_return_val_if_fail (GST_IS_QSV_ALLOCATOR (allocator), FALSE);
820 return gst_qsv_allocator_copy_cached_response (allocator,
821 response, &allocator->priv->response);
825 gst_qsv_allocator_set_options (GstQsvAllocator * allocator,
826 guint16 extra_alloc_size, gboolean dummy_alloc)
828 g_return_if_fail (GST_IS_QSV_ALLOCATOR (allocator));
830 allocator->priv->extra_alloc_size = extra_alloc_size;
831 allocator->priv->dummy_alloc = dummy_alloc;