unsigned long setup_icb(shvpu_meram_t *mdata, ICB **icb, unsigned long pitch, unsigned long lines, int res_lines, int block_lines, int rdnwr, int index) { unsigned int total_len = pitch * lines; unsigned int xk_lines; unsigned int line_len; unsigned long tmp; int pitch_2n; int md, res; int memblk; MERAM *meram = mdata->meram; md = rdnwr == 0 ? 1 : 2; res = rdnwr == 0 ? 2 : 0x20; if (pitch <= 1024) pitch_2n = 1; else if (pitch <= 2048) pitch_2n = 2; else /* Only support up to 4k pixel width frames */ pitch_2n = 4; if ((*icb = meram_lock_icb(meram, index)) == NULL) return -1; memblk = meram_alloc_icb_memory(meram, *icb, pitch_2n * res_lines); meram_write_icb(meram, *icb, MExxCTL, (block_lines << 28) | (memblk << 16) | 0x708 | md); meram_write_icb(meram, *icb, MExxSIZE, (lines-1) << 16 | (pitch -1)); meram_write_icb(meram, *icb, MExxMNCF, ((res_lines - 1) << 16) | (res << 24) | (0 << 15)); meram_write_icb(meram, *icb, MExxBSIZE, pitch | 0x90000000); return 0; }
int main (int argc, char * argv[]) { UIOMux * uiomux; uiomux_resource_t uiores; char * infilename[2] = {NULL, NULL}, * outfilename = NULL; FILE * infile[2], * outfile = NULL; size_t nread; size_t input_size[2], output_size; SHVIO *vio; struct ren_vid_surface src[2]; const struct ren_vid_surface *srclist[2] = { &src[0], &src[1] }; struct ren_vid_surface dst; void *inbuf[2], *outbuf; int ret; int frameno=0; int show_version = 0; int show_help = 0; int show_list_vio = 0; char * progname; char * viodev = NULL; int error = 0; int c; char * optstring = "hvo:O:c:s:C:S:f:u:l"; #ifdef HAVE_GETOPT_LONG static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"output", required_argument, 0, 'o'}, {"overlay", required_argument, 0, 'O'}, {"input-colorspace", required_argument, 0, 'c'}, {"input-size", required_argument, 0, 's'}, {"output-colorspace", required_argument, 0, 'C'}, {"output-size", required_argument, 0, 'S'}, {"filter", required_argument, 0, 'f'}, {"vio", required_argument, 0, 'u'}, {"list", no_argument, 0, 'l'}, {NULL,0,0,0} }; #endif #if defined(USE_MERAM_RA) || defined(USE_MERAM_WB) #define ALIGN16(_x) (((_x) + 15) / 16 * 16) #define ADJUST_PITCH(_p, _w) \ { \ (_p) = ((_w) - 1) | 1023; \ (_p) = (_p) | ((_p) >> 1); \ (_p) = (_p) | ((_p) >> 2); \ (_p) += 1; \ } unsigned long val; MERAM *meram = meram_open(); MERAM_REG *regs = meram_lock_reg(meram); size_t sz; unsigned long mblock; ICB *icbr, *icbw; #endif /* defined(USE_MERAM_RA) || defined(USE_MERAM_WB) */ memset(src, 0, sizeof (src[0]) * 2); src[0].w = -1; src[0].h = -1; dst.w = -1; dst.h = -1; src[0].format = REN_UNKNOWN; dst.format = REN_UNKNOWN; src[0].bpitchy = src[0].bpitchc = src[0].bpitcha = 0; dst.bpitchy = dst.bpitchc = dst.bpitcha = 0; memcpy((void *)&src[1], (void *)&src[0], sizeof(src[0])); src[1].blend_out.x = 0; src[1].blend_out.y = 0; src[1].blend_out.w = 220; src[1].blend_out.h = 440; progname = argv[0]; if (argc < 2) { usage (progname); return (1); } while (1) { #ifdef HAVE_GETOPT_LONG c = getopt_long (argc, argv, optstring, long_options, NULL); #else c = getopt (argc, argv, optstring); #endif if (c == -1) break; if (c == ':') { usage (progname); goto exit_err; } switch (c) { case 'h': /* help */ show_help = 1; break; case 'v': /* version */ show_version = 1; break; case 'o': /* output */ outfilename = optarg; break; case 'O': /* ovalery */ infilename[1] = optarg; break; case 'c': /* input colorspace */ set_colorspace (optarg, &src[0].format); break; case 's': /* input size */ set_size (optarg, &src[0].w, &src[0].h); break; case 'C': /* output colorspace */ set_colorspace (optarg, &dst.format); break; case 'S': /* output size */ set_size (optarg, &dst.w, &dst.h); break; case 'f': /* filter mode */ rotation = strtoul(optarg, NULL, 0); break; case 'l': show_list_vio = 1; break; case 'u': viodev = optarg; break; default: break; } } if (show_version) { printf ("%s version " VERSION "\n", progname); } if (show_help) { usage (progname); } #if 0 if (show_list_vio) { char **vio; int i, n; if (shvio_list_vio(&vio, &n) < 0) { printf ("Can't get a list of VIO available...\n"); } else { for(i = 0; i < n; i++) printf("%s", vio[i]); printf("Total: %d VIOs available.\n", n); } } #endif if (show_version || show_help || show_list_vio) { goto exit_ok; } if (optind >= argc) { usage (progname); goto exit_err; } infilename[0] = argv[optind++]; if (optind < argc) { outfilename = argv[optind++]; } printf ("Input file: %s\n", infilename[0]); if (infilename[1] != NULL) printf ("Overlay file: %s\n", infilename[1]); printf ("Output file: %s\n", outfilename); guess_colorspace (infilename[0], &src[0].format); if (infilename[1]) guess_colorspace (infilename[1], &src[1].format); guess_colorspace (outfilename, &dst.format); /* If the output colorspace isn't given and can't be guessed, then default to * the input colorspace (ie. no colorspace conversion) */ if (dst.format == REN_UNKNOWN) dst.format = src[0].format; guess_size (infilename[0], src[0].format, &src[0].w, &src[0].h); if (rotation & 0xF) { /* Swap width/height for rotation */ dst.w = src[0].h; dst.h = src[0].w; } else if (dst.w == -1 && dst.h == -1) { /* If the output size isn't given and can't be guessed, then default to * the input size (ie. no rescaling) */ dst.w = src[0].w; dst.h = src[0].h; } if (infilename[1]) guess_size (infilename[1], src[1].format, &src[1].w, &src[1].h); /* Setup memory pitch */ src[0].pitch = src[0].w; src[1].pitch = src[1].w; dst.pitch = dst.w; /* Check that all parameters are set */ if (src[0].format == REN_UNKNOWN) { fprintf (stderr, "ERROR: Input colorspace unspecified\n"); error = 1; } if (src[0].w == -1) { fprintf (stderr, "ERROR: Input width unspecified\n"); error = 1; } if (src[0].h == -1) { fprintf (stderr, "ERROR: Input height unspecified\n"); error = 1; } if (dst.format == REN_UNKNOWN) { fprintf (stderr, "ERROR: Output colorspace unspecified\n"); error = 1; } if (dst.w == -1) { fprintf (stderr, "ERROR: Output width unspecified\n"); error = 1; } if (dst.h == -1) { fprintf (stderr, "ERROR: Output height unspecified\n"); error = 1; } if (error) goto exit_err; printf ("Input colorspace:\t%s\n", show_colorspace (src[0].format)); printf ("Input size:\t\t%dx%d %s\n", src[0].w, src[0].h, show_size (src[0].w, src[0].h)); printf ("Output colorspace:\t%s\n", show_colorspace (dst.format)); printf ("Output size:\t\t%dx%d %s\n", dst.w, dst.h, show_size (dst.w, dst.h)); printf ("Rotation:\t\t%s\n", show_rotation (rotation)); input_size[0] = imgsize (src[0].format, src[0].w, src[0].h); if (infilename[1] != NULL) input_size[1] = imgsize (src[1].format, src[1].w, src[1].h); output_size = imgsize (dst.format, dst.w, dst.h); if (/*viodev*/ 1) { const char *blocks[2] = { "VPU5", NULL }; uiomux = uiomux_open_named(blocks); uiores = 1 << 0; } else { uiomux = uiomux_open (); uiores = UIOMUX_SH_VEU; } /* Set up memory buffers */ src[0].py = inbuf[0] = uiomux_malloc (uiomux, uiores, input_size[0], 32); if (src[0].format == REN_RGB565) { src[0].pc = 0; } else if (src[0].format == REN_YV12) { src[0].pc2 = src[0].py + (src[0].w * src[0].h); /* Cr(V) */ src[0].pc = src[0].pc2 + (src[0].w * src[0].h) / 4; /* Cb(U) */ } else if (src[0].format == REN_YV16) { src[0].pc2 = src[0].py + (src[0].w * src[0].h); /* Cr(V) */ src[0].pc = src[0].pc2 + (src[0].w * src[0].h) / 2; /* Cb(U) */ } else { src[0].pc = src[0].py + (src[0].w * src[0].h); /* CbCr(UV) */ } if (infilename[1] != NULL) { src[1].py = inbuf[1] = uiomux_malloc (uiomux, uiores, input_size[1], 32); if (src[1].format == REN_RGB565) { src[1].pc = 0; } else if (src[1].format == REN_YV12) { src[1].pc2 = src[1].py + (src[1].w * src[1].h); /* Cr(V) */ src[1].pc = src[1].pc2 + (src[1].w * src[1].h) / 4; /* Cb(U) */ } else if (src[1].format == REN_YV16) { src[1].pc2 = src[1].py + (src[1].w * src[1].h); /* Cr(V) */ src[1].pc = src[1].pc2 + (src[1].w * src[1].h) / 2; /* Cb(U) */ } else { src[1].pc = src[1].py + (src[1].w * src[1].h); /* CbCr(UV) */ } } dst.py = outbuf = uiomux_malloc (uiomux, uiores, output_size, 32); if (dst.format == REN_RGB565) { dst.pc = 0; } else if (dst.format == REN_YV12) { dst.pc2 = dst.py + (dst.w * dst.h); /* Cr(V) */ dst.pc = dst.pc2 + (dst.w * dst.h) / 4; /* Cb(U) */ } else if (dst.format == REN_YV16) { dst.pc2 = dst.py + (dst.w * dst.h); /* Cr(V) */ dst.pc = dst.pc2 + (dst.w * dst.h) / 2; /* Cb(U) */ } else { dst.pc = dst.py + (dst.w * dst.h); /* CbCr(UV) */ } #if defined(USE_MERAM_RA) || defined(USE_MERAM_WB) #error aaaa meram_read_reg(meram, regs, MEVCR1, &val); val |= 1 << 29; /* use 0xc0000000-0xdfffffff */ meram_write_reg(meram, regs, MEVCR1, val); meram_unlock_reg(meram, regs); #endif /* defined(USE_MERAM_RA) || defined(USE_MERAM_WB) */ #if defined(USE_MERAM_RA) #error bbbb /* calcurate byte-pitch */ src[0].bpitchy = size_y(src[0].format, src[0].pitch, 0); /* set up read-ahead cache for input */ icbr = meram_lock_icb(meram, 0); val = (3 << 24) | /* KRBNM: ((3+1) << 1) = 8 lines */ ((16 - 1) << 16); /* BNM: 16 = KRBNM * 2 lines */ ADJUST_PITCH(sz, src[0].bpitchy); sz *= 16; /* 16 lines */ if (src[0].format == REN_NV12) { val |= 2 << 12; /* CPL: YCbCr420 */ sz = sz * 3 / 2; } else if (src[0].format == REN_NV16) { val |= 3 << 12; /* CPL: YCbCr422 */ sz = sz * 2; } meram_write_icb(meram, icbr, MExxMCNF, val); sz = (sz + 1023) / 1024; mblock = meram_alloc_icb_memory(meram, icbr, (sz == 0) ? 1 : sz); val = (1 << 28) | /* BSZ: 2^1 line/block */ (mblock << 16) | /* MSAR */ (3 << 9) | /* WD: (constant) */ (1 << 8) | /* WS: (constant) */ (1 << 3) | /* CM: address mode 1 */ 1; /* MD: read buffer mode */ meram_write_icb(meram, icbr, MExxCTRL, val); val = ((src[0].h - 1) << 16) | /* YSZM1 */ (src[0].bpitchy - 1); /* XSZM1 */ meram_write_icb(meram, icbr, MExxBSIZE, val); val = ALIGN16(src[0].bpitchy); /* SBSIZE: 16 bytes aligned */ meram_write_icb(meram, icbr, MExxSBSIZE, val); ADJUST_PITCH(src[0].bpitchy, src[0].bpitchy); src[0].bpitchc = src[0].bpitcha = src[0].bpitchy; val = uiomux_all_virt_to_phys(src[0].py); meram_write_icb(meram, icbr, MExxSSARA, val); src[0].py = (void *)meram_get_icb_address(meram, icbr, 0); uiomux_register(src[0].py, (unsigned long)src[0].py, 8 << 20); if (is_ycbcr(src[0].format)) { val = uiomux_all_virt_to_phys(src[0].pc); meram_write_icb(meram, icbr, MExxSSARB, val); src[0].pc = (void *)meram_get_icb_address(meram, icbr, 1); uiomux_register(src[0].pc, (unsigned long)src[0].pc, 8 << 20); } else { meram_write_icb(meram, icbr, MExxSSARB, 0); } #endif /* defined(USE_MERAM_RA) */ #if defined(USE_MERAM_WB) /* calcurate byte-pitch */ dst.bpitchy = size_y(dst.format, dst.pitch, 0); /* set up write-back cache for input */ icbw = meram_lock_icb(meram, 1); val = (3 << 28) | /* KWBNM: ((3+1) << 1) = 8 lines */ ((16 - 1) << 16); /* BNM: 16 = KWBNM * 2 lines */ ADJUST_PITCH(sz, dst.bpitchy); sz *= 16; /* 16 lines */ if (dst.format == REN_NV12) { val |= 2 << 12; /* CPL: YCbCr420 */ sz = sz * 3 / 2; } else if (dst.format == REN_NV16) { val |= 3 << 12; /* CPL: YCbCr422 */ sz = sz * 2; } meram_write_icb(meram, icbw, MExxMCNF, val); sz = (sz + 1023) / 1024; mblock = meram_alloc_icb_memory(meram, icbw, (sz == 0) ? 1 : sz); val = (1 << 28) | /* BSZ: 2^1 line/block */ (mblock << 16) | /* MSAR */ (3 << 9) | /* WD: (constant) */ (1 << 8) | /* WS: (constant) */ (1 << 3) | /* CM: address mode 1 */ 2; /* MD: write buffer mode */ meram_write_icb(meram, icbw, MExxCTRL, val); val = ((dst.h - 1) << 16) | /* YSZM1 */ (dst.bpitchy - 1); /* XSZM1 */ meram_write_icb(meram, icbw, MExxBSIZE, val); val = ALIGN16(dst.bpitchy); /* SBSIZE: 16 bytes aligned */ meram_write_icb(meram, icbw, MExxSBSIZE, val); ADJUST_PITCH(dst.bpitchy, dst.bpitchy); dst.bpitchc = dst.bpitcha = dst.bpitchy; val = uiomux_all_virt_to_phys(dst.py); meram_write_icb(meram, icbw, MExxSSARA, val); dst.py = (void *)meram_get_icb_address(meram, icbw, 0); uiomux_register(dst.py, (unsigned long)dst.py, 8 << 20); if (is_ycbcr(dst.format)) { val = uiomux_all_virt_to_phys(dst.pc); meram_write_icb(meram, icbw, MExxSSARB, val); dst.pc = (void *)meram_get_icb_address(meram, icbw, 1); uiomux_register(dst.pc, (unsigned long)dst.pc, 8 << 20); } else { meram_write_icb(meram, icbw, MExxSSARB, 0); } #endif /* defined(USE_MERAM_WB) */ if (strcmp (infilename[0], "-") == 0) { infile[0] = stdin; } else { infile[0] = fopen (infilename[0], "rb"); if (infile[0] == NULL) { fprintf (stderr, "%s: unable to open input file %s\n", progname, infilename[0]); goto exit_err; } } if (infilename[1] != NULL) { infile[1] = fopen (infilename[1], "rb"); if (infile[1] == NULL) { fprintf (stderr, "%s: unable to open input file %s\n", progname, infilename[1]); goto exit_err; } } if (outfilename != NULL) { if (strcmp (outfilename, "-") == 0) { outfile = stdout; } else { outfile = fopen (outfilename, "wb"); if (outfile == NULL) { fprintf (stderr, "%s: unable to open output file %s\n", progname, outfilename); goto exit_err; } } } if (!viodev) vio = shvio_open(); else vio = shvio_open_named(viodev); if (vio == 0) { fprintf (stderr, "Error opening VIO\n"); goto exit_err; } while (1) { #ifdef DEBUG fprintf (stderr, "%s: Converting frame %d\n", progname, frameno); #endif /* Read input */ if ((nread = fread (inbuf[0], 1, input_size[0], infile[0])) != input_size[0]) { if (nread == 0 && feof (infile[0])) { break; } else { fprintf (stderr, "%p, %s: errors reading input file %s %d %d %d\n", inbuf[0], progname, infilename[0], nread, input_size[0], ferror(infile[0])); } } #if 1 if (infilename[1] != NULL) { if ((nread = fread (inbuf[1], 1, input_size[1], infile[1])) != input_size[1]) { if (nread == 0 && feof (infile[1])) { break; } else { fprintf (stderr, "%s: error reading input file %s\n", progname, infilename[1]); } } printf("invoke shvio_setup_blend()...\n"); ret = shvio_setup_blend(vio, NULL, srclist, 2, &dst); shvio_start(vio); printf("shvio_start_blend() = %d\n", ret); ret = shvio_wait(vio); } else { #endif if (rotation) { ret = shvio_rotate(vio, &src[0], &dst, rotation); } else { ret = shvio_resize(vio, &src[0], &dst); } } #if defined(USE_MERAM_WB) meram_read_icb(meram, icbw, MExxCTRL, &val); val |= 1 << 5; /* WF: flush data */ meram_write_icb(meram, icbw, MExxCTRL, val); #endif #if defined(USE_MERAM_RA) meram_read_icb(meram, icbr, MExxCTRL, &val); val |= 1 << 4; /* RF: flush data */ meram_write_icb(meram, icbr, MExxCTRL, val); #endif /* Write output */ if (outfile && fwrite (outbuf, 1, output_size, outfile) != output_size) { fprintf (stderr, "%s: error writing input file %s\n", progname, outfilename); } frameno++; } shvio_close (vio); #if defined(USE_MERAM_RA) /* finialize the read-ahead cache */ uiomux_unregister(src[0].py); if (is_ycbcr(src[0].format)) uiomux_unregister(src[0].pc); meram_free_icb_memory(meram, icbr); meram_unlock_icb(meram, icbr); #endif #if defined(USE_MERAM_WB) /* finialize the write-back cache */ uiomux_unregister(dst.py); if (is_ycbcr(dst.format)) uiomux_unregister(dst.pc); meram_free_icb_memory(meram, icbw); meram_unlock_icb(meram, icbw); #endif #if defined(USE_MERAM_RA) || defined(USE_MERAM_WB) meram_close(meram); #endif uiomux_free (uiomux, uiores, src[0].py, input_size[0]); if (infilename[1] != NULL) uiomux_free (uiomux, uiores, src[1].py, input_size[1]); uiomux_free (uiomux, uiores, dst.py, output_size); uiomux_close (uiomux); if (infile[0] != stdin) fclose (infile[0]); if (infilename[1] != NULL) fclose (infile[1]); if (outfile == stdout) { fflush (stdout); } else if (outfile) { fclose (outfile); } printf ("Frames:\t\t%d\n", frameno); exit_ok: exit (0); exit_err: exit (1); }