[xiph-cvs] cvs commit: w3d ppm.c ppm.h tarkin-io.c tarkin-io.h tarkin_dec.c tarkin_enc.c Makefile TODO bitcoder.h rle.h tarkin.c tarkin.h wavelet.c yuv.c yuv.h main.c
Holger Waechtler
holger at xiph.org
Fri Jun 29 02:19:28 PDT 2001
holger 01/06/29 02:19:27
Modified: . Makefile TODO bitcoder.h rle.h tarkin.c tarkin.h
wavelet.c yuv.c yuv.h
Added: . ppm.c ppm.h tarkin-io.c tarkin-io.h tarkin_dec.c
tarkin_enc.c
Removed: . main.c
Log:
- designed a something-like-a-fileformat; still has to be oggetized
(file i/o is in tarkin-io.[hc], this is the place to work on this ...)
- tarkin_enc.c / tarkin_dec.c encode/decode now the tarkin stream
- removed main.c
- ppm stuff is now in a ppm.[hc]
Revision Changes Path
1.4 +12 -7 w3d/Makefile
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/w3d/Makefile,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Makefile 2001/06/25 07:56:07 1.3
+++ Makefile 2001/06/29 09:19:25 1.4
@@ -4,18 +4,22 @@
CFLAGS = -g -O0 -Wall -DTYPE=int16_t -DRLECODER
LFLAGS = -g
-OBJS = wavelet.o wavelet_xform.o yuv.o tarkin.o main.o
-SRCS = $(OBJS:.o=.c)
+OBJS = ppm.o wavelet.o wavelet_xform.o yuv.o tarkin.o tarkin-io.o
+
TEST_TARGETS = _test_bitcoder _test_rle _test_huffman
+
+SRCS = $(OBJS:.o=.c)
TEST_OBJS = $(TEST_TARGETS:=.o)
TEST_SRCS = $(TEST_OBJS:.o=.c)
-TARGET = main
+
+all: tarkin_enc tarkin_dec
-all: $(TARGET)
+tarkin_enc: $(OBJS) tarkin_enc.o
+ $(CC) $(LFLAGS) $(OBJS) tarkin_enc.o -o $@
-$(TARGET): $(OBJS)
- $(CC) $(LFLAGS) $(OBJS) -o $@
+tarkin_dec: $(OBJS) tarkin_dec.o
+ $(CC) $(LFLAGS) $(OBJS) tarkin_dec.o -o $@
.c.o: .depend
$(CC) $(CFLAGS) -c $<
@@ -23,6 +27,7 @@
clean:
$(RM) $(OBJS) $(TARGET) gmon.out core .depend .depend.bak rle.histogram *.ppm
$(RM) $(TEST_TARGETS) $(TEST_OBJS)
+ $(RM) tarkin_enc tarkin_dec tarkin_enc.o tarkin_dec.o
test: .depend $(TEST_TARGETS)
@@ -34,6 +39,6 @@
.depend: $(SRCS) $(TEST_SRCS)
$(RM) .depend
touch .depend
- sh makedepend -f.depend -- $(CFLAGS) -- $(SRCS) $(TEST_SRCS)
+ sh makedepend -f.depend -- $(CFLAGS) -- $(SRCS) $(TEST_SRCS) tarkin_enc.c tarkin_dec.c
-include .depend
1.4 +3 -1 w3d/TODO
Index: TODO
===================================================================
RCS file: /usr/local/cvsroot/w3d/TODO,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TODO 2001/06/25 07:56:07 1.3
+++ TODO 2001/06/29 09:19:25 1.4
@@ -1,8 +1,10 @@
+- segfaults while destroying encoder stream
+
Here only the wavelet-related TODO's:
- arithmetic binary entropy coders may be faster, simpler and more efficient;
implement the ZP-Coder
- - design/implement a stream format
+ - oggetize the stream format
- write avitotarkin/quicktimetotarkin/mpegtotarkin/player/recorder
(a libsndfile/libaudiofile alike video library would be great !)
- profile
1.2 +2 -1 w3d/bitcoder.h
Index: bitcoder.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/bitcoder.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- bitcoder.h 2001/06/25 07:57:09 1.1
+++ bitcoder.h 2001/06/29 09:19:25 1.2
@@ -49,7 +49,8 @@
static inline
void bitcoder_encoder_done (BitCoderState *s)
{
- free (s->bitstream);
+// XXX FIXME !!!
+// free (s->bitstream);
}
1.3 +1 -0 w3d/rle.h
Index: rle.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/rle.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- rle.h 2001/06/25 07:56:07 1.2
+++ rle.h 2001/06/29 09:19:25 1.3
@@ -1,6 +1,7 @@
#ifndef __RLE_H
#define __RLE_H
+#include <string.h>
#include "bitcoder.h"
#if defined(RLECODER)
1.2 +238 -72 w3d/tarkin.c
Index: tarkin.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- tarkin.c 2001/06/25 07:56:07 1.1
+++ tarkin.c 2001/06/29 09:19:25 1.2
@@ -1,128 +1,294 @@
-/**
- * Not yet working.
- *
- * Everything here should get oggetized. But for now I don't
- * want to struggle with packets, so I simply write everything
- * binary.
+/*
+ * The real io-stuff is in tarkin-io.c
+ * (this one has to be rewritten to write ogg streams ...)
*/
#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
#include <string.h>
#include "tarkin.h"
+#include "tarkin-io.h"
+#include "yuv.h"
+#define N_FRAMES 1
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define LE32_TO_CPU(x)
-#define CPU_TO_LE32(x)
+TarkinStream* tarkin_stream_new (int fd)
+{
+ TarkinStream *s = (TarkinStream*) calloc (1, sizeof(TarkinStream));
-#elif __BYTE_ORDER == __BIG_ENDIAN
+ if (!s)
+ return NULL;
-#define LE32_TO_CPU(x) x = (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) \
- | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) << 24))
-#define CPU_TO_LE32(x) x = (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) \
- | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) << 24))
+ s->fd = fd;
+ s->frames_per_buf = N_FRAMES;
-#else
-#error unknown endianess !!
-#endif
+ return s;
+}
-static
-int read_tarkin_header (int fd, TarkinStream *s)
+void tarkin_stream_destroy (TarkinStream *s)
{
- char signature [6];
+ uint32_t i, j;
- if (read (fd, signature, 6) < 6)
- return TARKIN_IO_ERROR;
+ if (!s)
+ return;
- if (!strncmp(signature, "tarkin", 6) == 0)
- return TARKIN_SIGNATURE_NOT_FOUND;
+ for (i=0; i<s->n_layers; i++)
+ if (s->layer[i].waveletbuf)
+ for (j=0; j<s->layer[i].n_comp; j++)
+ wavelet_3d_buf_destroy (s->layer[i].waveletbuf[j]);
- if (read (fd, &s->n_layers, 4) < 4)
- return TARKIN_IO_ERROR;
+ if (s->layer)
+ free(s->layer);
- LE32_TO_CPU(s->n_layers);
+/**
+ * XXX FIXME HACK Alert: segfault when doin' this right ...
+ * somewhere is something really wrong ...
+ * perhaps in merge_bitstreams() ???
+ */
+// if (s->bitstream);
+// free(s->bitstream);
- return 0;
+ free(s);
}
+
-static
-int read_layer_descs (int fd, TarkinStream *s)
+int tarkin_stream_write_layer_descs (TarkinStream *s,
+ uint32_t n_layers,
+ TarkinVideoLayerDesc desc [])
{
- int i;
+ TarkinError err;
+ uint32_t max_bitstream_len = 0;
+ uint32_t i, j;
+
+ s->n_layers = n_layers;
+ s->layer = (TarkinVideoLayer*) calloc (n_layers, sizeof(TarkinVideoLayer));
+
+ for (i=0; i<n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
+
+ memcpy (&layer->desc, &desc[i], sizeof(TarkinVideoLayerDesc));
+
+ switch (layer->desc.format) {
+ case TARKIN_GRAYSCALE:
+ layer->n_comp = 1;
+ layer->color_fwd_xform = grayscale_to_y;
+ layer->color_inv_xform = y_to_grayscale;
+ break;
+ case TARKIN_RGB24:
+ layer->n_comp = 3;
+ layer->color_fwd_xform = rgb24_to_yuv;
+ layer->color_inv_xform = yuv_to_rgb24;
+ break;
+ case TARKIN_RGB32:
+ layer->n_comp = 3;
+ layer->color_fwd_xform = rgb32_to_yuv;
+ layer->color_inv_xform = yuv_to_rgb32;
+ break;
+ case TARKIN_RGBA:
+ layer->n_comp = 4;
+ layer->color_fwd_xform = rgba_to_yuv;
+ layer->color_inv_xform = yuv_to_rgba;
+ break;
+ default:
+ BUG("unknown color format");
+ break;
+ };
+
+ layer->waveletbuf = (Wavelet3DBuf**) calloc (layer->n_comp,
+ sizeof(Wavelet3DBuf*));
+ for (j=0; j<layer->n_comp; j++)
+ layer->waveletbuf[j] = wavelet_3d_buf_new (desc[i].width,
+ desc[i].height,
+ desc[i].frames_per_buf);
- s->layer = (TarkinVideoLayer*) calloc (1, s->n_layers * sizeof(TarkinVideoLayer));
+ layer->bitstream_len = layer->desc.bitrate / (8 * layer->n_comp);
- for (i=0; i<s->n_layers; i++) {
- if (read (fd, &s->layer[i], sizeof(TarkinVideoLayer)) < sizeof(TarkinVideoLayer)) {
- tarkin_stream_destroy (s);
- return TARKIN_IO_ERROR;
- }
- LE32_TO_CPU(s->layer[i].width);
- LE32_TO_CPU(s->layer[i].height);
- LE32_TO_CPU(s->layer[i].frames_per_buf);
- LE32_TO_CPU(s->layer[i].bitrate);
- LE32_TO_CPU(s->layer[i].format);
+ if (layer->bitstream_len > max_bitstream_len)
+ max_bitstream_len = layer->bitstream_len;
+
}
- return 0;
+ if ((err = write_tarkin_header(s->fd, s)) != TARKIN_OK)
+ return err;
+
+ err = write_layer_descs(s->fd, s);
+
+ s->bitstream = (uint8_t*) malloc (max_bitstream_len);
+
+ return err;
}
-TarkinStream* tarkin_stream_new (int fd)
+void tarkin_stream_flush (TarkinStream *s)
{
- TarkinStream *s = (TarkinStream*) calloc (1, sizeof(TarkinStream));
+ uint32_t i, j;
- if (!s)
- return NULL;
+ s->current_frame_in_buf=0;
- s->fd = fd;
+ for (i=0; i<s->n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
- return s;
+ for (j=0; j<layer->n_comp; j++) {
+ uint32_t bitstream_len;
+
+ wavelet_3d_buf_fwd_xform (layer->waveletbuf[j], 2, 2);
+ bitstream_len = wavelet_3d_buf_encode_coeff (layer->waveletbuf[j],
+ s->bitstream,
+ layer->desc.bitrate/8);
+ write_tarkin_bitstream (s->fd, s->bitstream, bitstream_len);
+ }
+ }
}
-void tarkin_stream_destroy (TarkinStream *s)
+uint32_t tarkin_stream_write_frame (TarkinStream *s, uint8_t **rgba)
{
- int i;
+ uint32_t i;
- if (!s)
- return;
+ for (i=0; i<s->n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
- for (i=0; i<s->n_layers; i++)
- if (s->layer[i].waveletbuf)
- wavelet_3d_buf_destroy (s->layer[i].waveletbuf);
+ layer->color_fwd_xform (rgba[i], layer->waveletbuf,
+ s->current_frame_in_buf);
+ }
- free(s->layer);
- free(s);
+ s->current_frame_in_buf++;
+
+ if (s->current_frame_in_buf == s->frames_per_buf)
+ tarkin_stream_flush (s);
+
+ return (++s->current_frame);
}
-uint32_t tarkin_read_frame (TarkinStream *s, uint8_t *buf)
+
+
+/**
+ * return value: number of layers, 0 on i/o error
+ */
+uint32_t tarkin_stream_read_header (TarkinStream *s)
{
- if (s->n_layers == 0) {
- if (read_tarkin_header(s->fd, s) != 0) {
- tarkin_stream_destroy (s);
- return 0;
- }
+ uint32_t max_bitstream_len = 0;
+ uint32_t i, j;
+
+ if (read_tarkin_header(s->fd, s) != TARKIN_OK)
+ return 0;
+
+ if (read_layer_descs(s->fd, s) != TARKIN_OK)
+ return 0;
+
+ for (i=0; i<s->n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
+
+ if (layer->desc.format != TARKIN_RGB24)
+ exit (-1);
- if (read_layer_descs(s->fd, s) != 0) {
- tarkin_stream_destroy (s);
- return 0;
+ switch (layer->desc.format) {
+ case TARKIN_GRAYSCALE:
+ layer->n_comp = 1;
+ layer->color_fwd_xform = grayscale_to_y;
+ layer->color_inv_xform = y_to_grayscale;
+ break;
+ case TARKIN_RGB24:
+ layer->n_comp = 3;
+ layer->color_fwd_xform = rgb24_to_yuv;
+ layer->color_inv_xform = yuv_to_rgb24;
+ break;
+ case TARKIN_RGB32:
+ layer->n_comp = 3;
+ layer->color_fwd_xform = rgb32_to_yuv;
+ layer->color_inv_xform = yuv_to_rgb32;
+ break;
+ case TARKIN_RGBA:
+ layer->n_comp = 4;
+ layer->color_fwd_xform = rgba_to_yuv;
+ layer->color_inv_xform = yuv_to_rgba;
+ break;
+ default:
+ BUG("unknown color format");
+ };
+
+ layer->waveletbuf = (Wavelet3DBuf**) calloc (layer->n_comp,
+ sizeof(Wavelet3DBuf*));
+ for (j=0; j<layer->n_comp; j++) {
+ layer->waveletbuf[j] = wavelet_3d_buf_new (layer->desc.width,
+ layer->desc.height,
+ layer->desc.frames_per_buf);
+ if (!layer->waveletbuf[j])
+ return 0;
}
+
+ layer->bitstream_len = layer->desc.bitrate / (8 * layer->n_comp);
+
+ if (layer->bitstream_len > max_bitstream_len)
+ max_bitstream_len = layer->bitstream_len;
}
-return 0;
+
+ s->bitstream = (uint8_t*) malloc (max_bitstream_len);
+
+ return s->n_layers;
}
-uint32_t tarkin_write_set_bitrate (TarkinStream *s, uint32_t bitrate);
-uint32_t tarkin_write_frame (TarkinStream *s, uint8_t *buf);
+
+int tarkin_stream_get_layer_desc (TarkinStream *s,
+ uint32_t layer_id,
+ TarkinVideoLayerDesc *desc)
+{
+ if (layer_id > s->n_layers-1)
+ return -1;
+
+ memcpy (desc, &(s->layer[layer_id].desc), sizeof(TarkinVideoLayerDesc));
+
+ return 0;
+}
+
+
+/**
+ * read all layers of the next frame to buf[0..n_layers]
+ * returns the number of this frame on success, -1 on error
+ */
+uint32_t tarkin_stream_read_frame (TarkinStream *s, uint8_t **rgba)
+{
+ uint32_t i, j;
+
+ if (s->current_frame_in_buf == 0) {
+ for (i=0; i<s->n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
+
+ for (j=0; j<layer->n_comp; j++) {
+ uint32_t bitstream_len;
+
+ bitstream_len = read_tarkin_bitstream (s->fd, s->bitstream);
+
+ if (bitstream_len == 0)
+ return 0xffffffff;
+
+ wavelet_3d_buf_decode_coeff (layer->waveletbuf[j], s->bitstream,
+ bitstream_len);
+ wavelet_3d_buf_inv_xform (layer->waveletbuf[j], 2, 2);
+ }
+ }
+ }
+
+ for (i=0; i<s->n_layers; i++) {
+ TarkinVideoLayer *layer = &s->layer[i];
+
+ layer->color_inv_xform (layer->waveletbuf, rgba[i],
+ s->current_frame_in_buf);
+ }
+
+ s->current_frame_in_buf++;
+
+ if (s->current_frame_in_buf == s->frames_per_buf)
+ s->current_frame_in_buf=0;
+
+ return (++s->current_frame);
+}
1.4 +38 -12 w3d/tarkin.h
Index: tarkin.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- tarkin.h 2001/06/25 07:56:07 1.3
+++ tarkin.h 2001/06/29 09:19:25 1.4
@@ -1,15 +1,25 @@
#ifndef __TARKIN_H
#define __TARKIN_H
+#include <stdio.h>
#include "wavelet.h"
+
+#define BUG(x...) \
+ do { \
+ printf("BUG in %s (%s: line %i): ", __FUNCTION__, __FILE__, __LINE__); \
+ printf(#x); \
+ printf("\n"); \
+ exit (-1); \
+ } while (0);
+
+
+
typedef enum {
TARKIN_GRAYSCALE,
TARKIN_RGB24, /* tight packed RGB */
TARKIN_RGB32, /* 32bit, no alphachannel */
TARKIN_RGBA, /* dito w/ alphachannel */
- TARKIN_ARGB,
- TARKIN_BGRA
} TarkinColorFormat;
typedef enum {
@@ -23,15 +33,21 @@
uint32_t width;
uint32_t height;
uint32_t frames_per_buf;
- uint32_t bitrate;
+ uint32_t bitrate; /* per color component */
TarkinColorFormat format;
} TarkinVideoLayerDesc;
typedef struct {
TarkinVideoLayerDesc desc;
- Wavelet3DBuf *waveletbuf;
- uint32_t frames_in_readbuf;
+ uint32_t n_comp; /* number of color components */
+ Wavelet3DBuf **waveletbuf;
+ uint32_t current_frame_in_buf;
+
+ uint32_t bitstream_len;
+
+ void (*color_fwd_xform) (uint8_t *rgba, Wavelet3DBuf *yuva [], uint32_t count);
+ void (*color_inv_xform) (Wavelet3DBuf *yuva [], uint8_t *rgba, uint32_t count);
} TarkinVideoLayer;
@@ -39,17 +55,27 @@
int fd;
uint32_t n_layers;
TarkinVideoLayer *layer;
+ uint32_t current_frame;
+ uint32_t current_frame_in_buf;
+ uint32_t frames_per_buf;
+ uint8_t *bitstream;
} TarkinStream;
-
-TarkinStream* tarkin_stream_new (int fd);
-void tarkin_stream_destroy (TarkinStream *s);
-uint32_t tarkin_read_frame (TarkinStream *s, uint8_t *buf);
+extern TarkinStream* tarkin_stream_new (int fd);
+extern void tarkin_stream_destroy (TarkinStream *s);
-uint32_t tarkin_write_set_bitrate (TarkinStream *s, uint32_t bitrate);
-uint32_t tarkin_write_frame (TarkinStream *s, uint8_t *buf);
-uint32_t tarkin_write_frame (TarkinStream *s, uint8_t *buf);
+extern int tarkin_stream_get_layer_desc (TarkinStream *s,
+ uint32_t layer_id,
+ TarkinVideoLayerDesc *desc);
+extern uint32_t tarkin_stream_read_header (TarkinStream *s);
+extern uint32_t tarkin_stream_read_frame (TarkinStream *s, uint8_t **buf);
+
+extern int tarkin_stream_write_layer_descs (TarkinStream *s,
+ uint32_t n_layers,
+ TarkinVideoLayerDesc desc []);
+extern uint32_t tarkin_stream_write_frame (TarkinStream *s, uint8_t **buf);
+extern void tarkin_stream_flush (TarkinStream *s);
#endif
1.4 +5 -33 w3d/wavelet.c
Index: wavelet.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/wavelet.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- wavelet.c 2001/06/25 07:56:07 1.3
+++ wavelet.c 2001/06/29 09:19:25 1.4
@@ -1,4 +1,5 @@
#include <stdlib.h>
+#include <string.h>
#include "wavelet.h"
#include "rle.h"
@@ -184,7 +185,6 @@
-#if 1
static inline
void encode_quadrant (const Wavelet3DBuf* buf,
@@ -292,32 +292,8 @@
decode_quadrant (buf,level,7,w1,h1,f1,s_stream,i_stream);
}
}
-#else
-static inline
-void encode_coefficients (const Wavelet3DBuf* buf,
- ENTROPY_CODER s_stream [],
- ENTROPY_CODER i_stream [])
-{
- uint32_t i;
- for (i=0; i<buf->width*buf->height*buf->frames; i++)
- encode_coeff(s_stream, i_stream, buf->data[i]);
-}
-
-static inline
-void decode_coefficients (Wavelet3DBuf* buf,
- ENTROPY_CODER s_stream [],
- ENTROPY_CODER i_stream [])
-{
- uint32_t i;
-
- for (i=0; i<buf->width*buf->height*buf->frames; i++)
- buf->data[i] = decode_coeff(s_stream, i_stream);
-}
-#endif
-
-
static
uint32_t setup_limittabs (ENTROPY_CODER significand_bitstream [],
ENTROPY_CODER insignificand_bitstream [],
@@ -342,6 +318,8 @@
byte_count += bytes;
}
+byte_count += 2 * 9 * sizeof(uint32_t); /* 2 limittabs, coded binary */
+
return byte_count;
}
@@ -358,13 +336,11 @@
for (i=0; i<9; i++) {
*(uint32_t*) bitstream = significand_limittab[i];
-printf("significand_limittab[%i] == %u\n", i, significand_limittab[i]);
bitstream += 4;
}
for (i=0; i<9; i++) {
*(uint32_t*) bitstream = insignificand_limittab[i];
-printf("insignificand_limittab[%i] == %u\n", i, insignificand_limittab[i]);
bitstream += 4;
}
@@ -381,13 +357,11 @@
for (i=0; i<9; i++) {
significand_limittab[i] = *(uint32_t*) bitstream;
-//printf("> significand_limittab[%i] == %u\n", i, significand_limittab[i]);
bitstream += 4;
}
for (i=0; i<9; i++) {
insignificand_limittab[i] = *(uint32_t*) bitstream;
-//printf("> insignificand_limittab[%i] == %u\n", i, insignificand_limittab[i]);
bitstream += 4;
}
@@ -467,10 +441,8 @@
encode_coefficients (buf, significand_bitstream, insignificand_bitstream);
- byte_count = setup_limittabs (significand_bitstream,
- insignificand_bitstream,
- significand_limittab,
- insignificand_limittab);
+ byte_count = setup_limittabs (significand_bitstream, insignificand_bitstream,
+ significand_limittab, insignificand_limittab);
bitstream = write_limittabs (bitstream,
significand_limittab, insignificand_limittab);
1.6 +143 -9 w3d/yuv.c
Index: yuv.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/yuv.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- yuv.c 2001/06/25 07:56:07 1.5
+++ yuv.c 2001/06/29 09:19:25 1.6
@@ -1,18 +1,31 @@
#include "yuv.h"
+static inline
+uint8_t CLAMP(int16_t x)
+{
+ return ((x > 255) ? 255 : (x < 0) ? 0 : x);
+}
-void rgb24_to_yuv (uint8_t *rgb, int16_t *y, int16_t *u, int16_t *v, uint32_t count, uint32_t rgbstride)
+
+
+
+
+void rgb24_to_yuv (uint8_t *rgb, Wavelet3DBuf *yuv [], uint32_t frame)
{
+ int count = yuv[0]->width * yuv[0]->height;
+ int16_t *y = yuv[0]->data + frame * count;
+ int16_t *u = yuv[1]->data + frame * count;
+ int16_t *v = yuv[2]->data + frame * count;
int i;
#if defined(TARKIN_YUV_EXACT)
- for (i=0; i<count; i++, rgb+=rgbstride) {
+ for (i=0; i<count; i++, rgb+=3) {
y [i] = ((int16_t) 77 * rgb [0] + 150 * rgb [1] + 29 * rgb [2]) / 256;
u [i] = ((int16_t) -44 * rgb [0] - 87 * rgb [1] + 131 * rgb [2]) / 256;
v [i] = ((int16_t) 131 * rgb [0] - 110 * rgb [1] - 21 * rgb [2]) / 256;
}
#else
- for (i=0; i<count; i++, rgb+=rgbstride) {
+ for (i=0; i<count; i++, rgb+=3) {
v [i] = rgb [0] - rgb [1];
u [i] = rgb [2] - rgb [1];
y [i] = rgb [1] + (u [i] + v [i]) / 4;
@@ -21,29 +34,150 @@
}
-static inline
-uint8_t CLAMP(int16_t x)
+void yuv_to_rgb24 (Wavelet3DBuf *yuv [], uint8_t *rgb, uint32_t frame)
{
- return ((x > 255) ? 255 : (x < 0) ? 0 : x);
+ int count = yuv[0]->width * yuv[0]->height;
+ int16_t *y = yuv[0]->data + frame * count;
+ int16_t *u = yuv[1]->data + frame * count;
+ int16_t *v = yuv[2]->data + frame * count;
+ int i;
+
+#if defined(TARKIN_YUV_EXACT)
+ for (i=0; i<count; i++, rgb+=3) {
+ rgb [0] = CLAMP(y [i] + 1.371 * v [i]);
+ rgb [1] = CLAMP(y [i] - 0.698 * v [i] - 0.336 * u [i]);
+ rgb [2] = CLAMP(y [i] + 1.732 * u [i]);
+ }
+#else
+ for (i=0; i<count; i++, rgb+=3) {
+ rgb [1] = CLAMP(y [i] - (u [i] + v [i]) / 4);
+ rgb [2] = CLAMP(u [i] + rgb [1]);
+ rgb [0] = CLAMP(v [i] + rgb [1]);
+ }
+#endif
+}
+
+
+void rgb32_to_yuv (uint8_t *rgb, Wavelet3DBuf *yuv [], uint32_t frame)
+{
+ int count = yuv[0]->width * yuv[0]->height;
+ int16_t *y = yuv[0]->data + frame * count;
+ int16_t *u = yuv[1]->data + frame * count;
+ int16_t *v = yuv[2]->data + frame * count;
+ int i;
+
+#if defined(TARKIN_YUV_EXACT)
+ for (i=0; i<count; i++, rgb+=4) {
+ y [i] = ((int16_t) 77 * rgb [0] + 150 * rgb [1] + 29 * rgb [2]) / 256;
+ u [i] = ((int16_t) -44 * rgb [0] - 87 * rgb [1] + 131 * rgb [2]) / 256;
+ v [i] = ((int16_t) 131 * rgb [0] - 110 * rgb [1] - 21 * rgb [2]) / 256;
+ }
+#else
+ for (i=0; i<count; i++, rgb+=4) {
+ v [i] = rgb [0] - rgb [1];
+ u [i] = rgb [2] - rgb [1];
+ y [i] = rgb [1] + (u [i] + v [i]) / 4;
+ }
+#endif
}
-void yuv_to_rgb24 (int16_t *y, int16_t *u, int16_t *v, uint8_t *rgb, uint32_t count, uint32_t rgbstride)
+void yuv_to_rgb32 (Wavelet3DBuf *yuv [], uint8_t *rgb, uint32_t frame)
{
+ int count = yuv[0]->width * yuv[0]->height;
+ int16_t *y = yuv[0]->data + frame * count;
+ int16_t *u = yuv[1]->data + frame * count;
+ int16_t *v = yuv[2]->data + frame * count;
int i;
#if defined(TARKIN_YUV_EXACT)
- for (i=0; i<count; i++, rgb+=rgbstride) {
+ for (i=0; i<count; i++, rgb+=4) {
rgb [0] = CLAMP(y [i] + 1.371 * v [i]);
rgb [1] = CLAMP(y [i] - 0.698 * v [i] - 0.336 * u [i]);
rgb [2] = CLAMP(y [i] + 1.732 * u [i]);
}
#else
- for (i=0; i<count; i++, rgb+=rgbstride) {
+ for (i=0; i<count; i++, rgb+=4) {
rgb [1] = CLAMP(y [i] - (u [i] + v [i]) / 4);
rgb [2] = CLAMP(u [i] + rgb [1]);
rgb [0] = CLAMP(v [i] + rgb [1]);
}
#endif
}
+
+
+void rgba_to_yuv (uint8_t *rgba, Wavelet3DBuf *yuva [], uint32_t frame)
+{
+ int count = yuva[0]->width * yuva[0]->height;
+ int16_t *y = yuva[0]->data + frame * count;
+ int16_t *u = yuva[1]->data + frame * count;
+ int16_t *v = yuva[2]->data + frame * count;
+ int16_t *a = yuva[3]->data + frame * count;
+ int i;
+
+#if defined(TARKIN_YUV_EXACT)
+ for (i=0; i<count; i++, rgba+=4) {
+ y [i] = ((int16_t) 77 * rgba [0] + 150 * rgba [1] + 29 * rgba [2]) / 256;
+ u [i] = ((int16_t) -44 * rgba [0] - 87 * rgba [1] + 131 * rgba [2]) / 256;
+ v [i] = ((int16_t) 131 * rgba [0] - 110 * rgba [1] - 21 * rgba [2]) / 256;
+ a [i] = rgba [3];
+ }
+#else
+ for (i=0; i<count; i++, rgba+=4) {
+ v [i] = rgba [0] - rgba [1];
+ u [i] = rgba [2] - rgba [1];
+ y [i] = rgba [1] + (u [i] + v [i]) / 4;
+ a [i] = rgba [3];
+ }
+#endif
+}
+
+
+void yuv_to_rgba (Wavelet3DBuf *yuva [], uint8_t *rgba, uint32_t frame)
+{
+ int count = yuva[0]->width * yuva[0]->height;
+ int16_t *y = yuva[0]->data + frame * count;
+ int16_t *u = yuva[1]->data + frame * count;
+ int16_t *v = yuva[2]->data + frame * count;
+ int16_t *a = yuva[3]->data + frame * count;
+ int i;
+
+#if defined(TARKIN_YUV_EXACT)
+ for (i=0; i<count; i++, rgba+=4) {
+ rgba [0] = CLAMP(y [i] + 1.371 * v [i]);
+ rgba [1] = CLAMP(y [i] - 0.698 * v [i] - 0.336 * u [i]);
+ rgba [2] = CLAMP(y [i] + 1.732 * u [i]);
+ rgba [3] = a [i];
+ }
+#else
+ for (i=0; i<count; i++, rgba+=4) {
+ rgba [1] = CLAMP(y [i] - (u [i] + v [i]) / 4);
+ rgba [2] = CLAMP(u [i] + rgba [1]);
+ rgba [0] = CLAMP(v [i] + rgba [1]);
+ rgba [3] = a [i];
+ }
+#endif
+}
+
+void grayscale_to_y (uint8_t *rgba, Wavelet3DBuf *y [], uint32_t frame)
+{
+ int count = y[0]->width * y[0]->height;
+ int16_t *_y = y[0]->data + frame * count;
+ int i;
+
+ for (i=0; i<count; i++)
+ _y [i] = rgba [i];
+}
+
+
+void y_to_grayscale (Wavelet3DBuf *y [], uint8_t *rgba, uint32_t frame)
+{
+ int count = y[0]->width * y[0]->height;
+ int16_t *_y = y[0]->data + frame * count;
+ int i;
+
+ for (i=0; i<count; i++)
+ rgba [i] = CLAMP(_y[i]);
+}
+
1.4 +11 -2 w3d/yuv.h
Index: yuv.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/yuv.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- yuv.h 2001/06/25 07:56:07 1.3
+++ yuv.h 2001/06/29 09:19:25 1.4
@@ -3,10 +3,19 @@
#define __YUV_H
#include <stdint.h>
+#include "wavelet.h"
-extern void rgb24_to_yuv (uint8_t *rgb, int16_t *y, int16_t *u, int16_t *v, uint32_t count, uint32_t rgbstride);
-extern void yuv_to_rgb24 (int16_t *y, int16_t *u, int16_t *v, uint8_t *rgb, uint32_t count, uint32_t rgbstride);
+extern void rgb24_to_yuv (uint8_t *rgb, Wavelet3DBuf *yuv [], uint32_t frame);
+extern void yuv_to_rgb24 (Wavelet3DBuf *yuv [], uint8_t *rgb, uint32_t frame);
+extern void rgb32_to_yuv (uint8_t *rgb, Wavelet3DBuf *yuv [], uint32_t frame);
+extern void yuv_to_rgb32 (Wavelet3DBuf *yuv [], uint8_t *rgb, uint32_t frame);
+
+extern void rgba_to_yuv (uint8_t *rgba, Wavelet3DBuf *yuva [], uint32_t frame);
+extern void yuv_to_rgba (Wavelet3DBuf *yuva [], uint8_t *rgba, uint32_t frame);
+
+extern void grayscale_to_y (uint8_t *rgba, Wavelet3DBuf *y [], uint32_t frame);
+extern void y_to_grayscale (Wavelet3DBuf *y [], uint8_t *rgba, uint32_t frame);
#endif
1.1 w3d/ppm.c
Index: ppm.c
===================================================================
/**
* This code has some serious problems with DOS-style CR/LF linebreaks.
* Simon already contributed better code, but there has been no attempt to
* use them for now.
* If you want do do this, please send me a patch.
*
* - Holger
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int read_ppm_info (char *fname, int *w, int *h)
{
int i;
FILE *file;
file = fopen (fname, "r");
if (!file) {
fprintf(stderr, "Error opening '%s'\n", fname);
return -1;
}
for (i=0; i<3; i++) {
char ln [255];
fgets(ln, 255, file);
if(*ln == '#')
i--;
else {
if (i == 0 && strncmp("P6", ln, 2)) {
fprintf(stderr, "Error: Need PPM file for input\n");
fclose (file);
exit(-1);
}
if (i == 1) {
ln[20] = 0;
sscanf(ln, "%i %i", w, h);
}
}
}
fclose (file);
return 0;
}
int read_ppm (char *fname, uint8_t *buf, int w, int h)
{
int i;
long _w, _h;
FILE *file;
file = fopen (fname, "r");
if (!file)
return -1;
for (i=0; i<3; i++) {
char ln [256];
fgets(ln, 255, file);
if(*ln == '#')
i--;
else {
if (i == 0 && strncmp("P6", ln, 2)) {
fprintf(stderr, "Error: Need PPM file for input\n");
fclose (file);
exit(-1);
}
if (i == 1) {
ln[20] = 0;
sscanf(ln, "%ld %ld", &_w, &_h);
}
}
}
if (w != _w || h != _h) {
fprintf (stderr, "%s: image size inconsistent (w: %i <-> %ld, h: %i <-> %ld) !\n", __FUNCTION__, w, _w, h , _h);
fclose (file);
exit (-1);
}
fread (buf, 3, w*h, file);
fclose (file);
return 0;
}
void write_ppm (char *fname, uint8_t *rgb, int w, int h)
{
FILE *outfile;
outfile = fopen (fname, "w");
if (!outfile) {
printf ("error opening '%s' for writing !!!\n", fname);
exit (-1);
}
fprintf (outfile, "P6\n%d %d\n%d\n", w, h, 255);
fwrite (rgb, 3, w*h, outfile);
fclose (outfile);
}
void write_ppm16 (char *fname, int16_t *rgb, int w, int h)
{
int i;
FILE *outfile;
outfile = fopen (fname, "w");
if (!outfile) {
printf ("error opening '%s' for writing !!!\n", fname);
exit (-1);
}
fprintf (outfile, "P6\n%d %d\n%d\n", w, h, 255);
for (i=0; i<w*h; i++) {
uint8_t c [3] = { rgb[i], rgb[i], rgb[i] };
fwrite (c, 1, 3, outfile);
}
fclose (outfile);
}
1.1 w3d/ppm.h
Index: ppm.h
===================================================================
#ifndef __PPM_H
#define __PPM_H
extern int read_ppm_info (char *fname, int *w, int *h);
extern int read_ppm (char *fname, uint8_t *buf, int w, int h);
extern void write_ppm (char *fname, uint8_t *buf, int w, int h);
extern void write_ppm16 (char *fname, int16_t *buf, int w, int h);
#endif
1.1 w3d/tarkin-io.c
Index: tarkin-io.c
===================================================================
/**
* Not yet working.
*
* Everything here should get oggetized. But for now I don't
* want to struggle with packets, so I simply write everything
* binary.
*/
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include "tarkin-io.h"
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LE32_TO_CPU(x)
#define CPU_TO_LE32(x)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define LE32_TO_CPU(x) x = (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) \
| ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) << 24))
#define CPU_TO_LE32(x) x = (((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) \
| ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) << 24))
#else
#error unknown endianess !!
#endif
int write_tarkin_header (int fd, TarkinStream *s)
{
char signature [6] = "tarkin";
uint32_t n_layers = s->n_layers;
if (write (fd, signature, 6) < 6)
return TARKIN_IO_ERROR;
CPU_TO_LE32(n_layers);
if (write (fd, &n_layers, 4) < 4)
return TARKIN_IO_ERROR;
return TARKIN_OK;
}
int write_layer_descs (int fd, TarkinStream *s)
{
int i;
TarkinVideoLayer layer;
for (i=0; i<s->n_layers; i++) {
memcpy(&layer, &s->layer[i], sizeof(TarkinVideoLayer));
CPU_TO_LE32(layer.width);
CPU_TO_LE32(layer.height);
CPU_TO_LE32(layer.frames_per_buf);
CPU_TO_LE32(layer.bitrate);
CPU_TO_LE32(layer.format);
if (write (fd, &layer, sizeof(TarkinVideoLayer)) < sizeof(TarkinVideoLayer)) {
return TARKIN_IO_ERROR;
}
}
return TARKIN_OK;
}
int write_tarkin_bitstream (int fd, uint8_t *bitstream, uint32_t len)
{
uint32_t bytes = len;
CPU_TO_LE32(bytes);
return (write (fd, &bytes, 4) + write (fd, bitstream, bytes));
}
int read_tarkin_header (int fd, TarkinStream *s)
{
char signature [6];
if (read (fd, signature, 6) < 6)
return TARKIN_IO_ERROR;
if (!strncmp(signature, "tarkin", 6) == 0)
return TARKIN_SIGNATURE_NOT_FOUND;
if (read (fd, &s->n_layers, 4) < 4)
return TARKIN_IO_ERROR;
LE32_TO_CPU(s->n_layers);
return TARKIN_OK;
}
int read_layer_descs (int fd, TarkinStream *s)
{
int i;
s->layer = (TarkinVideoLayer*) calloc (1, s->n_layers * sizeof(TarkinVideoLayer));
for (i=0; i<s->n_layers; i++) {
if (read (fd, &s->layer[i], sizeof(TarkinVideoLayer)) < sizeof(TarkinVideoLayer)) {
tarkin_stream_destroy (s);
return TARKIN_IO_ERROR;
}
LE32_TO_CPU(s->layer[i].width);
LE32_TO_CPU(s->layer[i].height);
LE32_TO_CPU(s->layer[i].frames_per_buf);
LE32_TO_CPU(s->layer[i].bitrate);
LE32_TO_CPU(s->layer[i].format);
}
return TARKIN_OK;
}
int read_tarkin_bitstream (int fd, uint8_t *bitstream)
{
uint32_t len;
if (read (fd, &len, 4) < 4 || len == 0)
return 0;
LE32_TO_CPU(len);
return read (fd, bitstream, len);
}
1.1 w3d/tarkin-io.h
Index: tarkin-io.h
===================================================================
#ifndef __TARKIN_IO_H
#define __TARKIN_IO_H
#include "tarkin.h"
extern int write_tarkin_header (int fd, TarkinStream *s);
extern int write_layer_descs (int fd, TarkinStream *s);
extern int write_tarkin_bitstream (int fd, uint8_t *bitstream, uint32_t len);
extern int read_tarkin_header (int fd, TarkinStream *s);
extern int read_layer_descs (int fd, TarkinStream *s);
extern int read_tarkin_bitstream (int fd, uint8_t *bitstream);
#endif
1.1 w3d/tarkin_dec.c
Index: tarkin_dec.c
===================================================================
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "tarkin.h"
#include "ppm.h"
int main (int argc, char **argv)
{
char *fname = "stream.tarkin";
char ofname [11];
uint32_t frame = 0;
uint8_t *rgb;
int fd;
TarkinStream *tarkin_stream;
uint32_t n_layers;
TarkinVideoLayerDesc layer;
if (argc == 2) {
fname = argv[1];
} else if (argc != 1) {
printf ("\n usage: %s <tarkin_stream>\n\n", argv[0]);
exit (-1);
}
if ((fd = open (fname, O_RDONLY)) < 0) {
printf ("error opening '%s'\n", fname);
exit (-1);
}
tarkin_stream = tarkin_stream_new (fd);
n_layers = tarkin_stream_read_header (tarkin_stream);
if (n_layers == 0) {
printf ("empty tarkin stream !!!\n");
exit (-1);
}
tarkin_stream_get_layer_desc (tarkin_stream, 0, &layer);
rgb = malloc (layer.width * layer.height * 3);
while (tarkin_stream_read_frame (tarkin_stream, &rgb) != 0xffffffff) {
snprintf(ofname, 11, "out%03d.ppm", frame);
printf ("write '%s'\n", ofname);
write_ppm (ofname, rgb, layer.width, layer.height);
frame ++;
};
free (rgb);
tarkin_stream_destroy (tarkin_stream);
close (fd);
return 0;
}
1.1 w3d/tarkin_enc.c
Index: tarkin_enc.c
===================================================================
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "tarkin.h"
#include "ppm.h"
int main (int argc, char **argv)
{
char *fmt = "%i.ppm";
char fname[256];
uint32_t frame = 0;
uint8_t *rgb;
int ylimit, ulimit, vlimit;
int a_moments, s_moments;
int fd;
TarkinStream *tarkin_stream;
TarkinVideoLayerDesc layer [] = { { 0, 0, 1, 5000, TARKIN_RGB24 } };
if (argc == 1) {
ylimit = 1000;
ulimit = 150;
vlimit = 150;
a_moments = 2;
s_moments = 2;
} else if (argc == 7) {
fmt = argv[1];
ylimit = strtol (argv[2], 0, 0);
ulimit = strtol (argv[3], 0, 0);
vlimit = strtol (argv[4], 0, 0);
a_moments = strtol (argv[5], 0, 0);
s_moments = strtol (argv[6], 0, 0);
} else {
printf ("\n"
" usage: %s <input filename format string> <ylimit> <ulimit> <vlimit> <a_m> <s_m>\n"
"\n"
" input ppm filename format: optional, \"%%i.ppm\" by default\n"
" ylimit, ulimit, vlimit: cut Y/U/V bitstream after limit bytes/frame\n"
" a_m, s_m: number of vanishing moments of the\n"
" analysis/synthesis filter, (2,2) by default\n"
"\n", argv[0]);
exit (-1);
}
snprintf (fname, 256, fmt, 0);
if (read_ppm_info (fname, &layer[0].width, &layer[0].height) < 0)
exit (-1);
rgb = malloc (layer[0].width * layer[0].height * 3);
if ((fd = open ("stream.tarkin", O_CREAT | O_RDWR | O_TRUNC, 0644)) < 0) {
printf ("error opening '%s' for writing !\n", "stream.tarkin");
exit (-1);
}
tarkin_stream = tarkin_stream_new (fd);
tarkin_stream_write_layer_descs (tarkin_stream, 1, layer);
do {
snprintf (fname, 256, fmt, frame);
printf ("read '");
printf (fname, frame);
printf ("'");
if (read_ppm (fname, rgb, layer[0].width, layer[0].height) < 0)
{
printf (" failed.\n");
break;
}
printf ("\n");
tarkin_stream_write_frame (tarkin_stream, &rgb);
frame++;
} while (0);
free (rgb);
tarkin_stream_destroy (tarkin_stream);
close (fd);
return 0;
}
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list