Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

v4l2capture.c

00001 /*
00002  *  This program is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  This program is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with this program; if not, write to the Free Software
00014  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015  *
00016  */
00017 //========================================================================
00018 //
00019 // Desc: Some helper functions for capturing from v4l2 device
00020 // Author: Marcin Rudowski
00021 // Email: mar_rud@poczta.onet.pl
00022 // Date: 19 Jun 2006
00023 //
00024 //========================================================================
00025 #include <sys/time.h>
00026 #include <sys/mman.h>
00027 #include <sys/ioctl.h>
00028 #include <errno.h>
00029 #include <stdio.h>
00030 
00031 #include <player/error.h>
00032 
00033 
00034 #include "v4l2capture.h"
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 
00039 
00040 
00041 
00042 //==========================================================================
00043 //  Definitions
00044 //==========================================================================
00045 
00046 #define FREE_ME(x) if (x) free(x); x = NULL;
00047 #define CLEAR(x) memset(&x, 0, sizeof(x))
00048 
00049 
00050 #define PERROR(str_err) PLAYER_ERROR2("%s: %s", (str_err), strerror(errno))
00051 
00052 
00054 static int discover_inputs(FRAMEGRABBER2* fg);
00055 
00057 static void printControl(struct v4l2_queryctrl *queryctrl);
00058 
00060 static int discover_controls(FRAMEGRABBER2* fg);
00061 
00063 static void getPixelFormat(FRAMEGRABBER2 *fg);
00064 
00066 static int usePixelFormat(FRAMEGRABBER2 *fg);
00067 
00069 static int assignMBufs(FRAMEGRABBER2 *fg);
00070 
00072 static void releaseMBufs(FRAMEGRABBER2* fg);
00073 
00075 static void wyczyscStan(FRAMEGRABBER2* fg);
00076 
00078 static void fg2_close(FRAMEGRABBER2* fg);
00079 
00080 
00081 //==========================================================================
00082 //                  General access functions
00083 //==========================================================================
00084 
00085 
00090 FRAMEGRABBER2* fg2_createFrameGrabber()
00091 {
00092     FRAMEGRABBER2* fg = (FRAMEGRABBER2*)malloc( sizeof( FRAMEGRABBER2 ) );
00093 
00094     fg->device = 0;     // Device name, eg. "/dev/video"
00095     fg->fd = -1;         // File handle for open device
00096 
00097     fg->numOfIn = 0;    // Number of Inputa
00098     fg->sources = 0;    // Input sources[] (eg. TV, SVideo)
00099     fg->source = 0;     // Currently selected source
00100 
00101     fg->numOfCtls = 0;
00102     fg->controls = 0;
00103 
00104     fg->buffers = 0;   // memory mapped buffer
00105     fg->n_buffers = 0;
00106 
00107     fg->isCapturing = 0;
00108     fg->pix_fmt = V4L2_PIX_FMT_RGB24;
00109     fg->width = 640;
00110     fg->height = 480;
00111     fg->field = V4L2_FIELD_ANY;
00112     fg->altField = V4L2_FIELD_TOP;
00113 
00114     fg->cur_frame=-1;  // Currently capuring frame no.
00115 
00116 
00117     return fg;
00118 }
00119 //-----------------------------------------------
00120 
00121 
00126 void fg2_delete(FRAMEGRABBER2** fg)
00127 {
00128     fg2_close(*fg);
00129     FREE_ME(*fg);
00130 }
00131 //-----------------------------------------------
00132 
00140 int fg2_open( FRAMEGRABBER2* fg, const char *dev)
00141 {
00142     //FRAMEGRABBER2* fg = (FRAMEGRABBER2*)malloc( sizeof( FRAMEGRABBER2 ) );
00143     if (fg->device) {
00144         PLAYER_WARN("Device already opened?");
00145     }
00146 
00147   // Use default device if none specified
00148     if ( dev != NULL )
00149     {
00150         fg->device = strdup( dev );
00151     }
00152     else
00153     {
00154         fg->device = strdup( FG_DEFAULT_DEVICE );
00155     }
00156 
00157   // Open the video device
00158     fg->fd = open( fg->device, O_RDWR );
00159     if ( fg->fd == -1 )
00160     {
00161         PERROR( "fg2_open(): open video device failed" );
00162         free( fg->device );
00163         fg->device = 0;
00164         //free( fg );
00165         return -1;
00166     }
00167     PLAYER_MSG0(2,"opened v4l2 device");
00168 
00169   // Make sure child processes don't inherit video (close on exec)
00170     fcntl( fg->fd, F_SETFD, FD_CLOEXEC );
00171 
00172   // For n-ary buffering
00173     fg->cur_frame = -1;
00174 
00175   // Get the device capabilities
00176     if( ioctl( fg->fd, VIDIOC_QUERYCAP, &(fg->caps) ) < 0 )
00177     {
00178         PERROR( "fg2_open(): query capabilities failed" );
00179         fg2_close(fg);
00180         //free( fg );
00181         return -1;
00182     }
00183     // sprawdz czy to wystarcza
00184     if( ! (fg->caps.capabilities && V4L2_CAP_VIDEO_CAPTURE) ){
00185         PLAYER_ERROR("V4L2_CAP_VIDEO_CAPTURE not supported");
00186         fg2_close(fg);
00187         return -1;
00188     }
00189     if( ! (fg->caps.capabilities && V4L2_CAP_STREAMING) ){
00190         PLAYER_ERROR("V4L2_CAP_STREAMING not supported");
00191         fg2_close(fg);
00192         return -1;
00193     }
00194     PLAYER_MSG2(1,"Found %s card with %s v4l2 driver", fg->caps.card, fg->caps.driver);
00195 
00196     /*+++++++++++++++++++++++++++*/
00197   // Read info for all input sources
00198     discover_inputs(fg);
00199     if (fg->numOfIn<=0){
00200         PLAYER_ERROR("No Inputs found");
00201         fg2_close(fg);
00202         return -1;
00203     }
00204 
00205     return 0;
00206 }
00207 
00208 //==========================================================================
00209 //                  Capturing
00210 //==========================================================================
00211 
00212 
00217 int fg2_startCapture(FRAMEGRABBER2* fg)
00218 {
00219     unsigned int i;
00220     enum v4l2_buf_type type;
00221 
00222     if (fg->isCapturing) {
00223         PLAYER_WARN("Already capturing");
00224         return -1;
00225     }
00226 
00227 
00228     PLAYER_MSG0(2,"Assigning buffers");
00229     if (assignMBufs(fg)!=0){
00230         PERROR( "fg2_startCapture(): assignMBufs" );
00231         return -1;
00232     }
00233 
00234     PLAYER_MSG0(2,"Adding buffers to dirver Queue");
00235     for (i = 0; i < fg->n_buffers; ++i)
00236     {
00237         struct v4l2_buffer buf;
00238 
00239         CLEAR (buf);
00240 
00241         buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00242         buf.memory      = V4L2_MEMORY_MMAP;
00243         buf.index       = i;
00244 
00245         if (-1 == ioctl (fg->fd, VIDIOC_QBUF, &buf)) {
00246             PERROR("VIDIOC_QBUF");
00247             return -1;
00248         }
00249     }
00250 
00251     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00252 
00253     PLAYER_MSG0(2,"Turning streaming on");
00254     if (-1 == ioctl (fg->fd, VIDIOC_STREAMON, &type)) {
00255         PERROR ("VIDIOC_STREAMON");
00256         return -1;
00257     }
00258     fg->isCapturing = 1;
00259     PLAYER_MSG0(0,"Capturing started");
00260     return 0;
00261 }
00262 
00268 int fg2_stopCapture(FRAMEGRABBER2* fg)
00269 {
00270     enum v4l2_buf_type type;
00271 
00272     PLAYER_MSG0(2,"stopping capturing");
00273     if (!fg->isCapturing){
00274         PLAYER_WARN("Capturing not started yet");
00275         return -1;
00276     }
00277     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00278 
00279     // Streamoff sam odkolejkowuje bufory
00280     PLAYER_MSG0(2,"stopping streaminfg");
00281     if (-1 == ioctl (fg->fd, VIDIOC_STREAMOFF, &type)) {
00282         PERROR ("VIDIOC_STREAMOFF");
00283         //return -1;
00284     }
00285     PLAYER_MSG0(2,"Releasing buffers");
00286     releaseMBufs(fg);
00287     PLAYER_MSG0(0,"capture stopped");
00288     fg->isCapturing = 0;
00289     return 0;
00290 }
00291 
00292 
00293 
00300 struct my_buffer *getFrameBuffer( FRAMEGRABBER2* fg )
00301 {
00302     static struct v4l2_buffer buf;
00303     int rv;
00304     //CLEAR (buf);
00305 
00306     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00307     buf.memory = V4L2_MEMORY_MMAP;
00308     buf.field = fg->altField;
00309     if (buf.field == V4L2_FIELD_TOP)
00310         buf.field = V4L2_FIELD_BOTTOM;
00311     else
00312         buf.field = V4L2_FIELD_TOP;
00313 
00314     rv = ioctl(fg->fd, VIDIOC_DQBUF, &buf);
00315     if (rv==-1)
00316     {
00317         switch (errno)
00318         {
00319             case EAGAIN:
00320                 PERROR("VIDIOC_DQBUF, eagain");
00321                 return NULL;
00322             default:
00323                 PERROR("VIDIOC_DQBUF");
00324                 return NULL;
00325         }
00326     }
00327 
00328     if (buf.index >= fg->n_buffers) {
00329         PLAYER_ERROR2("Something wrong: buf.index(%d) >= n_buffers(%d)", buf.index, fg->n_buffers);
00330         if (-1 == ioctl (fg->fd, VIDIOC_QBUF, &buf)) {
00331             PERROR("VIDIOC_QBUF");
00332         }
00333         return NULL;
00334     }
00335     //memcpy(&(fg->buffers[buf.index].buf), &buf, sizeof(buf));
00336     fg->buffers[buf.index].buf = &buf;
00337 
00338     return fg->buffers + buf.index;
00339 }
00340 
00341 
00347 void giveBackFrameBuffer( FRAMEGRABBER2* fg, struct my_buffer *mBuff)
00348 {
00349     if (mBuff==NULL)
00350         return;
00351     if (-1 == ioctl (fg->fd, VIDIOC_QBUF, mBuff->buf)) {
00352         PERROR("VIDIOC_QBUF");
00353     }
00354 }
00355 
00356 
00357 //==========================================================================
00358 //                  Source selection
00359 //==========================================================================
00360 
00364 int fg2_get_source_count( FRAMEGRABBER2* fg )
00365 {
00366     return fg->numOfIn;
00367 }
00368 
00372 int fg2_get_source_id( FRAMEGRABBER2* fg)
00373 {
00374     int out=0;
00375 
00376     if ( ioctl( fg->fd, VIDIOC_G_INPUT, &out ) < 0 )
00377     {
00378         PERROR( "fg2_get_source_id(): VIDIOC_G_INPUT failed" );
00379         return -1;
00380     }
00381     return out;
00382 }
00383 
00387 const char* fg2_get_source_name( FRAMEGRABBER2* fg)
00388 {
00389     return fg2_get_id_source_name(fg, fg2_get_source_id(fg));
00390 }
00391 
00395 const char* fg2_get_id_source_name( FRAMEGRABBER2* fg, int src )
00396 {
00397     if ( src<0 || (unsigned int)src > fg->numOfIn )
00398     {
00399         PLAYER_ERROR("fg2_get_source_name(): Invalid src number!" );
00400         return NULL;
00401     }
00402 
00403     return (const char *)fg->sources[src].name;
00404 }
00405 
00409 const char * fg2_get_device_name( FRAMEGRABBER2* fg )
00410 {
00411     return (const char *)(fg->caps.card);
00412 }
00413 
00419 int fg2_set_source( FRAMEGRABBER2* fg, int srcNo, const char *strSrc )
00420 {
00421     if (srcNo<0) {
00422         PLAYER_MSG1(1,"\t\tSetting SourceS: %s", strSrc);
00423         if (strSrc==NULL)
00424             srcNo=0;
00425         else {
00426             for(srcNo=0; (unsigned int)srcNo < fg->numOfIn; srcNo++)
00427                 if (strcasecmp(strSrc,(const char *)fg->sources[srcNo].name)==0)
00428                     break;
00429             if ((unsigned int)srcNo >= fg->numOfIn)
00430                 srcNo = -1;
00431         }
00432     } else
00433         PLAYER_MSG1(1,"\t\tSetting SourceI: %d", srcNo);
00434 
00435     if ( srcNo<0 ||  (unsigned int)srcNo >= fg->numOfIn )
00436     {
00437         PLAYER_ERROR2("fg2_set_sourced(): Invalid source number (%d > %d)r!", srcNo, fg->numOfIn );
00438         return -1;
00439     }
00440     PLAYER_MSG3(1,"selecting\t%d - %s (%d)", srcNo, fg->sources[srcNo].name, fg->sources[srcNo].type);
00441 
00442     fg->source = srcNo;
00443 
00444     if ( ioctl( fg->fd, VIDIOC_S_INPUT, &(fg->sources[srcNo]) ) < 0 )
00445     {
00446         PERROR( "fg2_set_source(): set source failed" );
00447         return -1;
00448     }
00449     // controls can be different per source
00450     discover_controls(fg);
00451 
00452     return 0;
00453 }
00454 
00455 
00456 
00457 //==========================================================================
00458 //                  Changing settings by controls
00459 //==========================================================================
00460 
00464 int fg2_countControls( FRAMEGRABBER2* fg)
00465 {
00466     return fg->numOfCtls;
00467 }
00468 
00473 int fg2_setControlValueI( FRAMEGRABBER2* fg, int id, double val)
00474 {
00475     struct v4l2_control control;
00476     unsigned int uVal;
00477 
00478     if (id<0 || (unsigned int)id>fg->numOfCtls)
00479         return -1;
00480 
00481     PLAYER_MSG2(2, "Setting value %f to '%s'", val, fg->controls[id].name);
00482 
00483     uVal = fg->controls[id].default_value;
00484 
00485     if (val>1.0){
00486         PLAYER_WARN1("value %f out of range for control:", val);
00487         printControl(&(fg->controls[id]));
00488         return -2;
00489     }
00490     if (val>=0.0 && fg->controls[id].minimum != fg->controls[id].maximum) {
00491         uVal = fg->controls[id].minimum +
00492                 (unsigned int )( val*(fg->controls[id].maximum
00493                 - fg->controls[id].minimum));
00494         PLAYER_MSG2(2, "uint value %u of '%f'", uVal, val);
00495     }
00496 
00497     memset (&control, 0, sizeof (control));
00498     control.id = fg->controls[id].id;
00499     control.value = uVal;
00500     if (ioctl (fg->fd, VIDIOC_S_CTRL, &control)!=0){
00501         PERROR("VIDIOC_S_CTRL");
00502         PLAYER_WARN1("Failed to set value %f to control:", val);
00503         printControl(&(fg->controls[id]));
00504         return -3;
00505     }
00506     usleep(50000);
00507     PLAYER_MSG1(2, "Value written %u'", control.value);
00508 
00509     return 0;
00510 }
00511 
00516 int fg2_setControlValue( FRAMEGRABBER2* fg, const char *id, double val)
00517 {
00518     unsigned int i;
00519     for(i=0; i<fg->numOfCtls; i++){
00520         if (strcasecmp(id, (const char *)fg->controls[i].name) == 0){
00521             return fg2_setControlValueI(fg, i, val);
00522         }
00523     }
00524     return -1;
00525 }
00526 
00531 double fg2_getControlValueI( FRAMEGRABBER2* fg, int id)
00532 {
00533     struct v4l2_control control;
00534     double dval;
00535 
00536     if (id<0 || (unsigned int)id>fg->numOfCtls)
00537         return -1;
00538 
00539     memset (&control, 0, sizeof (control));
00540     control.id = fg->controls[id].id;
00541     if (ioctl (fg->fd, VIDIOC_G_CTRL, &control)!=0){
00542         PERROR("VIDIOC_G_CTRL");
00543         PLAYER_WARN("Failed to get value of control:");
00544         printControl(&(fg->controls[id]));
00545         return -3;
00546     }
00547 
00548     if (fg->controls[id].maximum == fg->controls[id].minimum )
00549         return 0.0;
00550     dval = (double)(control.value - fg->controls[id].minimum)
00551                    / (fg->controls[id].maximum-fg->controls[id].minimum);
00552     PLAYER_MSG2(2, "uint value %u of '%f'", control.value, dval);
00553     return dval;
00554 }
00555 
00560 double fg2_getControlValue( FRAMEGRABBER2* fg, const char *id)
00561 {
00562     unsigned int i;
00563     for(i=0; i<fg->numOfCtls; i++){
00564         if (strcasecmp(id, (const char *)fg->controls[i].name) == 0){
00565             return fg2_getControlValueI(fg, i);
00566         }
00567     }
00568     return -1.0;
00569 }
00570 
00571 const char *fg2_getControlName( FRAMEGRABBER2* fg, int id)
00572 {
00573     if (id<0 || (unsigned int)id>=fg->numOfCtls)
00574         return 0;
00575     return (const char *)fg->controls[id].name;
00576 }
00577 
00578 //==========================================================================
00579 //                  Other settings
00580 //==========================================================================
00581 
00582 
00586 int fg2_set_source_norm( FRAMEGRABBER2* fg, v4l2_std_id norm )
00587 {
00588     PLAYER_MSG0(1,"setting new norm");
00589     return 0;
00590     if ( ioctl( fg->fd, VIDIOC_S_STD, &norm ) < 0 )
00591     {
00592         PERROR( "Mfg2_set_source_norm(): set channel/norm failed" );
00593         return -1;
00594     }
00595 
00596     return 0;
00597 }
00598 
00599 
00603 int fg2_setPixelSettings( FRAMEGRABBER2* fg, int width, int height,
00604                           unsigned int fmt, enum v4l2_field fld, int dpth )
00605 {
00606     PLAYER_MSG0(2,"fg2_set_capture_window()");
00607 
00608     fg->width = width;
00609     fg->height = height;
00610     fg->pix_fmt = fmt;
00611     fg->field = fld;
00612     fg->depth = dpth;
00613     ;
00614     return usePixelFormat(fg);
00615 }
00616 
00617 
00618 
00619 
00620 
00621 //==========================================================================
00622 //                  static functions
00623 //==========================================================================
00624 
00625 
00626 
00632 static int discover_inputs(FRAMEGRABBER2* fg)
00633 {
00634     struct v4l2_input input2;
00635     unsigned int i;
00636     fg->numOfIn=0;
00637     PLAYER_MSG0(2,"discover_inputs()");
00638 
00639     // okresl ile:
00640     for (fg->numOfIn = 0;; fg->numOfIn++) {
00641         memset(&input2,0,sizeof(input2));
00642         input2.index = fg->numOfIn;
00643         if (0 != ioctl( fg->fd, VIDIOC_ENUMINPUT, &input2 ) )
00644             break;
00645     }
00646     fg->source = 0;
00647     fg->sources = (struct v4l2_input *)malloc( sizeof( struct v4l2_input )*fg->numOfIn );
00648     PLAYER_MSG1(1,"Found sources: %d", fg->numOfIn);
00649     for ( i = 0; i < fg->numOfIn; i++ ) {
00650         fg->sources[i].index = i;
00651         ioctl( fg->fd, VIDIOC_ENUMINPUT, &(fg->sources[i]) );
00652         PLAYER_MSG3(1,"\t%d - %s (%d)", i, fg->sources[i].name, fg->sources[i].type);
00653     }
00654 
00655     return 0;
00656 }
00657 
00658 
00659 
00660 
00661 const char *ctlTypeToString[] = {
00662     "Unknown",
00663     "Integer", // 0-max-1
00664     "Boolean", // 0/1
00665     "Menu",    // 0-max-1
00666     "Button",  // dont care
00667 };
00668 
00669 
00670 static void printControl(struct v4l2_queryctrl *queryctrl){
00671     double procent = (queryctrl->default_value-queryctrl->minimum)*1.0
00672                    / (queryctrl->maximum-queryctrl->minimum);
00673     PLAYER_MSG6(1,"\t\"%s\" = %0.4f (def: %d, min: %d, max: %d) of %s",
00674           queryctrl->name,
00675           procent,
00676           queryctrl->default_value,
00677           queryctrl->minimum,
00678           queryctrl->maximum,
00679           ctlTypeToString[queryctrl->type]);
00680 }
00681 
00682 
00683 static int discover_controls(FRAMEGRABBER2* fg)
00684 {
00685     struct v4l2_queryctrl queryctrl;
00686     unsigned int counter;
00687     int i=0;
00688     PLAYER_MSG0(1,"Discovering controls:");
00689 
00690     fg->numOfCtls = 0;
00691     FREE_ME(fg->controls);
00692 
00693     memset (&queryctrl, 0, sizeof (queryctrl));
00694 
00695     for (queryctrl.id = V4L2_CID_BASE;
00696                 queryctrl.id < V4L2_CID_LASTP1 && i<10000;
00697                 queryctrl.id++, i++) {
00698         if (0 == ioctl (fg->fd, VIDIOC_QUERYCTRL, &queryctrl)) {
00699             if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00700                 continue;
00701 
00702             fg->numOfCtls++;
00703 
00704             //if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00705             //    enumerate_menu ();
00706         } else {
00707             if (errno == EINVAL)
00708                 continue;
00709 
00710             PERROR ("VIDIOC_QUERYCTRL");
00711             break;
00712         }
00713     }
00714 
00715     for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;queryctrl.id++) {
00716         if (0 == ioctl (fg->fd, VIDIOC_QUERYCTRL, &queryctrl)) {
00717             if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00718                 continue;
00719 
00720             fg->numOfCtls++;
00721 
00722             //if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00723             //    enumerate_menu ();
00724         } else {
00725             if (errno == EINVAL) {
00726                 if (queryctrl.id - V4L2_CID_PRIVATE_BASE < 100)
00727                     continue;
00728                 break;
00729             }
00730 
00731             PERROR ("VIDIOC_QUERYCTRL");
00732             break;
00733         }
00734     }
00735 
00736     if (fg->numOfCtls<=0) {
00737         PLAYER_WARN("\tNo controls");
00738         return  0;
00739     }
00740     fg->controls = (struct v4l2_queryctrl *)malloc( sizeof( struct v4l2_queryctrl )*fg->numOfCtls );
00741     counter = 0;
00742 
00743 
00744 
00745     memset (&queryctrl, 0, sizeof (queryctrl));
00746 
00747 
00748     i=0;
00749     for (queryctrl.id = V4L2_CID_BASE;
00750                 queryctrl.id < V4L2_CID_LASTP1 && i<10000;
00751                 queryctrl.id++, i++) {
00752         if (counter >= fg->numOfCtls)
00753             break;
00754         memset (&(fg->controls[counter]), 0, sizeof (fg->controls[counter]));
00755         fg->controls[counter].id = queryctrl.id;
00756         if (0 == ioctl (fg->fd, VIDIOC_QUERYCTRL, &(fg->controls[counter]))) {
00757             if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00758                 continue;
00759 
00760             printControl(&(fg->controls[counter]));
00761             counter++;
00762 
00763             //if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00764             //    enumerate_menu ();
00765         } else {
00766             if (errno == EINVAL)
00767                 continue;
00768 
00769             PERROR ("VIDIOC_QUERYCTRL");
00770             break;
00771         }
00772     }
00773 
00774     for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;queryctrl.id++) {
00775         if (counter >= fg->numOfCtls)
00776             break;
00777         memset (&(fg->controls[counter]), 0, sizeof (fg->controls[counter]));
00778         fg->controls[counter].id = queryctrl.id;
00779         if (0 == ioctl (fg->fd, VIDIOC_QUERYCTRL, &(fg->controls[counter]))) {
00780             if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00781                 continue;
00782 
00783             printControl(&(fg->controls[counter]));
00784             counter++;
00785 
00786             //if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
00787             //    enumerate_menu ();
00788         } else {
00789             if (errno == EINVAL) {
00790                 if (queryctrl.id - V4L2_CID_PRIVATE_BASE < 100)
00791                     continue;
00792                 break;
00793             }
00794 
00795             PERROR ("VIDIOC_QUERYCTRL");
00796             break;
00797         }
00798     }
00799 
00800     if (counter<fg->numOfCtls)
00801         fg->numOfCtls = counter;
00802 
00803 
00804 
00805     return 0;
00806 }
00807 
00808 static void getPixelFormat(FRAMEGRABBER2 *fg){
00809     char tmpp[5];
00810     tmpp[0] = tmpp[4] = 0;
00811     CLEAR (fg->frmt);
00812     fg->frmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00813     if (-1 == ioctl (fg->fd, VIDIOC_G_FMT, &(fg->frmt)))
00814     {
00815         PLAYER_ERROR1("VIDIOC_G_FMT: %s", strerror(errno));
00816         memcpy(tmpp, &(fg->frmt.fmt.pix.pixelformat), 4);
00817         PLAYER_ERROR3("got (%d, %d) %s", fg->frmt.fmt.pix.width, fg->frmt.fmt.pix.height, tmpp);
00818     } else {
00819         fg->width = fg->frmt.fmt.pix.width;
00820         fg->height = fg->frmt.fmt.pix.height;
00821         fg->pix_fmt = fg->frmt.fmt.pix.pixelformat;
00822         fg->field = fg->frmt.fmt.pix.field;
00823     }
00824 
00825 }
00826 
00831 static int usePixelFormat(FRAMEGRABBER2 *fg)
00832 {
00833     char tmpp[5];
00834     tmpp[0] = tmpp[4] = 0;
00835     memcpy(tmpp, &(fg->pix_fmt), 4);
00836     PLAYER_MSG3(1,"Changing pixel and frame format (%dx%d, %s)", fg->width, fg->height, tmpp);
00837         //struct v4l2_format fmt;
00838     CLEAR (fg->frmt);
00839     fg->frmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00840     fg->frmt.fmt.pix.width       = fg->width;
00841     fg->frmt.fmt.pix.height      = fg->height;
00842 
00843     fg->frmt.fmt.pix.pixelformat = fg->pix_fmt;
00844     fg->frmt.fmt.pix.field       = fg->field;
00845 
00846     if (-1 == ioctl (fg->fd, VIDIOC_S_FMT, &(fg->frmt)))
00847     {
00848         PLAYER_ERROR1("VIDIOC_S_FMT: %s", strerror(errno));
00849         memcpy(tmpp, &(fg->frmt.fmt.pix.pixelformat), 4);
00850         PLAYER_ERROR3("got (%d, %d) %s", fg->frmt.fmt.pix.width, fg->frmt.fmt.pix.height, tmpp);
00851         //return 0;
00852         getPixelFormat(fg);
00853         return -1;
00854     }
00855     if (fg->frmt.fmt.pix.bytesperline*8 != fg->depth*fg->width) {
00856         PLAYER_ERROR("Padding unsuported");
00857         getPixelFormat(fg);
00858         printf("Test");
00859         //return -1;
00860     }
00861 
00862     if (        fg->frmt.fmt.pix.width != fg->width ||
00863                 fg->frmt.fmt.pix.height != fg->height )
00864     {
00865         PLAYER_ERROR("Failed to apply required frame size settings");
00866         getPixelFormat(fg);
00867         return -1;
00868     }
00869 
00870     return 0;
00871 }
00872 
00873 
00874 
00879 static int assignMBufs(FRAMEGRABBER2 *fg){
00880     struct v4l2_requestbuffers req;
00881     PLAYER_MSG0(2,"assignMBufs()");
00882 
00883     CLEAR (req);
00884 
00885     req.count               = 2; // liczba buforow. minimum 2, moze byc wiecej
00886     req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00887     req.memory              = V4L2_MEMORY_MMAP;
00888 
00889     if (-1 == ioctl (fg->fd, VIDIOC_REQBUFS, &req)) {
00890         if (EINVAL == errno) {
00891             PLAYER_ERROR ("device does not support " "memory mapping");
00892             PLAYER_ERROR1("device does not support " "memory mapping: %s", strerror(errno));
00893         } else {
00894             PLAYER_ERROR1("VIDIOC_REQBUFS: %s", strerror(errno));
00895         }
00896         return -1;
00897     }
00898 
00899     if (req.count < 2)
00900     {
00901         PLAYER_ERROR ("Insufficient buffer memory on device");
00902         return -1;
00903     }
00904 
00905     //FREE_ME( fg->buffers );
00906     fg->buffers = (struct my_buffer*)calloc (req.count, sizeof (*fg->buffers));
00907 
00908     if (!fg->buffers)
00909     {
00910         PLAYER_ERROR ( "Out of memory");
00911         return -1;
00912     }
00913 
00914     // powiadom sterownik v4l2 o posiadanych buforach
00915     for (fg->n_buffers = 0; fg->n_buffers < req.count; ++fg->n_buffers)
00916     {
00917         struct v4l2_buffer buf;
00918 
00919         CLEAR (buf);
00920 
00921         buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00922         buf.memory      = V4L2_MEMORY_MMAP;
00923         buf.index       = fg->n_buffers;
00924 
00925         if (-1 == ioctl (fg->fd, VIDIOC_QUERYBUF, &buf)){
00926             PLAYER_ERROR1("VIDIOC_QUERYBUF: %s", strerror(errno));
00927             return -1;
00928         }
00929 
00930         fg->buffers[fg->n_buffers].id = fg->n_buffers;
00931         fg->buffers[fg->n_buffers].length = buf.length;
00932         fg->buffers[fg->n_buffers].start = mmap(
00933                     NULL /* start anywhere */,
00934                     buf.length,
00935                     PROT_READ | PROT_WRITE /* required */,
00936                     MAP_SHARED /* recommended */,
00937                     fg->fd, buf.m.offset
00938                 );
00939 
00940         if (MAP_FAILED == fg->buffers[fg->n_buffers].start) {
00941             PLAYER_ERROR1("MMAP: %s", strerror(errno));
00942             return -1;
00943         }
00944     }
00945 
00946     return 0;
00947 }
00948 
00949 static void releaseMBufs(FRAMEGRABBER2* fg){
00950     unsigned int i;
00951     for (i = 0; i < fg->n_buffers; ++i) {
00952         if (-1 == munmap (fg->buffers[i].start, fg->buffers[i].length))
00953             PLAYER_ERROR1("munmap: %s", strerror(errno));
00954     }
00955     FREE_ME(fg->buffers);
00956     fg->n_buffers = 0;
00957 
00958 }
00959 
00960 
00961 
00962 
00963 
00967 static void wyczyscStan(FRAMEGRABBER2* fg)
00968 {
00969     unsigned int i;
00970     if (fg->isCapturing)
00971         fg2_stopCapture(fg);
00972 
00973     for (i = 0; i < fg->n_buffers; ++i)
00974         if (-1 == munmap (fg->buffers[i].start, fg->buffers[i].length))
00975             PERROR("munmap");
00976     fg->n_buffers=0;
00977 
00978     //if (fg->fd>0)
00979     //    close( fg->fd );
00980     //fg->fd = 0;
00981 
00982     // Make sure we free all memory (backwards!)
00983     FREE_ME( fg->buffers );
00984     FREE_ME( fg->device );
00985     FREE_ME( fg->sources );
00986     //free( fg );
00987 }
00988 
00989 
00994 static void fg2_close(FRAMEGRABBER2* fg)
00995 {
00996     wyczyscStan(fg);
00997     if (fg->fd>0)
00998         close( fg->fd );
00999     fg->fd = 0;
01000 }
01001 
01002 
01003 /*
01004 static int fg2_get_source_type( FRAMEGRABBER2* fg, int ch )
01005 {
01006     if ( ch<0 || (unsigned int)ch > fg->numOfIn )
01007     {
01008         PLAYER_ERROR("fg2_get_source_type(): Invalid channel number!" );
01009         return -1;
01010     }
01011 
01012     return fg->sources[ch].type;
01013 }//*/
01014 
01015 
01016 
01017 
01018 

Generated on Thu Jun 29 22:04:43 2006 for Camerav4l2 by  doxygen 1.4.4