Source file component/file_out.c defines the spm_demo application file output component, using definitions from header file component/file_out.h. The file output component is similar to the file input component, so this section only describes a few important differences between them.
The file_out component recognizes two commands: FILE_OUT_CMD_FILENAME and FILE_OUT_CMD_REPORT_WRITTEN. Command FILE_OUT_CMD_FILENAME is like file input component command FILE_IN_CMD_FILENAME; it gives the name of the output file. Command FILE_OUT_CMD_REPORT_WRITTEN reports when file output is finished. File output component command handler function file_out_instance_cmdhandler handles the command. If no previous FILE_OUT_CMD_REPORT_WRITTEN command is pending and there is an active output file, it sets the report_written_cmd field of its context; the component execute function file_out_instance_execute will issue the command response on completion.
/* FILE_OUT_CMD_REPORT_WRITTEN */
if (id == FILE_OUT_CMD_REPORT_WRITTEN) {
/* Fail if there is already an REPORT_WRITTEN command pending. */
if (ocontext->report_written_cmd != NULL) {
spi_cmd_send_response(cmd, SPI_RESPONSE_ERRNO_FAIL, NULL, 0);
spi_cmd_free(cmd);
return;
}
/*
* If no active file, then response immediately that it is
* written. Otherwise record the command so the response can be
* sent later by the execute function.
*/
if (ocontext->fp == NULL) {
spi_cmd_send_response(cmd, SPI_RESPONSE_ERRNO_OK, NULL, 0);
ocontext->report_written_cmd = NULL;
spi_cmd_free(cmd);
} else {
ocontext->report_written_cmd = cmd;
}
return;
}
The end of the execute function sends the response after it writes the output file.
/*
* If a REPORT_WRITTEN command has been received,
* then reply that the file has been written.
*/
if (ocontext->report_written_cmd != NULL) {
spi_cmd_send_response(ocontext->report_written_cmd,
SPI_RESPONSE_ERRNO_OK, NULL, 0);
spi_log(SPI_LOG_DEBUG, SPI_LOG_LEVEL_DEBUG, "reporting written file\n");
...
}
7.9Green screen removal component
File components/gsr.c defines the green screen removal component. Its execute function gsr_instance_execute calls function gsr_pipeline, defined in Stream source gsr_pipeline.sc, to perform the work of green screen removal. The execute function is straightforward: it pops a buffer off its input port, processes the buffer with gsr_pipeline, pushes the processed buffer to its output port, and pauses itself:
/*
* GSR component instance execute function.
* Called when execution requirement is satisfied,
* i.e., when a buffer is available on the input port
* and space is available on the output port.
*/
static
void
gsr_instance_execute(spi_instance_context_t context)
{
spi_connection_t in_conn, out_conn;
spi_buffer_t buffer;
in_conn = spi_port_get_connection(GSR_PORT_IN, 0);
if ((buffer = spi_connection_pop(in_conn, 0)) == NULL) {
spi_log(spi_get_log(SPI_LOG_ERROR), SPI_LOG_LEVEL_ERROR_ASSERT,
"gsr: pop failed\n");
spi_set_state(SPI_INSTANCE_STATE_STOPPED);
return;
}
if (gsr_pipeline(buffer) != 0) {
spi_log(spi_get_log(SPI_LOG_ERROR), SPI_LOG_LEVEL_ERROR_FATAL,
"%s: buffer processing failed\n",
spi_get_name());
spi_set_state(SPI_INSTANCE_STATE_STOPPED);
return;
}
out_conn = spi_port_get_connection(GSR_PORT_OUT, 0);
if (spi_connection_push(out_conn, buffer, 0)) {
spi_log(spi_get_log(SPI_LOG_ERROR), SPI_LOG_LEVEL_ERROR_ASSERT,
"gsr: push failed\n");
spi_set_state(SPI_INSTANCE_STATE_STOPPED);
return;
}
...
spi_set_state(SPI_INSTANCE_STATE_PAUSED);
}
file_in and file_out component instances start out in the paused state (SPI_INSTANCE_STATE_PAUSED). Their command handlers switch to the running state (SPI_INSTANCE_STATE_RUNNING) when they receive a command that specifies an input filename or an output filename. Since the gsr component does not respond to any commands, it instead switches to the running state as soon as a new instance is created, by calling spi_set_state from initialization function gsr_instance_init.
This remainder of this section gives an overview of the green screen removal algorithm. Section Streams above describes the division of the input image into blocks and strips and the use of spi_load_index and spi_load_block during image processing. Section Kernels above describes the kernels that perform data-parallel operations efficiently.
spi_load_index loads pixel data from buffer into in_stream, using the index stream idx_stream generated previously. Kernal gsr_compute_average does the computationally intensive data-parallel work of computing the average color in each block, reading input stream in_stream and writing output stream avg_stream containing block average data. Then spi_store_block stores the updated block average data back to avg_buffer.
Next, gsr_pipeline builds a histogram of the average color information and finds the mode, which gives the background color of the input image.
Finally, gsr_pipeline makes another pass over the pixel data, this time calling gsr_remove_background to replace any color within a given color distance of the background color with a replacement color.
Share with your friends: |