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:
Wim Taymans 2004-10-04 16:53:48 +00:00
parent d2ba80e45e
commit b90716dd18
9 changed files with 302 additions and 50 deletions

View File

@ -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> 2004-10-04 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_event): * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_event):

View File

@ -19,12 +19,30 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif #endif
#include <string.h>
#include "gstjpegdec.h" #include "gstjpegdec.h"
#include "gstjpegenc.h" #include "gstjpegenc.h"
#include "gstsmokeenc.h" #include "gstsmokeenc.h"
#include "gstsmokedec.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 static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
@ -44,6 +62,10 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_SMOKEDEC)) GST_TYPE_SMOKEDEC))
return FALSE; 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; return TRUE;
} }

View File

@ -29,9 +29,9 @@
/* elementfactory information */ /* elementfactory information */
GstElementDetails gst_smokedec_details = { GstElementDetails gst_smokedec_details = {
"Smoke image decoder", "Smoke video decoder",
"Codec/Decoder/Image", "Codec/Decoder/Image",
"Decode images from Smoke format", "Decode video from Smoke format",
"Wim Taymans <wim@fluendo.com>", "Wim Taymans <wim@fluendo.com>",
}; };
@ -98,7 +98,7 @@ static GstStaticPadTemplate gst_smokedec_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("image/x-smoke, " GST_STATIC_CAPS ("video/x-smoke, "
"width = (int) [ 16, 4096 ], " "width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (double) [ 1, MAX ]") "height = (int) [ 16, 4096 ], " "framerate = (double) [ 1, MAX ]")
); );
@ -150,6 +150,7 @@ gst_smokedec_init (GstSmokeDec * smokedec)
smokedec->format = -1; smokedec->format = -1;
smokedec->width = -1; smokedec->width = -1;
smokedec->height = -1; smokedec->height = -1;
smokedec->next_time = 0;
} }
static GstPadLinkReturn static GstPadLinkReturn
@ -189,9 +190,10 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
gulong size, outsize; gulong size, outsize;
GstBuffer *outbuf; GstBuffer *outbuf;
SmokeCodecFlags flags; SmokeCodecFlags flags;
GstClockTime time;
/*GstMeta *meta; */
gint width, height; gint width, height;
gint fps_num, fps_denom;
smokedec = GST_SMOKEDEC (GST_OBJECT_PARENT (pad)); smokedec = GST_SMOKEDEC (GST_OBJECT_PARENT (pad));
@ -202,17 +204,36 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
data = (guchar *) GST_BUFFER_DATA (buf); data = (guchar *) GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (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_DEBUG ("gst_smokedec_chain: got buffer of %ld bytes in '%s'", size,
GST_OBJECT_NAME (smokedec)); 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); 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 (); outbuf = gst_buffer_new ();
outsize = GST_BUFFER_SIZE (outbuf) = width * height + width * height / 2; outsize = GST_BUFFER_SIZE (outbuf) = width * height + width * height / 2;
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize); 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) { if (smokedec->height != height) {
GstCaps *caps; GstCaps *caps;
@ -223,15 +244,26 @@ gst_smokedec_chain (GstPad * pad, GstData * _data)
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
"width", G_TYPE_INT, width, "width", G_TYPE_INT, width,
"height", G_TYPE_INT, height, "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_pad_set_explicit_caps (smokedec->srcpad, caps);
gst_caps_free (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"); if (!smokedec->need_keyframe) {
gst_pad_push (smokedec->srcpad, GST_DATA (outbuf)); 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));
}
} }

View File

