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
a5278b67
Commit
a5278b67
authored
Sep 02, 2018
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avcodec: add RemotelyAnywhere Screen Capture decoder
parent
af71a3ff
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
827 additions
and
2 deletions
+827
-2
Changelog
Changelog
+1
-0
configure
configure
+1
-0
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
rasc.c
libavcodec/rasc.c
+812
-0
version.h
libavcodec/version.h
+2
-2
riff.c
libavformat/riff.c
+1
-0
No files found.
Changelog
View file @
a5278b67
...
...
@@ -22,6 +22,7 @@ version <next>:
- MatchWare Screen Capture Codec decoder
- WinCam Motion Video decoder
- 1D LUT filter (lut1d)
- RemotelyAnywhere Screen Capture decoder
version 4.0:
...
...
configure
View file @
a5278b67
...
...
@@ -2719,6 +2719,7 @@ qdm2_decoder_select="mdct rdft mpegaudiodsp"
ra_144_decoder_select
=
"audiodsp"
ra_144_encoder_select
=
"audio_frame_queue lpc audiodsp"
ralf_decoder_select
=
"golomb"
rasc_decoder_deps
=
"zlib"
rawvideo_decoder_select
=
"bswapdsp"
rscc_decoder_deps
=
"zlib"
rtjpeg_decoder_select
=
"me_cmp"
...
...
libavcodec/Makefile
View file @
a5278b67
...
...
@@ -536,6 +536,7 @@ OBJS-$(CONFIG_RA_144_DECODER) += ra144dec.o ra144.o celp_filters.o
OBJS-$(CONFIG_RA_144_ENCODER)
+=
ra144enc.o
ra144.o
celp_filters.o
OBJS-$(CONFIG_RA_288_DECODER)
+=
ra288.o
celp_filters.o
OBJS-$(CONFIG_RALF_DECODER)
+=
ralf.o
OBJS-$(CONFIG_RASC_DECODER)
+=
rasc.o
OBJS-$(CONFIG_RAWVIDEO_DECODER)
+=
rawdec.o
OBJS-$(CONFIG_RAWVIDEO_ENCODER)
+=
rawenc.o
OBJS-$(CONFIG_REALTEXT_DECODER)
+=
realtextdec.o
ass.o
...
...
libavcodec/allcodecs.c
View file @
a5278b67
...
...
@@ -248,6 +248,7 @@ extern AVCodec ff_r10k_encoder;
extern
AVCodec
ff_r10k_decoder
;
extern
AVCodec
ff_r210_encoder
;
extern
AVCodec
ff_r210_decoder
;
extern
AVCodec
ff_rasc_decoder
;
extern
AVCodec
ff_rawvideo_encoder
;
extern
AVCodec
ff_rawvideo_decoder
;
extern
AVCodec
ff_rl2_decoder
;
...
...
libavcodec/avcodec.h
View file @
a5278b67
...
...
@@ -451,6 +451,7 @@ enum AVCodecID {
AV_CODEC_ID_PROSUMER
,
AV_CODEC_ID_MWSC
,
AV_CODEC_ID_WCMV
,
AV_CODEC_ID_RASC
,
/* 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 @
a5278b67
...
...
@@ -1682,6 +1682,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"WinCAM Motion Video"
),
.
props
=
AV_CODEC_PROP_LOSSLESS
,
},
{
.
id
=
AV_CODEC_ID_RASC
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
name
=
"rasc"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"RemotelyAnywhere Screen Capture"
),
.
props
=
AV_CODEC_PROP_LOSSY
,
},
/* various PCM "codecs" */
{
...
...
libavcodec/rasc.c
0 → 100644
View file @
a5278b67
/*
* RemotelyAnywhere Screen Capture decoder
*
* Copyright (c) 2018 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "bytestream.h"
#include "internal.h"
#include <zlib.h>
#define KBND MKTAG('K', 'B', 'N', 'D')
#define FINT MKTAG('F', 'I', 'N', 'T')
#define INIT MKTAG('I', 'N', 'I', 'T')
#define BNDL MKTAG('B', 'N', 'D', 'L')
#define KFRM MKTAG('K', 'F', 'R', 'M')
#define DLTA MKTAG('D', 'L', 'T', 'A')
#define MOUS MKTAG('M', 'O', 'U', 'S')
#define MPOS MKTAG('M', 'P', 'O', 'S')
#define MOVE MKTAG('M', 'O', 'V', 'E')
#define EMPT MKTAG('E', 'M', 'P', 'T')
typedef
struct
RASCContext
{
AVClass
*
class
;
int
skip_cursor
;
GetByteContext
gb
;
uint8_t
*
delta
;
int
delta_size
;
uint8_t
*
cursor
;
int
cursor_size
;
unsigned
cursor_w
;
unsigned
cursor_h
;
unsigned
cursor_x
;
unsigned
cursor_y
;
int
stride
;
int
bpp
;
z_stream
zstream
;
AVFrame
*
frame
;
AVFrame
*
frame1
;
AVFrame
*
frame2
;
}
RASCContext
;
static
void
clear_plane
(
AVCodecContext
*
avctx
,
AVFrame
*
frame
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
uint8_t
*
dst
=
frame
->
data
[
0
];
for
(
int
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
memset
(
dst
,
0
,
avctx
->
width
*
s
->
bpp
);
dst
+=
frame
->
linesize
[
0
];
}
}
static
void
copy_plane
(
AVCodecContext
*
avctx
,
AVFrame
*
src
,
AVFrame
*
dst
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
uint8_t
*
srcp
=
src
->
data
[
0
];
uint8_t
*
dstp
=
dst
->
data
[
0
];
for
(
int
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
memcpy
(
dstp
,
srcp
,
s
->
stride
);
srcp
+=
src
->
linesize
[
0
];
dstp
+=
dst
->
linesize
[
0
];
}
}
static
int
init_frames
(
AVCodecContext
*
avctx
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
int
ret
;
av_frame_unref
(
s
->
frame1
);
if
((
ret
=
ff_get_buffer
(
avctx
,
s
->
frame1
,
0
))
<
0
)
return
ret
;
av_frame_unref
(
s
->
frame2
);
if
((
ret
=
ff_get_buffer
(
avctx
,
s
->
frame2
,
0
))
<
0
)
return
ret
;
clear_plane
(
avctx
,
s
->
frame2
);
clear_plane
(
avctx
,
s
->
frame1
);
return
0
;
}
static
int
decode_fint
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
unsigned
w
,
h
,
fmt
;
int
ret
;
if
(
bytestream2_peek_le32
(
gb
)
!=
0x65
)
{
if
(
!
s
->
frame2
->
data
[
0
]
||
!
s
->
frame1
->
data
[
0
])
return
AVERROR_INVALIDDATA
;
clear_plane
(
avctx
,
s
->
frame2
);
clear_plane
(
avctx
,
s
->
frame1
);
return
0
;
}
bytestream2_skip
(
gb
,
8
);
w
=
bytestream2_get_le32
(
gb
);
h
=
bytestream2_get_le32
(
gb
);
bytestream2_skip
(
gb
,
30
);
fmt
=
bytestream2_get_le16
(
gb
);
bytestream2_skip
(
gb
,
24
);
switch
(
fmt
)
{
case
8
:
s
->
stride
=
FFALIGN
(
w
,
4
);
s
->
bpp
=
1
;
fmt
=
AV_PIX_FMT_PAL8
;
break
;
case
16
:
s
->
stride
=
w
*
2
;
s
->
bpp
=
2
;
fmt
=
AV_PIX_FMT_RGB555LE
;
break
;
case
32
:
s
->
stride
=
w
*
4
;
s
->
bpp
=
4
;
fmt
=
AV_PIX_FMT_BGR0
;
break
;
default:
return
AVERROR_INVALIDDATA
;
}
ret
=
ff_set_dimensions
(
avctx
,
w
,
h
);
if
(
ret
<
0
)
return
ret
;
avctx
->
width
=
w
;
avctx
->
height
=
h
;
avctx
->
pix_fmt
=
fmt
;
ret
=
init_frames
(
avctx
);
if
(
ret
<
0
)
return
ret
;
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
{
uint32_t
*
pal
=
(
uint32_t
*
)
s
->
frame2
->
data
[
1
];
for
(
int
i
=
0
;
i
<
256
;
i
++
)
pal
[
i
]
=
bytestream2_get_le32
(
gb
)
|
0xFF000000u
;
}
return
0
;
}
static
int
decode_zlib
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
,
unsigned
uncompressed_size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
int
zret
;
zret
=
inflateReset
(
&
s
->
zstream
);
if
(
zret
!=
Z_OK
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate reset error: %d
\n
"
,
zret
);
return
AVERROR_EXTERNAL
;
}
av_fast_padded_malloc
(
&
s
->
delta
,
&
s
->
delta_size
,
uncompressed_size
);
if
(
!
s
->
delta
)
return
AVERROR
(
ENOMEM
);
s
->
zstream
.
next_in
=
avpkt
->
data
+
bytestream2_tell
(
gb
);
s
->
zstream
.
avail_in
=
FFMIN
(
size
,
bytestream2_get_bytes_left
(
gb
));
s
->
zstream
.
next_out
=
s
->
delta
;
s
->
zstream
.
avail_out
=
s
->
delta_size
;
zret
=
inflate
(
&
s
->
zstream
,
Z_FINISH
);
if
(
zret
!=
Z_STREAM_END
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate failed with return code: %d.
\n
"
,
zret
);
return
AVERROR_INVALIDDATA
;
}
return
0
;
}
static
int
decode_move
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
GetByteContext
mc
;
unsigned
pos
,
compression
,
nb_moves
;
unsigned
uncompressed_size
;
int
ret
;
pos
=
bytestream2_tell
(
gb
);
bytestream2_skip
(
gb
,
8
);
nb_moves
=
bytestream2_get_le32
(
gb
);
bytestream2_skip
(
gb
,
8
);
compression
=
bytestream2_get_le32
(
gb
);
if
(
nb_moves
>
INT32_MAX
/
16
)
return
AVERROR_INVALIDDATA
;
uncompressed_size
=
16
*
nb_moves
;
if
(
compression
==
1
)
{
ret
=
decode_zlib
(
avctx
,
avpkt
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
),
uncompressed_size
);
if
(
ret
<
0
)
return
ret
;
bytestream2_init
(
&
mc
,
s
->
delta
,
uncompressed_size
);
}
else
if
(
compression
==
0
)
{
bytestream2_init
(
&
mc
,
avpkt
->
data
+
bytestream2_tell
(
gb
),
bytestream2_get_bytes_left
(
gb
));
}
else
if
(
compression
==
2
)
{
avpriv_request_sample
(
avctx
,
"compression %d"
,
compression
);
return
AVERROR_PATCHWELCOME
;
}
else
{
return
AVERROR_INVALIDDATA
;
}
if
(
bytestream2_get_bytes_left
(
&
mc
)
<
uncompressed_size
)
return
AVERROR_INVALIDDATA
;
for
(
int
i
=
0
;
i
<
nb_moves
;
i
++
)
{
int
type
,
start_x
,
start_y
,
end_x
,
end_y
,
mov_x
,
mov_y
;
uint8_t
*
e2
,
*
b1
,
*
b2
;
int
w
,
h
;
type
=
bytestream2_get_le16
(
&
mc
);
start_x
=
bytestream2_get_le16
(
&
mc
);
start_y
=
bytestream2_get_le16
(
&
mc
);
end_x
=
bytestream2_get_le16
(
&
mc
);
end_y
=
bytestream2_get_le16
(
&
mc
);
mov_x
=
bytestream2_get_le16
(
&
mc
);
mov_y
=
bytestream2_get_le16
(
&
mc
);
bytestream2_skip
(
&
mc
,
2
);
if
(
start_x
>=
avctx
->
width
||
start_y
>=
avctx
->
height
||
end_x
>=
avctx
->
width
||
end_y
>=
avctx
->
height
||
mov_x
>=
avctx
->
width
||
mov_y
>=
avctx
->
height
)
{
continue
;
}
if
(
start_x
>=
end_x
||
start_y
>=
end_y
)
continue
;
w
=
end_x
-
start_x
;
h
=
end_y
-
start_y
;
if
(
mov_x
+
w
>
avctx
->
width
||
mov_y
+
h
>
avctx
->
height
)
continue
;
if
(
!
s
->
frame2
->
data
[
0
]
||
!
s
->
frame1
->
data
[
0
])
return
AVERROR_INVALIDDATA
;
b1
=
s
->
frame1
->
data
[
0
]
+
s
->
frame1
->
linesize
[
0
]
*
(
start_y
+
h
)
+
start_x
*
s
->
bpp
;
b2
=
s
->
frame2
->
data
[
0
]
+
s
->
frame2
->
linesize
[
0
]
*
(
start_y
+
h
)
+
start_x
*
s
->
bpp
;
e2
=
s
->
frame2
->
data
[
0
]
+
s
->
frame2
->
linesize
[
0
]
*
(
mov_y
+
h
)
+
mov_x
*
s
->
bpp
;
if
(
type
==
2
)
{
for
(
int
j
=
0
;
j
<
h
;
j
++
)
{
memcpy
(
b1
,
b2
,
w
*
s
->
bpp
);
b1
-=
s
->
frame1
->
linesize
[
0
];
b2
-=
s
->
frame2
->
linesize
[
0
];
}
}
else
if
(
type
==
1
)
{
for
(
int
j
=
0
;
j
<
h
;
j
++
)
{
memset
(
b2
,
0
,
w
*
s
->
bpp
);
b2
-=
s
->
frame2
->
linesize
[
0
];
}
}
else
if
(
type
==
0
)
{
uint8_t
*
buffer
;
av_fast_padded_malloc
(
&
s
->
delta
,
&
s
->
delta_size
,
w
*
h
*
s
->
bpp
);
buffer
=
s
->
delta
;
if
(
!
buffer
)
return
AVERROR
(
ENOMEM
);
for
(
int
j
=
0
;
j
<
h
;
j
++
)
{
memcpy
(
buffer
+
j
*
w
*
s
->
bpp
,
e2
,
w
*
s
->
bpp
);
e2
-=
s
->
frame2
->
linesize
[
0
];
}
for
(
int
j
=
0
;
j
<
h
;
j
++
)
{
memcpy
(
b2
,
buffer
+
j
*
w
*
s
->
bpp
,
w
*
s
->
bpp
);
b2
-=
s
->
frame2
->
linesize
[
0
];
}
}
else
{
return
AVERROR_INVALIDDATA
;
}
}
bytestream2_skip
(
gb
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
));
return
0
;
}
#define NEXT_LINE \
if (cx >= w * s->bpp) { \
cx = 0; \
cy--; \
b1 -= s->frame1->linesize[0]; \
b2 -= s->frame2->linesize[0]; \
} \
len--;
static
int
decode_dlta
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
GetByteContext
dc
;
unsigned
uncompressed_size
,
pos
;
unsigned
x
,
y
,
w
,
h
;
int
ret
,
cx
,
cy
,
compression
;
uint8_t
*
b1
,
*
b2
;
pos
=
bytestream2_tell
(
gb
);
bytestream2_skip
(
gb
,
12
);
uncompressed_size
=
bytestream2_get_le32
(
gb
);
x
=
bytestream2_get_le32
(
gb
);
y
=
bytestream2_get_le32
(
gb
);
w
=
bytestream2_get_le32
(
gb
);
h
=
bytestream2_get_le32
(
gb
);
if
(
x
>=
avctx
->
width
||
y
>=
avctx
->
height
||
w
>
avctx
->
width
||
h
>
avctx
->
height
)
return
AVERROR_INVALIDDATA
;
if
(
x
+
w
>
avctx
->
width
||
y
+
h
>
avctx
->
height
)
return
AVERROR_INVALIDDATA
;
bytestream2_skip
(
gb
,
4
);
compression
=
bytestream2_get_le32
(
gb
);
if
(
compression
==
1
)
{
ret
=
decode_zlib
(
avctx
,
avpkt
,
size
,
uncompressed_size
);
if
(
ret
<
0
)
return
ret
;
bytestream2_init
(
&
dc
,
s
->
delta
,
uncompressed_size
);
}
else
if
(
compression
==
0
)
{
if
(
bytestream2_get_bytes_left
(
gb
)
<
uncompressed_size
)
return
AVERROR_INVALIDDATA
;
bytestream2_init
(
&
dc
,
avpkt
->
data
+
bytestream2_tell
(
gb
),
uncompressed_size
);
}
else
if
(
compression
==
2
)
{
avpriv_request_sample
(
avctx
,
"compression %d"
,
compression
);
return
AVERROR_PATCHWELCOME
;
}
else
{
return
AVERROR_INVALIDDATA
;
}
if
(
!
s
->
frame2
->
data
[
0
]
||
!
s
->
frame1
->
data
[
0
])
return
AVERROR_INVALIDDATA
;
b1
=
s
->
frame1
->
data
[
0
]
+
s
->
frame1
->
linesize
[
0
]
*
(
y
+
h
-
1
)
+
x
*
s
->
bpp
;
b2
=
s
->
frame2
->
data
[
0
]
+
s
->
frame2
->
linesize
[
0
]
*
(
y
+
h
-
1
)
+
x
*
s
->
bpp
;
cx
=
0
,
cy
=
h
;
while
(
bytestream2_get_bytes_left
(
&
dc
)
>
0
)
{
int
type
=
bytestream2_get_byte
(
&
dc
);
int
len
=
bytestream2_get_byte
(
&
dc
);
unsigned
fill
;
switch
(
type
)
{
case
1
:
while
(
len
>
0
&&
cy
>
0
)
{
cx
++
;
NEXT_LINE
}
break
;
case
2
:
while
(
len
>
0
&&
cy
>
0
)
{
int
v0
=
b1
[
cx
];
int
v1
=
b2
[
cx
];
b2
[
cx
]
=
v0
;
b1
[
cx
]
=
v1
;
cx
++
;
NEXT_LINE
}
break
;
case
3
:
while
(
len
>
0
&&
cy
>
0
)
{
fill
=
bytestream2_get_byte
(
&
dc
);
b1
[
cx
]
=
b2
[
cx
];
b2
[
cx
]
=
fill
;
cx
++
;
NEXT_LINE
}
break
;
case
4
:
fill
=
bytestream2_get_byte
(
&
dc
);
while
(
len
>
0
&&
cy
>
0
)
{
AV_WL32
(
b1
+
cx
,
AV_RL32
(
b2
+
cx
));
AV_WL32
(
b2
+
cx
,
fill
);
cx
++
;
NEXT_LINE
}
break
;
case
7
:
fill
=
bytestream2_get_le32
(
&
dc
);
while
(
len
>
0
&&
cy
>
0
)
{
AV_WL32
(
b1
+
cx
,
AV_RL32
(
b2
+
cx
));
AV_WL32
(
b2
+
cx
,
fill
);
cx
+=
4
;
NEXT_LINE
}
break
;
case
10
:
while
(
len
>
0
&&
cy
>
0
)
{
cx
+=
4
;
NEXT_LINE
}
break
;
case
12
:
while
(
len
>
0
&&
cy
>
0
)
{
unsigned
v0
,
v1
;
v0
=
AV_RL32
(
b2
+
cx
);
v1
=
AV_RL32
(
b1
+
cx
);
AV_WL32
(
b2
+
cx
,
v1
);
AV_WL32
(
b1
+
cx
,
v0
);
cx
+=
4
;
NEXT_LINE
}
break
;
case
13
:
while
(
len
>
0
&&
cy
>
0
)
{
fill
=
bytestream2_get_le32
(
&
dc
);
AV_WL32
(
b1
+
cx
,
AV_RL32
(
b2
+
cx
));
AV_WL32
(
b2
+
cx
,
fill
);
cx
+=
4
;
NEXT_LINE
}
break
;
default:
avpriv_request_sample
(
avctx
,
"runlen %d"
,
type
);
return
AVERROR_INVALIDDATA
;
}
}
bytestream2_skip
(
gb
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
));
return
0
;
}
static
int
decode_kfrm
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
uint8_t
*
dst
;
unsigned
pos
;
int
zret
,
ret
;
pos
=
bytestream2_tell
(
gb
);
if
(
bytestream2_peek_le32
(
gb
)
==
0x65
)
{
ret
=
decode_fint
(
avctx
,
avpkt
,
size
);
if
(
ret
<
0
)
return
ret
;
}
if
(
!
s
->
frame2
->
data
[
0
])
return
AVERROR_INVALIDDATA
;
zret
=
inflateReset
(
&
s
->
zstream
);
if
(
zret
!=
Z_OK
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate reset error: %d
\n
"
,
zret
);
return
AVERROR_EXTERNAL
;
}
s
->
zstream
.
next_in
=
avpkt
->
data
+
bytestream2_tell
(
gb
);
s
->
zstream
.
avail_in
=
bytestream2_get_bytes_left
(
gb
);
dst
=
s
->
frame2
->
data
[
0
]
+
(
avctx
->
height
-
1
)
*
s
->
frame2
->
linesize
[
0
];
for
(
int
i
=
0
;
i
<
avctx
->
height
;
i
++
)
{
s
->
zstream
.
next_out
=
dst
;
s
->
zstream
.
avail_out
=
s
->
stride
;
zret
=
inflate
(
&
s
->
zstream
,
Z_SYNC_FLUSH
);
if
(
zret
!=
Z_OK
&&
zret
!=
Z_STREAM_END
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate failed with return code: %d.
\n
"
,
zret
);
return
AVERROR_INVALIDDATA
;
}
dst
-=
s
->
frame2
->
linesize
[
0
];
}
dst
=
s
->
frame1
->
data
[
0
]
+
(
avctx
->
height
-
1
)
*
s
->
frame1
->
linesize
[
0
];
for
(
int
i
=
0
;
i
<
avctx
->
height
;
i
++
)
{
s
->
zstream
.
next_out
=
dst
;
s
->
zstream
.
avail_out
=
s
->
stride
;
zret
=
inflate
(
&
s
->
zstream
,
Z_SYNC_FLUSH
);
if
(
zret
!=
Z_OK
&&
zret
!=
Z_STREAM_END
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate failed with return code: %d.
\n
"
,
zret
);
return
AVERROR_INVALIDDATA
;
}
dst
-=
s
->
frame1
->
linesize
[
0
];
}
bytestream2_skip
(
gb
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
));
return
0
;
}
static
int
decode_mous
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
unsigned
w
,
h
,
pos
,
uncompressed_size
;
int
ret
;
pos
=
bytestream2_tell
(
gb
);
bytestream2_skip
(
gb
,
8
);
w
=
bytestream2_get_le32
(
gb
);
h
=
bytestream2_get_le32
(
gb
);
bytestream2_skip
(
gb
,
12
);
uncompressed_size
=
bytestream2_get_le32
(
gb
);
if
(
w
>
avctx
->
width
||
h
>
avctx
->
height
)
return
AVERROR_INVALIDDATA
;
if
(
uncompressed_size
!=
3
*
w
*
h
)
return
AVERROR_INVALIDDATA
;
av_fast_padded_malloc
(
&
s
->
cursor
,
&
s
->
cursor_size
,
uncompressed_size
);
if
(
!
s
->
cursor
)
return
AVERROR
(
ENOMEM
);
ret
=
decode_zlib
(
avctx
,
avpkt
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
),
uncompressed_size
);
if
(
ret
<
0
)
return
ret
;
memcpy
(
s
->
cursor
,
s
->
delta
,
uncompressed_size
);
bytestream2_skip
(
gb
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
));
s
->
cursor_w
=
w
;
s
->
cursor_h
=
h
;
return
0
;
}
static
int
decode_mpos
(
AVCodecContext
*
avctx
,
AVPacket
*
avpkt
,
unsigned
size
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
unsigned
pos
;
pos
=
bytestream2_tell
(
gb
);
bytestream2_skip
(
gb
,
8
);
s
->
cursor_x
=
bytestream2_get_le32
(
gb
);
s
->
cursor_y
=
bytestream2_get_le32
(
gb
);
bytestream2_skip
(
gb
,
size
-
(
bytestream2_tell
(
gb
)
-
pos
));
return
0
;
}
static
void
draw_cursor
(
AVCodecContext
*
avctx
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
uint8_t
*
dst
,
*
pal
;
if
(
!
s
->
cursor
)
return
;
if
(
s
->
cursor_x
>=
avctx
->
width
||
s
->
cursor_y
>=
avctx
->
height
)
return
;
if
(
s
->
cursor_x
+
s
->
cursor_w
>
avctx
->
width
||
s
->
cursor_y
+
s
->
cursor_h
>
avctx
->
height
)
return
;
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
{
pal
=
s
->
frame
->
data
[
1
];
for
(
int
i
=
0
;
i
<
s
->
cursor_h
;
i
++
)
{
for
(
int
j
=
0
;
j
<
s
->
cursor_w
;
j
++
)
{
int
cr
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
0
];
int
cg
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
1
];
int
cb
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
2
];
int
best
=
INT_MAX
;
int
index
=
0
;
int
dist
;
if
(
cr
==
s
->
cursor
[
0
]
&&
cg
==
s
->
cursor
[
1
]
&&
cb
==
s
->
cursor
[
2
])
continue
;
dst
=
s
->
frame
->
data
[
0
]
+
s
->
frame
->
linesize
[
0
]
*
(
s
->
cursor_y
+
i
)
+
(
s
->
cursor_x
+
j
);
for
(
int
k
=
0
;
k
<
256
;
k
++
)
{
int
pr
=
pal
[
k
*
4
+
0
];
int
pg
=
pal
[
k
*
4
+
1
];
int
pb
=
pal
[
k
*
4
+
2
];
dist
=
FFABS
(
cr
-
pr
)
+
FFABS
(
cg
-
pg
)
+
FFABS
(
cb
-
pb
);
if
(
dist
<
best
)
{
best
=
dist
;
index
=
k
;
}
}
dst
[
0
]
=
index
;
}
}
}
else
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_RGB555LE
)
{
for
(
int
i
=
0
;
i
<
s
->
cursor_h
;
i
++
)
{
for
(
int
j
=
0
;
j
<
s
->
cursor_w
;
j
++
)
{
int
cr
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
0
];
int
cg
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
1
];
int
cb
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
2
];
if
(
cr
==
s
->
cursor
[
0
]
&&
cg
==
s
->
cursor
[
1
]
&&
cb
==
s
->
cursor
[
2
])
continue
;
cr
>>=
3
;
cg
>>=
3
;
cb
>>=
3
;
dst
=
s
->
frame
->
data
[
0
]
+
s
->
frame
->
linesize
[
0
]
*
(
s
->
cursor_y
+
i
)
+
2
*
(
s
->
cursor_x
+
j
);
AV_WL16
(
dst
,
cr
|
cg
<<
5
|
cb
<<
10
);
}
}
}
else
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_BGR0
)
{
for
(
int
i
=
0
;
i
<
s
->
cursor_h
;
i
++
)
{
for
(
int
j
=
0
;
j
<
s
->
cursor_w
;
j
++
)
{
int
cr
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
0
];
int
cg
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
1
];
int
cb
=
s
->
cursor
[
3
*
s
->
cursor_w
*
(
s
->
cursor_h
-
i
-
1
)
+
3
*
j
+
2
];
if
(
cr
==
s
->
cursor
[
0
]
&&
cg
==
s
->
cursor
[
1
]
&&
cb
==
s
->
cursor
[
2
])
continue
;
dst
=
s
->
frame
->
data
[
0
]
+
s
->
frame
->
linesize
[
0
]
*
(
s
->
cursor_y
+
i
)
+
4
*
(
s
->
cursor_x
+
j
);
dst
[
0
]
=
cb
;
dst
[
1
]
=
cg
;
dst
[
2
]
=
cr
;
}
}
}
}
static
int
decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
got_frame
,
AVPacket
*
avpkt
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
GetByteContext
*
gb
=
&
s
->
gb
;
int
ret
,
intra
=
0
;
AVFrame
*
frame
=
data
;
bytestream2_init
(
gb
,
avpkt
->
data
,
avpkt
->
size
);
if
(
bytestream2_peek_le32
(
gb
)
==
EMPT
)
return
avpkt
->
size
;
s
->
frame
=
frame
;
while
(
bytestream2_get_bytes_left
(
gb
)
>
0
)
{
unsigned
type
,
size
=
0
;
type
=
bytestream2_get_le32
(
gb
);
if
(
type
==
KBND
||
type
==
BNDL
)
{
intra
=
type
==
KBND
;
type
=
bytestream2_get_le32
(
gb
);
}
size
=
bytestream2_get_le32
(
gb
);
if
(
bytestream2_get_bytes_left
(
gb
)
<
size
)
return
AVERROR_INVALIDDATA
;
switch
(
type
)
{
case
FINT
:
case
INIT
:
ret
=
decode_fint
(
avctx
,
avpkt
,
size
);
break
;
case
KFRM
:
ret
=
decode_kfrm
(
avctx
,
avpkt
,
size
);
break
;
case
DLTA
:
ret
=
decode_dlta
(
avctx
,
avpkt
,
size
);
break
;
case
MOVE
:
ret
=
decode_move
(
avctx
,
avpkt
,
size
);
break
;
case
MOUS
:
ret
=
decode_mous
(
avctx
,
avpkt
,
size
);
break
;
case
MPOS
:
ret
=
decode_mpos
(
avctx
,
avpkt
,
size
);
break
;
default:
bytestream2_skip
(
gb
,
size
);
}
if
(
ret
<
0
)
return
ret
;
}
if
((
ret
=
ff_get_buffer
(
avctx
,
s
->
frame
,
0
))
<
0
)
return
ret
;
if
(
!
s
->
frame2
->
data
[
0
]
||
!
s
->
frame1
->
data
[
0
])
return
AVERROR_INVALIDDATA
;
copy_plane
(
avctx
,
s
->
frame2
,
s
->
frame
);
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_PAL8
)
memcpy
(
s
->
frame
->
data
[
1
],
s
->
frame2
->
data
[
1
],
1024
);
if
(
!
s
->
skip_cursor
)
draw_cursor
(
avctx
);
s
->
frame
->
key_frame
=
intra
;
s
->
frame
->
pict_type
=
intra
?
AV_PICTURE_TYPE_I
:
AV_PICTURE_TYPE_P
;
*
got_frame
=
1
;
return
avpkt
->
size
;
}
static
av_cold
int
decode_init
(
AVCodecContext
*
avctx
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
int
zret
;
s
->
zstream
.
zalloc
=
Z_NULL
;
s
->
zstream
.
zfree
=
Z_NULL
;
s
->
zstream
.
opaque
=
Z_NULL
;
zret
=
inflateInit
(
&
s
->
zstream
);
if
(
zret
!=
Z_OK
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Inflate init error: %d
\n
"
,
zret
);
return
AVERROR_EXTERNAL
;
}
s
->
frame1
=
av_frame_alloc
();
s
->
frame2
=
av_frame_alloc
();
if
(
!
s
->
frame1
||
!
s
->
frame2
)
return
AVERROR
(
ENOMEM
);
return
0
;
}
static
av_cold
int
decode_close
(
AVCodecContext
*
avctx
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
av_freep
(
&
s
->
cursor
);
s
->
cursor_size
=
0
;
av_freep
(
&
s
->
delta
);
s
->
delta_size
=
0
;
av_frame_free
(
&
s
->
frame1
);
av_frame_free
(
&
s
->
frame2
);
inflateEnd
(
&
s
->
zstream
);
return
0
;
}
static
void
decode_flush
(
AVCodecContext
*
avctx
)
{
RASCContext
*
s
=
avctx
->
priv_data
;
clear_plane
(
avctx
,
s
->
frame1
);
clear_plane
(
avctx
,
s
->
frame2
);
}
static
const
AVOption
options
[]
=
{
{
"skip_cursor"
,
"skip the cursor"
,
offsetof
(
RASCContext
,
skip_cursor
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
0
},
0
,
1
,
AV_OPT_FLAG_DECODING_PARAM
|
AV_OPT_FLAG_VIDEO_PARAM
},
{
NULL
},
};
static
const
AVClass
rasc_decoder_class
=
{
.
class_name
=
"rasc decoder"
,
.
item_name
=
av_default_item_name
,
.
option
=
options
,
.
version
=
LIBAVUTIL_VERSION_INT
,
};
AVCodec
ff_rasc_decoder
=
{
.
name
=
"rasc"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"RemotelyAnywhere Screen Capture"
),
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
id
=
AV_CODEC_ID_RASC
,
.
priv_data_size
=
sizeof
(
RASCContext
),
.
init
=
decode_init
,
.
close
=
decode_close
,
.
decode
=
decode_frame
,
.
flush
=
decode_flush
,
.
capabilities
=
AV_CODEC_CAP_DR1
,
.
caps_internal
=
FF_CODEC_CAP_INIT_THREADSAFE
|
FF_CODEC_CAP_INIT_CLEANUP
,
.
priv_class
=
&
rasc_decoder_class
,
};
libavcodec/version.h
View file @
a5278b67
...
...
@@ -28,8 +28,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 58
#define LIBAVCODEC_VERSION_MINOR 2
7
#define LIBAVCODEC_VERSION_MICRO 10
1
#define LIBAVCODEC_VERSION_MINOR 2
8
#define LIBAVCODEC_VERSION_MICRO 10
0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
...
...
libavformat/riff.c
View file @
a5278b67
...
...
@@ -474,6 +474,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{
AV_CODEC_ID_PROSUMER
,
MKTAG
(
'B'
,
'T'
,
'2'
,
'0'
)
},
{
AV_CODEC_ID_MWSC
,
MKTAG
(
'M'
,
'W'
,
'S'
,
'C'
)
},
{
AV_CODEC_ID_WCMV
,
MKTAG
(
'W'
,
'C'
,
'M'
,
'V'
)
},
{
AV_CODEC_ID_RASC
,
MKTAG
(
'R'
,
'A'
,
'S'
,
'C'
)
},
{
AV_CODEC_ID_NONE
,
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