summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS2
-rw-r--r--ChangeLog1
-rw-r--r--src/libxinevdec/Makefile.am6
-rw-r--r--src/libxinevdec/qtrle.c912
4 files changed, 919 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index 500515d0a..a812b68e2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -235,7 +235,7 @@ Contributions
Mike Melanson <melanson@pcisys.net>
QT, FILM, RoQ, WAV, FLI, SMJPEG, Id CIN, WC3 movie, VOC, VQA, AIFF,
and SND/AU file demuxers; RoQ audio decoder; various ADPCM audio
- decoders; raw RGB & YUV support; FLI, MS RLE, and QT SMC video
+ decoders; raw RGB & YUV support; FLI, MS & QT RLE, and QT SMC video
decoders
Tim Ferguson <timf@mail.csse.monash.edu.au>
diff --git a/ChangeLog b/ChangeLog
index 5f5e3ff43..81b7ca573 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,7 @@ xine-lib (next version) [someone fill in stability and urgency]
* AIFF file demuxer
* Sun/NeXT SND/AU file demuxer
* Id CIN video decoder
+ * QT RLE video decoder
* QT SMC video decoder
* QT RPZA video decoder
* Wing Commander III video decoder
diff --git a/src/libxinevdec/Makefile.am b/src/libxinevdec/Makefile.am
index 7622da1ce..4c0b68ff9 100644
--- a/src/libxinevdec/Makefile.am
+++ b/src/libxinevdec/Makefile.am
@@ -20,7 +20,8 @@ lib_LTLIBRARIES = \
xineplug_decode_svq1.la \
xineplug_decode_yuv.la \
xineplug_decode_qtrpza.la \
- xineplug_decode_wc3video.la
+ xineplug_decode_wc3video.la \
+ xineplug_decode_qtrle.la
xineplug_decode_cinepak_la_SOURCES = cinepak.c
xineplug_decode_cinepak_la_LDFLAGS = -avoid-version -module
@@ -61,6 +62,9 @@ xineplug_decode_qtrpza_la_LDFLAGS = -avoid-version -module
xineplug_decode_wc3video_la_SOURCES = wc3video.c
xineplug_decode_wc3video_la_LDFLAGS = -avoid-version -module
+xineplug_decode_qtrle_la_SOURCES = qtrle.c
+xineplug_decode_qtrle_la_LDFLAGS = -avoid-version -module
+
noinst_HEADERS = svq1_codebooks.h
debug:
diff --git a/src/libxinevdec/qtrle.c b/src/libxinevdec/qtrle.c
new file mode 100644
index 000000000..a2926add7
--- /dev/null
+++ b/src/libxinevdec/qtrle.c
@@ -0,0 +1,912 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * QT RLE Decoder by Mike Melanson (melanson@pcisys.net)
+ * For more information on the QT RLE format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ *
+ * $Id: qtrle.c,v 1.1 2002/09/22 04:27:00 tmmm Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "xine_internal.h"
+#include "video_out.h"
+#include "buffer.h"
+#include "xineutils.h"
+#include "bswap.h"
+
+#define VIDEOBUFSIZE 128*1024
+
+#define BE_16(x) (be2me_16(*(unsigned short *)(x)))
+#define BE_32(x) (be2me_32(*(unsigned int *)(x)))
+
+typedef struct qtrle_decoder_s {
+ video_decoder_t video_decoder; /* parent video decoder structure */
+
+ /* these are traditional variables in a video decoder object */
+ vo_instance_t *video_out; /* object that will receive frames */
+ uint64_t video_step; /* frame duration in pts units */
+ int decoder_ok; /* current decoder status */
+ int skipframes;
+
+ unsigned char *buf; /* the accumulated buffer data */
+ int bufsize; /* the maximum size of buf */
+ int size; /* the current size of buf */
+
+ int width; /* the width of a video frame */
+ int height; /* the height of a video frame */
+ int depth; /* color depth (bits/pixel) */
+
+ unsigned char yuv_palette[256 * 4];
+ yuv_planes_t yuv_planes;
+
+} qtrle_decoder_t;
+
+/**************************************************************************
+ * QT RLE specific decode functions
+ *************************************************************************/
+
+/* monochrome color definitions */
+#define Y_BLACK COMPUTE_Y(0x00, 0x00, 0x00)
+#define U_BLACK COMPUTE_U(0x00, 0x00, 0x00)
+#define V_BLACK COMPUTE_V(0x00, 0x00, 0x00)
+#define Y_WHITE COMPUTE_Y(0xFF, 0xFF, 0xFF)
+#define U_WHITE COMPUTE_U(0xFF, 0xFF, 0xFF)
+#define V_WHITE COMPUTE_V(0xFF, 0xFF, 0xFF)
+
+static void decode_qtrle_1(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char y[32], u[32], v[32];
+ yuv_planes_t *yuv = &this->yuv_planes;
+ int i, shift, index, indices;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+
+ /* get the next 32 bits from the stream and treat them as 32
+ * 1-bit indices into the palette */
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 31; i < 32; i++, shift--) {
+ index = (indices >> shift) & 0x01;
+ if (index) {
+ y[i] = Y_WHITE;
+ u[i] = U_WHITE;
+ v[i] = V_WHITE;
+ } else {
+ y[i] = Y_BLACK;
+ u[i] = U_BLACK;
+ v[i] = V_BLACK;
+ }
+ }
+ while (rle_code--) {
+ for (i = 0; i < 32; i++) {
+ yuv->y[pixel_ptr] = y[i];
+ yuv->u[pixel_ptr] = u[i];
+ yuv->v[pixel_ptr] = v[i];
+ pixel_ptr++;
+ }
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 31; i < 32; i++, shift--) {
+ index = (indices >> shift) & 0x01;
+ if (index) {
+ yuv->y[pixel_ptr] = Y_WHITE;
+ yuv->u[pixel_ptr] = U_WHITE;
+ yuv->v[pixel_ptr] = V_WHITE;
+ } else {
+ yuv->y[pixel_ptr] = Y_BLACK;
+ yuv->u[pixel_ptr] = U_BLACK;
+ yuv->v[pixel_ptr] = V_BLACK;
+ }
+ pixel_ptr++;
+ }
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_2(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char y[16], u[16], v[16];
+ yuv_planes_t *yuv = &this->yuv_planes;
+ int i, shift, index, indices;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+
+ /* get the next 32 bits from the stream and treat them as 16
+ * 2-bit indices into the palette */
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 30; i < 16; i++, shift -= 2) {
+ index = (indices >> shift) & 0x03;
+ y[i] = this->yuv_palette[this->buf[index] * 4 + 0];
+ u[i] = this->yuv_palette[this->buf[index] * 4 + 1];
+ v[i] = this->yuv_palette[this->buf[index] * 4 + 2];
+ }
+ while (rle_code--) {
+ for (i = 0; i < 16; i++) {
+ yuv->y[pixel_ptr] = y[i];
+ yuv->u[pixel_ptr] = u[i];
+ yuv->v[pixel_ptr] = v[i];
+ pixel_ptr++;
+ }
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 30; i < 16; i++, shift -= 2) {
+ index = (indices >> shift) & 0x03;
+ yuv->y[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 0];
+ yuv->u[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 1];
+ yuv->v[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 2];
+ pixel_ptr++;
+ }
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_4(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char y[8], u[8], v[8];
+ yuv_planes_t *yuv = &this->yuv_planes;
+ int i, shift, index, indices;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+
+ /* get the next 32 bits from the stream and treat them as 8
+ * 4-bit indices into the palette */
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 28; i < 8; i++, shift -= 4) {
+ index = (indices >> shift) & 0x0F;
+ y[i] = this->yuv_palette[this->buf[index] * 4 + 0];
+ u[i] = this->yuv_palette[this->buf[index] * 4 + 1];
+ v[i] = this->yuv_palette[this->buf[index] * 4 + 2];
+ }
+ while (rle_code--) {
+ for (i = 0; i < 8; i++) {
+ yuv->y[pixel_ptr] = y[i];
+ yuv->u[pixel_ptr] = u[i];
+ yuv->v[pixel_ptr] = v[i];
+ pixel_ptr++;
+ }
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ indices = BE_32(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ for (i = 0, shift = 28; i < 8; i++, shift -= 4) {
+ index = (indices >> shift) & 0x0F;
+ yuv->y[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 0];
+ yuv->u[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 1];
+ yuv->v[pixel_ptr] = this->yuv_palette[this->buf[index] * 4 + 2];
+ pixel_ptr++;
+ }
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_8(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char y[4], u[4], v[4];
+ yuv_planes_t *yuv = &this->yuv_planes;
+ int i;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+ /* get the next 4 bytes from the stream, treat them as palette
+ * indices, and output them to the rle_code times */
+ for (i = 0; i < 4; i++) {
+ y[i] = this->yuv_palette[this->buf[stream_ptr] * 4 + 0];
+ u[i] = this->yuv_palette[this->buf[stream_ptr] * 4 + 1];
+ v[i] = this->yuv_palette[this->buf[stream_ptr] * 4 + 2];
+ stream_ptr++;
+ }
+ while (rle_code--) {
+ for (i = 0; i < 4; i++) {
+ yuv->y[pixel_ptr] = y[i];
+ yuv->u[pixel_ptr] = u[i];
+ yuv->v[pixel_ptr] = v[i];
+ pixel_ptr++;
+ }
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ for (i = 0; i < 4; i++) {
+ yuv->y[pixel_ptr] =
+ this->yuv_palette[this->buf[stream_ptr] * 4 + 0];
+ yuv->u[pixel_ptr] =
+ this->yuv_palette[this->buf[stream_ptr] * 4 + 1];
+ yuv->v[pixel_ptr] =
+ this->yuv_palette[this->buf[stream_ptr] * 4 + 2];
+ stream_ptr++;
+ pixel_ptr++;
+ }
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_16(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char r, g, b;
+ unsigned char y, u, v;
+ unsigned short packed_pixel;
+ yuv_planes_t *yuv = &this->yuv_planes;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+ packed_pixel = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+ UNPACK_RGB15(packed_pixel, r, g, b);
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ while (rle_code--) {
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ packed_pixel = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+ UNPACK_RGB15(packed_pixel, r, g, b);
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_24(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char r, g, b;
+ unsigned char y, u, v;
+ yuv_planes_t *yuv = &this->yuv_planes;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+ r = this->buf[stream_ptr++];
+ g = this->buf[stream_ptr++];
+ b = this->buf[stream_ptr++];
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ while (rle_code--) {
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ r = this->buf[stream_ptr++];
+ g = this->buf[stream_ptr++];
+ b = this->buf[stream_ptr++];
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+static void decode_qtrle_32(qtrle_decoder_t *this) {
+
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ signed char rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = this->width;
+ unsigned char r, g, b;
+ unsigned char y, u, v;
+ yuv_planes_t *yuv = &this->yuv_planes;
+
+ /* check if this frame is even supposed to change */
+ if (this->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ header = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ start_line = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&this->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = this->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ pixel_ptr = row_ptr + (this->buf[stream_ptr++] - 1);
+
+ while ((rle_code = (signed char)this->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0)
+ /* there's another skip code in the stream */
+ pixel_ptr += (this->buf[stream_ptr++] - 1);
+ else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+ stream_ptr++; /* skip alpha transparency (?) byte */
+ r = this->buf[stream_ptr++];
+ g = this->buf[stream_ptr++];
+ b = this->buf[stream_ptr++];
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ while (rle_code--) {
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ } else {
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ stream_ptr++; /* skip alpha transparency (?) byte */
+ r = this->buf[stream_ptr++];
+ g = this->buf[stream_ptr++];
+ b = this->buf[stream_ptr++];
+ y = COMPUTE_Y(r, g, b);
+ u = COMPUTE_U(r, g, b);
+ v = COMPUTE_V(r, g, b);
+ yuv->y[pixel_ptr] = y;
+ yuv->u[pixel_ptr] = u;
+ yuv->v[pixel_ptr] = v;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ row_ptr += row_inc;
+ }
+}
+
+/**************************************************************************
+ * xine video plugin functions
+ *************************************************************************/
+
+/*
+ * This function is responsible is called to initialize the video decoder
+ * for use. Initialization usually involves setting up the fields in your
+ * private video decoder object.
+ */
+static void qtrle_init (video_decoder_t *this_gen,
+ vo_instance_t *video_out) {
+ qtrle_decoder_t *this = (qtrle_decoder_t *) this_gen;
+
+ /* set our own video_out object to the one that xine gives us */
+ this->video_out = video_out;
+
+ /* indicate that the decoder is not quite ready yet */
+ this->decoder_ok = 0;
+}
+
+/*
+ * This function receives a buffer of data from the demuxer layer and
+ * figures out how to handle it based on its header flags.
+ */
+static void qtrle_decode_data (video_decoder_t *this_gen,
+ buf_element_t *buf) {
+
+ qtrle_decoder_t *this = (qtrle_decoder_t *) this_gen;
+ xine_bmiheader *bih;
+ palette_entry_t *palette;
+ int i;
+
+ vo_frame_t *img; /* video out frame */
+
+ /* a video decoder does not care about this flag (?) */
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW)
+ return;
+
+ if ((buf->decoder_flags & BUF_FLAG_SPECIAL) &&
+ (buf->decoder_info[1] == BUF_SPECIAL_PALETTE)) {
+ palette = (palette_entry_t *)buf->decoder_info[3];
+ for (i = 0; i < buf->decoder_info[2]; i++) {
+ this->yuv_palette[i * 4 + 0] =
+ COMPUTE_Y(palette[i].r, palette[i].g, palette[i].b);
+ this->yuv_palette[i * 4 + 1] =
+ COMPUTE_U(palette[i].r, palette[i].g, palette[i].b);
+ this->yuv_palette[i * 4 + 2] =
+ COMPUTE_V(palette[i].r, palette[i].g, palette[i].b);
+ }
+ }
+
+ if (buf->decoder_flags & BUF_FLAG_HEADER) { /* need to initialize */
+ this->video_out->open (this->video_out);
+
+ if(this->buf)
+ free(this->buf);
+
+ bih = (xine_bmiheader *) buf->content;
+ this->width = (bih->biWidth + 3) & ~0x03;
+ this->height = (bih->biHeight + 3) & ~0x03;
+ this->depth = bih->biBitCount;
+ this->video_step = buf->decoder_info[1];
+
+ if (this->buf)
+ free (this->buf);
+ this->bufsize = VIDEOBUFSIZE;
+ this->buf = malloc(this->bufsize);
+ this->size = 0;
+
+ init_yuv_planes(&this->yuv_planes, this->width, this->height);
+
+ this->video_out->open (this->video_out);
+ this->decoder_ok = 1;
+
+ return;
+ } else if (this->decoder_ok) {
+
+ if (this->size + buf->size > this->bufsize) {
+ this->bufsize = this->size + 2 * buf->size;
+ this->buf = realloc (this->buf, this->bufsize);
+ }
+
+ xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size);
+
+ this->size += buf->size;
+
+ if (buf->decoder_flags & BUF_FLAG_FRAMERATE)
+ this->video_step = buf->decoder_info[0];
+
+ if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
+
+ img = this->video_out->get_frame (this->video_out,
+ this->width, this->height,
+ XINE_VO_ASPECT_DONT_TOUCH,
+ XINE_IMGFMT_YUY2, VO_BOTH_FIELDS);
+
+ switch (this->depth & 0x1F) {
+
+ case 1:
+ decode_qtrle_1(this);
+ break;
+
+ case 2:
+ decode_qtrle_2(this);
+ break;
+
+ case 4:
+ decode_qtrle_4(this);
+ break;
+
+ case 8:
+ decode_qtrle_8(this);
+ break;
+
+ case 16:
+ decode_qtrle_16(this);
+ break;
+
+ case 24:
+ decode_qtrle_24(this);
+ break;
+
+ case 32:
+ decode_qtrle_32(this);
+ break;
+
+ }
+
+ yuv444_to_yuy2(&this->yuv_planes, img->base[0], img->pitches[0]);
+
+ img->duration = this->video_step;
+ img->pts = buf->pts;
+ img->bad_frame = 0;
+
+ if (img->copy) {
+ int height = img->height;
+ uint8_t *src[3];
+
+ src[0] = img->base[0];
+
+ while ((height -= 16) >= 0) {
+ img->copy(img, src);
+ src[0] += 16 * img->pitches[0];
+ }
+ }
+
+ img->draw(img);
+ img->free(img);
+
+ this->size = 0;
+ }
+ }
+}
+
+/*
+ * This function is called when xine needs to flush the system. Not
+ * sure when or if this is used or even if it needs to do anything.
+ */
+static void qtrle_flush (video_decoder_t *this_gen) {
+}
+
+/*
+ * This function resets the video decoder.
+ */
+static void qtrle_reset (video_decoder_t *this_gen) {
+ qtrle_decoder_t *this = (qtrle_decoder_t *) this_gen;
+
+ this->size = 0;
+}
+
+/*
+ * This function is called when xine shuts down the decoder. It should
+ * free any memory and release any other resources allocated during the
+ * execution of the decoder.
+ */
+static void qtrle_close (video_decoder_t *this_gen) {
+ qtrle_decoder_t *this = (qtrle_decoder_t *) this_gen;
+
+ if (this->buf) {
+ free (this->buf);
+ this->buf = NULL;
+ }
+
+ if (this->decoder_ok) {
+ this->decoder_ok = 0;
+ this->video_out->close(this->video_out);
+ }
+}
+
+/*
+ * This function returns the human-readable ID string to identify
+ * this decoder.
+ */
+static char *qtrle_get_id(void) {
+ return "QT RLE";
+}
+
+/*
+ * This function frees the video decoder instance allocated to the decoder.
+ */
+static void qtrle_dispose (video_decoder_t *this_gen) {
+ free (this_gen);
+}
+
+/*
+ * This function should be the plugin's only advertised function to the
+ * outside world. It allows xine to query the plugin module for the addresses
+ * to the necessary functions in the video decoder object.
+ */
+static void *init_video_decoder_plugin (xine_t *xine, void *data) {
+
+ qtrle_decoder_t *this ;
+
+ this = (qtrle_decoder_t *) malloc (sizeof (qtrle_decoder_t));
+ memset(this, 0, sizeof (qtrle_decoder_t));
+
+ this->video_decoder.init = qtrle_init;
+ this->video_decoder.decode_data = qtrle_decode_data;
+ this->video_decoder.flush = qtrle_flush;
+ this->video_decoder.reset = qtrle_reset;
+ this->video_decoder.close = qtrle_close;
+ this->video_decoder.get_identifier = qtrle_get_id;
+ this->video_decoder.dispose = qtrle_dispose;
+
+ return (video_decoder_t *) this;
+}
+
+/*
+ * exported plugin catalog entry
+ */
+static uint32_t video_types[] = {
+ BUF_VIDEO_QTRLE,
+ 0
+};
+
+static decoder_info_t dec_info_video = {
+ video_types, /* supported types */
+ 5 /* priority */
+};
+
+plugin_info_t xine_plugin_info[] = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_VIDEO_DECODER, 10, "qtrle", XINE_VERSION_CODE, &dec_info_video, init_video_decoder_plugin },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};