mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
ext/jpeg/: Updated smoke, new bitstream, allows embedding in ogg.
Original commit message from CVS: * ext/jpeg/gstjpeg.c: (smoke_type_find), (plugin_init): * ext/jpeg/gstsmokedec.c: (gst_smokedec_init), (gst_smokedec_chain): * ext/jpeg/gstsmokedec.h: * ext/jpeg/gstsmokeenc.c: (gst_smokeenc_class_init), (gst_smokeenc_init), (gst_smokeenc_resync), (gst_smokeenc_chain): * ext/jpeg/gstsmokeenc.h: * ext/jpeg/smokecodec.c: (smokecodec_encode_new), (smokecodec_decode_new), (smokecodec_info_free), (smokecodec_set_quality), (smokecodec_get_quality), (smokecodec_set_threshold), (smokecodec_get_threshold), (smokecodec_set_bitrate), (smokecodec_get_bitrate), (find_best_size), (abs_diff), (put), (smokecodec_encode_id), (smokecodec_encode), (smokecodec_parse_id), (smokecodec_parse_header), (smokecodec_decode): * ext/jpeg/smokecodec.h: * ext/jpeg/smokeformat.h: Updated smoke, new bitstream, allows embedding in ogg.
This commit is contained in:
parent
d2ba80e45e
commit
b90716dd18
9 changed files with 302 additions and 50 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
2004-10-04 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/jpeg/gstjpeg.c: (smoke_type_find), (plugin_init):
|
||||
* ext/jpeg/gstsmokedec.c: (gst_smokedec_init),
|
||||
(gst_smokedec_chain):
|
||||
* ext/jpeg/gstsmokedec.h:
|
||||
* ext/jpeg/gstsmokeenc.c: (gst_smokeenc_class_init),
|
||||
(gst_smokeenc_init), (gst_smokeenc_resync), (gst_smokeenc_chain):
|
||||
* ext/jpeg/gstsmokeenc.h:
|
||||
* ext/jpeg/smokecodec.c: (smokecodec_encode_new),
|
||||
(smokecodec_decode_new), (smokecodec_info_free),
|
||||
(smokecodec_set_quality), (smokecodec_get_quality),
|
||||
(smokecodec_set_threshold), (smokecodec_get_threshold),
|
||||
(smokecodec_set_bitrate), (smokecodec_get_bitrate),
|
||||
(find_best_size), (abs_diff), (put), (smokecodec_encode_id),
|
||||
(smokecodec_encode), (smokecodec_parse_id),
|
||||
(smokecodec_parse_header), (smokecodec_decode):
|
||||
* ext/jpeg/smokecodec.h:
|
||||
* ext/jpeg/smokeformat.h:
|
||||
Updated smoke, new bitstream, allows embedding in ogg.
|
||||
|
||||
2004-10-04 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_event):
|
||||
|
|
|
@ -19,12 +19,30 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "gstjpegdec.h"
|
||||
#include "gstjpegenc.h"
|
||||
#include "gstsmokeenc.h"
|
||||
#include "gstsmokedec.h"
|
||||
|
||||
static GstStaticCaps smoke_caps = GST_STATIC_CAPS ("video/x-smoke");
|
||||
|
||||
#define SMOKE_CAPS (gst_static_caps_get(&smoke_caps))
|
||||
static void
|
||||
smoke_type_find (GstTypeFind * tf, gpointer private)
|
||||
{
|
||||
guint8 *data = gst_type_find_peek (tf, 0, 6);
|
||||
|
||||
if (data) {
|
||||
if (data[0] != 0x80)
|
||||
return;
|
||||
if (memcmp (&data[1], "smoke", 5) != 0)
|
||||
return;
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SMOKE_CAPS);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
@ -44,6 +62,10 @@ plugin_init (GstPlugin * plugin)
|
|||
GST_TYPE_SMOKEDEC))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_type_find_register (plugin, "video/x-smoke", GST_RANK_PRIMARY,
|
||||
smoke_type_find, NULL, SMOKE_CAPS, NULL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
/* elementfactory information */
|
||||
GstElementDetails gst_smokedec_details = {
|
||||
"Smoke image decoder",
|
||||
"Smoke video decoder",
|
||||
"Codec/Decoder/Image",
|
||||
"Decode images from Smoke format",
|
||||
"Decode video from Smoke format",
|
||||
"Wim Taymans <wim@fluendo.com>",
|
||||
};
|
||||
|
||||
|
@ -98,7 +98,7 @@ static GstStaticPadTemplate gst_smokedec_sink_pad_template =
|
|||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("image/x-smoke, "
|
||||
GST_STATIC_CAPS ("video/x-smoke, "
|
||||
"width = (int) [ 16, 4096 ], "
|
||||
"height = (int) [ 16, 4096 ], " "framerate = (double) [ 1, MAX ]")
|
||||
);
|
||||
|
@ -150,6 +150,7 @@ gst_smokedec_init (GstSmokeDec * smokedec)
|
|||
smokedec->format = -1;
|
||||
smokedec->width = -1;
|
||||
smokedec->height = -1;
|
||||
smokedec->next_time = 0;
|
||||
}
|
||||
|
||||
static GstPadLinkReturn
|
||||
|
@ -189,9 +190,10 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
|
|||
gulong size, outsize;
|
||||
GstBuffer *outbuf;
|
||||
SmokeCodecFlags flags;
|
||||
GstClockTime time;
|
||||
|
||||
/*GstMeta *meta; */
|
||||
gint width, height;
|
||||
gint fps_num, fps_denom;
|
||||
|
||||
smokedec = GST_SMOKEDEC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
|
@ -202,17 +204,36 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
|
|||
|
||||
data = (guchar *) GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
time = GST_BUFFER_TIMESTAMP (buf);
|
||||
|
||||
GST_DEBUG ("gst_smokedec_chain: got buffer of %ld bytes in '%s'", size,
|
||||
GST_OBJECT_NAME (smokedec));
|
||||
|
||||
if (data[0] == SMOKECODEC_TYPE_ID) {
|
||||
smokecodec_parse_id (smokedec->info, data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
GST_DEBUG ("gst_smokedec_chain: reading header %08lx", *(gulong *) data);
|
||||
smokecodec_parse_header (smokedec->info, data, size, &flags, &width, &height);
|
||||
smokecodec_parse_header (smokedec->info, data, size, &flags, &width, &height,
|
||||
&fps_num, &fps_denom);
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
outsize = GST_BUFFER_SIZE (outbuf) = width * height + width * height / 2;
|
||||
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize);
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
|
||||
|
||||
GST_BUFFER_DURATION (outbuf) = GST_SECOND * fps_denom / fps_num;
|
||||
GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
|
||||
|
||||
if (time == GST_CLOCK_TIME_NONE) {
|
||||
if (GST_BUFFER_OFFSET (buf) == -1) {
|
||||
time = smokedec->next_time;
|
||||
} else {
|
||||
time = GST_BUFFER_OFFSET (buf) * GST_BUFFER_DURATION (outbuf);
|
||||
}
|
||||
}
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = time;
|
||||
smokedec->next_time = time + GST_BUFFER_DURATION (outbuf);
|
||||
|
||||
if (smokedec->height != height) {
|
||||
GstCaps *caps;
|
||||
|
@ -223,15 +244,26 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
|
|||
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
|
||||
"width", G_TYPE_INT, width,
|
||||
"height", G_TYPE_INT, height,
|
||||
"framerate", G_TYPE_DOUBLE, smokedec->fps, NULL);
|
||||
"framerate", G_TYPE_DOUBLE, ((double) fps_num) / fps_denom, NULL);
|
||||
gst_pad_set_explicit_caps (smokedec->srcpad, caps);
|
||||
gst_caps_free (caps);
|
||||
}
|
||||
|
||||
smokecodec_decode (smokedec->info, data, size, outdata);
|
||||
if (smokedec->need_keyframe) {
|
||||
if (flags & SMOKECODEC_KEYFRAME) {
|
||||
smokedec->need_keyframe = FALSE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (smokedec, "dropping buffer while waiting for keyframe");
|
||||
gst_buffer_unref (buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG ("gst_smokedec_chain: sending buffer");
|
||||
gst_pad_push (smokedec->srcpad, GST_DATA (outbuf));
|
||||
if (!smokedec->need_keyframe) {
|
||||
smokecodec_decode (smokedec->info, data, size, outdata);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
GST_DEBUG ("gst_smokedec_chain: sending buffer");
|
||||
gst_pad_push (smokedec->srcpad, GST_DATA (outbuf));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,12 +55,15 @@ struct _GstSmokeDec {
|
|||
gint width;
|
||||
gint height;
|
||||
gdouble fps;
|
||||
GstClockTime next_time;
|
||||
|
||||
SmokeCodecInfo *info;
|
||||
|
||||
gint threshold;
|
||||
gint quality;
|
||||
gint smoothing;
|
||||
|
||||
gboolean need_keyframe;
|
||||
};
|
||||
|
||||
struct _GstSmokeDecClass {
|
||||
|
|
|
@ -186,6 +186,7 @@ gst_smokeenc_init (GstSmokeEnc * smokeenc)
|
|||
smokeenc->width = 0;
|
||||
smokeenc->height = 0;
|
||||
smokeenc->frame = 0;
|
||||
smokeenc->need_header = TRUE;
|
||||
|
||||
gst_smokeenc_resync (smokeenc);
|
||||
|
||||
|
@ -264,9 +265,21 @@ gst_smokeenc_link (GstPad * pad, const GstCaps * caps)
|
|||
static void
|
||||
gst_smokeenc_resync (GstSmokeEnc * smokeenc)
|
||||
{
|
||||
GValue fps = { 0 };
|
||||
GValue framerate = { 0 };
|
||||
|
||||
GST_DEBUG ("gst_smokeenc_resync: resync");
|
||||
|
||||
smokecodec_encode_new (&smokeenc->info, smokeenc->width, smokeenc->height);
|
||||
g_value_init (&fps, G_TYPE_DOUBLE);
|
||||
g_value_init (&framerate, GST_TYPE_FRACTION);
|
||||
g_value_set_double (&fps, smokeenc->fps);
|
||||
g_value_transform (&fps, &framerate);
|
||||
|
||||
smokeenc->fps_num = gst_value_get_fraction_numerator (&framerate);
|
||||
smokeenc->fps_denom = gst_value_get_fraction_denominator (&framerate);
|
||||
|
||||
smokecodec_encode_new (&smokeenc->info, smokeenc->width, smokeenc->height,
|
||||
smokeenc->fps_num, smokeenc->fps_denom);
|
||||
smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
|
||||
smokeenc->max_quality);
|
||||
|
||||
|
@ -292,19 +305,33 @@ gst_smokeenc_chain (GstPad * pad, GstData * _data)
|
|||
GST_DEBUG ("gst_smokeenc_chain: got buffer of %ld bytes in '%s'", size,
|
||||
GST_OBJECT_NAME (smokeenc));
|
||||
|
||||
if (smokeenc->need_header) {
|
||||
outbuf = gst_buffer_new ();
|
||||
outsize = 256;
|
||||
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize);
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
|
||||
|
||||
smokecodec_encode_id (smokeenc->info, outdata, &encsize);
|
||||
|
||||
GST_BUFFER_SIZE (outbuf) = encsize;
|
||||
|
||||
gst_pad_push (smokeenc->srcpad, GST_DATA (outbuf));
|
||||
|
||||
smokeenc->need_header = FALSE;
|
||||
}
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
outsize = smokeenc->width * smokeenc->height * 3;
|
||||
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize);
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
|
||||
GST_BUFFER_DURATION (outbuf) =
|
||||
smokeenc->fps_denom * GST_SECOND / smokeenc->fps_num;
|
||||
|
||||
flags = 0;
|
||||
if (smokeenc->frame == 0) {
|
||||
if ((smokeenc->frame % smokeenc->keyframe) == 0) {
|
||||
flags |= SMOKECODEC_KEYFRAME;
|
||||
}
|
||||
|
||||
smokeenc->frame = (smokeenc->frame + 1) % smokeenc->keyframe;
|
||||
|
||||
smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
|
||||
smokeenc->max_quality);
|
||||
smokecodec_set_threshold (smokeenc->info, smokeenc->threshold);
|
||||
|
@ -312,9 +339,12 @@ gst_smokeenc_chain (GstPad * pad, GstData * _data)
|
|||
gst_buffer_unref (buf);
|
||||
|
||||
GST_BUFFER_SIZE (outbuf) = encsize;
|
||||
//memset(GST_BUFFER_DATA(outbuf)+encsize, 0, outsize - encsize);
|
||||
GST_BUFFER_OFFSET (outbuf) = smokeenc->frame;
|
||||
GST_BUFFER_OFFSET_END (outbuf) = smokeenc->frame + 1;
|
||||
|
||||
gst_pad_push (smokeenc->srcpad, GST_DATA (outbuf));
|
||||
|
||||
smokeenc->frame++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -57,12 +57,15 @@ struct _GstSmokeEnc {
|
|||
gint frame;
|
||||
gint keyframe;
|
||||
gdouble fps;
|
||||
gint fps_num, fps_denom;
|
||||
|
||||
SmokeCodecInfo *info;
|
||||
|
||||
gint threshold;
|
||||
gint min_quality;
|
||||
gint max_quality;
|
||||
|
||||
gboolean need_header;
|
||||
};
|
||||
|
||||
struct _GstSmokeEncClass {
|
||||
|
|
|
@ -34,15 +34,17 @@
|
|||
#include <jpeglib.h>
|
||||
|
||||
#include "smokecodec.h"
|
||||
#include "smokeformat.h"
|
||||
|
||||
//#define DEBUG(a...) printf( a );
|
||||
#define DEBUG(a,...)
|
||||
|
||||
|
||||
struct _SmokeCodecInfo
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int fps_num;
|
||||
unsigned int fps_denom;
|
||||
|
||||
unsigned int minquality;
|
||||
unsigned int maxquality;
|
||||
|
@ -112,7 +114,9 @@ smokecodec_term_source (j_decompress_ptr cinfo)
|
|||
|
||||
int
|
||||
smokecodec_encode_new (SmokeCodecInfo ** info,
|
||||
const unsigned int width, const unsigned int height)
|
||||
const unsigned int width,
|
||||
const unsigned int height,
|
||||
const unsigned int fps_num, const unsigned int fps_denom)
|
||||
{
|
||||
SmokeCodecInfo *newinfo;
|
||||
int i, j;
|
||||
|
@ -129,6 +133,8 @@ smokecodec_encode_new (SmokeCodecInfo ** info,
|
|||
}
|
||||
newinfo->width = width;
|
||||
newinfo->height = height;
|
||||
newinfo->fps_num = fps_num;
|
||||
newinfo->fps_denom = fps_denom;
|
||||
|
||||
/* setup jpeglib */
|
||||
memset (&newinfo->cinfo, 0, sizeof (newinfo->cinfo));
|
||||
|
@ -200,7 +206,7 @@ smokecodec_encode_new (SmokeCodecInfo ** info,
|
|||
int
|
||||
smokecodec_decode_new (SmokeCodecInfo ** info)
|
||||
{
|
||||
return smokecodec_encode_new (info, 16, 16);
|
||||
return smokecodec_encode_new (info, 16, 16, 1, 1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -348,6 +354,25 @@ put (const unsigned char *src, unsigned char *dest,
|
|||
}
|
||||
|
||||
/* encoding */
|
||||
SmokeCodecResult
|
||||
smokecodec_encode_id (SmokeCodecInfo * info,
|
||||
unsigned char *out, unsigned int *outsize)
|
||||
{
|
||||
int i;
|
||||
|
||||
*out++ = SMOKECODEC_TYPE_ID;
|
||||
for (i = 0; i < strlen (SMOKECODEC_ID_STRING); i++) {
|
||||
*out++ = SMOKECODEC_ID_STRING[i];
|
||||
}
|
||||
*out++ = 0;
|
||||
*out++ = 1;
|
||||
*out++ = 0;
|
||||
|
||||
*outsize = 9;
|
||||
|
||||
return SMOKECODEC_OK;
|
||||
}
|
||||
|
||||
SmokeCodecResult
|
||||
smokecodec_encode (SmokeCodecInfo * info,
|
||||
const unsigned char *in,
|
||||
|
@ -384,13 +409,24 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
|
||||
max = blocks_w * blocks_h;
|
||||
|
||||
out[IDX_TYPE] = SMOKECODEC_TYPE_DATA;
|
||||
|
||||
#define STORE16(var, pos, x) \
|
||||
var[pos] = (x >> 8); \
|
||||
var[pos] = (x >> 8); \
|
||||
var[pos+1] = (x & 0xff);
|
||||
#define STORE32(var, pos, x) \
|
||||
var[pos] = ((x >> 24) & 0xff); \
|
||||
var[pos+1] = ((x >> 16) & 0xff); \
|
||||
var[pos+2] = ((x >> 8) & 0xff); \
|
||||
var[pos+3] = (x & 0xff);
|
||||
|
||||
/* write dimension */
|
||||
STORE16 (out, 0, width);
|
||||
STORE16 (out, 2, height);
|
||||
STORE16 (out, IDX_WIDTH, width);
|
||||
STORE16 (out, IDX_HEIGHT, height);
|
||||
|
||||
/* write framerate */
|
||||
STORE32 (out, IDX_FPS_NUM, info->fps_num);
|
||||
STORE32 (out, IDX_FPS_DENOM, info->fps_denom);
|
||||
|
||||
if (!(flags & SMOKECODEC_KEYFRAME)) {
|
||||
int block = 0;
|
||||
|
@ -400,7 +436,7 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
for (j = 0; j < width; j += 2 * DCTSIZE) {
|
||||
s = abs_diff (ip, op, width);
|
||||
if (s >= threshold) {
|
||||
STORE16 (out, blocks * 2 + 10, block);
|
||||
STORE16 (out, blocks * 2 + IDX_BLOCKS, block);
|
||||
blocks++;
|
||||
}
|
||||
|
||||
|
@ -422,13 +458,13 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
blocks = 0;
|
||||
encoding = max;
|
||||
}
|
||||
STORE16 (out, 6, blocks);
|
||||
out[4] = (flags & 0xff);
|
||||
STORE16 (out, IDX_NUM_BLOCKS, blocks);
|
||||
out[IDX_FLAGS] = (flags & 0xff);
|
||||
|
||||
DEBUG ("blocks %d, encoding %d\n", blocks, encoding);
|
||||
|
||||
info->jdest.next_output_byte = &out[blocks * 2 + 12];
|
||||
info->jdest.free_in_buffer = (*outsize) - 12;
|
||||
info->jdest.next_output_byte = &out[blocks * 2 + OFFS_PICT];
|
||||
info->jdest.free_in_buffer = (*outsize) - OFFS_PICT;
|
||||
|
||||
if (encoding > 0) {
|
||||
int quality;
|
||||
|
@ -461,7 +497,7 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
if (flags & SMOKECODEC_KEYFRAME)
|
||||
pos = i;
|
||||
else
|
||||
pos = (out[i * 2 + 10] << 8) | (out[i * 2 + 11]);
|
||||
pos = (out[i * 2 + IDX_BLOCKS] << 8) | (out[i * 2 + IDX_BLOCKS + 1]);
|
||||
|
||||
x = pos % (width / (DCTSIZE * 2));
|
||||
y = pos / (width / (DCTSIZE * 2));
|
||||
|
@ -488,11 +524,10 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
jpeg_finish_compress (&info->cinfo);
|
||||
}
|
||||
|
||||
size = ((((*outsize) - 12 - info->jdest.free_in_buffer) + 3) & ~3);
|
||||
out[8] = size >> 8;
|
||||
out[9] = size & 0xff;
|
||||
size = ((((*outsize) - OFFS_PICT - info->jdest.free_in_buffer) + 3) & ~3);
|
||||
STORE16 (out, IDX_SIZE, size);
|
||||
|
||||
*outsize = size + blocks * 2 + 12;
|
||||
*outsize = size + blocks * 2 + OFFS_PICT;
|
||||
DEBUG ("outsize %d\n", *outsize);
|
||||
|
||||
// and decode in reference frame again
|
||||
|
@ -505,24 +540,62 @@ smokecodec_encode (SmokeCodecInfo * info,
|
|||
return SMOKECODEC_OK;
|
||||
}
|
||||
|
||||
SmokeCodecResult
|
||||
smokecodec_parse_id (SmokeCodecInfo * info,
|
||||
const unsigned char *in, const unsigned int insize)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (insize < 4 + strlen (SMOKECODEC_ID_STRING)) {
|
||||
return SMOKECODEC_WRONGVERSION;
|
||||
}
|
||||
|
||||
if (*in++ != SMOKECODEC_TYPE_ID)
|
||||
return SMOKECODEC_ERROR;
|
||||
|
||||
for (i = 0; i < strlen (SMOKECODEC_ID_STRING); i++) {
|
||||
if (*in++ != SMOKECODEC_ID_STRING[i])
|
||||
return SMOKECODEC_ERROR;
|
||||
}
|
||||
if (*in++ != 0 || *in++ != 1 || *in++ != 0)
|
||||
return SMOKECODEC_ERROR;
|
||||
|
||||
return SMOKECODEC_OK;
|
||||
}
|
||||
|
||||
#define READ16(var, pos, x) \
|
||||
x = var[pos]<<8 | var[pos+1];
|
||||
|
||||
#define READ32(var, pos, x) \
|
||||
x = var[pos]<<24 | var[pos+1]<<16 | \
|
||||
var[pos+2]<<8 | var[pos+3];
|
||||
|
||||
/* decoding */
|
||||
SmokeCodecResult
|
||||
smokecodec_parse_header (SmokeCodecInfo * info,
|
||||
const unsigned char *in,
|
||||
const unsigned int insize,
|
||||
SmokeCodecFlags * flags, unsigned int *width, unsigned int *height)
|
||||
SmokeCodecFlags * flags,
|
||||
unsigned int *width,
|
||||
unsigned int *height, unsigned int *fps_num, unsigned int *fps_denom)
|
||||
{
|
||||
|
||||
*width = in[0] << 8 | in[1];
|
||||
*height = in[2] << 8 | in[3];
|
||||
*flags = in[4];
|
||||
READ16 (in, IDX_WIDTH, *width);
|
||||
READ16 (in, IDX_HEIGHT, *height);
|
||||
*flags = in[IDX_FLAGS];
|
||||
READ32 (in, IDX_FPS_NUM, *fps_num);
|
||||
READ32 (in, IDX_FPS_DENOM, *fps_denom);
|
||||
|
||||
if (info->width != *width || info->height != *height) {
|
||||
if (info->width != *width ||
|
||||
info->height != *height ||
|
||||
info->fps_num != *fps_num || info->fps_denom != *fps_denom) {
|
||||
DEBUG ("new width: %d %d\n", *width, *height);
|
||||
|
||||
info->reference = realloc (info->reference, 3 * ((*width) * (*height)) / 2);
|
||||
info->width = *width;
|
||||
info->height = *height;
|
||||
info->fps_num = *fps_num;
|
||||
info->fps_denom = *fps_denom;
|
||||
}
|
||||
|
||||
return SMOKECODEC_OK;
|
||||
|
@ -533,6 +606,7 @@ smokecodec_decode (SmokeCodecInfo * info,
|
|||
const unsigned char *in, const unsigned int insize, unsigned char *out)
|
||||
{
|
||||
unsigned int width, height;
|
||||
unsigned int fps_num, fps_denom;
|
||||
SmokeCodecFlags flags;
|
||||
int i, j;
|
||||
int blocks_w, blocks_h;
|
||||
|
@ -542,9 +616,10 @@ smokecodec_decode (SmokeCodecInfo * info,
|
|||
unsigned char *op;
|
||||
int res;
|
||||
|
||||
smokecodec_parse_header (info, in, insize, &flags, &width, &height);
|
||||
smokecodec_parse_header (info, in, insize, &flags, &width, &height,
|
||||
&fps_num, &fps_denom);
|
||||
|
||||
blocks = in[6] << 8 | in[7];
|
||||
READ16 (in, IDX_NUM_BLOCKS, blocks);
|
||||
DEBUG ("blocks %d\n", blocks);
|
||||
|
||||
if (flags & SMOKECODEC_KEYFRAME)
|
||||
|
@ -552,12 +627,11 @@ smokecodec_decode (SmokeCodecInfo * info,
|
|||
else
|
||||
decoding = blocks;
|
||||
|
||||
|
||||
if (decoding > 0) {
|
||||
info->jsrc.next_input_byte = &in[blocks * 2 + 12];
|
||||
info->jsrc.bytes_in_buffer = insize - (blocks * 2 + 12);
|
||||
info->jsrc.next_input_byte = &in[blocks * 2 + OFFS_PICT];
|
||||
info->jsrc.bytes_in_buffer = insize - (blocks * 2 + OFFS_PICT);
|
||||
|
||||
DEBUG ("header %02x %d\n", in[blocks * 2 + 12], insize);
|
||||
DEBUG ("header %02x %d\n", in[blocks * 2 + OFFS_PICT], insize);
|
||||
res = jpeg_read_header (&info->dinfo, TRUE);
|
||||
DEBUG ("header %d %d %d\n", res, info->dinfo.image_width,
|
||||
info->dinfo.image_height);
|
||||
|
@ -590,7 +664,7 @@ smokecodec_decode (SmokeCodecInfo * info,
|
|||
if (flags & SMOKECODEC_KEYFRAME)
|
||||
pos = blockptr;
|
||||
else
|
||||
pos = (in[blockptr * 2 + 10] << 8) | (in[blockptr * 2 + 11]);
|
||||
READ16 (in, blockptr * 2 + IDX_BLOCKS, pos);
|
||||
|
||||
x = pos % (width / (DCTSIZE * 2));
|
||||
y = pos / (width / (DCTSIZE * 2));
|
||||
|
|
|
@ -30,11 +30,12 @@ extern "C" {
|
|||
typedef struct _SmokeCodecInfo SmokeCodecInfo;
|
||||
|
||||
typedef enum {
|
||||
SMOKECODEC_WRONGVERSION = -5,
|
||||
SMOKECODEC_WRONGSIZE = -4,
|
||||
SMOKECODEC_ERROR = -3,
|
||||
SMOKECODEC_NOMEM = -2,
|
||||
SMOKECODEC_NULLPTR = -1,
|
||||
SMOKECODEC_OK = 0,
|
||||
SMOKECODEC_OK = 0
|
||||
} SmokeCodecResult;
|
||||
|
||||
typedef enum {
|
||||
|
@ -42,11 +43,21 @@ typedef enum {
|
|||
SMOKECODEC_MOTION_VECTORS = (1<<1)
|
||||
} SmokeCodecFlags;
|
||||
|
||||
#define SMOKECODEC_ID_STRING "smoke"
|
||||
|
||||
typedef enum {
|
||||
SMOKECODEC_TYPE_ID = 0x80,
|
||||
SMOKECODEC_TYPE_COMMENT = 0x81,
|
||||
SMOKECODEC_TYPE_EXTRA = 0x83,
|
||||
SMOKECODEC_TYPE_DATA = 0x40
|
||||
} SmokePacketType;
|
||||
|
||||
/* init */
|
||||
int smokecodec_encode_new (SmokeCodecInfo **info,
|
||||
const unsigned int width,
|
||||
const unsigned int height);
|
||||
const unsigned int height,
|
||||
const unsigned int fps_num,
|
||||
const unsigned int fps_denom);
|
||||
|
||||
int smokecodec_decode_new (SmokeCodecInfo **info);
|
||||
|
||||
|
@ -69,6 +80,10 @@ SmokeCodecResult smokecodec_get_bitrate (SmokeCodecInfo *info,
|
|||
unsigned int *bitrate);
|
||||
|
||||
/* encoding */
|
||||
SmokeCodecResult smokecodec_encode_id (SmokeCodecInfo *info,
|
||||
unsigned char *out,
|
||||
unsigned int *outsize);
|
||||
|
||||
SmokeCodecResult smokecodec_encode (SmokeCodecInfo *info,
|
||||
const unsigned char *in,
|
||||
SmokeCodecFlags flags,
|
||||
|
@ -76,12 +91,18 @@ SmokeCodecResult smokecodec_encode (SmokeCodecInfo *info,
|
|||
unsigned int *outsize);
|
||||
|
||||
/* decoding */
|
||||
SmokeCodecResult smokecodec_parse_id (SmokeCodecInfo *info,
|
||||
const unsigned char *in,
|
||||
const unsigned int insize);
|
||||
|
||||
SmokeCodecResult smokecodec_parse_header (SmokeCodecInfo *info,
|
||||
const unsigned char *in,
|
||||
const unsigned int insize,
|
||||
SmokeCodecFlags *flags,
|
||||
unsigned int *width,
|
||||
unsigned int *height);
|
||||
unsigned int *height,
|
||||
unsigned int *fps_num,
|
||||
unsigned int *fps_denom);
|
||||
|
||||
SmokeCodecResult smokecodec_decode (SmokeCodecInfo *info,
|
||||
const unsigned char *in,
|
||||
|
|
46
ext/jpeg/smokeformat.h
Normal file
46
ext/jpeg/smokeformat.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Smoke Codec
|
||||
* Copyright (C) <2004> Wim Taymans <wim@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 __SMOKEFORMAT_H__
|
||||
#define __SMOKEFORMAT_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define IDX_TYPE 0
|
||||
#define IDX_WIDTH 1
|
||||
#define IDX_HEIGHT 3
|
||||
#define IDX_FPS_NUM 5
|
||||
#define IDX_FPS_DENOM 9
|
||||
#define IDX_FLAGS 13
|
||||
#define IDX_NUM_BLOCKS 14
|
||||
#define IDX_SIZE 16
|
||||
#define IDX_BLOCKS 18
|
||||
#define OFFS_PICT 18
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __SMOKEFORMAT_H__ */
|
Loading…
Reference in a new issue