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
d1c08027
Commit
d1c08027
authored
Jun 02, 2017
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avcodec: add Gremlin Digital Video decoder
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
29bdcf58
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
415 additions
and
1 deletion
+415
-1
Makefile
libavcodec/Makefile
+1
-0
allcodecs.c
libavcodec/allcodecs.c
+1
-0
avcodec.h
libavcodec/avcodec.h
+1
-0
codec_desc.c
libavcodec/codec_desc.c
+7
-0
gdv.c
libavcodec/gdv.c
+404
-0
version.h
libavcodec/version.h
+1
-1
No files found.
libavcodec/Makefile
View file @
d1c08027
...
...
@@ -308,6 +308,7 @@ OBJS-$(CONFIG_G723_1_DECODER) += g723_1dec.o g723_1.o \
OBJS-$(CONFIG_G723_1_ENCODER)
+=
g723_1enc.o
g723_1.o
\
acelp_vectors.o
celp_filters.o
celp_math.o
OBJS-$(CONFIG_G729_DECODER)
+=
g729dec.o
lsp.o
celp_math.o
celp_filters.o
acelp_filters.o
acelp_pitch_delay.o
acelp_vectors.o
g729postfilter.o
OBJS-$(CONFIG_GDV_DECODER)
+=
gdv.o
OBJS-$(CONFIG_GIF_DECODER)
+=
gifdec.o
lzw.o
OBJS-$(CONFIG_GIF_ENCODER)
+=
gif.o
lzwenc.o
OBJS-$(CONFIG_GREMLIN_DPCM_DECODER)
+=
dpcm.o
...
...
libavcodec/allcodecs.c
View file @
d1c08027
...
...
@@ -195,6 +195,7 @@ static void register_all(void)
REGISTER_DECODER
(
FRAPS
,
fraps
);
REGISTER_DECODER
(
FRWU
,
frwu
);
REGISTER_DECODER
(
G2M
,
g2m
);
REGISTER_DECODER
(
GDV
,
gdv
);
REGISTER_ENCDEC
(
GIF
,
gif
);
REGISTER_ENCDEC
(
H261
,
h261
);
REGISTER_ENCDEC
(
H263
,
h263
);
...
...
libavcodec/avcodec.h
View file @
d1c08027
...
...
@@ -446,6 +446,7 @@ enum AVCodecID {
AV_CODEC_ID_MSCC
,
AV_CODEC_ID_SRGC
,
AV_CODEC_ID_SVG
,
AV_CODEC_ID_GDV
,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO
=
0x10000
,
///< A dummy id pointing at the start of audio codecs
...
...
libavcodec/codec_desc.c
View file @
d1c08027
...
...
@@ -1410,6 +1410,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"Screen Recorder Gold Codec"
),
.
props
=
AV_CODEC_PROP_INTRA_ONLY
|
AV_CODEC_PROP_LOSSLESS
,
},
{
.
id
=
AV_CODEC_ID_GDV
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
name
=
"gdv"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"Gremlin Digital Video"
),
.
props
=
AV_CODEC_PROP_LOSSY
,
},
/* image codecs */
{
...
...
libavcodec/gdv.c
0 → 100644
View file @
d1c08027
/*
* Gremlin Digital Video (GDV) decoder
* Copyright (c) 2017 Konstantin Shishkov
* Copyright (c) 2017 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/common.h"
#include "avcodec.h"
#include "bytestream.h"
#include "internal.h"
typedef
struct
GDVContext
{
AVCodecContext
*
avctx
;
GetByteContext
gb
;
GetByteContext
g2
;
PutByteContext
pb
;
uint32_t
pal
[
256
];
uint8_t
*
frame
;
unsigned
frame_size
;
unsigned
scale_h
,
scale_v
;
}
GDVContext
;
typedef
struct
Bits32
{
uint32_t
queue
;
uint8_t
fill
;
}
Bits32
;
#define PREAMBLE_SIZE 4096
static
av_cold
int
gdv_decode_init
(
AVCodecContext
*
avctx
)
{
GDVContext
*
gdv
=
avctx
->
priv_data
;
int
i
,
j
,
k
;
avctx
->
pix_fmt
=
AV_PIX_FMT_PAL8
;
gdv
->
frame_size
=
avctx
->
width
*
avctx
->
height
+
PREAMBLE_SIZE
;
gdv
->
frame
=
av_calloc
(
gdv
->
frame_size
,
1
);
if
(
!
gdv
->
frame
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
for
(
j
=
0
;
j
<
256
;
j
++
)
{
for
(
k
=
0
;
k
<
8
;
k
++
)
{
gdv
->
frame
[
i
*
2048
+
j
*
8
+
k
]
=
j
;
}
}
}
return
0
;
}
static
void
rescale
(
GDVContext
*
gdv
,
uint8_t
*
dst
,
int
w
,
int
h
,
int
scale_v
,
int
scale_h
)
{
int
i
,
j
,
y
,
x
;
if
((
gdv
->
scale_v
==
scale_v
)
&&
(
gdv
->
scale_h
==
scale_h
))
{
return
;
}
if
(
gdv
->
scale_h
&&
gdv
->
scale_v
)
{
for
(
j
=
0
;
j
<
h
;
j
++
)
{
int
y
=
h
-
j
-
1
;
for
(
i
=
0
;
i
<
w
;
i
++
)
{
int
x
=
w
-
i
-
1
;
dst
[
PREAMBLE_SIZE
+
x
+
y
*
w
]
=
dst
[
PREAMBLE_SIZE
+
x
/
2
+
(
y
/
2
)
*
(
w
/
2
)];
}
}
}
else
if
(
gdv
->
scale_h
)
{
for
(
j
=
0
;
j
<
h
;
j
++
)
{
int
y
=
h
-
j
-
1
;
for
(
x
=
0
;
x
<
w
;
x
++
)
{
dst
[
PREAMBLE_SIZE
+
x
+
y
*
w
]
=
dst
[
PREAMBLE_SIZE
+
x
+
(
y
/
2
)
*
w
];
}
}
}
else
if
(
gdv
->
scale_v
)
{
for
(
j
=
0
;
j
<
h
;
j
++
)
{
int
y
=
h
-
j
-
1
;
for
(
i
=
0
;
i
<
w
;
i
++
)
{
int
x
=
w
-
i
-
1
;
dst
[
PREAMBLE_SIZE
+
x
+
y
*
w
]
=
dst
[
PREAMBLE_SIZE
+
x
/
2
+
y
*
(
w
/
2
)];
}
}
}
if
(
scale_h
&&
scale_v
)
{
for
(
y
=
0
;
y
<
h
/
2
;
y
++
)
{
for
(
x
=
0
;
x
<
w
/
2
;
x
++
)
{
dst
[
PREAMBLE_SIZE
+
x
+
y
*
(
w
/
2
)]
=
dst
[
PREAMBLE_SIZE
+
x
*
2
+
y
*
2
*
w
];
}
}
}
else
if
(
scale_h
)
{
for
(
y
=
0
;
y
<
h
/
2
;
y
++
)
{
for
(
x
=
0
;
x
<
w
;
x
++
)
{
dst
[
PREAMBLE_SIZE
+
x
+
y
*
w
]
=
dst
[
PREAMBLE_SIZE
+
x
+
y
*
2
*
w
];
}
}
}
else
if
(
scale_v
)
{
for
(
y
=
0
;
y
<
h
;
y
++
)
{
for
(
x
=
0
;
x
<
w
/
2
;
x
++
)
{
dst
[
PREAMBLE_SIZE
+
x
+
y
*
w
]
=
dst
[
PREAMBLE_SIZE
+
x
*
2
+
y
*
w
];
}
}
}
gdv
->
scale_v
=
scale_v
;
gdv
->
scale_h
=
scale_h
;
}
static
void
fill_bits32
(
Bits32
*
bits
,
GetByteContext
*
gb
)
{
bits
->
queue
=
bytestream2_get_le32
(
gb
);
bits
->
fill
=
32
;
}
static
int
read_bits32
(
Bits32
*
bits
,
GetByteContext
*
gb
,
int
nbits
)
{
int
res
=
bits
->
queue
&
((
1
<<
nbits
)
-
1
);
bits
->
queue
>>=
nbits
;
bits
->
fill
-=
nbits
;
if
(
bits
->
fill
<=
16
)
{
bits
->
queue
|=
bytestream2_get_le16
(
gb
)
<<
bits
->
fill
;
bits
->
fill
+=
16
;
}
return
res
;
}
static
void
lz_copy
(
PutByteContext
*
pb
,
GetByteContext
*
g2
,
int
offset
,
unsigned
len
)
{
int
i
;
if
(
offset
==
-
1
)
{
int
c
;
bytestream2_seek
(
g2
,
bytestream2_tell_p
(
pb
)
-
1
,
SEEK_SET
);
c
=
bytestream2_get_byte
(
g2
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
bytestream2_put_byte
(
pb
,
c
);
}
}
else
if
(
offset
<
0
)
{
int
start
=
bytestream2_tell_p
(
pb
)
-
(
-
offset
);
bytestream2_seek
(
g2
,
start
,
SEEK_SET
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
bytestream2_put_byte
(
pb
,
bytestream2_get_byte
(
g2
));
}
}
else
{
int
start
=
bytestream2_tell_p
(
pb
)
+
offset
;
bytestream2_seek
(
g2
,
start
,
SEEK_SET
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
bytestream2_put_byte
(
pb
,
bytestream2_get_byte
(
g2
));
}
}
}
static
int
decompress_68
(
AVCodecContext
*
avctx
,
unsigned
skip
,
unsigned
use8
)
{
GDVContext
*
gdv
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
gdv
->
gb
;
GetByteContext
*
g2
=
&
gdv
->
g2
;
PutByteContext
*
pb
=
&
gdv
->
pb
;
Bits32
bits
;
bytestream2_init
(
g2
,
gdv
->
frame
,
gdv
->
frame_size
);
bytestream2_skip_p
(
pb
,
skip
+
PREAMBLE_SIZE
);
fill_bits32
(
&
bits
,
gb
);
while
(
bytestream2_get_bytes_left_p
(
pb
)
>
0
&&
bytestream2_get_bytes_left
(
gb
)
>
0
)
{
int
tag
=
read_bits32
(
&
bits
,
gb
,
2
);
if
(
tag
==
0
)
{
int
b
=
read_bits32
(
&
bits
,
gb
,
1
);
if
(
b
==
0
)
{
bytestream2_put_byte
(
pb
,
bytestream2_get_byte
(
gb
));
}
else
{
int
i
,
len
=
2
;
int
lbits
=
0
;
while
(
1
)
{
int
val
;
lbits
+=
1
;
val
=
read_bits32
(
&
bits
,
gb
,
lbits
);
len
+=
val
;
if
(
val
!=
((
1
<<
lbits
)
-
1
))
{
break
;
}
assert
(
lbits
<
16
);
}
for
(
i
=
0
;
i
<
len
;
i
++
)
{
bytestream2_put_byte
(
pb
,
bytestream2_get_byte
(
gb
));
}
}
}
else
if
(
tag
==
1
)
{
int
b
=
read_bits32
(
&
bits
,
gb
,
1
);
int
len
;
if
(
b
==
0
)
{
len
=
(
read_bits32
(
&
bits
,
gb
,
4
))
+
2
;
}
else
{
int
bb
=
bytestream2_get_byte
(
gb
);
if
((
bb
&
0x80
)
==
0
)
{
len
=
bb
+
18
;
}
else
{
int
top
=
(
bb
&
0x7F
)
<<
8
;
len
=
top
+
bytestream2_get_byte
(
gb
)
+
146
;
}
}
bytestream2_skip_p
(
pb
,
len
);
}
else
if
(
tag
==
2
)
{
int
i
,
subtag
=
read_bits32
(
&
bits
,
gb
,
2
);
if
(
subtag
!=
3
)
{
int
top
=
(
read_bits32
(
&
bits
,
gb
,
4
))
<<
8
;
int
offs
=
top
+
bytestream2_get_byte
(
gb
);
if
((
subtag
!=
0
)
||
(
offs
<=
0xF80
))
{
int
len
=
(
subtag
)
+
3
;
lz_copy
(
pb
,
g2
,
(
offs
)
-
4096
,
len
);
}
else
{
if
(
offs
==
0xFFF
)
{
return
0
;
}
int
real_off
=
((
offs
>>
4
)
&
0x7
)
+
1
;
int
len
=
((
offs
&
0xF
)
+
2
)
*
2
;
int
c1
=
gdv
->
frame
[
bytestream2_tell_p
(
pb
)
-
real_off
];
int
c2
=
gdv
->
frame
[
bytestream2_tell_p
(
pb
)
-
real_off
+
1
];
for
(
i
=
0
;
i
<
len
/
2
;
i
++
)
{
bytestream2_put_byte
(
pb
,
c1
);
bytestream2_put_byte
(
pb
,
c2
);
}
}
}
else
{
int
b
=
bytestream2_get_byte
(
gb
);
int
off
=
((
b
&
0x7F
))
+
1
;
int
len
=
((
b
&
0x80
)
==
0
)
?
2
:
3
;
lz_copy
(
pb
,
g2
,
-
off
,
len
);
}
}
else
{
int
len
;
int
off
;
if
(
use8
)
{
int
b
=
bytestream2_get_byte
(
gb
);
if
((
b
&
0xC0
)
==
0xC0
)
{
len
=
((
b
&
0x3F
))
+
8
;
int
q
=
read_bits32
(
&
bits
,
gb
,
4
);
off
=
(
q
<<
8
)
+
(
bytestream2_get_byte
(
gb
))
+
1
;
}
else
{
int
ofs1
;
if
((
b
&
0x80
)
==
0
)
{
len
=
((
b
>>
4
))
+
6
;
ofs1
=
(
b
&
0xF
);
}
else
{
len
=
((
b
&
0x3F
))
+
14
;
ofs1
=
read_bits32
(
&
bits
,
gb
,
4
);
}
off
=
(
ofs1
<<
8
)
+
(
bytestream2_get_byte
(
gb
))
-
4096
;
}
}
else
{
int
b
=
bytestream2_get_byte
(
gb
);
if
((
b
>>
4
)
==
0xF
)
{
len
=
bytestream2_get_byte
(
gb
)
+
21
;
}
else
{
len
=
(
b
>>
4
)
+
6
;
}
int
ofs1
=
(
b
&
0xF
);
off
=
(
ofs1
<<
8
)
+
bytestream2_get_byte
(
gb
)
-
4096
;
}
lz_copy
(
pb
,
g2
,
off
,
len
);
}
}
return
0
;
}
static
int
gdv_decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
got_frame
,
AVPacket
*
avpkt
)
{
GDVContext
*
gdv
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
gdv
->
gb
;
PutByteContext
*
pb
=
&
gdv
->
pb
;
AVFrame
*
frame
=
data
;
int
ret
,
i
,
pal_size
;
const
uint8_t
*
pal
=
av_packet_get_side_data
(
avpkt
,
AV_PKT_DATA_PALETTE
,
&
pal_size
);
int
compression
;
unsigned
flags
;
uint8_t
*
dst
;
if
((
ret
=
ff_get_buffer
(
avctx
,
frame
,
0
))
<
0
)
return
ret
;
if
(
pal
&&
pal_size
==
AVPALETTE_SIZE
)
memcpy
(
gdv
->
pal
,
pal
,
AVPALETTE_SIZE
);
bytestream2_init
(
gb
,
avpkt
->
data
,
avpkt
->
size
);
bytestream2_init_writer
(
pb
,
gdv
->
frame
,
gdv
->
frame_size
);
flags
=
bytestream2_get_le32
(
gb
);
compression
=
flags
&
0xF
;
rescale
(
gdv
,
gdv
->
frame
,
avctx
->
width
,
avctx
->
height
,
!!
(
flags
&
0x10
),
!!
(
flags
&
0x20
));
switch
(
compression
)
{
case
1
:
memset
(
gdv
->
frame
+
PREAMBLE_SIZE
,
0
,
gdv
->
frame_size
-
PREAMBLE_SIZE
);
case
0
:
for
(
i
=
0
;
i
<
256
;
i
++
)
{
unsigned
r
=
bytestream2_get_byte
(
gb
);
unsigned
g
=
bytestream2_get_byte
(
gb
);
unsigned
b
=
bytestream2_get_byte
(
gb
);
gdv
->
pal
[
i
]
=
0xFF
<<
24
|
r
<<
18
|
g
<<
10
|
b
<<
2
;
}
break
;
case
3
:
break
;
case
6
:
ret
=
decompress_68
(
avctx
,
flags
>>
8
,
0
);
break
;
case
8
:
ret
=
decompress_68
(
avctx
,
flags
>>
8
,
1
);
break
;
default:
return
AVERROR_INVALIDDATA
;
}
memcpy
(
frame
->
data
[
1
],
gdv
->
pal
,
AVPALETTE_SIZE
);
dst
=
frame
->
data
[
0
];
if
(
!
gdv
->
scale_v
&&
!
gdv
->
scale_h
)
{
int
sidx
=
PREAMBLE_SIZE
,
didx
=
0
;
int
y
,
x
;
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
x
=
0
;
x
<
avctx
->
width
;
x
++
)
{
dst
[
x
+
didx
]
=
gdv
->
frame
[
x
+
sidx
];
}
sidx
+=
avctx
->
width
;
didx
+=
frame
->
linesize
[
0
];
}
}
else
{
int
sidx
=
PREAMBLE_SIZE
,
didx
=
0
;
int
y
,
x
;
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
if
(
!
gdv
->
scale_v
)
{
for
(
x
=
0
;
x
<
avctx
->
width
;
x
++
)
{
dst
[
didx
+
x
]
=
gdv
->
frame
[
sidx
+
x
];
}
}
else
{
for
(
x
=
0
;
x
<
avctx
->
width
;
x
++
)
{
dst
[
didx
+
x
]
=
gdv
->
frame
[
sidx
+
x
/
2
];
}
}
if
(
!
gdv
->
scale_h
||
((
y
&
1
)
==
1
))
{
sidx
+=
!
gdv
->
scale_v
?
avctx
->
width
:
avctx
->
width
/
2
;
}
didx
+=
frame
->
linesize
[
0
];
}
}
*
got_frame
=
1
;
return
ret
<
0
?
ret
:
avpkt
->
size
;
}
static
av_cold
int
gdv_decode_close
(
AVCodecContext
*
avctx
)
{
GDVContext
*
gdv
=
avctx
->
priv_data
;
av_freep
(
&
gdv
->
frame
);
return
0
;
}
AVCodec
ff_gdv_decoder
=
{
.
name
=
"gdv"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"Gremlin Digital Video"
),
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
id
=
AV_CODEC_ID_GDV
,
.
priv_data_size
=
sizeof
(
GDVContext
),
.
init
=
gdv_decode_init
,
.
close
=
gdv_decode_close
,
.
decode
=
gdv_decode_frame
,
.
capabilities
=
AV_CODEC_CAP_DR1
,
.
caps_internal
=
FF_CODEC_CAP_INIT_THREADSAFE
,
};
libavcodec/version.h
View file @
d1c08027
...
...
@@ -28,7 +28,7 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57
#define LIBAVCODEC_VERSION_MINOR 9
7
#define LIBAVCODEC_VERSION_MINOR 9
8
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
...
...
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