mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 11:10:37 +00:00
theora,tarkin: Remove ancient unused code
This commit is contained in:
parent
e76fc42417
commit
d247cf8e6d
29 changed files with 1 additions and 5897 deletions
12
configure.ac
12
configure.ac
|
@ -1443,17 +1443,6 @@ AG_GST_CHECK_FEATURE(SWFDEC, [swfdec plug-in], swfdec, [
|
|||
AC_SUBST(SWFDEC_LIBS)
|
||||
])
|
||||
|
||||
dnl *** theora ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_THEORADEC, true)
|
||||
AG_GST_CHECK_FEATURE(THEORADEC, [ogg theora codec], theoraexpdec, [
|
||||
PKG_CHECK_MODULES(THEORADEC, theoradec, HAVE_THEORADEC="yes", [
|
||||
HAVE_THEORADEC="no"
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
AC_SUBST(THEORADEC_LIBS)
|
||||
AC_SUBST(THEORADEC_CFLAGS)
|
||||
])
|
||||
|
||||
dnl *** XVID ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_XVID, true)
|
||||
AG_GST_CHECK_FEATURE(XVID, [xvid plugins], xvid, [
|
||||
|
@ -1898,7 +1887,6 @@ ext/gsettings/Makefile
|
|||
ext/gsettings/org.freedesktop.gstreamer.default-elements.gschema.xml
|
||||
ext/spc/Makefile
|
||||
ext/swfdec/Makefile
|
||||
ext/theora/Makefile
|
||||
ext/timidity/Makefile
|
||||
ext/vp8/Makefile
|
||||
ext/xvid/Makefile
|
||||
|
|
|
@ -324,18 +324,6 @@ else
|
|||
SWFDEC_DIR=
|
||||
endif
|
||||
|
||||
if USE_THEORADEC
|
||||
#THEORA_DIR = theora
|
||||
else
|
||||
THEORA_DIR =
|
||||
endif
|
||||
|
||||
# if USE_TARKIN
|
||||
# TARKIN_DIR=tarkin
|
||||
# else
|
||||
TARKIN_DIR=
|
||||
# endif
|
||||
|
||||
if USE_VP8
|
||||
VP8_DIR=vp8
|
||||
else
|
||||
|
@ -480,7 +468,6 @@ DIST_SUBDIRS = \
|
|||
spc \
|
||||
gme \
|
||||
swfdec \
|
||||
theora \
|
||||
timidity \
|
||||
vp8 \
|
||||
xvid \
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
plugin_LTLIBRARIES = libgsttarkin.la
|
||||
|
||||
libgsttarkin_la_SOURCES = tarkin.c \
|
||||
mem.c wavelet.c wavelet_xform.c \
|
||||
wavelet_coeff.c yuv.c info.c \
|
||||
gsttarkin.c gsttarkinenc.c gsttarkindec.c
|
||||
|
||||
libgsttarkin_la_CFLAGS = $(GST_CFLAGS) $(VORBIS_CFLAGS) -DTYPE_BITS=10 -DTYPE=int16_t -DRLECODER
|
||||
## AM_PATH_VORBIS also sets VORBISENC_LIBS
|
||||
libgsttarkin_la_LIBADD = $(VORBIS_LIBS) $(VORBISENC_LIBS)
|
||||
libgsttarkin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgsttarkin_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gsttarkinenc.h mem.h tarkin.h yuv.h wavelet.h
|
|
@ -1,8 +0,0 @@
|
|||
This is a video codec based on an integer wavelet in 3 dimensions (x,
|
||||
y, and time/frame). What documentation exists so far is on the
|
||||
vorbis-dev and (now) tarkin-dev mailing lists at xiph.org. Some brief
|
||||
documentation can be found in the w3d/docs directory.
|
||||
|
||||
For sample / test streams, see http://media.xiph.org/
|
||||
(and feel free to submit more streams if you have them).
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
|
||||
|
||||
Most important things:
|
||||
|
||||
- the entropy coder, replace static huffman
|
||||
- clean up the pnsr tools
|
||||
- write docs and do some performance analysis, compare to other codecs
|
||||
- think about a multiresolution multidimensional motion flow detection scheme,
|
||||
Marco posted a good paper comparing different algorithms to do this
|
||||
|
||||
|
||||
Open bugs and stuff required to fix them:
|
||||
|
||||
- wavelet xform bug at short rows, see workaround in wavelet_xform.c
|
||||
- (4,x) and (x,4) wavelet implementations have a bug which causes round-off
|
||||
errors in the two least significand bits
|
||||
|
||||
|
||||
Wavelet-related TODO's:
|
||||
|
||||
- remove unecessairy copying in inverse xform
|
||||
- improve truncation table setup
|
||||
- try other approaches to encode coefficients, jack was talking about VQ
|
||||
and reuse vorbis code
|
||||
- write avitotarkin/quicktimetotarkin/mpegtotarkin/player/recorder
|
||||
(a libsndfile/libaudiofile/libao alike video library would be great !)
|
||||
- profile
|
||||
- add special transform functions for large strides to prevent cache misses
|
||||
- mmx/3dnow/sse/altivec
|
||||
|
||||
|
||||
Other:
|
||||
|
||||
- u and v buffers could get quarter size already at color conversion
|
||||
this would speed up the whole algorithm; perhaps this should get
|
||||
configurable
|
||||
- fast internal 16bitY/U/V->15/16bitRGB for display could make sense
|
||||
- the wavelet codec could be used for still image compression too
|
||||
(we just have to define a file format with all goodies you can imagine;)
|
||||
- to make it perfect someone has to write a good bilevel compressor and
|
||||
mask seperation algorithm
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
|
||||
This is deprecated. Take a look in the w3d/docs directory.
|
||||
|
||||
The command line semantics are changed. You have to call the test program
|
||||
now like this:
|
||||
|
||||
./tarkin_enc ../clips/venuscubes-ppm/AnimSpace00%03d.ppm 5000 4 4
|
||||
./tarkin_dec
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Hi,
|
||||
|
||||
this is a experimental 3d-integer-wavelet-video compression codec. Since the
|
||||
integer wavelet transform is reversible and a reversible rgb-yuv conversion
|
||||
is used (you can understand it as (1,2) integer wavelet transform, too), this
|
||||
codec should be lossless if you transmit the whole bitstream.
|
||||
The Y/U/V-bitstreams are embedded, thus you can simply get lossy compression
|
||||
and shape the used bandwith by cutting bitstreams, when a user defined limit
|
||||
is reached.
|
||||
|
||||
|
||||
Here is how the current code works:
|
||||
|
||||
First we grab a block of N_FRAMES frames (defined in main.c) of .ppm files.
|
||||
Then each pixel becomes transformed into a YUV-alike colorspace. Take a look in
|
||||
yuv.c to see how it is done. Each component is then transformed into frequency
|
||||
space by applying the wavelet transform in x, y and frame direction.
|
||||
The frame-direction transform is our high-order 'motion compensation'.
|
||||
At boundaries we use (1,1)-Wavelets (== HAAR transform), inside the image
|
||||
(2,2)-Wavelets. (4,4)-Wavelets should be easy to add. See wavelet.c for details.
|
||||
|
||||
The resulting coefficients are scanned bitplane by bitplane and
|
||||
runlength-encoded. Runlengths are Huffman-compressed and written into the
|
||||
bitstreams. The bitplanes of higher-frequency scales are offset'ed to ensure a
|
||||
fast transmission of high-energy-low-frequency coefficients. (coder.c)
|
||||
The huffman coder is quite simple and uses a hardcoded table, this can be done
|
||||
much better, but I wanted to get it working fast.
|
||||
|
||||
Decompression works exactly like compression but in reversed direction.
|
||||
|
||||
The test program writes for each frame the grabbed original image, the y/u/v
|
||||
component (may look strange, since u/v can be negative and are not clamped to
|
||||
the [0:255] range), the coefficients (look much more like usual wavelet
|
||||
coefficients if you add 128 to each pixel), the coefficients after they are
|
||||
runlength/huffman encoded and decoded, the y/u/v components when inverse wavelet
|
||||
transform is done and the output image in .ppm format.
|
||||
|
||||
You can call the test program like this:
|
||||
|
||||
$ ./main 20000 5000 5000 ../clips/%i.ppm
|
||||
|
||||
which means: images are grabbed from directory ../clips/0.ppm, ../clips/1.ppm,
|
||||
etc. The Y component bitstream is limited to 20000 Bytes, the U and V bitstreams
|
||||
to 5000 Bytes. If the last argument is omitted, frames are taken from current
|
||||
directory.
|
||||
|
||||
Good Luck,
|
||||
|
||||
- Holger <hwaechtler@users.sourceforge.net>
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
#ifndef __BITCODER_H
|
||||
#define __BITCODER_H
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#if defined(BITCODER)
|
||||
|
||||
#define OUTPUT_BIT(coder,bit) bitcoder_write_bit(coder,bit)
|
||||
#define INPUT_BIT(coder) bitcoder_read_bit(coder)
|
||||
#define OUTPUT_BIT_DIRECT(coder,bit) bitcoder_write_bit(coder,bit)
|
||||
#define INPUT_BIT_DIRECT(coder) bitcoder_read_bit(coder)
|
||||
#define ENTROPY_CODER BitCoderState
|
||||
#define ENTROPY_ENCODER_init(coder,limit) bitcoder_coder_init(coder,limit)
|
||||
#define ENTROPY_ENCODER_DONE(coder) bitcoder_encoder_done(coder)
|
||||
#define ENTROPY_ENCODER_FLUSH(coder) bitcoder_flush(coder)
|
||||
#define ENTROPY_DECODER_INIT(coder,bitstream,limit) \
|
||||
bitcoder_decoder_init(coder,bitstream,limit)
|
||||
#define ENTROPY_DECODER_DONE(coder) /* nothing to do ... */
|
||||
#define ENTROPY_CODER_BITSTREAM(coder) (coder)->bitstream
|
||||
|
||||
#define ENTROPY_CODER_SYMBOL(coder) 1
|
||||
#define ENTROPY_CODER_RUNLENGTH(coder) 0
|
||||
#define ENTROPY_CODER_SKIP(coder,skip)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
int32_t bit_count; /* number of valid bits in byte */
|
||||
uint8_t byte; /* buffer to save bits */
|
||||
uint32_t byte_count; /* number of bytes written */
|
||||
uint8_t *bitstream;
|
||||
uint32_t limit; /* don't write more bytes to bitstream ... */
|
||||
int eos; /* end of stream reached */
|
||||
} BitCoderState;
|
||||
|
||||
|
||||
|
||||
static inline
|
||||
void bitcoder_encoder_init (BitCoderState *s, uint32_t limit)
|
||||
{
|
||||
s->bit_count = 0;
|
||||
s->byte = 0;
|
||||
s->byte_count = 0;
|
||||
s->bitstream = (uint8_t*) MALLOC (limit);
|
||||
s->limit = limit;
|
||||
s->eos = 0;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void bitcoder_encoder_done (BitCoderState *s)
|
||||
{
|
||||
FREE (s->bitstream);
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void bitcoder_decoder_init (BitCoderState *s, uint8_t *bitstream, uint32_t limit)
|
||||
{
|
||||
s->bit_count = -1;
|
||||
s->byte = 0;
|
||||
s->byte_count = 0;
|
||||
s->bitstream = bitstream;
|
||||
s->limit = limit;
|
||||
s->eos = 0;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
uint32_t bitcoder_flush (BitCoderState *s)
|
||||
{
|
||||
if (s->bit_count > 0 && s->byte_count < s->limit)
|
||||
s->bitstream [s->byte_count++] = s->byte << (8 - s->bit_count);
|
||||
|
||||
/*printf ("%s: %i bytes written.\n", __FUNCTION__, s->byte_count); */
|
||||
/*printf ("%s: last bit %i\n", __FUNCTION__, s->bit_count); */
|
||||
return s->byte_count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline
|
||||
void bitcoder_write_bit (BitCoderState *s, int bit)
|
||||
{
|
||||
s->byte <<= 1;
|
||||
s->byte |= bit & 1;
|
||||
|
||||
s->bit_count++;
|
||||
|
||||
if (s->bit_count == 8) {
|
||||
if (s->byte_count < s->limit) {
|
||||
s->bitstream [s->byte_count++] = s->byte;
|
||||
s->bit_count = 0;
|
||||
} else {
|
||||
s->eos = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
int bitcoder_read_bit (BitCoderState *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (s->bit_count <= 0) {
|
||||
if (!s->bitstream) {
|
||||
s->eos = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->byte_count < s->limit) {
|
||||
s->byte = s->bitstream [s->byte_count++];
|
||||
} else {
|
||||
s->eos = 1;
|
||||
s->byte = 0;
|
||||
}
|
||||
|
||||
s->bit_count = 8;
|
||||
}
|
||||
|
||||
ret = s->byte >> 7;
|
||||
s->byte <<= 1;
|
||||
s->bit_count--;
|
||||
|
||||
return ret & 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline
|
||||
void bit_print (TYPE byte)
|
||||
{
|
||||
int bit = 8*sizeof(TYPE);
|
||||
|
||||
do {
|
||||
bit--;
|
||||
printf ((byte & (1 << bit)) ? "1" : "0");
|
||||
} while (bit);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
#ifndef __GOLOMB_H
|
||||
#define __GOLOMB_H
|
||||
|
||||
|
||||
#include "bitcoder.h"
|
||||
|
||||
|
||||
static inline
|
||||
unsigned int required_bits (unsigned int x)
|
||||
{
|
||||
int bits = 31;
|
||||
|
||||
while ((x & (1 << bits)) == 0 && bits)
|
||||
bits--;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void write_number_binary (BitCoderState *b, unsigned int x, int bits, int u)
|
||||
{
|
||||
/*printf ("wrote %i with %i bits (%i+%i)\n", x, u+bits, u, bits); */
|
||||
while (bits) {
|
||||
bits--;
|
||||
bitcoder_write_bit (b, (x >> bits) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
unsigned int read_number_binary (BitCoderState *b, int bits)
|
||||
{
|
||||
unsigned int x = 0;
|
||||
|
||||
while (bits) {
|
||||
bits--;
|
||||
x |= bitcoder_read_bit (b) << bits;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void golomb_write_number (BitCoderState *b, unsigned int x, int bits)
|
||||
{
|
||||
unsigned int q, r;
|
||||
int i = 0;
|
||||
|
||||
assert (x > 0);
|
||||
|
||||
while ((q = (x - 1) >> bits) > 0) {
|
||||
bitcoder_write_bit (b, 1); /* fast temporary adaption, write */
|
||||
bits++; /* unary representation of q */
|
||||
i++;
|
||||
};
|
||||
|
||||
bitcoder_write_bit (b, 0);
|
||||
|
||||
r = x - 1 - (q << bits);
|
||||
|
||||
write_number_binary (b, r, bits, i+1);
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
unsigned int golomb_read_number (BitCoderState *b, int bits)
|
||||
{
|
||||
unsigned int q = 0, r, x;
|
||||
|
||||
while (bitcoder_read_bit (b) != 0) {
|
||||
bits++;
|
||||
}
|
||||
|
||||
r = read_number_binary (b, bits);
|
||||
x = (q << bits) + r + 1;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
uint8_t bits; /* a 5.3 fixed point integer */
|
||||
} GolombAdaptiveCoderState;
|
||||
|
||||
#define GOLOMB_ADAPTIVE_CODER_STATE_INITIALIZER { 8<<3, 0 }
|
||||
|
||||
|
||||
static const int golomb_w_tab [] = { 256, 128, 64 };
|
||||
|
||||
|
||||
|
||||
|
||||
static inline
|
||||
void golombcoder_encode_number (GolombAdaptiveCoderState *g,
|
||||
BitCoderState *b,
|
||||
unsigned int x)
|
||||
{
|
||||
golomb_write_number (b, x, g->bits >> 3);
|
||||
|
||||
g->bits = ((256 - golomb_w_tab[g->count]) * (int) g->bits +
|
||||
golomb_w_tab[g->count] * (required_bits(x)<<3)) / 256;
|
||||
g->count++;
|
||||
|
||||
if (g->count > 2)
|
||||
g->count = 2;
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
unsigned int golombcoder_decode_number (GolombAdaptiveCoderState *g,
|
||||
BitCoderState *b)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
x = golomb_read_number (b, g->bits >> 3);
|
||||
|
||||
g->bits = ((256 - golomb_w_tab[g->count]) * g->bits +
|
||||
golomb_w_tab[g->count] * (required_bits(x)<<3)) / 256;
|
||||
g->count++;
|
||||
|
||||
if (g->count > 2)
|
||||
g->count = 2;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gsttarkinenc.h"
|
||||
#include "gsttarkindec.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
if (!gst_element_register (plugin, "tarkinenc", GST_RANK_NONE,
|
||||
GST_TYPE_TARKINENC))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_element_register (plugin, "tarkindec", GST_RANK_PRIMARY,
|
||||
GST_TYPE_TARKINDEC))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"tarkin",
|
||||
"Tarkin plugin library",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
|
@ -1,334 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gsttarkindec.h"
|
||||
|
||||
static GstPadTemplate *dec_src_template, *dec_sink_template;
|
||||
|
||||
/* TarkinDec signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_BITRATE
|
||||
};
|
||||
|
||||
static void gst_tarkindec_base_init (gpointer g_class);
|
||||
static void gst_tarkindec_class_init (TarkinDecClass * klass);
|
||||
static void gst_tarkindec_init (TarkinDec * arkindec);
|
||||
|
||||
static void gst_tarkindec_chain (GstPad * pad, GstData * _data);
|
||||
static void gst_tarkindec_setup (TarkinDec * tarkindec);
|
||||
static GstStateChangeReturn gst_tarkindec_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
|
||||
static void gst_tarkindec_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_tarkindec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
/*static guint gst_tarkindec_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
tarkindec_get_type (void)
|
||||
{
|
||||
static GType tarkindec_type = 0;
|
||||
|
||||
if (!tarkindec_type) {
|
||||
static const GTypeInfo tarkindec_info = {
|
||||
sizeof (TarkinDecClass),
|
||||
gst_tarkindec_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_tarkindec_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (TarkinDec),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_tarkindec_init,
|
||||
};
|
||||
|
||||
tarkindec_type =
|
||||
g_type_register_static (GST_TYPE_ELEMENT, "TarkinDec", &tarkindec_info,
|
||||
0);
|
||||
}
|
||||
return tarkindec_type;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
tarkin_caps_factory (void)
|
||||
{
|
||||
return gst_caps_new ("tarkin_tarkin", "application/ogg", NULL);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
raw_caps_factory (void)
|
||||
{
|
||||
return
|
||||
GST_CAPS_NEW ("tarkin_raw",
|
||||
"video/x-raw-rgb",
|
||||
"bpp", GST_PROPS_INT (24),
|
||||
"depth", GST_PROPS_INT (24),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"red_mask", GST_PROPS_INT (0xff0000),
|
||||
"green_mask", GST_PROPS_INT (0xff00),
|
||||
"blue_mask", GST_PROPS_INT (0xff),
|
||||
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
|
||||
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
|
||||
"framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT)
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstCaps *raw_caps, *tarkin_caps;
|
||||
|
||||
raw_caps = raw_caps_factory ();
|
||||
tarkin_caps = tarkin_caps_factory ();
|
||||
|
||||
dec_sink_template = gst_pad_template_new ("sink",
|
||||
GST_PAD_SINK, GST_PAD_ALWAYS, tarkin_caps, NULL);
|
||||
dec_src_template = gst_pad_template_new ("src",
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS, raw_caps, NULL);
|
||||
gst_element_class_add_pad_template (element_class, dec_sink_template);
|
||||
gst_element_class_add_pad_template (element_class, dec_src_template);
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "Tarkin video decoder",
|
||||
"Codec/Decoder/Video",
|
||||
"Decodes video in OGG Tarkin format",
|
||||
"Monty <monty@xiph.org>, " "Wim Taymans <wim.taymans@chello.be>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_class_init (TarkinDecClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
|
||||
g_param_spec_int ("bitrate", "bitrate", "bitrate",
|
||||
G_MININT, G_MAXINT, 3000,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->set_property = gst_tarkindec_set_property;
|
||||
gobject_class->get_property = gst_tarkindec_get_property;
|
||||
|
||||
gstelement_class->change_state = gst_tarkindec_change_state;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_init (TarkinDec * tarkindec)
|
||||
{
|
||||
tarkindec->sinkpad = gst_pad_new_from_template (dec_sink_template, "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (tarkindec), tarkindec->sinkpad);
|
||||
gst_pad_set_chain_function (tarkindec->sinkpad, gst_tarkindec_chain);
|
||||
|
||||
tarkindec->srcpad = gst_pad_new_from_template (dec_src_template, "src");
|
||||
gst_element_add_pad (GST_ELEMENT (tarkindec), tarkindec->srcpad);
|
||||
|
||||
tarkindec->bitrate = 3000;
|
||||
tarkindec->setup = FALSE;
|
||||
tarkindec->nheader = 0;
|
||||
|
||||
/* we're chained and we can deal with events */
|
||||
GST_OBJECT_FLAG_SET (tarkindec, GST_ELEMENT_EVENT_AWARE);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_setup (TarkinDec * tarkindec)
|
||||
{
|
||||
tarkindec->tarkin_stream = tarkin_stream_new ();
|
||||
|
||||
ogg_sync_init (&tarkindec->oy);
|
||||
ogg_stream_init (&tarkindec->os, 1);
|
||||
tarkin_info_init (&tarkindec->ti);
|
||||
tarkin_comment_init (&tarkindec->tc);
|
||||
|
||||
tarkindec->setup = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
TarkinDec *tarkindec;
|
||||
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
g_return_if_fail (buf != NULL);
|
||||
|
||||
tarkindec = GST_TARKINDEC (gst_pad_get_parent (pad));
|
||||
|
||||
if (!tarkindec->setup) {
|
||||
GST_ELEMENT_ERROR (tarkindec, CORE, NEGOTATION, (NULL),
|
||||
("decoder not initialized (input is not tarkin?)"));
|
||||
if (GST_IS_BUFFER (buf))
|
||||
gst_buffer_unref (buf);
|
||||
else
|
||||
gst_pad_event_default (pad, GST_EVENT (buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
switch (GST_EVENT_TYPE (buf)) {
|
||||
case GST_EVENT_EOS:
|
||||
default:
|
||||
gst_pad_event_default (pad, GST_EVENT (buf));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
gchar *data;
|
||||
gulong size;
|
||||
gchar *buffer;
|
||||
guchar *rgb;
|
||||
TarkinTime date;
|
||||
TarkinVideoLayerDesc *layer;
|
||||
|
||||
/* data to decode */
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
buffer = ogg_sync_buffer (&tarkindec->oy, size);
|
||||
memcpy (buffer, data, size);
|
||||
ogg_sync_wrote (&tarkindec->oy, size);
|
||||
|
||||
if (ogg_sync_pageout (&tarkindec->oy, &tarkindec->og)) {
|
||||
ogg_stream_pagein (&tarkindec->os, &tarkindec->og);
|
||||
|
||||
while (ogg_stream_packetout (&tarkindec->os, &tarkindec->op)) {
|
||||
if (tarkindec->op.e_o_s)
|
||||
break;
|
||||
if (tarkindec->nheader < 3) { /* 3 first packets to headerin */
|
||||
tarkin_synthesis_headerin (&tarkindec->ti, &tarkindec->tc,
|
||||
&tarkindec->op);
|
||||
|
||||
if (tarkindec->nheader == 2) {
|
||||
tarkin_synthesis_init (tarkindec->tarkin_stream, &tarkindec->ti);
|
||||
}
|
||||
tarkindec->nheader++;
|
||||
} else {
|
||||
tarkin_synthesis_packetin (tarkindec->tarkin_stream, &tarkindec->op);
|
||||
|
||||
while (tarkin_synthesis_frameout (tarkindec->tarkin_stream, &rgb, 0,
|
||||
&date) == 0) {
|
||||
GstBuffer *outbuf;
|
||||
|
||||
layer = &tarkindec->tarkin_stream->layer->desc;
|
||||
|
||||
if (!GST_PAD_CAPS (tarkindec->srcpad)) {
|
||||
if (gst_pad_try_set_caps (tarkindec->srcpad, GST_CAPS_NEW ("tarkin_raw", "video/x-raw-rgb", "bpp", GST_PROPS_INT (24), "depth", GST_PROPS_INT (24), "endianness", GST_PROPS_INT (G_BYTE_ORDER), "red_mask", GST_PROPS_INT (0xff0000), "green_mask", GST_PROPS_INT (0xff00), "blue_mask", GST_PROPS_INT (0xff), "width", GST_PROPS_INT (layer->width), "height", GST_PROPS_INT (layer->height), "framerate", GST_PROPS_FLOAT (0.) /* FIXME!!! */
|
||||
)) <= 0) {
|
||||
GST_ELEMENT_ERROR (tarkindec, CORE, NEGOTATION, (NULL),
|
||||
("could not output format"));
|
||||
gst_buffer_unref (buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = rgb;
|
||||
GST_BUFFER_SIZE (outbuf) = layer->width * layer->height * 3;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (tarkindec->srcpad, GST_DATA (outbuf));
|
||||
|
||||
tarkin_synthesis_freeframe (tarkindec->tarkin_stream, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_tarkindec_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
TarkinDec *tarkindec;
|
||||
|
||||
tarkindec = GST_TARKINDEC (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_tarkindec_setup (tarkindec);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return parent_class->change_state (element, transition);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
TarkinDec *tarkindec;
|
||||
|
||||
g_return_if_fail (GST_IS_TARKINDEC (object));
|
||||
|
||||
tarkindec = GST_TARKINDEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_BITRATE:
|
||||
g_value_set_int (value, tarkindec->bitrate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkindec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
TarkinDec *tarkindec;
|
||||
|
||||
g_return_if_fail (GST_IS_TARKINDEC (object));
|
||||
|
||||
tarkindec = GST_TARKINDEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_BITRATE:
|
||||
tarkindec->bitrate = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TARKINDEC_H__
|
||||
#define __TARKINDEC_H__
|
||||
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "tarkin.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define GST_TYPE_TARKINDEC \
|
||||
(tarkindec_get_type())
|
||||
#define GST_TARKINDEC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TARKINDEC,TarkinDec))
|
||||
#define GST_TARKINDEC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TARKINDEC,TarkinDecClass))
|
||||
#define GST_IS_TARKINDEC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TARKINDEC))
|
||||
#define GST_IS_TARKINDEC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TARKINDEC))
|
||||
|
||||
typedef struct _TarkinDec TarkinDec;
|
||||
typedef struct _TarkinDecClass TarkinDecClass;
|
||||
|
||||
struct _TarkinDec {
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad,*srcpad;
|
||||
|
||||
ogg_sync_state oy;
|
||||
ogg_stream_state os;
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
|
||||
TarkinStream *tarkin_stream;
|
||||
TarkinComment tc;
|
||||
TarkinInfo ti;
|
||||
TarkinVideoLayerDesc layer[1];
|
||||
|
||||
gint frame_num;
|
||||
gint nheader;
|
||||
|
||||
gboolean eos;
|
||||
gint bitrate;
|
||||
gboolean setup;
|
||||
};
|
||||
|
||||
struct _TarkinDecClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType tarkindec_get_type(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __TARKINDEC_H__ */
|
|
@ -1,414 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gsttarkinenc.h"
|
||||
|
||||
static GstPadTemplate *enc_src_template, *enc_sink_template;
|
||||
|
||||
/* TarkinEnc signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_BITRATE,
|
||||
ARG_S_MOMENTS,
|
||||
ARG_A_MOMENTS
|
||||
};
|
||||
|
||||
static void gst_tarkinenc_base_init (gpointer g_class);
|
||||
static void gst_tarkinenc_class_init (TarkinEncClass * klass);
|
||||
static void gst_tarkinenc_init (TarkinEnc * arkinenc);
|
||||
|
||||
static void gst_tarkinenc_chain (GstPad * pad, GstData * _data);
|
||||
static void gst_tarkinenc_setup (TarkinEnc * tarkinenc);
|
||||
|
||||
static void gst_tarkinenc_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_tarkinenc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
/*static guint gst_tarkinenc_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
tarkinenc_get_type (void)
|
||||
{
|
||||
static GType tarkinenc_type = 0;
|
||||
|
||||
if (!tarkinenc_type) {
|
||||
static const GTypeInfo tarkinenc_info = {
|
||||
sizeof (TarkinEncClass),
|
||||
gst_tarkinenc_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_tarkinenc_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (TarkinEnc),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_tarkinenc_init,
|
||||
};
|
||||
|
||||
tarkinenc_type =
|
||||
g_type_register_static (GST_TYPE_ELEMENT, "TarkinEnc", &tarkinenc_info,
|
||||
0);
|
||||
}
|
||||
return tarkinenc_type;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
tarkin_caps_factory (void)
|
||||
{
|
||||
return gst_caps_new ("tarkin_tarkin", "application/ogg", NULL);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
raw_caps_factory (void)
|
||||
{
|
||||
return
|
||||
GST_CAPS_NEW ("tarkin_raw",
|
||||
"video/x-raw-rgb",
|
||||
"bpp", GST_PROPS_INT (24),
|
||||
"depth", GST_PROPS_INT (24),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"red_mask", GST_PROPS_INT (0xff0000),
|
||||
"green_mask", GST_PROPS_INT (0xff00),
|
||||
"blue_mask", GST_PROPS_INT (0xff),
|
||||
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
|
||||
"height", GST_PROPS_INT_RANGE (0, G_MAXINT),
|
||||
"framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT)
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstCaps *raw_caps, *tarkin_caps;
|
||||
|
||||
raw_caps = raw_caps_factory ();
|
||||
tarkin_caps = tarkin_caps_factory ();
|
||||
|
||||
enc_sink_template = gst_pad_template_new ("sink",
|
||||
GST_PAD_SINK, GST_PAD_ALWAYS, raw_caps, NULL);
|
||||
enc_src_template = gst_pad_template_new ("src",
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS, tarkin_caps, NULL);
|
||||
gst_element_class_add_pad_template (element_class, enc_sink_template);
|
||||
gst_element_class_add_pad_template (element_class, enc_src_template);
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "Tarkin video encoder",
|
||||
"Codec/Encoder/Video",
|
||||
"Encodes video in OGG Tarkin format",
|
||||
"Monty <monty@xiph.org>, " "Wim Taymans <wim.taymans@chello.be>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_class_init (TarkinEncClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
|
||||
g_param_spec_int ("bitrate", "bitrate", "bitrate",
|
||||
G_MININT, G_MAXINT, 3000,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_S_MOMENTS,
|
||||
g_param_spec_int ("s-moments", "Synthesis Moments",
|
||||
"Number of vanishing moments for the synthesis filter",
|
||||
1, 4, 2, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_A_MOMENTS,
|
||||
g_param_spec_int ("a-moments", "Analysis Moments",
|
||||
"Number of vanishing moments for the analysis filter",
|
||||
1, 4, 2, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->set_property = gst_tarkinenc_set_property;
|
||||
gobject_class->get_property = gst_tarkinenc_get_property;
|
||||
}
|
||||
|
||||
static GstPadLinkReturn
|
||||
gst_tarkinenc_sinkconnect (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
TarkinEnc *tarkinenc;
|
||||
|
||||
tarkinenc = GST_TARKINENC (gst_pad_get_parent (pad));
|
||||
|
||||
if (!GST_CAPS_IS_FIXED (caps))
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
|
||||
gst_caps_debug (caps, "caps to be set on tarkin sink pad");
|
||||
|
||||
tarkinenc->layer[0].bitstream_len = tarkinenc->bitrate;
|
||||
tarkinenc->layer[0].a_moments = tarkinenc->a_moments;
|
||||
tarkinenc->layer[0].s_moments = tarkinenc->s_moments;
|
||||
gst_caps_get_int (caps, "width", &tarkinenc->layer[0].width);
|
||||
gst_caps_get_int (caps, "height", &tarkinenc->layer[0].height);
|
||||
tarkinenc->layer[0].format = TARKIN_RGB24;
|
||||
tarkinenc->layer[0].frames_per_buf = TARKIN_RGB24;
|
||||
|
||||
gst_tarkinenc_setup (tarkinenc);
|
||||
|
||||
if (tarkinenc->setup)
|
||||
return GST_PAD_LINK_OK;
|
||||
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_init (TarkinEnc * tarkinenc)
|
||||
{
|
||||
tarkinenc->sinkpad = gst_pad_new_from_template (enc_sink_template, "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (tarkinenc), tarkinenc->sinkpad);
|
||||
gst_pad_set_chain_function (tarkinenc->sinkpad, gst_tarkinenc_chain);
|
||||
gst_pad_set_link_function (tarkinenc->sinkpad, gst_tarkinenc_sinkconnect);
|
||||
|
||||
tarkinenc->srcpad = gst_pad_new_from_template (enc_src_template, "src");
|
||||
gst_element_add_pad (GST_ELEMENT (tarkinenc), tarkinenc->srcpad);
|
||||
|
||||
tarkinenc->bitrate = 3000;
|
||||
tarkinenc->s_moments = 2;
|
||||
tarkinenc->a_moments = 2;
|
||||
tarkinenc->setup = FALSE;
|
||||
}
|
||||
|
||||
TarkinError
|
||||
free_frame (void *s, void *ptr)
|
||||
{
|
||||
return (TARKIN_OK);
|
||||
}
|
||||
|
||||
TarkinError
|
||||
packet_out (void *stream, ogg_packet * op)
|
||||
{
|
||||
ogg_page og;
|
||||
TarkinStream *s = stream;
|
||||
TarkinEnc *te = s->user_ptr;
|
||||
GstBuffer *outbuf;
|
||||
|
||||
ogg_stream_packetin (&te->os, op);
|
||||
|
||||
if (op->e_o_s) {
|
||||
ogg_stream_flush (&te->os, &og);
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = og.header;
|
||||
GST_BUFFER_SIZE (outbuf) = og.header_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (te->srcpad, GST_DATA (outbuf));
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = og.body;
|
||||
GST_BUFFER_SIZE (outbuf) = og.body_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (te->srcpad, GST_DATA (outbuf));
|
||||
} else {
|
||||
while (ogg_stream_pageout (&te->os, &og)) {
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = og.header;
|
||||
GST_BUFFER_SIZE (outbuf) = og.header_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (te->srcpad, GST_DATA (outbuf));
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = og.body;
|
||||
GST_BUFFER_SIZE (outbuf) = og.body_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (te->srcpad, GST_DATA (outbuf));
|
||||
}
|
||||
}
|
||||
return (TARKIN_OK);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_tarkinenc_setup (TarkinEnc * tarkinenc)
|
||||
{
|
||||
gint i;
|
||||
GstBuffer *outbuf;
|
||||
|
||||
ogg_stream_init (&tarkinenc->os, 1);
|
||||
tarkin_info_init (&tarkinenc->ti);
|
||||
|
||||
tarkinenc->ti.inter.numerator = 1;
|
||||
tarkinenc->ti.inter.denominator = 1;
|
||||
|
||||
tarkin_comment_init (&tarkinenc->tc);
|
||||
tarkin_comment_add_tag (&tarkinenc->tc, "TITLE", "GStreamer produced file");
|
||||
tarkin_comment_add_tag (&tarkinenc->tc, "ARTIST", "C coders ;)");
|
||||
|
||||
tarkinenc->tarkin_stream = tarkin_stream_new ();
|
||||
tarkin_analysis_init (tarkinenc->tarkin_stream,
|
||||
&tarkinenc->ti, free_frame, packet_out, (void *) tarkinenc);
|
||||
tarkin_analysis_add_layer (tarkinenc->tarkin_stream, &tarkinenc->layer[0]);
|
||||
|
||||
tarkin_analysis_headerout (tarkinenc->tarkin_stream, &tarkinenc->tc,
|
||||
tarkinenc->op, &tarkinenc->op[1], &tarkinenc->op[2]);
|
||||
for (i = 0; i < 3; i++) {
|
||||
ogg_stream_packetin (&tarkinenc->os, &tarkinenc->op[i]);
|
||||
}
|
||||
|
||||
ogg_stream_flush (&tarkinenc->os, &tarkinenc->og);
|
||||
|
||||
tarkinenc->frame_num = 0;
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = tarkinenc->og.header;
|
||||
GST_BUFFER_SIZE (outbuf) = tarkinenc->og.header_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (tarkinenc->srcpad, GST_DATA (outbuf));
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = tarkinenc->og.body;
|
||||
GST_BUFFER_SIZE (outbuf) = tarkinenc->og.body_len;
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
|
||||
gst_pad_push (tarkinenc->srcpad, GST_DATA (outbuf));
|
||||
|
||||
tarkinenc->setup = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstBuffer *buf = GST_BUFFER (_data);
|
||||
TarkinEnc *tarkinenc;
|
||||
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
g_return_if_fail (buf != NULL);
|
||||
|
||||
tarkinenc = GST_TARKINENC (gst_pad_get_parent (pad));
|
||||
|
||||
if (!tarkinenc->setup) {
|
||||
GST_ELEMENT_ERROR (tarkinenc, CORE, NEGOTIATION, (NULL),
|
||||
("encoder not initialized (input is not tarkin?)"));
|
||||
if (GST_IS_BUFFER (buf))
|
||||
gst_buffer_unref (buf);
|
||||
else
|
||||
gst_pad_event_default (pad, GST_EVENT (buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (GST_IS_EVENT (buf)) {
|
||||
switch (GST_EVENT_TYPE (buf)) {
|
||||
case GST_EVENT_EOS:
|
||||
tarkin_analysis_framein (tarkinenc->tarkin_stream, NULL, 0, NULL); /* EOS */
|
||||
tarkin_comment_clear (&tarkinenc->tc);
|
||||
tarkin_stream_destroy (tarkinenc->tarkin_stream);
|
||||
default:
|
||||
gst_pad_event_default (pad, GST_EVENT (buf));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
gchar *data;
|
||||
gulong size;
|
||||
TarkinTime date;
|
||||
|
||||
/* data to encode */
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
date.numerator = tarkinenc->frame_num;
|
||||
date.denominator = 1;
|
||||
tarkin_analysis_framein (tarkinenc->tarkin_stream, data, 0, &date);
|
||||
tarkinenc->frame_num++;
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
TarkinEnc *tarkinenc;
|
||||
|
||||
g_return_if_fail (GST_IS_TARKINENC (object));
|
||||
|
||||
tarkinenc = GST_TARKINENC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_BITRATE:
|
||||
g_value_set_int (value, tarkinenc->bitrate);
|
||||
break;
|
||||
case ARG_S_MOMENTS:
|
||||
g_value_set_int (value, tarkinenc->s_moments);
|
||||
break;
|
||||
case ARG_A_MOMENTS:
|
||||
g_value_set_int (value, tarkinenc->a_moments);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tarkinenc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
TarkinEnc *tarkinenc;
|
||||
|
||||
g_return_if_fail (GST_IS_TARKINENC (object));
|
||||
|
||||
tarkinenc = GST_TARKINENC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_BITRATE:
|
||||
tarkinenc->bitrate = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_S_MOMENTS:
|
||||
{
|
||||
gint s_moments;
|
||||
|
||||
s_moments = g_value_get_int (value);
|
||||
if (s_moments != 1 || s_moments != 2 || s_moments != 4) {
|
||||
g_warning ("tarkinenc: s_moments must be 1, 2 or 4");
|
||||
} else {
|
||||
tarkinenc->s_moments = s_moments;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARG_A_MOMENTS:
|
||||
{
|
||||
gint a_moments;
|
||||
|
||||
a_moments = g_value_get_int (value);
|
||||
if (a_moments != 1 || a_moments != 2 || a_moments != 4) {
|
||||
g_warning ("tarkinenc: a_moments must be 1, 2 or 4");
|
||||
} else {
|
||||
tarkinenc->a_moments = a_moments;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TARKINENC_H__
|
||||
#define __TARKINENC_H__
|
||||
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "tarkin.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define GST_TYPE_TARKINENC \
|
||||
(tarkinenc_get_type())
|
||||
#define GST_TARKINENC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TARKINENC,TarkinEnc))
|
||||
#define GST_TARKINENC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TARKINENC,TarkinEncClass))
|
||||
#define GST_IS_TARKINENC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TARKINENC))
|
||||
#define GST_IS_TARKINENC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TARKINENC))
|
||||
|
||||
typedef struct _TarkinEnc TarkinEnc;
|
||||
typedef struct _TarkinEncClass TarkinEncClass;
|
||||
|
||||
struct _TarkinEnc {
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad,*srcpad;
|
||||
|
||||
ogg_stream_state os; /* take physical pages, weld into a logical
|
||||
stream of packets */
|
||||
ogg_page og; /* one Ogg bitstream page. Tarkin packets are inside */
|
||||
ogg_packet op[3]; /* one raw packet of data for decode */
|
||||
|
||||
TarkinStream *tarkin_stream;
|
||||
TarkinComment tc;
|
||||
TarkinInfo ti;
|
||||
TarkinVideoLayerDesc layer[1];
|
||||
|
||||
gint frame_num;
|
||||
|
||||
gboolean eos;
|
||||
gint bitrate;
|
||||
gint s_moments;
|
||||
gint a_moments;
|
||||
gboolean setup;
|
||||
};
|
||||
|
||||
struct _TarkinEncClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType tarkinenc_get_type(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __TARKINENC_H__ */
|
|
@ -1,621 +0,0 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: maintain the info structure, info <-> header packets
|
||||
last mod: $Id$
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* general handling of the header and the TarkinInfo structure (and
|
||||
substructures) */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "tarkin.h"
|
||||
#include "yuv.h"
|
||||
#include "mem.h"
|
||||
|
||||
/* helpers */
|
||||
static void
|
||||
_v_writestring (oggpack_buffer * o, char *s, int bytes)
|
||||
{
|
||||
while (bytes--) {
|
||||
oggpack_write (o, *s++, 8);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_v_readstring (oggpack_buffer * o, char *buf, int bytes)
|
||||
{
|
||||
while (bytes--) {
|
||||
*buf++ = oggpack_read (o, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tarkin_comment_init (TarkinComment * vc)
|
||||
{
|
||||
memset (vc, 0, sizeof (*vc));
|
||||
}
|
||||
|
||||
void
|
||||
tarkin_comment_add (TarkinComment * vc, char *comment)
|
||||
{
|
||||
vc->user_comments = REALLOC (vc->user_comments,
|
||||
(vc->comments + 2) * sizeof (*vc->user_comments));
|
||||
vc->comment_lengths = REALLOC (vc->comment_lengths,
|
||||
(vc->comments + 2) * sizeof (*vc->comment_lengths));
|
||||
vc->comment_lengths[vc->comments] = strlen (comment);
|
||||
vc->user_comments[vc->comments] =
|
||||
MALLOC (vc->comment_lengths[vc->comments] + 1);
|
||||
strcpy (vc->user_comments[vc->comments], comment);
|
||||
vc->comments++;
|
||||
vc->user_comments[vc->comments] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
tarkin_comment_add_tag (TarkinComment * vc, char *tag, char *contents)
|
||||
{
|
||||
char *comment = alloca (strlen (tag) + strlen (contents) + 2); /* +2 for = and \0 */
|
||||
|
||||
strcpy (comment, tag);
|
||||
strcat (comment, "=");
|
||||
strcat (comment, contents);
|
||||
tarkin_comment_add (vc, comment);
|
||||
}
|
||||
|
||||
/* This is more or less the same as strncasecmp - but that doesn't exist
|
||||
* everywhere, and this is a fairly trivial function, so we include it */
|
||||
static int
|
||||
tagcompare (const char *s1, const char *s2, int n)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (c < n) {
|
||||
if (toupper (s1[c]) != toupper (s2[c]))
|
||||
return !0;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
tarkin_comment_query (TarkinComment * vc, char *tag, int count)
|
||||
{
|
||||
long i;
|
||||
int found = 0;
|
||||
int taglen = strlen (tag) + 1; /* +1 for the = we append */
|
||||
char *fulltag = alloca (taglen + 1);
|
||||
|
||||
strcpy (fulltag, tag);
|
||||
strcat (fulltag, "=");
|
||||
|
||||
for (i = 0; i < vc->comments; i++) {
|
||||
if (!tagcompare (vc->user_comments[i], fulltag, taglen)) {
|
||||
if (count == found)
|
||||
/* We return a pointer to the data, not a copy */
|
||||
return vc->user_comments[i] + taglen;
|
||||
else
|
||||
found++;
|
||||
}
|
||||
}
|
||||
return NULL; /* didn't find anything */
|
||||
}
|
||||
|
||||
int
|
||||
tarkin_comment_query_count (TarkinComment * vc, char *tag)
|
||||
{
|
||||
int i, count = 0;
|
||||
int taglen = strlen (tag) + 1; /* +1 for the = we append */
|
||||
char *fulltag = alloca (taglen + 1);
|
||||
|
||||
strcpy (fulltag, tag);
|
||||
strcat (fulltag, "=");
|
||||
|
||||
for (i = 0; i < vc->comments; i++) {
|
||||
if (!tagcompare (vc->user_comments[i], fulltag, taglen))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
tarkin_comment_clear (TarkinComment * vc)
|
||||
{
|
||||
if (vc) {
|
||||
long i;
|
||||
|
||||
for (i = 0; i < vc->comments; i++)
|
||||
if (vc->user_comments[i])
|
||||
FREE (vc->user_comments[i]);
|
||||
if (vc->user_comments)
|
||||
FREE (vc->user_comments);
|
||||
if (vc->comment_lengths)
|
||||
FREE (vc->comment_lengths);
|
||||
if (vc->vendor)
|
||||
FREE (vc->vendor);
|
||||
}
|
||||
memset (vc, 0, sizeof (*vc));
|
||||
}
|
||||
|
||||
/* used by synthesis, which has a full, alloced vi */
|
||||
void
|
||||
tarkin_info_init (TarkinInfo * vi)
|
||||
{
|
||||
memset (vi, 0, sizeof (*vi));
|
||||
}
|
||||
|
||||
void
|
||||
tarkin_info_clear (TarkinInfo * vi)
|
||||
{
|
||||
memset (vi, 0, sizeof (*vi));
|
||||
}
|
||||
|
||||
/* Header packing/unpacking ********************************************/
|
||||
|
||||
static int
|
||||
_tarkin_unpack_info (TarkinInfo * vi, oggpack_buffer * opb)
|
||||
{
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Decoding Info: ");
|
||||
#endif
|
||||
vi->version = oggpack_read (opb, 32);
|
||||
if (vi->version != 0)
|
||||
return (-TARKIN_VERSION);
|
||||
|
||||
vi->n_layers = oggpack_read (opb, 8);
|
||||
vi->inter.numerator = oggpack_read (opb, 32);
|
||||
vi->inter.denominator = oggpack_read (opb, 32);
|
||||
|
||||
vi->bitrate_upper = oggpack_read (opb, 32);
|
||||
vi->bitrate_nominal = oggpack_read (opb, 32);
|
||||
vi->bitrate_lower = oggpack_read (opb, 32);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf (" n_layers %d, interleave: %d/%d, ",
|
||||
vi->n_layers, vi->inter.numerator, vi->inter.denominator);
|
||||
#endif
|
||||
|
||||
if (vi->inter.numerator < 1)
|
||||
goto err_out;
|
||||
if (vi->inter.denominator < 1)
|
||||
goto err_out;
|
||||
if (vi->n_layers < 1)
|
||||
goto err_out;
|
||||
|
||||
if (oggpack_read (opb, 1) != 1)
|
||||
goto err_out; /* EOP check */
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("Success\n");
|
||||
#endif
|
||||
return (0);
|
||||
err_out:
|
||||
#ifdef DBG_OGG
|
||||
printf ("Failed\n");
|
||||
#endif
|
||||
tarkin_info_clear (vi);
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
static int
|
||||
_tarkin_unpack_comment (TarkinComment * vc, oggpack_buffer * opb)
|
||||
{
|
||||
int i;
|
||||
int vendorlen = oggpack_read (opb, 32);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Decoding comment: ");
|
||||
#endif
|
||||
if (vendorlen < 0)
|
||||
goto err_out;
|
||||
vc->vendor = _ogg_calloc (vendorlen + 1, 1);
|
||||
_v_readstring (opb, vc->vendor, vendorlen);
|
||||
vc->comments = oggpack_read (opb, 32);
|
||||
if (vc->comments < 0)
|
||||
goto err_out;
|
||||
vc->user_comments =
|
||||
_ogg_calloc (vc->comments + 1, sizeof (*vc->user_comments));
|
||||
vc->comment_lengths =
|
||||
_ogg_calloc (vc->comments + 1, sizeof (*vc->comment_lengths));
|
||||
|
||||
for (i = 0; i < vc->comments; i++) {
|
||||
int len = oggpack_read (opb, 32);
|
||||
|
||||
if (len < 0)
|
||||
goto err_out;
|
||||
vc->comment_lengths[i] = len;
|
||||
vc->user_comments[i] = _ogg_calloc (len + 1, 1);
|
||||
_v_readstring (opb, vc->user_comments[i], len);
|
||||
}
|
||||
if (oggpack_read (opb, 1) != 1)
|
||||
goto err_out; /* EOP check */
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("Success, read %d comments\n", vc->comments);
|
||||
#endif
|
||||
return (0);
|
||||
err_out:
|
||||
#ifdef DBG_OGG
|
||||
printf ("Failed\n");
|
||||
#endif
|
||||
tarkin_comment_clear (vc);
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
/* the real encoding details are here, currently TarkinVideoLayerDesc. */
|
||||
static int
|
||||
_tarkin_unpack_layer_desc (TarkinInfo * vi, oggpack_buffer * opb)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
vi->layer = CALLOC (vi->n_layers, (sizeof (*vi->layer)));
|
||||
memset (vi->layer, 0, vi->n_layers * sizeof (*vi->layer));
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("ogg: Decoding layers description: ");
|
||||
#endif
|
||||
for (i = 0; i < vi->n_layers; i++) {
|
||||
TarkinVideoLayer *layer = vi->layer + i;
|
||||
|
||||
layer->desc.width = oggpack_read (opb, 32);
|
||||
layer->desc.height = oggpack_read (opb, 32);
|
||||
layer->desc.a_moments = oggpack_read (opb, 32);
|
||||
layer->desc.s_moments = oggpack_read (opb, 32);
|
||||
layer->desc.frames_per_buf = oggpack_read (opb, 32);
|
||||
layer->desc.bitstream_len = oggpack_read (opb, 32);
|
||||
layer->desc.format = oggpack_read (opb, 32);
|
||||
|
||||
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:
|
||||
return -TARKIN_INVALID_COLOR_FORMAT;
|
||||
};
|
||||
|
||||
layer->waveletbuf = (Wavelet3DBuf **) CALLOC (layer->n_comp,
|
||||
sizeof (Wavelet3DBuf *));
|
||||
|
||||
layer->packet = MALLOC (layer->n_comp * sizeof (*layer->packet));
|
||||
memset (layer->packet, 0, layer->n_comp * sizeof (*layer->packet));
|
||||
|
||||
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);
|
||||
layer->packet[j].data = MALLOC (layer->desc.bitstream_len);
|
||||
layer->packet[j].storage = layer->desc.bitstream_len;
|
||||
}
|
||||
|
||||
vi->max_bitstream_len += layer->desc.bitstream_len + 2 * 10 * sizeof (uint32_t) * layer->n_comp; /* truncation tables */
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf
|
||||
("\n layer%d: size %dx%dx%d, format %d, a_m %d, s_m %d, %d fpb\n",
|
||||
i, layer->desc.width, layer->desc.height, layer->n_comp,
|
||||
layer->desc.format, layer->desc.a_moments, layer->desc.s_moments,
|
||||
layer->desc.frames_per_buf);
|
||||
#endif
|
||||
} /* for each layer */
|
||||
|
||||
if (oggpack_read (opb, 1) != 1)
|
||||
goto err_out; /* EOP check */
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("Success\n");
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
err_out:
|
||||
#ifdef DBG_OGG
|
||||
printf ("Failed\n");
|
||||
#endif
|
||||
tarkin_info_clear (vi);
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
/* The Tarkin header is in three packets; the initial small packet in
|
||||
the first page that identifies basic parameters, a second packet
|
||||
with bitstream comments and a third packet that holds the
|
||||
layer description structures. */
|
||||
|
||||
TarkinError
|
||||
tarkin_synthesis_headerin (TarkinInfo * vi, TarkinComment * vc, ogg_packet * op)
|
||||
{
|
||||
oggpack_buffer opb;
|
||||
|
||||
if (op) {
|
||||
oggpack_readinit (&opb, op->packet, op->bytes);
|
||||
|
||||
/* Which of the three types of header is this? */
|
||||
/* Also verify header-ness, tarkin */
|
||||
{
|
||||
char buffer[6];
|
||||
int packtype = oggpack_read (&opb, 8);
|
||||
|
||||
memset (buffer, 0, 6);
|
||||
_v_readstring (&opb, buffer, 6);
|
||||
if (memcmp (buffer, "tarkin", 6)) {
|
||||
/* not a tarkin header */
|
||||
return (-TARKIN_NOT_TARKIN);
|
||||
}
|
||||
switch (packtype) {
|
||||
case 0x01: /* least significant *bit* is read first */
|
||||
if (!op->b_o_s) {
|
||||
/* Not the initial packet */
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
if (vi->inter.numerator != 0) {
|
||||
/* previously initialized info header */
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
return (_tarkin_unpack_info (vi, &opb));
|
||||
|
||||
case 0x03: /* least significant *bit* is read first */
|
||||
if (vi->inter.denominator == 0) {
|
||||
/* um... we didn't get the initial header */
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
return (_tarkin_unpack_comment (vc, &opb));
|
||||
|
||||
case 0x05: /* least significant *bit* is read first */
|
||||
if (vi->inter.numerator == 0 || vc->vendor == NULL) {
|
||||
/* um... we didn;t get the initial header or comments yet */
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
return (_tarkin_unpack_layer_desc (vi, &opb));
|
||||
|
||||
default:
|
||||
/* Not a valid tarkin header type */
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (-TARKIN_BAD_HEADER);
|
||||
}
|
||||
|
||||
/* pack side **********************************************************/
|
||||
|
||||
static int
|
||||
_tarkin_pack_info (oggpack_buffer * opb, TarkinInfo * vi)
|
||||
{
|
||||
|
||||
/* preamble */
|
||||
oggpack_write (opb, 0x01, 8);
|
||||
_v_writestring (opb, "tarkin", 6);
|
||||
|
||||
/* basic information about the stream */
|
||||
oggpack_write (opb, 0x00, 32);
|
||||
oggpack_write (opb, vi->n_layers, 8);
|
||||
oggpack_write (opb, vi->inter.numerator, 32);
|
||||
oggpack_write (opb, vi->inter.denominator, 32);
|
||||
|
||||
oggpack_write (opb, vi->bitrate_upper, 32);
|
||||
oggpack_write (opb, vi->bitrate_nominal, 32);
|
||||
oggpack_write (opb, vi->bitrate_lower, 32);
|
||||
|
||||
oggpack_write (opb, 1, 1);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Putting out info, inter %d/%d, n_layers %d\n",
|
||||
vi->inter.numerator, vi->inter.denominator, vi->n_layers);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
_tarkin_pack_comment (oggpack_buffer * opb, TarkinComment * vc)
|
||||
{
|
||||
char temp[] = "libTarkin debugging edition 20011104";
|
||||
int bytes = strlen (temp);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write (opb, 0x03, 8);
|
||||
_v_writestring (opb, "tarkin", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write (opb, bytes, 32);
|
||||
_v_writestring (opb, temp, bytes);
|
||||
|
||||
/* comments */
|
||||
|
||||
oggpack_write (opb, vc->comments, 32);
|
||||
if (vc->comments) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vc->comments; i++) {
|
||||
if (vc->user_comments[i]) {
|
||||
oggpack_write (opb, vc->comment_lengths[i], 32);
|
||||
_v_writestring (opb, vc->user_comments[i], vc->comment_lengths[i]);
|
||||
} else {
|
||||
oggpack_write (opb, 0, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write (opb, 1, 1);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Putting out %d comments\n", vc->comments);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
_tarkin_pack_layer_desc (oggpack_buffer * opb, TarkinInfo * vi)
|
||||
{
|
||||
int i;
|
||||
TarkinVideoLayer *layer;
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Putting out layers description:\n");
|
||||
#endif
|
||||
|
||||
oggpack_write (opb, 0x05, 8);
|
||||
_v_writestring (opb, "tarkin", 6);
|
||||
|
||||
for (i = 0; i < vi->n_layers; i++) {
|
||||
layer = vi->layer + i;
|
||||
oggpack_write (opb, layer->desc.width, 32);
|
||||
oggpack_write (opb, layer->desc.height, 32);
|
||||
oggpack_write (opb, layer->desc.a_moments, 32);
|
||||
oggpack_write (opb, layer->desc.s_moments, 32);
|
||||
oggpack_write (opb, layer->desc.frames_per_buf, 32);
|
||||
oggpack_write (opb, layer->desc.bitstream_len, 32);
|
||||
oggpack_write (opb, layer->desc.format, 32);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf (" res. %dx%d, format %d, a_m %d, s_m %d, fpb %d\n",
|
||||
layer->desc.width, layer->desc.height, layer->desc.format,
|
||||
layer->desc.a_moments, layer->desc.s_moments,
|
||||
layer->desc.frames_per_buf);
|
||||
#endif
|
||||
|
||||
}
|
||||
oggpack_write (opb, 1, 1);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf (" wrote %ld bytes.\n", oggpack_bytes (opb));
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
tarkin_comment_header_out (TarkinComment * vc, ogg_packet * op)
|
||||
{
|
||||
|
||||
oggpack_buffer opb;
|
||||
|
||||
oggpack_writeinit (&opb);
|
||||
if (_tarkin_pack_comment (&opb, vc))
|
||||
return -TARKIN_NOT_IMPLEMENTED;
|
||||
|
||||
op->packet = MALLOC (oggpack_bytes (&opb));
|
||||
memcpy (op->packet, opb.buffer, oggpack_bytes (&opb));
|
||||
|
||||
op->bytes = oggpack_bytes (&opb);
|
||||
op->b_o_s = 0;
|
||||
op->e_o_s = 0;
|
||||
op->granulepos = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TarkinError
|
||||
tarkin_analysis_headerout (TarkinStream * v,
|
||||
TarkinComment * vc,
|
||||
ogg_packet * op, ogg_packet * op_comm, ogg_packet * op_code)
|
||||
{
|
||||
int ret = -TARKIN_NOT_IMPLEMENTED;
|
||||
TarkinInfo *vi;
|
||||
oggpack_buffer opb;
|
||||
tarkin_header_store *b = &v->headers;
|
||||
|
||||
vi = v->ti;
|
||||
|
||||
/* first header packet ********************************************* */
|
||||
|
||||
oggpack_writeinit (&opb);
|
||||
if (_tarkin_pack_info (&opb, vi))
|
||||
goto err_out;
|
||||
|
||||
/* build the packet */
|
||||
if (b->header)
|
||||
FREE (b->header);
|
||||
b->header = MALLOC (oggpack_bytes (&opb));
|
||||
memcpy (b->header, opb.buffer, oggpack_bytes (&opb));
|
||||
op->packet = b->header;
|
||||
op->bytes = oggpack_bytes (&opb);
|
||||
op->b_o_s = 1;
|
||||
op->e_o_s = 0;
|
||||
op->granulepos = 0;
|
||||
|
||||
/* second header packet (comments) ********************************* */
|
||||
|
||||
oggpack_reset (&opb);
|
||||
if (_tarkin_pack_comment (&opb, vc))
|
||||
goto err_out;
|
||||
|
||||
if (b->header1)
|
||||
FREE (b->header1);
|
||||
b->header1 = MALLOC (oggpack_bytes (&opb));
|
||||
memcpy (b->header1, opb.buffer, oggpack_bytes (&opb));
|
||||
op_comm->packet = b->header1;
|
||||
op_comm->bytes = oggpack_bytes (&opb);
|
||||
op_comm->b_o_s = 0;
|
||||
op_comm->e_o_s = 0;
|
||||
op_comm->granulepos = 0;
|
||||
|
||||
/* third header packet (modes/codebooks) *************************** */
|
||||
|
||||
oggpack_reset (&opb);
|
||||
if (_tarkin_pack_layer_desc (&opb, vi))
|
||||
goto err_out;
|
||||
|
||||
if (b->header2)
|
||||
FREE (b->header2);
|
||||
b->header2 = MALLOC (oggpack_bytes (&opb));
|
||||
memcpy (b->header2, opb.buffer, oggpack_bytes (&opb));
|
||||
op_code->packet = b->header2;
|
||||
op_code->bytes = oggpack_bytes (&opb);
|
||||
op_code->b_o_s = 0;
|
||||
op_code->e_o_s = 0;
|
||||
op_code->granulepos = 0;
|
||||
|
||||
oggpack_writeclear (&opb);
|
||||
return (0);
|
||||
err_out:
|
||||
oggpack_writeclear (&opb);
|
||||
memset (op, 0, sizeof (*op));
|
||||
memset (op_comm, 0, sizeof (*op_comm));
|
||||
memset (op_code, 0, sizeof (*op_code));
|
||||
|
||||
if (b->header)
|
||||
FREE (b->header);
|
||||
if (b->header1)
|
||||
FREE (b->header1);
|
||||
if (b->header2)
|
||||
FREE (b->header2);
|
||||
b->header = NULL;
|
||||
b->header1 = NULL;
|
||||
b->header2 = NULL;
|
||||
return (ret);
|
||||
}
|
153
ext/tarkin/mem.c
153
ext/tarkin/mem.c
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* Debugging implementation of MALLOC and friends
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#if defined(DBG_MEMLEAKS)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *mem;
|
||||
char *allocated_in_func;
|
||||
char *allocated_in_file;
|
||||
unsigned int allocated_in_line;
|
||||
}
|
||||
MemDesc;
|
||||
|
||||
|
||||
static int initialized = 0;
|
||||
static int alloc_count = 0;
|
||||
static MemDesc *alloc_list = NULL;
|
||||
|
||||
|
||||
static void
|
||||
dbg_memleaks_done (int exitcode, void *dummy)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
(void) dummy;
|
||||
|
||||
if (exitcode == 0 && alloc_count != 0) {
|
||||
fprintf (stderr, "\nmemory leak detected !!!\n");
|
||||
fprintf (stderr, "\nalloc_count == %i\n\n", alloc_count);
|
||||
for (i = 0; i < alloc_count; i++) {
|
||||
MemDesc *d = &alloc_list[i];
|
||||
|
||||
fprintf (stderr, "chunk %p allocated in %s (%s: %u) not free'd !!\n",
|
||||
d->mem, d->allocated_in_func, d->allocated_in_file,
|
||||
d->allocated_in_line);
|
||||
}
|
||||
free (alloc_list);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dbg_memleaks_init (void)
|
||||
{
|
||||
on_exit (dbg_memleaks_done, NULL);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
dbg_malloc (char *file, int line, char *func, size_t bytes)
|
||||
{
|
||||
void *mem = (void *) malloc (bytes);
|
||||
MemDesc *d;
|
||||
|
||||
if (!initialized)
|
||||
dbg_memleaks_init ();
|
||||
|
||||
alloc_count++;
|
||||
alloc_list = realloc (alloc_list, alloc_count * sizeof (MemDesc));
|
||||
|
||||
d = &alloc_list[alloc_count - 1];
|
||||
d->mem = mem;
|
||||
d->allocated_in_func = func;
|
||||
d->allocated_in_file = file;
|
||||
d->allocated_in_line = line;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
dbg_calloc (char *file, int line, char *func, size_t count, size_t bytes)
|
||||
{
|
||||
void *mem = (void *) calloc (count, bytes);
|
||||
MemDesc *d;
|
||||
|
||||
if (!initialized)
|
||||
dbg_memleaks_init ();
|
||||
|
||||
alloc_count++;
|
||||
alloc_list = realloc (alloc_list, alloc_count * sizeof (MemDesc));
|
||||
|
||||
d = &alloc_list[alloc_count - 1];
|
||||
d->mem = mem;
|
||||
d->allocated_in_func = func;
|
||||
d->allocated_in_file = file;
|
||||
d->allocated_in_line = line;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
dbg_realloc (char *file, int line, char *func, char *what,
|
||||
void *mem, size_t bytes)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < alloc_count; i++) {
|
||||
if (alloc_list[i].mem == mem) {
|
||||
alloc_list[i].mem = (void *) realloc (mem, bytes);
|
||||
return alloc_list[i].mem;
|
||||
}
|
||||
}
|
||||
|
||||
if (mem != NULL) {
|
||||
fprintf (stderr,
|
||||
"%s: trying to reallocate unknown chunk %p (%s)\n"
|
||||
" in %s (%s: %u) !!!\n",
|
||||
__FUNCTION__, mem, what, func, file, line);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
return dbg_malloc (file, line, func, bytes);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dbg_free (char *file, int line, char *func, char *what, void *mem)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!initialized)
|
||||
dbg_memleaks_init ();
|
||||
|
||||
for (i = 0; i < alloc_count; i++) {
|
||||
if (alloc_list[i].mem == mem) {
|
||||
free (mem);
|
||||
alloc_count--;
|
||||
memmove (&alloc_list[i], &alloc_list[i + 1],
|
||||
(alloc_count - i) * sizeof (MemDesc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s: trying to free unknown chunk %p (%s)\n"
|
||||
" in %s (%s: %u) !!!\n",
|
||||
__FUNCTION__, mem, what, func, file, line);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef __MEM_H
|
||||
#define __MEM_H
|
||||
|
||||
#include "_stdint.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#if defined(DBG_MEMLEAKS)
|
||||
|
||||
extern void* dbg_malloc (char *file, int line, char *func, size_t bytes);
|
||||
extern void* dbg_calloc (char *file, int line, char *func, size_t count, size_t bytes);
|
||||
extern void* dbg_realloc (char *file, int line, char *func, char *what, void *mem, size_t bytes);
|
||||
extern void dbg_free (char *file, int line, char *func, char *what, void *mem);
|
||||
|
||||
#define MALLOC(bytes) dbg_malloc(__FILE__,__LINE__,__FUNCTION__,bytes)
|
||||
#define CALLOC(count,bytes) dbg_calloc(__FILE__,__LINE__,__FUNCTION__,count,bytes)
|
||||
#define FREE(mem) dbg_free(__FILE__,__LINE__,__FUNCTION__,#mem,mem)
|
||||
#define REALLOC(mem,bytes) dbg_realloc(__FILE__,__LINE__,__FUNCTION__,#mem,mem,bytes)
|
||||
|
||||
#else
|
||||
|
||||
#define MALLOC malloc
|
||||
#define CALLOC calloc
|
||||
#define REALLOC realloc
|
||||
#define FREE free
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
143
ext/tarkin/rle.h
143
ext/tarkin/rle.h
|
@ -1,143 +0,0 @@
|
|||
#ifndef __RLE_H
|
||||
#define __RLE_H
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "mem.h"
|
||||
#include "bitcoder.h"
|
||||
#include "golomb.h"
|
||||
|
||||
#if defined(RLECODER)
|
||||
|
||||
#define OUTPUT_BIT(rlecoder,bit) rlecoder_write_bit(rlecoder,bit)
|
||||
#define INPUT_BIT(rlecoder) rlecoder_read_bit(rlecoder)
|
||||
#define OUTPUT_BIT_DIRECT(coder,bit) bitcoder_write_bit(&(coder)->bitcoder,bit)
|
||||
#define INPUT_BIT_DIRECT(rlecoder) bitcoder_read_bit(&(rlecoder)->bitcoder)
|
||||
#define ENTROPY_CODER RLECoderState
|
||||
#define ENTROPY_ENCODER_INIT(coder,limit) rlecoder_encoder_init(coder,limit)
|
||||
#define ENTROPY_ENCODER_DONE(coder) rlecoder_encoder_done(coder)
|
||||
#define ENTROPY_ENCODER_FLUSH(coder) rlecoder_encoder_flush(coder)
|
||||
#define ENTROPY_DECODER_INIT(coder,bitstream,limit) \
|
||||
rlecoder_decoder_init(coder,bitstream,limit)
|
||||
#define ENTROPY_DECODER_DONE(coder) /* nothing to do ... */
|
||||
#define ENTROPY_CODER_BITSTREAM(coder) ((coder)->bitcoder.bitstream)
|
||||
#define ENTROPY_CODER_EOS(coder) ((coder)->bitcoder.eos)
|
||||
|
||||
#define ENTROPY_CODER_SYMBOL(coder) ((coder)->symbol)
|
||||
#define ENTROPY_CODER_RUNLENGTH(coder) ((coder)->count)
|
||||
#define ENTROPY_CODER_SKIP(coder,skip) do { (coder)->count -= skip; } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int symbol;
|
||||
uint32_t count; /* have seen count symbol's */
|
||||
BitCoderState bitcoder;
|
||||
GolombAdaptiveCoderState golomb_state [2]; /* 2 states for 2 symbols... */
|
||||
int have_seen_1;
|
||||
} RLECoderState;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bit should be 0 or 1 !!!
|
||||
*/
|
||||
static inline
|
||||
void rlecoder_write_bit (RLECoderState *s, int bit)
|
||||
{
|
||||
assert (bit == 0 || bit == 1);
|
||||
|
||||
if (s->symbol == -1) {
|
||||
s->symbol = bit & 1;
|
||||
s->count = 1;
|
||||
s->have_seen_1 = bit;
|
||||
bitcoder_write_bit (&s->bitcoder, bit);
|
||||
}
|
||||
|
||||
if (s->symbol != bit) {
|
||||
golombcoder_encode_number (&s->golomb_state[s->symbol],
|
||||
&s->bitcoder, s->count);
|
||||
s->symbol = ~s->symbol & 1;
|
||||
s->have_seen_1 = 1;
|
||||
s->count = 1;
|
||||
} else
|
||||
s->count++;
|
||||
}
|
||||
|
||||
static inline
|
||||
int rlecoder_read_bit (RLECoderState *s)
|
||||
{
|
||||
if (s->count == 0) {
|
||||
s->symbol = ~s->symbol & 1;
|
||||
s->count = golombcoder_decode_number (&s->golomb_state[s->symbol],
|
||||
&s->bitcoder);
|
||||
if (s->bitcoder.eos) {
|
||||
s->symbol = 0;
|
||||
s->count = ~0;
|
||||
}
|
||||
}
|
||||
s->count--;
|
||||
return (s->symbol);
|
||||
}
|
||||
|
||||
|
||||
int coder_id = 0;
|
||||
FILE *file = NULL;
|
||||
|
||||
static inline
|
||||
void rlecoder_encoder_init (RLECoderState *s, uint32_t limit)
|
||||
{
|
||||
bitcoder_encoder_init (&s->bitcoder, limit);
|
||||
s->symbol = -1;
|
||||
s->have_seen_1 = 0;
|
||||
s->golomb_state[0].count = 0;
|
||||
s->golomb_state[1].count = 0;
|
||||
s->golomb_state[0].bits = 5 << 3;
|
||||
s->golomb_state[1].bits = 5 << 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* once you called this, you better should not encode any more symbols ...
|
||||
*/
|
||||
static inline
|
||||
uint32_t rlecoder_encoder_flush (RLECoderState *s)
|
||||
{
|
||||
if (s->symbol == -1 || !s->have_seen_1)
|
||||
return 0;
|
||||
|
||||
golombcoder_encode_number (&s->golomb_state[s->symbol],
|
||||
&s->bitcoder, s->count);
|
||||
return bitcoder_flush (&s->bitcoder);
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void rlecoder_decoder_init (RLECoderState *s, uint8_t *bitstream, uint32_t limit)
|
||||
{
|
||||
bitcoder_decoder_init (&s->bitcoder, bitstream, limit);
|
||||
s->golomb_state[0].count = 0;
|
||||
s->golomb_state[1].count = 0;
|
||||
s->golomb_state[0].bits = 5 << 3;
|
||||
s->golomb_state[1].bits = 5 << 3;
|
||||
s->symbol = bitcoder_read_bit (&s->bitcoder);
|
||||
s->count = golombcoder_decode_number (&s->golomb_state[s->symbol],
|
||||
&s->bitcoder) - 1;
|
||||
if (s->bitcoder.eos) {
|
||||
s->symbol = 0;
|
||||
s->count = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void rlecoder_encoder_done (RLECoderState *s)
|
||||
{
|
||||
bitcoder_encoder_done (&s->bitcoder);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,420 +0,0 @@
|
|||
/*
|
||||
* The real io-stuff is in tarkin-io.c
|
||||
* (this one has to be rewritten to write ogg streams ...)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "tarkin.h"
|
||||
#include "yuv.h"
|
||||
|
||||
|
||||
#define N_FRAMES 1
|
||||
|
||||
|
||||
|
||||
TarkinStream *
|
||||
tarkin_stream_new ()
|
||||
{
|
||||
TarkinStream *s = (TarkinStream *) CALLOC (1, sizeof (TarkinStream));
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
memset (s, 0, sizeof (*s));
|
||||
|
||||
s->frames_per_buf = N_FRAMES;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tarkin_stream_destroy (TarkinStream * s)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
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]);
|
||||
FREE (s->layer[i].packet[j].data);
|
||||
}
|
||||
FREE (s->layer[i].waveletbuf);
|
||||
FREE (s->layer[i].packet);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->layer)
|
||||
FREE (s->layer);
|
||||
|
||||
if (s->headers.header)
|
||||
FREE (s->headers.header);
|
||||
|
||||
if (s->headers.header1)
|
||||
FREE (s->headers.header1);
|
||||
|
||||
if (s->headers.header2)
|
||||
FREE (s->headers.header2);
|
||||
|
||||
|
||||
FREE (s);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
tarkin_analysis_init (TarkinStream * s, TarkinInfo * ti,
|
||||
TarkinError (*free_frame) (void *s, void *ptr),
|
||||
TarkinError (*packet_out) (void *s, ogg_packet * ptr), void *user_ptr)
|
||||
{
|
||||
if ((!ti->inter.numerator) || (!ti->inter.denominator))
|
||||
return (-TARKIN_FAULT);
|
||||
if ((!free_frame) || (!packet_out))
|
||||
return (-TARKIN_FAULT);
|
||||
s->ti = ti;
|
||||
s->free_frame = free_frame;
|
||||
s->packet_out = packet_out;
|
||||
s->user_ptr = user_ptr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
extern int
|
||||
tarkin_analysis_add_layer (TarkinStream * s, TarkinVideoLayerDesc * tvld)
|
||||
{
|
||||
int i;
|
||||
TarkinVideoLayer *layer;
|
||||
|
||||
if (s->n_layers) {
|
||||
s->layer = REALLOC (s->layer, (s->n_layers + 1) * sizeof (*s->layer));
|
||||
} else {
|
||||
s->layer = MALLOC (sizeof (*s->layer));
|
||||
}
|
||||
layer = s->layer + s->n_layers;
|
||||
memset (layer, 0, sizeof (*s->layer));
|
||||
memcpy (&layer->desc, tvld, sizeof (TarkinVideoLayerDesc));
|
||||
|
||||
s->n_layers++;
|
||||
s->ti->n_layers = s->n_layers;
|
||||
s->ti->layer = s->layer;
|
||||
|
||||
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:
|
||||
return -TARKIN_INVALID_COLOR_FORMAT;
|
||||
};
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg:add_layer %d with %d components\n",
|
||||
s->n_layers, layer->n_comp);
|
||||
#endif
|
||||
|
||||
layer->waveletbuf = (Wavelet3DBuf **) CALLOC (layer->n_comp,
|
||||
sizeof (Wavelet3DBuf *));
|
||||
|
||||
layer->packet = MALLOC (layer->n_comp * sizeof (*layer->packet));
|
||||
memset (layer->packet, 0, layer->n_comp * sizeof (*layer->packet));
|
||||
|
||||
for (i = 0; i < layer->n_comp; i++) {
|
||||
layer->waveletbuf[i] = wavelet_3d_buf_new (layer->desc.width,
|
||||
layer->desc.height, layer->desc.frames_per_buf);
|
||||
layer->packet[i].data = MALLOC (layer->desc.bitstream_len);
|
||||
layer->packet[i].storage = layer->desc.bitstream_len;
|
||||
}
|
||||
/*
|
||||
max_bitstream_len += layer->desc.bitstream_len
|
||||
+ 2 * 10 * sizeof(uint32_t) * layer->n_comp;
|
||||
*/
|
||||
return (TARKIN_OK);
|
||||
}
|
||||
|
||||
TarkinError
|
||||
_analysis_packetout (TarkinStream * s, uint32_t layer_id, uint32_t comp)
|
||||
{
|
||||
ogg_packet op;
|
||||
oggpack_buffer opb;
|
||||
uint8_t *data;
|
||||
uint32_t data_len;
|
||||
int i;
|
||||
|
||||
data = s->layer[layer_id].packet[comp].data;
|
||||
data_len = s->layer[layer_id].packet[comp].data_len;
|
||||
|
||||
oggpack_writeinit (&opb);
|
||||
oggpack_write (&opb, 0, 8); /* No feature flags for now */
|
||||
oggpack_write (&opb, layer_id, 12);
|
||||
oggpack_write (&opb, comp, 12);
|
||||
for (i = 0; i < data_len; i++)
|
||||
oggpack_write (&opb, *(data + i), 8);
|
||||
|
||||
op.b_o_s = 0;
|
||||
op.e_o_s = data_len ? 0 : 1;
|
||||
op.granulepos = 0;
|
||||
op.bytes = oggpack_bytes (&opb) + 4;
|
||||
op.packet = opb.buffer;
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: writing packet layer %d, comp %d, data_len %d %s\n",
|
||||
layer_id, comp, data_len, op.e_o_s ? "eos" : "");
|
||||
#endif
|
||||
s->layer[layer_id].packet[comp].data_len = 0; /* so direct call => eos */
|
||||
return (s->packet_out (s, &op));
|
||||
}
|
||||
|
||||
void
|
||||
_stream_flush (TarkinStream * s)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
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 comp_bitstream_len;
|
||||
TarkinPacket *packet = layer->packet + j;
|
||||
|
||||
/**
|
||||
* implicit 6:1:1 subsampling
|
||||
*/
|
||||
if (j == 0)
|
||||
comp_bitstream_len =
|
||||
6 * layer->desc.bitstream_len / (layer->n_comp + 5);
|
||||
else
|
||||
comp_bitstream_len = layer->desc.bitstream_len / (layer->n_comp + 5);
|
||||
|
||||
if (packet->storage < comp_bitstream_len) {
|
||||
packet->storage = comp_bitstream_len;
|
||||
packet->data = REALLOC (packet->data, comp_bitstream_len);
|
||||
}
|
||||
|
||||
wavelet_3d_buf_dump ("color-%d-%03d.pgm",
|
||||
s->current_frame, j, layer->waveletbuf[j], j == 0 ? 0 : 128);
|
||||
|
||||
wavelet_3d_buf_fwd_xform (layer->waveletbuf[j],
|
||||
layer->desc.a_moments, layer->desc.s_moments);
|
||||
|
||||
wavelet_3d_buf_dump ("coeff-%d-%03d.pgm",
|
||||
s->current_frame, j, layer->waveletbuf[j], 128);
|
||||
|
||||
packet->data_len = wavelet_3d_buf_encode_coeff (layer->waveletbuf[j],
|
||||
packet->data, comp_bitstream_len);
|
||||
|
||||
_analysis_packetout (s, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
tarkin_analysis_framein (TarkinStream * s, uint8_t * frame,
|
||||
uint32_t layer_id, TarkinTime * date)
|
||||
{
|
||||
TarkinVideoLayer *layer;
|
||||
|
||||
if (!frame)
|
||||
return (_analysis_packetout (s, 0, 0)); /* eos */
|
||||
if ((layer_id >= s->n_layers) || (date->denominator == 0))
|
||||
return (TARKIN_FAULT);
|
||||
|
||||
layer = s->layer + layer_id;
|
||||
layer->color_fwd_xform (frame, layer->waveletbuf, s->current_frame_in_buf);
|
||||
/* We don't use this feature for now, neither date... */
|
||||
s->free_frame (s, frame);
|
||||
|
||||
s->current_frame_in_buf++;
|
||||
|
||||
if (s->current_frame_in_buf == s->frames_per_buf)
|
||||
_stream_flush (s);
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: framein at pos %d/%d, n? %d,%d on layer %d\n",
|
||||
date->numerator, date->denominator,
|
||||
layer->frameno, s->current_frame, layer_id);
|
||||
#endif
|
||||
|
||||
layer->frameno++;
|
||||
return (++s->current_frame);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* tarkin_stream_read_header() is now info.c:_tarkin_unpack_layer_desc()
|
||||
*/
|
||||
|
||||
|
||||
|
||||
TarkinError
|
||||
tarkin_stream_get_layer_desc (TarkinStream * s,
|
||||
uint32_t layer_id, TarkinVideoLayerDesc * desc)
|
||||
{
|
||||
if (layer_id > s->n_layers - 1)
|
||||
return -TARKIN_INVALID_LAYER;
|
||||
|
||||
memcpy (desc, &(s->layer[layer_id].desc), sizeof (TarkinVideoLayerDesc));
|
||||
|
||||
return TARKIN_OK;
|
||||
}
|
||||
|
||||
TarkinError
|
||||
tarkin_synthesis_init (TarkinStream * s, TarkinInfo * ti)
|
||||
{
|
||||
s->ti = ti;
|
||||
s->layer = ti->layer; /* It was malloc()ed by headerin() */
|
||||
s->n_layers = ti->n_layers;
|
||||
return (TARKIN_OK);
|
||||
}
|
||||
|
||||
TarkinError
|
||||
tarkin_synthesis_packetin (TarkinStream * s, ogg_packet * op)
|
||||
{
|
||||
uint32_t i, layer_id, comp, data_len;
|
||||
uint32_t flags, junk;
|
||||
int nread;
|
||||
oggpack_buffer opb;
|
||||
TarkinPacket *packet;
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: Reading packet n? %lld, granulepos %lld, len %ld, %s%s\n",
|
||||
op->packetno, op->granulepos, op->bytes,
|
||||
op->b_o_s ? "b_o_s" : "", op->e_o_s ? "e_o_s" : "");
|
||||
#endif
|
||||
oggpack_readinit (&opb, op->packet, op->bytes);
|
||||
flags = oggpack_read (&opb, 8);
|
||||
layer_id = oggpack_read (&opb, 12); /* Theses are required for */
|
||||
comp = oggpack_read (&opb, 12); /* data hole handling (or maybe
|
||||
* packetno would be enough ?) */
|
||||
nread = 4;
|
||||
|
||||
if (flags) { /* This is void "infinite future features" feature ;) */
|
||||
if (flags & 1 << 7) {
|
||||
junk = flags;
|
||||
while (junk & 1 << 7)
|
||||
junk = oggpack_read (&opb, 8); /* allow for many future flags
|
||||
that must be correctly ordonned. */
|
||||
}
|
||||
/* This shows how to get a feature's data:
|
||||
if (flags & TARKIN_FLAGS_EXAMPLE){
|
||||
tp->example = oggpack_read(&opb,32);
|
||||
junk = tp->example & 3<<30;
|
||||
tp->example &= 0x4fffffff;
|
||||
}
|
||||
*/
|
||||
for (junk = 1 << 31; junk & 1 << 31;) /* and many future data */
|
||||
while ((junk = oggpack_read (&opb, 32)) & 1 << 30);
|
||||
/* That is, feature data comes in 30 bit chunks. We also have
|
||||
* 31 potentially useful bits in last chunk. */
|
||||
}
|
||||
|
||||
nread = (opb.ptr - opb.buffer);
|
||||
data_len = op->bytes - nread;
|
||||
|
||||
#ifdef DBG_OGG
|
||||
printf (" layer_id %d, comp %d, meta-data %dB, w3d data %dB.\n",
|
||||
layer_id, comp, nread, data_len);
|
||||
#endif
|
||||
|
||||
/* We now have for shure our data. */
|
||||
packet = &s->layer[layer_id].packet[comp];
|
||||
if (packet->data_len)
|
||||
return (-TARKIN_UNUSED); /* Previous data wasn't used */
|
||||
|
||||
if (packet->storage < data_len) {
|
||||
packet->storage = data_len + 255;
|
||||
packet->data = REALLOC (packet->data, packet->storage);
|
||||
}
|
||||
|
||||
for (i = 0; i < data_len; i++)
|
||||
packet->data[i] = oggpack_read (&opb, 8);
|
||||
|
||||
packet->data_len = data_len;
|
||||
|
||||
return (TARKIN_OK);
|
||||
}
|
||||
|
||||
TarkinError
|
||||
tarkin_synthesis_frameout (TarkinStream * s,
|
||||
uint8_t ** frame, uint32_t layer_id, TarkinTime * date)
|
||||
{
|
||||
int j;
|
||||
TarkinVideoLayer *layer = &s->layer[layer_id];
|
||||
|
||||
if (s->current_frame_in_buf == 0) {
|
||||
*frame = MALLOC (layer->desc.width * layer->desc.height * layer->n_comp);
|
||||
for (j = 0; j < layer->n_comp; j++) {
|
||||
TarkinPacket *packet = layer->packet + j;
|
||||
|
||||
if (packet->data_len == 0)
|
||||
goto err_out;
|
||||
|
||||
wavelet_3d_buf_decode_coeff (layer->waveletbuf[j], packet->data,
|
||||
packet->data_len);
|
||||
|
||||
wavelet_3d_buf_dump ("rcoeff-%d-%03d.pgm",
|
||||
s->current_frame, j, layer->waveletbuf[j], 128);
|
||||
|
||||
wavelet_3d_buf_inv_xform (layer->waveletbuf[j],
|
||||
layer->desc.a_moments, layer->desc.s_moments);
|
||||
|
||||
wavelet_3d_buf_dump ("rcolor-%d-%03d.pgm",
|
||||
s->current_frame, j, layer->waveletbuf[j], j == 0 ? 0 : 128);
|
||||
}
|
||||
|
||||
/* We did successfylly read a block from this layer, acknowledge it. */
|
||||
for (j = 0; j < layer->n_comp; j++)
|
||||
layer->packet[j].data_len = 0;
|
||||
}
|
||||
|
||||
layer->color_inv_xform (layer->waveletbuf, *frame, s->current_frame_in_buf);
|
||||
s->current_frame_in_buf++;
|
||||
s->current_frame++;
|
||||
|
||||
if (s->current_frame_in_buf == s->frames_per_buf)
|
||||
s->current_frame_in_buf = 0;
|
||||
|
||||
date->numerator = layer->frameno * s->ti->inter.numerator;
|
||||
date->denominator = s->ti->inter.denominator;
|
||||
#ifdef DBG_OGG
|
||||
printf ("dbg_ogg: outputting frame pos %d/%d from layer %d.\n",
|
||||
date->numerator, date->denominator, layer_id);
|
||||
#endif
|
||||
layer->frameno++;
|
||||
return (TARKIN_OK);
|
||||
err_out:
|
||||
FREE (*frame);
|
||||
return (TARKIN_NEED_MORE);
|
||||
}
|
||||
|
||||
int
|
||||
tarkin_synthesis_freeframe (TarkinStream * s, uint8_t * frame)
|
||||
{
|
||||
FREE (frame);
|
||||
|
||||
return (TARKIN_OK);
|
||||
}
|
|
@ -1,239 +0,0 @@
|
|||
#ifndef __TARKIN_H
|
||||
#define __TARKIN_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "wavelet.h"
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
|
||||
#define BUG(x...) \
|
||||
do { \
|
||||
printf("BUG in %s (%s: line %i): ", __FUNCTION__, __FILE__, __LINE__); \
|
||||
printf(#x); \
|
||||
printf("\n"); \
|
||||
exit (-1); \
|
||||
} while (0);
|
||||
|
||||
|
||||
/* Theses determine what infos the packet comes with */
|
||||
#define TARKIN_PACK_EXAMPLE 1
|
||||
|
||||
typedef struct {
|
||||
uint8_t *data;
|
||||
uint32_t data_len;
|
||||
uint32_t storage;
|
||||
} TarkinPacket;
|
||||
|
||||
|
||||
typedef enum {
|
||||
TARKIN_GRAYSCALE,
|
||||
TARKIN_RGB24, /* tight packed RGB */
|
||||
TARKIN_RGB32, /* 32bit, no alphachannel */
|
||||
TARKIN_RGBA, /* dito w/ alphachannel */
|
||||
TARKIN_YUV2, /* 16 bits YUV */
|
||||
TARKIN_YUV12, /* 12 bits YUV */
|
||||
TARKIN_FYUV, /* Tarkin's Fast YUV-like? */
|
||||
} TarkinColorFormat;
|
||||
|
||||
#define TARKIN_INTERNAL_FORMAT TARKIN_FYUV
|
||||
|
||||
typedef enum {
|
||||
TARKIN_OK = 0,
|
||||
TARKIN_IO_ERROR,
|
||||
TARKIN_SIGNATURE_NOT_FOUND,
|
||||
TARKIN_INVALID_LAYER,
|
||||
TARKIN_INVALID_COLOR_FORMAT,
|
||||
TARKIN_VERSION,
|
||||
TARKIN_BAD_HEADER,
|
||||
TARKIN_NOT_TARKIN,
|
||||
TARKIN_FAULT,
|
||||
TARKIN_UNUSED,
|
||||
TARKIN_NEED_MORE,
|
||||
TARKIN_NOT_IMPLEMENTED
|
||||
} TarkinError;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t a_moments;
|
||||
uint32_t s_moments;
|
||||
uint32_t frames_per_buf;
|
||||
uint32_t bitstream_len; /* for all color components, bytes */
|
||||
TarkinColorFormat format;
|
||||
} TarkinVideoLayerDesc;
|
||||
|
||||
|
||||
typedef struct {
|
||||
TarkinVideoLayerDesc desc;
|
||||
uint32_t n_comp; /* number of color components */
|
||||
Wavelet3DBuf **waveletbuf;
|
||||
TarkinPacket *packet;
|
||||
uint32_t current_frame_in_buf;
|
||||
uint32_t frameno;
|
||||
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
uint32_t numerator;
|
||||
uint32_t denominator;
|
||||
} TarkinTime; /* Let's say the unit is 1 second */
|
||||
|
||||
typedef struct TarkinInfo {
|
||||
int version;
|
||||
int n_layers;
|
||||
TarkinVideoLayer *layer;
|
||||
TarkinTime inter; /* numerator == O if per-frame time info. */
|
||||
int frames_per_block;
|
||||
int comp_per_block; /* AKA "packets per block" for now */
|
||||
uint32_t max_bitstream_len;
|
||||
|
||||
/* The below bitrate declarations are *hints*.
|
||||
Combinations of the three values carry the following implications:
|
||||
|
||||
all three set to the same value:
|
||||
implies a fixed rate bitstream
|
||||
only nominal set:
|
||||
implies a VBR stream that averages the nominal bitrate. No hard
|
||||
upper/lower limit
|
||||
upper and or lower set:
|
||||
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
may also be set to give a nominal rate.
|
||||
none set:
|
||||
the coder does not care to speculate.
|
||||
*/
|
||||
|
||||
long bitrate_upper;
|
||||
long bitrate_nominal;
|
||||
long bitrate_lower;
|
||||
long bitrate_window;
|
||||
} TarkinInfo;
|
||||
|
||||
/* This is used for encoding */
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
unsigned char *header1;
|
||||
unsigned char *header2;
|
||||
} tarkin_header_store;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Some of the fields in TarkinStream are redundent with TarkinInfo ones
|
||||
* and will probably get deleted, namely n_layers and frames_per_buf */
|
||||
typedef struct TarkinStream {
|
||||
uint32_t n_layers;
|
||||
TarkinVideoLayer *layer;
|
||||
uint32_t current_frame;
|
||||
uint32_t current_frame_in_buf;
|
||||
ogg_int64_t packetno;
|
||||
uint32_t frames_per_buf;
|
||||
uint32_t max_bitstream_len;
|
||||
TarkinInfo *ti;
|
||||
tarkin_header_store headers;
|
||||
/* These callbacks are only used for encoding */
|
||||
TarkinError (*free_frame)(void *tarkinstream, void *ptr);
|
||||
/* These thing allows not to buffer but it needs global var in caller. */
|
||||
TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr);
|
||||
void * user_ptr;
|
||||
} TarkinStream;
|
||||
|
||||
|
||||
typedef struct TarkinComment{
|
||||
/* unlimited user comment fields. libtarkin writes 'libtarkin'
|
||||
whatever vendor is set to in encode */
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} TarkinComment;
|
||||
|
||||
/* Tarkin PRIMITIVES: general ***************************************/
|
||||
|
||||
/* The Tarkin header is in three packets, the initial small packet in
|
||||
the first page that identifies basic parameters, that is a TarkinInfo
|
||||
structure, a second packet with bitstream comments and a third packet
|
||||
that holds the layers description structures. */
|
||||
|
||||
|
||||
/* Theses are the very same than Vorbis versions, they could be shared. */
|
||||
extern TarkinStream* tarkin_stream_new ();
|
||||
extern void tarkin_stream_destroy (TarkinStream *s);
|
||||
extern void tarkin_info_init(TarkinInfo *vi);
|
||||
extern void tarkin_info_clear(TarkinInfo *vi);
|
||||
extern void tarkin_comment_init(TarkinComment *vc);
|
||||
extern void tarkin_comment_add(TarkinComment *vc, char *comment);
|
||||
extern void tarkin_comment_add_tag(TarkinComment *vc,
|
||||
char *tag, char *contents);
|
||||
extern char *tarkin_comment_query(TarkinComment *vc, char *tag, int count);
|
||||
extern int tarkin_comment_query_count(TarkinComment *vc, char *tag);
|
||||
extern void tarkin_comment_clear(TarkinComment *vc);
|
||||
|
||||
/* Tarkin PRIMITIVES: analysis layer ****************************/
|
||||
/* Tarkin encoding is done this way : you init it passing a fresh
|
||||
* TarkinStream and a fresh TarkinInfo which has at least the rate_num
|
||||
* field renseigned. You also pass it two callback functions: free_frame()
|
||||
* is called when the lib doesn't need a frame anymore, and packet_out
|
||||
* is called when a packet is ready. The pointers given as arguments to
|
||||
* these callback functions are of course only valid at the function call
|
||||
* time. The user_ptr is stored in s and can be used by packet_out(). */
|
||||
extern int tarkin_analysis_init(TarkinStream *s,
|
||||
TarkinInfo *ti,
|
||||
TarkinError (*free_frame)(void *tarkinstream, void *ptr),
|
||||
TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr),
|
||||
void *user_ptr
|
||||
);
|
||||
/* Then you need to add at least a layer in your stream, passing a
|
||||
* TarkinVideoLayerDesc renseigned at least on the width, height and
|
||||
* format parameters. */
|
||||
extern int tarkin_analysis_add_layer(TarkinStream *s,
|
||||
TarkinVideoLayerDesc *tvld);
|
||||
/* At that point you are ready to get headers out the lib by calling
|
||||
* tarkin_analysis_headerout() passing it a renseigned TarkinComment
|
||||
* structure. It does fill your 3 ogg_packet headers, which are valid
|
||||
* till next call */
|
||||
extern int TarkinCommentheader_out(TarkinComment *vc, ogg_packet *op);
|
||||
extern TarkinError tarkin_analysis_headerout(TarkinStream *s,
|
||||
TarkinComment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code);
|
||||
/* You are now ready to pass in frames to the codec, however don't free
|
||||
* them before the codec told you so. It'll tell you when packets are
|
||||
* ready to be taken out. When you have no more frame, simply pass NULL.
|
||||
* If you encode multiple layers you have to do it synchronously, putting
|
||||
* one frame from each layer at a time. */
|
||||
extern uint32_t tarkin_analysis_framein(TarkinStream *s,
|
||||
uint8_t *frame, /* NULL for EOS */
|
||||
uint32_t layer,
|
||||
TarkinTime *date);
|
||||
|
||||
/* Tarkin PRIMITIVES: synthesis layer *******************************/
|
||||
/* For decoding, you needs first to give the three first packet of the
|
||||
* stream to tarkin_synthesis_headerin() which will fill for you blank
|
||||
* TarkinInfo and TarkinComment. */
|
||||
extern TarkinError tarkin_synthesis_headerin(TarkinInfo *vi,TarkinComment *vc,
|
||||
ogg_packet *op);
|
||||
/* Then you can init your stream with your TarkinInfo struct. */
|
||||
extern TarkinError tarkin_synthesis_init(TarkinStream *s,TarkinInfo *ti);
|
||||
/* All subsequent packets are to this be passed to tarkin_synthesis_packetin*/
|
||||
extern TarkinError tarkin_synthesis_packetin(TarkinStream *s, ogg_packet *op);
|
||||
/* and then tarkin_synthesis_frameout gives you ptr on next frame, or NULL. It
|
||||
* also fills for you date. */
|
||||
extern TarkinError tarkin_synthesis_frameout(TarkinStream *s,
|
||||
uint8_t **frame, uint32_t layer_id, TarkinTime *date);
|
||||
/* When you're done with a frame, tell it to the codec with this. */
|
||||
extern int tarkin_synthesis_freeframe(TarkinStream *s, uint8_t *frame);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "wavelet.h"
|
||||
|
||||
/*
|
||||
* (The transform code is in wavelet_xform.c)
|
||||
*/
|
||||
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MAX3(a,b,c) (MAX(a,MAX(b,c)))
|
||||
|
||||
|
||||
|
||||
Wavelet3DBuf *
|
||||
wavelet_3d_buf_new (uint32_t width, uint32_t height, uint32_t frames)
|
||||
{
|
||||
Wavelet3DBuf *buf = (Wavelet3DBuf *) MALLOC (sizeof (Wavelet3DBuf));
|
||||
uint32_t _w = width;
|
||||
uint32_t _h = height;
|
||||
uint32_t _f = frames;
|
||||
int level;
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->data = (TYPE *) MALLOC (width * height * frames * sizeof (TYPE));
|
||||
|
||||
if (!buf->data) {
|
||||
wavelet_3d_buf_destroy (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->width = width;
|
||||
buf->height = height;
|
||||
buf->frames = frames;
|
||||
buf->scales = 1;
|
||||
|
||||
while (_w > 1 || _h > 1 || _f > 1) {
|
||||
buf->scales++;
|
||||
_w = (_w + 1) / 2;
|
||||
_h = (_h + 1) / 2;
|
||||
_f = (_f + 1) / 2;
|
||||
}
|
||||
|
||||
buf->w = (uint32_t *) MALLOC (buf->scales * sizeof (uint32_t));
|
||||
buf->h = (uint32_t *) MALLOC (buf->scales * sizeof (uint32_t));
|
||||
buf->f = (uint32_t *) MALLOC (buf->scales * sizeof (uint32_t));
|
||||
buf->offset = (uint32_t (*)[8]) MALLOC (8 * buf->scales * sizeof (uint32_t));
|
||||
|
||||
buf->scratchbuf =
|
||||
(TYPE *) MALLOC (MAX3 (width, height, frames) * sizeof (TYPE));
|
||||
|
||||
if (!buf->w || !buf->h || !buf->f || !buf->offset || !buf->scratchbuf) {
|
||||
wavelet_3d_buf_destroy (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->w[buf->scales - 1] = width;
|
||||
buf->h[buf->scales - 1] = height;
|
||||
buf->f[buf->scales - 1] = frames;
|
||||
|
||||
for (level = buf->scales - 2; level >= 0; level--) {
|
||||
buf->w[level] = (buf->w[level + 1] + 1) / 2;
|
||||
buf->h[level] = (buf->h[level + 1] + 1) / 2;
|
||||
buf->f[level] = (buf->f[level + 1] + 1) / 2;
|
||||
buf->offset[level][0] = 0;
|
||||
buf->offset[level][1] = buf->w[level];
|
||||
buf->offset[level][2] = buf->h[level] * width;
|
||||
buf->offset[level][3] = buf->f[level] * width * height;
|
||||
buf->offset[level][4] = buf->offset[level][2] + buf->w[level];
|
||||
buf->offset[level][5] = buf->offset[level][3] + buf->w[level];
|
||||
buf->offset[level][6] = buf->offset[level][3] + buf->offset[level][2];
|
||||
buf->offset[level][7] = buf->offset[level][6] + buf->w[level];
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wavelet_3d_buf_destroy (Wavelet3DBuf * buf)
|
||||
{
|
||||
if (buf) {
|
||||
if (buf->data)
|
||||
FREE (buf->data);
|
||||
if (buf->w)
|
||||
FREE (buf->w);
|
||||
if (buf->h)
|
||||
FREE (buf->h);
|
||||
if (buf->f)
|
||||
FREE (buf->f);
|
||||
if (buf->offset)
|
||||
FREE (buf->offset);
|
||||
if (buf->scratchbuf)
|
||||
FREE (buf->scratchbuf);
|
||||
FREE (buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(DBG_XFORM)
|
||||
|
||||
#include "pnm.h"
|
||||
|
||||
void
|
||||
wavelet_3d_buf_dump (char *fmt,
|
||||
uint32_t first_frame_in_buf,
|
||||
uint32_t id, Wavelet3DBuf * buf, int16_t offset)
|
||||
{
|
||||
char fname[256];
|
||||
uint32_t f;
|
||||
|
||||
for (f = 0; f < buf->frames; f++) {
|
||||
snprintf (fname, 256, fmt, id, first_frame_in_buf + f);
|
||||
|
||||
write_pgm16 (fname, buf->data + f * buf->width * buf->height,
|
||||
buf->width, buf->height, offset);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef __WAVELET_H
|
||||
#define __WAVELET_H
|
||||
|
||||
#include "_stdint.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
TYPE *data;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t frames;
|
||||
uint32_t scales;
|
||||
uint32_t *w;
|
||||
uint32_t *h;
|
||||
uint32_t *f;
|
||||
uint32_t (*offset)[8];
|
||||
TYPE *scratchbuf;
|
||||
} Wavelet3DBuf;
|
||||
|
||||
|
||||
extern Wavelet3DBuf* wavelet_3d_buf_new (uint32_t width, uint32_t height,
|
||||
uint32_t frames);
|
||||
|
||||
extern void wavelet_3d_buf_destroy (Wavelet3DBuf* buf);
|
||||
|
||||
/*
|
||||
* transform buf->data
|
||||
* a_moments is the number of vanishing moments of the analyzing
|
||||
* highpass filter,
|
||||
* s_moments the one of the synthesizing lowpass filter.
|
||||
*/
|
||||
extern void wavelet_3d_buf_fwd_xform (Wavelet3DBuf* buf,
|
||||
int a_moments, int s_moments);
|
||||
extern void wavelet_3d_buf_inv_xform (Wavelet3DBuf* buf,
|
||||
int a_moments, int s_moments);
|
||||
|
||||
extern int wavelet_3d_buf_encode_coeff (const Wavelet3DBuf* buf,
|
||||
uint8_t *bitstream,
|
||||
uint32_t limit);
|
||||
|
||||
extern void wavelet_3d_buf_decode_coeff (Wavelet3DBuf* buf,
|
||||
uint8_t *bitstream,
|
||||
uint32_t limit);
|
||||
|
||||
#if defined(DBG_XFORM)
|
||||
extern void wavelet_3d_buf_dump (char *fmt,
|
||||
uint32_t first_frame_in_buf,
|
||||
uint32_t id,
|
||||
Wavelet3DBuf* buf,
|
||||
int16_t offset);
|
||||
#else
|
||||
#define wavelet_3d_buf_dump(x...)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,517 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "wavelet.h"
|
||||
#include "rle.h"
|
||||
|
||||
#define printf(args...)
|
||||
|
||||
#define GRAY_CODES 1
|
||||
|
||||
#if defined(GRAY_CODES)
|
||||
static inline uint16_t
|
||||
binary_to_gray (uint16_t x)
|
||||
{
|
||||
return x ^ (x >> 1);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
gray_to_binary (uint16_t x)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < 16; i += i)
|
||||
x ^= x >> i;
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline void
|
||||
encode_coeff (ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[], TYPE coeff)
|
||||
{
|
||||
int sign = (coeff >> (8 * sizeof (TYPE) - 1)) & 1;
|
||||
|
||||
#if defined(GRAY_CODES)
|
||||
TYPE significance = binary_to_gray (coeff);
|
||||
#else
|
||||
static TYPE mask[2] = { 0, ~0 };
|
||||
TYPE significance = coeff ^ mask[sign];
|
||||
#endif
|
||||
int i = TYPE_BITS;
|
||||
|
||||
do {
|
||||
i--;
|
||||
OUTPUT_BIT (&significand_bitstream[i], (significance >> i) & 1);
|
||||
} while (!((significance >> i) & 1) && i > 0);
|
||||
|
||||
OUTPUT_BIT (&significand_bitstream[i], sign);
|
||||
|
||||
while (--i >= 0)
|
||||
OUTPUT_BIT (&insignificand_bitstream[i], (significance >> i) & 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline TYPE
|
||||
decode_coeff (ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[])
|
||||
{
|
||||
#if !defined(GRAY_CODES)
|
||||
static TYPE mask[2] = { 0, ~0 };
|
||||
#endif
|
||||
TYPE significance = 0;
|
||||
int sign;
|
||||
int i = TYPE_BITS;
|
||||
|
||||
do {
|
||||
i--;
|
||||
significance |= INPUT_BIT (&significand_bitstream[i]) << i;
|
||||
/* if (ENTROPY_CODER_EOS(&significand_bitstream[i])) */
|
||||
/* return 0; */
|
||||
} while (!significance && i > 0);
|
||||
|
||||
sign = INPUT_BIT (&significand_bitstream[i]);
|
||||
/* if (ENTROPY_CODER_EOS(&significand_bitstream[i])) */
|
||||
/* return 0; */
|
||||
|
||||
while (--i >= 0)
|
||||
significance |= INPUT_BIT (&insignificand_bitstream[i]) << i;
|
||||
|
||||
#if defined(GRAY_CODES)
|
||||
significance |= sign << (8 * sizeof (TYPE) - 1);
|
||||
return gray_to_binary (significance);
|
||||
#else
|
||||
return (significance ^ mask[sign]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
skip_0coeffs (Wavelet3DBuf * buf,
|
||||
ENTROPY_CODER s_stream[], ENTROPY_CODER i_stream[], uint32_t limit)
|
||||
{
|
||||
int i;
|
||||
uint32_t skip = limit;
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
if (ENTROPY_CODER_SYMBOL (&s_stream[i]) != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
uint32_t runlength = ENTROPY_CODER_RUNLENGTH (&s_stream[i]);
|
||||
|
||||
if (i == 0)
|
||||
runlength /= 2; /* sign bits are in this bitplane ... */
|
||||
if (skip > runlength)
|
||||
skip = runlength;
|
||||
if (skip <= 2)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ENTROPY_CODER_SKIP (&s_stream[0], 2 * skip); /* kill sign+significance bits */
|
||||
|
||||
for (i = 1; i < TYPE_BITS; i++)
|
||||
ENTROPY_CODER_SKIP (&s_stream[i], skip);
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 1
|
||||
static inline void
|
||||
encode_quadrant (const Wavelet3DBuf * buf,
|
||||
int level, int quadrant, uint32_t w, uint32_t h, uint32_t f,
|
||||
ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[])
|
||||
{
|
||||
uint32_t x, y, z;
|
||||
|
||||
for (z = 0; z < f; z++) {
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
unsigned int index = buf->offset[level][quadrant]
|
||||
+ z * buf->width * buf->height + y * buf->width + x;
|
||||
|
||||
encode_coeff (significand_bitstream, insignificand_bitstream,
|
||||
buf->data[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
encode_coefficients (const Wavelet3DBuf * buf,
|
||||
ENTROPY_CODER s_stream[], ENTROPY_CODER i_stream[])
|
||||
{
|
||||
int level;
|
||||
|
||||
encode_coeff (s_stream, i_stream, buf->data[0]);
|
||||
|
||||
for (level = 0; level < buf->scales - 1; level++) {
|
||||
uint32_t w, h, f, w1, h1, f1;
|
||||
|
||||
w = buf->w[level];
|
||||
h = buf->h[level];
|
||||
f = buf->f[level];
|
||||
w1 = buf->w[level + 1] - w;
|
||||
h1 = buf->h[level + 1] - h;
|
||||
f1 = buf->f[level + 1] - f;
|
||||
|
||||
if (w1 > 0)
|
||||
encode_quadrant (buf, level, 1, w1, h, f, s_stream, i_stream);
|
||||
if (h1 > 0)
|
||||
encode_quadrant (buf, level, 2, w, h1, f, s_stream, i_stream);
|
||||
if (f1 > 0)
|
||||
encode_quadrant (buf, level, 3, w, h, f1, s_stream, i_stream);
|
||||
if (w1 > 0 && h1 > 0)
|
||||
encode_quadrant (buf, level, 4, w1, h1, f, s_stream, i_stream);
|
||||
if (w1 > 0 && f1 > 0)
|
||||
encode_quadrant (buf, level, 5, w1, h, f1, s_stream, i_stream);
|
||||
if (h1 > 0 && f1 > 0)
|
||||
encode_quadrant (buf, level, 6, w, h1, f1, s_stream, i_stream);
|
||||
if (h1 > 0 && f1 > 0 && f1 > 0)
|
||||
encode_quadrant (buf, level, 7, w1, h1, f1, s_stream, i_stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
decode_quadrant (Wavelet3DBuf * buf,
|
||||
int level, int quadrant, uint32_t w, uint32_t h, uint32_t f,
|
||||
ENTROPY_CODER s_stream[], ENTROPY_CODER i_stream[])
|
||||
{
|
||||
uint32_t x, y, z;
|
||||
|
||||
z = 0;
|
||||
do {
|
||||
y = 0;
|
||||
do {
|
||||
x = 0;
|
||||
do {
|
||||
uint32_t skip;
|
||||
uint32_t index = buf->offset[level][quadrant]
|
||||
+ z * buf->width * buf->height + y * buf->width + x;
|
||||
|
||||
buf->data[index] = decode_coeff (s_stream, i_stream);
|
||||
|
||||
skip = skip_0coeffs (buf, s_stream, i_stream,
|
||||
(w - x - 1) + (h - y - 1) * w + (f - z - 1) * w * h);
|
||||
if (skip > 0) {
|
||||
x += skip;
|
||||
while (x >= w) {
|
||||
y++;
|
||||
x -= w;
|
||||
while (y >= h) {
|
||||
z++;
|
||||
y -= h;
|
||||
if (z >= f)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
x++;
|
||||
} while (x < w);
|
||||
y++;
|
||||
} while (y < h);
|
||||
z++;
|
||||
} while (z < f);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decode_coefficients (Wavelet3DBuf * buf,
|
||||
ENTROPY_CODER s_stream[], ENTROPY_CODER i_stream[])
|
||||
{
|
||||
int level;
|
||||
|
||||
buf->data[0] = decode_coeff (s_stream, i_stream);
|
||||
|
||||
for (level = 0; level < buf->scales - 1; level++) {
|
||||
uint32_t w, h, f, w1, h1, f1;
|
||||
|
||||
w = buf->w[level];
|
||||
h = buf->h[level];
|
||||
f = buf->f[level];
|
||||
w1 = buf->w[level + 1] - w;
|
||||
h1 = buf->h[level + 1] - h;
|
||||
f1 = buf->f[level + 1] - f;
|
||||
|
||||
if (w1 > 0)
|
||||
decode_quadrant (buf, level, 1, w1, h, f, s_stream, i_stream);
|
||||
if (h1 > 0)
|
||||
decode_quadrant (buf, level, 2, w, h1, f, s_stream, i_stream);
|
||||
if (f1 > 0)
|
||||
decode_quadrant (buf, level, 3, w, h, f1, s_stream, i_stream);
|
||||
if (w1 > 0 && h1 > 0)
|
||||
decode_quadrant (buf, level, 4, w1, h1, f, s_stream, i_stream);
|
||||
if (w1 > 0 && f1 > 0)
|
||||
decode_quadrant (buf, level, 5, w1, h, f1, s_stream, i_stream);
|
||||
if (h1 > 0 && f1 > 0)
|
||||
decode_quadrant (buf, level, 6, w, h1, f1, s_stream, i_stream);
|
||||
if (h1 > 0 && f1 > 0 && f1 > 0)
|
||||
decode_quadrant (buf, level, 7, w1, h1, f1, s_stream, i_stream);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
static 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 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++) {
|
||||
uint32_t skip;
|
||||
|
||||
buf->data[i] = decode_coeff (s_stream, i_stream);
|
||||
|
||||
skip = skip_0coeffs (buf, s_stream, i_stream,
|
||||
buf->width * buf->height * buf->frames - i);
|
||||
i += skip;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static uint32_t
|
||||
setup_limittabs (ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[],
|
||||
uint32_t significand_limittab[],
|
||||
uint32_t insignificand_limittab[], uint32_t limit)
|
||||
{
|
||||
uint32_t significand_limit;
|
||||
uint32_t insignificand_limit;
|
||||
uint32_t byte_count;
|
||||
int i;
|
||||
|
||||
assert (limit > 2 * TYPE_BITS * sizeof (uint32_t)); /* limit too small */
|
||||
|
||||
printf ("%s: limit == %u\n", __FUNCTION__, limit);
|
||||
byte_count = 2 * TYPE_BITS * sizeof (uint32_t); /* 2 binary coded limittabs */
|
||||
limit -= byte_count;
|
||||
printf ("%s: rem. limit == %u\n", __FUNCTION__, limit);
|
||||
|
||||
significand_limit = limit * 7 / 8;
|
||||
insignificand_limit = limit - significand_limit;
|
||||
|
||||
printf ("%s: limit == %u\n", __FUNCTION__, limit);
|
||||
printf ("significand limit == %u\n", significand_limit);
|
||||
printf ("insignificand limit == %u\n", insignificand_limit);
|
||||
|
||||
for (i = TYPE_BITS - 1; i >= 0; i--) {
|
||||
uint32_t s_bytes, i_bytes;
|
||||
|
||||
if (i > 0) {
|
||||
significand_limittab[i] = (significand_limit + 1) / 2;
|
||||
insignificand_limittab[i] = (insignificand_limit + 1) / 2;
|
||||
} else {
|
||||
significand_limittab[0] = significand_limit;
|
||||
insignificand_limittab[0] = insignificand_limit;
|
||||
}
|
||||
|
||||
s_bytes = ENTROPY_ENCODER_FLUSH (&significand_bitstream[i]);
|
||||
i_bytes = ENTROPY_ENCODER_FLUSH (&insignificand_bitstream[i]);
|
||||
|
||||
if (s_bytes < significand_limittab[i])
|
||||
significand_limittab[i] = s_bytes;
|
||||
|
||||
if (i_bytes < insignificand_limittab[i])
|
||||
insignificand_limittab[i] = i_bytes;
|
||||
|
||||
byte_count += significand_limittab[i];
|
||||
byte_count += insignificand_limittab[i];
|
||||
|
||||
printf ("insignificand_limittab[%i] == %u / %u\n",
|
||||
i, insignificand_limittab[i], i_bytes);
|
||||
printf (" significand_limittab[%i] == %u / %u\n",
|
||||
i, significand_limittab[i], s_bytes);
|
||||
|
||||
significand_limit -= significand_limittab[i];
|
||||
insignificand_limit -= insignificand_limittab[i];
|
||||
}
|
||||
|
||||
printf ("byte_count == %u\n", byte_count);
|
||||
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write 'em binary for now, should be easy to compress ...
|
||||
*/
|
||||
static uint8_t *
|
||||
write_limittabs (uint8_t * bitstream,
|
||||
uint32_t significand_limittab[], uint32_t insignificand_limittab[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
*(uint32_t *) bitstream = significand_limittab[i];
|
||||
bitstream += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
*(uint32_t *) bitstream = insignificand_limittab[i];
|
||||
bitstream += 4;
|
||||
}
|
||||
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t *
|
||||
read_limittabs (uint8_t * bitstream,
|
||||
uint32_t significand_limittab[], uint32_t insignificand_limittab[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
significand_limittab[i] = *(uint32_t *) bitstream;
|
||||
printf ("significand_limittab[%i] == %u\n", i, significand_limittab[i]);
|
||||
bitstream += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
insignificand_limittab[i] = *(uint32_t *) bitstream;
|
||||
printf ("insignificand_limittab[%i] == %u\n", i,
|
||||
insignificand_limittab[i]);
|
||||
bitstream += 4;
|
||||
}
|
||||
|
||||
return bitstream;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* concatenate entropy coder bitstreams
|
||||
*/
|
||||
static void
|
||||
merge_bitstreams (uint8_t * bitstream,
|
||||
ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[],
|
||||
uint32_t significand_limittab[], uint32_t insignificand_limittab[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = TYPE_BITS - 1; i >= 0; i--) {
|
||||
memcpy (bitstream,
|
||||
ENTROPY_CODER_BITSTREAM (&significand_bitstream[i]),
|
||||
significand_limittab[i]);
|
||||
|
||||
bitstream += significand_limittab[i];
|
||||
}
|
||||
|
||||
for (i = TYPE_BITS - 1; i >= 0; i--) {
|
||||
memcpy (bitstream,
|
||||
ENTROPY_CODER_BITSTREAM (&insignificand_bitstream[i]),
|
||||
insignificand_limittab[i]);
|
||||
|
||||
bitstream += insignificand_limittab[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
split_bitstreams (uint8_t * bitstream,
|
||||
ENTROPY_CODER significand_bitstream[],
|
||||
ENTROPY_CODER insignificand_bitstream[],
|
||||
uint32_t significand_limittab[], uint32_t insignificand_limittab[])
|
||||
{
|
||||
uint32_t byte_count;
|
||||
int i;
|
||||
|
||||
for (i = TYPE_BITS - 1; i >= 0; i--) {
|
||||
byte_count = significand_limittab[i];
|
||||
ENTROPY_DECODER_INIT (&significand_bitstream[i], bitstream, byte_count);
|
||||
bitstream += byte_count;
|
||||
}
|
||||
|
||||
for (i = TYPE_BITS - 1; i >= 0; i--) {
|
||||
byte_count = insignificand_limittab[i];
|
||||
ENTROPY_DECODER_INIT (&insignificand_bitstream[i], bitstream, byte_count);
|
||||
bitstream += byte_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
wavelet_3d_buf_encode_coeff (const Wavelet3DBuf * buf,
|
||||
uint8_t * bitstream, uint32_t limit)
|
||||
{
|
||||
ENTROPY_CODER significand_bitstream[TYPE_BITS];
|
||||
ENTROPY_CODER insignificand_bitstream[TYPE_BITS];
|
||||
uint32_t significand_limittab[TYPE_BITS];
|
||||
uint32_t insignificand_limittab[TYPE_BITS];
|
||||
uint32_t byte_count;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++)
|
||||
ENTROPY_ENCODER_INIT (&significand_bitstream[i], limit);
|
||||
for (i = 0; i < TYPE_BITS; i++)
|
||||
ENTROPY_ENCODER_INIT (&insignificand_bitstream[i], limit);
|
||||
|
||||
encode_coefficients (buf, significand_bitstream, insignificand_bitstream);
|
||||
|
||||
byte_count = setup_limittabs (significand_bitstream, insignificand_bitstream,
|
||||
significand_limittab, insignificand_limittab, limit);
|
||||
|
||||
bitstream = write_limittabs (bitstream,
|
||||
significand_limittab, insignificand_limittab);
|
||||
|
||||
merge_bitstreams (bitstream, significand_bitstream, insignificand_bitstream,
|
||||
significand_limittab, insignificand_limittab);
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
ENTROPY_ENCODER_DONE (&significand_bitstream[i]);
|
||||
ENTROPY_ENCODER_DONE (&insignificand_bitstream[i]);
|
||||
}
|
||||
|
||||
return byte_count;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wavelet_3d_buf_decode_coeff (Wavelet3DBuf * buf,
|
||||
uint8_t * bitstream, uint32_t byte_count)
|
||||
{
|
||||
ENTROPY_CODER significand_bitstream[TYPE_BITS];
|
||||
ENTROPY_CODER insignificand_bitstream[TYPE_BITS];
|
||||
uint32_t significand_limittab[TYPE_BITS];
|
||||
uint32_t insignificand_limittab[TYPE_BITS];
|
||||
int i;
|
||||
|
||||
memset (buf->data, 0, buf->width * buf->height * buf->frames * sizeof (TYPE));
|
||||
|
||||
bitstream = read_limittabs (bitstream,
|
||||
significand_limittab, insignificand_limittab);
|
||||
|
||||
split_bitstreams (bitstream, significand_bitstream, insignificand_bitstream,
|
||||
significand_limittab, insignificand_limittab);
|
||||
|
||||
decode_coefficients (buf, significand_bitstream, insignificand_bitstream);
|
||||
|
||||
for (i = 0; i < TYPE_BITS; i++) {
|
||||
ENTROPY_DECODER_DONE (&significand_bitstream[i]);
|
||||
ENTROPY_DECODER_DONE (&insignificand_bitstream[i]);
|
||||
}
|
||||
}
|
|
@ -1,421 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include <assert.h>
|
||||
#include "wavelet.h"
|
||||
|
||||
|
||||
|
||||
static void
|
||||
fwd_analyze_1 (const TYPE * x, TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
d[i] = x[(2 * i + 1) * stride] - x[2 * i * stride];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fwd_synthesize_1 (const TYPE * x, TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
s[i * stride] = x[2 * i * stride] + d[i] / 2;
|
||||
if (n & 1)
|
||||
s[k * stride] = x[2 * k * stride] + d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
inv_analyze_1 (TYPE * x, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
x[(2 * i + 1) * stride] = d[i] + x[2 * i * stride];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
inv_synthesize_1 (TYPE * x, const TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
x[2 * i * stride] = s[i] - d[i] / 2;
|
||||
if (n & 1)
|
||||
x[2 * k * stride] = s[k] - d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
fwd_analyze_2 (const TYPE * x, TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
if (n & 1) {
|
||||
for (i = 0; i < k; i++)
|
||||
d[i] =
|
||||
x[(2 * i + 1) * stride] - (x[2 * i * stride] + x[(2 * i +
|
||||
2) * stride]) / 2;
|
||||
} else {
|
||||
for (i = 0; i < k - 1; i++)
|
||||
d[i] =
|
||||
x[(2 * i + 1) * stride] - (x[2 * i * stride] + x[(2 * i +
|
||||
2) * stride]) / 2;
|
||||
d[k - 1] = x[(n - 1) * stride] - x[(n - 2) * stride];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
fwd_synthesize_2 (const TYPE * x, TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
s[0] = x[0] + d[1] / 2;
|
||||
for (i = 1; i < k; i++)
|
||||
s[i * stride] = x[2 * i * stride] + (d[i - 1] + d[i]) / 4;
|
||||
if (n & 1)
|
||||
s[k * stride] = x[2 * k * stride] + d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
inv_analyze_2 (TYPE * x, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
if (n & 1) {
|
||||
for (i = 0; i < k; i++)
|
||||
x[(2 * i + 1) * stride] =
|
||||
d[i] + (x[2 * i * stride] + x[(2 * i + 2) * stride]) / 2;
|
||||
} else {
|
||||
for (i = 0; i < k - 1; i++)
|
||||
x[(2 * i + 1) * stride] =
|
||||
d[i] + (x[2 * i * stride] + x[(2 * i + 2) * stride]) / 2;
|
||||
x[(n - 1) * stride] = d[k - 1] + x[(n - 2) * stride];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
inv_synthesize_2 (TYPE * x, const TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
x[0] = s[0] - d[1] / 2;
|
||||
for (i = 1; i < k; i++)
|
||||
x[2 * i * stride] = s[i] - (d[i - 1] + d[i]) / 4;
|
||||
if (n & 1)
|
||||
x[2 * k * stride] = s[k] - d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
fwd_analyze_4 (const TYPE * x, TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
d[0] = x[stride] - (x[0] + x[2 * stride]) / 2;
|
||||
|
||||
if (n & 1) {
|
||||
for (i = 1; i < k - 1; i++)
|
||||
d[i] = x[(2 * i + 1) * stride]
|
||||
- ((uint32_t) 9 * (x[2 * i * stride] + x[(2 * i + 2) * stride])
|
||||
- (x[(2 * i - 2) * stride] + x[(2 * i + 4) * stride])) / 16;
|
||||
if (k > 1)
|
||||
d[k - 1] =
|
||||
x[(2 * k - 1) * stride] - (x[(2 * k - 2) * stride] +
|
||||
x[2 * k * stride]) / 2;
|
||||
} else {
|
||||
for (i = 1; i < k - 2; i++)
|
||||
d[i] = x[(2 * i + 1) * stride]
|
||||
- ((uint32_t) 9 * (x[2 * i * stride] + x[(2 * i + 2) * stride])
|
||||
- (x[(2 * i - 2) * stride] + x[(2 * i + 4) * stride])) / 16;
|
||||
if (k > 2)
|
||||
d[k - 2] = x[(2 * k - 3) * stride] - (x[(2 * k - 4) * stride]
|
||||
+ x[(2 * k - 2) * stride]) / 2;
|
||||
if (k > 1)
|
||||
d[k - 1] = x[(n - 1) * stride] - x[(n - 2) * stride];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fwd_synthesize_4 (const TYPE * x, TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
s[0] = x[0] + d[1] / 2;
|
||||
if (k > 1)
|
||||
s[stride] = x[2 * stride] + (d[0] + d[1]) / 4;
|
||||
for (i = 2; i < k - 1; i++)
|
||||
s[i * stride] = x[2 * i * stride]
|
||||
+ ((uint32_t) 9 * (d[i - 1] + d[i]) - (d[i - 2] + d[i + 1])) / 32;
|
||||
if (k > 2)
|
||||
s[(k - 1) * stride] = x[(2 * k - 2) * stride] + (d[k - 2] + d[k - 1]) / 4;
|
||||
if (n & 1)
|
||||
s[k * stride] = x[2 * k * stride] + d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
inv_analyze_4 (TYPE * x, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
x[stride] = d[0] + (x[0] + x[2 * stride]) / 2;
|
||||
|
||||
if (n & 1) {
|
||||
for (i = 1; i < k - 1; i++)
|
||||
x[(2 * i + 1) * stride] = d[i]
|
||||
+ ((uint32_t) 9 * (x[2 * i * stride] + x[(2 * i + 2) * stride])
|
||||
- (x[(2 * i - 2) * stride] + x[(2 * i + 4) * stride])) / 16;
|
||||
if (k > 1)
|
||||
x[(2 * k - 1) * stride] =
|
||||
d[k - 1] + (x[(2 * k - 2) * stride] + x[2 * k * stride]) / 2;
|
||||
} else {
|
||||
for (i = 1; i < k - 2; i++)
|
||||
x[(2 * i + 1) * stride] = d[i]
|
||||
+ (9 * (x[2 * i * stride] + x[(2 * i + 2) * stride])
|
||||
- (x[(2 * i - 2) * stride] + x[(2 * i + 4) * stride])) / 16;
|
||||
if (k > 2)
|
||||
x[(2 * k - 3) * stride] = d[k - 2] + (x[(2 * k - 4) * stride]
|
||||
+ x[(2 * k - 2) * stride]) / 2;
|
||||
if (k > 1)
|
||||
x[(n - 1) * stride] = d[k - 1] + x[(n - 2) * stride];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
inv_synthesize_4 (TYPE * x, const TYPE * s, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, k = n / 2;
|
||||
|
||||
x[0] = s[0] - d[1] / 2;
|
||||
if (k > 1)
|
||||
x[2 * stride] = s[1] - (d[0] + d[1]) / 4;
|
||||
for (i = 2; i < k - 1; i++)
|
||||
x[2 * i * stride] = s[i] - ((uint32_t) 9 * (d[i - 1] + d[i])
|
||||
- (d[i - 2] + d[i + 1])) / 32;
|
||||
if (k > 2)
|
||||
x[(2 * k - 2) * stride] = s[k - 1] - (d[k - 2] + d[k - 1]) / 4;
|
||||
if (n & 1)
|
||||
x[2 * k * stride] = s[k] - d[k - 1] / 2;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
copyback_d (TYPE * x, const TYPE * d, int stride, int n)
|
||||
{
|
||||
int i, j, k = n / 2;
|
||||
|
||||
for (i = n - k, j = 0; i < n; i++, j++)
|
||||
x[i * stride] = d[j];
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
copy_s_d (const TYPE * x, TYPE * s_d, int stride, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
s_d[i] = x[i * stride];
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef
|
||||
void (*FwdSFnc) (const TYPE * x, TYPE * s, const TYPE * d, int stride,
|
||||
int n);
|
||||
|
||||
typedef void (*FwdAFnc) (const TYPE * x, TYPE * d, int stride, int n);
|
||||
|
||||
typedef
|
||||
void (*InvSFnc) (TYPE * x, const TYPE * s, const TYPE * d, int stride,
|
||||
int n);
|
||||
|
||||
typedef void (*InvAFnc) (TYPE * x, const TYPE * d, int stride, int n);
|
||||
|
||||
|
||||
|
||||
static FwdSFnc fwd_synthesize[] = { NULL, fwd_synthesize_1, fwd_synthesize_2,
|
||||
NULL, fwd_synthesize_4
|
||||
};
|
||||
|
||||
static FwdAFnc fwd_analyze[] = { NULL, fwd_analyze_1, fwd_analyze_2,
|
||||
NULL, fwd_analyze_4
|
||||
};
|
||||
|
||||
static InvSFnc inv_synthesize[] = { NULL, inv_synthesize_1, inv_synthesize_2,
|
||||
NULL, inv_synthesize_4
|
||||
};
|
||||
|
||||
static InvAFnc inv_analyze[] = { NULL, inv_analyze_1, inv_analyze_2,
|
||||
NULL, inv_analyze_4
|
||||
};
|
||||
|
||||
|
||||
|
||||
static inline void
|
||||
fwd_xform (TYPE * scratchbuf, TYPE * data, int stride, int n,
|
||||
int a_moments, int s_moments)
|
||||
{
|
||||
TYPE *x = data;
|
||||
TYPE *d = scratchbuf;
|
||||
TYPE *s = data;
|
||||
|
||||
assert (a_moments == 1 || a_moments == 2 || a_moments == 4);
|
||||
assert (s_moments == 1 || s_moments == 2 || s_moments == 4);
|
||||
|
||||
/* XXX FIXME: Ugly hack to work around */
|
||||
/* the short-row bug in high */
|
||||
/* order xform functions */
|
||||
if (n < 9)
|
||||
a_moments = s_moments = 2;
|
||||
if (n < 5)
|
||||
a_moments = s_moments = 1;
|
||||
|
||||
fwd_analyze[a_moments] (x, d, stride, n);
|
||||
fwd_synthesize[s_moments] (x, s, d, stride, n);
|
||||
copyback_d (x, d, stride, n);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
inv_xform (TYPE * scratchbuf, TYPE * data, int stride, int n,
|
||||
int a_moments, int s_moments)
|
||||
{
|
||||
int k = n / 2;
|
||||
TYPE *x = data;
|
||||
TYPE *s = scratchbuf;
|
||||
TYPE *d = scratchbuf + n - k;
|
||||
|
||||
assert (a_moments == 1 || a_moments == 2 || a_moments == 4);
|
||||
assert (s_moments == 1 || s_moments == 2 || s_moments == 4);
|
||||
|
||||
/* XXX FIXME: Ugly hack to work around */
|
||||
/* the short-row bug in high */
|
||||
/* order xform functions */
|
||||
if (n < 9)
|
||||
a_moments = s_moments = 2;
|
||||
if (n < 5)
|
||||
a_moments = s_moments = 1;
|
||||
|
||||
copy_s_d (data, scratchbuf, stride, n);
|
||||
inv_synthesize[s_moments] (x, s, d, stride, n);
|
||||
inv_analyze[a_moments] (x, d, stride, n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
wavelet_3d_buf_fwd_xform (Wavelet3DBuf * buf, int a_moments, int s_moments)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = buf->scales - 1; level > 0; level--) {
|
||||
uint32_t w = buf->w[level];
|
||||
uint32_t h = buf->h[level];
|
||||
uint32_t f = buf->f[level];
|
||||
|
||||
if (w > 1) {
|
||||
int row, frame;
|
||||
|
||||
for (frame = 0; frame < f; frame++) {
|
||||
for (row = 0; row < h; row++) {
|
||||
TYPE *data = buf->data + (frame * buf->height + row) * buf->width;
|
||||
|
||||
fwd_xform (buf->scratchbuf, data, 1, w, a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (h > 1) {
|
||||
int col, frame;
|
||||
|
||||
for (frame = 0; frame < f; frame++) {
|
||||
for (col = 0; col < w; col++) {
|
||||
TYPE *data = buf->data + frame * buf->width * buf->height + col;
|
||||
|
||||
fwd_xform (buf->scratchbuf, data, buf->width, h,
|
||||
a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (f > 1) {
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w; i++) {
|
||||
TYPE *data = buf->data + j * buf->width + i;
|
||||
|
||||
fwd_xform (buf->scratchbuf, data, buf->width * buf->height, f,
|
||||
a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wavelet_3d_buf_inv_xform (Wavelet3DBuf * buf, int a_moments, int s_moments)
|
||||
{
|
||||
int level;
|
||||
|
||||
for (level = 1; level < buf->scales; level++) {
|
||||
uint32_t w = buf->w[level];
|
||||
uint32_t h = buf->h[level];
|
||||
uint32_t f = buf->f[level];
|
||||
|
||||
if (f > 1) {
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w; i++) {
|
||||
TYPE *data = buf->data + j * buf->width + i;
|
||||
|
||||
inv_xform (buf->scratchbuf, data, buf->width * buf->height, f,
|
||||
a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (h > 1) {
|
||||
int col, frame;
|
||||
|
||||
for (frame = 0; frame < f; frame++) {
|
||||
for (col = 0; col < w; col++) {
|
||||
TYPE *data = buf->data + frame * buf->width * buf->height + col;
|
||||
|
||||
inv_xform (buf->scratchbuf, data, buf->width, h,
|
||||
a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (w > 1) {
|
||||
int row, frame;
|
||||
|
||||
for (frame = 0; frame < f; frame++) {
|
||||
for (row = 0; row < h; row++) {
|
||||
TYPE *data = buf->data + (frame * buf->height + row) * buf->width;
|
||||
|
||||
inv_xform (buf->scratchbuf, data, 1, w, a_moments, s_moments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
234
ext/tarkin/yuv.c
234
ext/tarkin/yuv.c
|
@ -1,234 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "yuv.h"
|
||||
|
||||
/*#define TARKIN_YUV_EXACT*/
|
||||
/*#define TARKIN_YUV_LXY*/
|
||||
|
||||
|
||||
static inline uint8_t
|
||||
CLAMP (int16_t x)
|
||||
{
|
||||
return ((x > 255) ? 255 : (x < 0) ? 0 : x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 += 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;
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgb += 3) {
|
||||
y[i] = ((int16_t) 54 * rgb[0] + 182 * rgb[1] + 18 * rgb[2]) / 256;
|
||||
u[i] = rgb[0] - y[i];
|
||||
v[i] = rgb[2] - y[i];
|
||||
}
|
||||
#else
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
yuv_to_rgb24 (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 += 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]);
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgb += 3) {
|
||||
rgb[1] = CLAMP (y[i] - (76 * u[i] - 26 * v[i]) / 256);
|
||||
rgb[0] = CLAMP (y[i] + u[i]);
|
||||
rgb[2] = CLAMP (y[i] + v[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;
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgb += 4) {
|
||||
y[i] = ((int16_t) 54 * rgb[0] + 182 * rgb[1] + 18 * rgb[2]) / 256;
|
||||
u[i] = rgb[0] - y[i];
|
||||
v[i] = rgb[2] - y[i];
|
||||
}
|
||||
#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_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 += 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]);
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgb += 4) {
|
||||
rgb[1] = CLAMP (y[i] - (76 * u[i] - 26 * v[i]) / 256);
|
||||
rgb[0] = CLAMP (y[i] + u[i]);
|
||||
rgb[2] = CLAMP (y[i] + v[i]);
|
||||
}
|
||||
#else
|
||||
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];
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgba += 4) {
|
||||
y[i] = ((int16_t) 54 * rgba[0] + 182 * rgba[1] + 18 * rgba[2]) / 256;
|
||||
u[i] = rgba[0] - y[i];
|
||||
v[i] = rgba[2] - y[i];
|
||||
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];
|
||||
}
|
||||
#elif defined(TARKIN_YUV_LXY)
|
||||
for (i = 0; i < count; i++, rgba += 4) {
|
||||
rgba[1] = CLAMP (y[i] - (76 * u[i] - 26 * v[i]) / 256);
|
||||
rgba[0] = CLAMP (y[i] + u[i]);
|
||||
rgba[2] = CLAMP (y[i] + v[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,21 +0,0 @@
|
|||
|
||||
#ifndef __YUV_H
|
||||
#define __YUV_H
|
||||
|
||||
#include "_stdint.h"
|
||||
#include "wavelet.h"
|
||||
|
||||
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,16 +0,0 @@
|
|||
### FIXME: rename directory to theoraexp
|
||||
|
||||
plugin_LTLIBRARIES = libgsttheoraexp.la
|
||||
|
||||
noinst_HEADERS = theoradec.h
|
||||
|
||||
libgsttheoraexp_la_SOURCES = theoradec.c
|
||||
libgsttheoraexp_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(THEORADEC_CFLAGS)
|
||||
libgsttheoraexp_la_LIBADD = \
|
||||
$(GST_PLUGINS_BASE_LIBS) \
|
||||
-lgsttag-$(GST_MAJORMINOR) \
|
||||
$(GST_LIBS) \
|
||||
$(THEORADEC_LIBS)
|
||||
libgsttheoraexp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgsttheoraexp_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,99 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
* 2006 Michael Smith <msmith@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_THEORADEC_H__
|
||||
#define __GST_THEORADEC_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <theora/theoradec.h>
|
||||
#include <string.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_THEORA_DEC_EXP \
|
||||
(gst_theoradec_get_type())
|
||||
#define GST_THEORA_DEC_EXP(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_DEC_EXP,GstTheoraExpDec))
|
||||
#define GST_THEORA_DEC_EXP_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_DEC_EXP,GstTheoraExpDecClass))
|
||||
#define GST_IS_THEORA_DEC_EXP(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_DEC_EXP))
|
||||
#define GST_IS_THEORA_DEC_EXP_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_DEC_EXP))
|
||||
|
||||
typedef struct _GstTheoraExpDec GstTheoraExpDec;
|
||||
typedef struct _GstTheoraExpDecClass GstTheoraExpDecClass;
|
||||
|
||||
/**
|
||||
* GstTheoraExpDec:
|
||||
*
|
||||
* Decoder using theora-exp
|
||||
*/
|
||||
struct _GstTheoraExpDec
|
||||
{
|
||||
/* <private> */
|
||||
GstElement element;
|
||||
|
||||
/* Pads */
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
/* theora decoder state */
|
||||
th_dec_ctx *dec;
|
||||
th_setup_info *setup;
|
||||
|
||||
th_info info;
|
||||
th_comment comment;
|
||||
|
||||
gboolean have_header;
|
||||
guint64 granulepos;
|
||||
guint64 granule_shift;
|
||||
|
||||
GstClockTime last_timestamp;
|
||||
gboolean need_keyframe;
|
||||
gint width, height;
|
||||
gint offset_x, offset_y;
|
||||
gint output_bpp;
|
||||
|
||||
int frame_nr;
|
||||
gboolean discont;
|
||||
|
||||
GList *queued;
|
||||
|
||||
/* segment info */ /* with STREAM_LOCK */
|
||||
GstSegment segment;
|
||||
|
||||
/* QoS stuff */ /* with LOCK*/
|
||||
gboolean proportion;
|
||||
GstClockTime earliest_time;
|
||||
};
|
||||
|
||||
struct _GstTheoraExpDecClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_THEORADEC_H__ */
|
|
@ -1,5 +1,5 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2011 FIXME <fixme@example.com>
|
||||
* Copyright (C) 2011 David Schleef <ds@schleef.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
|
Loading…
Reference in a new issue