| /* |
| * Copyright 2008 Sony Corporation of America |
| * |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| * THE SOFTWARE. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <malloc.h> |
| #include <sys/stat.h> |
| #include <libspe2.h> |
| #include <mars/task.h> |
| |
| #define INFO \ |
| "\ |
| MARS Task Grayscale Sample \n\ |
| -------------------------- \n\ |
| This program does grayscale image conversion of an input \n\ |
| file ('%s') and outputs the resulting grayscale image to \n\ |
| an output file ('%s'). \n\ |
| \n\ |
| The sample creates a single task instance of the main task 1 \n\ |
| program that also creates %d task instances of the sub task 2 \n\ |
| program that handles the actual processing of the grayscale \n\ |
| conversion. The main task feeds data into a MARS task queue \n\ |
| from which each sub task instance processes a portion of the \n\ |
| input image data. Each sub task instance sets a unique bit in \n\ |
| a MARS task event flag when processing is complete. When all \n\ |
| tasks have completed processing and the main task receives the \n\ |
| event signaling completion, the main task completes execution. \n\ |
| \n", IN_FILENAME, OUT_FILENAME, NUM_TASKS |
| |
| #define IN_FILENAME "in.ppm" |
| #define OUT_FILENAME "out.ppm" |
| #define PPM_MAGIC "P6" |
| |
| #define NUM_TASKS 4 |
| #define QUEUE_DEPTH 4 |
| |
| typedef struct _image_t { |
| int width; |
| int height; |
| unsigned char *src; |
| unsigned char *dst; |
| } image_t; |
| |
| typedef struct { |
| uint64_t ea_task_id; |
| uint64_t ea_event; |
| uint64_t ea_queue; |
| uint64_t ea_src; |
| uint64_t ea_dst; |
| uint32_t num; |
| uint32_t pad; |
| } grayscale_params_t; |
| |
| typedef struct { |
| uint64_t ea_event; |
| uint64_t ea_src; |
| uint64_t ea_dst; |
| uint32_t num; |
| uint32_t id; |
| } grayscale_queue_elem_t; |
| |
| extern struct spe_program_handle mpu_task1_prog; |
| extern struct spe_program_handle mpu_task2_prog; |
| |
| static struct mars_context *mars_ctx; |
| static struct mars_task_id task1_id; |
| static struct mars_task_id task2_id[NUM_TASKS] __attribute__((aligned(16))); |
| static struct mars_task_args task_args; |
| static uint64_t ea_event; |
| static uint64_t ea_queue; |
| |
| static grayscale_params_t grayscale_params __attribute__((aligned(16))); |
| |
| /* create MARS execution environment for rgb2y processing */ |
| void rgb2y(unsigned char *src, unsigned char *dst, int num) |
| { |
| int ret, i; |
| |
| ret = mars_context_create(&mars_ctx, 0, 0); |
| if (ret) { |
| printf("MARS context create failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_event_flag_create(mars_ctx, &ea_event, |
| MARS_TASK_EVENT_FLAG_MPU_TO_MPU, |
| MARS_TASK_EVENT_FLAG_CLEAR_AUTO); |
| if (ret) { |
| printf("MARS task event flag create failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_queue_create(mars_ctx, &ea_queue, |
| sizeof(grayscale_queue_elem_t), |
| QUEUE_DEPTH, |
| MARS_TASK_QUEUE_MPU_TO_MPU); |
| if (ret) { |
| printf("MARS task queue create failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_create(mars_ctx, &task1_id, "Grayscale Main Task", |
| mpu_task1_prog.elf_image, MARS_TASK_CONTEXT_SAVE_SIZE_MAX); |
| if (ret) { |
| printf("MARS task 1 create failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| for (i = 0; i < NUM_TASKS; i++) { |
| ret = mars_task_create(mars_ctx, &task2_id[i], |
| "Grayscale Sub Task", mpu_task2_prog.elf_image, |
| MARS_TASK_CONTEXT_SAVE_SIZE_MAX); |
| if (ret) { |
| printf("MARS task 2 create failed! (%d)\n", ret); |
| exit(1); |
| } |
| } |
| |
| grayscale_params.ea_task_id = mars_ptr_to_ea(&task2_id); |
| grayscale_params.ea_event = ea_event; |
| grayscale_params.ea_queue = ea_queue; |
| grayscale_params.ea_src = mars_ptr_to_ea(src); |
| grayscale_params.ea_dst = mars_ptr_to_ea(dst); |
| grayscale_params.num = num; |
| task_args.type.u64[0] = mars_ptr_to_ea(&grayscale_params); |
| |
| ret = mars_task_schedule(&task1_id, &task_args, 0); |
| if (ret) { |
| printf("MARS task 1 schedule failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_wait(&task1_id, NULL); |
| if (ret) { |
| printf("MARS task 1 wait failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_destroy(&task1_id); |
| if (ret) { |
| printf("MARS task 1 destroy failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| for (i = 0; i < NUM_TASKS; i++) { |
| ret = mars_task_destroy(&task2_id[i]); |
| if (ret) { |
| printf("MARS task 2 destroy failed! (%d)\n", ret); |
| exit(1); |
| } |
| } |
| |
| ret = mars_task_event_flag_destroy(ea_event); |
| if (ret) { |
| printf("MARS task event flag destroy failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_task_queue_destroy(ea_queue); |
| if (ret) { |
| printf("MARS task queue destroy failed! (%d)\n", ret); |
| exit(1); |
| } |
| |
| ret = mars_context_destroy(mars_ctx); |
| if (ret) { |
| printf("MARS context destroy failed! (%d)\n", ret); |
| exit(1); |
| } |
| } |
| |
| /* read ppm data from input file */ |
| void read_ppm(image_t *img, char *fname) |
| { |
| char *token, *pc, *buf, *del = " \t\n"; |
| int i, w, h, luma, pixs, filesize; |
| struct stat st; |
| unsigned char *dot; |
| FILE *fp; |
| |
| /* read raw data */ |
| stat(fname, &st); |
| filesize = (int) st.st_size; |
| buf = (char *) malloc(filesize * sizeof(char)); |
| |
| if ((fp = fopen(fname, "r")) == NULL) { |
| fprintf(stderr, "error: failed to open file %s\n", fname); |
| exit(1); |
| } |
| |
| fseek(fp, 0, SEEK_SET); |
| fread(buf, filesize * sizeof(char), 1, fp); |
| fclose(fp); |
| |
| /* validate file format */ |
| token = (char *) (unsigned long) strtok(buf, del); |
| if (strncmp(token, PPM_MAGIC, 2) != 0) { |
| fprintf(stderr, "error: invalid file format\n"); |
| exit(1); |
| } |
| |
| /* skip comments */ |
| token = (char *) (unsigned long) strtok(NULL, del); |
| if (token[0] == '#') { |
| token = (char *) (unsigned long) strtok(NULL, "\n"); |
| token = (char *) (unsigned long) strtok(NULL, del); |
| } |
| |
| /* read picture size (and luma) */ |
| w = strtoul(token, &pc, 10); |
| token = (char *) (unsigned long) strtok(NULL, del); |
| h = strtoul(token, &pc, 10); |
| token = (char *) (unsigned long) strtok(NULL, del); |
| luma = strtoul(token, &pc, 10); |
| |
| img->width = w; |
| img->height = h; |
| |
| /* allocate an aligned memory */ |
| pixs = w * h; |
| img->src = (unsigned char *)memalign(16, pixs*4); |
| img->dst = (unsigned char *)memalign(16, pixs*4); |
| |
| /* read rgb data with 'r,g,b,0' formatted */ |
| dot = img->src; |
| pc++; |
| for (i = 0; i < pixs*4; i++) { |
| if (i % 4 == 3) { |
| *dot++ = 0; |
| } else { |
| *dot++ = *pc++; |
| } |
| } |
| |
| return; |
| } |
| |
| /* write ppm data to output file */ |
| void write_ppm(image_t *img, char *fname) |
| { |
| int i; |
| int w = img->width; |
| int h = img->height; |
| unsigned char *dot = img->dst; |
| FILE *fp; |
| |
| if ((fp = fopen(fname, "wb+")) == NULL) { |
| fprintf(stderr, "failed to open file %s\n", fname); |
| exit(1); |
| } |
| |
| fprintf(fp, "%s\n", PPM_MAGIC); |
| fprintf(fp, "%d %d\n", w, h); |
| fprintf(fp, "255\n"); |
| |
| for (i = 0; i < (w * h * 4); i++) { |
| if (i % 4 == 3) { |
| dot++; |
| } else { |
| putc((int) *dot++, fp); |
| } |
| } |
| |
| fclose(fp); |
| |
| return; |
| } |
| |
| void delete_image(image_t *img) |
| { |
| free(img->src); |
| free(img->dst); |
| |
| return; |
| } |
| |
| int main(int argc, char **argv) |
| { |
| image_t image; |
| |
| printf(INFO); |
| |
| read_ppm(&image, IN_FILENAME); |
| |
| rgb2y(image.src, image.dst, image.width * image.height); |
| |
| write_ppm(&image, OUT_FILENAME); |
| |
| delete_image(&image); |
| |
| return 0; |
| } |