mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
240 lines
8.7 KiB
C
240 lines
8.7 KiB
C
|
#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
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|