Originally committed as revision 2451 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
@@ -453,7 +453,13 @@ typedef struct AVPanScan{ | |||
* - decoding: set by lavc\ | |||
*/\ | |||
AVPanScan *pan_scan;\ | |||
\ | |||
/**\ | |||
* tell user application that palette has changed from previous frame.\ | |||
* - encoding: ??? (no palette-enabled encoder yet)\ | |||
* - decoding: set by lavc (default 0)\ | |||
*/\ | |||
int palette_has_changed;\ | |||
#define FF_QSCALE_TYPE_MPEG1 0 | |||
#define FF_QSCALE_TYPE_MPEG2 1 | |||
@@ -1345,6 +1351,13 @@ typedef struct AVCodecContext { | |||
* - decoding: unused | |||
*/ | |||
int lmax; | |||
/** | |||
* Palette control structure | |||
* - encoding: ??? (no palette-enabled encoder yet) | |||
* - decoding: set by user. | |||
*/ | |||
struct AVPaletteControl *palctrl; | |||
} AVCodecContext; | |||
@@ -1426,17 +1439,18 @@ typedef struct AVPicture { | |||
* This structure defines a method for communicating palette changes | |||
* between and demuxer and a decoder. | |||
*/ | |||
#define AVPALETTE_SIZE 256 | |||
typedef struct AVPaletteControl { | |||
/* demuxer sets this to 1 to indicate the palette has changed; | |||
* decoder resets to 0 */ | |||
int palette_changed; | |||
/* 256 3-byte RGB palette entries; the components should be | |||
* formatted in the buffer as "RGBRGB..." and should be scaled to | |||
* 8 bits if they originally represented 6-bit VGA palette | |||
* components */ | |||
unsigned char palette[256 * 3]; | |||
/* 4-byte ARGB palette entries, stored in native byte order; note that | |||
* the individual palette components should be on a 8-bit scale; if | |||
* the palette data comes from a IBM VGA native format, the component | |||
* data is probably 6 bits in size and needs to be scaled */ | |||
unsigned int palette[AVPALETTE_SIZE]; | |||
} AVPaletteControl; | |||
@@ -72,8 +72,6 @@ typedef struct IdcinContext { | |||
unsigned char *buf; | |||
int size; | |||
unsigned char palette[PALETTE_COUNT * 4]; | |||
hnode_t huff_nodes[256][HUF_TOKENS*2]; | |||
int num_huff_nodes[256]; | |||
@@ -218,27 +216,11 @@ static int idcin_decode_frame(AVCodecContext *avctx, | |||
uint8_t *buf, int buf_size) | |||
{ | |||
IdcinContext *s = (IdcinContext *)avctx->priv_data; | |||
AVPaletteControl *palette_control = | |||
(AVPaletteControl *)avctx->extradata; | |||
int i; | |||
unsigned int *palette32; | |||
int palette_index = 0; | |||
unsigned char r, g, b; | |||
AVPaletteControl *palette_control = avctx->palctrl; | |||
s->buf = buf; | |||
s->size = buf_size; | |||
if (palette_control->palette_changed) { | |||
palette32 = (unsigned int *)s->palette; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = palette_control->palette[palette_index++] * 1; | |||
g = palette_control->palette[palette_index++] * 1; | |||
b = palette_control->palette[palette_index++] * 1; | |||
palette32[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
palette_control->palette_changed = 0; | |||
} | |||
if (s->frame.data[0]) | |||
avctx->release_buffer(avctx, &s->frame); | |||
@@ -250,7 +232,12 @@ static int idcin_decode_frame(AVCodecContext *avctx, | |||
idcin_decode_vlcs(s); | |||
/* make the palette available on the way out */ | |||
memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4); | |||
memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4); | |||
/* If palette changed inform application*/ | |||
if (palette_control->palette_changed) { | |||
palette_control->palette_changed = 0; | |||
s->frame.palette_has_changed = 1; | |||
} | |||
*data_size = sizeof(AVFrame); | |||
*(AVFrame*)data = s->frame; | |||
@@ -65,8 +65,6 @@ typedef struct IpvideoContext { | |||
unsigned char *buf; | |||
int size; | |||
unsigned char palette[PALETTE_COUNT * 4]; | |||
unsigned char *stream_ptr; | |||
unsigned char *stream_end; | |||
unsigned char *pixel_ptr; | |||
@@ -83,21 +81,6 @@ typedef struct IpvideoContext { | |||
return -1; \ | |||
} | |||
static void ipvideo_new_palette(IpvideoContext *s, unsigned char *palette) { | |||
int i; | |||
unsigned char r, g, b; | |||
unsigned int *palette32; | |||
palette32 = (unsigned int *)s->palette; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette++; | |||
g = *palette++; | |||
b = *palette++; | |||
palette32[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
} | |||
#define COPY_FROM_CURRENT() \ | |||
motion_offset = current_offset; \ | |||
motion_offset += y * s->stride; \ | |||
@@ -828,7 +811,7 @@ static void ipvideo_decode_opcodes(IpvideoContext *s) | |||
code_counts[x] = 0; | |||
/* this is PAL8, so make the palette available */ | |||
memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4); | |||
memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4); | |||
s->stride = s->current_frame.linesize[0]; | |||
s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */ | |||
@@ -874,9 +857,8 @@ static int ipvideo_decode_init(AVCodecContext *avctx) | |||
s->avctx = avctx; | |||
if (s->avctx->extradata_size != sizeof(AVPaletteControl)) { | |||
printf (" Interplay video: expected extradata_size of %d\n", | |||
(int)sizeof(AVPaletteControl)); | |||
if (s->avctx->palctrl == NULL) { | |||
printf (" Interplay video: palette expected.\n"); | |||
return -1; | |||
} | |||
@@ -916,13 +898,7 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, | |||
uint8_t *buf, int buf_size) | |||
{ | |||
IpvideoContext *s = avctx->priv_data; | |||
AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata; | |||
if (palette_control->palette_changed) { | |||
/* load the new palette and reset the palette control */ | |||
ipvideo_new_palette(s, palette_control->palette); | |||
palette_control->palette_changed = 0; | |||
} | |||
AVPaletteControl *palette_control = avctx->palctrl; | |||
s->decoding_map = buf; | |||
s->buf = buf + s->decoding_map_size; | |||
@@ -936,6 +912,11 @@ static int ipvideo_decode_frame(AVCodecContext *avctx, | |||
ipvideo_decode_opcodes(s); | |||
if (palette_control->palette_changed) { | |||
palette_control->palette_changed = 0; | |||
s->current_frame.palette_has_changed = 1; | |||
} | |||
*data_size = sizeof(AVFrame); | |||
*(AVFrame*)data = s->current_frame; | |||
@@ -318,6 +318,7 @@ void avcodec_get_context_defaults(AVCodecContext *s){ | |||
s->intra_quant_bias= FF_DEFAULT_QUANT_BIAS; | |||
s->inter_quant_bias= FF_DEFAULT_QUANT_BIAS; | |||
s->palctrl = NULL; | |||
} | |||
/** | |||
@@ -120,7 +120,7 @@ typedef struct VqaContext { | |||
unsigned char *buf; | |||
int size; | |||
unsigned char palette[PALETTE_COUNT * 4]; | |||
unsigned int palette[PALETTE_COUNT]; | |||
int width; /* width of a frame */ | |||
int height; /* height of a frame */ | |||
@@ -311,7 +311,6 @@ static void vqa_decode_chunk(VqaContext *s) | |||
unsigned int index = 0; | |||
int i; | |||
unsigned char r, g, b; | |||
unsigned int *palette32; | |||
int index_shift; | |||
int cbf0_chunk = -1; | |||
@@ -407,13 +406,12 @@ static void vqa_decode_chunk(VqaContext *s) | |||
return; | |||
} | |||
cpl0_chunk += CHUNK_PREAMBLE_SIZE; | |||
palette32 = (unsigned int *)s->palette; | |||
for (i = 0; i < chunk_size / 3; i++) { | |||
/* scale by 4 to transform 6-bit palette -> 8-bit */ | |||
r = s->buf[cpl0_chunk++] * 4; | |||
g = s->buf[cpl0_chunk++] * 4; | |||
b = s->buf[cpl0_chunk++] * 4; | |||
palette32[i] = (r << 16) | (g << 8) | (b); | |||
s->palette[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
} | |||
@@ -583,6 +581,7 @@ static int vqa_decode_frame(AVCodecContext *avctx, | |||
/* make the palette available on the way out */ | |||
memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4); | |||
s->frame.palette_has_changed = 1; | |||
*data_size = sizeof(AVFrame); | |||
*(AVFrame*)data = s->frame; | |||
@@ -115,9 +115,8 @@ static int xan_decode_init(AVCodecContext *avctx) | |||
s->avctx = avctx; | |||
if ((avctx->codec->id == CODEC_ID_XAN_WC3) && | |||
(s->avctx->extradata_size != sizeof(AVPaletteControl))) { | |||
printf (" WC3 Xan video: expected extradata_size of %d\n", | |||
sizeof(AVPaletteControl)); | |||
(s->avctx->palctrl == NULL)) { | |||
printf (" WC3 Xan video: palette expected.\n"); | |||
return -1; | |||
} | |||
@@ -253,12 +252,13 @@ static void xan_unpack(unsigned char *dest, unsigned char *src) | |||
} | |||
static void inline xan_wc3_build_palette(XanContext *s, | |||
unsigned char *palette_data) | |||
unsigned int *palette_data) | |||
{ | |||
int i; | |||
unsigned char r, g, b; | |||
unsigned short *palette16; | |||
unsigned int *palette32; | |||
unsigned int pal_elem; | |||
/* transform the palette passed through the palette control structure | |||
* into the necessary internal format depending on colorspace */ | |||
@@ -268,9 +268,10 @@ static void inline xan_wc3_build_palette(XanContext *s, | |||
case PIX_FMT_RGB555: | |||
palette16 = (unsigned short *)s->palette; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette_data++; | |||
g = *palette_data++; | |||
b = *palette_data++; | |||
pal_elem = palette_data[i]; | |||
r = (pal_elem >> 16) & 0xff; | |||
g = (pal_elem >> 8) & 0xff; | |||
b = pal_elem & 0xff; | |||
palette16[i] = | |||
((r >> 3) << 10) | | |||
((g >> 3) << 5) | | |||
@@ -281,9 +282,10 @@ static void inline xan_wc3_build_palette(XanContext *s, | |||
case PIX_FMT_RGB565: | |||
palette16 = (unsigned short *)s->palette; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette_data++; | |||
g = *palette_data++; | |||
b = *palette_data++; | |||
pal_elem = palette_data[i]; | |||
r = (pal_elem >> 16) & 0xff; | |||
g = (pal_elem >> 8) & 0xff; | |||
b = pal_elem & 0xff; | |||
palette16[i] = | |||
((r >> 3) << 11) | | |||
((g >> 2) << 5) | | |||
@@ -293,17 +295,22 @@ static void inline xan_wc3_build_palette(XanContext *s, | |||
case PIX_FMT_RGB24: | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
s->palette[i * 4 + 0] = *palette_data++; | |||
s->palette[i * 4 + 1] = *palette_data++; | |||
s->palette[i * 4 + 2] = *palette_data++; | |||
pal_elem = palette_data[i]; | |||
r = (pal_elem >> 16) & 0xff; | |||
g = (pal_elem >> 8) & 0xff; | |||
b = pal_elem & 0xff; | |||
s->palette[i * 4 + 0] = r; | |||
s->palette[i * 4 + 1] = g; | |||
s->palette[i * 4 + 2] = b; | |||
} | |||
break; | |||
case PIX_FMT_BGR24: | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette_data++; | |||
g = *palette_data++; | |||
b = *palette_data++; | |||
pal_elem = palette_data[i]; | |||
r = (pal_elem >> 16) & 0xff; | |||
g = (pal_elem >> 8) & 0xff; | |||
b = pal_elem & 0xff; | |||
s->palette[i * 4 + 0] = b; | |||
s->palette[i * 4 + 1] = g; | |||
s->palette[i * 4 + 2] = r; | |||
@@ -313,19 +320,15 @@ static void inline xan_wc3_build_palette(XanContext *s, | |||
case PIX_FMT_PAL8: | |||
case PIX_FMT_RGBA32: | |||
palette32 = (unsigned int *)s->palette; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette_data++; | |||
g = *palette_data++; | |||
b = *palette_data++; | |||
palette32[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
memcpy (palette32, palette_data, PALETTE_COUNT * sizeof(unsigned int)); | |||
break; | |||
case PIX_FMT_YUV444P: | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = *palette_data++; | |||
g = *palette_data++; | |||
b = *palette_data++; | |||
pal_elem = palette_data[i]; | |||
r = (pal_elem >> 16) & 0xff; | |||
g = (pal_elem >> 8) & 0xff; | |||
b = pal_elem & 0xff; | |||
s->palette[i * 4 + 0] = COMPUTE_Y(r, g, b); | |||
s->palette[i * 4 + 1] = COMPUTE_U(r, g, b); | |||
s->palette[i * 4 + 2] = COMPUTE_V(r, g, b); | |||
@@ -730,8 +733,11 @@ static void xan_wc3_decode_frame(XanContext *s) { | |||
} | |||
/* for PAL8, make the palette available on the way out */ | |||
if (s->avctx->pix_fmt == PIX_FMT_PAL8) | |||
if (s->avctx->pix_fmt == PIX_FMT_PAL8) { | |||
memcpy(s->current_frame.data[1], s->palette, PALETTE_COUNT * 4); | |||
s->current_frame.palette_has_changed = 1; | |||
s->avctx->palctrl->palette_changed = 0; | |||
} | |||
} | |||
static void xan_wc4_decode_frame(XanContext *s) { | |||
@@ -742,13 +748,15 @@ static int xan_decode_frame(AVCodecContext *avctx, | |||
uint8_t *buf, int buf_size) | |||
{ | |||
XanContext *s = avctx->priv_data; | |||
AVPaletteControl *palette_control = (AVPaletteControl *)avctx->extradata; | |||
AVPaletteControl *palette_control = avctx->palctrl; | |||
int keyframe = 0; | |||
if (palette_control->palette_changed) { | |||
/* load the new palette and reset the palette control */ | |||
xan_wc3_build_palette(s, palette_control->palette); | |||
palette_control->palette_changed = 0; | |||
/* If pal8 we clear flag when we copy palette */ | |||
if (s->avctx->pix_fmt != PIX_FMT_PAL8) | |||
palette_control->palette_changed = 0; | |||
keyframe = 1; | |||
} | |||
@@ -90,8 +90,7 @@ typedef struct IdcinDemuxContext { | |||
int64_t pts; | |||
/* keep reference to extradata but never free it */ | |||
void *extradata; | |||
AVPaletteControl palctrl; | |||
} IdcinDemuxContext; | |||
static int idcin_probe(AVProbeData *p) | |||
@@ -175,7 +174,7 @@ static int idcin_read_header(AVFormatContext *s, | |||
HUFFMAN_TABLE_SIZE) | |||
return -EIO; | |||
/* save a reference in order to transport the palette */ | |||
idcin->extradata = st->codec.extradata; | |||
st->codec.palctrl = &idcin->palctrl; | |||
/* if sample rate is 0, assume no audio */ | |||
if (sample_rate) { | |||
@@ -227,9 +226,10 @@ static int idcin_read_packet(AVFormatContext *s, | |||
unsigned int chunk_size; | |||
IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data; | |||
ByteIOContext *pb = &s->pb; | |||
AVPaletteControl *palette_control = (AVPaletteControl *)idcin->extradata; | |||
int i; | |||
int palette_scale; | |||
unsigned char r, g, b; | |||
unsigned char palette_buffer[768]; | |||
if (url_feof(&s->pb)) | |||
return -EIO; | |||
@@ -240,20 +240,23 @@ static int idcin_read_packet(AVFormatContext *s, | |||
return -EIO; | |||
} else if (command == 1) { | |||
/* trigger a palette change */ | |||
palette_control->palette_changed = 1; | |||
if (get_buffer(pb, palette_control->palette, 768) != 768) | |||
idcin->palctrl.palette_changed = 1; | |||
if (get_buffer(pb, palette_buffer, 768) != 768) | |||
return -EIO; | |||
/* scale the palette as necessary */ | |||
palette_scale = 2; | |||
for (i = 0; i < 768; i++) | |||
if (palette_control->palette[i] > 63) { | |||
if (palette_buffer[i] > 63) { | |||
palette_scale = 0; | |||
break; | |||
} | |||
if (palette_scale) | |||
for (i = 0; i < 768; i++) | |||
palette_control->palette[i] <<= palette_scale; | |||
for (i = 0; i < 256; i++) { | |||
r = palette_buffer[i * 3 ] << palette_scale; | |||
g = palette_buffer[i * 3 + 1] << palette_scale; | |||
b = palette_buffer[i * 3 + 2] << palette_scale; | |||
idcin->palctrl.palette[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
} | |||
chunk_size = get_le32(pb); | |||
@@ -293,6 +296,7 @@ static int idcin_read_packet(AVFormatContext *s, | |||
static int idcin_read_close(AVFormatContext *s) | |||
{ | |||
return 0; | |||
} | |||
@@ -232,6 +232,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, | |||
int i, j; | |||
int first_color, last_color; | |||
int audio_flags; | |||
unsigned char r, g, b; | |||
/* see if there are any pending packets */ | |||
chunk_type = load_ipmovie_packet(s, pb, pkt); | |||
@@ -463,9 +464,10 @@ static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, | |||
for (i = first_color; i <= last_color; i++) { | |||
/* the palette is stored as a 6-bit VGA palette, thus each | |||
* component is shifted up to a 8-bit range */ | |||
s->palette_control.palette[i * 3 + 0] = scratch[j++] * 4; | |||
s->palette_control.palette[i * 3 + 1] = scratch[j++] * 4; | |||
s->palette_control.palette[i * 3 + 2] = scratch[j++] * 4; | |||
r = scratch[j++] * 4; | |||
g = scratch[j++] * 4; | |||
b = scratch[j++] * 4; | |||
s->palette_control.palette[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
/* indicate a palette change */ | |||
s->palette_control.palette_changed = 1; | |||
@@ -573,8 +575,7 @@ static int ipmovie_read_header(AVFormatContext *s, | |||
st->codec.height = ipmovie->video_height; | |||
/* palette considerations */ | |||
st->codec.extradata_size = sizeof(AVPaletteControl); | |||
st->codec.extradata = &ipmovie->palette_control; | |||
st->codec.palctrl = &ipmovie->palette_control; | |||
if (ipmovie->audio_type) { | |||
st = av_new_stream(s, 0); | |||
@@ -258,8 +258,7 @@ static int wc3_read_header(AVFormatContext *s, | |||
st->codec.height = wc3->height; | |||
/* palette considerations */ | |||
st->codec.extradata_size = sizeof(AVPaletteControl); | |||
st->codec.extradata = &wc3->palette_control; | |||
st->codec.palctrl = &wc3->palette_control; | |||
st = av_new_stream(s, 0); | |||
if (!st) | |||
@@ -294,6 +293,9 @@ static int wc3_read_packet(AVFormatContext *s, | |||
unsigned char preamble[WC3_PREAMBLE_SIZE]; | |||
unsigned char text[1024]; | |||
unsigned int palette_number; | |||
int i; | |||
unsigned char r, g, b; | |||
int base_palette_index; | |||
while (!packet_read) { | |||
@@ -319,9 +321,13 @@ static int wc3_read_packet(AVFormatContext *s, | |||
palette_number = LE_32(&preamble[0]); | |||
if (palette_number >= wc3->palette_count) | |||
return AVERROR_INVALIDDATA; | |||
memcpy(wc3->palette_control.palette, | |||
&wc3->palettes[palette_number * PALETTE_COUNT * 3], | |||
PALETTE_COUNT * 3); | |||
base_palette_index = palette_number * PALETTE_COUNT * 3; | |||
for (i = 0; i < PALETTE_COUNT; i++) { | |||
r = wc3->palettes[base_palette_index + i * 3 + 0]; | |||
g = wc3->palettes[base_palette_index + i * 3 + 1]; | |||
b = wc3->palettes[base_palette_index + i * 3 + 2]; | |||
wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b); | |||
} | |||
wc3->palette_control.palette_changed = 1; | |||
break; | |||