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 61 static EGLint getSurfaceWidth() { 62 return 512; 63 } 64 65 static EGLint getSurfaceHeight() { 66 return 512; 67 } 68 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 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 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 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 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 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 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 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 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 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 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 410 EGLint const* GLSurface::getContextAttribs() { 411 static EGLint sDefaultContextAttribs[] = { 412 EGL_CONTEXT_CLIENT_VERSION, 2, 413 EGL_NONE }; 414 415 return sDefaultContextAttribs; 416 } 417 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 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 498 sp<GLConsumer> SurfaceTextureBase::getST() { 499 return mST; 500 } 501 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 510 void SurfaceTextureBase::deinit() { 511 mANW.clear(); 512 mSTC.clear(); 513 514 mST->abandon(); 515 mST.clear(); 516 } 517 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 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 569 void SurfaceTextureGL::deinit() { 570 SurfaceTextureBase::deinit(); 571 GLSurface::deinit(); 572 } 573 574 // drawTexture draws the GLConsumer over the entire GL viewport. 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 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 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 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 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