//static bool first = true; // TODO: this is a hack for testing. void V4L2CaptureStream::threadMain()// throws CaptureException; { int res; //if (first) { printf("V4L2CaptureStream::threadMain()\n"); fflush(stdout); streamThrottle.waitUntilStart(); //first = false; printf("V4L2CaptureStream streamThrottle.waitUntilStart completed\n"); fflush(stdout); } res = fg2_startCapture(fg); if (res != 0) FailWithException("fg2_startCapture failed", res); while (!disposing) { struct my_buffer* frame = NULL; // TODO: support double-buffering. // printf("V4L2CaptureStream::fg2_grab...\n"); //fflush(stdout); frame = getFrameBuffer( fg ); // printf("V4L2CaptureStream::fg2_grab: %lx\n", (unsigned long) frame); //fflush(stdout); if (frame == 0) FailWithException("getFrameBuffer failed", -1); // TODO: notify observer instead. void *data = frame->start; int width = format.getWidth(); int height = format.getHeight(); switch (formatTypeV4L2) { // TODO: other formats case V4L2_PIX_FMT_RGB24: if (observer != 0) { Image image = Image(format, (unsigned char *) data, width * height * 3); observer->onNewImage(this, &image); } break; case V4L2_PIX_FMT_YUYV: if (observer != 0) { // 4 bytes = 2 pixels Image image = Image(format, yuyvToRGB((unsigned char *) data, width, height), width * height * 3, true); observer->onNewImage(this, &image); } break; case V4L2_PIX_FMT_RGB32: if (observer != 0) { Image image = Image(format, (unsigned char *) data, width * height * 4); observer->onNewImage(this, &image); } break; case V4L2_PIX_FMT_YUV420: { if (rgbbufsize == 0) { rgbbufsize = width * height * 3; rgbbuf = new unsigned char[rgbbufsize]; } yuv2rgb_buf((unsigned char *) data, width, height, rgbbuf); if (observer != 0) { Image image = Image(format, rgbbuf, rgbbufsize); observer->onNewImage(this, &image); } } break; default: printf("unknown or unsupported: %i\n", formatTypeV4L2); //FailWithException("unknown or unsupported format", formatTypeV4L2); } giveBackFrameBuffer(fg, frame); } res = fg2_stopCapture(fg); if (res != 0) FailWithException("fg2_stopCapture failed", res); fg2_delete(&fg); if (rgbbuf != 0) { delete[] rgbbuf; rgbbuf = 0; } disposed = true; }
/** * handle command without reply * @param cmd command in text representation * @param len length of cmd (including '\0') * @return 0 ok, -1 failure */ int CameraV4L2::handleCommand(char *cmd, int len){ int w; int h; enum v4l2_field fld; int ret=-1; unsigned int a,b,c; // backup double dblVal; ret = -1; // error on default PLAYER_MSG1(2,"Got command %s", cmd); switch(cmd[0]){ case 's': case 'S': if (sscanf(cmd+1," %d %d", &w, &h)!=2) break; fg2_stopCapture(fg); ret = tryPixelSettings(fg, w, h, this->v4l2_type_id, fieldType); fg2_startCapture(fg); break; case 'i': case 'I': // todo: rollback if needed if (cmd[2]>='0' && cmd[2]<='9') sscanf(cmd+2,"%d", &(this->source)); else { this->source = -1; } fg2_stopCapture(fg); ret = fg2_set_source(this->fg, this->source, cmd+2); fg2_startCapture(fg); break; case 'n': case 'N': a = this->norm; b = this->width; c = this->height; if (cmd[1]!=' ' || selectFormat(cmd+2)!=0) break; fg2_stopCapture(fg); ret = fg2_set_source_norm(this->fg, this->norm); ret |= tryPixelSettings(fg, this->width, this->height, this->v4l2_type_id, fieldType); if (ret!=0) { this->norm = a; this->width = b; this->height = c; // known working? fg2_set_source_norm(this->fg, this->norm); tryPixelSettings(fg, this->width, this->height, this->v4l2_type_id, fieldType); } fg2_startCapture(fg); break; case 'm': case 'M': a = this->data.format; b = this->depth; c = this->v4l2_type_id; if (cmd[1]!=' ' || selectFormat(cmd+2)!=0) break; fg2_stopCapture(fg); ret = tryPixelSettings(fg, this->width, this->height, this->v4l2_type_id, fieldType); if (ret!=0) { this->data.format = a; this->depth = b; this->v4l2_type_id = c; ret = tryPixelSettings(fg, this->width, this->height, this->v4l2_type_id, fieldType); } fg2_startCapture(fg); break; case 'w': case 'W': // todo: rollback if needed if (cmd[2]>='0' && cmd[2]<='9'){ sscanf(cmd+2,"%d", &(this->flip_rb)); ret = 0; } break; case 'f': case 'F': fld = fieldType; if (cmd[1]!=' ' || selectField(cmd+2)!=0) break; fg2_stopCapture(fg); ret = tryPixelSettings(fg, this->width, this->height, this->v4l2_type_id, fieldType); fg2_startCapture(fg); if (ret!=0) { fieldType = fld; } break; case 'c': case 'C': if (cmd[1] == 'i' || cmd[1] == 'I') { if (sscanf(cmd+2, "%lf %u", &dblVal, &a)!=2) break; ret = fg2_setControlValueI(fg, a, dblVal); break; } for(w=2; w<len-1; w++) if (cmd[w]==' ' || cmd[w+1]=='\0') break; if (sscanf(cmd+2,"%lf",&dblVal) != 1) break; ret = fg2_setControlValue(fg, cmd+w+1, dblVal); break; default: PLAYER_WARN1("Unknown command %s",cmd); break; } return ret; }