mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
avcodec/gdv: add decompression for 2 and 5 method
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
45dbb40cd1
commit
4d681269e0
107
libavcodec/gdv.c
107
libavcodec/gdv.c
@ -38,6 +38,11 @@ typedef struct GDVContext {
|
||||
unsigned scale_h, scale_v;
|
||||
} GDVContext;
|
||||
|
||||
typedef struct Bits8 {
|
||||
uint8_t queue;
|
||||
uint8_t fill;
|
||||
} Bits8;
|
||||
|
||||
typedef struct Bits32 {
|
||||
uint32_t queue;
|
||||
uint8_t fill;
|
||||
@ -124,6 +129,21 @@ static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, in
|
||||
gdv->scale_h = scale_h;
|
||||
}
|
||||
|
||||
static int read_bits2(Bits8 *bits, GetByteContext *gb)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (bits->fill == 0) {
|
||||
bits->queue |= bytestream2_get_byte(gb);
|
||||
bits->fill = 8;
|
||||
}
|
||||
res = bits->queue >> 6;
|
||||
bits->queue <<= 2;
|
||||
bits->fill -= 2;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fill_bits32(Bits32 *bits, GetByteContext *gb)
|
||||
{
|
||||
bits->queue = bytestream2_get_le32(gb);
|
||||
@ -173,6 +193,87 @@ static void lz_copy(PutByteContext *pb, GetByteContext *g2, int offset, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
static int decompress_2(AVCodecContext *avctx)
|
||||
{
|
||||
GDVContext *gdv = avctx->priv_data;
|
||||
GetByteContext *gb = &gdv->gb;
|
||||
GetByteContext *g2 = &gdv->g2;
|
||||
PutByteContext *pb = &gdv->pb;
|
||||
Bits8 bits = { 0 };
|
||||
int c, i;
|
||||
|
||||
bytestream2_init(g2, gdv->frame, gdv->frame_size);
|
||||
bytestream2_skip_p(pb, PREAMBLE_SIZE);
|
||||
|
||||
for (c = 0; c < 256; c++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
gdv->frame[c * 16 + i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
|
||||
int tag = read_bits2(&bits, gb);
|
||||
if (tag == 0) {
|
||||
bytestream2_put_byte(pb, bytestream2_get_byte(gb));
|
||||
} else if (tag == 1) {
|
||||
int b = bytestream2_get_byte(gb);
|
||||
int len = (b & 0xF) + 3;
|
||||
int top = (b >> 4) & 0xF;
|
||||
int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
|
||||
lz_copy(pb, g2, off, len);
|
||||
} else if (tag == 2) {
|
||||
int len = (bytestream2_get_byte(gb)) + 2;
|
||||
bytestream2_skip_p(pb, len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decompress_5(AVCodecContext *avctx, unsigned skip)
|
||||
{
|
||||
GDVContext *gdv = avctx->priv_data;
|
||||
GetByteContext *gb = &gdv->gb;
|
||||
GetByteContext *g2 = &gdv->g2;
|
||||
PutByteContext *pb = &gdv->pb;
|
||||
Bits8 bits = { 0 };
|
||||
|
||||
bytestream2_init(g2, gdv->frame, gdv->frame_size);
|
||||
bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
|
||||
|
||||
while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
|
||||
int tag = read_bits2(&bits, gb);
|
||||
if (tag == 0) {
|
||||
bytestream2_put_byte(pb, bytestream2_get_byte(gb));
|
||||
} else if (tag == 1) {
|
||||
int b = bytestream2_get_byte(gb);
|
||||
int len = (b & 0xF) + 3;
|
||||
int top = b >> 4;
|
||||
int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
|
||||
lz_copy(pb, g2, off, len);
|
||||
} else if (tag == 2) {
|
||||
int len;
|
||||
int b = bytestream2_get_byte(gb);
|
||||
if (b == 0) {
|
||||
break;
|
||||
}
|
||||
if (b != 0xFF) {
|
||||
len = b;
|
||||
} else {
|
||||
len = bytestream2_get_le16(gb);
|
||||
}
|
||||
bytestream2_skip_p(pb, len + 1);
|
||||
} else {
|
||||
int b = bytestream2_get_byte(gb);
|
||||
int len = (b & 0x3) + 2;
|
||||
int off = -(b >> 2) - 1;
|
||||
lz_copy(pb, g2, off, len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8)
|
||||
{
|
||||
GDVContext *gdv = avctx->priv_data;
|
||||
@ -333,8 +434,14 @@ static int gdv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
ret = decompress_2(avctx);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 5:
|
||||
ret = decompress_5(avctx, flags >> 8);
|
||||
break;
|
||||
case 6:
|
||||
ret = decompress_68(avctx, flags >> 8, 0);
|
||||
break;
|
||||
|
@ -42,14 +42,40 @@ static int gdv_read_probe(AVProbeData *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
} FixedSize[] = {
|
||||
{ 0, 320, 200},
|
||||
{ 1, 640, 200},
|
||||
{ 2, 320, 167},
|
||||
{ 3, 320, 180},
|
||||
{ 4, 320, 400},
|
||||
{ 5, 320, 170},
|
||||
{ 6, 160, 85},
|
||||
{ 7, 160, 83},
|
||||
{ 8, 160, 90},
|
||||
{ 9, 280, 128},
|
||||
{10, 320, 240},
|
||||
{11, 320, 201},
|
||||
{16, 640, 400},
|
||||
{17, 640, 200},
|
||||
{18, 640, 180},
|
||||
{19, 640, 167},
|
||||
{20, 640, 170},
|
||||
{21, 320, 240}
|
||||
};
|
||||
|
||||
static int gdv_read_header(AVFormatContext *ctx)
|
||||
{
|
||||
GDVContext *gdv = ctx->priv_data;
|
||||
AVIOContext *pb = ctx->pb;
|
||||
AVStream *vst, *ast;
|
||||
unsigned fps, snd_flags, vid_depth;
|
||||
unsigned fps, snd_flags, vid_depth, size_id;
|
||||
|
||||
avio_skip(pb, 6);
|
||||
avio_skip(pb, 4);
|
||||
size_id = avio_rl16(pb);
|
||||
|
||||
vst = avformat_new_stream(ctx, 0);
|
||||
if (!vst)
|
||||
@ -91,6 +117,18 @@ static int gdv_read_header(AVFormatContext *ctx)
|
||||
vst->codecpar->width = avio_rl16(pb);
|
||||
vst->codecpar->height = avio_rl16(pb);
|
||||
|
||||
if (vst->codecpar->width == 0 || vst->codecpar->height == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(FixedSize) - 1; i++) {
|
||||
if (FixedSize[i].id == size_id)
|
||||
break;
|
||||
}
|
||||
|
||||
vst->codecpar->width = FixedSize[i].width;
|
||||
vst->codecpar->height = FixedSize[i].height;
|
||||
}
|
||||
|
||||
avpriv_set_pts_info(vst, 64, 1, fps);
|
||||
|
||||
if (vid_depth & 1) {
|
||||
@ -100,7 +138,7 @@ static int gdv_read_header(AVFormatContext *ctx)
|
||||
unsigned r = avio_r8(pb);
|
||||
unsigned g = avio_r8(pb);
|
||||
unsigned b = avio_r8(pb);
|
||||
gdv->pal[i] = 0xFF << 24 | r << 18 | g << 10 | b << 2;
|
||||
gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user