/* zdjpeg.c
*
* Copyright (c)2008 Magnum Semiconductor Inc., All rights reserved.
*
* This command line JPEG decode utility is based on the IJG library djpeg.
* Several of the options supported by that program have been removed as they
* are not required to illustrate the operation of the ZEVIO JPEG decoder.
*
* This program performs a command line decode usingthe ZSP optimised decoder
*
* The original djpeg code is:
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
*/
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <stdint.h>
#include <signal.h>
#include <alloca.h>
#include <limits.h>
#include <ctype.h>
#include <poll.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <dirent.h>
#include <pthread.h>
#include <semaphore.h>
#include <zevio/zevio2d.h>
#include <zevio/zevio3d.h>
#include <zevio/gpu_factory.h>
#include "zeviojpegapi.h"
#include "display.h"
/*
* These constants are for the use of this program, the JPEG library itself
* is precompiled to support up to 800*600 displays which is all that can
* be reasonably expected on a current ZEVIO platform. The memory saving in
* the JPEG decoder for a smaller size such as 640*480 is minimal
*/
#define OUTPUT_W 800
#define OUTPUT_H 600
/*
* The value APP_PHY_MEMORY defines the memory reserved for final image output
* which must be to physically mapped memory. Currently this is large enough
* for an 800*600 linear image. However it is no longer required...
*/
#define APP_PHY_MEMORY 0
//#define TRACE fprintf(stdout, "( %s : %s : %d )\n", __FILE__, __func__, __LINE__);
#define TRACE
#define PPM_MAXVAL 255
#define READ_BINARY "rb"
#define WRITE_BINARY "wb"
#define INTERVAL_TIME 60 // Seconds!
static const char *progname;
static char *outfilename,
*playRoot;
static boolean thumbnail,
slideshow,
play,
tile,
flush;
static sem_t done;
static unsigned int oWidth,
oHeight,
loopCounter,
displayCounter,
presentationDelay,
quality;
static void *gpuVMem;
static ZV_GPU_BUFFER_OBJECT gpuBuf;
extern void encodeStart( zJpegDecompressPtr decompressCinfo, char *filename, unsigned int oWidth, unsigned int oHeight, unsigned int quality);
extern void encodeEnd( void );
extern void encodeWriteAPP1( unsigned char *pHeader, unsigned int length);
static void usage ( void );
static boolean keymatch (char * arg, const char * keyword, int minchars);
static int parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real);
static void freeInputBuffer( zJpegDecompressPtr cinfo,
int temp,
zJpegDecodeStatus status);
static void zdjpegErrorExit ( zJpegCommonPtr cinfo );
static int zdjpeg(int argc, char **argv);
/*
* Command line help message
*/
static void usage (void)
/* complain about bad command line */
{
fprintf(stderr, "\nUsage: %s [switches] <input file>\n\n", progname);
fprintf(stderr, "Switches (names may be abbreviated):\n\n");
fprintf(stderr, " -verbose Emit debug output\n");
fprintf(stderr, " -size WxH Force the output size to be WxH (scaling down only)\n");
fprintf(stderr, " -thumb Process embedded thumbnail if present\n");
fprintf(stderr, " -slideshow <N> Display 'N' iterations of images in directory\n");
fprintf(stderr, " -play <file root> Play a sequence of JPEGs <file root>00001.jpg etc\n");
fprintf(stderr, " -tile <N> <I> Like slideshow, but Thumbnails, display refresh every <I>\n");
fprintf(stderr, " -delay <1 - 99> Delay then clear 3D screen, default is to leave image\n");
fprintf(stderr, " -flush Forces a flush after 2s of every other Slideshow image\n");
fprintf(stderr, " \n and\n\n -outfile <quality> <filename> Writes a ppm file and a jpeg file at the \n specified quality level in addition to display\n");
exit(EXIT_FAILURE);
}
/*
* Assist function for command line parsing, converts case and recognises
* abbreviated keywords
*/
static boolean keymatch (char * arg, const char * keyword, int minchars)
{
register int ca, ck;
register int nmatched = 0;
while ((ca = *arg++) != '\0') {
if ((ck = *keyword++) == '\0')
return FALSE; /* arg longer than keyword, no good */
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
ca = tolower(ca);
if (ca != ck)
return FALSE; /* no good */
nmatched++; /* count matched characters */
}
/* reached end of argument; fail if it's too short for unique abbrev */
if (nmatched < minchars)
return FALSE;
return TRUE; /* A-OK */
}
/*
* Command line parser
*/
static int parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
int last_file_arg_seen, boolean for_real)
/* Parse optional switches.
* Returns argv[] index of first file-name argument (== argc if none).
* Any file names with indexes <= last_file_arg_seen are ignored;
* they have presumably been processed in a previous iteration.
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
* processing.
*/
{
int argn;
char * arg;
for_real = for_real;
/* Set up default JPEG parameters. */
outfilename = NULL;
cinfo->err->trace_level = 0;
cinfo->dct_method = JDCT_IFAST;
cinfo->quantize_colors = FALSE;
cinfo->two_pass_quantize = FALSE;
cinfo->do_fancy_upsampling = FALSE;
cinfo->dither_mode = JDITHER_ORDERED;
// cinfo->dither_mode = JDITHER_NONE;
presentationDelay = 0;
/* Scan command line options, adjust parameters */
for (argn = 1; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
/* Not a switch, must be a file name argument */
if (argn <= last_file_arg_seen) {
outfilename = NULL; /* -outfile applies to just one input file */
continue; /* ignore this name if previously processed */
}
break; /* else done parsing switches */
}
arg++; /* advance past switch marker character */
if (keymatch(arg, "verbose", 1)) {
cinfo->err->trace_level++;
} else if (keymatch(arg, "thumb", 2)) {
thumbnail = TRUE;
} else if (keymatch(arg, "flush", 2)) {
flush = TRUE;
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force monochrome output. */
cinfo->out_color_space = JCS_GRAYSCALE;
} else if (keymatch(arg, "outfile", 2)) {
/* Set output file name. */
if (slideshow == TRUE || tile == TRUE || play == TRUE)
usage();
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d",
&quality) != 1)
usage();
if (++argn >= argc) /* advance to next argument */
usage();
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "play", 2)) {
/* Set output file name. */
if (++argn >= argc) /* advance to next argument */
usage();
if (slideshow == TRUE || tile == TRUE || outfilename != NULL)
usage();
playRoot = argv[argn]; /* save it away for later use */
play = TRUE;
} else if (keymatch(arg, "delay", 2)) {
/* Set the presentation delay */
if (++argn >= argc)