Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
cb928fc4
Commit
cb928fc4
authored
May 10, 2016
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavc: add IFF ANIM decoder
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
97946b20
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
819 additions
and
97 deletions
+819
-97
Changelog
Changelog
+1
-0
codec_desc.c
libavcodec/codec_desc.c
+1
-1
iff.c
libavcodec/iff.c
+750
-75
iff.c
libavformat/iff.c
+67
-21
No files found.
Changelog
View file @
cb928fc4
...
@@ -33,6 +33,7 @@ version <next>:
...
@@ -33,6 +33,7 @@ version <next>:
- VAAPI-accelerated H.264/HEVC/MJPEG encoding
- VAAPI-accelerated H.264/HEVC/MJPEG encoding
- DTS Express (LBR) decoder
- DTS Express (LBR) decoder
- Generic OpenMAX IL encoder with support for Raspberry Pi
- Generic OpenMAX IL encoder with support for Raspberry Pi
- IFF ANIM demuxer & decoder
version 3.0:
version 3.0:
- Common Encryption (CENC) MP4 encoding and decoding support
- Common Encryption (CENC) MP4 encoding and decoding support
...
...
libavcodec/codec_desc.c
View file @
cb928fc4
...
@@ -887,7 +887,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
...
@@ -887,7 +887,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
.
id
=
AV_CODEC_ID_IFF_ILBM
,
.
id
=
AV_CODEC_ID_IFF_ILBM
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
name
=
"iff_ilbm"
,
.
name
=
"iff_ilbm"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"IFF
IL
BM"
),
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"IFF
ACBM/ANIM/DEEP/ILBM/P
BM"
),
.
props
=
AV_CODEC_PROP_LOSSY
,
.
props
=
AV_CODEC_PROP_LOSSY
,
},
},
{
{
...
...
libavcodec/iff.c
View file @
cb928fc4
/*
/*
* IFF ACBM/DEEP/ILBM/PBM bitmap decoder
* IFF ACBM/
ANIM/
DEEP/ILBM/PBM bitmap decoder
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
* Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
* Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
* Copyright (c) 2016 Paul B Mahol
*
*
* This file is part of FFmpeg.
* This file is part of FFmpeg.
*
*
...
@@ -22,7 +23,7 @@
...
@@ -22,7 +23,7 @@
/**
/**
* @file
* @file
* IFF ACBM/DEEP/ILBM/PBM bitmap decoder
* IFF ACBM/
ANIM/
DEEP/ILBM/PBM bitmap decoder
*/
*/
#include <stdint.h>
#include <stdint.h>
...
@@ -30,8 +31,8 @@
...
@@ -30,8 +31,8 @@
#include "libavutil/imgutils.h"
#include "libavutil/imgutils.h"
#include "bytestream.h"
#include "bytestream.h"
#include "avcodec.h"
#include "avcodec.h"
#include "get_bits.h"
#include "internal.h"
#include "internal.h"
#include "mathops.h"
// TODO: masking bits
// TODO: masking bits
typedef
enum
{
typedef
enum
{
...
@@ -50,6 +51,7 @@ typedef struct IffContext {
...
@@ -50,6 +51,7 @@ typedef struct IffContext {
uint32_t
*
mask_buf
;
///< temporary buffer for palette indices
uint32_t
*
mask_buf
;
///< temporary buffer for palette indices
uint32_t
*
mask_palbuf
;
///< masking palette table
uint32_t
*
mask_palbuf
;
///< masking palette table
unsigned
compression
;
///< delta compression method used
unsigned
compression
;
///< delta compression method used
unsigned
is_short
;
///< short compression method used
unsigned
bpp
;
///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
unsigned
bpp
;
///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
unsigned
ham
;
///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
unsigned
ham
;
///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
unsigned
flags
;
///< 1 for EHB, 0 is no extra half darkening
unsigned
flags
;
///< 1 for EHB, 0 is no extra half darkening
...
@@ -57,6 +59,11 @@ typedef struct IffContext {
...
@@ -57,6 +59,11 @@ typedef struct IffContext {
unsigned
masking
;
///< TODO: masking method used
unsigned
masking
;
///< TODO: masking method used
int
init
;
// 1 if buffer and palette data already initialized, 0 otherwise
int
init
;
// 1 if buffer and palette data already initialized, 0 otherwise
int16_t
tvdc
[
16
];
///< TVDC lookup table
int16_t
tvdc
[
16
];
///< TVDC lookup table
GetByteContext
gb
;
uint8_t
*
video
[
2
];
unsigned
video_size
;
uint32_t
*
pal
[
2
];
int
first
;
}
IffContext
;
}
IffContext
;
#define LUT8_PART(plane, v) \
#define LUT8_PART(plane, v) \
...
@@ -189,10 +196,11 @@ static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
...
@@ -189,10 +196,11 @@ static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
* @return >= 0 in case of success, a negative error code otherwise
* @return >= 0 in case of success, a negative error code otherwise
*/
*/
static
int
extract_header
(
AVCodecContext
*
const
avctx
,
static
int
extract_header
(
AVCodecContext
*
const
avctx
,
const
AVPacket
*
const
avpkt
)
{
const
AVPacket
*
const
avpkt
)
const
uint8_t
*
buf
;
{
unsigned
buf_size
;
IffContext
*
s
=
avctx
->
priv_data
;
IffContext
*
s
=
avctx
->
priv_data
;
const
uint8_t
*
buf
;
unsigned
buf_size
=
0
;
int
i
,
palette_size
;
int
i
,
palette_size
;
if
(
avctx
->
extradata_size
<
2
)
{
if
(
avctx
->
extradata_size
<
2
)
{
...
@@ -201,20 +209,51 @@ static int extract_header(AVCodecContext *const avctx,
...
@@ -201,20 +209,51 @@ static int extract_header(AVCodecContext *const avctx,
}
}
palette_size
=
avctx
->
extradata_size
-
AV_RB16
(
avctx
->
extradata
);
palette_size
=
avctx
->
extradata_size
-
AV_RB16
(
avctx
->
extradata
);
if
(
avpkt
)
{
if
(
avpkt
&&
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
int
image_size
;
uint32_t
chunk_id
;
if
(
avpkt
->
size
<
2
)
uint64_t
data_size
;
GetByteContext
*
gb
=
&
s
->
gb
;
bytestream2_skip
(
gb
,
4
);
while
(
bytestream2_get_bytes_left
(
gb
)
>=
1
)
{
chunk_id
=
bytestream2_get_le32
(
gb
);
data_size
=
bytestream2_get_be32
(
gb
);
if
(
chunk_id
==
MKTAG
(
'B'
,
'M'
,
'H'
,
'D'
))
{
bytestream2_skip
(
gb
,
data_size
+
(
data_size
&
1
));
}
else
if
(
chunk_id
==
MKTAG
(
'A'
,
'N'
,
'H'
,
'D'
))
{
if
(
data_size
<
40
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
image_size
=
avpkt
->
size
-
AV_RB16
(
avpkt
->
data
);
buf
=
avpkt
->
data
;
s
->
compression
=
(
bytestream2_get_byte
(
gb
)
<<
8
)
|
(
s
->
compression
&
0xFF
);
buf_size
=
bytestream_get_be16
(
&
buf
);
bytestream2_skip
(
gb
,
19
);
if
(
buf_size
<=
1
||
image_size
<=
1
)
{
s
->
is_short
=
!
(
bytestream2_get_be32
(
gb
)
&
1
);
av_log
(
avctx
,
AV_LOG_ERROR
,
data_size
-=
24
;
"Invalid image size received: %u -> image data offset: %d
\n
"
,
bytestream2_skip
(
gb
,
data_size
+
(
data_size
&
1
));
buf_size
,
image_size
);
}
else
if
(
chunk_id
==
MKTAG
(
'D'
,
'L'
,
'T'
,
'A'
)
||
chunk_id
==
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
))
{
if
(
chunk_id
==
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
))
s
->
compression
&=
0xFF
;
break
;
}
else
if
(
chunk_id
==
MKTAG
(
'C'
,
'M'
,
'A'
,
'P'
))
{
int
count
=
data_size
/
3
;
uint32_t
*
pal
=
s
->
pal
[
0
];
if
(
count
>
256
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
if
(
s
->
ham
)
{
for
(
i
=
0
;
i
<
count
;
i
++
)
pal
[
i
]
=
0xFF000000
|
bytestream2_get_le24
(
gb
);
}
else
{
for
(
i
=
0
;
i
<
count
;
i
++
)
pal
[
i
]
=
0xFF000000
|
bytestream2_get_be24
(
gb
);
}
}
bytestream2_skip
(
gb
,
data_size
&
1
);
}
else
{
}
else
{
bytestream2_skip
(
gb
,
data_size
+
(
data_size
&
1
));
}
}
}
else
if
(
!
avpkt
)
{
buf
=
avctx
->
extradata
;
buf
=
avctx
->
extradata
;
buf_size
=
bytestream_get_be16
(
&
buf
);
buf_size
=
bytestream_get_be16
(
&
buf
);
if
(
buf_size
<=
1
||
palette_size
<
0
)
{
if
(
buf_size
<=
1
||
palette_size
<
0
)
{
...
@@ -323,10 +362,13 @@ static int extract_header(AVCodecContext *const avctx,
...
@@ -323,10 +362,13 @@ static int extract_header(AVCodecContext *const avctx,
static
av_cold
int
decode_end
(
AVCodecContext
*
avctx
)
static
av_cold
int
decode_end
(
AVCodecContext
*
avctx
)
{
{
IffContext
*
s
=
avctx
->
priv_data
;
IffContext
*
s
=
avctx
->
priv_data
;
av_frame_free
(
&
s
->
frame
);
av_freep
(
&
s
->
planebuf
);
av_freep
(
&
s
->
planebuf
);
av_freep
(
&
s
->
ham_buf
);
av_freep
(
&
s
->
ham_buf
);
av_freep
(
&
s
->
ham_palbuf
);
av_freep
(
&
s
->
ham_palbuf
);
av_freep
(
&
s
->
video
[
0
]);
av_freep
(
&
s
->
video
[
1
]);
av_freep
(
&
s
->
pal
[
0
]);
av_freep
(
&
s
->
pal
[
1
]);
return
0
;
return
0
;
}
}
...
@@ -371,10 +413,16 @@ static av_cold int decode_init(AVCodecContext *avctx)
...
@@ -371,10 +413,16 @@ static av_cold int decode_init(AVCodecContext *avctx)
return
AVERROR
(
ENOMEM
);
return
AVERROR
(
ENOMEM
);
s
->
bpp
=
avctx
->
bits_per_coded_sample
;
s
->
bpp
=
avctx
->
bits_per_coded_sample
;
s
->
frame
=
av_frame_alloc
();
if
(
!
s
->
frame
)
{
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
decode_end
(
avctx
);
s
->
video_size
=
FFALIGN
(
avctx
->
width
,
2
)
*
avctx
->
height
*
s
->
bpp
;
s
->
video
[
0
]
=
av_calloc
(
FFALIGN
(
avctx
->
width
,
2
)
*
avctx
->
height
,
s
->
bpp
);
s
->
video
[
1
]
=
av_calloc
(
FFALIGN
(
avctx
->
width
,
2
)
*
avctx
->
height
,
s
->
bpp
);
s
->
pal
[
0
]
=
av_calloc
(
256
,
sizeof
(
*
s
->
pal
[
0
]));
s
->
pal
[
1
]
=
av_calloc
(
256
,
sizeof
(
*
s
->
pal
[
1
]));
if
(
!
s
->
video
[
0
]
||
!
s
->
video
[
1
]
||
!
s
->
pal
[
0
]
||
!
s
->
pal
[
1
])
return
AVERROR
(
ENOMEM
);
return
AVERROR
(
ENOMEM
);
s
->
first
=
1
;
}
}
if
((
err
=
extract_header
(
avctx
,
NULL
))
<
0
)
if
((
err
=
extract_header
(
avctx
,
NULL
))
<
0
)
...
@@ -480,20 +528,18 @@ static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
...
@@ -480,20 +528,18 @@ static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
* @return number of consumed bytes in byterun1 compressed bitstream
* @return number of consumed bytes in byterun1 compressed bitstream
*/
*/
static
int
decode_byterun
(
uint8_t
*
dst
,
int
dst_size
,
static
int
decode_byterun
(
uint8_t
*
dst
,
int
dst_size
,
const
uint8_t
*
buf
,
const
uint8_t
*
const
buf_end
)
GetByteContext
*
gb
)
{
{
const
uint8_t
*
const
buf_start
=
buf
;
unsigned
x
;
unsigned
x
;
for
(
x
=
0
;
x
<
dst_size
&&
b
uf
<
buf_end
;)
{
for
(
x
=
0
;
x
<
dst_size
&&
b
ytestream2_get_bytes_left
(
gb
)
>
0
;)
{
unsigned
length
;
unsigned
length
;
const
int8_t
value
=
*
buf
++
;
const
int8_t
value
=
bytestream2_get_byte
(
gb
)
;
if
(
value
>=
0
)
{
if
(
value
>=
0
)
{
length
=
FFMIN3
(
value
+
1
,
dst_size
-
x
,
buf_end
-
buf
);
length
=
FFMIN3
(
value
+
1
,
dst_size
-
x
,
bytestream2_get_bytes_left
(
gb
));
memcpy
(
dst
+
x
,
buf
,
length
);
bytestream2_get_buffer
(
gb
,
dst
+
x
,
length
);
buf
+=
length
;
}
else
if
(
value
>
-
128
)
{
}
else
if
(
value
>
-
128
)
{
length
=
FFMIN
(
-
value
+
1
,
dst_size
-
x
);
length
=
FFMIN
(
-
value
+
1
,
dst_size
-
x
);
memset
(
dst
+
x
,
*
buf
++
,
length
);
memset
(
dst
+
x
,
bytestream2_get_byte
(
gb
)
,
length
);
}
else
{
// noop
}
else
{
// noop
continue
;
continue
;
}
}
...
@@ -503,7 +549,7 @@ static int decode_byterun(uint8_t *dst, int dst_size,
...
@@ -503,7 +549,7 @@ static int decode_byterun(uint8_t *dst, int dst_size,
av_log
(
NULL
,
AV_LOG_WARNING
,
"decode_byterun ended before plane size
\n
"
);
av_log
(
NULL
,
AV_LOG_WARNING
,
"decode_byterun ended before plane size
\n
"
);
memset
(
dst
+
x
,
0
,
dst_size
-
x
);
memset
(
dst
+
x
,
0
,
dst_size
-
x
);
}
}
return
b
uf
-
buf_start
;
return
b
ytestream2_tell
(
gb
)
;
}
}
#define DECODE_RGBX_COMMON(type) \
#define DECODE_RGBX_COMMON(type) \
...
@@ -660,10 +706,525 @@ static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, i
...
@@ -660,10 +706,525 @@ static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, i
}
}
}
}
static
void
decode_byte_vertical_delta
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
bpp
,
int
dst_size
)
{
int
ncolumns
=
((
w
+
15
)
/
16
)
*
2
;
int
dstpitch
=
ncolumns
*
bpp
;
unsigned
ofsdst
,
ofssrc
,
opcode
,
x
;
GetByteContext
ptrs
,
gb
;
PutByteContext
pb
;
int
i
,
j
,
k
;
bytestream2_init
(
&
ptrs
,
buf
,
buf_end
-
buf
);
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
ofssrc
=
bytestream2_get_be32
(
&
ptrs
);
if
(
!
ofssrc
)
continue
;
if
(
ofssrc
>=
buf_end
-
buf
)
continue
;
bytestream2_init
(
&
gb
,
buf
+
ofssrc
,
buf_end
-
(
buf
+
ofssrc
));
for
(
j
=
0
;
j
<
ncolumns
;
j
++
)
{
ofsdst
=
j
+
k
*
ncolumns
;
i
=
bytestream2_get_byte
(
&
gb
);
while
(
i
>
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
if
(
opcode
==
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
x
=
bytestream2_get_byte
(
&
gb
);
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_byte
(
&
pb
,
x
);
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
else
if
(
opcode
<
0x80
)
{
ofsdst
+=
opcode
*
dstpitch
;
}
else
{
opcode
&=
0x7f
;
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_byte
(
&
pb
,
bytestream2_get_byte
(
&
gb
));
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
i
--
;
}
}
}
}
static
void
decode_delta_j
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
h
,
int
bpp
,
int
dst_size
)
{
int32_t
pitch
;
uint8_t
*
end
=
dst
+
dst_size
,
*
ptr
;
uint32_t
type
,
flag
,
cols
,
groups
,
rows
,
bytes
;
uint32_t
offset
;
int
planepitch_byte
=
(
w
+
7
)
/
8
;
int
planepitch
=
((
w
+
15
)
/
16
)
*
2
;
int
kludge_j
,
b
,
g
,
r
,
d
;
GetByteContext
gb
;
pitch
=
planepitch
*
bpp
;
kludge_j
=
w
<
320
?
(
320
-
w
)
/
8
/
2
:
0
;
bytestream2_init
(
&
gb
,
buf
,
buf_end
-
buf
);
while
(
bytestream2_get_bytes_left
(
&
gb
)
>=
2
)
{
type
=
bytestream2_get_be16
(
&
gb
);
switch
(
type
)
{
case
0
:
return
;
case
1
:
flag
=
bytestream2_get_be16
(
&
gb
);
cols
=
bytestream2_get_be16
(
&
gb
);
groups
=
bytestream2_get_be16
(
&
gb
);
for
(
g
=
0
;
g
<
groups
;
g
++
)
{
offset
=
bytestream2_get_be16
(
&
gb
);
if
(
kludge_j
)
offset
=
((
offset
/
(
320
/
8
))
*
pitch
)
+
(
offset
%
(
320
/
8
))
-
kludge_j
;
else
offset
=
((
offset
/
planepitch_byte
)
*
pitch
)
+
(
offset
%
planepitch_byte
);
ptr
=
dst
+
offset
;
if
(
ptr
>=
end
)
return
;
for
(
b
=
0
;
b
<
cols
;
b
++
)
{
for
(
d
=
0
;
d
<
bpp
;
d
++
)
{
uint8_t
value
=
bytestream2_get_byte
(
&
gb
);
if
(
flag
)
ptr
[
0
]
^=
value
;
else
ptr
[
0
]
=
value
;
ptr
+=
planepitch
;
if
(
ptr
>=
end
)
return
;
}
}
if
((
cols
*
bpp
)
&
1
)
bytestream2_skip
(
&
gb
,
1
);
}
break
;
case
2
:
flag
=
bytestream2_get_be16
(
&
gb
);
rows
=
bytestream2_get_be16
(
&
gb
);
bytes
=
bytestream2_get_be16
(
&
gb
);
groups
=
bytestream2_get_be16
(
&
gb
);
for
(
g
=
0
;
g
<
groups
;
g
++
)
{
offset
=
bytestream2_get_be16
(
&
gb
);
if
(
kludge_j
)
offset
=
((
offset
/
(
320
/
8
))
*
pitch
)
+
(
offset
%
(
320
/
8
))
-
kludge_j
;
else
offset
=
((
offset
/
planepitch_byte
)
*
pitch
)
+
(
offset
%
planepitch_byte
);
for
(
r
=
0
;
r
<
rows
;
r
++
)
{
for
(
d
=
0
;
d
<
bpp
;
d
++
)
{
ptr
=
dst
+
offset
+
(
r
*
pitch
)
+
d
*
planepitch
;
if
(
ptr
>=
end
)
return
;
for
(
b
=
0
;
b
<
bytes
;
b
++
)
{
uint8_t
value
=
bytestream2_get_byte
(
&
gb
);
if
(
flag
)
ptr
[
0
]
^=
value
;
else
ptr
[
0
]
=
value
;
ptr
++
;
if
(
ptr
>=
end
)
return
;
}
}
}
if
((
rows
*
bytes
*
bpp
)
&
1
)
bytestream2_skip
(
&
gb
,
1
);
}
break
;
default:
return
;
}
}
}
static
void
decode_short_vertical_delta
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
bpp
,
int
dst_size
)
{
int
ncolumns
=
(
w
+
15
)
>>
4
;
int
dstpitch
=
ncolumns
*
bpp
*
2
;
unsigned
ofsdst
,
ofssrc
,
ofsdata
,
opcode
,
x
;
GetByteContext
ptrs
,
gb
,
dptrs
,
dgb
;
PutByteContext
pb
;
int
i
,
j
,
k
;
if
(
buf_end
-
buf
<=
64
)
return
;
bytestream2_init
(
&
ptrs
,
buf
,
buf_end
-
buf
);
bytestream2_init
(
&
dptrs
,
buf
+
32
,
(
buf_end
-
buf
)
-
32
);
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
ofssrc
=
bytestream2_get_be32
(
&
ptrs
);
ofsdata
=
bytestream2_get_be32
(
&
dptrs
);
if
(
!
ofssrc
)
continue
;
if
(
ofssrc
>=
buf_end
-
buf
)
return
;
if
(
ofsdata
>=
buf_end
-
buf
)
return
;
bytestream2_init
(
&
gb
,
buf
+
ofssrc
,
buf_end
-
(
buf
+
ofssrc
));
bytestream2_init
(
&
dgb
,
buf
+
ofsdata
,
buf_end
-
(
buf
+
ofsdata
));
for
(
j
=
0
;
j
<
ncolumns
;
j
++
)
{
ofsdst
=
(
j
+
k
*
ncolumns
)
*
2
;
i
=
bytestream2_get_byte
(
&
gb
);
while
(
i
>
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
if
(
opcode
==
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
x
=
bytestream2_get_be16
(
&
dgb
);
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_be16
(
&
pb
,
x
);
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
else
if
(
opcode
<
0x80
)
{
ofsdst
+=
opcode
*
dstpitch
;
}
else
{
opcode
&=
0x7f
;
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_be16
(
&
pb
,
bytestream2_get_be16
(
&
dgb
));
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
i
--
;
}
}
}
}
static
void
decode_long_vertical_delta
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
bpp
,
int
dst_size
)
{
int
ncolumns
=
(
w
+
31
)
>>
5
;
int
dstpitch
=
((
w
+
15
)
/
16
*
2
)
*
bpp
;
unsigned
ofsdst
,
ofssrc
,
ofsdata
,
opcode
,
x
;
GetByteContext
ptrs
,
gb
,
dptrs
,
dgb
;
PutByteContext
pb
;
int
i
,
j
,
k
,
h
;
if
(
buf_end
-
buf
<=
64
)
return
;
h
=
(((
w
+
15
)
/
16
*
2
)
!=
((
w
+
31
)
/
32
*
4
))
?
1
:
0
;
bytestream2_init
(
&
ptrs
,
buf
,
buf_end
-
buf
);
bytestream2_init
(
&
dptrs
,
buf
+
32
,
(
buf_end
-
buf
)
-
32
);
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
ofssrc
=
bytestream2_get_be32
(
&
ptrs
);
ofsdata
=
bytestream2_get_be32
(
&
dptrs
);
if
(
!
ofssrc
)
continue
;
if
(
ofssrc
>=
buf_end
-
buf
)
return
;
if
(
ofsdata
>=
buf_end
-
buf
)
return
;
bytestream2_init
(
&
gb
,
buf
+
ofssrc
,
buf_end
-
(
buf
+
ofssrc
));
bytestream2_init
(
&
dgb
,
buf
+
ofsdata
,
buf_end
-
(
buf
+
ofsdata
));
for
(
j
=
0
;
j
<
ncolumns
;
j
++
)
{
ofsdst
=
(
j
+
k
*
ncolumns
)
*
4
-
h
*
(
2
*
k
);
i
=
bytestream2_get_byte
(
&
gb
);
while
(
i
>
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
if
(
opcode
==
0
)
{
opcode
=
bytestream2_get_byte
(
&
gb
);
if
(
h
&&
(
j
==
(
ncolumns
-
1
)))
{
x
=
bytestream2_get_be16
(
&
dgb
);
bytestream2_skip
(
&
dgb
,
2
);
}
else
{
x
=
bytestream2_get_be32
(
&
dgb
);
}
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
if
(
h
&&
(
j
==
(
ncolumns
-
1
)))
{
bytestream2_put_be16
(
&
pb
,
x
);
}
else
{
bytestream2_put_be32
(
&
pb
,
x
);
}
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
else
if
(
opcode
<
0x80
)
{
ofsdst
+=
opcode
*
dstpitch
;
}
else
{
opcode
&=
0x7f
;
while
(
opcode
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
if
(
h
&&
(
j
==
(
ncolumns
-
1
)))
{
bytestream2_put_be16
(
&
pb
,
bytestream2_get_be16
(
&
dgb
));
bytestream2_skip
(
&
dgb
,
2
);
}
else
{
bytestream2_put_be32
(
&
pb
,
bytestream2_get_be32
(
&
dgb
));
}
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
i
--
;
}
}
}
}
static
void
decode_short_vertical_delta2
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
bpp
,
int
dst_size
)
{
int
ncolumns
=
(
w
+
15
)
>>
4
;
int
dstpitch
=
ncolumns
*
bpp
*
2
;
unsigned
ofsdst
,
ofssrc
,
opcode
,
x
;
GetByteContext
ptrs
,
gb
;
PutByteContext
pb
;
int
i
,
j
,
k
;
bytestream2_init
(
&
ptrs
,
buf
,
buf_end
-
buf
);
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
ofssrc
=
bytestream2_get_be32
(
&
ptrs
);
if
(
!
ofssrc
)
continue
;
if
(
ofssrc
>=
buf_end
-
buf
)
continue
;
bytestream2_init
(
&
gb
,
buf
+
ofssrc
,
buf_end
-
(
buf
+
ofssrc
));
for
(
j
=
0
;
j
<
ncolumns
;
j
++
)
{
ofsdst
=
(
j
+
k
*
ncolumns
)
*
2
;
i
=
bytestream2_get_be16
(
&
gb
);
while
(
i
>
0
&&
bytestream2_get_bytes_left
(
&
gb
)
>
4
)
{
opcode
=
bytestream2_get_be16
(
&
gb
);
if
(
opcode
==
0
)
{
opcode
=
bytestream2_get_be16
(
&
gb
);
x
=
bytestream2_get_be16
(
&
gb
);
while
(
opcode
&&
bytestream2_get_bytes_left_p
(
&
pb
)
>
1
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_be16
(
&
pb
,
x
);
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
else
if
(
opcode
<
0x8000
)
{
ofsdst
+=
opcode
*
dstpitch
;
}
else
{
opcode
&=
0x7fff
;
while
(
opcode
&&
bytestream2_get_bytes_left
(
&
gb
)
>
1
&&
bytestream2_get_bytes_left_p
(
&
pb
)
>
1
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
bytestream2_put_be16
(
&
pb
,
bytestream2_get_be16
(
&
gb
));
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
i
--
;
}
}
}
}
static
void
decode_long_vertical_delta2
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
bpp
,
int
dst_size
)
{
int
ncolumns
=
(
w
+
31
)
>>
5
;
int
dstpitch
=
((
w
+
15
)
/
16
*
2
)
*
bpp
;
unsigned
ofsdst
,
ofssrc
,
opcode
,
x
;
unsigned
skip
=
0x80000000
,
mask
=
skip
-
1
;
GetByteContext
ptrs
,
gb
;
PutByteContext
pb
;
int
i
,
j
,
k
,
h
;
h
=
(((
w
+
15
)
/
16
*
2
)
!=
((
w
+
31
)
/
32
*
4
))
?
1
:
0
;
bytestream2_init
(
&
ptrs
,
buf
,
buf_end
-
buf
);
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
ofssrc
=
bytestream2_get_be32
(
&
ptrs
);
if
(
!
ofssrc
)
continue
;
if
(
ofssrc
>=
buf_end
-
buf
)
continue
;
bytestream2_init
(
&
gb
,
buf
+
ofssrc
,
buf_end
-
(
buf
+
ofssrc
));
for
(
j
=
0
;
j
<
ncolumns
;
j
++
)
{
ofsdst
=
(
j
+
k
*
ncolumns
)
*
4
-
h
*
(
2
*
k
);
if
(
h
&&
(
j
==
(
ncolumns
-
1
)))
{
skip
=
0x8000
;
mask
=
skip
-
1
;
}
i
=
bytestream2_get_be32
(
&
gb
);
while
(
i
>
0
&&
bytestream2_get_bytes_left
(
&
gb
)
>
4
)
{
opcode
=
bytestream2_get_be32
(
&
gb
);
if
(
opcode
==
0
)
{
if
(
h
&&
(
j
==
ncolumns
-
1
))
{
opcode
=
bytestream2_get_be16
(
&
gb
);
x
=
bytestream2_get_be16
(
&
gb
);
}
else
{
opcode
=
bytestream2_get_be32
(
&
gb
);
x
=
bytestream2_get_be32
(
&
gb
);
}
while
(
opcode
&&
bytestream2_get_bytes_left_p
(
&
pb
)
>
1
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
if
(
h
&&
(
j
==
ncolumns
-
1
))
bytestream2_put_be16
(
&
pb
,
x
);
else
bytestream2_put_be32
(
&
pb
,
x
);
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
else
if
(
opcode
<
skip
)
{
ofsdst
+=
opcode
*
dstpitch
;
}
else
{
opcode
&=
mask
;
while
(
opcode
&&
bytestream2_get_bytes_left
(
&
gb
)
>
1
&&
bytestream2_get_bytes_left_p
(
&
pb
)
>
1
)
{
bytestream2_seek_p
(
&
pb
,
ofsdst
,
SEEK_SET
);
if
(
h
&&
(
j
==
ncolumns
-
1
))
{
bytestream2_put_be16
(
&
pb
,
bytestream2_get_be16
(
&
gb
));
}
else
{
bytestream2_put_be32
(
&
pb
,
bytestream2_get_be32
(
&
gb
));
}
ofsdst
+=
dstpitch
;
opcode
--
;
}
}
i
--
;
}
}
}
}
static
void
decode_delta_l
(
uint8_t
*
dst
,
const
uint8_t
*
buf
,
const
uint8_t
*
buf_end
,
int
w
,
int
flag
,
int
bpp
,
int
dst_size
)
{
GetByteContext
off0
,
off1
,
dgb
,
ogb
;
PutByteContext
pb
;
unsigned
poff0
,
poff1
;
int
i
,
k
,
dstpitch
;
int
planepitch_byte
=
(
w
+
7
)
/
8
;
int
planepitch
=
((
w
+
15
)
/
16
)
*
2
;
int
pitch
=
planepitch
*
bpp
;
if
(
buf_end
-
buf
<=
64
)
return
;
bytestream2_init
(
&
off0
,
buf
,
buf_end
-
buf
);
bytestream2_init
(
&
off1
,
buf
+
32
,
buf_end
-
(
buf
+
32
));
bytestream2_init_writer
(
&
pb
,
dst
,
dst_size
);
dstpitch
=
flag
?
(((
w
+
7
)
/
8
)
*
bpp
)
:
2
;
for
(
k
=
0
;
k
<
bpp
;
k
++
)
{
poff0
=
bytestream2_get_be32
(
&
off0
);
poff1
=
bytestream2_get_be32
(
&
off1
);
if
(
!
poff0
)
continue
;
if
(
2LL
*
poff0
>=
buf_end
-
buf
)
return
;
if
(
2LL
*
poff1
>=
buf_end
-
buf
)
return
;
bytestream2_init
(
&
dgb
,
buf
+
2
*
poff0
,
buf_end
-
(
buf
+
2
*
poff0
));
bytestream2_init
(
&
ogb
,
buf
+
2
*
poff1
,
buf_end
-
(
buf
+
2
*
poff1
));
while
((
bytestream2_peek_be16
(
&
ogb
))
!=
0xFFFF
)
{
uint16_t
offset
=
bytestream2_get_be16
(
&
ogb
);
int16_t
cnt
=
bytestream2_get_be16
(
&
ogb
);
uint16_t
data
;
offset
=
((
2
*
offset
)
/
planepitch_byte
)
*
pitch
+
((
2
*
offset
)
%
planepitch_byte
)
+
k
*
planepitch
;
if
(
cnt
<
0
)
{
bytestream2_seek_p
(
&
pb
,
offset
,
SEEK_SET
);
cnt
=
-
cnt
;
data
=
bytestream2_get_be16
(
&
dgb
);
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
bytestream2_put_be16
(
&
pb
,
data
);
bytestream2_skip_p
(
&
pb
,
dstpitch
-
2
);
}
}
else
{
bytestream2_seek_p
(
&
pb
,
offset
,
SEEK_SET
);
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
data
=
bytestream2_get_be16
(
&
dgb
);
bytestream2_put_be16
(
&
pb
,
data
);
bytestream2_skip_p
(
&
pb
,
dstpitch
-
2
);
}
}
}
}
}
static
int
unsupported
(
AVCodecContext
*
avctx
)
static
int
unsupported
(
AVCodecContext
*
avctx
)
{
{
IffContext
*
s
=
avctx
->
priv_data
;
IffContext
*
s
=
avctx
->
priv_data
;
avpriv_request_sample
(
avctx
,
"bitmap (compression
%i
, bpp %i, ham %i)"
,
s
->
compression
,
s
->
bpp
,
s
->
ham
);
avpriv_request_sample
(
avctx
,
"bitmap (compression
0x%0x
, bpp %i, ham %i)"
,
s
->
compression
,
s
->
bpp
,
s
->
ham
);
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
}
}
...
@@ -672,23 +1233,30 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -672,23 +1233,30 @@ static int decode_frame(AVCodecContext *avctx,
AVPacket
*
avpkt
)
AVPacket
*
avpkt
)
{
{
IffContext
*
s
=
avctx
->
priv_data
;
IffContext
*
s
=
avctx
->
priv_data
;
const
uint8_t
*
buf
=
avpkt
->
size
>=
2
?
avpkt
->
data
+
AV_RB16
(
avpkt
->
data
)
:
NULL
;
AVFrame
*
frame
=
data
;
const
int
buf_size
=
avpkt
->
size
>=
2
?
avpkt
->
size
-
AV_RB16
(
avpkt
->
data
)
:
0
;
const
uint8_t
*
buf
=
avpkt
->
data
;
int
buf_size
=
avpkt
->
size
;
const
uint8_t
*
buf_end
=
buf
+
buf_size
;
const
uint8_t
*
buf_end
=
buf
+
buf_size
;
int
y
,
plane
,
res
;
int
y
,
plane
,
res
;
GetByteContext
gb
;
GetByteContext
*
gb
=
&
s
->
gb
;
const
AVPixFmtDescriptor
*
desc
;
const
AVPixFmtDescriptor
*
desc
;
bytestream2_init
(
gb
,
avpkt
->
data
,
avpkt
->
size
);
if
((
res
=
extract_header
(
avctx
,
avpkt
))
<
0
)
if
((
res
=
extract_header
(
avctx
,
avpkt
))
<
0
)
return
res
;
return
res
;
if
((
res
=
ff_reget_buffer
(
avctx
,
s
->
frame
))
<
0
)
if
((
res
=
ff_get_buffer
(
avctx
,
frame
,
0
))
<
0
)
return
res
;
return
res
;
s
->
frame
=
frame
;
buf
+=
bytestream2_tell
(
gb
);
buf_size
-=
bytestream2_tell
(
gb
);
desc
=
av_pix_fmt_desc_get
(
avctx
->
pix_fmt
);
desc
=
av_pix_fmt_desc_get
(
avctx
->
pix_fmt
);
if
(
!
s
->
init
&&
avctx
->
bits_per_coded_sample
<=
8
&&
if
(
!
s
->
init
&&
avctx
->
bits_per_coded_sample
<=
8
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
{
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
{
if
((
res
=
cmap_read_palette
(
avctx
,
(
uint32_t
*
)
s
->
frame
->
data
[
1
]))
<
0
)
if
((
res
=
cmap_read_palette
(
avctx
,
(
uint32_t
*
)
frame
->
data
[
1
]))
<
0
)
return
res
;
return
res
;
}
else
if
(
!
s
->
init
&&
avctx
->
bits_per_coded_sample
<=
8
&&
}
else
if
(
!
s
->
init
&&
avctx
->
bits_per_coded_sample
<=
8
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB32
)
{
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB32
)
{
...
@@ -697,22 +1265,33 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -697,22 +1265,33 @@ static int decode_frame(AVCodecContext *avctx,
}
}
s
->
init
=
1
;
s
->
init
=
1
;
if
(
s
->
compression
<=
0xff
&&
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
memcpy
(
s
->
pal
[
0
],
s
->
frame
->
data
[
1
],
256
*
4
);
}
if
(
s
->
compression
>
0xff
&&
s
->
first
)
{
memcpy
(
s
->
video
[
1
],
s
->
video
[
0
],
s
->
video_size
);
memcpy
(
s
->
pal
[
1
],
s
->
pal
[
0
],
256
*
4
);
s
->
first
=
0
;
}
switch
(
s
->
compression
)
{
switch
(
s
->
compression
)
{
case
0
:
case
0
x0
:
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'C'
,
'B'
,
'M'
))
{
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'C'
,
'B'
,
'M'
))
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
memset
(
s
->
frame
->
data
[
0
],
0
,
avctx
->
height
*
s
->
frame
->
linesize
[
0
]);
memset
(
frame
->
data
[
0
],
0
,
avctx
->
height
*
frame
->
linesize
[
0
]);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf
<
buf_end
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf
<
buf_end
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
decodeplane8
(
row
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
decodeplane8
(
row
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
buf
+=
s
->
planesize
;
buf
+=
s
->
planesize
;
}
}
}
}
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
memset
(
s
->
frame
->
data
[
0
],
0
,
avctx
->
height
*
s
->
frame
->
linesize
[
0
]);
memset
(
frame
->
data
[
0
],
0
,
avctx
->
height
*
frame
->
linesize
[
0
]);
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
const
uint8_t
*
start
=
buf
+
(
plane
*
avctx
->
height
+
y
)
*
s
->
planesize
;
const
uint8_t
*
start
=
buf
+
(
plane
*
avctx
->
height
+
y
)
*
s
->
planesize
;
...
@@ -728,7 +1307,7 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -728,7 +1307,7 @@ static int decode_frame(AVCodecContext *avctx,
int
raw_width
=
avctx
->
width
*
(
av_get_bits_per_pixel
(
desc
)
>>
3
);
int
raw_width
=
avctx
->
width
*
(
av_get_bits_per_pixel
(
desc
)
>>
3
);
int
x
;
int
x
;
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf
<
buf_end
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf
<
buf_end
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memcpy
(
row
,
buf
,
FFMIN
(
raw_width
,
buf_end
-
buf
));
memcpy
(
row
,
buf
,
FFMIN
(
raw_width
,
buf_end
-
buf
));
buf
+=
raw_width
;
buf
+=
raw_width
;
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_BGR32
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_BGR32
)
{
...
@@ -736,10 +1315,13 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -736,10 +1315,13 @@ static int decode_frame(AVCodecContext *avctx,
row
[
4
*
x
+
3
]
=
row
[
4
*
x
+
3
]
&
0xF0
|
(
row
[
4
*
x
+
3
]
>>
4
);
row
[
4
*
x
+
3
]
=
row
[
4
*
x
+
3
]
&
0xF0
|
(
row
[
4
*
x
+
3
]
>>
4
);
}
}
}
}
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'I'
,
'L'
,
'B'
,
'M'
))
{
// interleaved
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'I'
,
'L'
,
'B'
,
'M'
)
||
// interleaved
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
memcpy
(
s
->
video
[
0
],
buf
,
FFMIN
(
buf_end
-
buf
,
s
->
video_size
));
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
row
,
0
,
avctx
->
width
);
memset
(
row
,
0
,
avctx
->
width
);
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
decodeplane8
(
row
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
decodeplane8
(
row
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
...
@@ -748,7 +1330,7 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -748,7 +1330,7 @@ static int decode_frame(AVCodecContext *avctx,
}
}
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
decodeplane8
(
s
->
ham_buf
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
decodeplane8
(
s
->
ham_buf
,
buf
,
FFMIN
(
s
->
planesize
,
buf_end
-
buf
),
plane
);
...
@@ -758,7 +1340,7 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -758,7 +1340,7 @@ static int decode_frame(AVCodecContext *avctx,
}
}
}
else
{
// AV_PIX_FMT_BGR32
}
else
{
// AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
row
,
0
,
avctx
->
width
<<
2
);
memset
(
row
,
0
,
avctx
->
width
<<
2
);
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
&&
buf
<
buf_end
;
plane
++
)
{
decodeplane32
((
uint32_t
*
)
row
,
buf
,
decodeplane32
((
uint32_t
*
)
row
,
buf
,
...
@@ -770,13 +1352,13 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -770,13 +1352,13 @@ static int decode_frame(AVCodecContext *avctx,
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'P'
,
'B'
,
'M'
,
' '
))
{
// IFF-PBM
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'P'
,
'B'
,
'M'
,
' '
))
{
// IFF-PBM
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf_end
>
buf
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf_end
>
buf
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memcpy
(
row
,
buf
,
FFMIN
(
avctx
->
width
,
buf_end
-
buf
));
memcpy
(
row
,
buf
,
FFMIN
(
avctx
->
width
,
buf_end
-
buf
));
buf
+=
avctx
->
width
+
(
avctx
->
width
%
2
);
// padding if odd
buf
+=
avctx
->
width
+
(
avctx
->
width
%
2
);
// padding if odd
}
}
}
else
if
(
s
->
ham
)
{
// IFF-PBM: HAM to AV_PIX_FMT_BGR32
}
else
if
(
s
->
ham
)
{
// IFF-PBM: HAM to AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf_end
>
buf
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
&&
buf_end
>
buf
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memcpy
(
s
->
ham_buf
,
buf
,
FFMIN
(
avctx
->
width
,
buf_end
-
buf
));
memcpy
(
s
->
ham_buf
,
buf
,
FFMIN
(
avctx
->
width
,
buf_end
-
buf
));
buf
+=
avctx
->
width
+
(
avctx
->
width
&
1
);
// padding if odd
buf
+=
avctx
->
width
+
(
avctx
->
width
&
1
);
// padding if odd
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
...
@@ -785,43 +1367,55 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -785,43 +1367,55 @@ static int decode_frame(AVCodecContext *avctx,
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
}
}
break
;
break
;
case
1
:
case
0x1
:
if
(
avctx
->
codec_tag
==
MKTAG
(
'I'
,
'L'
,
'B'
,
'M'
))
{
// interleaved
if
(
avctx
->
codec_tag
==
MKTAG
(
'I'
,
'L'
,
'B'
,
'M'
)
||
// interleaved
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
uint8_t
*
video
=
s
->
video
[
0
];
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
row
,
0
,
avctx
->
width
);
memset
(
row
,
0
,
avctx
->
width
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
gb
);
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
memcpy
(
video
,
s
->
planebuf
,
s
->
planesize
);
video
+=
s
->
planesize
;
}
decodeplane8
(
row
,
s
->
planebuf
,
s
->
planesize
,
plane
);
decodeplane8
(
row
,
s
->
planebuf
,
s
->
planesize
,
plane
);
}
}
}
}
}
else
if
(
avctx
->
bits_per_coded_sample
<=
8
)
{
//8-bit (+ mask) to AV_PIX_FMT_BGR32
}
else
if
(
avctx
->
bits_per_coded_sample
<=
8
)
{
//8-bit (+ mask) to AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
s
->
mask_buf
,
0
,
avctx
->
width
*
sizeof
(
uint32_t
));
memset
(
s
->
mask_buf
,
0
,
avctx
->
width
*
sizeof
(
uint32_t
));
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
gb
);
decodeplane32
(
s
->
mask_buf
,
s
->
planebuf
,
s
->
planesize
,
plane
);
decodeplane32
(
s
->
mask_buf
,
s
->
planebuf
,
s
->
planesize
,
plane
);
}
}
lookup_pal_indicies
((
uint32_t
*
)
row
,
s
->
mask_buf
,
s
->
mask_palbuf
,
avctx
->
width
);
lookup_pal_indicies
((
uint32_t
*
)
row
,
s
->
mask_buf
,
s
->
mask_palbuf
,
avctx
->
width
);
}
}
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
}
else
if
(
s
->
ham
)
{
// HAM to AV_PIX_FMT_BGR32
uint8_t
*
video
=
s
->
video
[
0
];
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
gb
);
if
(
avctx
->
codec_tag
==
MKTAG
(
'A'
,
'N'
,
'I'
,
'M'
))
{
memcpy
(
video
,
s
->
planebuf
,
s
->
planesize
);
video
+=
s
->
planesize
;
}
decodeplane8
(
s
->
ham_buf
,
s
->
planebuf
,
s
->
planesize
,
plane
);
decodeplane8
(
s
->
ham_buf
,
s
->
planebuf
,
s
->
planesize
,
plane
);
}
}
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
}
}
}
else
{
// AV_PIX_FMT_BGR32
}
else
{
// AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
row
,
0
,
avctx
->
width
<<
2
);
memset
(
row
,
0
,
avctx
->
width
<<
2
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
s
->
planebuf
,
s
->
planesize
,
gb
);
decodeplane32
((
uint32_t
*
)
row
,
s
->
planebuf
,
s
->
planesize
,
plane
);
decodeplane32
((
uint32_t
*
)
row
,
s
->
planebuf
,
s
->
planesize
,
plane
);
}
}
}
}
...
@@ -829,48 +1423,129 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -829,48 +1423,129 @@ static int decode_frame(AVCodecContext *avctx,
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'P'
,
'B'
,
'M'
,
' '
))
{
// IFF-PBM
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'P'
,
'B'
,
'M'
,
' '
))
{
// IFF-PBM
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
buf
+=
decode_byterun
(
row
,
avctx
->
width
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
row
,
avctx
->
width
,
gb
);
}
}
}
else
if
(
s
->
ham
)
{
// IFF-PBM: HAM to AV_PIX_FMT_BGR32
}
else
if
(
s
->
ham
)
{
// IFF-PBM: HAM to AV_PIX_FMT_BGR32
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
s
->
frame
->
data
[
0
][
y
*
s
->
frame
->
linesize
[
0
]];
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
buf
+=
decode_byterun
(
s
->
ham_buf
,
avctx
->
width
,
buf
,
buf_end
);
buf
+=
decode_byterun
(
s
->
ham_buf
,
avctx
->
width
,
gb
);
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
}
}
}
else
}
else
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'D'
,
'E'
,
'E'
,
'P'
))
{
// IFF-DEEP
}
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'D'
,
'E'
,
'E'
,
'P'
))
{
// IFF-DEEP
if
(
av_get_bits_per_pixel
(
desc
)
==
32
)
if
(
av_get_bits_per_pixel
(
desc
)
==
32
)
decode_deep_rle32
(
s
->
frame
->
data
[
0
],
buf
,
buf_size
,
avctx
->
width
,
avctx
->
height
,
s
->
frame
->
linesize
[
0
]);
decode_deep_rle32
(
frame
->
data
[
0
],
buf
,
buf_size
,
avctx
->
width
,
avctx
->
height
,
frame
->
linesize
[
0
]);
else
else
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
}
}
break
;
break
;
case
4
:
case
0x4
:
bytestream2_init
(
&
gb
,
buf
,
buf_size
);
if
(
avctx
->
codec_tag
==
MKTAG
(
'R'
,
'G'
,
'B'
,
'8'
)
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB32
)
if
(
avctx
->
codec_tag
==
MKTAG
(
'R'
,
'G'
,
'B'
,
'8'
)
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB32
)
decode_rgb8
(
&
gb
,
s
->
frame
->
data
[
0
],
avctx
->
width
,
avctx
->
height
,
s
->
frame
->
linesize
[
0
]);
decode_rgb8
(
gb
,
frame
->
data
[
0
],
avctx
->
width
,
avctx
->
height
,
frame
->
linesize
[
0
]);
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'R'
,
'G'
,
'B'
,
'N'
)
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB444
)
else
if
(
avctx
->
codec_tag
==
MKTAG
(
'R'
,
'G'
,
'B'
,
'N'
)
&&
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB444
)
decode_rgbn
(
&
gb
,
s
->
frame
->
data
[
0
],
avctx
->
width
,
avctx
->
height
,
s
->
frame
->
linesize
[
0
]);
decode_rgbn
(
gb
,
frame
->
data
[
0
],
avctx
->
width
,
avctx
->
height
,
frame
->
linesize
[
0
]);
else
else
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
break
;
break
;
case
5
:
case
0x
5
:
if
(
avctx
->
codec_tag
==
MKTAG
(
'D'
,
'E'
,
'E'
,
'P'
))
{
if
(
avctx
->
codec_tag
==
MKTAG
(
'D'
,
'E'
,
'E'
,
'P'
))
{
if
(
av_get_bits_per_pixel
(
desc
)
==
32
)
if
(
av_get_bits_per_pixel
(
desc
)
==
32
)
decode_deep_tvdc32
(
s
->
frame
->
data
[
0
],
buf
,
buf_size
,
avctx
->
width
,
avctx
->
height
,
s
->
frame
->
linesize
[
0
],
s
->
tvdc
);
decode_deep_tvdc32
(
frame
->
data
[
0
],
buf
,
buf_size
,
avctx
->
width
,
avctx
->
height
,
frame
->
linesize
[
0
],
s
->
tvdc
);
else
else
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
}
else
}
else
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
break
;
break
;
case
0x500
:
case
0x501
:
decode_byte_vertical_delta
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
bpp
,
s
->
video_size
);
break
;
case
0x700
:
case
0x701
:
if
(
s
->
is_short
)
decode_short_vertical_delta
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
bpp
,
s
->
video_size
);
else
decode_long_vertical_delta
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
bpp
,
s
->
video_size
);
break
;
case
0x800
:
case
0x801
:
if
(
s
->
is_short
)
decode_short_vertical_delta2
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
bpp
,
s
->
video_size
);
else
decode_long_vertical_delta2
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
bpp
,
s
->
video_size
);
break
;
case
0x4a00
:
case
0x4a01
:
decode_delta_j
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
avctx
->
height
,
s
->
bpp
,
s
->
video_size
);
break
;
case
0x6c00
:
case
0x6c01
:
decode_delta_l
(
s
->
video
[
0
],
buf
,
buf_end
,
avctx
->
width
,
s
->
is_short
,
s
->
bpp
,
s
->
video_size
);
break
;
default:
default:
return
unsupported
(
avctx
);
return
unsupported
(
avctx
);
}
}
if
((
res
=
av_frame_ref
(
data
,
s
->
frame
))
<
0
)
if
(
s
->
compression
>
0xff
)
{
return
res
;
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
||
avctx
->
pix_fmt
==
AV_PIX_FMT_GRAY8
)
{
buf
=
s
->
video
[
0
];
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
row
,
0
,
avctx
->
width
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
decodeplane8
(
row
,
buf
,
s
->
planesize
,
plane
);
buf
+=
s
->
planesize
;
}
}
memcpy
(
frame
->
data
[
1
],
s
->
pal
[
0
],
256
*
4
);
}
else
if
(
s
->
ham
)
{
int
i
,
count
=
1
<<
s
->
ham
;
buf
=
s
->
video
[
0
];
memset
(
s
->
ham_palbuf
,
0
,
(
1
<<
s
->
ham
)
*
2
*
sizeof
(
uint32_t
));
for
(
i
=
0
;
i
<
count
;
i
++
)
{
s
->
ham_palbuf
[
i
*
2
+
1
]
=
s
->
pal
[
0
][
i
];
}
for
(
i
=
0
;
i
<
count
;
i
++
)
{
uint32_t
tmp
=
i
<<
(
8
-
s
->
ham
);
tmp
|=
tmp
>>
s
->
ham
;
s
->
ham_palbuf
[(
i
+
count
)
*
2
]
=
0xFF00FFFF
;
s
->
ham_palbuf
[(
i
+
count
*
2
)
*
2
]
=
0xFFFFFF00
;
s
->
ham_palbuf
[(
i
+
count
*
3
)
*
2
]
=
0xFFFF00FF
;
s
->
ham_palbuf
[(
i
+
count
)
*
2
+
1
]
=
0xFF000000
|
tmp
<<
16
;
s
->
ham_palbuf
[(
i
+
count
*
2
)
*
2
+
1
]
=
0xFF000000
|
tmp
;
s
->
ham_palbuf
[(
i
+
count
*
3
)
*
2
+
1
]
=
0xFF000000
|
tmp
<<
8
;
}
if
(
s
->
masking
==
MASK_HAS_MASK
)
{
for
(
i
=
0
;
i
<
8
*
(
1
<<
s
->
ham
);
i
++
)
s
->
ham_palbuf
[(
1
<<
s
->
bpp
)
+
i
]
=
s
->
ham_palbuf
[
i
]
|
0xFF000000
;
}
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
uint8_t
*
row
=
&
frame
->
data
[
0
][
y
*
frame
->
linesize
[
0
]];
memset
(
s
->
ham_buf
,
0
,
s
->
planesize
*
8
);
for
(
plane
=
0
;
plane
<
s
->
bpp
;
plane
++
)
{
decodeplane8
(
s
->
ham_buf
,
buf
,
s
->
planesize
,
plane
);
buf
+=
s
->
planesize
;
}
decode_ham_plane32
((
uint32_t
*
)
row
,
s
->
ham_buf
,
s
->
ham_palbuf
,
s
->
planesize
);
}
}
else
{
return
unsupported
(
avctx
);
}
FFSWAP
(
uint8_t
*
,
s
->
video
[
0
],
s
->
video
[
1
]);
FFSWAP
(
uint32_t
*
,
s
->
pal
[
0
],
s
->
pal
[
1
]);
}
if
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
)
{
frame
->
key_frame
=
1
;
frame
->
pict_type
=
AV_PICTURE_TYPE_I
;
}
else
{
frame
->
key_frame
=
0
;
frame
->
pict_type
=
AV_PICTURE_TYPE_P
;
}
*
got_frame
=
1
;
*
got_frame
=
1
;
...
@@ -880,7 +1555,7 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -880,7 +1555,7 @@ static int decode_frame(AVCodecContext *avctx,
#if CONFIG_IFF_ILBM_DECODER
#if CONFIG_IFF_ILBM_DECODER
AVCodec
ff_iff_ilbm_decoder
=
{
AVCodec
ff_iff_ilbm_decoder
=
{
.
name
=
"iff"
,
.
name
=
"iff"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"IFF"
),
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"IFF
ACBM/ANIM/DEEP/ILBM/PBM
"
),
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
id
=
AV_CODEC_ID_IFF_ILBM
,
.
id
=
AV_CODEC_ID_IFF_ILBM
,
.
priv_data_size
=
sizeof
(
IffContext
),
.
priv_data_size
=
sizeof
(
IffContext
),
...
...
libavformat/iff.c
View file @
cb928fc4
...
@@ -60,6 +60,8 @@
...
@@ -60,6 +60,8 @@
#define ID_RGBN MKTAG('R','G','B','N')
#define ID_RGBN MKTAG('R','G','B','N')
#define ID_DSD MKTAG('D','S','D',' ')
#define ID_DSD MKTAG('D','S','D',' ')
#define ID_ANIM MKTAG('A','N','I','M')
#define ID_ANIM MKTAG('A','N','I','M')
#define ID_ANHD MKTAG('A','N','H','D')
#define ID_DLTA MKTAG('D','L','T','A')
#define ID_FORM MKTAG('F','O','R','M')
#define ID_FORM MKTAG('F','O','R','M')
#define ID_FRM8 MKTAG('F','R','M','8')
#define ID_FRM8 MKTAG('F','R','M','8')
...
@@ -113,6 +115,7 @@ typedef struct IffDemuxContext {
...
@@ -113,6 +115,7 @@ typedef struct IffDemuxContext {
unsigned
transparency
;
///< transparency color index in palette
unsigned
transparency
;
///< transparency color index in palette
unsigned
masking
;
///< masking method used
unsigned
masking
;
///< masking method used
uint8_t
tvdc
[
32
];
///< TVDC lookup table
uint8_t
tvdc
[
32
];
///< TVDC lookup table
int64_t
pts
;
}
IffDemuxContext
;
}
IffDemuxContext
;
/* Metadata string read */
/* Metadata string read */
...
@@ -147,7 +150,6 @@ static int iff_probe(AVProbeData *p)
...
@@ -147,7 +150,6 @@ static int iff_probe(AVProbeData *p)
AV_RL32
(
d
+
8
)
==
ID_DEEP
||
AV_RL32
(
d
+
8
)
==
ID_DEEP
||
AV_RL32
(
d
+
8
)
==
ID_ILBM
||
AV_RL32
(
d
+
8
)
==
ID_ILBM
||
AV_RL32
(
d
+
8
)
==
ID_RGB8
||
AV_RL32
(
d
+
8
)
==
ID_RGB8
||
AV_RL32
(
d
+
8
)
==
ID_RGB8
||
AV_RL32
(
d
+
8
)
==
ID_ANIM
||
AV_RL32
(
d
+
8
)
==
ID_ANIM
||
AV_RL32
(
d
+
8
)
==
ID_RGBN
))
||
AV_RL32
(
d
+
8
)
==
ID_RGBN
))
||
(
AV_RL32
(
d
)
==
ID_FRM8
&&
AV_RL32
(
d
+
12
)
==
ID_DSD
))
(
AV_RL32
(
d
)
==
ID_FRM8
&&
AV_RL32
(
d
+
12
)
==
ID_DSD
))
...
@@ -367,8 +369,7 @@ static int iff_read_header(AVFormatContext *s)
...
@@ -367,8 +369,7 @@ static int iff_read_header(AVFormatContext *s)
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
st
->
codecpar
->
codec_tag
=
avio_rl32
(
pb
);
st
->
codecpar
->
codec_tag
=
avio_rl32
(
pb
);
if
(
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
{
if
(
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
{
avio_skip
(
pb
,
8
);
avio_skip
(
pb
,
12
);
st
->
codecpar
->
codec_tag
=
avio_rl32
(
pb
);
}
}
iff
->
bitmap_compression
=
-
1
;
iff
->
bitmap_compression
=
-
1
;
iff
->
svx8_compression
=
-
1
;
iff
->
svx8_compression
=
-
1
;
...
@@ -484,6 +485,9 @@ static int iff_read_header(AVFormatContext *s)
...
@@ -484,6 +485,9 @@ static int iff_read_header(AVFormatContext *s)
}
}
break
;
break
;
case
ID_ANHD
:
break
;
case
ID_DPEL
:
case
ID_DPEL
:
if
(
data_size
<
4
||
(
data_size
&
3
))
if
(
data_size
<
4
||
(
data_size
&
3
))
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
@@ -626,6 +630,9 @@ static int iff_read_header(AVFormatContext *s)
...
@@ -626,6 +630,9 @@ static int iff_read_header(AVFormatContext *s)
avio_skip
(
pb
,
data_size
-
(
avio_tell
(
pb
)
-
orig_pos
)
+
(
data_size
&
1
));
avio_skip
(
pb
,
data_size
-
(
avio_tell
(
pb
)
-
orig_pos
)
+
(
data_size
&
1
));
}
}
if
(
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
avio_seek
(
pb
,
12
,
SEEK_SET
);
else
avio_seek
(
pb
,
iff
->
body_pos
,
SEEK_SET
);
avio_seek
(
pb
,
iff
->
body_pos
,
SEEK_SET
);
switch
(
st
->
codecpar
->
codec_type
)
{
switch
(
st
->
codecpar
->
codec_type
)
{
...
@@ -672,6 +679,8 @@ static int iff_read_header(AVFormatContext *s)
...
@@ -672,6 +679,8 @@ static int iff_read_header(AVFormatContext *s)
case
AVMEDIA_TYPE_VIDEO
:
case
AVMEDIA_TYPE_VIDEO
:
iff
->
bpp
=
st
->
codecpar
->
bits_per_coded_sample
;
iff
->
bpp
=
st
->
codecpar
->
bits_per_coded_sample
;
if
(
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
avpriv_set_pts_info
(
st
,
32
,
1
,
60
);
if
((
screenmode
&
0x800
/* Hold And Modify */
)
&&
iff
->
bpp
<=
8
)
{
if
((
screenmode
&
0x800
/* Hold And Modify */
)
&&
iff
->
bpp
<=
8
)
{
iff
->
ham
=
iff
->
bpp
>
6
?
6
:
4
;
iff
->
ham
=
iff
->
bpp
>
6
?
6
:
4
;
st
->
codecpar
->
bits_per_coded_sample
=
24
;
st
->
codecpar
->
bits_per_coded_sample
=
24
;
...
@@ -705,6 +714,28 @@ static int iff_read_header(AVFormatContext *s)
...
@@ -705,6 +714,28 @@ static int iff_read_header(AVFormatContext *s)
return
0
;
return
0
;
}
}
static
unsigned
get_anim_duration
(
uint8_t
*
buf
,
int
size
)
{
GetByteContext
gb
;
bytestream2_init
(
&
gb
,
buf
,
size
);
bytestream2_skip
(
&
gb
,
4
);
while
(
bytestream2_get_bytes_left
(
&
gb
)
>
8
)
{
unsigned
chunk
=
bytestream2_get_le32
(
&
gb
);
unsigned
size
=
bytestream2_get_be32
(
&
gb
);
if
(
chunk
==
ID_ANHD
)
{
if
(
size
<
40
)
break
;
bytestream2_skip
(
&
gb
,
14
);
return
bytestream2_get_be32
(
&
gb
);
}
else
{
bytestream2_skip
(
&
gb
,
size
+
size
&
1
);
}
}
return
10
;
}
static
int
iff_read_packet
(
AVFormatContext
*
s
,
static
int
iff_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
AVPacket
*
pkt
)
{
{
...
@@ -714,8 +745,12 @@ static int iff_read_packet(AVFormatContext *s,
...
@@ -714,8 +745,12 @@ static int iff_read_packet(AVFormatContext *s,
int
ret
;
int
ret
;
int64_t
pos
=
avio_tell
(
pb
);
int64_t
pos
=
avio_tell
(
pb
);
if
(
pos
>=
iff
->
body_end
)
if
(
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
{
if
(
avio_feof
(
pb
))
return
AVERROR_EOF
;
return
AVERROR_EOF
;
}
else
if
(
pos
>=
iff
->
body_end
)
{
return
AVERROR_EOF
;
}
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
{
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
{
if
(
st
->
codecpar
->
codec_tag
==
ID_DSD
||
st
->
codecpar
->
codec_tag
==
ID_MAUD
)
{
if
(
st
->
codecpar
->
codec_tag
==
ID_DSD
||
st
->
codecpar
->
codec_tag
==
ID_MAUD
)
{
...
@@ -725,28 +760,39 @@ static int iff_read_packet(AVFormatContext *s,
...
@@ -725,28 +760,39 @@ static int iff_read_packet(AVFormatContext *s,
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
ret
=
av_get_packet
(
pb
,
pkt
,
iff
->
body_size
);
ret
=
av_get_packet
(
pb
,
pkt
,
iff
->
body_size
);
}
}
}
else
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
}
else
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
&&
uint8_t
*
buf
;
st
->
codecpar
->
codec_tag
==
ID_ANIM
)
{
uint64_t
data_size
,
orig_pos
;
uint32_t
chunk_id
=
0
;
if
(
iff
->
body_size
>
INT_MAX
-
2
)
while
(
!
avio_feof
(
pb
))
{
return
AVERROR_INVALIDDATA
;
if
(
avio_feof
(
pb
))
if
(
av_new_packet
(
pkt
,
iff
->
body_size
+
2
)
<
0
)
{
return
AVERROR_EOF
;
return
AVERROR
(
ENOMEM
);
}
chunk_id
=
avio_rl32
(
pb
);
data_size
=
avio_rb32
(
pb
);
orig_pos
=
avio_tell
(
pb
);
buf
=
pkt
->
data
;
if
(
chunk_id
==
ID_FORM
)
bytestream_put_be16
(
&
buf
,
2
);
break
;
ret
=
avio_read
(
pb
,
buf
,
iff
->
body_size
);
else
if
(
ret
<
0
)
{
avio_skip
(
pb
,
data_size
);
av_packet_unref
(
pkt
);
}
}
else
if
(
ret
<
iff
->
body_size
)
ret
=
av_get_packet
(
pb
,
pkt
,
data_size
);
av_shrink_packet
(
pkt
,
ret
+
2
);
pkt
->
pos
=
orig_pos
;
pkt
->
duration
=
get_anim_duration
(
pkt
->
data
,
pkt
->
size
);
if
(
pos
==
12
)
pkt
->
flags
|=
AV_PKT_FLAG_KEY
;
}
else
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
&&
st
->
codecpar
->
codec_tag
!=
ID_ANIM
)
{
ret
=
av_get_packet
(
pb
,
pkt
,
iff
->
body_size
);
pkt
->
pos
=
pos
;
if
(
pos
==
iff
->
body_pos
)
pkt
->
flags
|=
AV_PKT_FLAG_KEY
;
}
else
{
}
else
{
av_assert0
(
0
);
av_assert0
(
0
);
}
}
if
(
pos
==
iff
->
body_pos
)
pkt
->
flags
|=
AV_PKT_FLAG_KEY
;
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
pkt
->
stream_index
=
0
;
pkt
->
stream_index
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment