1 //==============================================================================
2 // Copyright Intel Corporation
3 //
4 // SPDX-License-Identifier: MIT
5 //==============================================================================
6 
7 ///
8 /// Utility library header file for sample code
9 ///
10 /// @file
11 
12 #ifndef EXAMPLES_UTIL_H_
13 #define EXAMPLES_UTIL_H_
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #ifdef USE_MEDIASDK1
20     #include "mfxvideo.h"
21 enum {
22     MFX_FOURCC_I420 = MFX_FOURCC_IYUV /*!< Alias for the IYUV color format. */
23 };
24 #else
25     #include "vpl/mfxjpeg.h"
26     #include "vpl/mfxvideo.h"
27 #endif
28 
29 #if (MFX_VERSION >= 2000)
30     #include "vpl/mfxdispatcher.h"
31 #endif
32 
33 #ifdef __unix__
34     #include <fcntl.h>
35 #endif
36 
37 #ifdef LIBVA_SUPPORT
38     #include "va/va.h"
39     #include "va/va_drm.h"
40 #endif
41 
42 #define WAIT_5_MILLISECONDS   5
43 #define WAIT_100_MILLISECONDS 100
44 #define MAX_PATH              260
45 #define MAX_WIDTH             3840
46 #define MAX_HEIGHT            2160
47 #define IS_ARG_EQ(a, b)       (!strcmp((a), (b)))
48 
49 #define VERIFY(x, y)       \
50     if (!(x)) {            \
51         printf("%s\n", y); \
52         goto end;          \
53     }
54 
55 #define ALIGN16(value)           (((value + 15) >> 4) << 4)
56 #define ALIGN32(X)               (((mfxU32)((X) + 31)) & (~(mfxU32)31))
57 #define VPLVERSION(major, minor) (major << 16 | minor)
58 
59 #if defined(_WIN32) || defined(_WIN64)
60     #include <windows.h>
61     #define sleep(msec) Sleep(msec)
62 #else
63     #include <unistd.h>
64     #define sleep(msec) usleep(1000 * msec)
65 #endif
66 
67 enum ExampleParams { PARAM_IMPL = 0, PARAM_INFILE, PARAM_INRES, PARAM_COUNT };
68 enum ParamGroup {
69     PARAMS_CREATESESSION = 0,
70     PARAMS_DECODE,
71     PARAMS_ENCODE,
72     PARAMS_VPP,
73     PARAMS_TRANSCODE
74 };
75 
76 typedef struct _Params {
77     mfxIMPL impl;
78 #if (MFX_VERSION >= 2000)
79     mfxVariant implValue;
80 #endif
81 
82     char *infileName;
83     char *inmodelName;
84 
85     mfxU16 srcWidth;
86     mfxU16 srcHeight;
87 } Params;
88 
ValidateFileName(char * in)89 char *ValidateFileName(char *in) {
90     if (in) {
91         if (strnlen(in, MAX_PATH) > MAX_PATH)
92             return NULL;
93     }
94 
95     return in;
96 }
97 
ValidateSize(char * in,mfxU16 * vsize,mfxU32 vmax)98 bool ValidateSize(char *in, mfxU16 *vsize, mfxU32 vmax) {
99     if (in) {
100         *vsize = static_cast<mfxU16>(strtol(in, NULL, 10));
101         if (*vsize <= vmax)
102             return true;
103     }
104 
105     *vsize = 0;
106     return false;
107 }
108 
ParseArgsAndValidate(int argc,char * argv[],Params * params,ParamGroup group)109 bool ParseArgsAndValidate(int argc, char *argv[], Params *params, ParamGroup group) {
110     int idx;
111     char *s;
112 
113     // init all params to 0
114     *params      = {};
115     params->impl = MFX_IMPL_SOFTWARE;
116 #if (MFX_VERSION >= 2000)
117     params->implValue.Type     = MFX_VARIANT_TYPE_U32;
118     params->implValue.Data.U32 = MFX_IMPL_TYPE_SOFTWARE;
119 #endif
120 
121     for (idx = 1; idx < argc;) {
122         // all switches must start with '-'
123         if (argv[idx][0] != '-') {
124             printf("ERROR - invalid argument: %s\n", argv[idx]);
125             return false;
126         }
127 
128         // switch string, starting after the '-'
129         s = &argv[idx][1];
130         idx++;
131 
132         // search for match
133         if (IS_ARG_EQ(s, "i")) {
134             params->infileName = ValidateFileName(argv[idx++]);
135             if (!params->infileName) {
136                 return false;
137             }
138         }
139         else if (IS_ARG_EQ(s, "m")) {
140             params->inmodelName = ValidateFileName(argv[idx++]);
141             if (!params->inmodelName) {
142                 return false;
143             }
144         }
145         else if (IS_ARG_EQ(s, "w")) {
146             if (!ValidateSize(argv[idx++], &params->srcWidth, MAX_WIDTH))
147                 return false;
148         }
149         else if (IS_ARG_EQ(s, "h")) {
150             if (!ValidateSize(argv[idx++], &params->srcHeight, MAX_HEIGHT))
151                 return false;
152         }
153         else if (IS_ARG_EQ(s, "hw")) {
154             params->impl = MFX_IMPL_HARDWARE;
155 #if (MFX_VERSION >= 2000)
156             params->implValue.Data.U32 = MFX_IMPL_TYPE_HARDWARE;
157 #endif
158         }
159         else if (IS_ARG_EQ(s, "sw")) {
160             params->impl = MFX_IMPL_SOFTWARE;
161 #if (MFX_VERSION >= 2000)
162             params->implValue.Data.U32 = MFX_IMPL_TYPE_SOFTWARE;
163 #endif
164         }
165     }
166 
167     // input file required by all except createsession
168     if ((group != PARAMS_CREATESESSION) && (!params->infileName)) {
169         printf("ERROR - input file name (-i) is required\n");
170         return false;
171     }
172 
173     // VPP and encode samples require an input resolution
174     if ((PARAMS_VPP == group) || (PARAMS_ENCODE == group)) {
175         if ((!params->srcWidth) || (!params->srcHeight)) {
176             printf("ERROR - source width/height required\n");
177             return false;
178         }
179     }
180 
181     return true;
182 }
183 
InitAcceleratorHandle(mfxSession session,int * fd)184 void *InitAcceleratorHandle(mfxSession session, int *fd) {
185     mfxIMPL impl;
186     mfxStatus sts = MFXQueryIMPL(session, &impl);
187     if (sts != MFX_ERR_NONE)
188         return NULL;
189 
190 #ifdef LIBVA_SUPPORT
191     if ((impl & MFX_IMPL_VIA_VAAPI) == MFX_IMPL_VIA_VAAPI) {
192         if (!fd)
193             return NULL;
194         VADisplay va_dpy = NULL;
195         // initialize VAAPI context and set session handle (req in Linux)
196         *fd = open("/dev/dri/renderD128", O_RDWR);
197         if (*fd >= 0) {
198             va_dpy = vaGetDisplayDRM(*fd);
199             if (va_dpy) {
200                 int major_version = 0, minor_version = 0;
201                 if (VA_STATUS_SUCCESS == vaInitialize(va_dpy, &major_version, &minor_version)) {
202                     MFXVideoCORE_SetHandle(session,
203                                            static_cast<mfxHandleType>(MFX_HANDLE_VA_DISPLAY),
204                                            va_dpy);
205                 }
206             }
207         }
208         return va_dpy;
209     }
210 #endif
211 
212     return NULL;
213 }
214 
FreeAcceleratorHandle(void * accelHandle,int fd)215 void FreeAcceleratorHandle(void *accelHandle, int fd) {
216 #ifdef LIBVA_SUPPORT
217     if (accelHandle) {
218         vaTerminate((VADisplay)accelHandle);
219     }
220     if (fd) {
221         close(fd);
222     }
223 #endif
224 }
225 
226 //Shows implementation info for Media SDK or oneVPL
ShowImplInfo(mfxSession session)227 mfxVersion ShowImplInfo(mfxSession session) {
228     mfxIMPL impl;
229     mfxVersion version = { 0, 1 };
230 
231     mfxStatus sts = MFXQueryIMPL(session, &impl);
232     if (sts != MFX_ERR_NONE)
233         return version;
234 
235     sts = MFXQueryVersion(session, &version);
236     if (sts != MFX_ERR_NONE)
237         return version;
238 
239     printf("Session loaded: ApiVersion = %d.%d \timpl= ", version.Major, version.Minor);
240 
241     switch (impl) {
242         case MFX_IMPL_SOFTWARE:
243             puts("Software");
244             break;
245         case MFX_IMPL_HARDWARE | MFX_IMPL_VIA_VAAPI:
246             puts("Hardware:VAAPI");
247             break;
248         case MFX_IMPL_HARDWARE | MFX_IMPL_VIA_D3D11:
249             puts("Hardware:D3D11");
250             break;
251         case MFX_IMPL_HARDWARE | MFX_IMPL_VIA_D3D9:
252             puts("Hardware:D3D9");
253             break;
254         default:
255             puts("Unknown");
256             break;
257     }
258 
259     return version;
260 }
261 
262 // Shows implementation info with oneVPL
ShowImplementationInfo(mfxLoader loader,mfxU32 implnum)263 void ShowImplementationInfo(mfxLoader loader, mfxU32 implnum) {
264     mfxImplDescription *idesc = nullptr;
265     mfxStatus sts;
266     //Loads info about implementation at specified list location
267     sts = MFXEnumImplementations(loader, implnum, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *)&idesc);
268     if (!idesc || (sts != MFX_ERR_NONE))
269         return;
270 
271     printf("Implementation details:\n");
272     printf("  ApiVersion:           %hu.%hu  \n", idesc->ApiVersion.Major, idesc->ApiVersion.Minor);
273     printf("  Implementation type:  %s\n", (idesc->Impl == MFX_IMPL_TYPE_SOFTWARE) ? "SW" : "HW");
274     printf("  AccelerationMode via: ");
275     switch (idesc->AccelerationMode) {
276         case MFX_ACCEL_MODE_NA:
277             printf("NA \n");
278             break;
279         case MFX_ACCEL_MODE_VIA_D3D9:
280             printf("D3D9\n");
281             break;
282         case MFX_ACCEL_MODE_VIA_D3D11:
283             printf("D3D11\n");
284             break;
285         case MFX_ACCEL_MODE_VIA_VAAPI:
286             printf("VAAPI\n");
287             break;
288         case MFX_ACCEL_MODE_VIA_VAAPI_DRM_MODESET:
289             printf("VAAPI_DRM_MODESET\n");
290             break;
291         case MFX_ACCEL_MODE_VIA_VAAPI_GLX:
292             printf("VAAPI_GLX\n");
293             break;
294         case MFX_ACCEL_MODE_VIA_VAAPI_X11:
295             printf("VAAPI_X11\n");
296             break;
297         case MFX_ACCEL_MODE_VIA_VAAPI_WAYLAND:
298             printf("VAAPI_WAYLAND\n");
299             break;
300         case MFX_ACCEL_MODE_VIA_HDDLUNITE:
301             printf("HDDLUNITE\n");
302             break;
303         default:
304             printf("unknown\n");
305             break;
306     }
307     MFXDispReleaseImplDescription(loader, idesc);
308 
309 #if (MFX_VERSION >= 2004)
310     //Show implementation path, added in 2.4 API
311     mfxHDL implPath = nullptr;
312     sts             = MFXEnumImplementations(loader, implnum, MFX_IMPLCAPS_IMPLPATH, &implPath);
313     if (!implPath || (sts != MFX_ERR_NONE))
314         return;
315 
316     printf("  Path: %s\n\n", reinterpret_cast<mfxChar *>(implPath));
317     MFXDispReleaseImplDescription(loader, implPath);
318 #endif
319 }
320 
PrepareFrameInfo(mfxFrameInfo * fi,mfxU32 format,mfxU16 w,mfxU16 h)321 void PrepareFrameInfo(mfxFrameInfo *fi, mfxU32 format, mfxU16 w, mfxU16 h) {
322     // Video processing input data format
323     fi->FourCC        = format;
324     fi->ChromaFormat  = MFX_CHROMAFORMAT_YUV420;
325     fi->CropX         = 0;
326     fi->CropY         = 0;
327     fi->CropW         = w;
328     fi->CropH         = h;
329     fi->PicStruct     = MFX_PICSTRUCT_PROGRESSIVE;
330     fi->FrameRateExtN = 30;
331     fi->FrameRateExtD = 1;
332     // width must be a multiple of 16
333     // height must be a multiple of 16 in case of frame picture and a multiple of 32 in case of field picture
334     fi->Width = ALIGN16(fi->CropW);
335     fi->Height =
336         (MFX_PICSTRUCT_PROGRESSIVE == fi->PicStruct) ? ALIGN16(fi->CropH) : ALIGN32(fi->CropH);
337 }
338 
GetSurfaceSize(mfxU32 FourCC,mfxU32 width,mfxU32 height)339 mfxU32 GetSurfaceSize(mfxU32 FourCC, mfxU32 width, mfxU32 height) {
340     mfxU32 nbytes = 0;
341 
342     switch (FourCC) {
343         case MFX_FOURCC_I420:
344         case MFX_FOURCC_NV12:
345             nbytes = width * height + (width >> 1) * (height >> 1) + (width >> 1) * (height >> 1);
346             break;
347         case MFX_FOURCC_I010:
348         case MFX_FOURCC_P010:
349             nbytes = width * height + (width >> 1) * (height >> 1) + (width >> 1) * (height >> 1);
350             nbytes *= 2;
351             break;
352         case MFX_FOURCC_RGB4:
353             nbytes = width * height * 4;
354             break;
355         default:
356             break;
357     }
358 
359     return nbytes;
360 }
361 
GetFreeSurfaceIndex(mfxFrameSurface1 * SurfacesPool,mfxU16 nPoolSize)362 int GetFreeSurfaceIndex(mfxFrameSurface1 *SurfacesPool, mfxU16 nPoolSize) {
363     for (mfxU16 i = 0; i < nPoolSize; i++) {
364         if (0 == SurfacesPool[i].Data.Locked)
365             return i;
366     }
367     return MFX_ERR_NOT_FOUND;
368 }
369 
AllocateExternalSystemMemorySurfacePool(mfxU8 ** buf,mfxFrameSurface1 * surfpool,mfxFrameInfo frame_info,mfxU16 surfnum)370 mfxStatus AllocateExternalSystemMemorySurfacePool(mfxU8 **buf,
371                                                   mfxFrameSurface1 *surfpool,
372                                                   mfxFrameInfo frame_info,
373                                                   mfxU16 surfnum) {
374     // initialize surface pool (I420, RGB4 format)
375     mfxU32 surfaceSize = GetSurfaceSize(frame_info.FourCC, frame_info.Width, frame_info.Height);
376     if (!surfaceSize)
377         return MFX_ERR_MEMORY_ALLOC;
378 
379     size_t framePoolBufSize = static_cast<size_t>(surfaceSize) * surfnum;
380     *buf                    = reinterpret_cast<mfxU8 *>(calloc(framePoolBufSize, 1));
381 
382     mfxU16 surfW;
383     mfxU16 surfH = frame_info.Height;
384 
385     if (frame_info.FourCC == MFX_FOURCC_RGB4) {
386         surfW = frame_info.Width * 4;
387 
388         for (mfxU32 i = 0; i < surfnum; i++) {
389             surfpool[i]            = { 0 };
390             surfpool[i].Info       = frame_info;
391             size_t buf_offset      = static_cast<size_t>(i) * surfaceSize;
392             surfpool[i].Data.B     = *buf + buf_offset;
393             surfpool[i].Data.G     = surfpool[i].Data.B + 1;
394             surfpool[i].Data.R     = surfpool[i].Data.B + 2;
395             surfpool[i].Data.A     = surfpool[i].Data.B + 3;
396             surfpool[i].Data.Pitch = surfW;
397         }
398     }
399     else {
400         surfW = (frame_info.FourCC == MFX_FOURCC_P010) ? frame_info.Width * 2 : frame_info.Width;
401 
402         for (mfxU32 i = 0; i < surfnum; i++) {
403             surfpool[i]            = { 0 };
404             surfpool[i].Info       = frame_info;
405             size_t buf_offset      = static_cast<size_t>(i) * surfaceSize;
406             surfpool[i].Data.Y     = *buf + buf_offset;
407             surfpool[i].Data.U     = *buf + buf_offset + (surfW * surfH);
408             surfpool[i].Data.V     = surfpool[i].Data.U + ((surfW / 2) * (surfH / 2));
409             surfpool[i].Data.Pitch = surfW;
410         }
411     }
412 
413     return MFX_ERR_NONE;
414 }
415 
FreeExternalSystemMemorySurfacePool(mfxU8 * dec_buf,mfxFrameSurface1 * surfpool)416 void FreeExternalSystemMemorySurfacePool(mfxU8 *dec_buf, mfxFrameSurface1 *surfpool) {
417     if (dec_buf)
418         free(dec_buf);
419 
420     if (surfpool)
421         free(surfpool);
422 }
423 
424 // Read encoded stream from file
ReadEncodedStream(mfxBitstream & bs,FILE * f)425 mfxStatus ReadEncodedStream(mfxBitstream &bs, FILE *f) {
426     mfxU8 *p0 = bs.Data;
427     mfxU8 *p1 = bs.Data + bs.DataOffset;
428     if (bs.DataOffset > bs.MaxLength - 1) {
429         return MFX_ERR_NOT_ENOUGH_BUFFER;
430     }
431     if (bs.DataLength + bs.DataOffset > bs.MaxLength) {
432         return MFX_ERR_NOT_ENOUGH_BUFFER;
433     }
434     for (mfxU32 i = 0; i < bs.DataLength; i++) {
435         *(p0++) = *(p1++);
436     }
437     bs.DataOffset = 0;
438     bs.DataLength += (mfxU32)fread(bs.Data + bs.DataLength, 1, bs.MaxLength - bs.DataLength, f);
439     if (bs.DataLength == 0)
440         return MFX_ERR_MORE_DATA;
441 
442     return MFX_ERR_NONE;
443 }
444 
445 // Write encoded stream to file
WriteEncodedStream(mfxBitstream & bs,FILE * f)446 void WriteEncodedStream(mfxBitstream &bs, FILE *f) {
447     fwrite(bs.Data + bs.DataOffset, 1, bs.DataLength, f);
448     bs.DataLength = 0;
449     return;
450 }
451 
452 // Load raw I420 frames to mfxFrameSurface
ReadRawFrame(mfxFrameSurface1 * surface,FILE * f)453 mfxStatus ReadRawFrame(mfxFrameSurface1 *surface, FILE *f) {
454     mfxU16 w, h, i, pitch;
455     size_t bytes_read;
456     mfxU8 *ptr;
457     mfxFrameInfo *info = &surface->Info;
458     mfxFrameData *data = &surface->Data;
459 
460     w = info->Width;
461     h = info->Height;
462 
463     switch (info->FourCC) {
464         case MFX_FOURCC_I420:
465             // read luminance plane (Y)
466             pitch = data->Pitch;
467             ptr   = data->Y;
468             for (i = 0; i < h; i++) {
469                 bytes_read = (mfxU32)fread(ptr + i * pitch, 1, w, f);
470                 if (w != bytes_read)
471                     return MFX_ERR_MORE_DATA;
472             }
473 
474             // read chrominance (U, V)
475             pitch /= 2;
476             h /= 2;
477             w /= 2;
478             ptr = data->U;
479             for (i = 0; i < h; i++) {
480                 bytes_read = (mfxU32)fread(ptr + i * pitch, 1, w, f);
481                 if (w != bytes_read)
482                     return MFX_ERR_MORE_DATA;
483             }
484 
485             ptr = data->V;
486             for (i = 0; i < h; i++) {
487                 bytes_read = (mfxU32)fread(ptr + i * pitch, 1, w, f);
488                 if (w != bytes_read)
489                     return MFX_ERR_MORE_DATA;
490             }
491             break;
492         case MFX_FOURCC_NV12:
493             // Y
494             pitch = data->Pitch;
495             for (i = 0; i < h; i++) {
496                 bytes_read = fread(data->Y + i * pitch, 1, w, f);
497                 if (w != bytes_read)
498                     return MFX_ERR_MORE_DATA;
499             }
500             // UV
501             h /= 2;
502             for (i = 0; i < h; i++) {
503                 bytes_read = fread(data->UV + i * pitch, 1, w, f);
504                 if (w != bytes_read)
505                     return MFX_ERR_MORE_DATA;
506             }
507             break;
508         case MFX_FOURCC_RGB4:
509             // Y
510             pitch = data->Pitch;
511             for (i = 0; i < h; i++) {
512                 bytes_read = fread(data->B + i * pitch, 1, pitch, f);
513                 if (pitch != bytes_read)
514                     return MFX_ERR_MORE_DATA;
515             }
516             break;
517         default:
518             printf("Unsupported FourCC code, skip LoadRawFrame\n");
519             break;
520     }
521 
522     return MFX_ERR_NONE;
523 }
524 
525 #if (MFX_VERSION >= 2000)
ReadRawFrame_InternalMem(mfxFrameSurface1 * surface,FILE * f)526 mfxStatus ReadRawFrame_InternalMem(mfxFrameSurface1 *surface, FILE *f) {
527     bool is_more_data = false;
528 
529     // Map makes surface writable by CPU for all implementations
530     mfxStatus sts = surface->FrameInterface->Map(surface, MFX_MAP_WRITE);
531     if (sts != MFX_ERR_NONE) {
532         printf("mfxFrameSurfaceInterface->Map failed (%d)\n", sts);
533         return sts;
534     }
535 
536     sts = ReadRawFrame(surface, f);
537     if (sts != MFX_ERR_NONE) {
538         if (sts == MFX_ERR_MORE_DATA)
539             is_more_data = true;
540         else
541             return sts;
542     }
543 
544     // Unmap/release returns local device access for all implementations
545     sts = surface->FrameInterface->Unmap(surface);
546     if (sts != MFX_ERR_NONE) {
547         printf("mfxFrameSurfaceInterface->Unmap failed (%d)\n", sts);
548         return sts;
549     }
550 
551     return (is_more_data == true) ? MFX_ERR_MORE_DATA : MFX_ERR_NONE;
552 }
553 #endif
554 
555 // Write raw I420 frame to file
WriteRawFrame(mfxFrameSurface1 * surface,FILE * f)556 mfxStatus WriteRawFrame(mfxFrameSurface1 *surface, FILE *f) {
557     mfxU16 w, h, i, pitch;
558     mfxFrameInfo *info = &surface->Info;
559     mfxFrameData *data = &surface->Data;
560 
561     w = info->Width;
562     h = info->Height;
563 
564     // write the output to disk
565     switch (info->FourCC) {
566         case MFX_FOURCC_I420:
567             // Y
568             pitch = data->Pitch;
569             for (i = 0; i < h; i++) {
570                 fwrite(data->Y + i * pitch, 1, w, f);
571             }
572             // U
573             pitch /= 2;
574             h /= 2;
575             w /= 2;
576             for (i = 0; i < h; i++) {
577                 fwrite(data->U + i * pitch, 1, w, f);
578             }
579             // V
580             for (i = 0; i < h; i++) {
581                 fwrite(data->V + i * pitch, 1, w, f);
582             }
583             break;
584         case MFX_FOURCC_NV12:
585             // Y
586             pitch = data->Pitch;
587             for (i = 0; i < h; i++) {
588                 fwrite(data->Y + i * pitch, 1, w, f);
589             }
590             // UV
591             h /= 2;
592             for (i = 0; i < h; i++) {
593                 fwrite(data->UV + i * pitch, 1, w, f);
594             }
595             break;
596         case MFX_FOURCC_RGB4:
597             // Y
598             pitch = data->Pitch;
599             for (i = 0; i < h; i++) {
600                 fwrite(data->B + i * pitch, 1, pitch, f);
601             }
602             break;
603         default:
604             return MFX_ERR_UNSUPPORTED;
605             break;
606     }
607 
608     return MFX_ERR_NONE;
609 }
610 
611 #if (MFX_VERSION >= 2000)
612 // Write raw frame to file
WriteRawFrame_InternalMem(mfxFrameSurface1 * surface,FILE * f)613 mfxStatus WriteRawFrame_InternalMem(mfxFrameSurface1 *surface, FILE *f) {
614     mfxStatus sts = surface->FrameInterface->Map(surface, MFX_MAP_READ);
615     if (sts != MFX_ERR_NONE) {
616         printf("mfxFrameSurfaceInterface->Map failed (%d)\n", sts);
617         return sts;
618     }
619 
620     sts = WriteRawFrame(surface, f);
621     if (sts != MFX_ERR_NONE) {
622         printf("Error in WriteRawFrame\n");
623         return sts;
624     }
625 
626     sts = surface->FrameInterface->Unmap(surface);
627     if (sts != MFX_ERR_NONE) {
628         printf("mfxFrameSurfaceInterface->Unmap failed (%d)\n", sts);
629         return sts;
630     }
631 
632     sts = surface->FrameInterface->Release(surface);
633     if (sts != MFX_ERR_NONE) {
634         printf("mfxFrameSurfaceInterface->Release failed (%d)\n", sts);
635         return sts;
636     }
637 
638     return sts;
639 }
640 #endif
641 
642 #endif //EXAMPLES_UTIL_H_
643