This chapter provides tips and techniques for capturing video, working with colormaps, and improving performance when working with grayscale images.
This section discusses blurring in fast-moving images, changing video formats while capturing video, and capturing video at a constant rate.
Because the video signal coming into the SunVideo card consists of two interlaced fields, there is about a 1/30 second difference between the time that the first and last pixels of a frame are captured. Therefore, when you play back digitized video, you may see some blurring of fast-moving images. An example is a "stock ticker" that pans across a screen.
The blurring of fast-moving images can be more apparent if you're capturing and displaying a full-size image. You can reduce blurring by using a scale factor of 0.5 when calling the xil_scale() function on the captured image because you are getting information from only one field. In the case of the example programs (such as rtvc_capture_movie), a scale factor of 0.5 corresponds to a shrink factor argument (-s <shrink_factor'>) of "2."
The video format coming to the SunVideo card is checked only when the xil_set_device_attribute() function sets the PORT or PORT_V attributes or when the xil_get_device_attribute() function gets the FORMAT or FORMAT_V attributes. Therefore, the example SunVideo programs will produce bad video if you change video formats while capturing video. This can happen, for example, if you disconnect a PAL video device's cable from the active port and connect an NTSC device to the port. In this case, the example programs can return a "capture timed out" error message.
Here are some tips for capturing video from the SunVideo program at a constant rate.
A few of the reasons that video might not be captured at a constant rate are:
Colorcubes, special kinds of lookup tables, are used for general image modification. Each entry in an XIL colorcube contains an index, a value that may appear in the source image, and a value or set of values to be written to the destination image.
You can change the values in a colorcube to gamma correct the luminance (Y) values of an image and to vary the range of colors used by an image (rescale the luminance and chrominance values).
The general steps to modify a colorcube are:
The xil_rescale() function performs the rescale operation. This function operates only one images; therefore, the functions xil_export() and xil_import() must be used to manipulate the lookup tables as if they were images. The code example in the following section shows the use of xil_export() and xil_import().
In a colorcube, color levels are typically equally spaced throughout a gamut. The problem with this is that level-to-level changes at the low end of the gamut seem greater to the eye than equal changes at the high end.
To create a gamma-corrected colorcube in which level-to-level changes seem consistent throughout the range, you space the luminance (Y) values logarithmically rather than linearly. The following code fragment from dither.c is an example.
---------------------------------------------------
double dither_gamma = 2.0; unsigned int count, buf_size, i; Xil_unsigned8* buffer; Xil_unsigned8* data_ptr; double gamma; . . /* copy the lookup table data into the image. */ xil_export(image_src); xil_get_memory_storage(image_src, &storage); data_ptr = storage.byte.data; /* gamma correct the y values */ gamma = 1.0/dither_gamma; for (i = 0; i < buf_size; i+= 3) { double tmp = ((double) buffer[i]) / 255.0; tmp = pow(tmp,gamma) * 255.0; if (tmp 255) buffer[i] = 255; else buffer[i] = (Xil_unsigned8)tmp; } for (i=0; i < buf_size; i+=3) { data_ptr[0] = buffer[i]; data_ptr[1] = buffer[i+1]; data_ptr[2] = buffer[i+2]; data_ptr += storage.byte.pixel_stride; } xil_import(image_src, TRUE); xil_rescale(image_src, image_src, scale, offset); xil_color_convert(image_src, image_dst); xil_export(image_dst); ---------------------------------------------------
Note - The SunVideo example programs achieve gamma correction on 8-bit displays by replacing the yuv_to_rgb lookup table with a modified version. Gamma correction can be disabled for the SunVideo example programs by setting the variable dither_version to 0 in the file dither.c.
You can vary the range of colors used by an image. For example, you can ignore the highest saturation values that are unlikely to occur and define more level-to-level changes within the range of colors that is more likely to occur. To vary the range of colors used by an image, you experiment with the numbers used to compute the rescale_values and offset_values parameters of the xil_rescale() function. The following code fragment from dither.c is an example.
-------------------------------------------------------
int min[3]; int max[3]; int i; min[0] = 27; max[0] = 200; min[1] = 72; max[1] = 175; min[2] = 78; max[2] = 168; for (i=0; i< 3; i++) { rescale_values[i] = 255.0 / (float(max[i] - min[i]); offset_values[i] = -min[i] * rescale_values[i]; } . . -------------------------------------------------------
When working with grayscale images, the use of molecules becomes especially important for achieving good performance. If the capture operation is performed atomically, the chrominance bands of the image are unnecessarily copied from the SunVideo card to the intermediate image in host memory, even though only the luminance band is of interest.
One way to ensure the use of molecules for grayscale capture is to call the xil_scale() function after the implicit capture, even if you want to capture a full size image (scale factor of 1). The following code fragment and comments from display.c illustrate this point; it shows the fastest way to capture and display a grayscale image for both 8-bit and 24-bit displays. The image rtvc_luma is a single-banded child image from the SunVideo card with a band offset of 0 (a Y-only image).
------------------------------------------------------------------
if (grayscale) { if (display_depth == 24) { /* * even if scale_factor is 1, this combination of xil_scale() * & xil_lookup() is faster than * xil_lookup(rtvc_luma,display,graylookup) */ xil_scale(rtvc_luma, single_band, "nearest", scale_factor, scale_factor); xil_lookup(single_band, display, graylookup); xil_toss(single_band); } else { /* display_depth is 8 */ /* * even if scale_factor is 1, xil_scale() is faster than * xil_copy(rtvc_luma,display) for this case */ xil_scale(rtvc_luma, display, "nearest", scale_factor, scale_factor); } ------------------------------------------------------------------