1 /*
2 * Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #include "VideoEncoderLog.h"
18 #include "VideoEncoderUtils.h"
19 #include <va/va_android.h>
20 #include <va/va_drmcommon.h>
21 
22 #ifdef IMG_GFX
23 #include <hal/hal_public.h>
24 #include <hardware/gralloc.h>
25 #include <sync/sync.h>
26 
27 //#define GFX_DUMP
28 
29 #define OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar 0x7FA00E00
30 
31 static hw_module_t const *gModule = NULL;
32 static gralloc_module_t const *gAllocMod = NULL; /* get by force hw_module_t */
33 static alloc_device_t  *gAllocDev = NULL;
34 
gfx_init(void)35 static int gfx_init(void) {
36 
37     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gModule);
38     if (err) {
39         LOG_E("FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
40         return -1;
41     } else
42         LOG_V("hw_get_module returned\n");
43     gAllocMod = (gralloc_module_t const *)gModule;
44 
45     return 0;
46 }
47 
gfx_alloc(uint32_t w,uint32_t h,int format,int usage,buffer_handle_t * handle,int32_t * stride)48 static int gfx_alloc(uint32_t w, uint32_t h, int format,
49           int usage, buffer_handle_t* handle, int32_t* stride) {
50 
51     int err;
52 
53     if (!gAllocDev) {
54         if (!gModule) {
55             if (gfx_init()) {
56                 LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
57                 return -1;
58             }
59         }
60 
61         err = gralloc_open(gModule, &gAllocDev);
62         if (err) {
63             LOG_E("FATAL: gralloc open failed\n");
64             return -1;
65         }
66     }
67 
68     err = gAllocDev->alloc(gAllocDev, w, h, format, usage, handle, stride);
69     if (err) {
70         LOG_E("alloc(%u, %u, %d, %08x, ...) failed %d (%s)\n",
71                w, h, format, usage, err, strerror(-err));
72     }
73 
74     return err;
75 }
76 
gfx_free(buffer_handle_t handle)77 static int gfx_free(buffer_handle_t handle) {
78 
79     int err;
80 
81     if (!gAllocDev) {
82         if (!gModule) {
83             if (gfx_init()) {
84                 LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
85                 return -1;
86             }
87         }
88 
89         err = gralloc_open(gModule, &gAllocDev);
90         if (err) {
91             LOG_E("FATAL: gralloc open failed\n");
92             return -1;
93         }
94     }
95 
96     err = gAllocDev->free(gAllocDev, handle);
97     if (err) {
98         LOG_E("free(...) failed %d (%s)\n", err, strerror(-err));
99     }
100 
101     return err;
102 }
103 
gfx_lock(buffer_handle_t handle,int usage,int left,int top,int width,int height,void ** vaddr)104 static int gfx_lock(buffer_handle_t handle, int usage,
105                       int left, int top, int width, int height, void** vaddr) {
106 
107     int err;
108 
109     if (!gAllocMod) {
110         if (gfx_init()) {
111             LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
112             return -1;
113         }
114     }
115 
116     err = gAllocMod->lock(gAllocMod, handle, usage,
117                           left, top, width, height, vaddr);
118     LOG_V("gfx_lock: handle is %x, usage is %x, vaddr is %x.\n", (unsigned int)handle, usage, (unsigned int)*vaddr);
119 
120     if (err){
121         LOG_E("lock(...) failed %d (%s).\n", err, strerror(-err));
122         return -1;
123     } else
124         LOG_V("lock returned with address %p\n", *vaddr);
125 
126     return err;
127 }
128 
gfx_unlock(buffer_handle_t handle)129 static int gfx_unlock(buffer_handle_t handle) {
130 
131     int err;
132 
133     if (!gAllocMod) {
134         if (gfx_init()) {
135             LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
136             return -1;
137         }
138     }
139 
140     err = gAllocMod->unlock(gAllocMod, handle);
141     if (err) {
142         LOG_E("unlock(...) failed %d (%s)", err, strerror(-err));
143         return -1;
144     } else
145         LOG_V("unlock returned\n");
146 
147     return err;
148 }
149 
gfx_Blit(buffer_handle_t src,buffer_handle_t dest,int w,int h,int,int)150 static int gfx_Blit(buffer_handle_t src, buffer_handle_t dest,
151                       int w, int h, int , int )
152 {
153     int err;
154 
155     if (!gAllocMod) {
156         if (gfx_init()) {
157             LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
158             return -1;
159         }
160     }
161 
162 #ifdef MRFLD_GFX
163     {
164         int fenceFd;
165         err = gAllocMod->perform(gAllocMod, GRALLOC_MODULE_BLIT_HANDLE_TO_HANDLE_IMG, src, dest, w, h, 0, 0, 0, -1, &fenceFd);
166         if (!err) {
167             sync_wait(fenceFd, -1);
168             close(fenceFd);
169         }
170     }
171 #else
172     IMG_gralloc_module_public_t* GrallocMod = (IMG_gralloc_module_public_t*)gModule;
173     err = GrallocMod->Blit2(GrallocMod, src, dest, w, h, 0, 0);
174 #endif
175 
176     if (err) {
177         LOG_E("Blit failed %d (%s)", err, strerror(-err));
178         return -1;
179     } else
180         LOG_V("Blit returned\n");
181 
182     return err;
183 }
184 
GetGfxBufferInfo(intptr_t handle,ValueInfo & vinfo)185 Encode_Status GetGfxBufferInfo(intptr_t handle, ValueInfo& vinfo){
186 
187     /* only support OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
188                                 HAL_PIXEL_FORMAT_NV12
189                                 HAL_PIXEL_FORMAT_BGRA_8888
190                                 HAL_PIXEL_FORMAT_RGBA_8888
191                                 HAL_PIXEL_FORMAT_RGBX_8888
192                                 HAL_PIXEL_FORMAT_BGRX_8888 */
193     IMG_native_handle_t* h = (IMG_native_handle_t*) handle;
194 
195     vinfo.width = h->iWidth;
196     vinfo.height = h->iHeight;
197     vinfo.lumaStride = h->iWidth;
198 
199     LOG_V("GetGfxBufferInfo: gfx iWidth=%d, iHeight=%d, iFormat=%x in handle structure\n", h->iWidth, h->iHeight, h->iFormat);
200 
201     if (h->iFormat == HAL_PIXEL_FORMAT_NV12) {
202     #ifdef MRFLD_GFX
203         vinfo.lumaStride = (h->iWidth + 63) & ~63; //64 aligned
204     #else //on CTP
205         if (h->iWidth > 512)
206             vinfo.lumaStride = (h->iWidth + 63) & ~63;  //64 aligned
207         else
208             vinfo.lumaStride = 512;
209     #endif
210     } else if ((h->iFormat == HAL_PIXEL_FORMAT_BGRA_8888)||
211                   (h->iFormat == HAL_PIXEL_FORMAT_RGBA_8888)||
212                   (h->iFormat == HAL_PIXEL_FORMAT_RGBX_8888)||
213                   (h->iFormat == HAL_PIXEL_FORMAT_BGRX_8888)) {
214         vinfo.lumaStride = (h->iWidth + 31) & ~31;
215     } else if (h->iFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar) {
216         //nothing to do
217     } else
218         return ENCODE_NOT_SUPPORTED;
219 
220     vinfo.format = h->iFormat;
221 
222     LOG_V("Actual Width=%d, Height=%d, Stride=%d\n\n", vinfo.width, vinfo.height, vinfo.lumaStride);
223     return ENCODE_SUCCESS;
224 }
225 
226 #ifdef GFX_DUMP
DumpGfx(intptr_t handle,char * filename)227 void DumpGfx(intptr_t handle, char* filename) {
228     ValueInfo vinfo;
229     void* vaddr[3];
230     FILE* fp;
231     int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN;
232 
233     GetGfxBufferInfo(handle, vinfo);
234     if (gfx_lock((buffer_handle_t)handle, usage, 0, 0, vinfo.width, vinfo.height, &vaddr[0]) != 0)
235         return ENCODE_DRIVER_FAIL;
236     fp = fopen(filename, "wb");
237     fwrite(vaddr[0], 1, vinfo.lumaStride * vinfo.height * 4, fp);
238     fclose(fp);
239     LOG_I("dump %d bytes data to %s\n", vinfo.lumaStride * vinfo.height * 4, filename);
240     gfx_unlock((buffer_handle_t)handle);
241 
242     return;
243 }
244 #endif
245 
246 #endif
247 
248 extern "C" {
249 VAStatus vaLockSurface(VADisplay dpy,
250     VASurfaceID surface,
251     unsigned int *fourcc,
252     unsigned int *luma_stride,
253     unsigned int *chroma_u_stride,
254     unsigned int *chroma_v_stride,
255     unsigned int *luma_offset,
256     unsigned int *chroma_u_offset,
257     unsigned int *chroma_v_offset,
258     unsigned int *buffer_name,
259     void **buffer
260 );
261 
262 VAStatus vaUnlockSurface(VADisplay dpy,
263     VASurfaceID surface
264 );
265 }
266 
VASurfaceMap(VADisplay display,int hwcap)267 VASurfaceMap::VASurfaceMap(VADisplay display, int hwcap) {
268 
269     mVADisplay = display;
270     mSupportedSurfaceMemType = hwcap;
271     mValue = 0;
272     mVASurface = VA_INVALID_SURFACE;
273     mTracked = false;
274     mAction = 0;
275     memset(&mVinfo, 0, sizeof(ValueInfo));
276 #ifdef IMG_GFX
277     mGfxHandle = NULL;
278 #endif
279 }
280 
~VASurfaceMap()281 VASurfaceMap::~VASurfaceMap() {
282 
283     if (!mTracked && (mVASurface != VA_INVALID_SURFACE))
284         vaDestroySurfaces(mVADisplay, &mVASurface, 1);
285 
286 #ifdef IMG_GFX
287     if (mGfxHandle)
288         gfx_free(mGfxHandle);
289 #endif
290 }
291 
doMapping()292 Encode_Status VASurfaceMap::doMapping() {
293 
294     Encode_Status ret = ENCODE_SUCCESS;
295 
296     if (mVASurface == VA_INVALID_SURFACE) {
297 
298         int width = mVASurfaceWidth = mVinfo.width;
299         int height = mVASurfaceHeight = mVinfo.height;
300         int stride = mVASurfaceStride = mVinfo.lumaStride;
301 
302         if (mAction & MAP_ACTION_COLORCONVERT) {
303 
304             //only support gfx buffer
305             if (mVinfo.mode != MEM_MODE_GFXHANDLE)
306                 return ENCODE_NOT_SUPPORTED;
307 
308         #ifdef IMG_GFX //only enable on IMG chip
309 
310             //do not trust valueinfo for gfx case, directly get from structure
311             ValueInfo tmp;
312 
313             ret = GetGfxBufferInfo(mValue, tmp);
314             CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
315             width = tmp.width;
316             height = tmp.height;
317             stride = tmp.lumaStride;
318 
319             if (HAL_PIXEL_FORMAT_NV12 == tmp.format || OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar == tmp.format)
320                 mAction &= ~MAP_ACTION_COLORCONVERT;
321             else {
322                 //allocate new gfx buffer if format is not NV12
323                 int usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
324 
325                 //use same size with original and HAL_PIXEL_FORMAT_NV12 format
326                 if (gfx_alloc(width, height, HAL_PIXEL_FORMAT_NV12, usage, &mGfxHandle, &stride) != 0)
327                     return ENCODE_DRIVER_FAIL;
328 
329                 LOG_V("Create an new gfx buffer handle 0x%p for color convert, width=%d, height=%d, stride=%d\n",
330                            mGfxHandle, width, height, stride);
331             }
332 
333         #else
334             return ENCODE_NOT_SUPPORTED;
335         #endif
336         }
337 
338         if (mAction & MAP_ACTION_ALIGN64 && stride % 64 != 0) {
339             //check if stride is not 64 aligned, must allocate new 64 aligned vasurface
340             stride = (stride + 63 ) & ~63;
341             mAction |= MAP_ACTION_COPY;
342         }
343 
344         if(mAction & MAP_ACTION_ALIGN64 && width <= 320 && height <= 240) {
345             mAction |= MAP_ACTION_COPY;
346         }
347 
348         if (mAction & MAP_ACTION_COPY) { //must allocate new vasurface(EXternalMemoryNULL, uncached)
349             //allocate new vasurface
350             mVASurface = CreateNewVASurface(mVADisplay, stride, height);
351             if (mVASurface == VA_INVALID_SURFACE)
352                 return ENCODE_DRIVER_FAIL;
353             mVASurfaceWidth = mVASurfaceStride = stride;
354             mVASurfaceHeight = height;
355             LOGI("create new vaSurface for MAP_ACTION_COPY\n");
356         } else {
357         #ifdef IMG_GFX
358             if (mGfxHandle != NULL) {
359                 //map new gfx handle to vasurface
360                 ret = MappingGfxHandle((intptr_t)mGfxHandle);
361                 CHECK_ENCODE_STATUS_RETURN("MappingGfxHandle");
362                 LOGV("map new allocated gfx handle to vaSurface\n");
363             } else
364         #endif
365             {
366                 //map original value to vasurface
367                 ret = MappingToVASurface();
368                 CHECK_ENCODE_STATUS_RETURN("MappingToVASurface");
369             }
370         }
371     }
372 
373     if (mAction & MAP_ACTION_COLORCONVERT) {
374         ret = doActionColConv();
375         CHECK_ENCODE_STATUS_RETURN("doActionColConv");
376     }
377 
378     if (mAction & MAP_ACTION_COPY) {
379         //keep src color format is NV12, then do copy
380         ret = doActionCopy();
381         CHECK_ENCODE_STATUS_RETURN("doActionCopy");
382     }
383 
384     return ENCODE_SUCCESS;
385 }
386 
MappingToVASurface()387 Encode_Status VASurfaceMap::MappingToVASurface() {
388 
389     Encode_Status ret = ENCODE_SUCCESS;
390 
391     if (mVASurface != VA_INVALID_SURFACE) {
392         LOG_I("VASurface is already set before, nothing to do here\n");
393         return ENCODE_SUCCESS;
394     }
395     LOG_V("MappingToVASurface mode=%d, value=%p\n", mVinfo.mode, (void*)mValue);
396 
397     const char *mode = NULL;
398     switch (mVinfo.mode) {
399         case MEM_MODE_SURFACE:
400             mode = "SURFACE";
401             ret = MappingSurfaceID(mValue);
402             break;
403         case MEM_MODE_GFXHANDLE:
404             mode = "GFXHANDLE";
405             ret = MappingGfxHandle(mValue);
406             break;
407         case MEM_MODE_KBUFHANDLE:
408             mode = "KBUFHANDLE";
409             ret = MappingKbufHandle(mValue);
410             break;
411         case MEM_MODE_MALLOC:
412         case MEM_MODE_NONECACHE_USRPTR:
413             mode = "MALLOC or NONCACHE_USRPTR";
414             ret = MappingMallocPTR(mValue);
415             break;
416         case MEM_MODE_ION:
417         case MEM_MODE_V4L2:
418         case MEM_MODE_USRPTR:
419         case MEM_MODE_CI:
420         default:
421             LOG_I("UnSupported memory mode 0x%08x", mVinfo.mode);
422             return ENCODE_NOT_SUPPORTED;
423     }
424 
425     LOG_V("%s: Format=%x, lumaStride=%d, width=%d, height=%d\n", mode, mVinfo.format, mVinfo.lumaStride, mVinfo.width, mVinfo.height);
426     LOG_V("vaSurface 0x%08x is created for value = 0x%p\n", mVASurface, (void*)mValue);
427 
428     return ret;
429 }
430 
MappingSurfaceID(intptr_t value)431 Encode_Status VASurfaceMap::MappingSurfaceID(intptr_t value) {
432 
433     VAStatus vaStatus = VA_STATUS_SUCCESS;
434 
435     //try to get kbufhandle from SurfaceID
436     uint32_t fourCC = 0;
437     uint32_t lumaStride = 0;
438     uint32_t chromaUStride = 0;
439     uint32_t chromaVStride = 0;
440     uint32_t lumaOffset = 0;
441     uint32_t chromaUOffset = 0;
442     uint32_t chromaVOffset = 0;
443     uint32_t kBufHandle = 0;
444 
445     vaStatus = vaLockSurface(
446             (VADisplay)mVinfo.handle, (VASurfaceID)value,
447             &fourCC, &lumaStride, &chromaUStride, &chromaVStride,
448             &lumaOffset, &chromaUOffset, &chromaVOffset, &kBufHandle, NULL);
449 
450     CHECK_VA_STATUS_RETURN("vaLockSurface");
451     LOG_V("Surface incoming = 0x%p\n", (void*)value);
452     LOG_V("lumaStride = %d, chromaUStride = %d, chromaVStride=%d\n", lumaStride, chromaUStride, chromaVStride);
453     LOG_V("lumaOffset = %d, chromaUOffset = %d, chromaVOffset = %d\n", lumaOffset, chromaUOffset, chromaVOffset);
454     LOG_V("kBufHandle = 0x%08x, fourCC = %d\n", kBufHandle, fourCC);
455 
456     vaStatus = vaUnlockSurface((VADisplay)mVinfo.handle, (VASurfaceID)value);
457     CHECK_VA_STATUS_RETURN("vaUnlockSurface");
458 
459     mVinfo.mode = MEM_MODE_KBUFHANDLE;
460     mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
461 
462     mVASurface = CreateSurfaceFromExternalBuf(kBufHandle, mVinfo);
463     if (mVASurface == VA_INVALID_SURFACE)
464         return ENCODE_INVALID_SURFACE;
465 
466     mVASurfaceWidth = mVinfo.width;
467     mVASurfaceHeight = mVinfo.height;
468     mVASurfaceStride = mVinfo.lumaStride;
469     return ENCODE_SUCCESS;
470 }
471 
MappingGfxHandle(intptr_t value)472 Encode_Status VASurfaceMap::MappingGfxHandle(intptr_t value) {
473 
474     LOG_V("MappingGfxHandle %p......\n", (void*)value);
475     LOG_V("format = 0x%08x, lumaStride = %d in ValueInfo\n", mVinfo.format, mVinfo.lumaStride);
476 
477     //default value for all HW platforms, maybe not accurate
478     mVASurfaceWidth = mVinfo.width;
479     mVASurfaceHeight = mVinfo.height;
480     mVASurfaceStride = mVinfo.lumaStride;
481 
482 #ifdef IMG_GFX
483     Encode_Status ret;
484     ValueInfo tmp;
485 
486     ret = GetGfxBufferInfo(value, tmp);
487     CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
488     mVASurfaceWidth = tmp.width;
489     mVASurfaceHeight = tmp.height;
490     mVASurfaceStride = tmp.lumaStride;
491 #endif
492 
493     LOG_V("Mapping vasurface Width=%d, Height=%d, Stride=%d\n", mVASurfaceWidth, mVASurfaceHeight, mVASurfaceStride);
494 
495     ValueInfo vinfo;
496     memset(&vinfo, 0, sizeof(ValueInfo));
497     vinfo.mode = MEM_MODE_GFXHANDLE;
498     vinfo.width = mVASurfaceWidth;
499     vinfo.height = mVASurfaceHeight;
500     vinfo.lumaStride = mVASurfaceStride;
501     mVASurface = CreateSurfaceFromExternalBuf(value, vinfo);
502     if (mVASurface == VA_INVALID_SURFACE)
503         return ENCODE_INVALID_SURFACE;
504 
505     return ENCODE_SUCCESS;
506 }
507 
MappingKbufHandle(intptr_t value)508 Encode_Status VASurfaceMap::MappingKbufHandle(intptr_t value) {
509 
510     LOG_V("MappingKbufHandle value=%p\n", (void*)value);
511 
512     mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
513     mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
514     if (mVASurface == VA_INVALID_SURFACE)
515         return ENCODE_INVALID_SURFACE;
516 
517     mVASurfaceWidth = mVinfo.width;
518     mVASurfaceHeight = mVinfo.height;
519     mVASurfaceStride = mVinfo.lumaStride;
520 
521     return ENCODE_SUCCESS;
522 }
523 
MappingMallocPTR(intptr_t value)524 Encode_Status VASurfaceMap::MappingMallocPTR(intptr_t value) {
525 
526     mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
527     if (mVASurface == VA_INVALID_SURFACE)
528         return ENCODE_INVALID_SURFACE;
529 
530     mVASurfaceWidth = mVinfo.width;
531     mVASurfaceHeight = mVinfo.height;
532     mVASurfaceStride = mVinfo.lumaStride;
533 
534     return ENCODE_SUCCESS;
535 }
536 
537 //always copy with same color format NV12
doActionCopy()538 Encode_Status VASurfaceMap::doActionCopy() {
539 
540     VAStatus vaStatus = VA_STATUS_SUCCESS;
541 
542     uint32_t width = 0, height = 0, stride = 0;
543     uint8_t *pSrcBuffer, *pDestBuffer;
544     intptr_t handle = 0;
545 
546     LOG_V("Copying Src Buffer data to VASurface\n");
547 
548     if (mVinfo.mode != MEM_MODE_MALLOC && mVinfo.mode != MEM_MODE_GFXHANDLE) {
549         LOG_E("Not support copy in mode %d", mVinfo.mode);
550         return ENCODE_NOT_SUPPORTED;
551     }
552 
553     LOG_V("Src Buffer information\n");
554     LOG_V("Mode = %d, width = %d, stride = %d, height = %d\n",
555            mVinfo.mode, mVinfo.width, mVinfo.lumaStride, mVinfo.height);
556 
557     uint32_t srcY_offset, srcUV_offset;
558     uint32_t srcY_pitch, srcUV_pitch;
559 
560     if (mVinfo.mode == MEM_MODE_MALLOC) {
561         width = mVinfo.width;
562         height = mVinfo.height;
563         stride = mVinfo.lumaStride;
564         pSrcBuffer = (uint8_t*) mValue;
565         srcY_offset = 0;
566         srcUV_offset = stride * height;
567         srcY_pitch = stride;
568         srcUV_pitch = stride;
569     } else {
570 
571     #ifdef IMG_GFX  //only enable on IMG chips
572         int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN;
573 
574         //do not trust valueinfo, directly get from structure
575         Encode_Status ret;
576         ValueInfo tmp;
577 
578         if (mGfxHandle)
579             handle = (intptr_t) mGfxHandle;
580         else
581             handle = mValue;
582 
583         ret = GetGfxBufferInfo(handle, tmp);
584         CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
585         width = tmp.width;
586         height = tmp.height;
587         stride = tmp.lumaStride;
588 
589         //only support HAL_PIXEL_FORMAT_NV12 & OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
590         if (HAL_PIXEL_FORMAT_NV12 != tmp.format && OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar != tmp.format) {
591             LOG_E("Not support gfx buffer format %x", tmp.format);
592             return ENCODE_NOT_SUPPORTED;
593         }
594 
595         srcY_offset = 0;
596         srcUV_offset = stride * height;
597         srcY_pitch = stride;
598         srcUV_pitch = stride;
599 
600         //lock gfx handle with buffer real size
601         void* vaddr[3];
602         if (gfx_lock((buffer_handle_t) handle, usage, 0, 0, width, height, &vaddr[0]) != 0)
603             return ENCODE_DRIVER_FAIL;
604         pSrcBuffer = (uint8_t*)vaddr[0];
605     #else
606 
607         return ENCODE_NOT_SUPPORTED;
608     #endif
609     }
610 
611 
612     VAImage destImage;
613     vaStatus = vaDeriveImage(mVADisplay, mVASurface, &destImage);
614     CHECK_VA_STATUS_RETURN("vaDeriveImage");
615     vaStatus = vaMapBuffer(mVADisplay, destImage.buf, (void **)&pDestBuffer);
616     CHECK_VA_STATUS_RETURN("vaMapBuffer");
617 
618     LOG_V("\nDest VASurface information\n");
619     LOG_V("pitches[0] = %d\n", destImage.pitches[0]);
620     LOG_V("pitches[1] = %d\n", destImage.pitches[1]);
621     LOG_V("offsets[0] = %d\n", destImage.offsets[0]);
622     LOG_V("offsets[1] = %d\n", destImage.offsets[1]);
623     LOG_V("num_planes = %d\n", destImage.num_planes);
624     LOG_V("width = %d\n", destImage.width);
625     LOG_V("height = %d\n", destImage.height);
626 
627     if (width > destImage.width || height > destImage.height) {
628         LOG_E("src buffer is bigger than destination buffer\n");
629         return ENCODE_INVALID_PARAMS;
630     }
631 
632     uint8_t *srcY, *dstY;
633     uint8_t *srcUV, *dstUV;
634 
635     srcY = pSrcBuffer + srcY_offset;
636     dstY = pDestBuffer + destImage.offsets[0];
637     srcUV = pSrcBuffer + srcUV_offset;
638     dstUV = pDestBuffer + destImage.offsets[1];
639 
640     for (uint32_t i = 0; i < height; i++) {
641         memcpy(dstY, srcY, width);
642         srcY += srcY_pitch;
643         dstY += destImage.pitches[0];
644     }
645 
646     for (uint32_t i = 0; i < height / 2; i++) {
647         memcpy(dstUV, srcUV, width);
648         srcUV += srcUV_pitch;
649         dstUV += destImage.pitches[1];
650     }
651 
652     vaStatus = vaUnmapBuffer(mVADisplay, destImage.buf);
653     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
654     vaStatus = vaDestroyImage(mVADisplay, destImage.image_id);
655     CHECK_VA_STATUS_RETURN("vaDestroyImage");
656 
657 #ifdef IMG_GFX
658     if (mVinfo.mode == MEM_MODE_GFXHANDLE) {
659         //unlock gfx handle
660         gfx_unlock((buffer_handle_t) handle);
661     }
662 #endif
663     LOG_V("Copying Src Buffer data to VASurface Complete\n");
664 
665     return ENCODE_SUCCESS;
666 }
667 
doActionColConv()668 Encode_Status VASurfaceMap::doActionColConv() {
669 
670 #ifdef IMG_GFX
671     if (mGfxHandle == NULL) {
672         LOG_E("something wrong, why new gfxhandle is not allocated? \n");
673         return ENCODE_FAIL;
674     }
675 
676     LOG_V("doActionColConv gfx_Blit width=%d, height=%d\n", mVinfo.width, mVinfo.height);
677     if (gfx_Blit((buffer_handle_t)mValue, mGfxHandle,
678             mVinfo.width, mVinfo.height, 0, 0) != 0)
679         return ENCODE_DRIVER_FAIL;
680 
681   #ifdef GFX_DUMP
682     LOG_I("dumpping gfx data.....\n");
683     DumpGfx(mValue, "/data/dump.rgb");
684     DumpGfx((intptr_t)mGfxHandle, "/data/dump.yuv");
685   #endif
686     return ENCODE_SUCCESS;
687 
688 #else
689     return ENCODE_NOT_SUPPORTED;
690 #endif
691 }
692 
CreateSurfaceFromExternalBuf(intptr_t value,ValueInfo & vinfo)693 VASurfaceID VASurfaceMap::CreateSurfaceFromExternalBuf(intptr_t value, ValueInfo& vinfo) {
694 
695     VAStatus vaStatus;
696     VASurfaceAttribExternalBuffers extbuf;
697     VASurfaceAttrib attribs[2];
698     VASurfaceID surface = VA_INVALID_SURFACE;
699     int type;
700     unsigned long data = value;
701 
702     extbuf.pixel_format = VA_FOURCC_NV12;
703     extbuf.width = vinfo.width;
704     extbuf.height = vinfo.height;
705     extbuf.data_size = vinfo.size;
706     if (extbuf.data_size == 0)
707         extbuf.data_size = vinfo.lumaStride * vinfo.height * 1.5;
708     extbuf.num_buffers = 1;
709     extbuf.num_planes = 3;
710     extbuf.pitches[0] = vinfo.lumaStride;
711     extbuf.pitches[1] = vinfo.lumaStride;
712     extbuf.pitches[2] = vinfo.lumaStride;
713     extbuf.pitches[3] = 0;
714     extbuf.offsets[0] = 0;
715     extbuf.offsets[1] = vinfo.lumaStride * vinfo.height;
716     extbuf.offsets[2] = extbuf.offsets[1];
717     extbuf.offsets[3] = 0;
718     extbuf.buffers = &data;
719     extbuf.flags = 0;
720     extbuf.private_data = NULL;
721 
722     switch(vinfo.mode) {
723         case MEM_MODE_GFXHANDLE:
724             type = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
725             break;
726         case MEM_MODE_KBUFHANDLE:
727             type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
728             break;
729         case MEM_MODE_MALLOC:
730             type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
731             break;
732         case MEM_MODE_NONECACHE_USRPTR:
733             type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
734             extbuf.flags |= VA_SURFACE_EXTBUF_DESC_UNCACHED;
735             break;
736         case MEM_MODE_SURFACE:
737         case MEM_MODE_ION:
738         case MEM_MODE_V4L2:
739         case MEM_MODE_USRPTR:
740         case MEM_MODE_CI:
741         default:
742             //not support
743             return VA_INVALID_SURFACE;
744     }
745 
746     if (!(mSupportedSurfaceMemType & type))
747         return VA_INVALID_SURFACE;
748 
749     attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
750     attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
751     attribs[0].value.type = VAGenericValueTypeInteger;
752     attribs[0].value.value.i = type;
753 
754     attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
755     attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
756     attribs[1].value.type = VAGenericValueTypePointer;
757     attribs[1].value.value.p = (void *)&extbuf;
758 
759     vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420, vinfo.width,
760                                  vinfo.height, &surface, 1, attribs, 2);
761     if (vaStatus != VA_STATUS_SUCCESS){
762         LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus);
763         surface = VA_INVALID_SURFACE;
764     }
765     return surface;
766 }
767 
CreateNewVASurface(VADisplay display,int32_t width,int32_t height)768 VASurfaceID CreateNewVASurface(VADisplay display, int32_t width, int32_t height) {
769 
770     VAStatus vaStatus;
771     VASurfaceID surface = VA_INVALID_SURFACE;
772     VASurfaceAttrib attribs[2];
773     VASurfaceAttribExternalBuffers extbuf;
774     unsigned long data;
775 
776     extbuf.pixel_format = VA_FOURCC_NV12;
777     extbuf.width = width;
778     extbuf.height = height;
779     extbuf.data_size = width * height * 3 / 2;
780     extbuf.num_buffers = 1;
781     extbuf.num_planes = 3;
782     extbuf.pitches[0] = width;
783     extbuf.pitches[1] = width;
784     extbuf.pitches[2] = width;
785     extbuf.pitches[3] = 0;
786     extbuf.offsets[0] = 0;
787     extbuf.offsets[1] = width * height;
788     extbuf.offsets[2] = extbuf.offsets[1];
789     extbuf.offsets[3] = 0;
790     extbuf.buffers = &data;
791     extbuf.flags = 0;
792     extbuf.private_data = NULL;
793 
794     attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
795     attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
796     attribs[0].value.type = VAGenericValueTypeInteger;
797     attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
798 
799     attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
800     attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
801     attribs[1].value.type = VAGenericValueTypePointer;
802     attribs[1].value.value.p = (void *)&extbuf;
803 
804     vaStatus = vaCreateSurfaces(display, VA_RT_FORMAT_YUV420, width,
805                                  height, &surface, 1, attribs, 2);
806     if (vaStatus != VA_STATUS_SUCCESS)
807         LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus);
808 
809     return surface;
810 }
811