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
31static hw_module_t const *gModule = NULL;
32static gralloc_module_t const *gAllocMod = NULL; /* get by force hw_module_t */
33static alloc_device_t  *gAllocDev = NULL;
34
35static 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
48static 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
77static 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
104static 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
129static 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
150static 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
185Encode_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
227void 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
248extern "C" {
249VAStatus 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
262VAStatus vaUnlockSurface(VADisplay dpy,
263    VASurfaceID surface
264);
265}
266
267VASurfaceMap::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
281VASurfaceMap::~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
292Encode_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
387Encode_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
431Encode_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
472Encode_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
508Encode_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
524Encode_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
538Encode_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
668Encode_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
693VASurfaceID 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
768VASurfaceID 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