URL: https://linuxfr.org/forums/programmation-c--2/posts/libtheora Title: libtheora Authors: fog2100 Date: 2010年12月08日T15:31:43+01:00 Tags: Score: 0 Bonjour, J'ai modifié le fichier examples/png2theora.c de la bibliothèque libtheora afin de pouvoir encoder un sldeshow de fichiers png avec une durée attribuée à chaque slide. La modif fonctionnait bien dans sa première version, mais maintenant j'ai des soucis dans la deuxième version. Le message d'erreur affiché par le programme: ` Could not set keyframe interval to 64. Internal Theora library error. ` Je ne sais pas de quoi il s'agit. /******************************************************************** £spaces£ £/spaces£* * £spaces£ £/spaces£* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * £spaces£ £/spaces£* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * £spaces£ £/spaces£* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * £spaces£ £/spaces£* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * £spaces£ £/spaces£* * £spaces£ £/spaces£* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009,2009 * £spaces£ £/spaces£* by the Xiph.Org Foundation and contributors [http://www.xiph.org/](http://www.xiph.org/) * £spaces£ £/spaces£* * £spaces£ £/spaces£******************************************************************** £spaces£ £/spaces£function: example encoder application; makes an Ogg Theora £spaces£ £/spaces£file from a sequence of png images £spaces£ £/spaces£last mod: $Id: png2theora.c 16503 2009年08月22日 18:14:02Z giles $ £spaces£ £/spaces£based on code from Vegard Nossum £spaces£ £/spaces£********************************************************************/ #define _FILE_OFFSET_BITS 64 #include <errno.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <math.h> #include <libgen.h> #include <sys/types.h> #include <dirent.h> #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <png.h> #include <ogg/ogg.h> #include "theora/theoraenc.h" #define PROGRAM_NAME "png2theora" #define PROGRAM_VERSION "1.1" static const char *option_output = NULL; static int video_fps_numerator = 24; static int video_fps_denominator = 1; static int video_aspect_numerator = 0; static int video_aspect_denominator = 0; static int video_rate = -1; static int video_quality = -1; ogg_uint32_t keyframe_frequency = 0; int buf_delay = -1; int vp3_compatible = 0; static int chroma_format = TH_PF_420; static FILE *twopass_file = NULL; static int twopass = 0; static int passno; static FILE *ogg_fp = NULL; static ogg_stream_state ogg_os; static ogg_packet op; static ogg_page og; static th_enc_ctx *td; static th_info ti; static char *input_filter; const char *optstring = "o:t:hv:4円:2円:V:s:S:f:F:ck:d:1円2円3円4円5円6円"; struct option options[] = { { "output", required_argument, NULL, 'o' }, { £spaces£ £/spaces£"time", required_argument, NULL, 't' }, { "help", no_argument, NULL, £spaces£ £/spaces£'h' }, { "chroma-444", no_argument, NULL, '5円' }, { "chroma-422", £spaces£ £/spaces£no_argument, NULL, '6円' }, { "video-rate-target", required_argument, £spaces£ £/spaces£NULL, 'V' }, { "video-quality", required_argument, NULL, 'v' }, { £spaces£ £/spaces£"aspect-numerator", required_argument, NULL, 's' }, { £spaces£ £/spaces£"aspect-denominator", required_argument, NULL, 'S' }, { £spaces£ £/spaces£"framerate-numerator", required_argument, NULL, 'f' }, { £spaces£ £/spaces£"framerate-denominator", required_argument, NULL, 'F' }, { £spaces£ £/spaces£"vp3-compatible", no_argument, NULL, 'c' }, { "soft-target", £spaces£ £/spaces£no_argument, NULL, '1円' }, { "keyframe-freq", required_argument, NULL, £spaces£ £/spaces£'k' }, { "buf-delay", required_argument, NULL, 'd' }, { "two-pass", £spaces£ £/spaces£no_argument, NULL, '2円' }, { "first-pass", required_argument, NULL, £spaces£ £/spaces£'3円' }, { "second-pass", required_argument, NULL, '4円' }, { NULL, 0, £spaces£ £/spaces£NULL, 0 } }; static void usage(void) { £spaces£ £/spaces£fprintf( £spaces£ £/spaces£stderr, £spaces£ £/spaces£"%s %s\n" £spaces£ £/spaces£"Usage: %s [options] \n\n" £spaces£ £/spaces£"The input argument uses C printf format to represent a list of files,\n" £spaces£ £/spaces£" i.e. file-%%06d.png to look for files file000001.png to file9999999.png \n\n" £spaces£ £/spaces£"Options: \n\n" £spaces£ £/spaces£" -o --output <filename.ogv> file name for encoded output (required);\n" £spaces£ £/spaces£" -v --video-quality Theora quality selector fro 0 to 10\n" £spaces£ £/spaces£" -t --time Time in frame count\n" £spaces£ £/spaces£" (0 yields smallest files but lowest\n" £spaces£ £/spaces£" video quality. 10 yields highest\n" £spaces£ £/spaces£" fidelity but large files)\n\n" £spaces£ £/spaces£" -V --video-rate-target bitrate target for Theora video\n\n" £spaces£ £/spaces£" --soft-target Use a large reservoir and treat the rate\n" £spaces£ £/spaces£" as a soft target; rate control is less\n" £spaces£ £/spaces£" strict but resulting quality is usually\n" £spaces£ £/spaces£" higher/smoother overall. Soft target also\n" £spaces£ £/spaces£" allows an optional -v setting to specify\n" £spaces£ £/spaces£" a minimum allowed quality.\n\n" £spaces£ £/spaces£" --two-pass Compress input using two-pass rate control\n" £spaces£ £/spaces£" This option performs both passes automatically.\n\n" £spaces£ £/spaces£" --first-pass Perform first-pass of a two-pass rate\n" £spaces£ £/spaces£" controlled encoding, saving pass data to\n" £spaces£ £/spaces£" for a later second pass\n\n" £spaces£ £/spaces£" --second-pass Perform second-pass of a two-pass rate\n" £spaces£ £/spaces£" controlled encoding, reading first-pass\n" £spaces£ £/spaces£" data from . The first pass\n" £spaces£ £/spaces£" data must come from a first encoding pass\n" £spaces£ £/spaces£" using identical input video to work\n" £spaces£ £/spaces£" properly.\n\n" £spaces£ £/spaces£" -k --keyframe-freq Keyframe frequency\n" £spaces£ £/spaces£" -d --buf-delay Buffer delay (in frames). Longer delays\n" £spaces£ £/spaces£" allow smoother rate adaptation and provide\n" £spaces£ £/spaces£" better overall quality, but require more\n" £spaces£ £/spaces£" client side buffering and add latency. The\n" £spaces£ £/spaces£" default value is the keyframe interval for\n" £spaces£ £/spaces£" one-pass encoding (or somewhat larger if\n" £spaces£ £/spaces£" --soft-target is used) and infinite for\n" £spaces£ £/spaces£" two-pass encoding.\n" £spaces£ £/spaces£" --chroma-444 Use 4:4:4 chroma subsampling\n" £spaces£ £/spaces£" --chroma-422 Use 4:2:2 chroma subsampling\n" £spaces£ £/spaces£" (4:2:0 is default)\n\n" £spaces£ £/spaces£" -s --aspect-numerator Aspect ratio numerator, default is 0\n" £spaces£ £/spaces£" -S --aspect-denominator Aspect ratio denominator, default is 0\n" £spaces£ £/spaces£" -f --framerate-numerator Frame rate numerator\n" £spaces£ £/spaces£" -F --framerate-denominator Frame rate denominator\n" £spaces£ £/spaces£" The frame rate nominator divided by this\n" £spaces£ £/spaces£" determines the frame rate in units per tick\n", £spaces£ £/spaces£PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_NAME); £spaces£ £/spaces£exit(0); } #ifdef WIN32 int alphasort (const void *a, const void *b) { £spaces£ £/spaces£return strcoll ((*(const struct dirent **) a)->d_name, £spaces£ £/spaces£(*(const struct dirent **) b)->d_name); } int scandir (const char *dir, struct dirent ***namelist, £spaces£ £/spaces£int (*select)(const struct dirent *), int (*compar)(const void *, const void *)) { £spaces£ £/spaces£DIR *d; £spaces£ £/spaces£struct dirent *entry; £spaces£ £/spaces£register int i=0; £spaces£ £/spaces£size_t entrysize; £spaces£ £/spaces£if ((d=opendir(dir)) == NULL) £spaces£ £/spaces£return(-1); £spaces£ £/spaces£*namelist=NULL; £spaces£ £/spaces£while ((entry=readdir(d)) != NULL) £spaces£ £/spaces£{ £spaces£ £/spaces£if (select == NULL || (select != NULL && (*select)(entry))) £spaces£ £/spaces£{ £spaces£ £/spaces£*namelist=(struct dirent **)realloc((void *)(*namelist), £spaces£ £/spaces£(size_t)((i+1)*sizeof(struct dirent *))); £spaces£ £/spaces£if (*namelist == NULL) return(-1); £spaces£ £/spaces£entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1; £spaces£ £/spaces£(*namelist)[i]=(struct dirent *)malloc(entrysize); £spaces£ £/spaces£if ((*namelist)[i] == NULL) return(-1); £spaces£ £/spaces£memcpy((*namelist)[i], entry, entrysize); £spaces£ £/spaces£i++; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£if (closedir(d)) return(-1); £spaces£ £/spaces£if (i == 0) return(-1); £spaces£ £/spaces£if (compar != NULL) £spaces£ £/spaces£qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar); £spaces£ £/spaces£return(i); } #endif static int theora_write_frame(unsigned long w, unsigned long h, £spaces£ £/spaces£unsigned char *yuv, int last) { £spaces£ £/spaces£th_ycbcr_buffer ycbcr; £spaces£ £/spaces£ogg_packet op; £spaces£ £/spaces£ogg_page og; £spaces£ £/spaces£unsigned long yuv_w; £spaces£ £/spaces£unsigned long yuv_h; £spaces£ £/spaces£unsigned char *yuv_y; £spaces£ £/spaces£unsigned char *yuv_u; £spaces£ £/spaces£unsigned char *yuv_v; £spaces£ £/spaces£unsigned int x; £spaces£ £/spaces£unsigned int y; £spaces£ £/spaces£/* Must hold: yuv_w >= w */ £spaces£ £/spaces£yuv_w = (w + 15) & ~15; £spaces£ £/spaces£/* Must hold: yuv_h >= h */ £spaces£ £/spaces£yuv_h = (h + 15) & ~15; £spaces£ £/spaces£ycbcr[0].width = yuv_w; £spaces£ £/spaces£ycbcr[0].height = yuv_h; £spaces£ £/spaces£ycbcr[0].stride = yuv_w; £spaces£ £/spaces£ycbcr[1].width = (chroma_format == TH_PF_444) ? yuv_w : (yuv_w >> 1); £spaces£ £/spaces£ycbcr[1].stride = ycbcr[1].width; £spaces£ £/spaces£ycbcr[1].height = (chroma_format == TH_PF_420) ? (yuv_h >> 1) : yuv_h; £spaces£ £/spaces£ycbcr[2].width = ycbcr[1].width; £spaces£ £/spaces£ycbcr[2].stride = ycbcr[1].stride; £spaces£ £/spaces£ycbcr[2].height = ycbcr[1].height; £spaces£ £/spaces£ycbcr[0].data = yuv_y = malloc(ycbcr[0].stride * ycbcr[0].height); £spaces£ £/spaces£ycbcr[1].data = yuv_u = malloc(ycbcr[1].stride * ycbcr[1].height); £spaces£ £/spaces£ycbcr[2].data = yuv_v = malloc(ycbcr[2].stride * ycbcr[2].height); £spaces£ £/spaces£for (y = 0; y < h; y++) { £spaces£ £/spaces£for (x = 0; x < w; x++) { £spaces£ £/spaces£yuv_y[x + y * yuv_w] = yuv[3 * (x + y * w) + 0]; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£if (chroma_format == TH_PF_420) { £spaces£ £/spaces£for (y = 0; y < h; y += 2) { £spaces£ £/spaces£for (x = 0; x < w; x += 2) { £spaces£ £/spaces£yuv_u[(x >> 1) + (y >> 1) * (yuv_w >> 1)] = yuv[3 * (x + y * w) £spaces£ £/spaces£+ 1]; £spaces£ £/spaces£yuv_v[(x >> 1) + (y >> 1) * (yuv_w >> 1)] = yuv[3 * (x + y * w) £spaces£ £/spaces£+ 2]; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£} else if (chroma_format == TH_PF_444) { £spaces£ £/spaces£for (y = 0; y < h; y++) { £spaces£ £/spaces£for (x = 0; x < w; x++) { £spaces£ £/spaces£yuv_u[x + y * ycbcr[1].stride] = yuv[3 * (x + y * w) + 1]; £spaces£ £/spaces£yuv_v[x + y * ycbcr[2].stride] = yuv[3 * (x + y * w) + 2]; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£} else { /* TH_PF_422 */ £spaces£ £/spaces£for (y = 0; y < h; y += 1) { £spaces£ £/spaces£for (x = 0; x < w; x += 2) { £spaces£ £/spaces£yuv_u[(x >> 1) + y * ycbcr[1].stride] £spaces£ £/spaces£= yuv[3 * (x + y * w) + 1]; £spaces£ £/spaces£yuv_v[(x >> 1) + y * ycbcr[2].stride] £spaces£ £/spaces£= yuv[3 * (x + y * w) + 2]; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£/* Theora is a one-frame-in,one-frame-out system; submit a frame £spaces£ £/spaces£for compression and pull out the packet */ £spaces£ £/spaces£/* in two-pass mode's second pass, we need to submit first-pass data */ £spaces£ £/spaces£if (passno == 2) { £spaces£ £/spaces£int ret; £spaces£ £/spaces£for (;;) { £spaces£ £/spaces£static unsigned char buffer[80]; £spaces£ £/spaces£static int buf_pos; £spaces£ £/spaces£int bytes; £spaces£ £/spaces£/*Ask the encoder how many bytes it would like.*/ £spaces£ £/spaces£bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_IN, NULL, 0); £spaces£ £/spaces£if (bytes < 0) { £spaces£ £/spaces£fprintf(stderr, "Error submitting pass data in second pass.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/*If it's got enough, stop.*/ £spaces£ £/spaces£if (bytes == 0) £spaces£ £/spaces£break; £spaces£ £/spaces£/*Read in some more bytes, if necessary.*/ £spaces£ £/spaces£if (bytes > 80 - buf_pos) £spaces£ £/spaces£bytes = 80 - buf_pos; £spaces£ £/spaces£if (bytes > 0 && fread(buffer + buf_pos, 1, bytes, twopass_file) £spaces£ £/spaces£< bytes) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not read frame data from two-pass data file!\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/*And pass them off.*/ £spaces£ £/spaces£ret = th_encode_ctl(td, TH_ENCCTL_2PASS_IN, buffer, bytes); £spaces£ £/spaces£if (ret < 0) { £spaces£ £/spaces£fprintf(stderr, "Error submitting pass data in second pass.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/*If the encoder consumed the whole buffer, reset it.*/ £spaces£ £/spaces£if (ret >= bytes) £spaces£ £/spaces£buf_pos = 0; £spaces£ £/spaces£/*Otherwise remember how much it used.*/ £spaces£ £/spaces£else £spaces£ £/spaces£buf_pos += ret; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£if (th_encode_ycbcr_in(td, ycbcr)) { £spaces£ £/spaces£fprintf(stderr, "%s: error: could not encode frame\n", option_output); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£/* in two-pass mode's first pass we need to extract and save the pass data */ £spaces£ £/spaces£if (passno == 1) { £spaces£ £/spaces£unsigned char *buffer; £spaces£ £/spaces£int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, £spaces£ £/spaces£sizeof(buffer)); £spaces£ £/spaces£if (bytes < 0) { £spaces£ £/spaces£fprintf(stderr, "Could not read two-pass data from encoder.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (fwrite(buffer, 1, bytes, twopass_file) < bytes) { £spaces£ £/spaces£fprintf(stderr, "Unable to write to two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£fflush(twopass_file); £spaces£ £/spaces£} £spaces£ £/spaces£if (!th_encode_packetout(td, last, &op)) { £spaces£ £/spaces£fprintf(stderr, "%s: error: could not read packets\n", option_output); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£if (passno != 1) { £spaces£ £/spaces£ogg_stream_packetin(&ogg_os, &op); £spaces£ £/spaces£while (ogg_stream_pageout(&ogg_os, &og)) { £spaces£ £/spaces£fwrite(og.header, og.header_len, 1, ogg_fp); £spaces£ £/spaces£fwrite(og.body, og.body_len, 1, ogg_fp); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£free(yuv_y); £spaces£ £/spaces£free(yuv_u); £spaces£ £/spaces£free(yuv_v); £spaces£ £/spaces£return 0; } static unsigned char clamp(double d) { £spaces£ £/spaces£if (d < 0) £spaces£ £/spaces£return 0; £spaces£ £/spaces£if (d > 255) £spaces£ £/spaces£return 255; £spaces£ £/spaces£return d; } static void rgb_to_yuv(png_bytep *png, unsigned char *yuv, unsigned int w, £spaces£ £/spaces£unsigned int h) { £spaces£ £/spaces£unsigned int x; £spaces£ £/spaces£unsigned int y; £spaces£ £/spaces£for (y = 0; y < h; y++) { £spaces£ £/spaces£for (x = 0; x < w; x++) { £spaces£ £/spaces£png_byte r; £spaces£ £/spaces£png_byte g; £spaces£ £/spaces£png_byte b; £spaces£ £/spaces£r = png[y][3 * x + 0]; £spaces£ £/spaces£g = png[y][3 * x + 1]; £spaces£ £/spaces£b = png[y][3 * x + 2]; £spaces£ £/spaces£/* XXX: Cringe. */ £spaces£ £/spaces£yuv[3 * (x + w * y) + 0] = clamp(0.299 * r + 0.587 * g + 0.114 * b); £spaces£ £/spaces£yuv[3 * (x + w * y) + 1] = clamp((0.436 * 255 - 0.14713 * r £spaces£ £/spaces£- 0.28886 * g + 0.436 * b) / 0.872); £spaces£ £/spaces£yuv[3 * (x + w * y) + 2] = clamp((0.615 * 255 + 0.615 * r - 0.51499 £spaces£ £/spaces£* g - 0.10001 * b) / 1.230); £spaces£ £/spaces£} £spaces£ £/spaces£} } static int png_read(const char *pathname, unsigned int *w, unsigned int *h, £spaces£ £/spaces£unsigned char **yuv) { £spaces£ £/spaces£FILE *fp; £spaces£ £/spaces£unsigned char header[8]; £spaces£ £/spaces£png_structp png_ptr; £spaces£ £/spaces£png_infop info_ptr; £spaces£ £/spaces£png_infop end_ptr; £spaces£ £/spaces£png_bytep row_data; £spaces£ £/spaces£png_bytep *row_pointers; £spaces£ £/spaces£png_color_16p bkgd; £spaces£ £/spaces£png_uint_32 width; £spaces£ £/spaces£png_uint_32 height; £spaces£ £/spaces£int bit_depth; £spaces£ £/spaces£int color_type; £spaces£ £/spaces£int interlace_type; £spaces£ £/spaces£int compression_type; £spaces£ £/spaces£int filter_method; £spaces£ £/spaces£png_uint_32 y; £spaces£ £/spaces£fp = fopen(pathname, "rb"); £spaces£ £/spaces£if (!fp) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", pathname, strerror(errno)); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£fread(header, 1, 8, fp); £spaces£ £/spaces£if (png_sig_cmp(header, 0, 8)) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", pathname, "not a PNG"); £spaces£ £/spaces£fclose(fp); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); £spaces£ £/spaces£if (!png_ptr) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", pathname, £spaces£ £/spaces£"couldn't create png read structure"); £spaces£ £/spaces£fclose(fp); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£info_ptr = png_create_info_struct(png_ptr); £spaces£ £/spaces£if (!info_ptr) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", pathname, £spaces£ £/spaces£"couldn't create png info structure"); £spaces£ £/spaces£png_destroy_read_struct(&png_ptr, NULL, NULL); £spaces£ £/spaces£fclose(fp); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£end_ptr = png_create_info_struct(png_ptr); £spaces£ £/spaces£if (!end_ptr) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", pathname, £spaces£ £/spaces£"couldn't create png info structure"); £spaces£ £/spaces£png_destroy_read_struct(&png_ptr, &info_ptr, NULL); £spaces£ £/spaces£fclose(fp); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£png_init_io(png_ptr, fp); £spaces£ £/spaces£png_set_sig_bytes(png_ptr, 8); £spaces£ £/spaces£png_read_info(png_ptr, info_ptr); £spaces£ £/spaces£png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, £spaces£ £/spaces£&interlace_type, &compression_type, &filter_method); £spaces£ £/spaces£png_set_expand(png_ptr); £spaces£ £/spaces£if (bit_depth < 8) £spaces£ £/spaces£png_set_packing(png_ptr); £spaces£ £/spaces£if (bit_depth == 16) £spaces£ £/spaces£png_set_strip_16(png_ptr); £spaces£ £/spaces£if (!(color_type & PNG_COLOR_MASK_COLOR)) £spaces£ £/spaces£png_set_gray_to_rgb(png_ptr); £spaces£ £/spaces£if (png_get_bKGD(png_ptr, info_ptr, &bkgd)) { £spaces£ £/spaces£png_set_background(png_ptr, bkgd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); £spaces£ £/spaces£} £spaces£ £/spaces£/*Note that color_type 2 and 3 can also have alpha, despite not setting the £spaces£ £/spaces£PNG_COLOR_MASK_ALPHA bit. £spaces£ £/spaces£We always strip it to prevent libpng from overrunning our buffer.*/ £spaces£ £/spaces£png_set_strip_alpha(png_ptr); £spaces£ £/spaces£row_data = (png_bytep) png_malloc(png_ptr, 3 * height * width * png_sizeof( £spaces£ £/spaces£*row_data)); £spaces£ £/spaces£row_pointers = (png_bytep *) png_malloc(png_ptr, height * png_sizeof( £spaces£ £/spaces£*row_pointers)); £spaces£ £/spaces£for (y = 0; y < height; y++) { £spaces£ £/spaces£row_pointers[y] = row_data + y * (3 * width); £spaces£ £/spaces£} £spaces£ £/spaces£png_read_image(png_ptr, row_pointers); £spaces£ £/spaces£png_read_end(png_ptr, end_ptr); £spaces£ £/spaces£*w = width; £spaces£ £/spaces£*h = height; £spaces£ £/spaces£*yuv = malloc(*w * *h * 3); £spaces£ £/spaces£rgb_to_yuv(row_pointers, *yuv, *w, *h); £spaces£ £/spaces£png_free(png_ptr, row_pointers); £spaces£ £/spaces£png_free(png_ptr, row_data); £spaces£ £/spaces£png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr); £spaces£ £/spaces£fclose(fp); £spaces£ £/spaces£return 0; } static int include_files(const struct dirent *de) { £spaces£ £/spaces£char name[1024]; £spaces£ £/spaces£int number = -1; £spaces£ £/spaces£sscanf(de->d_name, input_filter, &number); £spaces£ £/spaces£sprintf(name, input_filter, number); £spaces£ £/spaces£return !strcmp(name, de->d_name); } static int ilog(unsigned _v) { £spaces£ £/spaces£int ret; £spaces£ £/spaces£for (ret = 0; _v; ret++) £spaces£ £/spaces£_v >>= 1; £spaces£ £/spaces£return ret; } static int current_index = 0; // argument index static struct dirent ** current_dirent; // files array for argument index static int dir_index = 0; // files array index static int dir_count = 0; // files array length static int n = 0; // files array length static char *input_directory; // files array string static struct dirent **png_files; // files list static char ** argv; static int first_step = 1; void init_filelist(const char ** arglist) { £spaces£ £/spaces£argv = arglist; £spaces£ £/spaces£current_index = optind; } void init_dirent(const char *input_png) { £spaces£ £/spaces£char *input_mask; £spaces£ £/spaces£const char *scratch; £spaces£ £/spaces£input_mask = argv[current_index]; £spaces£ £/spaces£current_index++; £spaces£ £/spaces£if (!input_mask) { £spaces£ £/spaces£fprintf(stderr, "505 no input files specified; run with -h for help.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/* dirname and basename must operate on scratch strings */ £spaces£ £/spaces£scratch = strdup(input_mask); £spaces£ £/spaces£input_directory = strdup(dirname(scratch)); £spaces£ £/spaces£free(scratch); £spaces£ £/spaces£scratch = strdup(input_mask); £spaces£ £/spaces£input_filter = strdup(basename(scratch)); £spaces£ £/spaces£free(scratch); £spaces£ £/spaces£fprintf(stderr, "Input directory: %s\n", input_directory); £spaces£ £/spaces£n = scandir(input_directory, &png_files, include_files, alphasort); £spaces£ £/spaces£if (!n) { £spaces£ £/spaces£fprintf(stderr, "518 no input files found; run with -h for help.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£dir_count = n; £spaces£ £/spaces£snprintf(input_png, 1023, "%s/%s", input_directory, £spaces£ £/spaces£png_files[dir_index]->d_name); } int nextdirectory(const char * input_png) { £spaces£ £/spaces£if (dir_index >= dir_count) { £spaces£ £/spaces£if (current_index < optind) { £spaces£ £/spaces£init_dirent(input_png); £spaces£ £/spaces£dir_index = 0; £spaces£ £/spaces£} else { £spaces£ £/spaces£return 1; £spaces£ £/spaces£return 0; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£snprintf(input_png, 1023, "%s/%s", input_directory, £spaces£ £/spaces£png_files[dir_index++]->d_name); £spaces£ £/spaces£return 1; } int nextfile(unsigned int *w, unsigned int *h, th_ycbcr_buffer *ycbcr, £spaces£ £/spaces£const char *input_png) { £spaces£ £/spaces£if (first_step) { £spaces£ £/spaces£init_dirent(input_png); £spaces£ £/spaces£first_step = 0; £spaces£ £/spaces£} £spaces£ £/spaces£nextdirectory(input_png); £spaces£ £/spaces£fprintf(stderr, "File = %s\n", input_png); £spaces£ £/spaces£if (png_read(input_png, &w, &h, &ycbcr)) { £spaces£ £/spaces£fprintf(stderr, "could not read %s\n", input_png); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£fprintf(stderr, "Png read OK"); £spaces£ £/spaces£return 1; } int main(int argc, char *argv[]) { £spaces£ £/spaces£int multi = 1; £spaces£ £/spaces£int c, long_option_index; £spaces£ £/spaces£int i; £spaces£ £/spaces£char *input_mask; £spaces£ £/spaces£char *scratch; £spaces£ £/spaces£th_comment tc; £spaces£ £/spaces£int soft_target = 0; £spaces£ £/spaces£int ret; £spaces£ £/spaces£int timeFrames = 24 * 5; £spaces£ £/spaces£printf("Option switch"); £spaces£ £/spaces£while (1) { £spaces£ £/spaces£c = getopt_long(argc, argv, optstring, options, &long_option_index); £spaces£ £/spaces£if (c == EOF) £spaces£ £/spaces£break; £spaces£ £/spaces£switch (c) { £spaces£ £/spaces£case 'h': £spaces£ £/spaces£usage(); £spaces£ £/spaces£break; £spaces£ £/spaces£case 'o': £spaces£ £/spaces£option_output = optarg; £spaces£ £/spaces£break; £spaces£ £/spaces£; £spaces£ £/spaces£case 'v': £spaces£ £/spaces£video_quality = rint(atof(optarg) * 6.3); £spaces£ £/spaces£if (video_quality < 0 || video_quality > 63) { £spaces£ £/spaces£fprintf(stderr, "Illegal video quality (choose 0 through 10)\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£video_rate = 0; £spaces£ £/spaces£break; £spaces£ £/spaces£case 'V': £spaces£ £/spaces£video_rate = rint(atof(optarg) * 1000); £spaces£ £/spaces£if (video_rate < 1) { £spaces£ £/spaces£fprintf(stderr, "Illegal video bitrate (choose > 0 please)\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£video_quality = 0; £spaces£ £/spaces£break; £spaces£ £/spaces£case '1円': £spaces£ £/spaces£soft_target = 1; £spaces£ £/spaces£break; £spaces£ £/spaces£case 'c': £spaces£ £/spaces£vp3_compatible = 1; £spaces£ £/spaces£break; £spaces£ £/spaces£case 'k': £spaces£ £/spaces£keyframe_frequency = rint(atof(optarg)); £spaces£ £/spaces£if (keyframe_frequency < 1 || keyframe_frequency > 2147483647) { £spaces£ £/spaces£fprintf(stderr, "Illegal keyframe frequency\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£break; £spaces£ £/spaces£case 'd': £spaces£ £/spaces£buf_delay = atoi(optarg); £spaces£ £/spaces£if (buf_delay <= 0) { £spaces£ £/spaces£fprintf(stderr, "Illegal buffer delay\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£break; £spaces£ £/spaces£case 's': £spaces£ £/spaces£video_aspect_numerator = rint(atof(optarg)); £spaces£ £/spaces£break; £spaces£ £/spaces£case 'S': £spaces£ £/spaces£video_aspect_denominator = rint(atof(optarg)); £spaces£ £/spaces£break; £spaces£ £/spaces£case 't': £spaces£ £/spaces£timeFrames = (atoi(optarg)); £spaces£ £/spaces£break; £spaces£ £/spaces£case 'f': £spaces£ £/spaces£video_fps_numerator = rint(atof(optarg)); £spaces£ £/spaces£break; £spaces£ £/spaces£case 'F': £spaces£ £/spaces£video_fps_denominator = rint(atof(optarg)); £spaces£ £/spaces£break; £spaces£ £/spaces£case '5円': £spaces£ £/spaces£chroma_format = TH_PF_444; £spaces£ £/spaces£break; £spaces£ £/spaces£case '6円': £spaces£ £/spaces£chroma_format = TH_PF_422; £spaces£ £/spaces£break; £spaces£ £/spaces£case '2円': £spaces£ £/spaces£twopass = 3; /* perform both passes */ £spaces£ £/spaces£twopass_file = tmpfile(); £spaces£ £/spaces£if (!twopass_file) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Unable to open temporary file for twopass data\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£break; £spaces£ £/spaces£case '3円': £spaces£ £/spaces£twopass = 1; /* perform first pass */ £spaces£ £/spaces£twopass_file = fopen(optarg, "wb"); £spaces£ £/spaces£if (!twopass_file) { £spaces£ £/spaces£fprintf(stderr, "Unable to open \'%s\' for twopass data\n", £spaces£ £/spaces£optarg); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£break; £spaces£ £/spaces£case '4円': £spaces£ £/spaces£twopass = 2; /* perform second pass */ £spaces£ £/spaces£twopass_file = fopen(optarg, "rb"); £spaces£ £/spaces£if (!twopass_file) { £spaces£ £/spaces£fprintf(stderr, "Unable to open twopass data file \'%s\'", £spaces£ £/spaces£optarg); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£break; £spaces£ £/spaces£default: £spaces£ £/spaces£usage(); £spaces£ £/spaces£break; £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£if (argc < 3) { £spaces£ £/spaces£usage(); £spaces£ £/spaces£} £spaces£ £/spaces£if (soft_target) { £spaces£ £/spaces£if (video_rate <= 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Soft rate target (--soft-target) requested without a bitrate (-V).\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (video_quality == -1) £spaces£ £/spaces£video_quality = 0; £spaces£ £/spaces£} else { £spaces£ £/spaces£if (video_rate > 0) £spaces£ £/spaces£video_quality = 0; £spaces£ £/spaces£if (video_quality == -1) £spaces£ £/spaces£video_quality = 48; £spaces£ £/spaces£} £spaces£ £/spaces£if (keyframe_frequency <= 0) { £spaces£ £/spaces£/*Use a default keyframe frequency of 64 for 1-pass (streaming) mode, and £spaces£ £/spaces256ドル for two-pass mode.*/ £spaces£ £/spaces£keyframe_frequency = twopass ? 256 : 64; £spaces£ £/spaces£} £spaces£ £/spaces£fprintf(stderr, "Init argument"); £spaces£ £/spaces£init_filelist(argv); £spaces£ £/spaces£input_mask = argv[optind]; £spaces£ £/spaces£if (!input_mask) { £spaces£ £/spaces£fprintf(stderr, "no input files specified; run with -h for help.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/* dirname and basename must operate on scratch strings */ £spaces£ £/spaces£scratch = strdup(input_mask); £spaces£ £/spaces£input_directory = strdup(dirname(scratch)); £spaces£ £/spaces£free(scratch); £spaces£ £/spaces£scratch = strdup(input_mask); £spaces£ £/spaces£input_filter = strdup(basename(scratch)); £spaces£ £/spaces£free(scratch); #ifdef DEBUG £spaces£ £/spaces£fprintf(stderr, "scanning %s with filter '%s'\n", £spaces£ £/spaces£input_directory, input_filter); #endif £spaces£ £/spaces£ogg_fp = fopen(option_output, "wb"); £spaces£ £/spaces£if (!ogg_fp) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", option_output, £spaces£ £/spaces£"couldn't open output file"); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£srand(time(NULL)); £spaces£ £/spaces£if (ogg_stream_init(&ogg_os, rand())) { £spaces£ £/spaces£fprintf(stderr, "%s: error: %s\n", option_output, £spaces£ £/spaces£"couldn't create ogg stream state"); £spaces£ £/spaces£return 1; £spaces£ £/spaces£} £spaces£ £/spaces£for (passno = (twopass == 3 ? 1 : twopass); passno <= (twopass == 3 ? 2 £spaces£ £/spaces£: twopass); passno++) { £spaces£ £/spaces£unsigned int w; £spaces£ £/spaces£unsigned int h; £spaces£ £/spaces£unsigned char *yuv; £spaces£ £/spaces£char input_png[1024]; £spaces£ £/spaces£int frameIndex = 0; £spaces£ £/spaces£th_ycbcr_buffer ycbcr; £spaces£ £/spaces£ycbcr[0].data = 0; £spaces£ £/spaces£int last = 0; £spaces£ £/spaces£fprintf(stderr, "Call to next file"); £spaces£ £/spaces£nextfile(&w, &h, &ycbcr, input_png); £spaces£ £/spaces£if (passno != 2) £spaces£ £/spaces£fprintf(stderr, "%d frames, %dx%d\n", n, w, h); £spaces£ £/spaces£/* setup complete. Raw processing loop */ £spaces£ £/spaces£switch (passno) { £spaces£ £/spaces£case 0: £spaces£ £/spaces£case 2: £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"\rCompressing.... \n"); £spaces£ £/spaces£break; £spaces£ £/spaces£case 1: £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"\rScanning first pass.... \n"); £spaces£ £/spaces£break; £spaces£ £/spaces£} £spaces£ £/spaces£fprintf(stderr, "%s\n", input_png); £spaces£ £/spaces£th_info_init(&ti); £spaces£ £/spaces£ti.frame_width = ((w + 15) >> 4) << 4; £spaces£ £/spaces£ti.frame_height = ((h + 15) >> 4) << 4; £spaces£ £/spaces£ti.pic_width = w; £spaces£ £/spaces£ti.pic_height = h; £spaces£ £/spaces£ti.pic_x = 0; £spaces£ £/spaces£ti.pic_y = 0; £spaces£ £/spaces£ti.fps_numerator = video_fps_numerator; £spaces£ £/spaces£ti.fps_denominator = video_fps_denominator; £spaces£ £/spaces£ti.aspect_numerator = video_aspect_numerator; £spaces£ £/spaces£ti.aspect_denominator = video_aspect_denominator; £spaces£ £/spaces£ti.colorspace = TH_CS_UNSPECIFIED; £spaces£ £/spaces£ti.pixel_fmt = chroma_format; £spaces£ £/spaces£ti.target_bitrate = video_rate; £spaces£ £/spaces£ti.quality = video_quality; £spaces£ £/spaces£ti.keyframe_granule_shift = ilog(keyframe_frequency - 1); £spaces£ £/spaces£td = th_encode_alloc(&ti); £spaces£ £/spaces£th_info_clear(&ti); £spaces£ £/spaces£/* setting just the granule shift only allows power-of-two keyframe £spaces£ £/spaces£spacing. Set the actual requested spacing. */ £spaces£ £/spaces£ret = th_encode_ctl(td, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, £spaces£ £/spaces£&keyframe_frequency, sizeof(keyframe_frequency - 1)); £spaces£ £/spaces£if (ret < 0) { £spaces£ £/spaces£fprintf(stderr, "Could not set keyframe interval to %d.\n", £spaces£ £/spaces£(int) keyframe_frequency); £spaces£ £/spaces£} £spaces£ £/spaces£if (vp3_compatible) { £spaces£ £/spaces£ret = th_encode_ctl(td, TH_ENCCTL_SET_VP3_COMPATIBLE, £spaces£ £/spaces£&vp3_compatible, sizeof(vp3_compatible)); £spaces£ £/spaces£if (ret < 0 || !vp3_compatible) { £spaces£ £/spaces£fprintf(stderr, "Could not enable strict VP3 compatibility.\n"); £spaces£ £/spaces£if (ret >= 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Ensure your source format is supported by VP3.\n"); £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"(4:2:0 pixel format, width and height multiples of 16).\n"); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£if (soft_target) { £spaces£ £/spaces£/* reverse the rate control flags to favor a 'long time' strategy */ £spaces£ £/spaces£int arg = TH_RATECTL_CAP_UNDERFLOW; £spaces£ £/spaces£ret £spaces£ £/spaces£= th_encode_ctl(td, TH_ENCCTL_SET_RATE_FLAGS, &arg, £spaces£ £/spaces£sizeof(arg)); £spaces£ £/spaces£if (ret < 0) £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not set encoder flags for --soft-target\n"); £spaces£ £/spaces£/* Default buffer control is overridden on two-pass */ £spaces£ £/spaces£if (!twopass && buf_delay < 0) { £spaces£ £/spaces£if ((keyframe_frequency * 7 >> 1) > 5 * video_fps_numerator £spaces£ £/spaces£/ video_fps_denominator) £spaces£ £/spaces£arg = keyframe_frequency * 7 >> 1; £spaces£ £/spaces£else £spaces£ £/spaces£arg = 5 * video_fps_numerator / video_fps_denominator; £spaces£ £/spaces£ret = th_encode_ctl(td, TH_ENCCTL_SET_RATE_BUFFER, &arg, £spaces£ £/spaces£sizeof(arg)); £spaces£ £/spaces£if (ret < 0) £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not set rate control buffer for --soft-target\n"); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£/* set up two-pass if needed */ £spaces£ £/spaces£if (passno == 1) { £spaces£ £/spaces£unsigned char *buffer; £spaces£ £/spaces£int bytes; £spaces£ £/spaces£bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, £spaces£ £/spaces£sizeof(buffer)); £spaces£ £/spaces£if (bytes < 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not set up the first pass of two-pass mode.\n"); £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Did you remember to specify an estimated bitrate?\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£/*Perform a seek test to ensure we can overwrite this placeholder data at £spaces£ £/spaces£the end; this is better than letting the user sit through a whole £spaces£ £/spaces£encode only to find out their pass 1 file is useless at the end.*/ £spaces£ £/spaces£if (fseek(twopass_file, 0, SEEK_SET) < 0) { £spaces£ £/spaces£fprintf(stderr, "Unable to seek in two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (fwrite(buffer, 1, bytes, twopass_file) < bytes) { £spaces£ £/spaces£fprintf(stderr, "Unable to write to two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£fflush(twopass_file); £spaces£ £/spaces£} £spaces£ £/spaces£if (passno == 2) { £spaces£ £/spaces£/*Enable the second pass here. £spaces£ £/spaces£We make this call just to set the encoder into 2-pass mode, because £spaces£ £/spaces£by default enabling two-pass sets the buffer delay to the whole file £spaces£ £/spaces£(because there's no way to explicitly request that behavior). £spaces£ £/spaces£If we waited until we were actually encoding, it would overwite our £spaces£ £/spaces£settings.*/ £spaces£ £/spaces£if (th_encode_ctl(td, TH_ENCCTL_2PASS_IN, NULL, 0) < 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not set up the second pass of two-pass mode.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (twopass == 3) { £spaces£ £/spaces£if (fseek(twopass_file, 0, SEEK_SET) < 0) { £spaces£ £/spaces£fprintf(stderr, "Unable to seek in two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£/*Now we can set the buffer delay if the user requested a non-default one £spaces£ £/spaces£(this has to be done after two-pass is enabled).*/ £spaces£ £/spaces£if (passno != 1 && buf_delay >= 0) { £spaces£ £/spaces£ret = th_encode_ctl(td, TH_ENCCTL_SET_RATE_BUFFER, &buf_delay, £spaces£ £/spaces£sizeof(buf_delay)); £spaces£ £/spaces£if (ret < 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Warning: could not set desired buffer delay.\n"); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£/* write the bitstream header packets with proper page interleave */ £spaces£ £/spaces£th_comment_init(&tc); £spaces£ £/spaces£/* first packet will get its own page automatically */ £spaces£ £/spaces£if (th_encode_flushheader(td, &tc, &op) <= 0) { £spaces£ £/spaces£fprintf(stderr, "Internal Theora library error.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£th_comment_clear(&tc); £spaces£ £/spaces£if (passno != 1) { £spaces£ £/spaces£ogg_stream_packetin(&ogg_os, &op); £spaces£ £/spaces£if (ogg_stream_pageout(&ogg_os, &og) != 1) { £spaces£ £/spaces£fprintf(stderr, "Internal Ogg library error.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£fwrite(og.header, 1, og.header_len, ogg_fp); £spaces£ £/spaces£fwrite(og.body, 1, og.body_len, ogg_fp); £spaces£ £/spaces£} £spaces£ £/spaces£/* create the remaining theora headers */ £spaces£ £/spaces£for (;;) { £spaces£ £/spaces£ret = th_encode_flushheader(td, &tc, &op); £spaces£ £/spaces£if (ret < 0) { £spaces£ £/spaces£fprintf(stderr, "Internal Theora library error.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} else if (!ret) £spaces£ £/spaces£break; £spaces£ £/spaces£if (passno != 1) £spaces£ £/spaces£ogg_stream_packetin(&ogg_os, &op); £spaces£ £/spaces£} £spaces£ £/spaces£/* Flush the rest of our headers. This ensures £spaces£ £/spaces£the actual data in each stream will start £spaces£ £/spaces£on a new page, as per spec. */ £spaces£ £/spaces£if (passno != 1) { £spaces£ £/spaces£for (;;) { £spaces£ £/spaces£int result = ogg_stream_flush(&ogg_os, &og); £spaces£ £/spaces£if (result < 0) { £spaces£ £/spaces£/* can't get here */ £spaces£ £/spaces£fprintf(stderr, "Internal Ogg library error.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (result == 0) £spaces£ £/spaces£break; £spaces£ £/spaces£fwrite(og.header, 1, og.header_len, ogg_fp); £spaces£ £/spaces£fwrite(og.body, 1, og.body_len, ogg_fp); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£int lastfile = 0; £spaces£ £/spaces£while (1) { £spaces£ £/spaces£i = 0; £spaces£ £/spaces£last = 0; £spaces£ £/spaces£do { £spaces£ £/spaces£frameIndex = 0; £spaces£ £/spaces£while (frameIndex < timeFrames) { £spaces£ £/spaces£if (i >= dir_index - 1 && frameIndex == timeFrames - 1 £spaces£ £/spaces£&& lastfile) £spaces£ £/spaces£last = 1; £spaces£ £/spaces£if (theora_write_frame(w, h, ycbcr, last)) { £spaces£ £/spaces£fprintf(stderr, "Encoding error.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£printf("Frame no %d\n", frameIndex++); £spaces£ £/spaces£} £spaces£ £/spaces£free(ycbcr); £spaces£ £/spaces£i++; £spaces£ £/spaces£if (!lastfile) { £spaces£ £/spaces£lastfile = nextfile(&w, &h, &ycbcr, input_png); £spaces£ £/spaces£} £spaces£ £/spaces£} while (!last); £spaces£ £/spaces£} £spaces£ £/spaces£if (passno == 1) { £spaces£ £/spaces£/* need to read the final (summary) packet */ £spaces£ £/spaces£unsigned char *buffer; £spaces£ £/spaces£int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, £spaces£ £/spaces£sizeof(buffer)); £spaces£ £/spaces£if (bytes < 0) { £spaces£ £/spaces£fprintf(stderr, £spaces£ £/spaces£"Could not read two-pass summary data from encoder.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (fseek(twopass_file, 0, SEEK_SET) < 0) { £spaces£ £/spaces£fprintf(stderr, "Unable to seek in two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£if (fwrite(buffer, 1, bytes, twopass_file) < bytes) { £spaces£ £/spaces£fprintf(stderr, "Unable to write to two-pass data file.\n"); £spaces£ £/spaces£exit(1); £spaces£ £/spaces£} £spaces£ £/spaces£fflush(twopass_file); £spaces£ £/spaces£} £spaces£ £/spaces£} £spaces£ £/spaces£th_encode_free(td); £spaces£ £/spaces£if (ogg_stream_flush(&ogg_os, &og)) { £spaces£ £/spaces£fwrite(og.header, og.header_len, 1, ogg_fp); £spaces£ £/spaces£fwrite(og.body, og.body_len, 1, ogg_fp); £spaces£ £/spaces£} £spaces£ £/spaces£free(input_directory); £spaces£ £/spaces£free(input_filter); £spaces£ £/spaces£while (n--) £spaces£ £/spaces£free(png_files[n]); £spaces£ £/spaces£free(png_files); £spaces£ £/spaces£if (ogg_fp) { £spaces£ £/spaces£fflush(ogg_fp); £spaces£ £/spaces£if (ogg_fp != stdout) £spaces£ £/spaces£fclose(ogg_fp); £spaces£ £/spaces£} £spaces£ £/spaces£ogg_stream_clear(&ogg_os); £spaces£ £/spaces£if (twopass_file) £spaces£ £/spaces£fclose(twopass_file); £spaces£ £/spaces£fprintf(stderr, "\r \ndone.\n\n"); £spaces£ £/spaces£return 0; }

AltStyle によって変換されたページ (->オリジナル) /