1 /* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <time.h>
34 #include <semaphore.h>
35 #include <pthread.h>
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/wait.h>
40 
41 #include <ui/DisplayInfo.h>
42 #include <gui/Surface.h>
43 #include <gui/SurfaceComposerClient.h>
44 #include <gui/ISurfaceComposer.h>
45 
46 #include <system/camera.h>
47 
48 #include <camera/Camera.h>
49 #include <camera/CameraParameters.h>
50 #include <media/mediarecorder.h>
51 
52 #include <utils/RefBase.h>
53 #include <utils/Mutex.h>
54 #include <utils/Condition.h>
55 #include <binder/IPCThreadState.h>
56 #include <binder/ProcessState.h>
57 #include <binder/IServiceManager.h>
58 #include <cutils/properties.h>
59 #include <cutils/memory.h>
60 #include <SkImageDecoder.h>
61 #include <SkImageEncoder.h>
62 #include <MediaCodec.h>
63 #include <OMX_IVCommon.h>
64 #include <foundation/AMessage.h>
65 #include <media/ICrypto.h>
66 #include <MediaMuxer.h>
67 #include <foundation/ABuffer.h>
68 #include <MediaErrors.h>
69 #include <gralloc_priv.h>
70 #include <math.h>
71 
72 #include "qcamera_test.h"
73 
74 #define ERROR(format, ...) printf( \
75     "%s[%d] : ERROR: "format"\n", __func__, __LINE__, ##__VA_ARGS__)
76 #define VIDEO_BUF_ALLIGN(size, allign) (((size) + (allign-1)) & (~(allign-1)))
77 
78 namespace qcamera {
79 
80 using namespace android;
81 
82 int CameraContext::JpegIdx = 0;
83 int CameraContext::mPiPIdx = 0;
84 SkBitmap *CameraContext::skBMtmp[2];
85 sp<IMemory> CameraContext::PiPPtrTmp[2];
86 
87 /*===========================================================================
88  * FUNCTION   : previewCallback
89  *
90  * DESCRIPTION: preview callback preview mesages are enabled
91  *
92  * PARAMETERS :
93  *   @mem : preview buffer
94  *
95  * RETURN     : None
96  *==========================================================================*/
previewCallback(const sp<IMemory> & mem)97 void CameraContext::previewCallback(const sp<IMemory>& mem)
98 {
99     printf("PREVIEW Callback 0x%x", ( unsigned int ) mem->pointer());
100     uint8_t *ptr = (uint8_t*) mem->pointer();
101     printf("PRV_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
102            ptr[0],
103            ptr[1],
104            ptr[2],
105            ptr[3],
106            ptr[4],
107            ptr[5],
108            ptr[6],
109            ptr[7],
110            ptr[8],
111            ptr[9]);
112 }
113 
114 /*===========================================================================
115  * FUNCTION   : useLock
116  *
117  * DESCRIPTION: Mutex lock for CameraContext
118  *
119  * PARAMETERS : none
120  *
121  * RETURN     : none
122  *==========================================================================*/
useLock()123 void CameraContext::useLock()
124 {
125     Mutex::Autolock l(mLock);
126     if ( mInUse ) {
127         mCond.wait(mLock);
128     } else {
129         mInUse = true;
130     }
131 }
132 
133 /*===========================================================================
134  * FUNCTION   : signalFinished
135  *
136  * DESCRIPTION: Mutex unlock CameraContext
137  *
138  * PARAMETERS : none
139  *
140  * RETURN     : none
141  *==========================================================================*/
signalFinished()142 void CameraContext::signalFinished()
143 {
144     Mutex::Autolock l(mLock);
145     mInUse = false;
146     mCond.signal();
147 }
148 
149 /*===========================================================================
150  * FUNCTION   : mutexLock
151  *
152  * DESCRIPTION: Mutex lock for ViV Video
153  *
154  * PARAMETERS : none
155  *
156  * RETURN     : none
157  *==========================================================================*/
mutexLock()158 void CameraContext::mutexLock()
159 {
160     Mutex::Autolock l(mViVLock);
161     if (mViVinUse ) {
162         mViVCond.wait(mViVLock);
163     } else {
164         mViVinUse = true;
165     }
166 }
167 
168 /*===========================================================================
169  * FUNCTION   : mutexUnLock
170  *
171  * DESCRIPTION: Mutex unlock for ViV Video
172  *
173  * PARAMETERS : none
174  *
175  * RETURN     : none
176  *==========================================================================*/
mutexUnlock()177 void CameraContext::mutexUnlock()
178 {
179     Mutex::Autolock l(mViVLock);
180     mViVinUse = false;
181     mViVCond.signal();
182 }
183 
184 
185 
186 /*===========================================================================
187  * FUNCTION   : saveFile
188  *
189  * DESCRIPTION: helper function for saving buffers on filesystem
190  *
191  * PARAMETERS :
192  *   @mem : buffer to save to filesystem
193  *   @path: File path
194  *
195  * RETURN     : status_t type of status
196  *              NO_ERROR  -- success
197  *              none-zero failure code
198  *==========================================================================*/
saveFile(const sp<IMemory> & mem,String8 path)199 status_t CameraContext::saveFile(const sp<IMemory>& mem, String8 path)
200 {
201     unsigned char *buff = NULL;
202     int size;
203     int fd = -1;
204 
205     if (mem == NULL) {
206         return BAD_VALUE;
207     }
208 
209     fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0655);
210     if(fd < 0) {
211         printf("Unable to open file %s %s\n", path.string(), strerror(fd));
212         return -errno;
213     }
214 
215     size = mem->size();
216     if (size <= 0) {
217         printf("IMemory object is of zero size\n");
218         close(fd);
219         return BAD_VALUE;
220     }
221 
222     buff = (unsigned char *)mem->pointer();
223     if (!buff) {
224         printf("Buffer pointer is invalid\n");
225         close(fd);
226         return BAD_VALUE;
227     }
228 
229     if ( size != write(fd, buff, size) ) {
230         printf("Bad Write error (%d)%s\n",
231                errno,
232                strerror(errno));
233         close(fd);
234         return INVALID_OPERATION;
235     }
236 
237     printf("%s: buffer=%08X, size=%d stored at %s\n",
238            __FUNCTION__, (int)buff, size, path.string());
239 
240     if (fd >= 0)
241         close(fd);
242 
243     return NO_ERROR;
244 }
245 
246 /*===========================================================================
247  * FUNCTION   : PiPCopyToOneFile
248  *
249  * DESCRIPTION: Copy the smaller picture to the bigger one
250  *
251  * PARAMETERS :
252  *   @bitmap0 : Decoded image buffer 0
253  *   @bitmap1 : Decoded image buffer 1
254  *
255  * RETURN     : decoded picture in picture in SkBitmap
256  *==========================================================================*/
PiPCopyToOneFile(SkBitmap * bitmap0,SkBitmap * bitmap1)257 SkBitmap * CameraContext::PiPCopyToOneFile(
258     SkBitmap *bitmap0, SkBitmap *bitmap1)
259 {
260     int size0;
261     int size1;
262     SkBitmap *src;
263     SkBitmap *dst;
264     unsigned int dstOffset;
265     unsigned int srcOffset;
266 
267     if (bitmap0 == NULL && bitmap1 == NULL) {
268         return NULL;
269     }
270 
271     size0 = bitmap0->getSize();
272     if (size0 <= 0) {
273         printf("Decoded image 0 is of zero size\n");
274         return NULL;
275     }
276 
277     size1 = bitmap1->getSize();
278         if (size1 <= 0) {
279             printf("Decoded image 1 is of zero size\n");
280             return NULL;
281         }
282 
283     if (size0 > size1) {
284         dst = bitmap0;
285         src = bitmap1;
286     } else if (size1 > size0){
287         dst = bitmap1;
288         src = bitmap0;
289     } else {
290         printf("Picture size should be with different size!\n");
291         return NULL;
292     }
293 
294     for(int i=0; i<src->height(); i++) {
295         dstOffset = i*(dst->width())*mfmtMultiplier;
296         srcOffset = i*(src->width())*mfmtMultiplier;
297         memcpy(((unsigned char *) dst->getPixels())+dstOffset,
298             ((unsigned char *) src->getPixels())+srcOffset,
299             src->width()*mfmtMultiplier);
300     }
301 
302     return dst;
303 }
304 
305 /*===========================================================================
306  * FUNCTION   : decodeJPEG
307  *
308  * DESCRIPTION: decode jpeg input buffer.
309  *
310  * PARAMETERS :
311  *   @mem : buffer to decode
312  *
313  * RETURN     : decoded picture in SkBitmap
314 
315  *==========================================================================*/
decodeJPEG(const sp<IMemory> & mem)316 SkBitmap *CameraContext::decodeJPEG(const sp<IMemory>& mem)
317 {
318     SkBitmap *skBM;
319     skBM = new SkBitmap; //Deleted in encodeJPEG (skBMtmp[0] and skBMtmp[1])
320     SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
321     const void *buff = NULL;
322     int size;
323 
324     buff = (const void *)mem->pointer();
325     size= mem->size();
326 
327     switch(prefConfig) {
328         case SkBitmap::kARGB_8888_Config:
329         {
330             mfmtMultiplier = 4;
331         }
332             break;
333 
334         case SkBitmap::kARGB_4444_Config:
335         {
336             mfmtMultiplier = 2;
337         }
338         break;
339 
340         case SkBitmap::kRGB_565_Config:
341         {
342             mfmtMultiplier = 2;
343         }
344         break;
345 
346         case SkBitmap::kIndex8_Config:
347         {
348             mfmtMultiplier = 4;
349         }
350         break;
351 
352         case SkBitmap::kA8_Config:
353         {
354             mfmtMultiplier = 4;
355         }
356         break;
357 
358         default:
359         {
360             mfmtMultiplier = 0;
361             printf("Decode format is not correct!\n");
362         }
363         break;
364     }
365 
366     if (SkImageDecoder::DecodeMemory(buff, size, skBM, prefConfig,
367             SkImageDecoder::kDecodePixels_Mode) == false) {
368         printf("%s():%d:: Failed during jpeg decode\n",__FUNCTION__,__LINE__);
369         return NULL;
370     }
371 
372     return skBM;
373 }
374 
375 /*===========================================================================
376  * FUNCTION   : encodeJPEG
377  *
378  * DESCRIPTION: encode the decoded input buffer.
379  *
380  * PARAMETERS :
381  *   @stream  : SkWStream
382  *   @bitmap  : SkBitmap decoded image to encode
383  *   @path    : File path
384  *
385  * RETURN     : status_t type of status
386  *              NO_ERROR  -- success
387  *              none-zero failure code
388 
389  *==========================================================================*/
encodeJPEG(SkWStream * stream,const SkBitmap * bitmap,String8 path)390 status_t CameraContext::encodeJPEG(SkWStream * stream,
391     const SkBitmap *bitmap, String8 path)
392 {
393     int qFactor = 100;
394     long len;
395     status_t ret;
396     unsigned char *buff;
397     unsigned char temp;
398 
399     skJpegEnc = SkImageEncoder::Create(SkImageEncoder::kJPEG_Type);
400 
401     if (skJpegEnc->encodeStream(stream, *bitmap, qFactor) == false) {
402         return BAD_VALUE;
403     }
404     printf("%s: buffer=%08X, size=%d stored at %s\n",
405         __FUNCTION__, (int)bitmap->getPixels(),
406         bitmap->getSize(), path.string());
407     delete skBMtmp[0];
408     delete skBMtmp[1];
409 
410     FILE *fh = fopen(path.string(), "r+");
411     if ( !fh ) {
412         printf("Could not open file %s\n", path.string());
413         return BAD_VALUE;
414     }
415 
416     fseek(fh, 0, SEEK_END);
417     len = ftell(fh);
418     rewind(fh);
419 
420     if( !len ) {
421         printf("File %s is empty !\n", path.string());
422         fclose(fh);
423         return BAD_VALUE;
424     }
425 
426     buff = (unsigned char*)malloc(len);
427     if (!buff) {
428         printf("Cannot allocate memory for buffer reading!\n");
429         return BAD_VALUE;
430     }
431 
432     ret = fread(buff, 1, len, fh);
433     if (ret != len) {
434         printf("Reading error\n");
435         return BAD_VALUE;
436     }
437 
438     ret = ReadSectionsFromBuffer(buff, len, READ_ALL);
439     if (ret != NO_ERROR) {
440         printf("Cannot read sections from buffer\n");
441         DiscardData();
442         DiscardSections();
443         return BAD_VALUE;
444     }
445     free(buff);
446     rewind(fh);
447 
448     temp = 0xff;
449     ret = fwrite(&temp, sizeof(unsigned char), 1, fh);
450     if (ret != 1) {
451         printf("Writing error\n");
452     }
453     temp = 0xd8;
454     fwrite(&temp, sizeof(unsigned char), 1, fh);
455 
456     for (int i=0; i<mSectionsRead; i++) {
457         switch((mSections[i].Type)) {
458 
459         case 0x123:
460             fwrite(mSections[i].Data, sizeof(unsigned char),
461                 mSections[i].Size, fh);
462             break;
463 
464         case 0xe0:
465             temp = 0xff;
466             fwrite(&temp, sizeof(unsigned char), 1, fh);
467             temp = 0xe1;
468             fwrite(&temp, sizeof(unsigned char), 1, fh);
469             fwrite(mJEXIFSection.Data, sizeof(unsigned char),
470                 mJEXIFSection.Size, fh);
471             break;
472 
473         default:
474             temp = 0xff;
475             fwrite(&temp, sizeof(unsigned char), 1, fh);
476             fwrite(&mSections[i].Type, sizeof(unsigned char), 1, fh);
477             fwrite(mSections[i].Data, sizeof(unsigned char),
478                 mSections[i].Size, fh);
479             break;
480         }
481     }
482     free(mJEXIFSection.Data);
483     DiscardData();
484     DiscardSections();
485     fclose(fh);
486 
487     ret = NO_ERROR;
488 
489     return ret;
490 }
491 
492 /*===========================================================================
493  * FUNCTION   : readSectionsFromBuffer
494  *
495  * DESCRIPTION: read all jpeg sections of input buffer.
496  *
497  * PARAMETERS :
498  *   @mem : buffer to read from Metadata Sections
499  *   @buffer_size: buffer size
500  *   @ReadMode: Read mode - all, jpeg or exif
501  *
502  * RETURN     : status_t type of status
503  *              NO_ERROR  -- success
504  *              none-zero failure code
505  *==========================================================================*/
ReadSectionsFromBuffer(unsigned char * buffer,unsigned int buffer_size,ReadMode_t ReadMode)506 status_t CameraContext::ReadSectionsFromBuffer (unsigned char *buffer,
507         unsigned int buffer_size, ReadMode_t ReadMode)
508 {
509     int a;
510     unsigned int pos = 0;
511     int HaveCom = 0;
512     mSectionsAllocated = 10;
513 
514     mSections = (Sections_t *)malloc(sizeof(Sections_t) * mSectionsAllocated);
515 
516     if (!buffer) {
517         printf("Input buffer is null\n");
518         return BAD_VALUE;
519     }
520 
521     if (buffer_size < 1) {
522         printf("Input size is 0\n");
523         return BAD_VALUE;
524     }
525 
526     a = (int) buffer[pos++];
527 
528     if (a != 0xff || buffer[pos++] != M_SOI){
529         printf("No valid image\n");
530         return BAD_VALUE;
531     }
532 
533     for(;;){
534         int itemlen;
535         int marker = 0;
536         int ll,lh;
537         unsigned char * Data;
538 
539         CheckSectionsAllocated();
540 
541         for (a = 0; a <= 16; a++){
542             marker = buffer[pos++];
543             if (marker != 0xff) break;
544 
545             if (a >= 16){
546                 fprintf(stderr,"too many padding bytes\n");
547                 return BAD_VALUE;
548             }
549         }
550 
551         mSections[mSectionsRead].Type = marker;
552 
553         // Read the length of the section.
554         lh = buffer[pos++];
555         ll = buffer[pos++];
556 
557         itemlen = (lh << 8) | ll;
558 
559         if (itemlen < 2) {
560             ALOGE("invalid marker");
561             return BAD_VALUE;
562         }
563 
564         mSections[mSectionsRead].Size = itemlen;
565 
566         Data = (unsigned char *)malloc(itemlen);
567         if (Data == NULL) {
568             ALOGE("Could not allocate memory");
569             return NO_MEMORY;
570         }
571         mSections[mSectionsRead].Data = Data;
572 
573         // Store first two pre-read bytes.
574         Data[0] = (unsigned char)lh;
575         Data[1] = (unsigned char)ll;
576 
577         if (pos+itemlen-2 > buffer_size) {
578            ALOGE("Premature end of file?");
579           return BAD_VALUE;
580         }
581 
582         memcpy(Data+2, buffer+pos, itemlen-2); // Read the whole section.
583         pos += itemlen-2;
584 
585         mSectionsRead += 1;
586 
587         switch(marker){
588 
589             case M_SOS:   // stop before hitting compressed data
590                 // If reading entire image is requested, read the rest of the
591                 // data.
592                 if (ReadMode & READ_IMAGE){
593                     int size;
594                     // Determine how much file is left.
595                     size = buffer_size - pos;
596 
597                     if (size < 1) {
598                         ALOGE("could not read the rest of the image");
599                         return BAD_VALUE;
600                     }
601                     Data = (unsigned char *)malloc(size);
602                     if (Data == NULL) {
603                         ALOGE("%d: could not allocate data for entire "
604                             "image size: %d", __LINE__, size);
605                         return BAD_VALUE;
606                     }
607 
608                     memcpy(Data, buffer+pos, size);
609 
610                     CheckSectionsAllocated();
611                     mSections[mSectionsRead].Data = Data;
612                     mSections[mSectionsRead].Size = size;
613                     mSections[mSectionsRead].Type = PSEUDO_IMAGE_MARKER;
614                     mSectionsRead ++;
615                     mHaveAll = 1;
616                 }
617                 return NO_ERROR;
618 
619             case M_EOI:   // in case it's a tables-only JPEG stream
620                 ALOGE("No image in jpeg!\n");
621                 return BAD_VALUE;
622 
623             case M_COM: // Comment section
624                 if (HaveCom || ((ReadMode & READ_METADATA) == 0)){
625                     // Discard this section.
626                     free(mSections[--mSectionsRead].Data);
627                 }
628                 break;
629 
630             case M_JFIF:
631                 // Regular jpegs always have this tag, exif images have the
632                 // exif marker instead, althogh ACDsee will write images
633                 // with both markers.
634                 // this program will re-create this marker on absence of exif
635                 // marker.
636                 // hence no need to keep the copy from the file.
637                 if (ReadMode & READ_METADATA){
638                     if (memcmp(Data+2, "JFIF", 4) == 0) {
639                         break;
640                     }
641                     free(mSections[--mSectionsRead].Data);
642                 }
643                 break;
644 
645             case M_EXIF:
646                 // There can be different section using the same marker.
647                 if (ReadMode & READ_METADATA){
648                     if (memcmp(Data+2, "Exif", 4) == 0){
649                         break;
650                     }else if (memcmp(Data+2, "http:", 5) == 0){
651                         // Change tag for internal purposes.
652                         mSections[mSectionsRead-1].Type = M_XMP;
653                         break;
654                     }
655                 }
656                 // Oterwise, discard this section.
657                 free(mSections[--mSectionsRead].Data);
658                 break;
659 
660             case M_IPTC:
661                 if (ReadMode & READ_METADATA){
662                     // Note: We just store the IPTC section.
663                     // Its relatively straightforward
664                     // and we don't act on any part of it,
665                     // so just display it at parse time.
666                 }else{
667                     free(mSections[--mSectionsRead].Data);
668                 }
669                 break;
670 
671             case M_SOF0:
672             case M_SOF1:
673             case M_SOF2:
674             case M_SOF3:
675             case M_SOF5:
676             case M_SOF6:
677             case M_SOF7:
678             case M_SOF9:
679             case M_SOF10:
680             case M_SOF11:
681             case M_SOF13:
682             case M_SOF14:
683             case M_SOF15:
684                 break;
685             default:
686                 // Skip any other sections.
687                 break;
688         }
689     }
690     return NO_ERROR;
691 }
692 
693 /*===========================================================================
694  * FUNCTION   : CheckSectionsAllocated
695  *
696  * DESCRIPTION: Check allocated jpeg sections.
697  *
698  * PARAMETERS : none
699  *
700  * RETURN     : none
701 
702  *==========================================================================*/
CheckSectionsAllocated(void)703 void CameraContext::CheckSectionsAllocated(void)
704 {
705     if (mSectionsRead > mSectionsAllocated){
706         ALOGE("allocation screw up");
707     }
708     if (mSectionsRead >= mSectionsAllocated){
709         mSectionsAllocated += mSectionsAllocated +1;
710         mSections = (Sections_t *)realloc(mSections,
711             sizeof(Sections_t) * mSectionsAllocated);
712         if (mSections == NULL){
713             ALOGE("could not allocate data for entire image");
714         }
715     }
716 }
717 
718 /*===========================================================================
719  * FUNCTION   : findSection
720  *
721  * DESCRIPTION: find the desired Section of the JPEG buffer.
722  *
723  * PARAMETERS :
724  *  @SectionType: Section type
725  *
726  * RETURN     : return the found section
727 
728  *==========================================================================*/
FindSection(int SectionType)729 CameraContext::Sections_t *CameraContext::FindSection(int SectionType)
730 {
731     int a;
732 
733     for (a = 0; a < mSectionsRead; a++){
734         if (mSections[a].Type == SectionType){
735             return &mSections[a];
736         }
737     }
738     // Could not be found.
739     return NULL;
740 }
741 
742 
743 /*===========================================================================
744  * FUNCTION   : DiscardData
745  *
746  * DESCRIPTION: DiscardData
747  *
748  * PARAMETERS : none
749  *
750  * RETURN     : none
751 
752  *==========================================================================*/
DiscardData()753 void CameraContext::DiscardData()
754 {
755     int a;
756 
757     for (a = 0; a < mSectionsRead; a++){
758         free(mSections[a].Data);
759     }
760 
761     mSectionsRead = 0;
762     mHaveAll = 0;
763 }
764 
765 /*===========================================================================
766  * FUNCTION   : DiscardSections
767  *
768  * DESCRIPTION: Discard allocated sections
769  *
770  * PARAMETERS : none
771  *
772  * RETURN     : none
773 
774  *==========================================================================*/
DiscardSections()775 void CameraContext::DiscardSections()
776 {
777     free(mSections);
778     mSectionsAllocated = 0;
779     mHaveAll = 0;
780 }
781 
782 /*===========================================================================
783  * FUNCTION   : notify
784  *
785  * DESCRIPTION: notify callback
786  *
787  * PARAMETERS :
788  *   @msgType : type of callback
789  *   @ext1: extended parameters
790  *   @ext2: extended parameters
791  *
792  * RETURN     : None
793  *==========================================================================*/
notify(int32_t msgType,int32_t ext1,int32_t ext2)794 void CameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
795 {
796     printf("Notify cb: %d %d %d\n", msgType, ext1, ext2);
797 
798     if (( msgType & CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) {
799         int fd = dup(ext2);
800         printf("notify Preview Frame fd: %d dup fd: %d\n", ext2, fd);
801         close(fd);
802     }
803 
804     if ( msgType & CAMERA_MSG_FOCUS ) {
805         printf("AutoFocus %s \n",
806                (ext1) ? "OK" : "FAIL");
807     }
808 
809     if ( msgType & CAMERA_MSG_SHUTTER ) {
810         printf("Shutter done \n");
811     }
812 
813     if ( msgType & CAMERA_MSG_ERROR) {
814         printf("Camera Test CAMERA_MSG_ERROR\n");
815         stopPreview();
816         closeCamera();
817     }
818 }
819 
820 /*===========================================================================
821  * FUNCTION   : postData
822  *
823  * DESCRIPTION: handles data callbacks
824  *
825  * PARAMETERS :
826  *   @msgType : type of callback
827  *   @dataPtr: buffer data
828  *   @metadata: additional metadata where available
829  *
830  * RETURN     : None
831  *==========================================================================*/
postData(int32_t msgType,const sp<IMemory> & dataPtr,camera_frame_metadata_t * metadata)832 void CameraContext::postData(int32_t msgType,
833                              const sp<IMemory>& dataPtr,
834                              camera_frame_metadata_t *metadata)
835 {
836     Size currentPictureSize = mSupportedPictureSizes.itemAt(
837         mCurrentPictureSizeIdx);
838     unsigned char *buff = NULL;
839     int size;
840     status_t ret = 0;
841 
842     memset(&mJEXIFSection, 0, sizeof(mJEXIFSection)),
843 
844     printf("Data cb: %d\n", msgType);
845 
846     if ( msgType & CAMERA_MSG_PREVIEW_FRAME ) {
847         previewCallback(dataPtr);
848     }
849 
850     if ( msgType & CAMERA_MSG_RAW_IMAGE ) {
851         printf("RAW done \n");
852     }
853 
854     if (msgType & CAMERA_MSG_POSTVIEW_FRAME) {
855         printf("Postview frame \n");
856     }
857 
858     if (msgType & CAMERA_MSG_COMPRESSED_IMAGE ) {
859         String8 jpegPath;
860         jpegPath = jpegPath.format("/sdcard/img_%d.jpg", JpegIdx);
861         if (!mPiPCapture) {
862             // Normal capture case
863             printf("JPEG done\n");
864             saveFile(dataPtr, jpegPath);
865             JpegIdx++;
866         } else {
867             // PiP capture case
868             SkFILEWStream *wStream;
869             skBMtmp[mPiPIdx] = decodeJPEG(dataPtr);
870 
871             mWidthTmp[mPiPIdx] = currentPictureSize.width;
872             mHeightTmp[mPiPIdx] = currentPictureSize.height;
873             PiPPtrTmp[mPiPIdx] = dataPtr;
874             // If there are two jpeg buffers
875             if (mPiPIdx == 1) {
876                 printf("PiP done\n");
877 
878                 // Find the the capture with higher width and height and read
879                 // its jpeg sections
880                 if ((mWidthTmp[0]*mHeightTmp[0]) >
881                         (mWidthTmp[1]*mHeightTmp[1])) {
882                     buff = (unsigned char *)PiPPtrTmp[0]->pointer();
883                     size = PiPPtrTmp[0]->size();
884                 } else if ((mWidthTmp[0]*mHeightTmp[0]) <
885                         (mWidthTmp[1]*mHeightTmp[1])) {
886                     buff = (unsigned char *)PiPPtrTmp[1]->pointer();
887                     size = PiPPtrTmp[1]->size();
888                 } else {
889                     printf("Cannot take PiP. Images are with the same width"
890                             " and height size!!!\n");
891                     return;
892                 }
893 
894                 if (buff != NULL && size != 0) {
895                     ret = ReadSectionsFromBuffer(buff, size, READ_ALL);
896                     if (ret != NO_ERROR) {
897                         printf("Cannot read sections from buffer\n");
898                         DiscardData();
899                         DiscardSections();
900                         return;
901                     }
902 
903                     mJEXIFTmp = FindSection(M_EXIF);
904                     mJEXIFSection = *mJEXIFTmp;
905                     mJEXIFSection.Data =
906                         (unsigned char*)malloc(mJEXIFTmp->Size);
907                     memcpy(mJEXIFSection.Data,
908                         mJEXIFTmp->Data, mJEXIFTmp->Size);
909                     DiscardData();
910                     DiscardSections();
911 
912                     wStream = new SkFILEWStream(jpegPath.string());
913                     skBMDec = PiPCopyToOneFile(skBMtmp[0], skBMtmp[1]);
914                     if (encodeJPEG(wStream, skBMDec, jpegPath) != false) {
915                         printf("%s():%d:: Failed during jpeg encode\n",
916                             __FUNCTION__,__LINE__);
917                         return;
918                     }
919                     mPiPIdx = 0;
920                     JpegIdx++;
921                     delete wStream;
922                 }
923             } else {
924                 mPiPIdx++;
925             }
926             disablePiPCapture();
927         }
928     }
929 
930     if ( ( msgType & CAMERA_MSG_PREVIEW_METADATA ) &&
931          ( NULL != metadata ) ) {
932         printf("Face detected %d \n", metadata->number_of_faces);
933     }
934 
935     signalFinished();
936 }
937 
938 /*===========================================================================
939  * FUNCTION   : postDataTimestamp
940  *
941  * DESCRIPTION: handles recording callbacks
942  *
943  * PARAMETERS :
944  *   @timestamp : timestamp of buffer
945  *   @msgType : type of buffer
946  *   @dataPtr : buffer data
947  *
948  * RETURN     : None
949  *==========================================================================*/
postDataTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr)950 void CameraContext::postDataTimestamp(nsecs_t timestamp,
951                                       int32_t msgType,
952                                       const sp<IMemory>& dataPtr)
953 {
954     printf("Recording cb: %d %lld %p\n", msgType, timestamp, dataPtr.get());
955 }
956 
postRecordingFrameHandleTimestamp(nsecs_t,native_handle_t *)957 void CameraContext::postRecordingFrameHandleTimestamp(nsecs_t, native_handle_t*) {
958 }
959 
recordingFrameHandleCallbackTimestamp(nsecs_t,native_handle_t *)960 void CameraContext::recordingFrameHandleCallbackTimestamp(nsecs_t, native_handle_t*) {
961 }
962 
963 /*===========================================================================
964  * FUNCTION   : dataCallbackTimestamp
965  *
966  * DESCRIPTION: handles recording callbacks. Used for ViV recording
967  *
968  * PARAMETERS :
969  *   @timestamp : timestamp of buffer
970  *   @msgType : type of buffer
971  *   @dataPtr : buffer data
972  *
973  * RETURN     : None
974  *==========================================================================*/
dataCallbackTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr)975 void CameraContext::dataCallbackTimestamp(nsecs_t timestamp,
976         int32_t msgType,
977         const sp<IMemory>& dataPtr)
978 {
979     mutexLock();
980     // Not needed check. Just avoiding warnings of not used variables.
981     if (timestamp > 0)
982         timestamp = 0;
983     // Not needed check. Just avoiding warnings of not used variables.
984     if (msgType > 0)
985         msgType = 0;
986     int i = 0;
987     void * srcBuff = NULL;
988     void * dstBuff = NULL;
989 
990     size_t srcYStride = 0, dstYStride = 0;
991     size_t srcUVStride = 0, dstUVStride = 0;
992     size_t srcYScanLines = 0, dstYScanLines = 0;
993     size_t srcUVScanLines = 0, dstUVScanLines = 0;
994     size_t srcOffset = 0, dstOffset = 0;
995     size_t srcBaseOffset = 0;
996     size_t dstBaseOffset = 0;
997     Size currentVideoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
998     status_t err = NO_ERROR;
999     ANativeWindowBuffer* anb = NULL;
1000 
1001     dstBuff = (void *) dataPtr->pointer();
1002 
1003     if (mCameraIndex == mInterpr->mViVVid.sourceCameraID) {
1004         srcYStride = calcStride(currentVideoSize.width);
1005         srcUVStride = calcStride(currentVideoSize.width);
1006         srcYScanLines = calcYScanLines(currentVideoSize.height);
1007         srcUVScanLines = calcUVScanLines(currentVideoSize.height);
1008         mInterpr->mViVBuff.srcWidth = currentVideoSize.width;
1009         mInterpr->mViVBuff.srcHeight = currentVideoSize.height;
1010 
1011 
1012         mInterpr->mViVBuff.YStride = srcYStride;
1013         mInterpr->mViVBuff.UVStride = srcUVStride;
1014         mInterpr->mViVBuff.YScanLines = srcYScanLines;
1015         mInterpr->mViVBuff.UVScanLines = srcUVScanLines;
1016 
1017         memcpy( mInterpr->mViVBuff.buff, (void *) dataPtr->pointer(),
1018             mInterpr->mViVBuff.buffSize);
1019 
1020         mInterpr->mViVVid.isBuffValid = true;
1021     } else if (mCameraIndex == mInterpr->mViVVid.destinationCameraID) {
1022         if(mInterpr->mViVVid.isBuffValid == true) {
1023             dstYStride = calcStride(currentVideoSize.width);
1024             dstUVStride = calcStride(currentVideoSize.width);
1025             dstYScanLines = calcYScanLines(currentVideoSize.height);
1026             dstUVScanLines = calcUVScanLines(currentVideoSize.height);
1027 
1028             srcYStride = mInterpr->mViVBuff.YStride;
1029             srcUVStride = mInterpr->mViVBuff.UVStride;
1030             srcYScanLines = mInterpr->mViVBuff.YScanLines;
1031             srcUVScanLines = mInterpr->mViVBuff.UVScanLines;
1032 
1033 
1034             for (i=0; i<(int) mInterpr->mViVBuff.srcHeight; i++) {
1035                 srcOffset = i*srcYStride;
1036                 dstOffset = i*dstYStride;
1037                 memcpy((unsigned char *) dstBuff + dstOffset,
1038                     (unsigned char *) mInterpr->mViVBuff.buff +
1039                     srcOffset, mInterpr->mViVBuff.srcWidth);
1040             }
1041             srcBaseOffset = srcYStride * srcYScanLines;
1042             dstBaseOffset = dstYStride * dstYScanLines;
1043             for (i=0;i<(int) mInterpr->mViVBuff.srcHeight/2;i++) {
1044                 srcOffset = i*srcUVStride + srcBaseOffset;
1045                 dstOffset = i*dstUVStride + dstBaseOffset;
1046                 memcpy((unsigned char *) dstBuff + dstOffset,
1047                     (unsigned char *) mInterpr->mViVBuff.buff +
1048                     srcOffset, mInterpr->mViVBuff.srcWidth);
1049             }
1050 
1051             err = native_window_dequeue_buffer_and_wait(
1052                 mInterpr->mViVVid.ANW.get(),&anb);
1053             if (err != NO_ERROR) {
1054                 printf("Cannot dequeue anb for sensor %d!!!\n", mCameraIndex);
1055                 return;
1056             }
1057             mInterpr->mViVVid.graphBuf = new GraphicBuffer(anb, false);
1058             if(NULL == mInterpr->mViVVid.graphBuf.get()) {
1059                 printf("Invalid Graphic buffer\n");
1060                 return;
1061             }
1062             err = mInterpr->mViVVid.graphBuf->lock(
1063                 GRALLOC_USAGE_SW_WRITE_OFTEN,
1064                 (void**)(&mInterpr->mViVVid.mappedBuff));
1065             if (err != NO_ERROR) {
1066                 printf("Graphic buffer could not be locked %d!!!\n", err);
1067                 return;
1068             }
1069 
1070             srcYStride = dstYStride;
1071             srcUVStride = dstUVStride;
1072             srcYScanLines = dstYScanLines;
1073             srcUVScanLines = dstUVScanLines;
1074             srcBuff = dstBuff;
1075 
1076             for (i=0; i<(int) currentVideoSize.height; i++) {
1077                 srcOffset = i*srcYStride;
1078                 dstOffset = i*dstYStride;
1079                 memcpy((unsigned char *) mInterpr->mViVVid.mappedBuff +
1080                     dstOffset, (unsigned char *) srcBuff +
1081                     srcOffset, currentVideoSize.width);
1082             }
1083 
1084             srcBaseOffset = srcYStride * srcYScanLines;
1085             dstBaseOffset = dstUVStride * currentVideoSize.height;
1086 
1087             for (i=0;i<(int) currentVideoSize.height/2;i++) {
1088                 srcOffset = i*srcUVStride + srcBaseOffset;
1089                 dstOffset = i*dstUVStride + dstBaseOffset;
1090                 memcpy((unsigned char *) mInterpr->mViVVid.mappedBuff +
1091                     dstOffset, (unsigned char *) srcBuff +
1092                     srcOffset, currentVideoSize.width);
1093             }
1094 
1095 
1096             mInterpr->mViVVid.graphBuf->unlock();
1097 
1098             err = mInterpr->mViVVid.ANW->queueBuffer(
1099                 mInterpr->mViVVid.ANW.get(), anb, -1);
1100             if(err)
1101                 printf("Failed to enqueue buffer to recorder!!!\n");
1102         }
1103     }
1104     mCamera->releaseRecordingFrame(dataPtr);
1105 
1106     mutexUnlock();
1107 }
1108 
1109 /*===========================================================================
1110  * FUNCTION   : ViVEncoderThread
1111  *
1112  * DESCRIPTION: Creates a separate thread for ViV recording
1113  *
1114  * PARAMETERS : None
1115  *
1116  * RETURN     : None
1117  *==========================================================================*/
ViVEncoderThread()1118 status_t Interpreter::ViVEncoderThread()
1119 {
1120     int ret = NO_ERROR;
1121     pthread_attr_t attr;
1122     pthread_attr_init(&attr);
1123 
1124     ret = pthread_create(&mViVEncThread, &attr, ThreadWrapper, this);
1125     ret = pthread_attr_destroy(&attr);
1126 
1127     return ret;
1128 }
1129 
1130 /*===========================================================================
1131  * FUNCTION   : ThreadWrapper
1132  *
1133  * DESCRIPTION: Helper function for for ViV recording thread
1134  *
1135  * PARAMETERS : Interpreter context
1136  *
1137  * RETURN     : None
1138  *==========================================================================*/
ThreadWrapper(void * context)1139 void *Interpreter::ThreadWrapper(void *context) {
1140     Interpreter *writer = static_cast<Interpreter *>(context);
1141     writer->ViVEncode();
1142     return NULL;
1143 }
1144 
1145 /*===========================================================================
1146  * FUNCTION   : ViVEncode
1147  *
1148  * DESCRIPTION: Thread for ViV encode. Buffers from video codec are sent to
1149  *              muxer and saved in a file.
1150  *
1151  * PARAMETERS : Interpreter context
1152  *
1153  * RETURN     : None
1154  *==========================================================================*/
ViVEncode()1155 void Interpreter::ViVEncode()
1156 {
1157     status_t err = NO_ERROR;
1158     ssize_t trackIdx = -1;
1159     uint32_t debugNumFrames = 0;
1160 
1161     size_t bufIndex, offset, size;
1162     int64_t ptsUsec;
1163     uint32_t flags;
1164     bool DoRecording = true;
1165 
1166 
1167     err = mTestContext->mViVVid.codec->getOutputBuffers(
1168         &mTestContext->mViVVid.buffers);
1169     if (err != NO_ERROR) {
1170         printf("Unable to get output buffers (err=%d)\n", err);
1171     }
1172 
1173     while (DoRecording) {
1174         err = mTestContext->mViVVid.codec->dequeueOutputBuffer(
1175             &bufIndex,
1176             &offset,
1177             &size,
1178             &ptsUsec,
1179             &flags, -1);
1180 
1181         switch (err) {
1182 
1183         case NO_ERROR:
1184             // got a buffer
1185             if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) {
1186                 // ignore this -- we passed the CSD into MediaMuxer when
1187                 // we got the format change notification
1188                 size = 0;
1189             }
1190             if (size != 0) {
1191                 // If the virtual display isn't providing us with timestamps,
1192                 // use the current time.
1193                 if (ptsUsec == 0) {
1194                     ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000;
1195                 }
1196 
1197                 // The MediaMuxer docs are unclear, but it appears that we
1198                 // need to pass either the full set of BufferInfo flags, or
1199                 // (flags & BUFFER_FLAG_SYNCFRAME).
1200                 err = mTestContext->mViVVid.muxer->writeSampleData(
1201                     mTestContext->mViVVid.buffers[bufIndex],
1202                     trackIdx,
1203                     ptsUsec,
1204                     flags);
1205                 if (err != NO_ERROR) {
1206                     fprintf(stderr, "Failed writing data to muxer (err=%d)\n",
1207                             err);
1208                 }
1209                 debugNumFrames++;
1210             }
1211             err = mTestContext->mViVVid.codec->releaseOutputBuffer(bufIndex);
1212             if (err != NO_ERROR) {
1213                 fprintf(stderr, "Unable to release output buffer (err=%d)\n",
1214                         err);
1215             }
1216             if ((flags & MediaCodec::BUFFER_FLAG_EOS) != 0) {
1217                 // Not expecting EOS from SurfaceFlinger.  Go with it.
1218                 printf("Received end-of-stream\n");
1219                 //DoRecording = false;
1220             }
1221             break;
1222         case -EAGAIN:                       // INFO_TRY_AGAIN_LATER
1223             ALOGV("Got -EAGAIN, looping");
1224             break;
1225         case INFO_FORMAT_CHANGED:           // INFO_OUTPUT_FORMAT_CHANGED
1226         {
1227             // format includes CSD, which we must provide to muxer
1228             sp<AMessage> newFormat;
1229             mTestContext->mViVVid.codec->getOutputFormat(&newFormat);
1230             trackIdx = mTestContext->mViVVid.muxer->addTrack(newFormat);
1231             err = mTestContext->mViVVid.muxer->start();
1232             if (err != NO_ERROR) {
1233                 printf("Unable to start muxer (err=%d)\n", err);
1234             }
1235         }
1236         break;
1237         case INFO_OUTPUT_BUFFERS_CHANGED:   // INFO_OUTPUT_BUFFERS_CHANGED
1238             // not expected for an encoder; handle it anyway
1239             ALOGV("Encoder buffers changed");
1240             err = mTestContext->mViVVid.codec->getOutputBuffers(
1241                 &mTestContext->mViVVid.buffers);
1242             if (err != NO_ERROR) {
1243                 printf("Unable to get new output buffers (err=%d)\n", err);
1244             }
1245         break;
1246         case INVALID_OPERATION:
1247             DoRecording = false;
1248         break;
1249         default:
1250             printf("Got weird result %d from dequeueOutputBuffer\n", err);
1251         break;
1252         }
1253     }
1254 
1255     return;
1256 }
1257 
1258 
1259 /*===========================================================================
1260  * FUNCTION   : calcBufferSize
1261  *
1262  * DESCRIPTION: Temp buffer size calculation. Temp buffer is used to store
1263  *              the buffer from the camera with smaller resolution. It is
1264  *              copied to the buffer from camera with higher resolution.
1265  *
1266  * PARAMETERS :
1267  *   @width   : video size width
1268  *   @height  : video size height
1269  *
1270  * RETURN     : size_t
1271  *==========================================================================*/
calcBufferSize(int width,int height)1272 size_t CameraContext::calcBufferSize(int width, int height)
1273 {
1274     size_t size = 0;
1275     size_t UVAlignment;
1276     size_t YPlane, UVPlane, YStride, UVStride, YScanlines, UVScanlines;
1277     if (!width || !height) {
1278         return size;
1279     }
1280     UVAlignment = 4096;
1281     YStride = calcStride(width);
1282     UVStride = calcStride(width);
1283     YScanlines = calcYScanLines(height);
1284     UVScanlines = calcUVScanLines(height);
1285     YPlane = YStride * YScanlines;
1286     UVPlane = UVStride * UVScanlines + UVAlignment;
1287     size = YPlane + UVPlane;
1288     size = VIDEO_BUF_ALLIGN(size, 4096);
1289 
1290     return size;
1291 }
1292 
1293 /*===========================================================================
1294  * FUNCTION   : calcStride
1295  *
1296  * DESCRIPTION: Temp buffer stride calculation.
1297  *
1298  * PARAMETERS :
1299  *   @width   : video size width
1300  *
1301  * RETURN     : size_t
1302  *==========================================================================*/
calcStride(int width)1303 size_t CameraContext::calcStride(int width)
1304 {
1305     size_t alignment, stride = 0;
1306     if (!width) {
1307         return stride;
1308     }
1309     alignment = 128;
1310     stride = VIDEO_BUF_ALLIGN(width, alignment);
1311 
1312     return stride;
1313 }
1314 
1315 /*===========================================================================
1316  * FUNCTION   : calcYScanLines
1317  *
1318  * DESCRIPTION: Temp buffer scanlines calculation for Y plane.
1319  *
1320  * PARAMETERS :
1321  *   @width   : video size height
1322  *
1323  * RETURN     : size_t
1324  *==========================================================================*/
calcYScanLines(int height)1325 size_t CameraContext::calcYScanLines(int height)
1326 {
1327     size_t alignment, scanlines = 0;
1328         if (!height) {
1329             return scanlines;
1330         }
1331     alignment = 32;
1332     scanlines = VIDEO_BUF_ALLIGN(height, alignment);
1333 
1334     return scanlines;
1335 }
1336 
1337 /*===========================================================================
1338  * FUNCTION   : calcUVScanLines
1339  *
1340  * DESCRIPTION: Temp buffer scanlines calculation for UV plane.
1341  *
1342  * PARAMETERS :
1343  *   @width   : video size height
1344  *
1345  * RETURN     : size_t
1346  *==========================================================================*/
calcUVScanLines(int height)1347 size_t CameraContext::calcUVScanLines(int height)
1348 {
1349     size_t alignment, scanlines = 0;
1350     if (!height) {
1351         return scanlines;
1352     }
1353     alignment = 16;
1354     scanlines = VIDEO_BUF_ALLIGN(((height + 1) >> 1), alignment);
1355 
1356     return scanlines;
1357 }
1358 
1359 /*===========================================================================
1360  * FUNCTION   : printSupportedParams
1361  *
1362  * DESCRIPTION: dump common supported parameters
1363  *
1364  * PARAMETERS : None
1365  *
1366  * RETURN     : None
1367  *==========================================================================*/
printSupportedParams()1368 void CameraContext::printSupportedParams()
1369 {
1370     printf("\n\r\tSupported Cameras: %s",
1371            mParams.get("camera-indexes")?
1372                mParams.get("camera-indexes") : "NULL");
1373     printf("\n\r\tSupported Picture Sizes: %s",
1374            mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES)?
1375            mParams.get(
1376                CameraParameters::KEY_SUPPORTED_PICTURE_SIZES) : "NULL");
1377     printf("\n\r\tSupported Picture Formats: %s",
1378            mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS)?
1379            mParams.get(
1380                CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS) : "NULL");
1381     printf("\n\r\tSupported Preview Sizes: %s",
1382            mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES)?
1383            mParams.get(
1384                CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES) : "NULL");
1385     printf("\n\r\tSupported Video Sizes: %s",
1386             mParams.get(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES)?
1387             mParams.get(
1388                CameraParameters::KEY_SUPPORTED_VIDEO_SIZES) : "NULL");
1389     printf("\n\r\tSupported Preview Formats: %s",
1390            mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS)?
1391            mParams.get(
1392                CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS) : "NULL");
1393     printf("\n\r\tSupported Preview Frame Rates: %s",
1394            mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)?
1395            mParams.get(
1396                CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES) : "NULL");
1397     printf("\n\r\tSupported Thumbnail Sizes: %s",
1398            mParams.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES)?
1399            mParams.get(
1400                CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES) : "NULL");
1401     printf("\n\r\tSupported Whitebalance Modes: %s",
1402            mParams.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE)?
1403            mParams.get(
1404                CameraParameters::KEY_SUPPORTED_WHITE_BALANCE) : "NULL");
1405     printf("\n\r\tSupported Effects: %s",
1406            mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS)?
1407            mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS) : "NULL");
1408     printf("\n\r\tSupported Scene Modes: %s",
1409            mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES)?
1410            mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES) : "NULL");
1411     printf("\n\r\tSupported Focus Modes: %s",
1412            mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES)?
1413            mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES) : "NULL");
1414     printf("\n\r\tSupported Antibanding Options: %s",
1415            mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING)?
1416            mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING) : "NULL");
1417     printf("\n\r\tSupported Flash Modes: %s",
1418            mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES)?
1419            mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES) : "NULL");
1420     printf("\n\r\tSupported Focus Areas: %d",
1421            mParams.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
1422     printf("\n\r\tSupported FPS ranges : %s",
1423            mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)?
1424            mParams.get(
1425                CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE) : "NULL");
1426     printf("\n\r\tFocus Distances: %s \n",
1427            mParams.get(CameraParameters::KEY_FOCUS_DISTANCES)?
1428            mParams.get(CameraParameters::KEY_FOCUS_DISTANCES) : "NULL");
1429 }
1430 
1431 /*===========================================================================
1432  * FUNCTION   : createPreviewSurface
1433  *
1434  * DESCRIPTION: helper function for creating preview surfaces
1435  *
1436  * PARAMETERS :
1437  *   @width : preview width
1438  *   @height: preview height
1439  *   @pixFormat : surface pixelformat
1440  *
1441  * RETURN     : status_t type of status
1442  *              NO_ERROR  -- success
1443  *              none-zero failure code
1444  *==========================================================================*/
createPreviewSurface(unsigned int width,unsigned int height,int32_t pixFormat)1445 status_t CameraContext::createPreviewSurface(unsigned int width,
1446                                              unsigned int height,
1447                                              int32_t pixFormat)
1448 {
1449     int ret = NO_ERROR;
1450     DisplayInfo dinfo;
1451     sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
1452                         ISurfaceComposer::eDisplayIdMain));
1453     SurfaceComposerClient::getDisplayInfo(display, &dinfo);
1454     unsigned int previewWidth, previewHeight;
1455 
1456     if ( dinfo.w < width ) {
1457         previewWidth = dinfo.w;
1458     } else {
1459         previewWidth = width;
1460     }
1461 
1462     if ( dinfo.h < height ) {
1463         previewHeight = dinfo.h;
1464     } else {
1465         previewHeight = height;
1466     }
1467 
1468     mClient = new SurfaceComposerClient();
1469 
1470     if ( NULL == mClient.get() ) {
1471         printf("Unable to establish connection to Surface Composer \n");
1472         return NO_INIT;
1473     }
1474 
1475     mSurfaceControl = mClient->createSurface(String8("QCamera_Test"),
1476                                              previewWidth,
1477                                              previewHeight,
1478                                              pixFormat,
1479                                              0);
1480     if ( NULL == mSurfaceControl.get() ) {
1481         printf("Unable to create preview surface \n");
1482         return NO_INIT;
1483     }
1484 
1485     mPreviewSurface = mSurfaceControl->getSurface();
1486     if ( NULL != mPreviewSurface.get() ) {
1487         mClient->openGlobalTransaction();
1488         ret |= mSurfaceControl->setLayer(0x7fffffff);
1489         if ( mCameraIndex == 0 )
1490             ret |= mSurfaceControl->setPosition(0, 0);
1491         else
1492             ret |= mSurfaceControl->setPosition(
1493                 dinfo.w - previewWidth, dinfo.h - previewHeight);
1494 
1495         ret |= mSurfaceControl->setSize(previewWidth, previewHeight);
1496         ret |= mSurfaceControl->show();
1497         mClient->closeGlobalTransaction();
1498 
1499         if ( NO_ERROR != ret ) {
1500             printf("Preview surface configuration failed! \n");
1501         }
1502     } else {
1503         ret = NO_INIT;
1504     }
1505 
1506     return ret;
1507 }
1508 
1509 /*===========================================================================
1510  * FUNCTION   : destroyPreviewSurface
1511  *
1512  * DESCRIPTION: closes previously open preview surface
1513  *
1514  * PARAMETERS : None
1515  *
1516  * RETURN     : status_t type of status
1517  *              NO_ERROR  -- success
1518  *              none-zero failure code
1519  *==========================================================================*/
destroyPreviewSurface()1520 status_t CameraContext::destroyPreviewSurface()
1521 {
1522     if ( NULL != mPreviewSurface.get() ) {
1523         mPreviewSurface.clear();
1524     }
1525 
1526     if ( NULL != mSurfaceControl.get() ) {
1527         mSurfaceControl->clear();
1528         mSurfaceControl.clear();
1529     }
1530 
1531     if ( NULL != mClient.get() ) {
1532         mClient->dispose();
1533         mClient.clear();
1534     }
1535 
1536     return NO_ERROR;
1537 }
1538 
1539 /*===========================================================================
1540  * FUNCTION   : CameraContext
1541  *
1542  * DESCRIPTION: camera context constructor
1543  *
1544  * PARAMETERS : None
1545  *
1546  * RETURN     : None
1547  *==========================================================================*/
CameraContext(int cameraIndex)1548 CameraContext::CameraContext(int cameraIndex) :
1549     mCameraIndex(cameraIndex),
1550     mResizePreview(true),
1551     mHardwareActive(false),
1552     mPreviewRunning(false),
1553     mRecordRunning(false),
1554     mVideoFd(-1),
1555     mVideoIdx(0),
1556     mRecordingHint(false),
1557     mDoPrintMenu(true),
1558     mPiPCapture(false),
1559     mfmtMultiplier(1),
1560     mSectionsRead(false),
1561     mSectionsAllocated(false),
1562     mSections(NULL),
1563     mJEXIFTmp(NULL),
1564     mHaveAll(false),
1565     mViVinUse(false),
1566     mCamera(NULL),
1567     mClient(NULL),
1568     mSurfaceControl(NULL),
1569     mPreviewSurface(NULL),
1570     mInUse(false)
1571 {
1572     mRecorder = new MediaRecorder();
1573 }
1574 
1575 /*===========================================================================
1576  * FUNCTION     : setTestCtxInstance
1577  *
1578  * DESCRIPTION  : Sends TestContext instance to CameraContext
1579  *
1580  * PARAMETERS   :
1581  *    @instance : TestContext instance
1582  *
1583  * RETURN     : None
1584  *==========================================================================*/
setTestCtxInstance(TestContext * instance)1585 void CameraContext::setTestCtxInstance(TestContext  *instance)
1586 {
1587     mInterpr = instance;
1588 }
1589 
1590 /*===========================================================================
1591  * FUNCTION     : setTestCtxInst
1592  *
1593  * DESCRIPTION  : Sends TestContext instance to Interpreter
1594  *
1595  * PARAMETERS   :
1596  *    @instance : TestContext instance
1597  *
1598  * RETURN     : None
1599  *==========================================================================*/
setTestCtxInst(TestContext * instance)1600 void Interpreter::setTestCtxInst(TestContext  *instance)
1601 {
1602     mTestContext = instance;
1603 }
1604 
1605 /*===========================================================================
1606  * FUNCTION   : ~CameraContext
1607  *
1608  * DESCRIPTION: camera context destructor
1609  *
1610  * PARAMETERS : None
1611  *
1612  * RETURN     : None
1613  *==========================================================================*/
~CameraContext()1614 CameraContext::~CameraContext()
1615 {
1616     stopPreview();
1617     closeCamera();
1618 }
1619 
1620 /*===========================================================================
1621  * FUNCTION   : openCamera
1622  *
1623  * DESCRIPTION: connects to and initializes camera
1624  *
1625  * PARAMETERS : None
1626  *
1627  * RETURN     : status_t type of status
1628  *              NO_ERROR  -- success
1629  *              none-zero failure code
1630  *==========================================================================*/
openCamera()1631 status_t  CameraContext::openCamera()
1632 {
1633     useLock();
1634 
1635     if ( NULL != mCamera.get() ) {
1636         printf("Camera already open! \n");
1637         return NO_ERROR;
1638     }
1639 
1640     printf("openCamera(camera_index=%d)\n", mCameraIndex);
1641 
1642 #ifndef USE_JB_MR1
1643 
1644     String16 packageName("CameraTest");
1645 
1646     mCamera = Camera::connect(mCameraIndex,
1647                               packageName,
1648                               Camera::USE_CALLING_UID);
1649 
1650 #else
1651 
1652     mCamera = Camera::connect(mCameraIndex);
1653 
1654 #endif
1655 
1656     if ( NULL == mCamera.get() ) {
1657         printf("Unable to connect to CameraService\n");
1658         return NO_INIT;
1659     }
1660 
1661     mParams = mCamera->getParameters();
1662     mParams.getSupportedPreviewSizes(mSupportedPreviewSizes);
1663     mParams.getSupportedPictureSizes(mSupportedPictureSizes);
1664     mParams.getSupportedVideoSizes(mSupportedVideoSizes);
1665 
1666     mCurrentPictureSizeIdx = mSupportedPictureSizes.size() / 2;
1667     mCurrentPreviewSizeIdx = mSupportedPreviewSizes.size() / 2;
1668     mCurrentVideoSizeIdx   = mSupportedVideoSizes.size() / 2;
1669 
1670     mCamera->setListener(this);
1671     mHardwareActive = true;
1672 
1673     mInterpr->setViVSize((Size) mSupportedVideoSizes.itemAt(
1674         mCurrentVideoSizeIdx),
1675         mCameraIndex);
1676 
1677     signalFinished();
1678 
1679     return NO_ERROR;
1680 }
1681 
1682 /*===========================================================================
1683  * FUNCTION   : onAsBinder
1684  *
1685  * DESCRIPTION: onAsBinder
1686  *
1687  * PARAMETERS : None
1688  *
1689  * RETURN     : Pointer to IBinder
1690  *==========================================================================*/
onAsBinder()1691 IBinder* CameraContext::onAsBinder() {
1692     return NULL;
1693 }
1694 
1695 /*===========================================================================
1696  * FUNCTION   : getNumberOfCameras
1697  *
1698  * DESCRIPTION: returns the number of supported camera by the system
1699  *
1700  * PARAMETERS : None
1701  *
1702  * RETURN     : supported camera count
1703  *==========================================================================*/
getNumberOfCameras()1704 int CameraContext::getNumberOfCameras()
1705 {
1706     int ret = -1;
1707 
1708     if ( NULL != mCamera.get() ) {
1709         ret = mCamera->getNumberOfCameras();
1710     }
1711 
1712     return ret;
1713 }
1714 
1715 /*===========================================================================
1716  * FUNCTION   : closeCamera
1717  *
1718  * DESCRIPTION: closes a previously the initialized camera reference
1719  *
1720  * PARAMETERS : None
1721  *
1722  * RETURN     : status_t type of status
1723  *              NO_ERROR  -- success
1724  *              none-zero failure code
1725  *==========================================================================*/
closeCamera()1726 status_t CameraContext::closeCamera()
1727 {
1728     useLock();
1729     if ( NULL == mCamera.get() ) {
1730         return NO_INIT;
1731     }
1732 
1733     mCamera->disconnect();
1734     mCamera.clear();
1735 
1736     mRecorder->init();
1737     mRecorder->close();
1738     mRecorder->release();
1739     mRecorder.clear();
1740 
1741     mHardwareActive = false;
1742     mPreviewRunning = false;
1743     mRecordRunning = false;
1744 
1745     signalFinished();
1746     return NO_ERROR;
1747 }
1748 
1749 /*===========================================================================
1750  * FUNCTION   : startPreview
1751  *
1752  * DESCRIPTION: starts camera preview
1753  *
1754  * PARAMETERS : None
1755  *
1756  * RETURN     : status_t type of status
1757  *              NO_ERROR  -- success
1758  *              none-zero failure code
1759  *==========================================================================*/
startPreview()1760 status_t CameraContext::startPreview()
1761 {
1762     useLock();
1763 
1764     int ret = NO_ERROR;
1765     int previewWidth, previewHeight;
1766     Size calculatedPreviewSize;
1767     Size currentPreviewSize = mSupportedPreviewSizes.itemAt(
1768         mCurrentPreviewSizeIdx);
1769     Size currentPictureSize = mSupportedPictureSizes.itemAt(
1770         mCurrentPictureSizeIdx);
1771     Size currentVideoSize   = mSupportedVideoSizes.itemAt(
1772         mCurrentVideoSizeIdx);
1773 
1774 #ifndef USE_JB_MR1
1775 
1776     sp<IGraphicBufferProducer> gbp;
1777 
1778 #endif
1779 
1780     if (!mHardwareActive ) {
1781         printf("Camera not active! \n");
1782         return NO_INIT;
1783     }
1784 
1785     if (mPreviewRunning) {
1786         printf("Preview is already running! \n");
1787         signalFinished();
1788         return NO_ERROR;
1789     }
1790 
1791     if (mResizePreview) {
1792         mPreviewRunning = false;
1793 
1794         if ( mRecordingHint ) {
1795             calculatedPreviewSize =
1796                 getPreviewSizeFromVideoSizes(currentVideoSize);
1797             previewWidth = calculatedPreviewSize.width;
1798             previewHeight = calculatedPreviewSize.height;
1799         } else {
1800             previewWidth = currentPreviewSize.width;
1801             previewHeight = currentPreviewSize.height;
1802         }
1803 
1804         ret = createPreviewSurface(previewWidth,
1805                                    previewHeight,
1806                                    HAL_PIXEL_FORMAT_YCrCb_420_SP);
1807         if (  NO_ERROR != ret ) {
1808             printf("Error while creating preview surface\n");
1809             return ret;
1810         }
1811 
1812         // set rdi mode if system prop is set for front camera
1813         if (mCameraIndex == 1) {
1814             char value[32];
1815             property_get("persist.camera.rdimode", value, "0");
1816             int rdimode = atoi(value);
1817             printf("rdi mode = %d\n", rdimode);
1818             if (rdimode == 1) {
1819                 mParams.set("rdi-mode", "enable");
1820             } else {
1821                 mParams.set("rdi-mode", "disable");
1822             }
1823         } else {
1824             mParams.set("rdi-mode", "disable");
1825         }
1826 
1827         //mParams.set("rdi-mode", "enable");
1828         mParams.set("recording-hint", "true");
1829         mParams.setPreviewSize(previewWidth, previewHeight);
1830         mParams.setPictureSize(currentPictureSize.width,
1831             currentPictureSize.height);
1832         mParams.setVideoSize(
1833             currentVideoSize.width, currentVideoSize.height);
1834 
1835         ret |= mCamera->setParameters(mParams.flatten());
1836 
1837 #ifndef USE_JB_MR1
1838 
1839         gbp = mPreviewSurface->getIGraphicBufferProducer();
1840         ret |= mCamera->setPreviewTarget(gbp);
1841 
1842 #else
1843 
1844         ret |= mCamera->setPreviewDisplay(mPreviewSurface);
1845 
1846 #endif
1847         mResizePreview = false;
1848     }
1849 
1850     if ( !mPreviewRunning ) {
1851         ret |= mCamera->startPreview();
1852         if ( NO_ERROR != ret ) {
1853             printf("Preview start failed! \n");
1854             return ret;
1855         }
1856 
1857         mPreviewRunning = true;
1858     }
1859 
1860     signalFinished();
1861 
1862     return ret;
1863 }
1864 
1865 /*===========================================================================
1866  * FUNCTION   : getPreviewSizeFromVideoSizes
1867  *
1868  * DESCRIPTION: Get the preview size from video size. Find all resolutions with
1869  *              the same aspect ratio and choose the same or the closest
1870  *              from them.
1871  *
1872  * PARAMETERS :
1873  *   @currentVideoSize: current video size
1874 
1875  *
1876  * RETURN     : PreviewSize
1877  *==========================================================================*/
getPreviewSizeFromVideoSizes(Size currentVideoSize)1878 Size CameraContext::getPreviewSizeFromVideoSizes(Size currentVideoSize)
1879 {
1880 
1881     Size tmpPreviewSize;
1882     Size PreviewSize;
1883     Size PreviewSizes[mSupportedPreviewSizes.size()];
1884     float tolerance = 0.00001;
1885     float videoRatio;
1886     float previewRatio;
1887     size_t i = 0;
1888     size_t j = 0;
1889     int delta;
1890 
1891     // Find all the resolutions with the same aspect ratio and choose the
1892     // same or the closest resolution from them. Choose the closest resolution
1893     // in case same aspect ratio is not found
1894     if (currentVideoSize.width * currentVideoSize.height > 0 &&
1895             mSupportedPreviewSizes.size() > 0) {
1896         videoRatio = (float)currentVideoSize.width /
1897             (float)currentVideoSize.height;
1898         for (i=0; i<mSupportedPreviewSizes.size(); i++) {
1899             tmpPreviewSize = mSupportedPreviewSizes.itemAt(i);
1900             previewRatio = (float)tmpPreviewSize.width /
1901                 (float)tmpPreviewSize.height;
1902             if (fabs(videoRatio - previewRatio) < tolerance) {
1903                 PreviewSizes[j] = tmpPreviewSize;
1904                 j++;
1905             }
1906         }
1907 
1908         if ( j > 0 ) {
1909             delta = abs((currentVideoSize.width *currentVideoSize.height)-
1910                 (PreviewSizes[0].width * PreviewSizes[0].height));
1911             PreviewSize = PreviewSizes[0];
1912             for (i=0; i<j; i++) {
1913                 if(abs(currentVideoSize.width * currentVideoSize.height) -
1914                     (PreviewSizes[i].width * PreviewSizes[i].height) <
1915                     delta) {
1916                     PreviewSize = PreviewSizes[i];
1917                     delta = abs((currentVideoSize.width *
1918                         currentVideoSize.height) -
1919                         (PreviewSizes[i].width * PreviewSizes[i].height));
1920                 }
1921             }
1922         } else {
1923             // Choose the closest resolution in case same aspect ratio is
1924             // not found
1925             tmpPreviewSize = mSupportedPreviewSizes.itemAt(j);
1926             PreviewSize = tmpPreviewSize;
1927             delta = abs(
1928                     (currentVideoSize.width * currentVideoSize.height)-
1929                     (tmpPreviewSize.width * tmpPreviewSize.height));
1930             for (i=0; i<mSupportedPreviewSizes.size(); i++) {
1931                 tmpPreviewSize = mSupportedPreviewSizes.itemAt(i);
1932                 if(abs(
1933                         (currentVideoSize.width * currentVideoSize.height)-
1934                         (tmpPreviewSize.width * tmpPreviewSize.height)) <
1935                         delta) {
1936                     PreviewSize = tmpPreviewSize;
1937                     delta = abs(
1938                             (currentVideoSize.width * currentVideoSize.height)-
1939                             (tmpPreviewSize.width * tmpPreviewSize.height));
1940                 }
1941             }
1942         }
1943     } else {
1944         memset(&PreviewSize, 0, sizeof(PreviewSize));
1945     }
1946     return PreviewSize;
1947 }
1948 
1949 /*===========================================================================
1950  * FUNCTION   : autoFocus
1951  *
1952  * DESCRIPTION: Triggers autofocus
1953  *
1954  * PARAMETERS : None
1955  *
1956  * RETURN     : status_t type of status
1957  *              NO_ERROR  -- success
1958  *              none-zero failure code
1959  *==========================================================================*/
autoFocus()1960 status_t CameraContext::autoFocus()
1961 {
1962     useLock();
1963     status_t ret = NO_ERROR;
1964 
1965     if ( mPreviewRunning ) {
1966         ret = mCamera->autoFocus();
1967     }
1968 
1969     signalFinished();
1970     return ret;
1971 }
1972 
1973 /*===========================================================================
1974  * FUNCTION   : enablePreviewCallbacks
1975  *
1976  * DESCRIPTION: Enables preview callback messages
1977  *
1978  * PARAMETERS : None
1979  *
1980  * RETURN     : status_t type of status
1981  *              NO_ERROR  -- success
1982  *              none-zero failure code
1983  *==========================================================================*/
enablePreviewCallbacks()1984 status_t CameraContext::enablePreviewCallbacks()
1985 {
1986     useLock();
1987     if ( mHardwareActive ) {
1988         mCamera->setPreviewCallbackFlags(
1989             CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
1990     }
1991 
1992     signalFinished();
1993     return NO_ERROR;
1994 }
1995 
1996 /*===========================================================================
1997  * FUNCTION   : takePicture
1998  *
1999  * DESCRIPTION: triggers image capture
2000  *
2001  * PARAMETERS : None
2002  *
2003  * RETURN     : status_t type of status
2004  *              NO_ERROR  -- success
2005  *              none-zero failure code
2006  *==========================================================================*/
takePicture()2007 status_t CameraContext::takePicture()
2008 {
2009     status_t ret = NO_ERROR;
2010 
2011     useLock(); // Unlocked in jpeg callback
2012 
2013     if ( mPreviewRunning ) {
2014         ret = mCamera->takePicture(
2015             CAMERA_MSG_COMPRESSED_IMAGE|
2016             CAMERA_MSG_RAW_IMAGE);
2017         if (!mRecordingHint) {
2018             mPreviewRunning = false;
2019         }
2020     } else {
2021         printf("Please resume/start the preview before taking a picture!\n");
2022         signalFinished(); //Unlock in case preview is not running
2023     }
2024     return ret;
2025 }
2026 
2027 /*===========================================================================
2028  * FUNCTION   : configureRecorder
2029  *
2030  * DESCRIPTION: Configure video recorder
2031  *
2032  * PARAMETERS : None
2033  *
2034  * RETURN     : status_t type of status
2035  *              NO_ERROR  -- success
2036  *              none-zero failure code
2037  *==========================================================================*/
configureRecorder()2038 status_t CameraContext::configureRecorder()
2039 {
2040     useLock();
2041     status_t ret = NO_ERROR;
2042 
2043     mResizePreview = true;
2044     mParams.set("recording-hint", "true");
2045     mRecordingHint = true;
2046     mCamera->setParameters(mParams.flatten());
2047 
2048     Size videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
2049     ret = mRecorder->setParameters(
2050         String8("video-param-encoding-bitrate=64000"));
2051     if ( ret != NO_ERROR ) {
2052         ERROR("Could not configure recorder (%d)", ret);
2053         return ret;
2054     }
2055 
2056     ret = mRecorder->setCamera(
2057         mCamera->remote(), mCamera->getRecordingProxy());
2058     if ( ret != NO_ERROR ) {
2059         ERROR("Could not set camera (%d)", ret);
2060         return ret;
2061     }
2062     ret = mRecorder->setVideoSource(VIDEO_SOURCE_CAMERA);
2063     if ( ret != NO_ERROR ) {
2064         ERROR("Could not set video soruce (%d)", ret);
2065         return ret;
2066     }
2067     ret = mRecorder->setAudioSource(AUDIO_SOURCE_DEFAULT);
2068     if ( ret != NO_ERROR ) {
2069         ERROR("Could not set audio source (%d)", ret);
2070         return ret;
2071     }
2072     ret = mRecorder->setOutputFormat(OUTPUT_FORMAT_DEFAULT);
2073     if ( ret != NO_ERROR ) {
2074         ERROR("Could not set output format (%d)", ret);
2075         return ret;
2076     }
2077 
2078     ret = mRecorder->setVideoEncoder(VIDEO_ENCODER_DEFAULT);
2079     if ( ret != NO_ERROR ) {
2080         ERROR("Could not set video encoder (%d)", ret);
2081         return ret;
2082     }
2083 
2084     char fileName[100];
2085 
2086     sprintf(fileName, "/sdcard/vid_cam%d_%dx%d_%d.mpeg", mCameraIndex,
2087             videoSize.width, videoSize.height, mVideoIdx++);
2088 
2089     if ( mVideoFd < 0 ) {
2090         mVideoFd = open(fileName, O_CREAT | O_RDWR );
2091     }
2092 
2093     if ( mVideoFd < 0 ) {
2094         ERROR("Could not open video file for writing %s!", fileName);
2095         return UNKNOWN_ERROR;
2096     }
2097 
2098     ret = mRecorder->setOutputFile(mVideoFd, 0, 0);
2099     if ( ret != NO_ERROR ) {
2100         ERROR("Could not set output file (%d)", ret);
2101         return ret;
2102     }
2103 
2104     ret = mRecorder->setVideoSize(videoSize.width, videoSize.height);
2105     if ( ret  != NO_ERROR ) {
2106         ERROR("Could not set video size %dx%d", videoSize.width,
2107             videoSize.height);
2108         return ret;
2109     }
2110 
2111     ret = mRecorder->setVideoFrameRate(30);
2112     if ( ret != NO_ERROR ) {
2113         ERROR("Could not set video frame rate (%d)", ret);
2114         return ret;
2115     }
2116 
2117     ret = mRecorder->setAudioEncoder(AUDIO_ENCODER_DEFAULT);
2118     if ( ret != NO_ERROR ) {
2119         ERROR("Could not set audio encoder (%d)", ret);
2120         return ret;
2121     }
2122 
2123     signalFinished();
2124     return ret;
2125 }
2126 
2127 /*===========================================================================
2128  * FUNCTION   : unconfigureViVRecording
2129  *
2130  * DESCRIPTION: Unconfigures video in video recording
2131  *
2132  * PARAMETERS : None
2133  *
2134  * RETURN     : status_t type of status
2135  *              NO_ERROR  -- success
2136  *              none-zero failure code
2137  *==========================================================================*/
unconfigureRecorder()2138 status_t CameraContext::unconfigureRecorder()
2139 {
2140     useLock();
2141 
2142     if ( !mRecordRunning ) {
2143         mResizePreview = true;
2144         mParams.set("recording-hint", "false");
2145         mRecordingHint = false;
2146         mCamera->setParameters(mParams.flatten());
2147     }
2148 
2149     signalFinished();
2150     return NO_ERROR;
2151 }
2152 
2153 /*===========================================================================
2154  * FUNCTION   : configureViVRecording
2155  *
2156  * DESCRIPTION: Configures video in video recording
2157  *
2158  * PARAMETERS : None
2159  *
2160  * RETURN     : status_t type of status
2161  *              NO_ERROR  -- success
2162  *              none-zero failure code
2163  *==========================================================================*/
configureViVRecording()2164 status_t CameraContext::configureViVRecording()
2165 {
2166     status_t ret = NO_ERROR;
2167 
2168     mResizePreview = true;
2169     mParams.set("recording-hint", "true");
2170     mRecordingHint = true;
2171     mCamera->setParameters(mParams.flatten());
2172     mCamera->setRecordingProxyListener(this);
2173 
2174     signalFinished();
2175     return ret;
2176 }
2177 
2178 /*===========================================================================
2179  * FUNCTION   : startRecording
2180  *
2181  * DESCRIPTION: triggers start recording
2182  *
2183  * PARAMETERS : None
2184  *
2185  * RETURN     : status_t type of status
2186  *              NO_ERROR  -- success
2187  *              none-zero failure code
2188  *==========================================================================*/
startRecording()2189 status_t CameraContext::startRecording()
2190 {
2191     useLock();
2192     status_t ret = NO_ERROR;
2193 
2194 
2195     if ( mPreviewRunning ) {
2196 
2197         mCamera->unlock();
2198 
2199         ret = mRecorder->prepare();
2200         if ( ret != NO_ERROR ) {
2201             ERROR("Could not prepare recorder");
2202             return ret;
2203         }
2204 
2205         ret = mRecorder->start();
2206         if ( ret != NO_ERROR ) {
2207             ERROR("Could not start recorder");
2208             return ret;
2209         }
2210 
2211         mRecordRunning = true;
2212     }
2213     signalFinished();
2214     return ret;
2215 }
2216 
2217 /*===========================================================================
2218  * FUNCTION   : stopRecording
2219  *
2220  * DESCRIPTION: triggers start recording
2221  *
2222  * PARAMETERS : None
2223  *
2224  * RETURN     : status_t type of status
2225  *              NO_ERROR  -- success
2226  *              none-zero failure code
2227  *==========================================================================*/
stopRecording()2228 status_t CameraContext::stopRecording()
2229 {
2230     useLock();
2231     status_t ret = NO_ERROR;
2232 
2233     if ( mRecordRunning ) {
2234             mRecorder->stop();
2235             close(mVideoFd);
2236             mVideoFd = -1;
2237 
2238         mRecordRunning = false;
2239     }
2240 
2241     signalFinished();
2242 
2243     return ret;
2244 }
2245 
2246 /*===========================================================================
2247  * FUNCTION   : startViVRecording
2248  *
2249  * DESCRIPTION: Starts video in video recording
2250  *
2251  * PARAMETERS : None
2252  *
2253  * RETURN     : status_t type of status
2254  *              NO_ERROR  -- success
2255  *              none-zero failure code
2256  *==========================================================================*/
startViVRecording()2257 status_t CameraContext::startViVRecording()
2258 {
2259     useLock();
2260     status_t ret;
2261 
2262     if (mInterpr->mViVVid.VideoSizes[0].width *
2263             mInterpr->mViVVid.VideoSizes[0].height >=
2264             mInterpr->mViVVid.VideoSizes[1].width *
2265             mInterpr->mViVVid.VideoSizes[1].height) {
2266         mInterpr->mViVBuff.buffSize = calcBufferSize(
2267             mInterpr->mViVVid.VideoSizes[1].width,
2268             mInterpr->mViVVid.VideoSizes[1].height);
2269         if (mInterpr->mViVBuff.buff == NULL) {
2270             mInterpr->mViVBuff.buff =
2271                 (void *)malloc(mInterpr->mViVBuff.buffSize);
2272         }
2273         mInterpr->mViVVid.sourceCameraID = 1;
2274         mInterpr->mViVVid.destinationCameraID = 0;
2275 
2276     } else {
2277         mInterpr->mViVBuff.buffSize = calcBufferSize(
2278             mInterpr->mViVVid.VideoSizes[0].width,
2279             mInterpr->mViVVid.VideoSizes[0].height);
2280         if (mInterpr->mViVBuff.buff == NULL) {
2281             mInterpr->mViVBuff.buff =
2282                 (void *)malloc(mInterpr->mViVBuff.buffSize);
2283         }
2284         mInterpr->mViVVid.sourceCameraID = 0;
2285         mInterpr->mViVVid.destinationCameraID = 1;
2286     }
2287 
2288     ret = mCamera->startRecording();
2289 
2290     signalFinished();
2291     return ret;
2292 }
2293 
2294 /*===========================================================================
2295  * FUNCTION   : stopViVRecording
2296  *
2297  * DESCRIPTION: Stops video in video recording
2298  *
2299  * PARAMETERS : None
2300  *
2301  * RETURN     : status_t type of status
2302  *              NO_ERROR  -- success
2303  *              none-zero failure code
2304  *==========================================================================*/
stopViVRecording()2305 status_t CameraContext::stopViVRecording()
2306 {
2307     useLock();
2308     status_t ret = NO_ERROR;
2309 
2310     mCamera->stopRecording();
2311 
2312     signalFinished();
2313     return ret;
2314 }
2315 
2316 /*===========================================================================
2317  * FUNCTION   : stopPreview
2318  *
2319  * DESCRIPTION: stops camera preview
2320  *
2321  * PARAMETERS : None
2322  *
2323  * RETURN     : status_t type of status
2324  *              NO_ERROR  -- success
2325  *              none-zero failure code
2326  *==========================================================================*/
stopPreview()2327 status_t CameraContext::stopPreview()
2328 {
2329     useLock();
2330     status_t ret = NO_ERROR;
2331 
2332     if ( mHardwareActive ) {
2333         mCamera->stopPreview();
2334         ret = destroyPreviewSurface();
2335     }
2336 
2337     mPreviewRunning  = false;
2338     mResizePreview = true;
2339 
2340     signalFinished();
2341 
2342     return ret;
2343 }
2344 
2345 /*===========================================================================
2346  * FUNCTION   : resumePreview
2347  *
2348  * DESCRIPTION: resumes camera preview after image capture
2349  *
2350  * PARAMETERS : None
2351  *
2352  * RETURN     : status_t type of status
2353  *              NO_ERROR  -- success
2354  *              none-zero failure code
2355  *==========================================================================*/
resumePreview()2356 status_t CameraContext::resumePreview()
2357 {
2358     useLock();
2359     status_t ret = NO_ERROR;
2360 
2361     if ( mHardwareActive ) {
2362         ret = mCamera->startPreview();
2363         mPreviewRunning = true;
2364     } else {
2365         ret = NO_INIT;
2366     }
2367 
2368     signalFinished();
2369     return ret;
2370 }
2371 
2372 /*===========================================================================
2373  * FUNCTION   : nextPreviewSize
2374  *
2375  * DESCRIPTION: Iterates through all supported preview sizes.
2376  *
2377  * PARAMETERS : None
2378  *
2379  * RETURN     : status_t type of status
2380  *              NO_ERROR  -- success
2381  *              none-zero failure code
2382  *==========================================================================*/
nextPreviewSize()2383 status_t CameraContext::nextPreviewSize()
2384 {
2385     useLock();
2386     if ( mHardwareActive ) {
2387         mCurrentPreviewSizeIdx += 1;
2388         mCurrentPreviewSizeIdx %= mSupportedPreviewSizes.size();
2389         Size previewSize = mSupportedPreviewSizes.itemAt(
2390             mCurrentPreviewSizeIdx);
2391         mParams.setPreviewSize(previewSize.width,
2392                                previewSize.height);
2393         mResizePreview = true;
2394 
2395         if ( mPreviewRunning ) {
2396             mCamera->stopPreview();
2397             mCamera->setParameters(mParams.flatten());
2398             mCamera->startPreview();
2399         } else {
2400             mCamera->setParameters(mParams.flatten());
2401         }
2402     }
2403 
2404     signalFinished();
2405     return NO_ERROR;
2406 }
2407 
2408 
2409 /*===========================================================================
2410  * FUNCTION   : setPreviewSize
2411  *
2412  * DESCRIPTION: Sets exact preview size if supported
2413  *
2414  * PARAMETERS : format size in the form of WIDTHxHEIGHT
2415  *
2416  * RETURN     : status_t type of status
2417  *              NO_ERROR  -- success
2418  *              none-zero failure code
2419  *==========================================================================*/
setPreviewSize(const char * format)2420 status_t CameraContext::setPreviewSize(const char *format)
2421 {
2422     useLock();
2423     if ( mHardwareActive ) {
2424         int newHeight;
2425         int newWidth;
2426         sscanf(format, "%dx%d", &newWidth, &newHeight);
2427 
2428         unsigned int i;
2429         for (i = 0; i < mSupportedPreviewSizes.size(); ++i) {
2430             Size previewSize = mSupportedPreviewSizes.itemAt(i);
2431             if ( newWidth == previewSize.width &&
2432                  newHeight == previewSize.height )
2433             {
2434                 break;
2435             }
2436 
2437         }
2438         if ( i == mSupportedPreviewSizes.size())
2439         {
2440             printf("Preview size %dx%d not supported !\n",
2441                 newWidth, newHeight);
2442             return INVALID_OPERATION;
2443         }
2444 
2445         mParams.setPreviewSize(newWidth,
2446                                newHeight);
2447         mResizePreview = true;
2448 
2449         if ( mPreviewRunning ) {
2450             mCamera->stopPreview();
2451             mCamera->setParameters(mParams.flatten());
2452             mCamera->startPreview();
2453         } else {
2454             mCamera->setParameters(mParams.flatten());
2455         }
2456     }
2457 
2458     signalFinished();
2459     return NO_ERROR;
2460 }
2461 
2462 /*===========================================================================
2463  * FUNCTION   : getCurrentPreviewSize
2464  *
2465  * DESCRIPTION: queries the currently configured preview size
2466  *
2467  * PARAMETERS :
2468  *  @previewSize : preview size currently configured
2469  *
2470  * RETURN     : status_t type of status
2471  *              NO_ERROR  -- success
2472  *              none-zero failure code
2473  *==========================================================================*/
getCurrentPreviewSize(Size & previewSize)2474 status_t CameraContext::getCurrentPreviewSize(Size &previewSize)
2475 {
2476     useLock();
2477     if ( mHardwareActive ) {
2478         previewSize = mSupportedPreviewSizes.itemAt(mCurrentPreviewSizeIdx);
2479     }
2480     signalFinished();
2481     return NO_ERROR;
2482 }
2483 
2484 /*===========================================================================
2485  * FUNCTION   : nextPictureSize
2486  *
2487  * DESCRIPTION: Iterates through all supported picture sizes.
2488  *
2489  * PARAMETERS : None
2490  *
2491  * RETURN     : status_t type of status
2492  *              NO_ERROR  -- success
2493  *              none-zero failure code
2494  *==========================================================================*/
nextPictureSize()2495 status_t CameraContext::nextPictureSize()
2496 {
2497     useLock();
2498     if ( mHardwareActive ) {
2499         mCurrentPictureSizeIdx += 1;
2500         mCurrentPictureSizeIdx %= mSupportedPictureSizes.size();
2501         Size pictureSize = mSupportedPictureSizes.itemAt(
2502             mCurrentPictureSizeIdx);
2503         mParams.setPictureSize(pictureSize.width,
2504             pictureSize.height);
2505         mCamera->setParameters(mParams.flatten());
2506     }
2507     signalFinished();
2508     return NO_ERROR;
2509 }
2510 
2511 /*===========================================================================
2512  * FUNCTION   : setPictureSize
2513  *
2514  * DESCRIPTION: Sets exact preview size if supported
2515  *
2516  * PARAMETERS : format size in the form of WIDTHxHEIGHT
2517  *
2518  * RETURN     : status_t type of status
2519  *              NO_ERROR  -- success
2520  *              none-zero failure code
2521  *==========================================================================*/
setPictureSize(const char * format)2522 status_t CameraContext::setPictureSize(const char *format)
2523 {
2524     useLock();
2525     if ( mHardwareActive ) {
2526         int newHeight;
2527         int newWidth;
2528         sscanf(format, "%dx%d", &newWidth, &newHeight);
2529 
2530         unsigned int i;
2531         for (i = 0; i < mSupportedPictureSizes.size(); ++i) {
2532             Size PictureSize = mSupportedPictureSizes.itemAt(i);
2533             if ( newWidth == PictureSize.width &&
2534                  newHeight == PictureSize.height )
2535             {
2536                 break;
2537             }
2538 
2539         }
2540         if ( i == mSupportedPictureSizes.size())
2541         {
2542             printf("Preview size %dx%d not supported !\n",
2543                 newWidth, newHeight);
2544             return INVALID_OPERATION;
2545         }
2546 
2547         mParams.setPictureSize(newWidth,
2548                                newHeight);
2549         mCamera->setParameters(mParams.flatten());
2550     }
2551 
2552     signalFinished();
2553     return NO_ERROR;
2554 }
2555 
2556 /*===========================================================================
2557  * FUNCTION   : nextVideoSize
2558  *
2559  * DESCRIPTION: Select the next available video size
2560  *
2561  * PARAMETERS : none
2562  *
2563  * RETURN     : status_t type of status
2564  *              NO_ERROR  -- success
2565  *              none-zero failure code
2566  *==========================================================================*/
nextVideoSize()2567 status_t CameraContext::nextVideoSize()
2568 {
2569     useLock();
2570     if ( mHardwareActive ) {
2571         mCurrentVideoSizeIdx += 1;
2572         mCurrentVideoSizeIdx %= mSupportedVideoSizes.size();
2573         Size videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
2574         mParams.setVideoSize(videoSize.width,
2575                              videoSize.height);
2576         mCamera->setParameters(mParams.flatten());
2577         mInterpr->setViVSize((Size) mSupportedVideoSizes.itemAt(
2578             mCurrentVideoSizeIdx), mCameraIndex);
2579     }
2580     signalFinished();
2581     return NO_ERROR;
2582 }
2583 
2584 /*===========================================================================
2585  * FUNCTION   : setVideoSize
2586  *
2587  * DESCRIPTION: Set video size
2588  *
2589  * PARAMETERS :
2590  *   @format  : format
2591  *
2592  * RETURN     : status_t type of status
2593  *              NO_ERROR  -- success
2594  *              none-zero failure code
2595  *==========================================================================*/
setVideoSize(const char * format)2596 status_t CameraContext::setVideoSize(const char *format)
2597 {
2598     useLock();
2599     if ( mHardwareActive ) {
2600         int newHeight;
2601         int newWidth;
2602         sscanf(format, "%dx%d", &newWidth, &newHeight);
2603 
2604         unsigned int i;
2605         for (i = 0; i < mSupportedVideoSizes.size(); ++i) {
2606             Size PictureSize = mSupportedVideoSizes.itemAt(i);
2607             if ( newWidth == PictureSize.width &&
2608                  newHeight == PictureSize.height )
2609             {
2610                 break;
2611             }
2612 
2613         }
2614         if ( i == mSupportedVideoSizes.size())
2615         {
2616             printf("Preview size %dx%d not supported !\n",
2617                 newWidth, newHeight);
2618             return INVALID_OPERATION;
2619         }
2620 
2621         mParams.setVideoSize(newWidth,
2622                              newHeight);
2623         mCamera->setParameters(mParams.flatten());
2624     }
2625 
2626     signalFinished();
2627     return NO_ERROR;
2628 }
2629 
2630 /*===========================================================================
2631  * FUNCTION    : getCurrentVideoSize
2632  *
2633  * DESCRIPTION : Get current video size
2634  *
2635  * PARAMETERS  :
2636  *   @videoSize: video Size
2637  *
2638  * RETURN      : status_t type of status
2639  *               NO_ERROR  -- success
2640  *               none-zero failure code
2641  *==========================================================================*/
getCurrentVideoSize(Size & videoSize)2642 status_t CameraContext::getCurrentVideoSize(Size &videoSize)
2643 {
2644     useLock();
2645     if ( mHardwareActive ) {
2646         videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
2647     }
2648     signalFinished();
2649     return NO_ERROR;
2650 }
2651 
2652 /*===========================================================================
2653  * FUNCTION   : getCurrentPictureSize
2654  *
2655  * DESCRIPTION: queries the currently configured picture size
2656  *
2657  * PARAMETERS :
2658  *  @pictureSize : picture size currently configured
2659  *
2660  * RETURN     : status_t type of status
2661  *              NO_ERROR  -- success
2662  *              none-zero failure code
2663  *==========================================================================*/
getCurrentPictureSize(Size & pictureSize)2664 status_t CameraContext::getCurrentPictureSize(Size &pictureSize)
2665 {
2666     useLock();
2667     if ( mHardwareActive ) {
2668         pictureSize = mSupportedPictureSizes.itemAt(mCurrentPictureSizeIdx);
2669     }
2670     signalFinished();
2671     return NO_ERROR;
2672 }
2673 
2674 }; //namespace qcamera ends here
2675 
2676 using namespace qcamera;
2677 
2678 /*===========================================================================
2679  * FUNCTION   : printMenu
2680  *
2681  * DESCRIPTION: prints the available camera options
2682  *
2683  * PARAMETERS :
2684  *  @currentCamera : camera context currently being used
2685  *
2686  * RETURN     : None
2687  *==========================================================================*/
printMenu(sp<CameraContext> currentCamera)2688 void CameraContext::printMenu(sp<CameraContext> currentCamera)
2689 {
2690     if ( !mDoPrintMenu ) return;
2691     Size currentPictureSize, currentPreviewSize, currentVideoSize;
2692 
2693     assert(currentCamera.get());
2694 
2695     currentCamera->getCurrentPictureSize(currentPictureSize);
2696     currentCamera->getCurrentPreviewSize(currentPreviewSize);
2697     currentCamera->getCurrentVideoSize(currentVideoSize);
2698 
2699     printf("\n\n=========== FUNCTIONAL TEST MENU ===================\n\n");
2700 
2701     printf(" \n\nSTART / STOP / GENERAL SERVICES \n");
2702     printf(" -----------------------------\n");
2703     printf("   %c. Switch camera - Current Index: %d\n",
2704             Interpreter::SWITCH_CAMERA_CMD,
2705             currentCamera->getCameraIndex());
2706     printf("   %c. Resume Preview after capture \n",
2707             Interpreter::RESUME_PREVIEW_CMD);
2708     printf("   %c. Quit \n",
2709             Interpreter::EXIT_CMD);
2710     printf("   %c. Camera Capability Dump",
2711             Interpreter::DUMP_CAPS_CMD);
2712 
2713     printf(" \n\n PREVIEW SUB MENU \n");
2714     printf(" -----------------------------\n");
2715     printf("   %c. Start Preview\n",
2716             Interpreter::START_PREVIEW_CMD);
2717     printf("   %c. Stop Preview\n",
2718             Interpreter::STOP_PREVIEW_CMD);
2719     printf("   %c. Preview size:  %dx%d\n",
2720            Interpreter::CHANGE_PREVIEW_SIZE_CMD,
2721            currentPreviewSize.width,
2722            currentPreviewSize.height);
2723     printf("   %c. Video size:  %dx%d\n",
2724             Interpreter::CHANGE_VIDEO_SIZE_CMD,
2725             currentVideoSize.width,
2726             currentVideoSize.height);
2727     printf("   %c. Start Recording\n",
2728             Interpreter::START_RECORD_CMD);
2729     printf("   %c. Stop Recording\n",
2730             Interpreter::STOP_RECORD_CMD);
2731     printf("   %c. Start ViV Recording\n",
2732             Interpreter::START_VIV_RECORD_CMD);
2733     printf("   %c. Stop ViV Recording\n",
2734             Interpreter::STOP_VIV_RECORD_CMD);
2735     printf("   %c. Enable preview frames\n",
2736             Interpreter::ENABLE_PRV_CALLBACKS_CMD);
2737     printf("   %c. Trigger autofocus \n",
2738             Interpreter::AUTOFOCUS_CMD);
2739 
2740     printf(" \n\n IMAGE CAPTURE SUB MENU \n");
2741     printf(" -----------------------------\n");
2742     printf("   %c. Take picture/Full Press\n",
2743             Interpreter::TAKEPICTURE_CMD);
2744     printf("   %c. Take picture in picture\n",
2745             Interpreter::TAKEPICTURE_IN_PICTURE_CMD);
2746     printf("   %c. Picture size:  %dx%d\n",
2747            Interpreter::CHANGE_PICTURE_SIZE_CMD,
2748            currentPictureSize.width,
2749            currentPictureSize.height);
2750 
2751     printf("\n");
2752     printf("   Choice: ");
2753 }
2754 
2755 /*===========================================================================
2756  * FUNCTION   : enablePrintPreview
2757  *
2758  * DESCRIPTION: Enables printing the preview
2759  *
2760  * PARAMETERS : None
2761  *
2762  * RETURN     : None
2763  *==========================================================================*/
enablePrintPreview()2764 void CameraContext::enablePrintPreview()
2765 {
2766     mDoPrintMenu = true;
2767 }
2768 
2769 /*===========================================================================
2770  * FUNCTION   : disablePrintPreview
2771  *
2772  * DESCRIPTION: Disables printing the preview
2773  *
2774  * PARAMETERS : None
2775  *
2776  * RETURN     : None
2777  *==========================================================================*/
disablePrintPreview()2778 void CameraContext::disablePrintPreview()
2779 {
2780     mDoPrintMenu = false;
2781 }
2782 
2783 /*===========================================================================
2784  * FUNCTION   : enablePiPCapture
2785  *
2786  * DESCRIPTION: Enables picture in picture capture
2787  *
2788  * PARAMETERS : None
2789  *
2790  * RETURN     : None
2791  *==========================================================================*/
enablePiPCapture()2792 void CameraContext::enablePiPCapture()
2793 {
2794     mPiPCapture = true;
2795 }
2796 
2797 /*===========================================================================
2798  * FUNCTION   : disablePiPCapture
2799  *
2800  * DESCRIPTION: Disables picture in picture capture
2801  *
2802  * PARAMETERS : None
2803  *
2804  * RETURN     : None
2805  *==========================================================================*/
disablePiPCapture()2806 void CameraContext::disablePiPCapture()
2807 {
2808     mPiPCapture = false;
2809 }
2810 
2811 /*===========================================================================
2812  * FUNCTION   : configureViVCodec
2813  *
2814  * DESCRIPTION: Configures video in video codec
2815  *
2816  * PARAMETERS : none
2817  *
2818  * RETURN     : status_t type of status
2819  *              NO_ERROR  -- success
2820  *              none-zero failure code
2821  *==========================================================================*/
configureViVCodec()2822 status_t Interpreter::configureViVCodec()
2823 {
2824     status_t ret = NO_ERROR;
2825     char fileName[100];
2826     sp<AMessage> format = new AMessage;
2827     sp<ALooper> looper = new ALooper;
2828 
2829     if (mTestContext->mViVVid.VideoSizes[0].width *
2830             mTestContext->mViVVid.VideoSizes[0].height >=
2831             mTestContext->mViVVid.VideoSizes[1].width *
2832             mTestContext->mViVVid.VideoSizes[1].height) {
2833         sprintf(fileName, "/sdcard/ViV_vid_%dx%d_%d.mp4",
2834             mTestContext->mViVVid.VideoSizes[0].width,
2835             mTestContext->mViVVid.VideoSizes[0].height,
2836             mTestContext->mViVVid.ViVIdx++);
2837         format->setInt32("width", mTestContext->mViVVid.VideoSizes[0].width);
2838         format->setInt32("height", mTestContext->mViVVid.VideoSizes[0].height);
2839     } else {
2840         sprintf(fileName, "/sdcard/ViV_vid_%dx%d_%d.mp4",
2841             mTestContext->mViVVid.VideoSizes[1].width,
2842             mTestContext->mViVVid.VideoSizes[1].height,
2843             mTestContext->mViVVid.ViVIdx++);
2844         format->setInt32("width", mTestContext->mViVVid.VideoSizes[1].width);
2845         format->setInt32("height", mTestContext->mViVVid.VideoSizes[1].height);
2846     }
2847     mTestContext->mViVVid.muxer = new MediaMuxer(
2848         fileName, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
2849 
2850     format->setString("mime", "video/avc");
2851     format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
2852 
2853     format->setInt32("bitrate", 1000000);
2854     format->setFloat("frame-rate", 30);
2855     format->setInt32("i-frame-interval", 10);
2856 
2857     looper->setName("ViV_recording_looper");
2858     looper->start();
2859     ALOGV("Creating codec");
2860     mTestContext->mViVVid.codec = MediaCodec::CreateByType(
2861         looper, "video/avc", true);
2862     if (mTestContext->mViVVid.codec == NULL) {
2863         fprintf(stderr, "ERROR: unable to create video/avc codec instance\n");
2864         return UNKNOWN_ERROR;
2865     }
2866     ret = mTestContext->mViVVid.codec->configure(format, NULL, NULL,
2867             MediaCodec::CONFIGURE_FLAG_ENCODE);
2868     if (ret != NO_ERROR) {
2869         mTestContext->mViVVid.codec->release();
2870         mTestContext->mViVVid.codec.clear();
2871 
2872         fprintf(stderr, "ERROR: unable to configure codec (err=%d)\n", ret);
2873         return ret;
2874     }
2875 
2876     ALOGV("Creating buffer producer");
2877     ret = mTestContext->mViVVid.codec->createInputSurface(
2878         &mTestContext->mViVVid.bufferProducer);
2879     if (ret != NO_ERROR) {
2880         mTestContext->mViVVid.codec->release();
2881         mTestContext->mViVVid.codec.clear();
2882 
2883         fprintf(stderr,
2884             "ERROR: unable to create encoder input surface (err=%d)\n", ret);
2885         return ret;
2886     }
2887 
2888     ret = mTestContext->mViVVid.codec->start();
2889     if (ret != NO_ERROR) {
2890         mTestContext->mViVVid.codec->release();
2891         mTestContext->mViVVid.codec.clear();
2892 
2893         fprintf(stderr, "ERROR: unable to start codec (err=%d)\n", ret);
2894         return ret;
2895     }
2896     ALOGV("Codec prepared");
2897 
2898     mTestContext->mViVVid.surface = new Surface(
2899         mTestContext->mViVVid.bufferProducer);
2900     mTestContext->mViVVid.ANW = mTestContext->mViVVid.surface;
2901     ret = native_window_api_connect(mTestContext->mViVVid.ANW.get(),
2902         NATIVE_WINDOW_API_CPU);
2903     if (mTestContext->mViVVid.VideoSizes[0].width *
2904         mTestContext->mViVVid.VideoSizes[0].height >=
2905         mTestContext->mViVVid.VideoSizes[1].width *
2906         mTestContext->mViVVid.VideoSizes[1].height) {
2907         native_window_set_buffers_geometry(mTestContext->mViVVid.ANW.get(),
2908             mTestContext->mViVVid.VideoSizes[0].width,
2909             mTestContext->mViVVid.VideoSizes[0].height,
2910             HAL_PIXEL_FORMAT_NV12_ENCODEABLE);
2911     } else {
2912         native_window_set_buffers_geometry(mTestContext->mViVVid.ANW.get(),
2913             mTestContext->mViVVid.VideoSizes[1].width,
2914             mTestContext->mViVVid.VideoSizes[1].height,
2915             HAL_PIXEL_FORMAT_NV12_ENCODEABLE);
2916     }
2917     native_window_set_usage(mTestContext->mViVVid.ANW.get(),
2918         GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
2919     native_window_set_buffer_count(mTestContext->mViVVid.ANW.get(),
2920         mTestContext->mViVVid.buff_cnt);
2921 
2922     ViVEncoderThread();
2923 
2924     return ret;
2925 }
2926 
2927 /*===========================================================================
2928  * FUNCTION   : unconfigureViVCodec
2929  *
2930  * DESCRIPTION: Unconfigures video in video codec
2931  *
2932  * PARAMETERS : none
2933  *
2934  * RETURN     : status_t type of status
2935  *              NO_ERROR  -- success
2936  *              none-zero failure code
2937  *==========================================================================*/
unconfigureViVCodec()2938 status_t Interpreter::unconfigureViVCodec()
2939 {
2940     status_t ret = NO_ERROR;
2941 
2942     ret = native_window_api_disconnect(mTestContext->mViVVid.ANW.get(),
2943         NATIVE_WINDOW_API_CPU);
2944     mTestContext->mViVVid.bufferProducer = NULL;
2945     mTestContext->mViVVid.codec->stop();
2946     pthread_join(mViVEncThread, NULL);
2947     mTestContext->mViVVid.muxer->stop();
2948     mTestContext->mViVVid.codec->release();
2949     mTestContext->mViVVid.codec.clear();
2950     mTestContext->mViVVid.muxer.clear();
2951     mTestContext->mViVVid.surface.clear();
2952   return ret;
2953 }
2954 
2955 /*===========================================================================
2956  * FUNCTION   : Interpreter
2957  *
2958  * DESCRIPTION: Interpreter constructor
2959  *
2960  * PARAMETERS : none
2961  *
2962  * RETURN     : none
2963  *==========================================================================*/
Interpreter(const char * file)2964 Interpreter::Interpreter(const char *file)
2965     : mCmdIndex(0)
2966     , mScript(NULL)
2967 {
2968     if (!file){
2969         printf("no File Given\n");
2970         mUseScript = false;
2971         return;
2972     }
2973 
2974     FILE *fh = fopen(file, "r");
2975     if ( !fh ) {
2976         printf("Could not open file %s\n", file);
2977         mUseScript = false;
2978         return;
2979     }
2980 
2981     fseek(fh, 0, SEEK_END);
2982     int len = ftell(fh);
2983     rewind(fh);
2984 
2985     if( !len ) {
2986         printf("Script file %s is empty !\n", file);
2987         fclose(fh);
2988         return;
2989     }
2990 
2991     mScript = new char[len + 1];
2992     if ( !mScript ) {
2993         fclose(fh);
2994         return;
2995     }
2996 
2997     fread(mScript, sizeof(char), len, fh);
2998     mScript[len] = '\0'; // ensure null terminated;
2999     fclose(fh);
3000 
3001 
3002     char *p1;
3003     char *p2;
3004     p1 = p2 = mScript;
3005 
3006     do {
3007         switch (*p1) {
3008         case '\0':
3009         case '|':
3010             p1++;
3011             break;
3012         case SWITCH_CAMERA_CMD:
3013         case RESUME_PREVIEW_CMD:
3014         case START_PREVIEW_CMD:
3015         case STOP_PREVIEW_CMD:
3016         case CHANGE_PREVIEW_SIZE_CMD:
3017         case CHANGE_PICTURE_SIZE_CMD:
3018         case START_RECORD_CMD:
3019         case STOP_RECORD_CMD:
3020         case START_VIV_RECORD_CMD:
3021         case STOP_VIV_RECORD_CMD:
3022         case DUMP_CAPS_CMD:
3023         case AUTOFOCUS_CMD:
3024         case TAKEPICTURE_CMD:
3025         case TAKEPICTURE_IN_PICTURE_CMD:
3026         case ENABLE_PRV_CALLBACKS_CMD:
3027         case EXIT_CMD:
3028         case DELAY:
3029             p2 = p1;
3030             while( (p2 != (mScript + len)) && (*p2 != '|')) {
3031                 p2++;
3032             }
3033             *p2 = '\0';
3034             if (p2 == (p1 + 1))
3035                 mCommands.push_back(Command(
3036                     static_cast<Interpreter::Commands_e>(*p1)));
3037             else
3038                 mCommands.push_back(Command(
3039                     static_cast<Interpreter::Commands_e>(*p1), (p1 + 1)));
3040             p1 = p2;
3041             break;
3042         default:
3043             printf("Invalid cmd %c \n", *p1);
3044             do {
3045                 p1++;
3046 
3047             } while(*p1 != '|' && p1 != (mScript + len));
3048 
3049         }
3050     } while(p1 != (mScript + len));
3051     mUseScript = true;
3052 }
3053 
3054 /*===========================================================================
3055  * FUNCTION   : ~Interpreter
3056  *
3057  * DESCRIPTION: Interpreter destructor
3058  *
3059  * PARAMETERS : none
3060  *
3061  * RETURN     : none
3062  *==========================================================================*/
~Interpreter()3063 Interpreter::~Interpreter()
3064 {
3065     if ( mScript )
3066         delete[] mScript;
3067 
3068     mCommands.clear();
3069 }
3070 
3071 /*===========================================================================
3072  * FUNCTION        : getCommand
3073  *
3074  * DESCRIPTION     : Get a command from interpreter
3075  *
3076  * PARAMETERS      :
3077  *   @currentCamera: Current camera context
3078  *
3079  * RETURN          : command
3080  *==========================================================================*/
getCommand(sp<CameraContext> currentCamera)3081 Interpreter::Command Interpreter::getCommand(
3082     sp<CameraContext> currentCamera)
3083 {
3084     if( mUseScript ) {
3085         return mCommands[mCmdIndex++];
3086     } else {
3087         currentCamera->printMenu(currentCamera);
3088         return Interpreter::Command(
3089             static_cast<Interpreter::Commands_e>(getchar()));
3090     }
3091 }
3092 
3093 /*===========================================================================
3094  * FUNCTION        : TestContext
3095  *
3096  * DESCRIPTION     : TestContext constructor
3097  *
3098  * PARAMETERS      : None
3099  *
3100  * RETURN          : None
3101  *==========================================================================*/
TestContext()3102 TestContext::TestContext()
3103 {
3104     sp<CameraContext> camera;
3105     int i = 0;
3106     mTestRunning = false;
3107     mInterpreter = NULL;
3108     mViVVid.ViVIdx = 0;
3109     mViVVid.buff_cnt = 9;
3110     mViVVid.graphBuf = 0;
3111     mViVVid.mappedBuff = NULL;
3112     mViVVid.isBuffValid = false;
3113     mViVVid.sourceCameraID = -1;
3114     mViVVid.destinationCameraID = -1;
3115     memset(&mViVBuff, 0, sizeof(ViVBuff_t));
3116 
3117     ProcessState::self()->startThreadPool();
3118 
3119     do {
3120         camera = new CameraContext(i);
3121         if ( NULL == camera.get() ) {
3122             break;
3123         }
3124         camera->setTestCtxInstance(this);
3125 
3126         status_t stat = camera->openCamera();
3127         if ( NO_ERROR != stat ) {
3128             printf("Error encountered Openging camera id : %d\n", i);
3129             break;
3130         }
3131 
3132         mAvailableCameras.add(camera);
3133         i++;
3134     } while ( i < camera->getNumberOfCameras() ) ;
3135 
3136     if (i < camera->getNumberOfCameras() ) {
3137         for (size_t j = 0; j < mAvailableCameras.size(); j++) {
3138             camera = mAvailableCameras.itemAt(j);
3139             camera->closeCamera();
3140             camera.clear();
3141         }
3142 
3143         mAvailableCameras.clear();
3144     }
3145 }
3146 
3147 /*===========================================================================
3148  * FUNCTION        : ~TestContext
3149  *
3150  * DESCRIPTION     : TestContext destructor
3151  *
3152  * PARAMETERS      : None
3153  *
3154  * RETURN          : None
3155  *==========================================================================*/
~TestContext()3156 TestContext::~TestContext()
3157 {
3158     delete mInterpreter;
3159 
3160     for (size_t j = 0; j < mAvailableCameras.size(); j++) {
3161         sp<CameraContext> camera = mAvailableCameras.itemAt(j);
3162         camera->closeCamera();
3163         camera.clear();
3164     }
3165 
3166     mAvailableCameras.clear();
3167 }
3168 
3169 /*===========================================================================
3170  * FUNCTION        : GetCamerasNum
3171  *
3172  * DESCRIPTION     : Get the number of available cameras
3173  *
3174  * PARAMETERS      : None
3175  *
3176  * RETURN          : Number of cameras
3177  *==========================================================================*/
GetCamerasNum()3178 int32_t TestContext::GetCamerasNum()
3179 {
3180     return mAvailableCameras.size();
3181 }
3182 
3183 /*===========================================================================
3184  * FUNCTION        : AddScriptFromFile
3185  *
3186  * DESCRIPTION     : Add script from file
3187  *
3188  * PARAMETERS      :
3189  *   @scriptFile   : Script file
3190  *
3191  * RETURN          : status_t type of status
3192  *                   NO_ERROR  -- success
3193  *                   none-zero failure code
3194  *==========================================================================*/
AddScriptFromFile(const char * scriptFile)3195 status_t TestContext::AddScriptFromFile(const char *scriptFile)
3196 {
3197     mInterpreter = new Interpreter(scriptFile);
3198     mInterpreter->setTestCtxInst(this);
3199 
3200     return NO_ERROR;
3201 }
3202 
3203 /*===========================================================================
3204  * FUNCTION        : releasePiPBuff
3205  *
3206  * DESCRIPTION     : Release video in video temp buffer
3207  *
3208  * PARAMETERS      : None
3209  *
3210  * RETURN          : None
3211  *==========================================================================*/
releasePiPBuff()3212 void Interpreter::releasePiPBuff() {
3213     free(mTestContext->mViVBuff.buff);
3214     mTestContext->mViVBuff.buff = NULL;
3215 }
3216 
3217 /*===========================================================================
3218  * FUNCTION   : functionalTest
3219  *
3220  * DESCRIPTION: queries and executes client supplied commands for testing a
3221  *              particular camera.
3222  *
3223  * PARAMETERS :
3224  *  @availableCameras : List with all cameras supported
3225  *
3226  * RETURN     : status_t type of status
3227  *              NO_ERROR  -- continue testing
3228  *              none-zero -- quit test
3229  *==========================================================================*/
FunctionalTest()3230 status_t TestContext::FunctionalTest()
3231 {
3232     status_t stat = NO_ERROR;
3233 
3234     assert(mAvailableCameras.size());
3235 
3236     if ( !mInterpreter ) {
3237         mInterpreter = new Interpreter();
3238         mInterpreter->setTestCtxInst(this);
3239     }
3240 
3241 
3242     mTestRunning = true;
3243 
3244     while (mTestRunning) {
3245         sp<CameraContext> currentCamera =
3246             mAvailableCameras.itemAt(mCurrentCameraIndex);
3247         Interpreter::Command command =
3248             mInterpreter->getCommand(currentCamera);
3249         currentCamera->enablePrintPreview();
3250 
3251         switch (command.cmd) {
3252         case Interpreter::SWITCH_CAMERA_CMD:
3253         {
3254             mCurrentCameraIndex++;
3255             mCurrentCameraIndex %= mAvailableCameras.size();
3256             currentCamera = mAvailableCameras.itemAt(mCurrentCameraIndex);
3257         }
3258             break;
3259 
3260         case Interpreter::RESUME_PREVIEW_CMD:
3261         {
3262             stat = currentCamera->resumePreview();
3263         }
3264             break;
3265 
3266         case Interpreter::START_PREVIEW_CMD:
3267         {
3268             stat = currentCamera->startPreview();
3269         }
3270             break;
3271 
3272         case Interpreter::STOP_PREVIEW_CMD:
3273         {
3274             stat = currentCamera->stopPreview();
3275         }
3276             break;
3277 
3278         case Interpreter::CHANGE_VIDEO_SIZE_CMD:
3279         {
3280             if ( command.arg )
3281                 stat = currentCamera->setVideoSize(command.arg);
3282             else
3283                 stat = currentCamera->nextVideoSize();
3284         }
3285         break;
3286 
3287         case Interpreter::CHANGE_PREVIEW_SIZE_CMD:
3288         {
3289             if ( command.arg )
3290                 stat = currentCamera->setPreviewSize(command.arg);
3291             else
3292                 stat = currentCamera->nextPreviewSize();
3293         }
3294             break;
3295 
3296         case Interpreter::CHANGE_PICTURE_SIZE_CMD:
3297         {
3298             if ( command.arg )
3299                 stat = currentCamera->setPictureSize(command.arg);
3300             else
3301                 stat = currentCamera->nextPictureSize();
3302         }
3303             break;
3304 
3305         case Interpreter::DUMP_CAPS_CMD:
3306         {
3307             currentCamera->printSupportedParams();
3308         }
3309             break;
3310 
3311         case Interpreter::AUTOFOCUS_CMD:
3312         {
3313             stat = currentCamera->autoFocus();
3314         }
3315             break;
3316 
3317         case Interpreter::TAKEPICTURE_CMD:
3318         {
3319             stat = currentCamera->takePicture();
3320         }
3321             break;
3322 
3323         case Interpreter::TAKEPICTURE_IN_PICTURE_CMD:
3324         {
3325             if (mAvailableCameras.size() == 2) {
3326                 mSaveCurrentCameraIndex = mCurrentCameraIndex;
3327                 for (size_t i = 0; i < mAvailableCameras.size(); i++) {
3328                     mCurrentCameraIndex = i;
3329                     currentCamera = mAvailableCameras.itemAt(
3330                         mCurrentCameraIndex);
3331                     currentCamera->enablePiPCapture();
3332                     stat = currentCamera->takePicture();
3333                 }
3334                 mCurrentCameraIndex = mSaveCurrentCameraIndex;
3335             } else {
3336                 printf("Number of available sensors should be 2\n");
3337             }
3338         }
3339         break;
3340 
3341         case Interpreter::ENABLE_PRV_CALLBACKS_CMD:
3342         {
3343             stat = currentCamera->enablePreviewCallbacks();
3344         }
3345             break;
3346 
3347         case Interpreter::START_RECORD_CMD:
3348         {
3349             stat = currentCamera->stopPreview();
3350             stat = currentCamera->configureRecorder();
3351             stat = currentCamera->startPreview();
3352             stat = currentCamera->startRecording();
3353         }
3354             break;
3355 
3356         case Interpreter::STOP_RECORD_CMD:
3357         {
3358             stat = currentCamera->stopRecording();
3359 
3360             stat = currentCamera->stopPreview();
3361             stat = currentCamera->unconfigureRecorder();
3362             stat = currentCamera->startPreview();
3363         }
3364             break;
3365 
3366         case Interpreter::START_VIV_RECORD_CMD:
3367         {
3368 
3369             if (mAvailableCameras.size() == 2) {
3370                 mSaveCurrentCameraIndex = mCurrentCameraIndex;
3371                 stat = mInterpreter->configureViVCodec();
3372                 for ( size_t i = 0; i < mAvailableCameras.size(); i++ ) {
3373                     mCurrentCameraIndex = i;
3374                     currentCamera = mAvailableCameras.itemAt(
3375                         mCurrentCameraIndex);
3376                     stat = currentCamera->stopPreview();
3377                     stat = currentCamera->configureViVRecording();
3378                     stat = currentCamera->startPreview();
3379                     stat = currentCamera->startViVRecording();
3380                 }
3381                 mCurrentCameraIndex = mSaveCurrentCameraIndex;
3382             } else {
3383                 printf("Number of available sensors should be 2\n");
3384             }
3385 
3386         }
3387             break;
3388 
3389         case Interpreter::STOP_VIV_RECORD_CMD:
3390         {
3391             if (mAvailableCameras.size() == 2) {
3392                 mSaveCurrentCameraIndex = mCurrentCameraIndex;
3393                 for ( size_t i = 0; i < mAvailableCameras.size(); i++ ) {
3394                     mCurrentCameraIndex = i;
3395                     currentCamera = mAvailableCameras.itemAt(
3396                         mCurrentCameraIndex);
3397                     stat = currentCamera->stopViVRecording();
3398                     stat = currentCamera->stopPreview();
3399                     stat = currentCamera->unconfigureRecorder();
3400                     stat = currentCamera->startPreview();
3401                 }
3402                 stat = mInterpreter->unconfigureViVCodec();
3403                 mCurrentCameraIndex = mSaveCurrentCameraIndex;
3404 
3405                 mInterpreter->releasePiPBuff();
3406             } else {
3407                 printf("Number of available sensors should be 2\n");
3408             }
3409         }
3410         break;
3411 
3412         case Interpreter::EXIT_CMD:
3413         {
3414             currentCamera->stopPreview();
3415             mTestRunning = false;
3416         }
3417             break;
3418         case Interpreter::DELAY:
3419         {
3420             if ( command.arg )
3421                 usleep(1000 * atoi(command.arg));
3422         }
3423             break;
3424         default:
3425         {
3426             currentCamera->disablePrintPreview();
3427         }
3428             break;
3429         }
3430         printf("Command status 0x%x \n", stat);
3431     }
3432 
3433     return NO_ERROR;
3434 }
3435 
3436 /*===========================================================================
3437  * FUNCTION     : setViVSize
3438  *
3439  * DESCRIPTION  : Set video in video size
3440  *
3441  * PARAMETERS   :
3442  *   @VideoSize : video size
3443  *   @camIndex  : camera index
3444  *
3445  * RETURN       : none
3446  *==========================================================================*/
setViVSize(Size VideoSize,int camIndex)3447 void TestContext::setViVSize(Size VideoSize, int camIndex)
3448 {
3449     mViVVid.VideoSizes[camIndex] = VideoSize;
3450 }
3451 
3452 /*===========================================================================
3453  * FUNCTION     : main
3454  *
3455  * DESCRIPTION  : main function
3456  *
3457  * PARAMETERS   :
3458  *   @argc      : argc
3459  *   @argv      : argv
3460  *
3461  * RETURN       : int status
3462  *==========================================================================*/
main(int argc,char * argv[])3463 int main(int argc, char *argv[])
3464 {
3465     TestContext ctx;
3466 
3467     if (argc > 1) {
3468         if ( ctx.AddScriptFromFile((const char *)argv[1]) ) {
3469             printf("Could not add script file... "
3470                 "continuing in normal menu mode! \n");
3471         }
3472     }
3473 
3474     ctx.FunctionalTest();
3475 
3476     return 0;
3477 }
3478