DSLR Camera Software
Design Rationale
Camera software is a complex combination of (often modular) physical inputs, data processing, and physical outputs. For the purposes of our design, we will be analyzing different architectures against the following functions of the camera when an image is captured: 1) adjusting the settings before taking the photo, 2) triggering the photo to be taken, 3) processing the image(s) in the buffer, and 4) writing the image(s) to the external storage device. In addition, the architectures will need to conform well to the requirements of taking photos in both automatic (FR-1) and manual mode (FR-2), all while adapting to the incorporation of various modular components, such as lenses (NFR-5), GPS, and more. In order to utilize external modular components, the system must default to using the external component rather than the onboard equivalent (FR-10).
The aforementioned functions align as subsets of the three modules above and as combinations of the various Functional and Nonfunctional Requirements listed above. Module 1 (Equipment Operator) contains the Setting Adjustment function and the part of the Shutter Trigger function responsible for the physical manipulation of the shutter. Module 2 (Image Processor) contains the Image Processing and Writing to Storage functions. Module 3 (Controller), contains the event portion of the Shutter Trigger function that coordinates the events throughout the various modules. Due to the nature of embedded systems, the architectures do not necessarily need to be very extensible as one of their key attributes. In addition, speed is paramount in this system, so architectures emphasizing performance will be given higher priority.
Function 1: Setting Adjustment
The first step of taking a photo is the adjustment of the various camera settings, such as shutter speed, aperture, focus, focal length (zoom), flash activation, and light sensitivity (ISO). In the “manual” use case (FR-2), this action is quite straight-forward. Since the camera operator determines the value assigned to each setting, the software only needs to read the values from each respective component. However, the “automatic” use case (FR-1) is significantly more complicated and will have a much greater impact on the overall architecture of this first function. In “automatic” mode, the camera must use a variety of sensors to detect the current settings of each component and then determine the outcome of the photo if taken with the current settings. If the photo is underexposed, overexposed, blurry, in low-light conditions, etc., the camera software must determine ideal values for each component in order to create the most optimal photo. The camera must also, assuming each component is compatible, use physical mechanisms to interact with its components. For example, the camera must interact with the lens to adjust the aperture (FR-4) and focus (FR-3), which are attributes that have to be physically set. The shutter speed must also be determined automatically by the system based upon the amount of light on the sensor (FR-6). In a bright environment, the shutter speed will be fast; conversely, in a dark environment, the shutter speed will be slow as to allow more light to hit the sensor. In addition to being able to adjust these settings to create an optimal photo, the camera must be able to perform all of these actions at once, and quickly as to not prevent the photographer from achieving the desired shot. From this perspective, the asynchronous coordination of each component in timely fashion is arguably the most important feature that an architecture should be able to provide.
The aforementioned architectural requirement restricts several styles that will not allow for the quick adjustment of these settings. A few styles stand out as being potentially well suited to this requirement, such as the Process Control solution style, the Shared Memory design, and the Event-Driven design. For the “automatic” use case, the Process Control solution style would allow a variety of sensors to be read and then determine a set point that will result in the best photo. This process is, by design, continuous and allows for frequent fluctuations of variables in the environment. The Shared Memory design has the benefit of being efficient and fast, but does not necessarily align with the use case. Since we are reading data from different sensors and using the data to determine ideal values for the image, there is no instance where memory would need to be shared. This would just add unnecessary complexity to the system. When considering an Event-Driven design, the fact that the component raising the event has no control over how other components will respond, or even when they respond makes it particularly unsuitable for a module that requires sequenced processing. In addition, from the perspective of adjusting settings, it is not very efficient to publish an event to all subscribers every time the light level in the environment changes slightly. Based on the the above analysis, the Process Control architectural style seems best suited to the task of settings adjustment.
Function 2: Triggering the Shutter
The act of triggering the shutter (the part of the camera that is actually responsible for taking the photo) is arguably the most critical part of the entire system. In many respects, it is the piece of the system that controls the use of other components in the system as described in Module 3 (Controller). While the adjustment of settings must take place quickly, it is the triggering of the shutter that should have the least amount of latency. The standard amount of latency for a mid-range, consumer DSLR is roughly 100ms or less (NFR-9). With this in mind, reducing the latency between the action triggering the shutter and the shutter activating is an aspect of the design that needs to be hoisted into the architecture wherever possible. Hoisting low latency into the architecture will ensure that the camera functions quickly above all else. It is not enough, however, to simply take the photo immediately after the camera operator presses the shutter button. In automatic mode, if the camera operator presses the shutter button when the current settings would cause the photo to be significantly overexposed (white) or underexposed (black), then the photo should not be taken at all.
To accomplish this, the system needs to evaluate whether or not the settings are conducive to a quality photo. The Setting Adjustment function will need to notify the system when the settings are appropriate for a photo to be taken. At this point, the camera operator still needs to fully press the shutter button (half-press initiating the Setting Adjustment function). Both events need to be asynchronous and resolve before triggering the shutter. When this occurs, all components in the camera need to respond in a coordinated manner to produce an optimal image. Since the settings being ready and the shutter button press can certainly be described as significant state changes in the system, the Event-Driven architecture comes to mind immediately. In addition, the need for concurrency would seem to fit well with the Shared Data design. The Event-Driven architecture is easily extensible, allowing the addition of new components which can be added to the subscriber list to listen for the shutter activation event. The Shared Data design is easily extensible as well, since new components need only reference the shared data elements when created or added to the system. In these regards, the two designs are on relatively even footing. However, where the Event-Driven architecture surpasses the Shared Data design is its ability to respond to specific events without being as resource intensive - nor as inefficient - as a recurring check against the shared data model would be.
The other portion of this function is the physical activation of the shutter in order to take the photo (Module 1 - Equipment Operator). This piece partially overlaps the Setting Adjustment function in that the shutter speed must either be set by the camera operator in manual mode, or by the system in automatic mode. Since the system sets the shutter speed based on the amount of light in the environment, a Process Control system similar to the Setting Adjustment function makes the most sense for the same reasons listed above.
Function 3: Image Processing
After the shutter has been activated and the picture taken, the camera must apply any default image processing to the photos (FR-9) stored in the buffer (NFR-9). For example, most cameras have a “noise reduction” feature that helps eliminate the graininess of photos, particularly when a high ISO (light sensitivity) is used (FR-9.2). In addition, many DSLRs have image editing abilities, such as the application of black and white filters (FR-9.1). These edits can be applied before the image is written to storage, or after, when the camera operator is reviewing their photos. In this manner, the image processing component should be reusable. Once the edits are complete, they are written to the buffer (NFR-8) to be written to the SD card in the event that the image processing completes faster than the SD card is able to handle. This situation may seem unlikely, but the speed with which files can be written to the SD card is contingent upon the “class” of the SD card, ranging from Class 2 (slowest - min. 2 MB/s write) to Class 10 (fastest - min. 10 MB/s write).
The Image Processing function should be structured in such a way that new processing components can be added or removed based on user preference. For example, the camera operator should be able to specify that noise-reduction, a black and white filter, and JPEG format should all be applied to the resulting picture. This requirement lends itself to more extensible architectures, like Pipe-and-Filter and Object-Oriented. Other architectures, such as Event-Driven, are certainly extensible as well. However, since the image can only have one form of processing applied at a time, there is no sense in choosing a design that is more complex and better geared to asynchronous uses when it would ultimately be implemented in a sequential manner. The Pipe-and-Filter architecture has certain other drawbacks, such as the fact that it is rather computationally inefficient since the data as a whole has to be copied to each component and then modified. Since a camera needs to process images as quickly as possible, and ideally with minimal computing power, the Pipe-and-Filter architecture is too resource intensive to be viable. The Object-Oriented design, however, would only require the data to be held in memory in one location, upon which all changes would be made directly. In addition, each processing component of the Image Processor is logically separated from the rest of the components, allowing for modularity. Being able to treat images as objects also has the added benefits of not only being easily comprehended, but also allows each image to share or have the same structure. Certain attributes in the metadata will always be present, so they can be set by the system or left as null.
Function 4: Writing to Storage
Finally, after all the other functions have been performed, the image must be stored on the SD card (FR-7). Functionally, the camera must be able to take several photos in short succession - faster than the camera can write to the SD card. Because of this limitation, there must be a buffer to hold the image data while the series of photos is written to the SD card (NFR-8). The data written to the buffer will be in RAW image format (a minimally processed form of image data). At the point in time that the camera writes the data from the buffer onto the SD card, the image may be stored in the RAW image format, or JPEG format (a compressed, processed form) based on the camera operator’s settings (NFR-10). The process of writing the information from the buffer to the SD card will take no more than one second per image (NFR-7). Information from various camera components (either onboard or external) must be aggregated and stored as image metadata. This data will contain information about the system’s settings when the image was captured, a timestamp, and location data if a GPS component is present (FR-8).
Due to the limitation of the SD card to have more than one image written at a time, a more sequential architectural style must be considered. Since writing data to the SD card is heavily contingent upon the Image Processing function and are both subsets of the Image Processor module, the Object-Oriented design will persist to the writing of the data to the SD card. Any change in architecture with the management of the data would take time and processing power, both of which need to be minimized in the context of an embedded system such as a DSLR camera.