summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEwald Snel <esnel@users.sourceforge.net>2002-12-15 18:44:52 +0000
committerEwald Snel <esnel@users.sourceforge.net>2002-12-15 18:44:52 +0000
commitcba89b653c86bc6d2e303b94e2e8d84aad7f5444 (patch)
tree28713691f8062495626d5f7fea9a7e5ec85b5e71
parent422d666bdfc36ee4b90466fac94b1d6e2c1d3536 (diff)
downloadxine-lib-cba89b653c86bc6d2e303b94e2e8d84aad7f5444.tar.gz
xine-lib-cba89b653c86bc6d2e303b94e2e8d84aad7f5444.tar.bz2
More cleanups, accurate frame clipping if video size not divisible by 4
CVS patchset: 3548 CVS date: 2002/12/15 18:44:52
-rw-r--r--src/libxinevdec/cinepak.c129
1 files changed, 70 insertions, 59 deletions
diff --git a/src/libxinevdec/cinepak.c b/src/libxinevdec/cinepak.c
index 2d116786f..1245af8f2 100644
--- a/src/libxinevdec/cinepak.c
+++ b/src/libxinevdec/cinepak.c
@@ -22,7 +22,7 @@
* based on overview of Cinepak algorithm and example decoder
* by Tim Ferguson: http://www.csse.monash.edu.au/~timf/
*
- * $Id: cinepak.c,v 1.24 2002/12/15 18:02:35 esnel Exp $
+ * $Id: cinepak.c,v 1.25 2002/12/15 18:44:52 esnel Exp $
*/
#include <stdlib.h>
@@ -68,11 +68,17 @@ typedef struct cvid_decoder_s {
int bufsize;
int size;
- long biWidth;
- long biHeight;
- uint8_t *img_buffer;
-
cvid_strip_t strips[MAX_STRIPS];
+
+ unsigned int coded_width;
+ unsigned int coded_height;
+ int luma_pitch;
+ int chroma_pitch;
+ uint8_t *current;
+ int offsets[3];
+
+ unsigned int width;
+ unsigned int height;
} cvid_decoder_t;
static unsigned char yuv_palette[256 * 4];
@@ -146,8 +152,7 @@ static int cinepak_decode_vectors (cvid_decoder_t *this, cvid_strip_t *strip,
uint8_t *eod = (data + size);
uint32_t flag, mask;
cvid_codebook_t *codebook;
- int x, y;
- int n = (this->biWidth * this->biHeight);
+ unsigned int x, y;
uint8_t *iy[4];
uint8_t *iu[2];
uint8_t *iv[2];
@@ -157,14 +162,14 @@ static int cinepak_decode_vectors (cvid_decoder_t *this, cvid_strip_t *strip,
for (y=strip->y1; y < strip->y2; y+=4) {
- iy[0] = this->img_buffer + (y * this->biWidth) + strip->x1;
- iy[1] = iy[0] + this->biWidth;
- iy[2] = iy[1] + this->biWidth;
- iy[3] = iy[2] + this->biWidth;
- iu[0] = this->img_buffer + n + ((y * this->biWidth) >> 2) + (strip->x1 >> 1);
- iu[1] = iu[0] + (this->biWidth >> 1);
- iv[0] = iu[0] + (n >> 2);
- iv[1] = iv[0] + (this->biWidth >> 1);
+ iy[0] = &this->current[strip->x1 + (y * this->luma_pitch) + this->offsets[0]];
+ iy[1] = iy[0] + this->luma_pitch;
+ iy[2] = iy[1] + this->luma_pitch;
+ iy[3] = iy[2] + this->luma_pitch;
+ iu[0] = &this->current[(strip->x1/2) + ((y/2) * this->chroma_pitch) + this->offsets[1]];
+ iu[1] = iu[0] + this->chroma_pitch;
+ iv[0] = &this->current[(strip->x1/2) + ((y/2) * this->chroma_pitch) + this->offsets[2]];
+ iv[1] = iv[0] + this->chroma_pitch;
for (x=strip->x1; x < strip->x2; x+=4) {
if ((chunk_id & 0x0100) && !(mask >>= 1)) {
@@ -249,9 +254,9 @@ static int cinepak_decode_strip (cvid_decoder_t *this,
uint8_t *eod = (data + size);
int chunk_id, chunk_size;
- if (strip->x1 >= this->biWidth || strip->x2 > this->biWidth ||
- strip->y1 >= this->biHeight || strip->y2 > this->biHeight ||
- strip->x1 >= strip->x2 || strip->y1 >= strip->y2)
+ if (strip->x1 >= this->coded_width || strip->x2 > this->coded_width ||
+ strip->y1 >= this->coded_height || strip->y2 > this->coded_height ||
+ strip->x1 >= strip->x2 || strip->y1 >= strip->y2)
return -1;
while ((data + 4) <= eod) {
@@ -308,7 +313,7 @@ static int cinepak_decode_frame (cvid_decoder_t *this, uint8_t *data, int size)
this->strips[i].y1 = y0;
this->strips[i].x1 = 0;
this->strips[i].y2 = y0 + BE_16 (&data[8]);
- this->strips[i].x2 = this->biWidth;
+ this->strips[i].x2 = this->coded_width;
strip_size = BE_16 (&data[2]) - 12;
data += 12;
@@ -334,6 +339,31 @@ static int cinepak_decode_frame (cvid_decoder_t *this, uint8_t *data, int size)
return 0;
}
+static void cinepak_copy_frame (cvid_decoder_t *this, uint8_t *base[3], int pitches[3]) {
+ int i, j;
+ uint8_t *src, *dst;
+
+ src = &this->current[this->offsets[0]];
+ dst = base[0];
+
+ for (i=0; i < this->height; ++i) {
+ memcpy (dst, src, this->width);
+ src += this->luma_pitch;
+ dst += pitches[0];
+ }
+
+ for (i=1; i < 3; i++) {
+ src = &this->current[this->offsets[i]];
+ dst = base[i];
+
+ for (j=0; j < (this->height / 2); ++j) {
+ memcpy (dst, src, (this->width / 2));
+ src += this->chroma_pitch;
+ dst += pitches[i];
+ }
+ }
+}
+
static void cvid_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
cvid_decoder_t *this = (cvid_decoder_t *) this_gen;
@@ -359,15 +389,23 @@ static void cvid_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
if (buf->decoder_flags & BUF_FLAG_HEADER) {
xine_bmiheader *bih;
+ int chroma_size;
bih = (xine_bmiheader *) buf->content;
- this->biWidth = (bih->biWidth + 3) & ~0x03;
- this->biHeight = (bih->biHeight + 3) & ~0x03;
this->video_step = buf->decoder_info[1];
- if (this->img_buffer)
- free (this->img_buffer);
- this->img_buffer = malloc((this->biWidth * this->biHeight * 3) / 2);
+ this->width = (bih->biWidth + 1) & ~0x1;
+ this->height = (bih->biHeight + 1) & ~0x1;
+ this->coded_width = (this->width + 3) & ~0x3;
+ this->coded_height = (this->height + 3) & ~0x3;
+ this->luma_pitch = this->coded_width;
+ this->chroma_pitch = this->coded_width / 2;
+
+ chroma_size = (this->chroma_pitch * (this->coded_height / 2));
+ this->current = (uint8_t *) realloc (this->current, 6*chroma_size);
+ this->offsets[0] = 0;
+ this->offsets[1] = 4*chroma_size;
+ this->offsets[2] = 5*chroma_size;
if (this->buf)
free (this->buf);
@@ -401,45 +439,21 @@ static void cvid_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
vo_frame_t *img;
- uint8_t *dy, *du, *dv, *sy, *su, *sv;
- int result, y;
+ int result;
result = cinepak_decode_frame (this, this->buf, this->size);
- result = 0;
img = this->stream->video_out->get_frame (this->stream->video_out,
- this->biWidth, this->biHeight,
- XINE_VO_ASPECT_SQUARE,
- XINE_IMGFMT_YV12, VO_BOTH_FIELDS);
+ this->width, this->height,
+ XINE_VO_ASPECT_SQUARE,
+ XINE_IMGFMT_YV12, VO_BOTH_FIELDS);
img->duration = this->video_step;
img->pts = buf->pts;
img->bad_frame = (result != 0);
if (result == 0) {
- dy = img->base[0];
- du = img->base[1];
- dv = img->base[2];
- sy = this->img_buffer;
- su = this->img_buffer + (this->biWidth * this->biHeight);
- sv = this->img_buffer + ((this->biWidth * this->biHeight * 5) / 4);
-
- for (y=0; y < this->biHeight; y++) {
- xine_fast_memcpy (dy, sy, this->biWidth);
-
- dy += img->pitches[0];
- sy += this->biWidth;
- }
-
- for (y=0; y < (this->biHeight/2); y++) {
- xine_fast_memcpy (du, su, this->biWidth/2);
- xine_fast_memcpy (dv, sv, this->biWidth/2);
-
- du += img->pitches[1];
- dv += img->pitches[2];
- su += this->biWidth/2;
- sv += this->biWidth/2;
- }
+ cinepak_copy_frame (this, img->base, img->pitches);
}
img->draw(img, this->stream);
@@ -465,14 +479,12 @@ static void cvid_discontinuity (video_decoder_t *this_gen) {
static void cvid_dispose (video_decoder_t *this_gen) {
cvid_decoder_t *this = (cvid_decoder_t *) this_gen;
- if (this->img_buffer) {
- free (this->img_buffer);
- this->img_buffer = NULL;
+ if (this->current) {
+ free (this->current);
}
if (this->buf) {
free (this->buf);
- this->buf = NULL;
}
if (this->decoder_ok) {
@@ -487,7 +499,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
cvid_decoder_t *this ;
- this = (cvid_decoder_t *) malloc (sizeof (cvid_decoder_t));
+ this = (cvid_decoder_t *) xine_xmalloc (sizeof (cvid_decoder_t));
this->video_decoder.decode_data = cvid_decode_data;
this->video_decoder.flush = cvid_flush;
@@ -501,7 +513,6 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
this->decoder_ok = 0;
this->buf = NULL;
- this->img_buffer = NULL;
return &this->video_decoder;
}