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
08a4c4bf
Commit
08a4c4bf
authored
Nov 05, 2006
by
Kostya Shishkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fraps v2 and v4 support
Originally committed as revision 6896 to
svn://svn.ffmpeg.org/ffmpeg/trunk
parent
13638ea9
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
165 additions
and
23 deletions
+165
-23
fraps.c
libavcodec/fraps.c
+165
-23
No files found.
libavcodec/fraps.c
View file @
08a4c4bf
/*
/*
* Fraps FPS1 decoder
* Fraps FPS1 decoder
* Copyright (c) 2005 Roine Gustafsson
* Copyright (c) 2005 Roine Gustafsson
* Copyright (c) 2006 Konstantin Shishkov
*
*
* This file is part of FFmpeg.
* This file is part of FFmpeg.
*
*
...
@@ -24,24 +25,42 @@
...
@@ -24,24 +25,42 @@
* @file fraps.c
* @file fraps.c
* Lossless Fraps 'FPS1' decoder
* Lossless Fraps 'FPS1' decoder
* @author Roine Gustafsson <roine at users sf net>
* @author Roine Gustafsson <roine at users sf net>
* @author Konstantin Shishkov
*
*
* Only decodes version 0 and 1 files.
* Only decodes version 0 and 1 files.
* Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
* Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
*
*
* Version 2 files, which are the most commonly found Fraps files, cannot be
* Version 2 files support by Konstantin Shishkov
* decoded yet.
*/
*/
#include "avcodec.h"
#include "avcodec.h"
#include "bitstream.h"
#include "dsputil.h"
#define FPS_TAG MKTAG('F', 'P', 'S', 'x')
#define FPS_TAG MKTAG('F', 'P', 'S', 'x')
/* symbol for Huffman tree node */
#define HNODE -1
/**
* Huffman node
* FIXME one day this should belong to one general framework
*/
typedef
struct
Node
{
int16_t
sym
;
int16_t
n0
;
int
count
;
}
Node
;
/**
/**
* local variable storage
* local variable storage
*/
*/
typedef
struct
FrapsContext
{
typedef
struct
FrapsContext
{
AVCodecContext
*
avctx
;
AVCodecContext
*
avctx
;
AVFrame
frame
;
AVFrame
frame
;
Node
nodes
[
512
];
uint8_t
*
tmpbuf
;
DSPContext
dsp
;
}
FrapsContext
;
}
FrapsContext
;
...
@@ -60,10 +79,110 @@ static int decode_init(AVCodecContext *avctx)
...
@@ -60,10 +79,110 @@ static int decode_init(AVCodecContext *avctx)
s
->
avctx
=
avctx
;
s
->
avctx
=
avctx
;
s
->
frame
.
data
[
0
]
=
NULL
;
s
->
frame
.
data
[
0
]
=
NULL
;
s
->
tmpbuf
=
NULL
;
dsputil_init
(
&
s
->
dsp
,
avctx
);
return
0
;
return
0
;
}
}
/**
* Comparator - our nodes should ascend by count
* but with preserved symbol order
*/
static
int
huff_cmp
(
const
Node
*
a
,
const
Node
*
b
){
return
(
a
->
count
-
b
->
count
)
*
256
+
a
->
sym
-
b
->
sym
;
}
static
void
get_tree_codes
(
uint32_t
*
bits
,
int16_t
*
lens
,
Node
*
nodes
,
int
node
,
uint32_t
pfx
,
int
pl
)
{
int
s
;
s
=
nodes
[
node
].
sym
;
if
(
s
!=
HNODE
){
bits
[
s
]
=
pfx
;
lens
[
s
]
=
pl
;
}
else
{
pfx
<<=
1
;
pl
++
;
get_tree_codes
(
bits
,
lens
,
nodes
,
nodes
[
node
].
n0
,
pfx
,
pl
);
pfx
|=
1
;
get_tree_codes
(
bits
,
lens
,
nodes
,
nodes
[
node
].
n0
+
1
,
pfx
,
pl
);
}
}
static
int
build_huff_tree
(
VLC
*
vlc
,
Node
*
nodes
)
{
uint32_t
bits
[
256
];
int16_t
lens
[
256
];
get_tree_codes
(
bits
,
lens
,
nodes
,
510
,
0
,
0
);
return
init_vlc
(
vlc
,
9
,
256
,
lens
,
2
,
2
,
bits
,
4
,
4
,
0
);
}
/**
* decode Fraps v2 packed plane
*/
static
int
fraps2_decode_plane
(
FrapsContext
*
s
,
uint8_t
*
dst
,
int
stride
,
int
w
,
int
h
,
uint8_t
*
src
,
int
size
,
int
Uoff
)
{
int
i
,
j
;
int
cur_node
;
GetBitContext
gb
;
VLC
vlc
;
int64_t
sum
=
0
;
for
(
i
=
0
;
i
<
256
;
i
++
){
s
->
nodes
[
i
].
sym
=
i
;
s
->
nodes
[
i
].
count
=
LE_32
(
src
);
s
->
nodes
[
i
].
n0
=
-
2
;
src
+=
4
;
sum
+=
s
->
nodes
[
i
].
count
;
}
size
-=
1024
;
if
(
sum
>>
31
)
{
av_log
(
s
->
avctx
,
AV_LOG_ERROR
,
"Too high symbol frequencies. Tree construction is not possible
\n
"
);
return
-
1
;
}
qsort
(
s
->
nodes
,
256
,
sizeof
(
Node
),
huff_cmp
);
cur_node
=
256
;
// FIXME how it will handle nodes with zero count?
for
(
i
=
0
;
i
<
511
;
i
+=
2
){
s
->
nodes
[
cur_node
].
sym
=
HNODE
;
s
->
nodes
[
cur_node
].
count
=
s
->
nodes
[
i
].
count
+
s
->
nodes
[
i
+
1
].
count
;
s
->
nodes
[
cur_node
].
n0
=
i
;
for
(
j
=
cur_node
;
j
>
0
;
j
--
){
if
(
s
->
nodes
[
j
].
count
>=
s
->
nodes
[
j
-
1
].
count
)
break
;
FFSWAP
(
Node
,
s
->
nodes
[
j
],
s
->
nodes
[
j
-
1
]);
}
cur_node
++
;
}
if
(
build_huff_tree
(
&
vlc
,
s
->
nodes
)
<
0
){
av_log
(
s
->
avctx
,
AV_LOG_ERROR
,
"Error building tree
\n
"
);
return
-
1
;
}
/* we have built Huffman table and are ready to decode plane */
/* convert bits so they may be used by standard bitreader */
s
->
dsp
.
bswap_buf
(
s
->
tmpbuf
,
src
,
size
>>
2
);
init_get_bits
(
&
gb
,
s
->
tmpbuf
,
size
*
8
);
for
(
j
=
0
;
j
<
h
;
j
++
){
for
(
i
=
0
;
i
<
w
;
i
++
){
dst
[
i
]
=
get_vlc2
(
&
gb
,
vlc
.
table
,
9
,
3
);
/* lines are stored as deltas between previous lines
* and we need to add 0x80 to the first lines of chroma planes
*/
if
(
j
)
dst
[
i
]
+=
dst
[
i
-
stride
];
else
if
(
Uoff
)
dst
[
i
]
+=
0x80
;
}
dst
+=
stride
;
}
free_vlc
(
&
vlc
);
return
0
;
}
/**
/**
* decode a frame
* decode a frame
...
@@ -86,16 +205,18 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -86,16 +205,18 @@ static int decode_frame(AVCodecContext *avctx,
unsigned
int
x
,
y
;
unsigned
int
x
,
y
;
uint32_t
*
buf32
;
uint32_t
*
buf32
;
uint32_t
*
luma1
,
*
luma2
,
*
cb
,
*
cr
;
uint32_t
*
luma1
,
*
luma2
,
*
cb
,
*
cr
;
uint32_t
offs
[
4
];
int
i
,
is_chroma
,
planes
;
header
=
LE_32
(
buf
);
header
=
LE_32
(
buf
);
version
=
header
&
0xff
;
version
=
header
&
0xff
;
header_size
=
(
header
&
(
1
<<
30
))
?
8
:
4
;
/* bit 30 means pad to 8 bytes */
header_size
=
(
header
&
(
1
<<
30
))
?
8
:
4
;
/* bit 30 means pad to 8 bytes */
if
(
version
>
1
)
{
if
(
version
>
2
&&
version
!=
4
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
av_log
(
avctx
,
AV_LOG_ERROR
,
"This file is encoded with Fraps version %d. "
\
"This file is encoded with Fraps version %d. "
\
"This codec can only decode version 0
and 1
.
\n
"
,
version
);
"This codec can only decode version 0
, 1, 2 and 4
.
\n
"
,
version
);
return
-
1
;
return
-
1
;
}
}
...
@@ -187,30 +308,50 @@ static int decode_frame(AVCodecContext *avctx,
...
@@ -187,30 +308,50 @@ static int decode_frame(AVCodecContext *avctx,
break
;
break
;
case
2
:
case
2
:
case
4
:
/**
/**
* Fraps v2 sub-header description. All numbers are little-endian:
* Fraps v2 is Huffman-coded YUV420 planes
* (this is all guesswork)
* Fraps v4 is the same except it works in grayscale
*
* 0: DWORD 'FPSx'
* 4: DWORD 0x00000010 unknown, perhaps flags
* 8: DWORD off_2 offset to plane 2
* 12: DWORD off_3 offset to plane 3
* 16: 256xDWORD freqtbl_1 frequency table for plane 1
* 1040: plane_1
* ...
* off_2: 256xDWORD freqtbl_2 frequency table for plane 2
* plane_2
* ...
* off_3: 256xDWORD freqtbl_3 frequency table for plane 3
* plane_3
*/
*/
if
((
BE_32
(
buf
)
!=
FPS_TAG
)
||
(
buf_size
<
(
3
*
1024
+
8
)))
{
avctx
->
pix_fmt
=
(
version
==
2
)
?
PIX_FMT_YUV420P
:
PIX_FMT_GRAY8
;
planes
=
(
version
==
2
)
?
3
:
1
;
f
->
reference
=
1
;
f
->
buffer_hints
=
FF_BUFFER_HINTS_VALID
|
FF_BUFFER_HINTS_PRESERVE
|
FF_BUFFER_HINTS_REUSABLE
;
if
(
avctx
->
reget_buffer
(
avctx
,
f
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"reget_buffer() failed
\n
"
);
return
-
1
;
}
/* skip frame */
if
(
buf_size
==
8
)
{
f
->
pict_type
=
FF_P_TYPE
;
f
->
key_frame
=
0
;
break
;
}
f
->
pict_type
=
FF_I_TYPE
;
f
->
key_frame
=
1
;
if
((
LE_32
(
buf
)
!=
FPS_TAG
)
||
(
buf_size
<
(
planes
*
1024
+
24
)))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Fraps: error in data stream
\n
"
);
av_log
(
avctx
,
AV_LOG_ERROR
,
"Fraps: error in data stream
\n
"
);
return
-
1
;
return
-
1
;
}
}
for
(
i
=
0
;
i
<
planes
;
i
++
)
{
/* NOT FINISHED */
offs
[
i
]
=
LE_32
(
buf
+
4
+
i
*
4
);
if
(
offs
[
i
]
>=
buf_size
||
(
i
&&
offs
[
i
]
<=
offs
[
i
-
1
]
+
1024
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Fraps: plane %i offset is out of bounds
\n
"
,
i
);
return
-
1
;
}
}
offs
[
planes
]
=
buf_size
;
for
(
i
=
0
;
i
<
planes
;
i
++
){
is_chroma
=
!!
i
;
s
->
tmpbuf
=
av_realloc
(
s
->
tmpbuf
,
offs
[
i
+
1
]
-
offs
[
i
]
-
1024
);
if
(
fraps2_decode_plane
(
s
,
f
->
data
[
i
],
f
->
linesize
[
i
],
avctx
->
width
>>
is_chroma
,
avctx
->
height
>>
is_chroma
,
buf
+
offs
[
i
],
offs
[
i
+
1
]
-
offs
[
i
],
is_chroma
)
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error decoding plane %i
\n
"
,
i
);
return
-
1
;
}
}
break
;
break
;
}
}
...
@@ -233,6 +374,7 @@ static int decode_end(AVCodecContext *avctx)
...
@@ -233,6 +374,7 @@ static int decode_end(AVCodecContext *avctx)
if
(
s
->
frame
.
data
[
0
])
if
(
s
->
frame
.
data
[
0
])
avctx
->
release_buffer
(
avctx
,
&
s
->
frame
);
avctx
->
release_buffer
(
avctx
,
&
s
->
frame
);
av_freep
(
&
s
->
tmpbuf
);
return
0
;
return
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