Merge commit 'c6303f8d70c25dd6c6e6486c78bf99c9924e2b6b'

* commit 'c6303f8d70c25dd6c6e6486c78bf99c9924e2b6b':
  yop: simplify/sanitize the decoding loop
  c93: set palette_has_changed.
  bmp: cosmetics, reformat
  hlsenc: Don't duplicate a string constant

Conflicts:
	libavcodec/bmp.c
	tests/ref/fate/yop

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-12-24 15:42:52 +01:00
commit 9dbedf331e
4 changed files with 84 additions and 94 deletions

View File

@ -25,7 +25,8 @@
#include "internal.h" #include "internal.h"
#include "msrledec.h" #include "msrledec.h"
static av_cold int bmp_decode_init(AVCodecContext *avctx){ static av_cold int bmp_decode_init(AVCodecContext *avctx)
{
BMPContext *s = avctx->priv_data; BMPContext *s = avctx->priv_data;
avcodec_get_frame_defaults(&s->picture); avcodec_get_frame_defaults(&s->picture);
@ -39,10 +40,10 @@ static int bmp_decode_frame(AVCodecContext *avctx,
AVPacket *avpkt) AVPacket *avpkt)
{ {
const uint8_t *buf = avpkt->data; const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size; int buf_size = avpkt->size;
BMPContext *s = avctx->priv_data; BMPContext *s = avctx->priv_data;
AVFrame *picture = data; AVFrame *picture = data;
AVFrame *p = &s->picture; AVFrame *p = &s->picture;
unsigned int fsize, hsize; unsigned int fsize, hsize;
int width, height; int width, height;
unsigned int depth; unsigned int depth;
@ -56,19 +57,19 @@ static int bmp_decode_frame(AVCodecContext *avctx,
const uint8_t *buf0 = buf; const uint8_t *buf0 = buf;
GetByteContext gb; GetByteContext gb;
if(buf_size < 14){ if (buf_size < 14) {
av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size); av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
return -1; return -1;
} }
if(bytestream_get_byte(&buf) != 'B' || if (bytestream_get_byte(&buf) != 'B' ||
bytestream_get_byte(&buf) != 'M') { bytestream_get_byte(&buf) != 'M') {
av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
return -1; return -1;
} }
fsize = bytestream_get_le32(&buf); fsize = bytestream_get_le32(&buf);
if(buf_size < fsize){ if (buf_size < fsize) {
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n", av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n",
buf_size, fsize); buf_size, fsize);
fsize = buf_size; fsize = buf_size;
@ -77,30 +78,30 @@ static int bmp_decode_frame(AVCodecContext *avctx,
buf += 2; /* reserved1 */ buf += 2; /* reserved1 */
buf += 2; /* reserved2 */ buf += 2; /* reserved2 */
hsize = bytestream_get_le32(&buf); /* header size */ hsize = bytestream_get_le32(&buf); /* header size */
ihsize = bytestream_get_le32(&buf); /* more header size */ ihsize = bytestream_get_le32(&buf); /* more header size */
if(ihsize + 14 > hsize){ if (ihsize + 14 > hsize) {
av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
return -1; return -1;
} }
/* sometimes file size is set to some headers size, set a real size in that case */ /* sometimes file size is set to some headers size, set a real size in that case */
if(fsize == 14 || fsize == ihsize + 14) if (fsize == 14 || fsize == ihsize + 14)
fsize = buf_size - 2; fsize = buf_size - 2;
if(fsize <= hsize){ if (fsize <= hsize) {
av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n", av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n",
fsize, hsize); fsize, hsize);
return -1; return -1;
} }
switch(ihsize){ switch (ihsize) {
case 40: // windib case 40: // windib
case 56: // windib v3 case 56: // windib v3
case 64: // OS/2 v2 case 64: // OS/2 v2
case 108: // windib v4 case 108: // windib v4
case 124: // windib v5 case 124: // windib v5
width = bytestream_get_le32(&buf); width = bytestream_get_le32(&buf);
height = bytestream_get_le32(&buf); height = bytestream_get_le32(&buf);
break; break;
case 12: // OS/2 v1 case 12: // OS/2 v1
@ -112,7 +113,8 @@ static int bmp_decode_frame(AVCodecContext *avctx,
return -1; return -1;
} }
if(bytestream_get_le16(&buf) != 1){ /* planes */ /* planes */
if (bytestream_get_le16(&buf) != 1) {
av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
return -1; return -1;
} }
@ -124,12 +126,13 @@ static int bmp_decode_frame(AVCodecContext *avctx,
else else
comp = BMP_RGB; comp = BMP_RGB;
if(comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && comp != BMP_RLE8){ if (comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 &&
comp != BMP_RLE8) {
av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
return -1; return -1;
} }
if(comp == BMP_BITFIELDS){ if (comp == BMP_BITFIELDS) {
buf += 20; buf += 20;
rgb[0] = bytestream_get_le32(&buf); rgb[0] = bytestream_get_le32(&buf);
rgb[1] = bytestream_get_le32(&buf); rgb[1] = bytestream_get_le32(&buf);
@ -137,14 +140,14 @@ static int bmp_decode_frame(AVCodecContext *avctx,
alpha = bytestream_get_le32(&buf); alpha = bytestream_get_le32(&buf);
} }
avctx->width = width; avctx->width = width;
avctx->height = height > 0? height: -height; avctx->height = height > 0 ? height : -height;
avctx->pix_fmt = AV_PIX_FMT_NONE; avctx->pix_fmt = AV_PIX_FMT_NONE;
switch(depth){ switch (depth) {
case 32: case 32:
if(comp == BMP_BITFIELDS){ if (comp == BMP_BITFIELDS) {
if (rgb[0] == 0xFF000000 && rgb[1] == 0x00FF0000 && rgb[2] == 0x0000FF00) if (rgb[0] == 0xFF000000 && rgb[1] == 0x00FF0000 && rgb[2] == 0x0000FF00)
avctx->pix_fmt = alpha ? AV_PIX_FMT_ABGR : AV_PIX_FMT_0BGR; avctx->pix_fmt = alpha ? AV_PIX_FMT_ABGR : AV_PIX_FMT_0BGR;
else if (rgb[0] == 0x00FF0000 && rgb[1] == 0x0000FF00 && rgb[2] == 0x000000FF) else if (rgb[0] == 0x00FF0000 && rgb[1] == 0x0000FF00 && rgb[2] == 0x000000FF)
@ -165,7 +168,7 @@ static int bmp_decode_frame(AVCodecContext *avctx,
avctx->pix_fmt = AV_PIX_FMT_BGR24; avctx->pix_fmt = AV_PIX_FMT_BGR24;
break; break;
case 16: case 16:
if(comp == BMP_RGB) if (comp == BMP_RGB)
avctx->pix_fmt = AV_PIX_FMT_RGB555; avctx->pix_fmt = AV_PIX_FMT_RGB555;
else if (comp == BMP_BITFIELDS) { else if (comp == BMP_BITFIELDS) {
if (rgb[0] == 0xF800 && rgb[1] == 0x07E0 && rgb[2] == 0x001F) if (rgb[0] == 0xF800 && rgb[1] == 0x07E0 && rgb[2] == 0x001F)
@ -181,16 +184,16 @@ static int bmp_decode_frame(AVCodecContext *avctx,
} }
break; break;
case 8: case 8:
if(hsize - ihsize - 14 > 0) if (hsize - ihsize - 14 > 0)
avctx->pix_fmt = AV_PIX_FMT_PAL8; avctx->pix_fmt = AV_PIX_FMT_PAL8;
else else
avctx->pix_fmt = AV_PIX_FMT_GRAY8; avctx->pix_fmt = AV_PIX_FMT_GRAY8;
break; break;
case 1: case 1:
case 4: case 4:
if(hsize - ihsize - 14 > 0){ if (hsize - ihsize - 14 > 0) {
avctx->pix_fmt = AV_PIX_FMT_PAL8; avctx->pix_fmt = AV_PIX_FMT_PAL8;
}else{ } else {
av_log(avctx, AV_LOG_ERROR, "Unknown palette for %d-colour BMP\n", 1<<depth); av_log(avctx, AV_LOG_ERROR, "Unknown palette for %d-colour BMP\n", 1<<depth);
return -1; return -1;
} }
@ -200,84 +203,85 @@ static int bmp_decode_frame(AVCodecContext *avctx,
return -1; return -1;
} }
if(avctx->pix_fmt == AV_PIX_FMT_NONE){ if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
return -1; return -1;
} }
if(p->data[0]) if (p->data[0])
avctx->release_buffer(avctx, p); avctx->release_buffer(avctx, p);
p->reference = 0; p->reference = 0;
if(ff_get_buffer(avctx, p) < 0){ if (ff_get_buffer(avctx, p) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1; return -1;
} }
p->pict_type = AV_PICTURE_TYPE_I; p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1; p->key_frame = 1;
buf = buf0 + hsize; buf = buf0 + hsize;
dsize = buf_size - hsize; dsize = buf_size - hsize;
/* Line size in file multiple of 4 */ /* Line size in file multiple of 4 */
n = ((avctx->width * depth + 31) / 8) & ~3; n = ((avctx->width * depth + 31) / 8) & ~3;
if(n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8){ if (n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8) {
av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
dsize, n * avctx->height); dsize, n * avctx->height);
return -1; return -1;
} }
// RLE may skip decoding some picture areas, so blank picture before decoding // RLE may skip decoding some picture areas, so blank picture before decoding
if(comp == BMP_RLE4 || comp == BMP_RLE8) if (comp == BMP_RLE4 || comp == BMP_RLE8)
memset(p->data[0], 0, avctx->height * p->linesize[0]); memset(p->data[0], 0, avctx->height * p->linesize[0]);
if(height > 0){ if (height > 0) {
ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; ptr = p->data[0] + (avctx->height - 1) * p->linesize[0];
linesize = -p->linesize[0]; linesize = -p->linesize[0];
} else { } else {
ptr = p->data[0]; ptr = p->data[0];
linesize = p->linesize[0]; linesize = p->linesize[0];
} }
if(avctx->pix_fmt == AV_PIX_FMT_PAL8){ if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
int colors = 1 << depth; int colors = 1 << depth;
memset(p->data[1], 0, 1024); memset(p->data[1], 0, 1024);
if(ihsize >= 36){ if (ihsize >= 36) {
int t; int t;
buf = buf0 + 46; buf = buf0 + 46;
t = bytestream_get_le32(&buf); t = bytestream_get_le32(&buf);
if(t < 0 || t > (1 << depth)){ if (t < 0 || t > (1 << depth)) {
av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth); av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth);
}else if(t){ } else if (t) {
colors = t; colors = t;
} }
} }
buf = buf0 + 14 + ihsize; //palette location buf = buf0 + 14 + ihsize; //palette location
if((hsize-ihsize-14) < (colors << 2)){ // OS/2 bitmap, 3 bytes per palette entry // OS/2 bitmap, 3 bytes per palette entry
for(i = 0; i < colors; i++) if ((hsize-ihsize-14) < (colors << 2)) {
for (i = 0; i < colors; i++)
((uint32_t*)p->data[1])[i] = (0xFFU<<24) | bytestream_get_le24(&buf); ((uint32_t*)p->data[1])[i] = (0xFFU<<24) | bytestream_get_le24(&buf);
}else{ } else {
for(i = 0; i < colors; i++) for (i = 0; i < colors; i++)
((uint32_t*)p->data[1])[i] = 0xFFU << 24 | bytestream_get_le32(&buf); ((uint32_t*)p->data[1])[i] = 0xFFU << 24 | bytestream_get_le32(&buf);
} }
buf = buf0 + hsize; buf = buf0 + hsize;
} }
if(comp == BMP_RLE4 || comp == BMP_RLE8){ if (comp == BMP_RLE4 || comp == BMP_RLE8) {
if(height < 0){ if (height < 0) {
p->data[0] += p->linesize[0] * (avctx->height - 1); p->data[0] += p->linesize[0] * (avctx->height - 1);
p->linesize[0] = -p->linesize[0]; p->linesize[0] = -p->linesize[0];
} }
bytestream2_init(&gb, buf, dsize); bytestream2_init(&gb, buf, dsize);
ff_msrle_decode(avctx, (AVPicture*)p, depth, &gb); ff_msrle_decode(avctx, (AVPicture*)p, depth, &gb);
if(height < 0){ if (height < 0) {
p->data[0] += p->linesize[0] * (avctx->height - 1); p->data[0] += p->linesize[0] * (avctx->height - 1);
p->linesize[0] = -p->linesize[0]; p->linesize[0] = -p->linesize[0];
} }
}else{ } else {
switch(depth){ switch (depth) {
case 1: case 1:
for (i = 0; i < avctx->height; i++) { for (i = 0; i < avctx->height; i++) {
int j; int j;
@ -298,16 +302,16 @@ static int bmp_decode_frame(AVCodecContext *avctx,
case 8: case 8:
case 24: case 24:
case 32: case 32:
for(i = 0; i < avctx->height; i++){ for (i = 0; i < avctx->height; i++) {
memcpy(ptr, buf, n); memcpy(ptr, buf, n);
buf += n; buf += n;
ptr += linesize; ptr += linesize;
} }
break; break;
case 4: case 4:
for(i = 0; i < avctx->height; i++){ for (i = 0; i < avctx->height; i++) {
int j; int j;
for(j = 0; j < n; j++){ for (j = 0; j < n; j++) {
ptr[j*2+0] = (buf[j] >> 4) & 0xF; ptr[j*2+0] = (buf[j] >> 4) & 0xF;
ptr[j*2+1] = buf[j] & 0xF; ptr[j*2+1] = buf[j] & 0xF;
} }
@ -316,11 +320,11 @@ static int bmp_decode_frame(AVCodecContext *avctx,
} }
break; break;
case 16: case 16:
for(i = 0; i < avctx->height; i++){ for (i = 0; i < avctx->height; i++) {
const uint16_t *src = (const uint16_t *) buf; const uint16_t *src = (const uint16_t *) buf;
uint16_t *dst = (uint16_t *) ptr; uint16_t *dst = (uint16_t *) ptr;
for(j = 0; j < avctx->width; j++) for (j = 0; j < avctx->width; j++)
*dst++ = av_le2ne16(*src++); *dst++ = av_le2ne16(*src++);
buf += n; buf += n;

View File

@ -237,6 +237,7 @@ static int decode_frame(AVCodecContext *avctx, void *data,
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
palette[i] = 0xFFU << 24 | bytestream2_get_be24(&gb); palette[i] = 0xFFU << 24 | bytestream2_get_be24(&gb);
} }
newpic->palette_has_changed = 1;
} else { } else {
if (oldpic->data[1]) if (oldpic->data[1])
memcpy(newpic->data[1], oldpic->data[1], 256 * 4); memcpy(newpic->data[1], oldpic->data[1], 256 * 4);

View File

@ -36,7 +36,6 @@ typedef struct YopDecContext {
int num_pal_colors; int num_pal_colors;
int first_color[2]; int first_color[2];
int frame_data_length; int frame_data_length;
int row_pos;
uint8_t *low_nibble; uint8_t *low_nibble;
uint8_t *srcptr; uint8_t *srcptr;
@ -177,27 +176,12 @@ static uint8_t yop_get_next_nibble(YopDecContext *s)
return ret; return ret;
} }
/**
* Take s->dstptr to the next macroblock in sequence.
*/
static void yop_next_macroblock(YopDecContext *s)
{
// If we are advancing to the next row of macroblocks
if (s->row_pos == s->frame.linesize[0] - 2) {
s->dstptr += s->frame.linesize[0];
s->row_pos = 0;
}else {
s->row_pos += 2;
}
s->dstptr += 2;
}
static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt) AVPacket *avpkt)
{ {
YopDecContext *s = avctx->priv_data; YopDecContext *s = avctx->priv_data;
int tag, firstcolor, is_odd_frame; int tag, firstcolor, is_odd_frame;
int ret, i; int ret, i, x, y;
uint32_t *palette; uint32_t *palette;
if (s->frame.data[0]) if (s->frame.data[0])
@ -214,12 +198,9 @@ static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
return ret; return ret;
} }
s->frame.linesize[0] = avctx->width;
s->dstbuf = s->frame.data[0]; s->dstbuf = s->frame.data[0];
s->dstptr = s->frame.data[0]; s->dstptr = s->frame.data[0];
s->srcptr = avpkt->data + 4; s->srcptr = avpkt->data + 4;
s->row_pos = 0;
s->low_nibble = NULL; s->low_nibble = NULL;
is_odd_frame = avpkt->data[0]; is_odd_frame = avpkt->data[0];
@ -240,23 +221,28 @@ static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
s->frame.palette_has_changed = 1; s->frame.palette_has_changed = 1;
while (s->dstptr - s->dstbuf < for (y = 0; y < avctx->height; y += 2) {
avctx->width * avctx->height && for (x = 0; x < avctx->width; x += 2) {
s->srcptr - avpkt->data < avpkt->size) { if (s->srcptr - avpkt->data >= avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "Packet too small.\n");
tag = yop_get_next_nibble(s); return AVERROR_INVALIDDATA;
if (tag != 0xf) {
yop_paint_block(s, tag);
}else {
tag = yop_get_next_nibble(s);
ret = yop_copy_previous_block(s, tag);
if (ret < 0) {
avctx->release_buffer(avctx, &s->frame);
return ret;
} }
tag = yop_get_next_nibble(s);
if (tag != 0xf) {
yop_paint_block(s, tag);
} else {
tag = yop_get_next_nibble(s);
ret = yop_copy_previous_block(s, tag);
if (ret < 0) {
avctx->release_buffer(avctx, &s->frame);
return ret;
}
}
s->dstptr += 2;
} }
yop_next_macroblock(s); s->dstptr += 2*s->frame.linesize[0] - x;
} }
*got_frame = 1; *got_frame = 1;

View File

@ -5,4 +5,3 @@
0, 3, 3, 1, 302760, 0xe0fc92da 0, 3, 3, 1, 302760, 0xe0fc92da
0, 4, 4, 1, 302760, 0xd7699bb4 0, 4, 4, 1, 302760, 0xd7699bb4
0, 5, 5, 1, 302760, 0x26e93266 0, 5, 5, 1, 302760, 0x26e93266
0, 6, 6, 1, 302760, 0x4cddb216