Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
BC
public
external
ffmpeg
Commits
45ecda85
Commit
45ecda85
authored
Aug 17, 2011
by
Alberto Delmás
Committed by
Anton Khirnov
Aug 23, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Windows Media Image decoder (WMVP/WVP2)
Signed-off-by:
Anton Khirnov
<
anton@khirnov.net
>
parent
3be5a943
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
431 additions
and
85 deletions
+431
-85
Changelog
Changelog
+1
-0
configure
configure
+2
-0
doc/general.texi
doc/general.texi
+1
-0
libavcodec/allcodecs.c
libavcodec/allcodecs.c
+2
-0
libavcodec/avcodec.h
libavcodec/avcodec.h
+2
-0
libavcodec/h263dec.c
libavcodec/h263dec.c
+2
-0
libavcodec/mpegvideo.c
libavcodec/mpegvideo.c
+10
-2
libavcodec/vc1.c
libavcodec/vc1.c
+0
-3
libavcodec/vc1.h
libavcodec/vc1.h
+3
-0
libavcodec/vc1dec.c
libavcodec/vc1dec.c
+327
-77
libavcodec/vc1dsp.c
libavcodec/vc1dsp.c
+68
-0
libavcodec/vc1dsp.h
libavcodec/vc1dsp.h
+10
-0
libavcodec/version.h
libavcodec/version.h
+1
-1
libavformat/riff.c
libavformat/riff.c
+2
-2
No files found.
Changelog
View file @
45ecda85
...
...
@@ -41,6 +41,7 @@ easier to use. The changes are:
'-preset <presetname>'.
* -intra option was removed, it's equivalent to -g 0.
- XMV demuxer
- Windows Media Image decoder
version 0.7:
...
...
configure
View file @
45ecda85
...
...
@@ -1354,6 +1354,7 @@ vc1_dxva2_hwaccel_deps="dxva2api_h DXVA_PictureParameters_wDecodedPictureIndex"
vc1_dxva2_hwaccel_select
=
"dxva2 vc1_decoder"
vc1_vaapi_hwaccel_select
=
"vaapi vc1_decoder"
vc1_vdpau_decoder_select
=
"vdpau vc1_decoder"
vc1image_decoder_select
=
"vc1_decoder"
vorbis_decoder_select
=
"mdct"
vorbis_encoder_select
=
"mdct"
vp6_decoder_select
=
"huffman"
...
...
@@ -1374,6 +1375,7 @@ wmv3_decoder_select="vc1_decoder"
wmv3_dxva2_hwaccel_select
=
"vc1_dxva2_hwaccel"
wmv3_vaapi_hwaccel_select
=
"vc1_vaapi_hwaccel"
wmv3_vdpau_decoder_select
=
"vc1_vdpau_decoder"
wmv3image_decoder_select
=
"wmv3_decoder"
zlib_decoder_select
=
"zlib"
zlib_encoder_select
=
"zlib"
zmbv_decoder_select
=
"zlib"
...
...
doc/general.texi
View file @
45ecda85
...
...
@@ -518,6 +518,7 @@ following image formats are supported:
@item VMware Screen Codec / VMware Video @tab @tab X
@tab Codec used in videos captured by VMware.
@item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X
@item Windows Media Image @tab @tab X
@item Windows Media Video 7 @tab X @tab X
@item Windows Media Video 8 @tab X @tab X
@item Windows Media Video 9 @tab @tab X
...
...
libavcodec/allcodecs.c
View file @
45ecda85
...
...
@@ -203,6 +203,7 @@ void avcodec_register_all(void)
REGISTER_DECODER
(
VB
,
vb
);
REGISTER_DECODER
(
VC1
,
vc1
);
REGISTER_DECODER
(
VC1_VDPAU
,
vc1_vdpau
);
REGISTER_DECODER
(
VC1IMAGE
,
vc1image
);
REGISTER_DECODER
(
VCR1
,
vcr1
);
REGISTER_DECODER
(
VMDVIDEO
,
vmdvideo
);
REGISTER_DECODER
(
VMNC
,
vmnc
);
...
...
@@ -217,6 +218,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC
(
WMV2
,
wmv2
);
REGISTER_DECODER
(
WMV3
,
wmv3
);
REGISTER_DECODER
(
WMV3_VDPAU
,
wmv3_vdpau
);
REGISTER_DECODER
(
WMV3IMAGE
,
wmv3image
);
REGISTER_DECODER
(
WNV1
,
wnv1
);
REGISTER_DECODER
(
XAN_WC3
,
xan_wc3
);
REGISTER_DECODER
(
XAN_WC4
,
xan_wc4
);
...
...
libavcodec/avcodec.h
View file @
45ecda85
...
...
@@ -208,6 +208,8 @@ enum CodecID {
CODEC_ID_PRORES
,
CODEC_ID_JV
,
CODEC_ID_DFA
,
CODEC_ID_WMV3IMAGE
,
CODEC_ID_VC1IMAGE
,
/* various PCM "codecs" */
CODEC_ID_FIRST_AUDIO
=
0x10000
,
///< A dummy id pointing at the start of audio codecs
...
...
libavcodec/h263dec.c
View file @
45ecda85
...
...
@@ -91,6 +91,8 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
break
;
case
CODEC_ID_VC1
:
case
CODEC_ID_WMV3
:
case
CODEC_ID_VC1IMAGE
:
case
CODEC_ID_WMV3IMAGE
:
s
->
h263_pred
=
1
;
s
->
msmpeg4_version
=
6
;
avctx
->
chroma_sample_location
=
AVCHROMA_LOC_LEFT
;
...
...
libavcodec/mpegvideo.c
View file @
45ecda85
...
...
@@ -208,7 +208,12 @@ void ff_copy_picture(Picture *dst, Picture *src){
*/
static
void
free_frame_buffer
(
MpegEncContext
*
s
,
Picture
*
pic
)
{
ff_thread_release_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
/* Windows Media Image codecs allocate internal buffers with different
dimensions; ignore user defined callbacks for these */
if
(
s
->
codec_id
!=
CODEC_ID_WMV3IMAGE
&&
s
->
codec_id
!=
CODEC_ID_VC1IMAGE
)
ff_thread_release_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
else
avcodec_default_release_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
av_freep
(
&
pic
->
f
.
hwaccel_picture_private
);
}
...
...
@@ -230,7 +235,10 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic)
}
}
r
=
ff_thread_get_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
if
(
s
->
codec_id
!=
CODEC_ID_WMV3IMAGE
&&
s
->
codec_id
!=
CODEC_ID_VC1IMAGE
)
r
=
ff_thread_get_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
else
r
=
avcodec_default_get_buffer
(
s
->
avctx
,
(
AVFrame
*
)
pic
);
if
(
r
<
0
||
!
pic
->
f
.
age
||
!
pic
->
f
.
type
||
!
pic
->
f
.
data
[
0
])
{
av_log
(
s
->
avctx
,
AV_LOG_ERROR
,
"get_buffer() failed (%d %d %d %p)
\n
"
,
...
...
libavcodec/vc1.c
View file @
45ecda85
...
...
@@ -314,9 +314,6 @@ int vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitConte
"Old interlaced mode is not supported
\n
"
);
return
-
1
;
}
if
(
v
->
res_sprite
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"WMVP is not fully supported
\n
"
);
}
}
// (fps-2)/4 (->30)
...
...
libavcodec/vc1.h
View file @
45ecda85
...
...
@@ -311,6 +311,9 @@ typedef struct VC1Context{
//@{
int
new_sprite
;
int
two_sprites
;
AVFrame
sprite_output_frame
;
int
output_width
,
output_height
,
sprite_width
,
sprite_height
;
uint8_t
*
sr_rows
[
2
][
2
];
///< Sprite resizer line cache
//@}
int
p_frame_skipped
;
...
...
libavcodec/vc1dec.c
View file @
45ecda85
...
...
@@ -3278,116 +3278,279 @@ static void vc1_decode_blocks(VC1Context *v)
}
}
static
inline
float
get_float_val
(
GetBitContext
*
gb
)
#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER
typedef
struct
{
/**
* Transform coefficients for both sprites in 16.16 fixed point format,
* in the order they appear in the bitstream:
* x scale
* rotation 1 (unused)
* x offset
* rotation 2 (unused)
* y scale
* y offset
* alpha
*/
int
coefs
[
2
][
7
];
int
effect_type
,
effect_flag
;
int
effect_pcount1
,
effect_pcount2
;
///< amount of effect parameters stored in effect_params
int
effect_params1
[
15
],
effect_params2
[
10
];
///< effect parameters in 16.16 fixed point format
}
SpriteData
;
static
inline
int
get_fp_val
(
GetBitContext
*
gb
)
{
return
(
float
)
get_bits_long
(
gb
,
30
)
/
(
1
<<
15
)
-
(
1
<<
14
)
;
return
(
get_bits_long
(
gb
,
30
)
-
(
1
<<
29
))
<<
1
;
}
static
void
vc1_sprite_parse_transform
(
VC1Context
*
v
,
GetBitContext
*
gb
,
floa
t
c
[
7
])
static
void
vc1_sprite_parse_transform
(
GetBitContext
*
gb
,
in
t
c
[
7
])
{
c
[
1
]
=
c
[
3
]
=
0
.
0
f
;
c
[
1
]
=
c
[
3
]
=
0
;
switch
(
get_bits
(
gb
,
2
))
{
case
0
:
c
[
0
]
=
1
.
0
f
;
c
[
2
]
=
get_f
loat
_val
(
gb
);
c
[
4
]
=
1
.
0
f
;
c
[
0
]
=
1
<<
16
;
c
[
2
]
=
get_f
p
_val
(
gb
);
c
[
4
]
=
1
<<
16
;
break
;
case
1
:
c
[
0
]
=
c
[
4
]
=
get_f
loat
_val
(
gb
);
c
[
2
]
=
get_f
loat
_val
(
gb
);
c
[
0
]
=
c
[
4
]
=
get_f
p
_val
(
gb
);
c
[
2
]
=
get_f
p
_val
(
gb
);
break
;
case
2
:
c
[
0
]
=
get_f
loat
_val
(
gb
);
c
[
2
]
=
get_f
loat
_val
(
gb
);
c
[
4
]
=
get_f
loat
_val
(
gb
);
c
[
0
]
=
get_f
p
_val
(
gb
);
c
[
2
]
=
get_f
p
_val
(
gb
);
c
[
4
]
=
get_f
p
_val
(
gb
);
break
;
case
3
:
av_log_ask_for_sample
(
v
->
s
.
avctx
,
NULL
);
c
[
0
]
=
get_float_val
(
gb
);
c
[
1
]
=
get_float_val
(
gb
);
c
[
2
]
=
get_float_val
(
gb
);
c
[
3
]
=
get_float_val
(
gb
);
c
[
4
]
=
get_float_val
(
gb
);
c
[
0
]
=
get_fp_val
(
gb
);
c
[
1
]
=
get_fp_val
(
gb
);
c
[
2
]
=
get_fp_val
(
gb
);
c
[
3
]
=
get_fp_val
(
gb
);
c
[
4
]
=
get_fp_val
(
gb
);
break
;
}
c
[
5
]
=
get_f
loat
_val
(
gb
);
c
[
5
]
=
get_f
p
_val
(
gb
);
if
(
get_bits1
(
gb
))
c
[
6
]
=
get_f
loat
_val
(
gb
);
c
[
6
]
=
get_f
p
_val
(
gb
);
else
c
[
6
]
=
1
.
0
f
;
c
[
6
]
=
1
<<
16
;
}
static
void
vc1_parse_sprites
(
VC1Context
*
v
,
GetBitContext
*
gb
)
static
void
vc1_parse_sprites
(
VC1Context
*
v
,
GetBitContext
*
gb
,
SpriteData
*
sd
)
{
int
effect_type
,
effect_flag
,
effect_pcount1
,
effect_pcount2
,
i
;
float
effect_params1
[
14
],
effect_params2
[
10
];
float
coefs
[
2
][
7
];
vc1_sprite_parse_transform
(
v
,
gb
,
coefs
[
0
]);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"S1:"
);
for
(
i
=
0
;
i
<
7
;
i
++
)
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
" %.3f"
,
coefs
[
0
][
i
]);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
if
(
v
->
two_sprites
)
{
vc1_sprite_parse_transform
(
v
,
gb
,
coefs
[
1
]);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"S2:"
);
AVCodecContext
*
avctx
=
v
->
s
.
avctx
;
int
sprite
,
i
;
for
(
sprite
=
0
;
sprite
<=
v
->
two_sprites
;
sprite
++
)
{
vc1_sprite_parse_transform
(
gb
,
sd
->
coefs
[
sprite
]);
if
(
sd
->
coefs
[
sprite
][
1
]
||
sd
->
coefs
[
sprite
][
3
])
av_log_ask_for_sample
(
avctx
,
"Rotation coefficients are not zero"
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
sprite
?
"S2:"
:
"S1:"
);
for
(
i
=
0
;
i
<
7
;
i
++
)
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
" %.3f"
,
coefs
[
1
][
i
]);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
" %d.%.3d"
,
sd
->
coefs
[
sprite
][
i
]
/
(
1
<<
16
),
(
abs
(
sd
->
coefs
[
sprite
][
i
])
&
0xFFFF
)
*
1000
/
(
1
<<
16
));
av_log
(
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
}
skip_bits
(
gb
,
2
);
if
(
effect_type
=
get_bits_long
(
gb
,
30
)){
switch
(
effect_pcount1
=
get_bits
(
gb
,
4
))
{
case
2
:
effect_params1
[
0
]
=
get_float_val
(
gb
);
effect_params1
[
1
]
=
get_float_val
(
gb
);
break
;
if
(
sd
->
effect_type
=
get_bits_long
(
gb
,
30
))
{
switch
(
sd
->
effect_pcount1
=
get_bits
(
gb
,
4
))
{
case
7
:
vc1_sprite_parse_transform
(
v
,
gb
,
effect_params1
);
vc1_sprite_parse_transform
(
gb
,
sd
->
effect_params1
);
break
;
case
14
:
vc1_sprite_parse_transform
(
v
,
gb
,
effect_params1
);
vc1_sprite_parse_transform
(
v
,
gb
,
&
effect_params1
[
7
]
);
vc1_sprite_parse_transform
(
gb
,
sd
->
effect_params1
);
vc1_sprite_parse_transform
(
gb
,
sd
->
effect_params1
+
7
);
break
;
default:
av_log_ask_for_sample
(
v
->
s
.
avctx
,
NULL
);
return
;
for
(
i
=
0
;
i
<
sd
->
effect_pcount1
;
i
++
)
sd
->
effect_params1
[
i
]
=
get_fp_val
(
gb
)
;
}
if
(
effect_type
!=
13
||
effect_params1
[
0
]
!=
coefs
[
0
][
6
])
{
if
(
sd
->
effect_type
!=
13
||
sd
->
effect_params1
[
0
]
!=
sd
->
coefs
[
0
][
6
])
{
// effect 13 is simple alpha blending and matches the opacity above
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"Effect: %d; params: "
,
effect_type
);
for
(
i
=
0
;
i
<
effect_pcount1
;
i
++
)
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
" %.3f"
,
effect_params1
[
i
]);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
"Effect: %d; params: "
,
sd
->
effect_type
);
for
(
i
=
0
;
i
<
sd
->
effect_pcount1
;
i
++
)
av_log
(
avctx
,
AV_LOG_DEBUG
,
" %d.%.2d"
,
sd
->
effect_params1
[
i
]
/
(
1
<<
16
),
(
abs
(
sd
->
effect_params1
[
i
])
&
0xFFFF
)
*
1000
/
(
1
<<
16
));
av_log
(
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
}
effect_pcount2
=
get_bits
(
gb
,
16
);
if
(
effect_pcount2
>
10
)
{
av_log
(
v
->
s
.
avctx
,
AV_LOG_ERROR
,
"Too many effect parameters
\n
"
);
sd
->
effect_pcount2
=
get_bits
(
gb
,
16
);
if
(
sd
->
effect_pcount2
>
10
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Too many effect parameters
\n
"
);
return
;
}
else
if
(
effect_pcount2
)
{
i
=
0
;
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"Effect params 2: "
);
while
(
i
<
effect_pcount2
){
effect_params2
[
i
]
=
get_float_val
(
gb
);
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
" %.3f"
,
effect_params2
[
i
]);
i
++
;
}
else
if
(
sd
->
effect_pcount2
)
{
i
=
-
1
;
av_log
(
avctx
,
AV_LOG_DEBUG
,
"Effect params 2: "
);
while
(
++
i
<
sd
->
effect_pcount2
){
sd
->
effect_params2
[
i
]
=
get_fp_val
(
gb
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
" %d.%.2d"
,
sd
->
effect_params2
[
i
]
/
(
1
<<
16
),
(
abs
(
sd
->
effect_params2
[
i
])
&
0xFFFF
)
*
1000
/
(
1
<<
16
));
}
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
av_log
(
avctx
,
AV_LOG_DEBUG
,
"
\n
"
);
}
}
if
(
effect_flag
=
get_bits1
(
gb
))
av_log
(
v
->
s
.
avctx
,
AV_LOG_DEBUG
,
"Effect flag set
\n
"
);
if
(
sd
->
effect_flag
=
get_bits1
(
gb
))
av_log
(
avctx
,
AV_LOG_DEBUG
,
"Effect flag set
\n
"
);
if
(
get_bits_count
(
gb
)
>=
gb
->
size_in_bits
+
(
v
->
s
.
avctx
->
codec_id
==
CODEC_ID_WMV3
?
64
:
0
))
av_log
(
v
->
s
.
avctx
,
AV_LOG_ERROR
,
"Buffer overrun
\n
"
);
(
avctx
->
codec_id
==
CODEC_ID_WMV3
IMAGE
?
64
:
0
))
av_log
(
avctx
,
AV_LOG_ERROR
,
"Buffer overrun
\n
"
);
if
(
get_bits_count
(
gb
)
<
gb
->
size_in_bits
-
8
)
av_log
(
v
->
s
.
avctx
,
AV_LOG_WARNING
,
"Buffer not fully read
\n
"
);
av_log
(
avctx
,
AV_LOG_WARNING
,
"Buffer not fully read
\n
"
);
}
static
void
vc1_draw_sprites
(
VC1Context
*
v
,
SpriteData
*
sd
)
{
int
i
,
plane
,
row
,
sprite
;
int
sr_cache
[
2
][
2
]
=
{
{
-
1
,
-
1
},
{
-
1
,
-
1
}
};
uint8_t
*
src_h
[
2
][
2
];
int
xoff
[
2
],
xadv
[
2
],
yoff
[
2
],
yadv
[
2
],
alpha
;
int
ysub
[
2
];
MpegEncContext
*
s
=
&
v
->
s
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
xoff
[
i
]
=
av_clip
(
sd
->
coefs
[
i
][
2
],
0
,
v
->
sprite_width
-
1
<<
16
);
xadv
[
i
]
=
sd
->
coefs
[
i
][
0
];
if
(
xadv
[
i
]
!=
1
<<
16
||
(
v
->
sprite_width
<<
16
)
-
(
v
->
output_width
<<
16
)
-
xoff
[
i
])
xadv
[
i
]
=
av_clip
(
xadv
[
i
],
0
,
((
v
->
sprite_width
<<
16
)
-
xoff
[
i
]
-
1
)
/
v
->
output_width
);
yoff
[
i
]
=
av_clip
(
sd
->
coefs
[
i
][
5
],
0
,
v
->
sprite_height
-
1
<<
16
);
yadv
[
i
]
=
av_clip
(
sd
->
coefs
[
i
][
4
],
0
,
((
v
->
sprite_height
<<
16
)
-
yoff
[
i
])
/
v
->
output_height
);
}
alpha
=
av_clip
(
sd
->
coefs
[
1
][
6
],
0
,
(
1
<<
16
)
-
1
);
for
(
plane
=
0
;
plane
<
(
s
->
flags
&
CODEC_FLAG_GRAY
?
1
:
3
);
plane
++
)
{
int
width
=
v
->
output_width
>>!!
plane
;
for
(
row
=
0
;
row
<
v
->
output_height
>>!!
plane
;
row
++
)
{
uint8_t
*
dst
=
v
->
sprite_output_frame
.
data
[
plane
]
+
v
->
sprite_output_frame
.
linesize
[
plane
]
*
row
;
for
(
sprite
=
0
;
sprite
<=
v
->
two_sprites
;
sprite
++
)
{
uint8_t
*
iplane
=
s
->
current_picture
.
f
.
data
[
plane
];
int
iline
=
s
->
current_picture
.
f
.
linesize
[
plane
];
int
ycoord
=
yoff
[
sprite
]
+
yadv
[
sprite
]
*
row
;
int
yline
=
ycoord
>>
16
;
ysub
[
sprite
]
=
ycoord
&
0xFFFF
;
if
(
sprite
)
{
iplane
=
s
->
last_picture
.
f
.
data
[
plane
];
iline
=
s
->
last_picture
.
f
.
linesize
[
plane
];
}
if
(
!
(
xoff
[
sprite
]
&
0xFFFF
)
&&
xadv
[
sprite
]
==
1
<<
16
)
{
src_h
[
sprite
][
0
]
=
iplane
+
(
xoff
[
sprite
]
>>
16
)
+
yline
*
iline
;
if
(
ysub
[
sprite
])
src_h
[
sprite
][
1
]
=
iplane
+
(
xoff
[
sprite
]
>>
16
)
+
(
yline
+
1
)
*
iline
;
}
else
{
if
(
sr_cache
[
sprite
][
0
]
!=
yline
)
{
if
(
sr_cache
[
sprite
][
1
]
==
yline
)
{
FFSWAP
(
uint8_t
*
,
v
->
sr_rows
[
sprite
][
0
],
v
->
sr_rows
[
sprite
][
1
]);
FFSWAP
(
int
,
sr_cache
[
sprite
][
0
],
sr_cache
[
sprite
][
1
]);
}
else
{
v
->
vc1dsp
.
sprite_h
(
v
->
sr_rows
[
sprite
][
0
],
iplane
+
yline
*
iline
,
xoff
[
sprite
],
xadv
[
sprite
],
width
);
sr_cache
[
sprite
][
0
]
=
yline
;
}
}
if
(
ysub
[
sprite
]
&&
sr_cache
[
sprite
][
1
]
!=
yline
+
1
)
{
v
->
vc1dsp
.
sprite_h
(
v
->
sr_rows
[
sprite
][
1
],
iplane
+
(
yline
+
1
)
*
iline
,
xoff
[
sprite
],
xadv
[
sprite
],
width
);
sr_cache
[
sprite
][
1
]
=
yline
+
1
;
}
src_h
[
sprite
][
0
]
=
v
->
sr_rows
[
sprite
][
0
];
src_h
[
sprite
][
1
]
=
v
->
sr_rows
[
sprite
][
1
];
}
}
if
(
!
v
->
two_sprites
)
{
if
(
ysub
[
0
])
{
v
->
vc1dsp
.
sprite_v_single
(
dst
,
src_h
[
0
][
0
],
src_h
[
0
][
1
],
ysub
[
0
],
width
);
}
else
{
memcpy
(
dst
,
src_h
[
0
][
0
],
width
);
}
}
else
{
if
(
ysub
[
0
]
&&
ysub
[
1
])
{
v
->
vc1dsp
.
sprite_v_double_twoscale
(
dst
,
src_h
[
0
][
0
],
src_h
[
0
][
1
],
ysub
[
0
],
src_h
[
1
][
0
],
src_h
[
1
][
1
],
ysub
[
1
],
alpha
,
width
);
}
else
if
(
ysub
[
0
])
{
v
->
vc1dsp
.
sprite_v_double_onescale
(
dst
,
src_h
[
0
][
0
],
src_h
[
0
][
1
],
ysub
[
0
],
src_h
[
1
][
0
],
alpha
,
width
);
}
else
if
(
ysub
[
1
])
{
v
->
vc1dsp
.
sprite_v_double_onescale
(
dst
,
src_h
[
1
][
0
],
src_h
[
1
][
1
],
ysub
[
1
],
src_h
[
0
][
0
],
(
1
<<
16
)
-
1
-
alpha
,
width
);
}
else
{
v
->
vc1dsp
.
sprite_v_double_noscale
(
dst
,
src_h
[
0
][
0
],
src_h
[
1
][
0
],
alpha
,
width
);
}
}
}
if
(
!
plane
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
xoff
[
i
]
>>=
1
;
yoff
[
i
]
>>=
1
;
}
}
}
}
static
int
vc1_decode_sprites
(
VC1Context
*
v
,
GetBitContext
*
gb
)
{
MpegEncContext
*
s
=
&
v
->
s
;
AVCodecContext
*
avctx
=
s
->
avctx
;
SpriteData
sd
;
vc1_parse_sprites
(
v
,
gb
,
&
sd
);
if
(
!
s
->
current_picture
.
f
.
data
[
0
])
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Got no sprites
\n
"
);
return
-
1
;
}
if
(
v
->
two_sprites
&&
(
!
s
->
last_picture_ptr
||
!
s
->
last_picture
.
f
.
data
[
0
]))
{
av_log
(
avctx
,
AV_LOG_WARNING
,
"Need two sprites, only got one
\n
"
);
v
->
two_sprites
=
0
;
}
if
(
v
->
sprite_output_frame
.
data
[
0
])
avctx
->
release_buffer
(
avctx
,
&
v
->
sprite_output_frame
);
v
->
sprite_output_frame
.
buffer_hints
=
FF_BUFFER_HINTS_VALID
;
v
->
sprite_output_frame
.
reference
=
0
;
if
(
avctx
->
get_buffer
(
avctx
,
&
v
->
sprite_output_frame
)
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"get_buffer() failed
\n
"
);
return
-
1
;
}
vc1_draw_sprites
(
v
,
&
sd
);
return
0
;
}
static
void
vc1_sprite_flush
(
AVCodecContext
*
avctx
)
{
VC1Context
*
v
=
avctx
->
priv_data
;
MpegEncContext
*
s
=
&
v
->
s
;
AVFrame
*
f
=
&
s
->
current_picture
.
f
;
int
plane
,
i
;
/* Windows Media Image codecs have a convergence interval of two keyframes.
Since we can't enforce it, clear to black the missing sprite. This is
wrong but it looks better than doing nothing. */
if
(
f
->
data
[
0
])
for
(
plane
=
0
;
plane
<
(
s
->
flags
&
CODEC_FLAG_GRAY
?
1
:
3
);
plane
++
)
for
(
i
=
0
;
i
<
v
->
sprite_height
>>!!
plane
;
i
++
)
memset
(
f
->
data
[
plane
]
+
i
*
f
->
linesize
[
plane
],
plane
?
128
:
0
,
f
->
linesize
[
plane
]);
}
#endif
/** Initialize a VC1/WMV3 decoder
* @todo TODO: Handle VC-1 IDUs (Transport level?)
* @todo TODO: Decypher remaining bits in extra_data
...
...
@@ -3399,6 +3562,10 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
GetBitContext
gb
;
int
i
,
cur_width
,
cur_height
;
/* save the container output size for WMImage */
v
->
output_width
=
avctx
->
width
;
v
->
output_height
=
avctx
->
height
;
if
(
!
avctx
->
extradata_size
||
!
avctx
->
extradata
)
return
-
1
;
if
(
!
(
avctx
->
flags
&
CODEC_FLAG_GRAY
))
avctx
->
pix_fmt
=
avctx
->
get_format
(
avctx
,
avctx
->
codec
->
pix_fmts
);
...
...
@@ -3420,7 +3587,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
cur_width
=
avctx
->
coded_width
=
avctx
->
width
;
cur_height
=
avctx
->
coded_height
=
avctx
->
height
;
if
(
avctx
->
codec_id
==
CODEC_ID_WMV3
)
if
(
avctx
->
codec_id
==
CODEC_ID_WMV3
||
avctx
->
codec_id
==
CODEC_ID_WMV3IMAGE
)
{
int
count
=
0
;
...
...
@@ -3562,6 +3729,25 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
}
ff_intrax8_common_init
(
&
v
->
x8
,
s
);
if
(
avctx
->
codec_id
==
CODEC_ID_WMV3IMAGE
||
avctx
->
codec_id
==
CODEC_ID_VC1IMAGE
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
!
(
v
->
sr_rows
[
i
>>
1
][
i
%
2
]
=
av_malloc
(
v
->
output_width
)))
return
-
1
;
s
->
low_delay
=
1
;
v
->
sprite_width
=
avctx
->
coded_width
;
v
->
sprite_height
=
avctx
->
coded_height
;
avctx
->
coded_width
=
avctx
->
width
=
v
->
output_width
;
avctx
->
coded_height
=
avctx
->
height
=
v
->
output_height
;
// prevent 16.16 overflows
if
(
v
->
sprite_width
>
1
<<
14
||
v
->
sprite_height
>
1
<<
14
||
v
->
output_width
>
1
<<
14
||
v
->
output_height
>
1
<<
14
)
return
-
1
;
}
return
0
;
}
...
...
@@ -3614,7 +3800,7 @@ static int vc1_decode_frame(AVCodecContext *avctx,
}
//for advanced profile we may need to parse and unescape data
if
(
avctx
->
codec_id
==
CODEC_ID_VC1
)
{
if
(
avctx
->
codec_id
==
CODEC_ID_VC1
||
avctx
->
codec_id
==
CODEC_ID_VC1IMAGE
)
{
int
buf_size2
=
0
;
buf2
=
av_mallocz
(
buf_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
...
...
@@ -3679,8 +3865,19 @@ static int vc1_decode_frame(AVCodecContext *avctx,
if
(
v
->
res_sprite
)
{
v
->
new_sprite
=
!
get_bits1
(
&
s
->
gb
);
v
->
two_sprites
=
get_bits1
(
&
s
->
gb
);
if
(
!
v
->
new_sprite
)
goto
end
;
/* res_sprite means a Windows Media Image stream, CODEC_ID_*IMAGE means
we're using the sprite compositor. These are intentionally kept separate
so you can get the raw sprites by using the wmv3 decoder for WMVP or
the vc1 one for WVP2 */
if
(
avctx
->
codec_id
==
CODEC_ID_WMV3IMAGE
||
avctx
->
codec_id
==
CODEC_ID_VC1IMAGE
)
{
if
(
v
->
new_sprite
)
{
// switch AVCodecContext parameters to those of the sprites
avctx
->
width
=
avctx
->
coded_width
=
v
->
sprite_width
;
avctx
->
height
=
avctx
->
coded_height
=
v
->
sprite_height
;
}
else
{
goto
image
;
}
}
}
// do parse frame header
...
...
@@ -3694,8 +3891,10 @@ static int vc1_decode_frame(AVCodecContext *avctx,
}
}
if
(
v
->
res_sprite
&&
s
->
pict_type
!=
AV_PICTURE_TYPE_I
)
{
av_log
(
v
->
s
.
avctx
,
AV_LOG_WARNING
,
"Sprite decoder: expected I-frame
\n
"
);
if
((
avctx
->
codec_id
==
CODEC_ID_WMV3IMAGE
||
avctx
->
codec_id
==
CODEC_ID_VC1IMAGE
)
&&
s
->
pict_type
!=
AV_PICTURE_TYPE_I
)
{
av_log
(
v
->
s
.
avctx
,
AV_LOG_ERROR
,
"Sprite decoder: expected I-frame
\n
"
);
goto
err
;
}
// for skipping the frame
...
...
@@ -3758,6 +3957,19 @@ static int vc1_decode_frame(AVCodecContext *avctx,
assert
(
s
->
current_picture
.
f
.
pict_type
==
s
->
current_picture_ptr
->
f
.
pict_type
);
assert
(
s
->
current_picture
.
f
.
pict_type
==
s
->
pict_type
);
if
(
avctx
->
codec_id
==
CODEC_ID_WMV3IMAGE
||
avctx
->
codec_id
==
CODEC_ID_VC1IMAGE
)
{
image:
avctx
->
width
=
avctx
->
coded_width
=
v
->
output_width
;
avctx
->
height
=
avctx
->
coded_height
=
v
->
output_height
;
if
(
avctx
->
skip_frame
>=
AVDISCARD_NONREF
)
goto
end
;
#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER
if
(
vc1_decode_sprites
(
v
,
&
s
->
gb
))
goto
err
;
#endif
*
pict
=
v
->
sprite_output_frame
;
*
data_size
=
sizeof
(
AVFrame
);
}
else
{
if
(
s
->
pict_type
==
AV_PICTURE_TYPE_B
||
s
->
low_delay
)
{
*
pict
=
*
(
AVFrame
*
)
s
->
current_picture_ptr
;
}
else
if
(
s
->
last_picture_ptr
!=
NULL
)
{
...
...
@@ -3769,9 +3981,9 @@ assert(s->current_picture.f.pict_type == s->pict_type);
ff_print_debug_info
(
s
,
pict
);
}
}
end:
if
(
v
->
res_sprite
)
vc1_parse_sprites
(
v
,
&
s
->
gb
);
av_free
(
buf2
);
for
(
i
=
0
;
i
<
n_slices
;
i
++
)
av_free
(
slices
[
i
].
buf
);
...
...
@@ -3793,7 +4005,13 @@ err:
static
av_cold
int
vc1_decode_end
(
AVCodecContext
*
avctx
)