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
59 using namespace android;
60
getSurfaceWidth()61 static EGLint getSurfaceWidth() {
62 return 512;
63 }
64
getSurfaceHeight()65 static EGLint getSurfaceHeight() {
66 return 512;
67 }
68
calcBufSize(int format,int width,int height)69 static 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
calcOffset(int format,unsigned int width,unsigned int top,unsigned int left)90 static 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
getHalPixFormat(const char * format)111 static 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
getUsageFromANW(int format)129 static 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
writeCroppedNV12(unsigned int offset,unsigned int stride,unsigned int bufWidth,unsigned int bufHeight,const Rect & crop,int fd,unsigned char * buffer)148 static 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
writeCroppedUYVY(unsigned int offset,unsigned int stride,unsigned int bufWidth,unsigned int bufHeight,const Rect & crop,int fd,unsigned char * buffer)203 static 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
copyCroppedNV12(unsigned int offset,unsigned int strideSrc,unsigned int strideDst,unsigned int bufWidth,unsigned int bufHeight,const Rect & crop,void * bufferSrc,void * bufferDst)234 static 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
copyCroppedPacked16(unsigned int offset,unsigned int stride,unsigned int bufWidth,unsigned int bufHeight,const Rect & crop,void * bufferSrc,void * bufferDst)284 static 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
initialize(int display)312 void 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
deinit()375 void 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
getConfigAttribs()395 EGLint 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
getContextAttribs()410 EGLint const* GLSurface::getContextAttribs() {
411 static EGLint sDefaultContextAttribs[] = {
412 EGL_CONTEXT_CLIENT_VERSION, 2,
413 EGL_NONE };
414
415 return sDefaultContextAttribs;
416 }
417
loadShader(GLenum shaderType,const char * pSource,GLuint * outShader)418 void 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
createProgram(const char * pVertexSource,const char * pFragmentSource,GLuint * outPgm)456 void 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
getST()498 sp<GLConsumer> SurfaceTextureBase::getST() {
499 return mST;
500 }
501
initialize(int tex_id,EGLenum tex_target)502 void 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
deinit()510 void SurfaceTextureBase::deinit() {
511 mANW.clear();
512 mSTC.clear();
513
514 mST->abandon();
515 mST.clear();
516 }
517
getId(const char ** name)518 void 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
initialize(int display,int tex_id)531 void 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
deinit()569 void SurfaceTextureGL::deinit() {
570 SurfaceTextureBase::deinit();
571 GLSurface::deinit();
572 }
573
574 // drawTexture draws the GLConsumer over the entire GL viewport.
drawTexture()575 void 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
handleBuffer(sp<GraphicBuffer> & graphic_buffer,uint8_t * buffer,unsigned int count,const Rect & crop)622 void 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
getCrop(sp<GraphicBuffer> & graphic_buffer,const float * mtx)693 Rect 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
setInput(buffer_info_t bufinfo,const char * format,ShotParameters & params)743 void BufferSourceInput::setInput(buffer_info_t bufinfo, const char *format, ShotParameters ¶ms) {
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
showMetadata(sp<IMemory> data)851 void 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