@ -55,12 +55,15 @@ struct _GstSmokeDec {
gint width; gint width;
gint height; gint height;
gdouble fps; gdouble fps;
GstClockTime next_time;
SmokeCodecInfo *info; SmokeCodecInfo *info;
gint threshold; gint threshold;
gint quality; gint quality;
gint smoothing; gint smoothing;
gboolean need_keyframe;
}; };
struct _GstSmokeDecClass { struct _GstSmokeDecClass {

View File

@ -186,6 +186,7 @@ gst_smokeenc_init (GstSmokeEnc * smokeenc)
smokeenc->width = 0; smokeenc->width = 0;
smokeenc->height = 0; smokeenc->height = 0;
smokeenc->frame = 0; smokeenc->frame = 0;
smokeenc->need_header = TRUE;
gst_smokeenc_resync (smokeenc); gst_smokeenc_resync (smokeenc);
@ -264,9 +265,21 @@ gst_smokeenc_link (GstPad * pad, const GstCaps * caps)
static void static void
gst_smokeenc_resync (GstSmokeEnc * smokeenc) gst_smokeenc_resync (GstSmokeEnc * smokeenc)
{ {
GValue fps = { 0 };
GValue framerate = { 0 };
GST_DEBUG ("gst_smokeenc_resync: resync"); 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, smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
smokeenc->max_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_DEBUG ("gst_smokeenc_chain: got buffer of %ld bytes in '%s'", size,
GST_OBJECT_NAME (smokeenc)); 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 (); outbuf = gst_buffer_new ();
outsize = smokeenc->width * smokeenc->height * 3; outsize = smokeenc->width * smokeenc->height * 3;
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize); outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize);
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); 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; flags = 0;
if (smokeenc->frame == 0) { if ((smokeenc->frame % smokeenc->keyframe) == 0) {
flags |= SMOKECODEC_KEYFRAME; flags |= SMOKECODEC_KEYFRAME;
} }
smokeenc->frame = (smokeenc->frame + 1) % smokeenc->keyframe;
smokecodec_set_quality (smokeenc->info, smokeenc->min_quality, smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
smokeenc->max_quality); smokeenc->max_quality);
smokecodec_set_threshold (smokeenc->info, smokeenc->threshold); smokecodec_set_threshold (smokeenc->info, smokeenc->threshold);
@ -312,9 +339,12 @@ gst_smokeenc_chain (GstPad * pad, GstData * _data)
gst_buffer_unref (buf); gst_buffer_unref (buf);
GST_BUFFER_SIZE (outbuf) = encsize; 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)); gst_pad_push (smokeenc->srcpad, GST_DATA (outbuf));
smokeenc->frame++;
} }
static void static void

View File

