static dc1394error_t windows_capture_setup (platform_camera_t * craw, uint32_t num_dma_buffers, uint32_t flags) { int i; free_resources(craw); ULARGE_INTEGER dma_buffer_size; const char * device_path = craw->device->device_path; t1394_GetHostDmaCapabilities (device_path, NULL, &dma_buffer_size); const dc1394video_frame_t * frame = &craw->capture.frames[0]; int max_buffer_size = frame->total_bytes; //number of bytes needed int max_bytes = frame->packet_size / 2; PACQUISITION_BUFFER acquisition_buffer = dc1394BuildAcquisitonBuffer(max_buffer_size, (unsigned long)dma_buffer_size.QuadPart, max_bytes, 0); ISOCH_STREAM_PARAMS stream_params; if (acquisition_buffer) { stream_params.nMaxBufferSize = acquisition_buffer->subBuffers[0].ulSize; stream_params.nNumberOfBuffers = (num_dma_buffers * acquisition_buffer->nSubBuffers) + 1; // free the buffer: this wouldn't be necessary if this were merged into StartImageAcquisitionEx dc1394FreeAcquisitionBuffer(acquisition_buffer); acquisition_buffer = NULL; } else { dc1394_log_error("windows_capture_setup: failed to determine required buffer size and count!"); return DC1394_FAILURE; } dc1394speed_t speed; if (dc1394_video_get_iso_speed(craw->camera, &speed) != DC1394_SUCCESS) { dc1394_log_error("windows_capture_setup: failed to get iso speed!"); return DC1394_FAILURE; } uint32_t channel = -1; stream_params.fulSpeed = 1 << speed; stream_params.nChannel = channel; stream_params.nMaxBytesPerFrame = max_bytes; DWORD ret = t1394IsochSetupStream(craw->device->device_path, &stream_params); craw->allocated_channel = stream_params.nChannel; if (ret != ERROR_SUCCESS) { dc1394_log_error("windows_capture_setup: Error on IsochSetupStream: %d\n", ret); return DC1394_FAILURE; } #if 1 // allocate channel/bandwidth if requested if (flags & DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC) { if (dc1394_iso_allocate_channel (craw->camera, 0, &craw->allocated_channel) != DC1394_SUCCESS) { return DC1394_FAILURE; } if (dc1394_video_set_iso_channel (craw->camera, craw->allocated_channel) != DC1394_SUCCESS) { return DC1394_FAILURE; } } #endif #if 1 if (flags & DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC) { unsigned int bandwidth_usage; if (dc1394_video_get_bandwidth_usage (craw->camera, &bandwidth_usage) != DC1394_SUCCESS) { return DC1394_FAILURE; } if (dc1394_iso_allocate_bandwidth (craw->camera, bandwidth_usage) != DC1394_SUCCESS) { return DC1394_FAILURE; } craw->allocated_bandwidth = bandwidth_usage; } #endif /* QUEUE the buffers */ for (i = 0; i < num_dma_buffers; ++i) { PACQUISITION_BUFFER buffer = dc1394BuildAcquisitonBuffer(max_buffer_size, dma_buffer_size.QuadPart, max_bytes, i); if(!buffer) { dc1394_log_error("windows_capture_setup: Error Allocating AcqBuffer %d\n", i); return DC1394_FAILURE; } // add it to our list of buffers if (i == 0) { craw->pLastBuffer = craw->pFirstBuffer = buffer; craw->pLastBuffer->pNextBuffer = craw->pCurrentBuffer = NULL; } else { craw->pFirstBuffer->pNextBuffer = buffer; craw->pFirstBuffer = buffer; } } // all done making buffers // open our long term device handle HANDLE device; if((device = OpenDevice(device_path, TRUE)) == INVALID_HANDLE_VALUE) { dc1394_log_error("windows_capture_setup error opening device (%s)\n", craw->device->device_path); return DC1394_FAILURE; } // all done making buffers // open our long term device handle PACQUISITION_BUFFER buffer; for (buffer = craw->pLastBuffer; buffer != NULL; buffer = buffer->pNextBuffer) { DWORD ret = dc1394AttachAcquisitionBuffer(device, buffer); if (ret != ERROR_SUCCESS) { dc1394_log_error("windows_capture_setup: Failed to attach buffer %u/%u", buffer->index, num_dma_buffers); return DC1394_FAILURE; } } // new: sleep a little while and verify that the buffers were // successfully attached this basically catches "Parameter is Incorrect" // here instead of confusing users at AcquireImageEx() // 50 ms is all it should take for completion routines to fire and // propagate in the kernel Sleep(50); for (buffer = craw->pLastBuffer; buffer != NULL; buffer = buffer->pNextBuffer) { DWORD dwBytesRet = 0; for (unsigned int bb = 0; bb < buffer->nSubBuffers; ++bb) { if (!GetOverlappedResult(device, &(buffer->subBuffers[bb].overLapped), &dwBytesRet, FALSE)) { if (GetLastError() != ERROR_IO_INCOMPLETE) { dc1394_log_error("Buffer validation failed for buffer %u\n", buffer->index,bb); return DC1394_FAILURE; } // else: this is the actual success case } else { dc1394_log_error("Buffer %u is unexpectedly ready during pre-listen validation\n", buffer->index, bb); return DC1394_FAILURE; } } } ret = t1394IsochListen(craw->device->device_path); if (ret != ERROR_SUCCESS) { dc1394_log_error("Error %08lx on IOCTL_ISOCH_LISTEN\n", ret); return DC1394_FAILURE; } // starting from here we use the ISO channel so we set the flag // in the camera struct: craw->capture_is_set = 1; for (i = 1; i < num_dma_buffers; ++i) { memcpy(&craw->capture.frames[i], frame, sizeof (dc1394video_frame_t)); } craw->capture.frames_last_index = num_dma_buffers - 1; craw->device_acquisition = device; return DC1394_SUCCESS; }
dc1394error_t dc1394_juju_capture_setup(platform_camera_t *craw, uint32_t num_dma_buffers, uint32_t flags) { struct fw_cdev_create_iso_context create; struct fw_cdev_start_iso start_iso; dc1394error_t err; dc1394video_frame_t proto; int i, j, retval; dc1394camera_t * camera = craw->camera; if (flags & DC1394_CAPTURE_FLAGS_DEFAULT) flags = DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC | DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC; craw->flags = flags; // if capture is already set, abort if (craw->capture_is_set>0) return DC1394_CAPTURE_IS_RUNNING; // if auto iso is requested, stop ISO (if necessary) if (flags & DC1394_CAPTURE_FLAGS_AUTO_ISO) { dc1394switch_t is_iso_on; dc1394_video_get_transmission(camera, &is_iso_on); if (is_iso_on == DC1394_ON) { err=dc1394_video_set_transmission(camera, DC1394_OFF); DC1394_ERR_RTN(err,"Could not stop ISO!"); } } if (capture_basic_setup(camera, &proto) != DC1394_SUCCESS) { dc1394_log_error("basic setup failed"); return DC1394_FAILURE; } if (flags & (DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC | DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC)) { uint64_t channels_allowed = 0; unsigned int bandwidth_units = 0; int channel; if (flags & DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC) channels_allowed = 0xffff; if (flags & DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC) dc1394_video_get_bandwidth_usage (camera, &bandwidth_units); err = juju_iso_allocate (craw, channels_allowed, bandwidth_units, &craw->capture_iso_resource); if (err == DC1394_SUCCESS) { channel = craw->capture_iso_resource->channel; } else if (err == DC1394_FUNCTION_NOT_SUPPORTED) { channel = craw->node_id & 0x3f; dc1394_log_warning ("iso allocation not available in this kernel, " "using channel %d...", channel); } else { dc1394_log_error ("juju: Failed to allocate iso resources"); return err; } if (dc1394_video_set_iso_channel (camera, channel) != DC1394_SUCCESS) return DC1394_NO_ISO_CHANNEL; } if (dc1394_video_get_iso_channel (camera, &craw->iso_channel) != DC1394_SUCCESS) return DC1394_FAILURE; dc1394_log_debug ("juju: Receiving from iso channel %d", craw->iso_channel); craw->iso_fd = open(craw->filename, O_RDWR); if (craw->iso_fd < 0) { dc1394_log_error("error opening file: %s", strerror (errno)); return DC1394_FAILURE; } create.type = FW_CDEV_ISO_CONTEXT_RECEIVE; create.header_size = craw->header_size; create.channel = craw->iso_channel; create.speed = SCODE_400; err = DC1394_IOCTL_FAILURE; if (ioctl(craw->iso_fd, FW_CDEV_IOC_CREATE_ISO_CONTEXT, &create) < 0) { dc1394_log_error("failed to create iso context"); goto error_fd; } craw->iso_handle = create.handle; craw->num_frames = num_dma_buffers; craw->current = -1; craw->buffer_size = proto.total_bytes * num_dma_buffers; craw->buffer = mmap(NULL, craw->buffer_size, PROT_READ | PROT_WRITE , MAP_SHARED, craw->iso_fd, 0); err = DC1394_IOCTL_FAILURE; if (craw->buffer == MAP_FAILED) goto error_fd; err = DC1394_MEMORY_ALLOCATION_FAILURE; craw->frames = malloc (num_dma_buffers * sizeof *craw->frames); if (craw->frames == NULL) goto error_mmap; for (i = 0; i < num_dma_buffers; i++) { err = init_frame(craw, i, &proto); if (err != DC1394_SUCCESS) { dc1394_log_error("error initing frames"); break; } } if (err != DC1394_SUCCESS) { for (j = 0; j < i; j++) release_frame(craw, j); goto error_mmap; } for (i = 0; i < num_dma_buffers; i++) { err = queue_frame(craw, i); if (err != DC1394_SUCCESS) { dc1394_log_error("error queuing"); goto error_frames; } } // starting from here we use the ISO channel so we set the flag in // the camera struct: craw->capture_is_set = 1; start_iso.cycle = -1; start_iso.tags = FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS; start_iso.sync = 1; start_iso.handle = craw->iso_handle; retval = ioctl(craw->iso_fd, FW_CDEV_IOC_START_ISO, &start_iso); err = DC1394_IOCTL_FAILURE; if (retval < 0) { dc1394_log_error("error starting iso"); goto error_frames; } // if auto iso is requested, start ISO if (flags & DC1394_CAPTURE_FLAGS_AUTO_ISO) { err=dc1394_video_set_transmission(camera, DC1394_ON); DC1394_ERR_RTN(err,"Could not start ISO!"); craw->iso_auto_started=1; } return DC1394_SUCCESS; error_frames: for (i = 0; i < num_dma_buffers; i++) release_frame(craw, i); error_mmap: munmap(craw->buffer, craw->buffer_size); error_fd: close(craw->iso_fd); return err; }
dc1394error_t platform_capture_setup(platform_camera_t *craw, uint32_t num_dma_buffers, uint32_t flags) { dc1394camera_t * camera = craw->camera; dc1394error_t err; if (flags & DC1394_CAPTURE_FLAGS_DEFAULT) flags = DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC | DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC; // if capture is already set, abort if (craw->capture_is_set>0) return DC1394_CAPTURE_IS_RUNNING; craw->capture.flags=flags; craw->allocated_channel = -1; // if auto iso is requested, stop ISO (if necessary) if (flags & DC1394_CAPTURE_FLAGS_AUTO_ISO) { dc1394switch_t is_iso_on; dc1394_video_get_transmission(camera, &is_iso_on); if (is_iso_on == DC1394_ON) { err=dc1394_video_set_transmission(camera, DC1394_OFF); DC1394_ERR_RTN(err,"Could not stop ISO!"); } } // allocate channel/bandwidth if requested if (flags & DC1394_CAPTURE_FLAGS_CHANNEL_ALLOC) { if (dc1394_iso_allocate_channel (camera, 0, &craw->allocated_channel) != DC1394_SUCCESS) goto fail; if (dc1394_video_set_iso_channel (camera, craw->allocated_channel) != DC1394_SUCCESS) goto fail; } if (flags & DC1394_CAPTURE_FLAGS_BANDWIDTH_ALLOC) { unsigned int bandwidth_usage; if (dc1394_video_get_bandwidth_usage (camera, &bandwidth_usage) != DC1394_SUCCESS) goto fail; if (dc1394_iso_allocate_bandwidth (camera, bandwidth_usage) != DC1394_SUCCESS) goto fail; craw->allocated_bandwidth = bandwidth_usage; } craw->capture.frames = malloc (num_dma_buffers * sizeof (dc1394video_frame_t)); err=capture_basic_setup(camera, craw->capture.frames); if (err != DC1394_SUCCESS) goto fail; if (dc1394_video_get_iso_channel (camera, &craw->iso_channel) != DC1394_SUCCESS) goto fail; // the capture_is_set flag is set inside this function: err=capture_linux_setup (craw, num_dma_buffers); if (err != DC1394_SUCCESS) goto fail; // if auto iso is requested, start ISO if (flags & DC1394_CAPTURE_FLAGS_AUTO_ISO) { err=dc1394_video_set_transmission(camera, DC1394_ON); DC1394_ERR_RTN(err,"Could not start ISO!"); craw->iso_auto_started=1; } return DC1394_SUCCESS; fail: // free resources if they were allocated if (craw->allocated_channel >= 0) { if (dc1394_iso_release_channel (camera, craw->allocated_channel) != DC1394_SUCCESS) dc1394_log_warning("Warning: Could not free ISO channel"); } if (craw->allocated_bandwidth) { if (dc1394_iso_release_bandwidth (camera, craw->allocated_bandwidth) != DC1394_SUCCESS) dc1394_log_warning("Warning: Could not free bandwidth"); } craw->allocated_channel = -1; craw->allocated_bandwidth = 0; free (craw->capture.frames); craw->capture.frames = NULL; dc1394_log_error ("Error: Failed to setup DMA capture"); return DC1394_FAILURE; }