render_file.c
author Tero Marttila <terom@fixme.fi>
Sun, 01 Jun 2008 01:48:09 +0300
changeset 3 675be0a45157
parent 1 6aa1a0d1f88d
child 8 4d38ccbeb93e
permissions -rw-r--r--
working chunked-streaming of remote-rendered mandelbrots in web_main, next step will be flow control. Remote rendering doesn't compile in render_node.

committer: Tero Marttila <terom@fixme.fi>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "mandelbrot.h"
#include "common.h"

static int verbose;

void render_local (int img_w, int img_h, FILE *output) {
    render_t ctx;

    render_init(&ctx, RENDER_PNG);
    render_set_size(&ctx, img_w, img_h);
    render_region_full(&ctx);
    render_io_stream(&ctx, output);

    double duration;

    if (mandelbrot_render_timed(&ctx, &duration) != MANDELBROT_OK)
        err_exit("mandelbrot_render_region failed");
    
    if (verbose) 
        fprintf(stdout, "rendered %dx%d mandelbrot in %f seconds\n", img_w, img_h, duration);
}

#if 0
void render_remote (int img_w, int img_h, FILE *output, FILE *remote) {
    render_t ctx;
    struct render_cmd cmd;

    render_init(&ctx, RENDER_PNG);
    render_set_size(&ctx, img_w, img_h);
    render_region_full(&ctx);

    if (render_cmd_build(&ctx, &cmd))
        err_exit("mandelbrot_render_remote failed");

    int ret = fwrite((void *) &cmd, sizeof(cmd), 1, remote);
    
    if (ret != 1)
        perr_exit("fwrite(remote)");
        
    if (verbose)
        printf("sent render command of %zu bytes\n", sizeof(cmd));

    // shuffle data around
    while (!feof(remote)) {
        char buf[1024];

        int bytes = fread(buf, 1, sizeof(buf), remote);

        if (bytes)
            if (fwrite(buf, bytes, 1, output) != 1)
                perr_exit("fwrite(output)");
    }
    
    if (verbose)
        printf("got PNG data\n");

    if (ferror(remote))
        perr_exit("fread(remote)");
}

FILE *open_remote (char *remote) {
    char *addr_str, *port_str = NULL;

    addr_str = strsep(&remote, ":");

    if (remote)
        port_str = remote;
    
    struct sockaddr_in addr;

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port_str ? atoi(port_str) : RENDER_PORT);
    
    if (inet_aton(addr_str, &addr.sin_addr) == 0)
        err_exit("invalid address: %s", addr_str);

    int sock;
    
    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        perr_exit("socket");

    if (verbose)
        printf("connect(%s, %d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    
    if (connect(sock, (const struct sockaddr *) &addr, sizeof(addr)) == -1)
        perr_exit("connect(%s, %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    
    FILE *fh = fdopen(sock, "w+");

    if (!fh || ferror(fh))
        perr_exit("fdopen");

    setbuffer(fh, NULL, 0);

    return fh;
}
#endif

int main (int argc, char **argv) {
    int opt;
    
    FILE *output = NULL, *remote = NULL;
    int img_w = 256, img_h = 256;
    

    while ((opt = getopt(argc, argv, "w:h:o:vr:")) != -1) {
        switch(opt) {
            case 'w' :
                img_w = atoi(optarg);
                break;

            case 'h' :
                img_h = atoi(optarg);
                break;

            case 'o' :
                if (output)
                    err_exit("Only use -o once");

                output = fopen(optarg, "w");

                if (!output)
                    die(optarg);

                break;

            case 'v' :
                verbose = 1;
                break;

#if 0
            case 'r' :
                if (remote)
                    err_exit("Only use -r once");

                remote = open_remote(optarg);

                break;
#endif

            default :
                err_exit("Usage: %s [-w img_w] [-h img_h] [-o output_file] [-v] [-r host[:port]]", argv[0]);
        }
    }

    if (!output)
        output = stdout;

#if 0
    if (remote) {
        if (verbose)
            fprintf(stderr, "Render [%dx%d] mandelbrot remotely\n", img_w, img_h);

        render_remote(img_w, img_h, output, remote);

        fclose(remote);
    } else
#endif    
    {
        if (verbose)
            fprintf(stderr, "Render [%dx%d] mandelbrot locally\n", img_w, img_h);

        render_local(img_w, img_h, output);
    }

    fclose(output);

    return 0;
}