@ -57,12 +57,15 @@ struct _GstSmokeEnc {
gint frame; gint frame;
gint keyframe; gint keyframe;
gdouble fps; gdouble fps;
gint fps_num, fps_denom;
SmokeCodecInfo *info; SmokeCodecInfo *info;
gint threshold; gint threshold;
gint min_quality; gint min_quality;
gint max_quality; gint max_quality;
gboolean need_header;
}; };
struct _GstSmokeEncClass { struct _GstSmokeEncClass {

View File

@ -34,15 +34,17 @@
#include <jpeglib.h> #include <jpeglib.h>
#include "smokecodec.h" #include "smokecodec.h"
#include "smokeformat.h"
//#define DEBUG(a...) printf( a ); //#define DEBUG(a...) printf( a );
#define DEBUG(a,...) #define DEBUG(a,...)
struct _SmokeCodecInfo struct _SmokeCodecInfo
{ {
unsigned int width; unsigned int width;
unsigned int height; unsigned int height;
unsigned int fps_num;
unsigned int fps_denom;
unsigned int minquality; unsigned int minquality;
unsigned int maxquality; unsigned int maxquality;
@ -112,7 +114,9 @@ smokecodec_term_source (j_decompress_ptr cinfo)
int int
smokecodec_encode_new (SmokeCodecInfo ** info, 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; SmokeCodecInfo *newinfo;
int i, j; int i, j;
@ -129,6 +133,8 @@ smokecodec_encode_new (SmokeCodecInfo ** info,
} }
newinfo->width = width; newinfo->width = width;
newinfo->height = height; newinfo->height = height;
newinfo->fps_num = fps_num;
newinfo->fps_denom = fps_denom;
/* setup jpeglib */ /* setup jpeglib */
memset (&newinfo->cinfo, 0, sizeof (newinfo->cinfo)); memset (&newinfo->cinfo, 0, sizeof (newinfo->cinfo));
@ -200,7 +206,7 @@ smokecodec_encode_new (SmokeCodecInfo ** info,
int int
smokecodec_decode_new (SmokeCodecInfo ** info) smokecodec_decode_new (SmokeCodecInfo ** info)
{ {
return smokecodec_encode_new (info, 16, 16); return smokecodec_encode_new (info, 16, 16, 1, 1);
} }
int int
@ -348,6 +354,25 @@ put (const unsigned char *src, unsigned char *dest,
} }
/* encoding */ /* 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 SmokeCodecResult
smokecodec_encode (SmokeCodecInfo * info, smokecodec_encode (SmokeCodecInfo * info,
const unsigned char *in, const unsigned char *in,
@ -384,13 +409,24 @@ smokecodec_encode (SmokeCodecInfo * info,
max = blocks_w * blocks_h; max = blocks_w * blocks_h;
out[IDX_TYPE] = SMOKECODEC_TYPE_DATA;
#define STORE16(var, pos, x) \ #define STORE16(var, pos, x) \
var[pos] = (x >> 8); \ var[pos] = (x >> 8); \
var[pos+1] = (x & 0xff); 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 */ /* write dimension */
STORE16 (out, 0, width); STORE16 (out, IDX_WIDTH, width);
STORE16 (out, 2, height); 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)) { if (!(flags & SMOKECODEC_KEYFRAME)) {
int block = 0; int block = 0;
@ -400,7 +436,7 @@ smokecodec_encode (SmokeCodecInfo * info,
for (j = 0; j < width; j += 2 * DCTSIZE) { for (j = 0; j < width; j += 2 * DCTSIZE) {
s = abs_diff (ip, op, width); s = abs_diff (ip, op, width);
if (s >= threshold) { if (s >= threshold) {
STORE16 (out, blocks * 2 + 10, block); STORE16 (out, blocks * 2 + IDX_BLOCKS, block);
blocks++; blocks++;
} }
@ -422,13 +458,13 @@ smokecodec_encode (SmokeCodecInfo * info,
blocks = 0; blocks = 0;
encoding = max; encoding = max;
} }
STORE16 (out, 6, blocks); STORE16 (out, IDX_NUM_BLOCKS, blocks);
out[4] = (flags & 0xff); out[IDX_FLAGS] = (flags & 0xff);
DEBUG ("blocks %d, encoding %d\n", blocks, encoding); DEBUG ("blocks %d, encoding %d\n", blocks, encoding);
info->jdest.next_output_byte = &out[blocks * 2 + 12]; info->jdest.next_output_byte = &out[blocks * 2 + OFFS_PICT];
info->jdest.free_in_buffer = (*outsize) - 12; info->jdest.free_in_buffer = (*outsize) - OFFS_PICT;
if (encoding > 0) { if (encoding > 0) {
int quality; int quality;
@ -461,7 +497,7 @@ smokecodec_encode (SmokeCodecInfo * info,
if (flags & SMOKECODEC_KEYFRAME) if (flags & SMOKECODEC_KEYFRAME)
pos = i; pos = i;
else 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)); x = pos % (width / (DCTSIZE * 2));
y = pos / (width / (DCTSIZE * 2)); y = pos / (width / (DCTSIZE * 2));
@ -488,11 +524,10 @@ smokecodec_encode (SmokeCodecInfo * info,
jpeg_finish_compress (&info->cinfo); jpeg_finish_compress (&info->cinfo);
} }
size = ((((*outsize) - 12 - info->jdest.free_in_buffer) + 3) & ~3); size = ((((*outsize) - OFFS_PICT - info->jdest.free_in_buffer) + 3) & ~3);
out[8] = size >> 8; STORE16 (out, IDX_SIZE, size);
out[9] = size & 0xff;
*outsize = size + blocks * 2 + 12; *outsize = size + blocks * 2 + OFFS_PICT;
DEBUG ("outsize %d\n", *outsize); DEBUG ("outsize %d\n", *outsize);
// and decode in reference frame again // and decode in reference frame again
@ -505,24 +540,62 @@ smokecodec_encode (SmokeCodecInfo * info,
return SMOKECODEC_OK; 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 */ /* decoding */
SmokeCodecResult SmokeCodecResult
smokecodec_parse_header (SmokeCodecInfo * info, smokecodec_parse_header (SmokeCodecInfo * info,
const unsigned char *in, const unsigned char *in,
const unsigned int insize, 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]; READ16 (in, IDX_WIDTH, *width);
*height = in[2] << 8 | in[3]; READ16 (in, IDX_HEIGHT, *height);
*flags = in[4]; *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); DEBUG ("new width: %d %d\n", *width, *height);
info->reference = realloc (info->reference, 3 * ((*width) * (*height)) / 2); info->reference = realloc (info->reference, 3 * ((*width) * (*height)) / 2);
info->width = *width; info->width = *width;
info->height = *height; info->height = *height;
info->fps_num = *fps_num;
info->fps_denom = *fps_denom;
} }
return SMOKECODEC_OK; return SMOKECODEC_OK;
@ -533,6 +606,7 @@ smokecodec_decode (SmokeCodecInfo * info,
const unsigned char *in, const unsigned int insize, unsigned char *out) const unsigned char *in, const unsigned int insize, unsigned char *out)
{ {
unsigned int width, height; unsigned int width, height;
unsigned int fps_num, fps_denom;
SmokeCodecFlags flags; SmokeCodecFlags flags;
int i, j; int i, j;
int blocks_w, blocks_h; int blocks_w, blocks_h;
@ -542,9 +616,10 @@ smokecodec_decode (SmokeCodecInfo * info,
unsigned char *op; unsigned char *op;
int res; 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); DEBUG ("blocks %d\n", blocks);
if (flags & SMOKECODEC_KEYFRAME) if (flags & SMOKECODEC_KEYFRAME)
@ -552,12 +627,11 @@ smokecodec_decode (SmokeCodecInfo * info,
else else
decoding = blocks; decoding = blocks;
if (decoding > 0) { if (decoding > 0) {
info->jsrc.next_input_byte = &in[blocks * 2 + 12]; info->jsrc.next_input_byte = &in[blocks * 2 + OFFS_PICT];
info->jsrc.bytes_in_buffer = insize - (blocks * 2 + 12); 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); res = jpeg_read_header (&info->dinfo, TRUE);
DEBUG ("header %d %d %d\n", res, info->dinfo.image_width, DEBUG ("header %d %d %d\n", res, info->dinfo.image_width,
info->dinfo.image_height); info->dinfo.image_height);
@ -590,7 +664,7 @@ smokecodec_decode (SmokeCodecInfo * info,
if (flags & SMOKECODEC_KEYFRAME) if (flags & SMOKECODEC_KEYFRAME)
pos = blockptr; pos = blockptr;
else else
pos = (in[blockptr * 2 + 10] << 8) | (in[blockptr * 2 + 11]); READ16 (in, blockptr * 2 + IDX_BLOCKS, pos);
x = pos % (width / (DCTSIZE * 2)); x = pos % (width / (DCTSIZE * 2));
y = pos / (width / (DCTSIZE * 2)); y = pos / (width / (DCTSIZE * 2));

View File

@ -30,11 +30,12 @@ extern "C" {
typedef struct _SmokeCodecInfo SmokeCodecInfo; typedef struct _SmokeCodecInfo SmokeCodecInfo;
typedef enum { typedef enum {
SMOKECODEC_WRONGVERSION = -5,
SMOKECODEC_WRONGSIZE = -4, SMOKECODEC_WRONGSIZE = -4,
SMOKECODEC_ERROR = -3, SMOKECODEC_ERROR = -3,
SMOKECODEC_NOMEM = -2, SMOKECODEC_NOMEM = -2,
SMOKECODEC_NULLPTR = -1, SMOKECODEC_NULLPTR = -1,
SMOKECODEC_OK = 0, SMOKECODEC_OK = 0
} SmokeCodecResult; } SmokeCodecResult;
typedef enum { typedef enum {
@ -42,11 +43,21 @@ typedef enum {
SMOKECODEC_MOTION_VECTORS = (1<<1) SMOKECODEC_MOTION_VECTORS = (1<<1)
} SmokeCodecFlags; } 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 */ /* init */
int smokecodec_encode_new (SmokeCodecInfo **info, int smokecodec_encode_new (SmokeCodecInfo **info,
const unsigned int width, 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); int smokecodec_decode_new (SmokeCodecInfo **info);
@ -69,6 +80,10 @@ SmokeCodecResult smokecodec_get_bitrate (SmokeCodecInfo *info,
unsigned int *bitrate); unsigned int *bitrate);
/* encoding */ /* encoding */
SmokeCodecResult smokecodec_encode_id (SmokeCodecInfo *info,
unsigned char *out,
unsigned int *outsize);
SmokeCodecResult smokecodec_encode (SmokeCodecInfo *info, SmokeCodecResult smokecodec_encode (SmokeCodecInfo *info,
const unsigned char *in, const unsigned char *in,
SmokeCodecFlags flags, SmokeCodecFlags flags,
@ -76,12 +91,18 @@ SmokeCodecResult smokecodec_encode (SmokeCodecInfo *info,
unsigned int *outsize); unsigned int *outsize);
/* decoding */ /* decoding */
SmokeCodecResult smokecodec_parse_id (SmokeCodecInfo *info,
const unsigned char *in,
const unsigned int insize);
SmokeCodecResult smokecodec_parse_header (SmokeCodecInfo *info, SmokeCodecResult smokecodec_parse_header (SmokeCodecInfo *info,
const unsigned char *in, const unsigned char *in,
const unsigned int insize, const unsigned int insize,
SmokeCodecFlags *flags, SmokeCodecFlags *flags,
unsigned int *width, unsigned int *width,
unsigned int *height); unsigned int *height,
unsigned int *fps_num,
unsigned int *fps_denom);
SmokeCodecResult smokecodec_decode (SmokeCodecInfo *info, SmokeCodecResult smokecodec_decode (SmokeCodecInfo *info,
const unsigned char *in, const unsigned char *in,

46
ext/jpeg/smokeformat.h Normal file
View 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__ */