1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <time.h>
7#include <semaphore.h>
8#include <pthread.h>
9#include <string.h>
10#include <climits>
11#include <math.h>
12
13#include <gui/GLConsumer.h>
14#include <gui/Surface.h>
15#include <ui/GraphicBuffer.h>
16#include <ui/GraphicBufferMapper.h>
17
18#include <camera/Camera.h>
19#include <camera/ICamera.h>
20#include <media/mediarecorder.h>
21
22#include <binder/IPCThreadState.h>
23#include <binder/ProcessState.h>
24#include <binder/IServiceManager.h>
25#include <cutils/properties.h>
26#include <camera/CameraParameters.h>
27#include <camera/ShotParameters.h>
28#include <camera/CameraMetadata.h>
29#include <system/audio.h>
30#include <system/camera.h>
31
32#include <cutils/memory.h>
33#include <utils/Log.h>
34
35#include <sys/wait.h>
36
37#include "camera_test.h"
38#include "camera_test_surfacetexture.h"
39
40#define ASSERT(X) \
41    do { \
42       if(!(X)) { \
43           printf("error: %s():%d", __FUNCTION__, __LINE__); \
44           return; \
45       } \
46    } while(0);
47
48#define ALIGN_DOWN(x, n) ((x) & (~((n) - 1)))
49#define ALIGN_UP(x, n) ((((x) + (n) - 1)) & (~((n) - 1)))
50#define ALIGN_WIDTH 32 // Should be 32...but the calculated dimension causes an ion crash
51#define ALIGN_HEIGHT 2 // Should be 2...but the calculated dimension causes an ion crash
52
53//temporarily define format here
54#define HAL_PIXEL_FORMAT_TI_NV12 0x100
55#define HAL_PIXEL_FORMAT_TI_Y8 0x103
56#define HAL_PIXEL_FORMAT_TI_Y16 0x104
57#define HAL_PIXEL_FORMAT_TI_UYVY 0x105
58
59using namespace android;
60
61static EGLint getSurfaceWidth() {
62    return 512;
63}
64
65static EGLint getSurfaceHeight() {
66    return 512;
67}
68
69static size_t calcBufSize(int format, int width, int height)
70{
71    int buf_size;
72
73    switch (format) {
74        case HAL_PIXEL_FORMAT_TI_NV12:
75            buf_size = width * height * 3 /2;
76            break;
77        case HAL_PIXEL_FORMAT_TI_Y16:
78        case HAL_PIXEL_FORMAT_TI_UYVY:
79            buf_size = width * height * 2;
80            break;
81        // add more formats later
82        default:
83            buf_size = width * height * 3 /2;
84            break;
85    }
86
87    return buf_size;
88}
89
90static unsigned int calcOffset(int format, unsigned int width, unsigned int top, unsigned int left)
91{
92    unsigned int bpp;
93
94    switch (format) {
95        case HAL_PIXEL_FORMAT_TI_NV12:
96            bpp = 1;
97            break;
98        case HAL_PIXEL_FORMAT_TI_UYVY:
99        case HAL_PIXEL_FORMAT_TI_Y16:
100            bpp = 2;
101            break;
102        // add more formats later
103        default:
104            bpp = 1;
105            break;
106    }
107
108    return top * width + left * bpp;
109}
110
111static int getHalPixFormat(const char *format)
112{
113    int pixformat = HAL_PIXEL_FORMAT_TI_NV12;
114    if ( NULL != format ) {
115        if ( strcmp(format, CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0 ) {
116            pixformat = HAL_PIXEL_FORMAT_TI_Y16;
117        } else if ( strcmp(format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ) {
118            pixformat = HAL_PIXEL_FORMAT_TI_NV12;
119        } else if ( strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422I) == 0 ) {
120            pixformat = HAL_PIXEL_FORMAT_TI_UYVY;
121        } else {
122            pixformat = HAL_PIXEL_FORMAT_TI_NV12;
123        }
124    }
125
126    return pixformat;
127}
128
129static int getUsageFromANW(int format)
130{
131    int usage = GRALLOC_USAGE_SW_READ_RARELY |
132                GRALLOC_USAGE_SW_WRITE_NEVER;
133
134    switch (format) {
135        case HAL_PIXEL_FORMAT_TI_NV12:
136        case HAL_PIXEL_FORMAT_TI_Y16:
137            // This usage flag indicates to gralloc we want the
138            // buffers to come from system heap
139            usage |= GRALLOC_USAGE_PRIVATE_0;
140            break;
141        default:
142            // No special flags needed
143            break;
144    }
145    return usage;
146}
147
148static status_t writeCroppedNV12(unsigned int offset,
149                                 unsigned int stride,
150                                 unsigned int bufWidth,
151                                 unsigned int bufHeight,
152                                 const Rect &crop,
153                                 int fd,
154                                 unsigned char *buffer)
155{
156    unsigned char *luma = NULL, *chroma = NULL, *src = NULL;
157    unsigned int uvoffset;
158    int write_size;
159
160    if (!buffer || !crop.isValid()) {
161        return BAD_VALUE;
162    }
163
164    src = buffer;
165    // offset to beginning of uv plane
166    uvoffset =  stride * bufHeight;
167    // offset to beginning of valid region of uv plane
168    uvoffset += (offset - (offset % stride)) / 2 + (offset % stride);
169
170    // start of valid luma region
171    luma = src + offset;
172    // start of valid chroma region
173    chroma = src + uvoffset;
174
175    // write luma line x line
176    unsigned int height = crop.height();
177    unsigned int width = crop.width();
178    write_size = width;
179    for (unsigned int i = 0; i < height; i++) {
180        if (write_size != write(fd, luma, width)) {
181            printf("Bad Write error (%d)%s\n",
182                    errno, strerror(errno));
183            return UNKNOWN_ERROR;
184        }
185        luma += stride;
186    }
187
188    // write chroma line x line
189    height /= 2;
190    write_size = width;
191    for (unsigned int i = 0; i < height; i++) {
192        if (write_size != write(fd, chroma, width)) {
193            printf("Bad Write error (%d)%s\n",
194                    errno, strerror(errno));
195            return UNKNOWN_ERROR;
196        }
197        chroma += stride;
198    }
199
200    return NO_ERROR;
201}
202
203static status_t writeCroppedUYVY(unsigned int offset,
204                                 unsigned int stride,
205                                 unsigned int bufWidth,
206                                 unsigned int bufHeight,
207                                 const Rect &crop,
208                                 int fd,
209                                 unsigned char *buffer)
210{
211    unsigned char *src = NULL;
212    int write_size;
213
214    if (!buffer) {
215        return BAD_VALUE;
216    }
217
218    src = buffer + offset;
219    int height = crop.height();
220    int width = crop.width();
221    write_size = width*2;
222    for (unsigned int i = 0; i < height; i++) {
223        if (write_size != write(fd, src, width*2)) {
224            printf("Bad Write error (%d)%s\n",
225                    errno, strerror(errno));
226            return UNKNOWN_ERROR;
227        }
228        src += stride*2;
229    }
230
231    return NO_ERROR;
232}
233
234static status_t copyCroppedNV12(unsigned int offset,
235                                unsigned int strideSrc,
236                                unsigned int strideDst,
237                                unsigned int bufWidth,
238                                unsigned int bufHeight,
239                                const Rect &crop,
240                                void *bufferSrc,
241                                void *bufferDst)
242{
243    unsigned char *lumaSrc = NULL, *chromaSrc = NULL;
244    unsigned char *lumaDst = NULL, *chromaDst = NULL;
245    unsigned int uvoffset;
246    int write_size;
247
248    if (!bufferSrc || !bufferDst) {
249        return BAD_VALUE;
250    }
251
252    uvoffset = strideSrc * crop.height();
253    uvoffset += (offset - (offset % strideSrc)) / 2 + (offset % strideSrc);
254
255    lumaSrc = static_cast<unsigned char *>(bufferSrc) + offset;
256    chromaSrc = static_cast<unsigned char *>(bufferSrc) + uvoffset;
257
258    int height = crop.height();
259    int width = crop.width();
260
261    uvoffset =  strideDst * height;
262
263    lumaDst = static_cast<unsigned char *>(bufferDst);
264    chromaDst = static_cast<unsigned char *>(bufferDst) + uvoffset;
265
266    write_size = width;
267    for (unsigned int i = 0; i < height; i++) {
268        memcpy(lumaDst, lumaSrc, width);
269        lumaSrc += strideSrc;
270        lumaDst += strideDst;
271    }
272
273    height /= 2;
274    write_size = width;
275    for (unsigned int i = 0; i < height; i++) {
276        memcpy(chromaDst, chromaSrc, width);
277        chromaSrc += strideSrc;
278        chromaDst += strideDst;
279    }
280
281    return NO_ERROR;
282}
283
284static status_t copyCroppedPacked16(unsigned int offset,
285                                    unsigned int stride,
286                                    unsigned int bufWidth,
287                                    unsigned int bufHeight,
288                                    const Rect &crop,
289                                    void *bufferSrc,
290                                    void *bufferDst)
291{
292    unsigned char *src = NULL, *dst = NULL;
293
294    if (!bufferSrc || !bufferDst) {
295        return BAD_VALUE;
296    }
297
298    src = static_cast<unsigned char *>(bufferSrc) + offset;
299    dst = static_cast<unsigned char *>(bufferDst);
300
301    int height = crop.height();
302    int width = crop.width();
303    for (unsigned int i = 0; i < height; i++) {
304        memcpy(dst, src, width*2);
305        src += stride*2;
306        dst += width*2;
307    }
308
309    return NO_ERROR;
310}
311
312void GLSurface::initialize(int display) {
313    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
314    ASSERT(EGL_SUCCESS == eglGetError());
315    ASSERT(EGL_NO_DISPLAY != mEglDisplay);
316
317    EGLint majorVersion;
318    EGLint minorVersion;
319    ASSERT(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
320    ASSERT(EGL_SUCCESS == eglGetError());
321
322    EGLint numConfigs = 0;
323    ASSERT(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
324                1, &numConfigs));
325    ASSERT(EGL_SUCCESS == eglGetError());
326
327    if (display) {
328        mComposerClient = new SurfaceComposerClient;
329        ASSERT(NO_ERROR == mComposerClient->initCheck());
330        mSurfaceControl = mComposerClient->createSurface(
331                String8("Test Surface"), 0,
332                800, 480, HAL_PIXEL_FORMAT_YCrCb_420_SP, 0);
333
334        ASSERT(mSurfaceControl != NULL);
335        ASSERT(mSurfaceControl->isValid());
336
337        SurfaceComposerClient::openGlobalTransaction();
338        ASSERT(NO_ERROR == mSurfaceControl->setLayer(0x7FFFFFFF));
339        ASSERT(NO_ERROR == mSurfaceControl->show());
340        SurfaceComposerClient::closeGlobalTransaction();
341
342        sp<ANativeWindow> window = mSurfaceControl->getSurface();
343        mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
344                window.get(), NULL);
345    } else {
346        EGLint pbufferAttribs[] = {
347            EGL_WIDTH, getSurfaceWidth(),
348            EGL_HEIGHT, getSurfaceHeight(),
349            EGL_NONE };
350        mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
351                pbufferAttribs);
352    }
353    ASSERT(EGL_SUCCESS == eglGetError());
354    ASSERT(EGL_NO_SURFACE != mEglSurface);
355
356    mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
357            getContextAttribs());
358    ASSERT(EGL_SUCCESS == eglGetError());
359    ASSERT(EGL_NO_CONTEXT != mEglContext);
360
361    ASSERT(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
362            mEglContext));
363    ASSERT(EGL_SUCCESS == eglGetError());
364
365    EGLint w, h;
366    ASSERT(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
367    ASSERT(EGL_SUCCESS == eglGetError());
368    ASSERT(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
369    ASSERT(EGL_SUCCESS == eglGetError());
370
371    glViewport(0, 0, w, h);
372    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
373}
374
375void GLSurface::deinit() {
376    if (mComposerClient != NULL) {
377        mComposerClient->dispose();
378    }
379
380    if (mEglContext != EGL_NO_CONTEXT) {
381        eglDestroyContext(mEglDisplay, mEglContext);
382    }
383
384    if (mEglSurface != EGL_NO_SURFACE) {
385        eglDestroySurface(mEglDisplay, mEglSurface);
386    }
387    if (mEglDisplay != EGL_NO_DISPLAY) {
388        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
389               EGL_NO_CONTEXT);
390        eglTerminate(mEglDisplay);
391    }
392    ASSERT(EGL_SUCCESS == eglGetError());
393}
394
395EGLint const* GLSurface::getConfigAttribs() {
396    static EGLint sDefaultConfigAttribs[] = {
397        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
398        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
399        EGL_RED_SIZE, 8,
400        EGL_GREEN_SIZE, 8,
401        EGL_BLUE_SIZE, 8,
402        EGL_ALPHA_SIZE, 8,
403        EGL_DEPTH_SIZE, 16,
404        EGL_STENCIL_SIZE, 8,
405        EGL_NONE };
406
407    return sDefaultConfigAttribs;
408}
409
410EGLint const* GLSurface::getContextAttribs() {
411    static EGLint sDefaultContextAttribs[] = {
412        EGL_CONTEXT_CLIENT_VERSION, 2,
413        EGL_NONE };
414
415    return sDefaultContextAttribs;
416}
417
418void GLSurface::loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
419    GLuint shader = glCreateShader(shaderType);
420    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
421    if (shader) {
422        glShaderSource(shader, 1, &pSource, NULL);
423        ASSERT(GLenum(GL_NO_ERROR) == glGetError());
424        glCompileShader(shader);
425        ASSERT(GLenum(GL_NO_ERROR) == glGetError());
426        GLint compiled = 0;
427        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
428        ASSERT(GLenum(GL_NO_ERROR) == glGetError());
429        if (!compiled) {
430            GLint infoLen = 0;
431            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
432            ASSERT(GLenum(GL_NO_ERROR) == glGetError());
433            if (infoLen) {
434                char* buf = (char*) malloc(infoLen);
435                if (buf) {
436                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
437                    printf("Shader compile log:\n%s\n", buf);
438                    free(buf);
439                }
440            } else {
441                char* buf = (char*) malloc(0x1000);
442                if (buf) {
443                    glGetShaderInfoLog(shader, 0x1000, NULL, buf);
444                    printf("Shader compile log:\n%s\n", buf);
445                    free(buf);
446                }
447            }
448            glDeleteShader(shader);
449            shader = 0;
450        }
451    }
452    ASSERT(shader != 0);
453    *outShader = shader;
454}
455
456void GLSurface::createProgram(const char* pVertexSource, const char* pFragmentSource,
457            GLuint* outPgm) {
458    GLuint vertexShader, fragmentShader;
459    {
460        loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
461    }
462    {
463        loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
464    }
465
466    GLuint program = glCreateProgram();
467    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
468    if (program) {
469        glAttachShader(program, vertexShader);
470        ASSERT(GLenum(GL_NO_ERROR) == glGetError());
471        glAttachShader(program, fragmentShader);
472        ASSERT(GLenum(GL_NO_ERROR) == glGetError());
473        glLinkProgram(program);
474        GLint linkStatus = GL_FALSE;
475        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
476        if (linkStatus != GL_TRUE) {
477            GLint bufLength = 0;
478            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
479            if (bufLength) {
480                char* buf = (char*) malloc(bufLength);
481                if (buf) {
482                    glGetProgramInfoLog(program, bufLength, NULL, buf);
483                    printf("Program link log:\n%s\n", buf);
484                    free(buf);
485                }
486            }
487            glDeleteProgram(program);
488            program = 0;
489        }
490    }
491    glDeleteShader(vertexShader);
492    glDeleteShader(fragmentShader);
493    ASSERT(program != 0);
494    *outPgm = program;
495}
496
497// GLConsumer specific
498sp<GLConsumer> SurfaceTextureBase::getST() {
499     return mST;
500}
501
502void SurfaceTextureBase::initialize(int tex_id, EGLenum tex_target) {
503    mTexId = tex_id;
504    sp<BufferQueue> bq = new BufferQueue();
505    mST = new GLConsumer(bq, tex_id, tex_target);
506    mSTC = new Surface(mST);
507    mANW = mSTC;
508}
509
510void SurfaceTextureBase::deinit() {
511    mANW.clear();
512    mSTC.clear();
513
514    mST->abandon();
515    mST.clear();
516}
517
518void SurfaceTextureBase::getId(const char **name) {
519    sp<ANativeWindow> windowTapOut = mSTC;
520
521    *name = NULL;
522    if (windowTapOut.get()) {
523        windowTapOut->perform(windowTapOut.get(), NATIVE_WINDOW_GET_ID, name);
524    }
525
526    windowTapOut.clear();
527}
528
529// GLConsumer with GL specific
530
531void SurfaceTextureGL::initialize(int display, int tex_id) {
532    GLSurface::initialize(display);
533    SurfaceTextureBase::initialize(tex_id, GL_TEXTURE_EXTERNAL_OES);
534
535    const char vsrc[] =
536        "attribute vec4 vPosition;\n"
537        "varying vec2 texCoords;\n"
538        "uniform mat4 texMatrix;\n"
539        "void main() {\n"
540        "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
541        "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
542        "  gl_Position = vPosition;\n"
543        "}\n";
544
545    const char fsrc[] =
546        "#extension GL_OES_EGL_image_external : require\n"
547        "precision mediump float;\n"
548        "uniform samplerExternalOES texSampler;\n"
549        "varying vec2 texCoords;\n"
550        "void main() {\n"
551        "  gl_FragColor = texture2D(texSampler, texCoords);\n"
552        "}\n";
553
554    {
555        createProgram(vsrc, fsrc, &mPgm);
556    }
557
558    mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
559    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
560    ASSERT(-1 != mPositionHandle);
561    mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
562    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
563    ASSERT(-1 != mTexSamplerHandle);
564    mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
565    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
566    ASSERT(-1 != mTexMatrixHandle);
567}
568
569void SurfaceTextureGL::deinit() {
570    SurfaceTextureBase::deinit();
571    GLSurface::deinit();
572}
573
574// drawTexture draws the GLConsumer over the entire GL viewport.
575void SurfaceTextureGL::drawTexture() {
576    const GLfloat triangleVertices[] = {
577        -1.0f, 1.0f,
578        -1.0f, -1.0f,
579        1.0f, -1.0f,
580        1.0f, 1.0f,
581    };
582
583    glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
584            triangleVertices);
585    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
586    glEnableVertexAttribArray(mPositionHandle);
587    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
588
589    glUseProgram(mPgm);
590    glUniform1i(mTexSamplerHandle, 0);
591    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
592    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexId);
593    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
594
595    // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
596    // they're setting the defautls for that target, but when hacking things
597    // to use GL_TEXTURE_2D they are needed to achieve the same behavior.
598    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER,
599            GL_LINEAR);
600    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
601    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER,
602            GL_LINEAR);
603    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
604    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
605            GL_CLAMP_TO_EDGE);
606    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
607    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
608            GL_CLAMP_TO_EDGE);
609    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
610
611    GLfloat texMatrix[16];
612    mST->getTransformMatrix(texMatrix);
613    glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
614
615    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
616    ASSERT(GLenum(GL_NO_ERROR) == glGetError());
617
618    eglSwapBuffers(mEglDisplay, mEglSurface);
619}
620
621// buffer source stuff
622void BufferSourceThread::handleBuffer(sp<GraphicBuffer> &graphic_buffer, uint8_t *buffer,
623                                        unsigned int count, const Rect &crop) {
624    int size;
625    buffer_info_t info;
626    unsigned int offset = 0;
627    int fd = -1;
628    char fn[256];
629
630    if (!graphic_buffer.get()) {
631        printf("Invalid graphic_buffer!\n");
632        return;
633    }
634
635    size = calcBufSize((int)graphic_buffer->getPixelFormat(),
636                              graphic_buffer->getWidth(),
637                              graphic_buffer->getHeight());
638    if (size <= 0) {
639        printf("Can't get size!\n");
640        return;
641    }
642
643    if (!buffer) {
644        printf("Invalid mapped buffer!\n");
645        return;
646    }
647
648    info.size = size;
649    info.width = graphic_buffer->getWidth();
650    info.height = graphic_buffer->getHeight();
651    info.format = graphic_buffer->getPixelFormat();
652    info.buf = graphic_buffer;
653    info.crop = crop;
654
655    {
656        Mutex::Autolock lock(mReturnedBuffersMutex);
657        if (mReturnedBuffers.size() >= kReturnedBuffersMaxCapacity) mReturnedBuffers.removeAt(0);
658    }
659
660    // re-calculate size and offset
661    size = calcBufSize((int) graphic_buffer->getPixelFormat(), crop.width(), crop.height());
662    offset = calcOffset((int) graphic_buffer->getPixelFormat(), info.width, crop.top, crop.left);
663
664    // Do not write buffer to file if we are streaming capture
665    // It adds too much latency
666    if (!mRestartCapture) {
667        fn[0] = 0;
668        sprintf(fn, "/sdcard/img%03d.raw", count);
669        fd = open(fn, O_CREAT | O_WRONLY | O_TRUNC, 0777);
670        if (fd >= 0) {
671            if (HAL_PIXEL_FORMAT_TI_NV12 == info.format) {
672                writeCroppedNV12(offset, info.width, info.width, info.height,
673                                 crop, fd, buffer);
674            } else if (HAL_PIXEL_FORMAT_TI_UYVY == info.format) {
675                writeCroppedUYVY(offset, info.width, info.width, info.height,
676                                 crop, fd, buffer);
677            } else if (size != write(fd, buffer + offset, size)) {
678                printf("Bad Write int a %s error (%d)%s\n", fn, errno, strerror(errno));
679            }
680            printf("%s: buffer=%08X, size=%d stored at %s\n"
681                   "\tRect: top[%d] left[%d] right[%d] bottom[%d] width[%d] height[%d] offset[%d] stride[%d]\n",
682                        __FUNCTION__, (int)buffer, size, fn,
683                        crop.top, crop.left, crop.right, crop.bottom,
684                        crop.width(), crop.height(),
685                        offset, info.width);
686            close(fd);
687        } else {
688            printf("error opening or creating %s\n", fn);
689        }
690    }
691}
692
693Rect BufferSourceThread::getCrop(sp<GraphicBuffer> &graphic_buffer, const float *mtx) {
694    Rect crop(graphic_buffer->getWidth(), graphic_buffer->getHeight());
695
696    // calculate crop rectangle from tranformation matrix
697    float sx, sy, tx, ty, h, w;
698    unsigned int rect_x, rect_y;
699    /*   sx, 0, 0, 0,
700         0, sy, 0, 0,
701         0, 0, 1, 0,
702         tx, ty, 0, 1 */
703
704    sx = mtx[0];
705    sy = mtx[5];
706    tx = mtx[12];
707    ty = mtx[13];
708    w = float(graphic_buffer->getWidth());
709    h = float(graphic_buffer->getHeight());
710
711    unsigned int bottom = (unsigned int)(h - (ty * h + 1));
712    unsigned int left = (unsigned int)(tx * w -1);
713    rect_y = (unsigned int)(fabsf(sy) * h);
714    rect_x = (unsigned int)(fabsf(sx) * w);
715
716    // handle v-flip
717    if (sy < 0.0f) {
718        bottom = h - bottom;
719    }
720
721    // handle h-flip
722    if (sx < 0.0f) {
723        left = w - left;
724    }
725
726    unsigned int top = bottom - rect_y;
727    unsigned int right = left + rect_x;
728
729    Rect updatedCrop(left, top, right, bottom);
730    if (updatedCrop.isValid()) {
731        crop = updatedCrop;
732    } else {
733        printf("Crop for buffer %d is not valid: "
734               "left=%u, top=%u, right=%u, bottom=%u. "
735               "Will use default.\n",
736               mCounter,
737               left, top, right, bottom);
738    }
739
740    return crop;
741}
742
743void BufferSourceInput::setInput(buffer_info_t bufinfo, const char *format, ShotParameters &params) {
744    ANativeWindowBuffer* anb;
745    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
746    int pixformat = HAL_PIXEL_FORMAT_TI_NV12;
747    size_t tapInMinUndequeued = 0;
748
749    int aligned_width, aligned_height;
750
751    pixformat = bufinfo.format;
752
753    // Aligning is not needed for Bayer
754    if ( ( pixformat == HAL_PIXEL_FORMAT_TI_Y16 ) ||
755         ( pixformat == HAL_PIXEL_FORMAT_TI_UYVY ) ) {
756        aligned_width = bufinfo.crop.right - bufinfo.crop.left;
757    } else {
758        aligned_width = ALIGN_UP(bufinfo.crop.right - bufinfo.crop.left, ALIGN_WIDTH);
759    }
760    aligned_height = bufinfo.crop.bottom - bufinfo.crop.top;
761    printf("aligned width: %d height: %d \n", aligned_width, aligned_height);
762
763    if (mWindowTapIn.get() == 0) {
764        return;
765    }
766
767    native_window_set_usage(mWindowTapIn.get(),
768                            getUsageFromANW(pixformat));
769    mWindowTapIn->perform(mWindowTapIn.get(),
770                          NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
771                          &tapInMinUndequeued);;
772    native_window_set_buffer_count(mWindowTapIn.get(), tapInMinUndequeued);
773    native_window_set_buffers_geometry(mWindowTapIn.get(),
774                  aligned_width, aligned_height, bufinfo.format);
775
776    // if buffer dimensions are the same as the aligned dimensions, then we can
777    // queue the buffer directly to tapin surface. if the dimensions are different
778    // then the aligned ones, then we have to copy the buffer into our own buffer
779    // to make sure the stride of the buffer is correct
780    if ((aligned_width != bufinfo.width) || (aligned_height != bufinfo.height) ||
781        ( pixformat == HAL_PIXEL_FORMAT_TI_Y16 ) ||
782        ( pixformat == HAL_PIXEL_FORMAT_TI_UYVY) ) {
783        void *dest[3] = { 0 };
784        void *src[3] = { 0 };
785        Rect bounds(aligned_width, aligned_height);
786
787        mWindowTapIn->dequeueBuffer(mWindowTapIn.get(), &anb);
788        mapper.lock(anb->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, dest);
789        // copy buffer to input buffer if available
790        if (bufinfo.buf.get()) {
791            bufinfo.buf->lock(GRALLOC_USAGE_SW_READ_OFTEN, src);
792        }
793        if (src[0]) {
794            switch (pixformat) {
795                case HAL_PIXEL_FORMAT_TI_Y16:
796                case HAL_PIXEL_FORMAT_TI_UYVY:
797                    copyCroppedPacked16(bufinfo.offset,
798                                        bufinfo.width,
799                                        bufinfo.width,
800                                        bufinfo.height,
801                                        bufinfo.crop,
802                                        src[0],
803                                        dest[0]);
804                    break;
805                case HAL_PIXEL_FORMAT_TI_NV12:
806                    copyCroppedNV12(bufinfo.offset,
807                                    bufinfo.width,
808                                    aligned_width,
809                                    bufinfo.width,
810                                    bufinfo.height,
811                                    bufinfo.crop,
812                                    src[0],
813                                    dest[0]);
814                    break;
815                default:
816                    printf("Pixel format 0x%x not supported\n", pixformat);
817                    exit(1);
818                    break;
819            }
820        }
821        if (bufinfo.buf.get()) {
822            bufinfo.buf->unlock();
823        }
824
825        mapper.unlock(anb->handle);
826    } else {
827        mWindowTapIn->perform(mWindowTapIn.get(), NATIVE_WINDOW_ADD_BUFFER_SLOT, &bufinfo.buf);
828        anb = bufinfo.buf->getNativeBuffer();
829    }
830
831    mWindowTapIn->queueBuffer(mWindowTapIn.get(), anb);
832
833    {
834        sp<ANativeWindow> windowTapIn = mWindowTapIn;
835        const char* id = NULL;
836
837        if (windowTapIn.get()) {
838            windowTapIn->perform(windowTapIn.get(), NATIVE_WINDOW_GET_ID, &id);
839        }
840
841        if (id) {
842            params.set(KEY_TAP_IN_SURFACE, id);
843        } else {
844            params.remove(KEY_TAP_IN_SURFACE);
845        }
846
847        windowTapIn.clear();
848    }
849}
850
851void BufferSourceThread::showMetadata(sp<IMemory> data) {
852    static nsecs_t prevTime = 0;
853    nsecs_t currTime = 0;
854
855    ssize_t offset;
856    size_t size;
857
858    if ( NULL == data.get() ) {
859        printf("No Metadata!");
860        return;
861    }
862
863    sp<IMemoryHeap> heap = data->getMemory(&offset, &size);
864    camera_metadata_t * meta = static_cast<camera_metadata_t *> (heap->base());
865
866    printf("         frame nmber: %d\n", meta->frame_number);
867    printf("         shot number: %d\n", meta->shot_number);
868    printf("         analog gain: %d req: %d range: %d~%d dev: %d err: %d\n",
869           meta->analog_gain,
870           meta->analog_gain_req,
871           meta->analog_gain_min,
872           meta->analog_gain_max,
873           meta->analog_gain_dev,
874           meta->analog_gain_error);
875    printf("       exposure time: %d req: %d range: %d~%d dev: %d err: %d\n",
876           meta->exposure_time,
877           meta->exposure_time_req,
878           meta->exposure_time_min,
879           meta->exposure_time_max,
880           meta->exposure_time_dev,
881           meta->exposure_time_error);
882    printf("     EV compensation: req: %d dev: %d\n",
883           meta->exposure_compensation_req,
884           meta->exposure_dev);
885    printf("            awb gain: %d\n", meta->analog_gain);
886    printf("         awb offsets: %d\n", meta->offset_b);
887    printf("     awb temperature: %d\n", meta->awb_temp);
888
889    printf("   LSC table applied: %d\n", meta->lsc_table_applied);
890    if ( meta->lsc_table_applied ) {
891        uint8_t *lscTable = (uint8_t *)meta + meta->lsc_table_offset;
892        printf("LSC Table Size:%d Data[0:7]: %d:%d:%d:%d:%d:%d:%d:%d\n",
893                meta->lsc_table_size,
894                lscTable[0],
895                lscTable[1],
896                lscTable[2],
897                lscTable[3],
898                lscTable[4],
899                lscTable[5],
900                lscTable[6],
901                lscTable[7]);
902    }
903
904    printf("    Faces detected: %d\n", meta->number_of_faces);
905
906    currTime = meta->timestamp;
907    printf("      timestamp (ns): %llu\n", currTime);
908    if (prevTime) printf("inter-shot time (ms): %llu\n", (currTime - prevTime) / 1000000l);
909    prevTime = currTime;
910}
911