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 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; }