Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Guillaume Martres
aom-rav1e
Commits
a82001b1
Commit
a82001b1
authored
Oct 21, 2013
by
Ivan Maltz
Committed by
Gerrit Code Review
Oct 21, 2013
Browse files
Merge "SVC improvements"
parents
f6d870f7
663916ce
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
libs.mk
View file @
a82001b1
...
...
@@ -122,6 +122,7 @@ ifeq ($(CONFIG_VP9_ENCODER),yes)
CODEC_EXPORTS-yes
+=
$(
addprefix
$(VP9_PREFIX)
,
$(VP9_CX_EXPORTS)
)
CODEC_SRCS-yes
+=
$(VP9_PREFIX)
vp9cx.mk vpx/vp8.h vpx/vp8cx.h
INSTALL-LIBS-yes
+=
include/vpx/vp8.h include/vpx/vp8cx.h
INSTALL-LIBS-yes
+=
include/vpx/svc_context.h
INSTALL_MAPS
+=
include/vpx/%
$(SRC_PATH_BARE)
/
$(VP9_PREFIX)
/%
CODEC_DOC_SRCS
+=
vpx/vp8.h vpx/vp8cx.h
CODEC_DOC_SECTIONS
+=
vp9 vp9_encoder
...
...
test/svc_test.cc
0 → 100644
View file @
a82001b1
#include
<string>
#include
"third_party/googletest/src/include/gtest/gtest.h"
#include
"test/i420_video_source.h"
#include
"test/decode_test_driver.h"
#include
"vpx/vpx_encoder.h"
#include
"vpx/vp8cx.h"
#include
"test/codec_factory.h"
extern
"C"
{
#include
"vpx/svc_context.h"
}
namespace
{
using
libvpx_test
::
CodecFactory
;
using
libvpx_test
::
VP9CodecFactory
;
using
libvpx_test
::
Decoder
;
class
SvcTest
:
public
::
testing
::
Test
{
protected:
SvcTest
()
:
codec_iface_
(
0
),
test_file_name
(
"hantro_collage_w352h288.yuv"
),
decoder_
(
0
)
{}
virtual
void
SetUp
()
{
memset
(
&
svc_
,
0
,
sizeof
(
svc_
));
svc_
.
first_frame_full_size
=
1
;
svc_
.
encoding_mode
=
INTER_LAYER_PREDICTION_IP
;
svc_
.
log_level
=
SVC_LOG_DEBUG
;
svc_
.
log_print
=
1
;
svc_
.
gop_size
=
100
;
codec_iface_
=
vpx_codec_vp9_cx
();
vpx_codec_err_t
res
=
vpx_codec_enc_config_default
(
codec_iface_
,
&
codec_enc_
,
0
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
codec_enc_
.
g_w
=
kWidth
;
codec_enc_
.
g_h
=
kHeight
;
codec_enc_
.
g_timebase
.
num
=
1
;
codec_enc_
.
g_timebase
.
den
=
60
;
vpx_codec_dec_cfg_t
dec_cfg
=
{
0
};
VP9CodecFactory
codec_factory
;
decoder_
=
codec_factory
.
CreateDecoder
(
dec_cfg
,
0
);
}
SvcContext
svc_
;
vpx_codec_ctx_t
codec_
;
struct
vpx_codec_enc_cfg
codec_enc_
;
vpx_codec_iface_t
*
codec_iface_
;
std
::
string
test_file_name
;
enum
{
kWidth
=
352
,
kHeight
=
288
,
};
Decoder
*
decoder_
;
};
TEST_F
(
SvcTest
,
SvcInit
)
{
svc_
.
spatial_layers
=
0
;
// not enough layers
vpx_codec_err_t
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
codec_iface_
,
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_INVALID_PARAM
);
svc_
.
spatial_layers
=
6
;
// too many layers
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
codec_iface_
,
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_INVALID_PARAM
);
svc_
.
spatial_layers
=
2
;
svc_
.
scale_factors
=
"4/16,16*16"
;
// invalid scale values
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
codec_iface_
,
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_INVALID_PARAM
);
svc_
.
scale_factors
=
"4/16,16/16"
;
// valid scale values
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
codec_iface_
,
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
}
// test that decoder can handle an svc frame as the first frame in a sequence
// this test is disabled since it with the deco
TEST_F
(
SvcTest
,
DISABLED_FirstFrameHasLayers
)
{
svc_
.
first_frame_full_size
=
0
;
svc_
.
spatial_layers
=
2
;
svc_
.
scale_factors
=
"4/16,16/16"
;
svc_
.
quantizer_values
=
"40,30"
;
vpx_codec_err_t
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
vpx_codec_vp9_cx
(),
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
libvpx_test
::
I420VideoSource
video
(
test_file_name
,
kWidth
,
kHeight
,
codec_enc_
.
g_timebase
.
den
,
codec_enc_
.
g_timebase
.
num
,
0
,
30
);
video
.
Begin
();
res
=
vpx_svc_encode
(
&
svc_
,
&
codec_
,
video
.
img
(),
video
.
pts
(),
video
.
duration
(),
VPX_DL_REALTIME
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
vpx_codec_err_t
res_dec
=
decoder_
->
DecodeFrame
(
(
const
uint8_t
*
)
svc_get_buffer
(
&
svc_
),
svc_get_frame_size
(
&
svc_
));
// this test fails with a decoder error
ASSERT_EQ
(
VPX_CODEC_OK
,
res_dec
)
<<
decoder_
->
DecodeError
();
}
TEST_F
(
SvcTest
,
EncodeThreeFrames
)
{
svc_
.
first_frame_full_size
=
1
;
svc_
.
spatial_layers
=
2
;
svc_
.
scale_factors
=
"4/16,16/16"
;
svc_
.
quantizer_values
=
"40,30"
;
vpx_codec_err_t
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
vpx_codec_vp9_cx
(),
&
codec_enc_
);
ASSERT_EQ
(
res
,
VPX_CODEC_OK
);
libvpx_test
::
I420VideoSource
video
(
test_file_name
,
kWidth
,
kHeight
,
codec_enc_
.
g_timebase
.
den
,
codec_enc_
.
g_timebase
.
num
,
0
,
30
);
// FRAME 1
video
.
Begin
();
// this frame is full size, with only one layer
res
=
vpx_svc_encode
(
&
svc_
,
&
codec_
,
video
.
img
(),
video
.
pts
(),
video
.
duration
(),
VPX_DL_REALTIME
);
ASSERT_EQ
(
res
,
VPX_CODEC_OK
);
EXPECT_EQ
(
1
,
svc_is_keyframe
(
&
svc_
));
vpx_codec_err_t
res_dec
=
decoder_
->
DecodeFrame
(
(
const
uint8_t
*
)
svc_get_buffer
(
&
svc_
),
svc_get_frame_size
(
&
svc_
));
ASSERT_EQ
(
VPX_CODEC_OK
,
res_dec
)
<<
decoder_
->
DecodeError
();
// FRAME 2
video
.
Next
();
// this is an I-frame
res
=
vpx_svc_encode
(
&
svc_
,
&
codec_
,
video
.
img
(),
video
.
pts
(),
video
.
duration
(),
VPX_DL_REALTIME
);
ASSERT_EQ
(
res
,
VPX_CODEC_OK
);
EXPECT_EQ
(
1
,
svc_is_keyframe
(
&
svc_
));
res_dec
=
decoder_
->
DecodeFrame
((
const
uint8_t
*
)
svc_get_buffer
(
&
svc_
),
svc_get_frame_size
(
&
svc_
));
ASSERT_EQ
(
VPX_CODEC_OK
,
res_dec
)
<<
decoder_
->
DecodeError
();
// FRAME 2
video
.
Next
();
// this is a P-frame
res
=
vpx_svc_encode
(
&
svc_
,
&
codec_
,
video
.
img
(),
video
.
pts
(),
video
.
duration
(),
VPX_DL_REALTIME
);
ASSERT_EQ
(
res
,
VPX_CODEC_OK
);
EXPECT_EQ
(
0
,
svc_is_keyframe
(
&
svc_
));
res_dec
=
decoder_
->
DecodeFrame
((
const
uint8_t
*
)
svc_get_buffer
(
&
svc_
),
svc_get_frame_size
(
&
svc_
));
ASSERT_EQ
(
VPX_CODEC_OK
,
res_dec
)
<<
decoder_
->
DecodeError
();
}
TEST_F
(
SvcTest
,
GetLayerResolution
)
{
unsigned
int
layer_width
,
layer_height
;
svc_
.
first_frame_full_size
=
0
;
svc_
.
spatial_layers
=
2
;
svc_
.
scale_factors
=
"4/16,8/16"
;
svc_
.
quantizer_values
=
"40,30"
;
vpx_codec_err_t
res
=
vpx_svc_init
(
&
svc_
,
&
codec_
,
vpx_codec_vp9_cx
(),
&
codec_enc_
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
// ensure that requested layer is a valid layer
res
=
svc_get_layer_resolution
(
&
svc_
,
svc_
.
spatial_layers
,
&
layer_width
,
&
layer_height
);
EXPECT_EQ
(
res
,
VPX_CODEC_INVALID_PARAM
);
res
=
svc_get_layer_resolution
(
&
svc_
,
0
,
&
layer_width
,
&
layer_height
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
EXPECT_EQ
((
unsigned
int
)(
kWidth
*
4
/
16
),
layer_width
);
EXPECT_EQ
((
unsigned
int
)(
kHeight
*
4
/
16
),
layer_height
);
res
=
svc_get_layer_resolution
(
&
svc_
,
1
,
&
layer_width
,
&
layer_height
);
EXPECT_EQ
(
res
,
VPX_CODEC_OK
);
EXPECT_EQ
((
unsigned
int
)(
kWidth
*
8
/
16
),
layer_width
);
EXPECT_EQ
((
unsigned
int
)(
kHeight
*
8
/
16
),
layer_height
);
}
}
// namespace
test/test.mk
View file @
a82001b1
...
...
@@ -96,6 +96,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct8x8_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER)
+=
dct16x16_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER)
+=
variance_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER)
+=
dct32x32_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER)
+=
svc_test.cc
endif
# VP9
...
...
vp9/common/vp9_onyx.h
View file @
a82001b1
...
...
@@ -221,8 +221,6 @@ extern "C"
int
vp9_set_size_literal
(
VP9_PTR
comp
,
unsigned
int
width
,
unsigned
int
height
);
int
vp9_switch_layer
(
VP9_PTR
comp
,
int
layer
);
void
vp9_set_svc
(
VP9_PTR
comp
,
int
use_svc
);
int
vp9_get_quantizer
(
VP9_PTR
c
);
...
...
vp9/encoder/vp9_onyx_if.c
View file @
a82001b1
...
...
@@ -4226,37 +4226,9 @@ int vp9_set_size_literal(VP9_PTR comp, unsigned int width,
return
0
;
}
int
vp9_switch_layer
(
VP9_PTR
comp
,
int
layer
)
{
VP9_COMP
*
cpi
=
(
VP9_COMP
*
)
comp
;
if
(
cpi
->
use_svc
)
{
cpi
->
current_layer
=
layer
;
// Use buffer i for layer i LST
cpi
->
lst_fb_idx
=
layer
;
// Use buffer i-1 for layer i Alt (Inter-layer prediction)
if
(
layer
!=
0
)
cpi
->
alt_fb_idx
=
layer
-
1
;
// Use the rest for Golden
if
(
layer
<
2
*
cpi
->
number_spatial_layers
-
NUM_REF_FRAMES
)
cpi
->
gld_fb_idx
=
cpi
->
lst_fb_idx
;
else
cpi
->
gld_fb_idx
=
2
*
cpi
->
number_spatial_layers
-
1
-
layer
;
printf
(
"Switching to layer %d:
\n
"
,
layer
);
printf
(
"Using references: LST/GLD/ALT [%d|%d|%d]
\n
"
,
cpi
->
lst_fb_idx
,
cpi
->
gld_fb_idx
,
cpi
->
alt_fb_idx
);
}
else
{
printf
(
"Switching layer not supported. Enable SVC first
\n
"
);
}
return
0
;
}
void
vp9_set_svc
(
VP9_PTR
comp
,
int
use_svc
)
{
VP9_COMP
*
cpi
=
(
VP9_COMP
*
)
comp
;
cpi
->
use_svc
=
use_svc
;
if
(
cpi
->
use_svc
)
printf
(
"Enabled SVC encoder
\n
"
);
return
;
}
...
...
vp9/vp9_cx_iface.c
View file @
a82001b1
...
...
@@ -442,8 +442,6 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
MAP
(
VP8E_SET_ARNR_TYPE
,
xcfg
.
arnr_type
);
MAP
(
VP8E_SET_TUNING
,
xcfg
.
tuning
);
MAP
(
VP8E_SET_CQ_LEVEL
,
xcfg
.
cq_level
);
MAP
(
VP9E_SET_MAX_Q
,
ctx
->
cfg
.
rc_max_quantizer
);
MAP
(
VP9E_SET_MIN_Q
,
ctx
->
cfg
.
rc_min_quantizer
);
MAP
(
VP8E_SET_MAX_INTRA_BITRATE_PCT
,
xcfg
.
rc_max_intra_bitrate_pct
);
MAP
(
VP9E_SET_LOSSLESS
,
xcfg
.
lossless
);
MAP
(
VP9E_SET_FRAME_PARALLEL_DECODING
,
xcfg
.
frame_parallel_decoding_mode
);
...
...
@@ -1029,66 +1027,40 @@ static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
}
}
static
vpx_codec_err_t
vp9e_set_width
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
unsigned
int
*
data
=
va_arg
(
args
,
unsigned
int
*
);
if
(
data
)
{
int
res
;
res
=
vp9_set_size_literal
(
ctx
->
cpi
,
*
data
,
0
);
if
(
!
res
)
{
return
VPX_CODEC_OK
;
}
else
{
return
VPX_CODEC_INVALID_PARAM
;
}
}
else
{
return
VPX_CODEC_INVALID_PARAM
;
}
static
vpx_codec_err_t
vp9e_set_svc
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
int
data
=
va_arg
(
args
,
int
);
vp9_set_svc
(
ctx
->
cpi
,
data
);
return
VPX_CODEC_OK
;
}
static
vpx_codec_err_t
vp9e_set_height
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
unsigned
int
*
data
=
va_arg
(
args
,
unsigned
int
*
);
if
(
data
)
{
int
res
;
res
=
vp9_set_size_literal
(
ctx
->
cpi
,
0
,
*
data
);
static
vpx_codec_err_t
vp9e_set_svc_parameters
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
vpx_svc_parameters_t
*
data
=
va_arg
(
args
,
vpx_svc_parameters_t
*
);
VP9_COMP
*
cpi
=
(
VP9_COMP
*
)
ctx
->
cpi
;
vpx_svc_parameters_t
params
;
if
(
!
res
)
{
return
VPX_CODEC_OK
;
}
else
{
return
VPX_CODEC_INVALID_PARAM
;
}
}
else
{
if
(
!
data
)
{
return
VPX_CODEC_INVALID_PARAM
;
}
}
static
vpx_codec_err_t
vp9e_set_layer
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
unsigned
int
*
data
=
va_arg
(
args
,
unsigned
int
*
);
if
(
data
)
{
int
res
;
res
=
0
;
params
=
*
(
vpx_svc_parameters_t
*
)
data
;
res
=
vp9_switch_layer
(
ctx
->
cpi
,
*
data
);
cpi
->
current_layer
=
params
.
layer
;
cpi
->
lst_fb_idx
=
params
.
lst_fb_idx
;
cpi
->
gld_fb_idx
=
params
.
gld_fb_idx
;
cpi
->
alt_fb_idx
=
params
.
alt_fb_idx
;
if
(
!
res
)
{
return
VPX_CODEC_OK
;
}
else
{
return
VPX_CODEC_INVALID_PARAM
;
}
}
else
{
if
(
vp9_set_size_literal
(
ctx
->
cpi
,
params
.
width
,
params
.
height
)
!=
0
)
{
return
VPX_CODEC_INVALID_PARAM
;
}
}
static
vpx_codec_err_t
vp9e_set_svc
(
vpx_codec_alg_priv_t
*
ctx
,
int
ctr_id
,
va_list
args
)
{
int
data
=
va_arg
(
args
,
int
);
vp9_set_svc
(
ctx
->
cpi
,
data
);
ctx
->
cfg
.
rc_max_quantizer
=
params
.
max_quantizer
;
ctx
->
cfg
.
rc_min_quantizer
=
params
.
min_quantizer
;
set_vp9e_config
(
&
ctx
->
oxcf
,
ctx
->
cfg
,
ctx
->
vp8_cfg
);
vp9_change_config
(
ctx
->
cpi
,
&
ctx
->
oxcf
);
return
VPX_CODEC_OK
;
}
...
...
@@ -1116,16 +1088,12 @@ static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = {
{
VP8E_SET_ARNR_TYPE
,
set_param
},
{
VP8E_SET_TUNING
,
set_param
},
{
VP8E_SET_CQ_LEVEL
,
set_param
},
{
VP9E_SET_MAX_Q
,
set_param
},
{
VP9E_SET_MIN_Q
,
set_param
},
{
VP8E_SET_MAX_INTRA_BITRATE_PCT
,
set_param
},
{
VP9E_SET_LOSSLESS
,
set_param
},
{
VP9E_SET_FRAME_PARALLEL_DECODING
,
set_param
},
{
VP9_GET_REFERENCE
,
get_reference
},
{
VP9E_SET_WIDTH
,
vp9e_set_width
},
{
VP9E_SET_HEIGHT
,
vp9e_set_height
},
{
VP9E_SET_LAYER
,
vp9e_set_layer
},
{
VP9E_SET_SVC
,
vp9e_set_svc
},
{
VP9E_SET_SVC_PARAMETERS
,
vp9e_set_svc_parameters
},
{
-
1
,
NULL
},
};
...
...
vp9_spatial_scalable_encoder.c
View file @
a82001b1
...
...
@@ -23,24 +23,22 @@
#define VPX_CODEC_DISABLE_COMPAT 1
#include
"vpx/vpx_encoder.h"
#include
"vpx/vp8cx.h"
#include
"vpx/svc_context.h"
#define interface (vpx_codec_vp9_cx())
#define fourcc 0x30395056
#define IVF_FILE_HDR_SZ (32)
#define IVF_FRAME_HDR_SZ (12)
#define NUM_BUFFERS 8
char
*
input_filename
;
char
*
output_filename
;
unsigned
int
number_frames_to_code
=
60
*
60
;
unsigned
int
number_frames_to_skip
=
0
;
unsigned
int
number_spatial_layers
=
5
;
unsigned
int
key_period
=
100
;
unsigned
int
gop_size
=
100
;
typedef
enum
ENCODING_MODE
{
INTER_LAYER_PREDICTION_I
,
INTER_LAYER_PREDICTION_IP
,
USE_GOLDEN_FRAME
}
ENCODING_MODE
;
char
*
scaling_factor
;
char
*
quantizer
;
SVC_ENCODING_MODE
encoding_mode
=
INTER_LAYER_PREDICTION_IP
;
static
void
mem_put_le16
(
char
*
mem
,
unsigned
int
val
)
{
mem
[
0
]
=
val
;
...
...
@@ -57,7 +55,10 @@ static void mem_put_le32(char *mem, unsigned int val) {
static
void
usage
(
char
*
program_name
)
{
printf
(
"Usage: %s [-f frames] [-s skip_frames] [-w width] [-h height]
\n\t
"
"[-n rate_num] [-d rate_den] [-b bitrate] [-l layers] "
"[-n rate_num] [-d rate_den] [-b bitrate] [-l layers] [-g gop_size]
\n\t
"
"[-z dummy_frame (default 1)
\n\t
"
"[-q quantizer (lowest to highest)]
\n\t
"
"[-r 1/16th scale factor (lowest to highest layer)] "
"<input_filename> <output_filename>
\n
"
,
basename
(
program_name
));
exit
(
EXIT_FAILURE
);
...
...
@@ -83,78 +84,98 @@ static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
static
int
read_frame
(
FILE
*
f
,
vpx_image_t
*
img
)
{
size_t
nbytes
,
to_read
;
int
res
=
1
;
int
plane
;
for
(
plane
=
0
;
plane
<
3
;
plane
++
)
{
unsigned
char
*
ptr
;
int
w
=
(
plane
?
(
1
+
img
->
d_w
)
/
2
:
img
->
d_w
);
int
h
=
(
plane
?
(
1
+
img
->
d_h
)
/
2
:
img
->
d_h
);
int
r
;
to_read
=
img
->
w
*
img
->
h
*
3
/
2
;
nbytes
=
fread
(
img
->
planes
[
0
],
1
,
to_read
,
f
);
if
(
nbytes
!=
to_read
)
{
res
=
0
;
if
(
nbytes
>
0
)
printf
(
"Warning: Read partial frame. Check your width & height!
\n
"
);
switch
(
plane
)
{
case
1
:
ptr
=
img
->
planes
[
VPX_PLANE_U
];
break
;
case
2
:
ptr
=
img
->
planes
[
VPX_PLANE_V
];
break
;
default:
ptr
=
img
->
planes
[
plane
];
}
for
(
r
=
0
;
r
<
h
;
r
++
)
{
to_read
=
w
;
nbytes
=
fread
(
ptr
,
1
,
to_read
,
f
);
if
(
nbytes
!=
to_read
)
{
res
=
0
;
if
(
nbytes
>
0
)
printf
(
"Warning: Read partial frame. Check your width & height!
\n
"
);
break
;
}
ptr
+=
img
->
stride
[
plane
];
}
if
(
!
res
)
break
;
}
return
res
;
}
static
int
read_dummy_frame
(
vpx_image_t
*
img
)
{
size_t
to_read
;
to_read
=
img
->
w
*
img
->
h
*
3
/
2
;
memset
(
img
->
planes
[
0
],
129
,
to_read
);
static
int
create_dummy_frame
(
vpx_image_t
*
img
)
{
size_t
buf_size
;
buf_size
=
img
->
w
*
img
->
h
*
3
/
2
;
memset
(
img
->
planes
[
0
],
129
,
buf_size
);
return
1
;
}
static
void
write_ivf_file_header
(
FILE
*
outfile
,
const
vpx_codec_enc_cfg_t
*
cfg
,
int
frame_cnt
)
{
static
void
write_ivf_file_header
(
FILE
*
outfile
,
unsigned
int
width
,
unsigned
int
height
,
int
timebase_num
,
int
timebase_den
,
int
frame_cnt
)
{
char
header
[
32
];
if
(
cfg
->
g_pass
!=
VPX_RC_ONE_PASS
&&
cfg
->
g_pass
!=
VPX_RC_LAST_PASS
)
return
;
header
[
0
]
=
'D'
;
header
[
1
]
=
'K'
;
header
[
2
]
=
'I'
;
header
[
3
]
=
'F'
;
mem_put_le16
(
header
+
4
,
0
);
/* version */
mem_put_le16
(
header
+
6
,
32
);
/* headersize */
mem_put_le32
(
header
+
8
,
fourcc
);
/* headersize */
mem_put_le16
(
header
+
12
,
cfg
->
g_w
);
/* width */
mem_put_le16
(
header
+
14
,
cfg
->
g_h
);
/* height */
mem_put_le32
(
header
+
16
,
cfg
->
g_
timebase
.
den
);
/* rate */
mem_put_le32
(
header
+
20
,
cfg
->
g_
timebase
.
num
);
/* scale */
mem_put_le32
(
header
+
24
,
frame_cnt
);
/* length */
mem_put_le32
(
header
+
28
,
0
);
/* unused */
mem_put_le16
(
header
+
4
,
0
);
/* version */
mem_put_le16
(
header
+
6
,
32
);
/* headersize */
mem_put_le32
(
header
+
8
,
fourcc
);
/* headersize */
mem_put_le16
(
header
+
12
,
width
);
/* width */
mem_put_le16
(
header
+
14
,
height
);
/* height */
mem_put_le32
(
header
+
16
,
timebase
_
den
);
/* rate */
mem_put_le32
(
header
+
20
,
timebase
_
num
);
/* scale */
mem_put_le32
(
header
+
24
,
frame_cnt
);
/* length */
mem_put_le32
(
header
+
28
,
0
);
/* unused */
(
void
)
fwrite
(
header
,
1
,
32
,
outfile
);
}
static
void
write_ivf_frame_header
(
FILE
*
outfile
,
const
vpx_codec_cx_pkt_t
*
pkt
)
{
static
void
write_ivf_frame_header
(
FILE
*
outfile
,
vpx_codec_pts_t
pts
,
size_t
sz
)
{
char
header
[
12
];
vpx_codec_pts_t
pts
;
if
(
pkt
->
kind
!=
VPX_CODEC_CX_FRAME_PKT
)
return
;
pts
=
pkt
->
data
.
frame
.
pts
;
mem_put_le32
(
header
,
pkt
->
data
.
frame
.
sz
);
mem_put_le32
(
header
,
sz
);
mem_put_le32
(
header
+
4
,
pts
&
0xFFFFFFFF
);
mem_put_le32
(
header
+
8
,
pts
>>
32
);
(
void
)
fwrite
(
header
,
1
,
12
,
outfile
);
}
static
void
check_parameters
()
{
if
(
number_spatial_layers
>
5
)
die
(
"Cannot support more than 5 layers"
);
}
static
void
parse_command_line
(
int
argc
,
char
**
argv
,
vpx_codec_enc_cfg_t
*
cfg
)
{
static
void
parse_command_line
(
int
argc
,
char
**
argv
,
SvcContext
*
svc_ctx
,
vpx_codec_enc_cfg_t
*
enc_cfg
)
{
unsigned
int
width
=
1920
;
unsigned
int
height
=
1080
;
unsigned
int
timebase_num
=
1
;
unsigned
int
timebase_den
=
60
;
unsigned
int
bitrate
=
1000
;
unsigned
int
number_spatial_layers
=
5
;
int
use_dummy_frame
=
1
;
int
c
;
vpx_codec_err_t
res
;
int
r
=
0
;
int
q
=
0
;
opterr
=
0
;
while
((
c
=
getopt
(
argc
,
argv
,
"f:w:h:n:d:b:s:l:p:"
))
!=
-
1
)
switch
(
c
)
{
while
((
c
=
getopt
(
argc
,
argv
,
"f:w:h:n:d:b:s:l:g:r:q:z:"
))
!=
-
1
)
switch
(
c
)
{
case
'f'
:
number_frames_to_code
=
atoi
(
optarg
);
break
;
...
...
@@ -179,8 +200,17 @@ static void parse_command_line(int argc, char **argv,
case
'l'
:
number_spatial_layers
=
atoi
(
optarg
);
break
;
case
'p'
:
key_period
=
atoi
(
optarg
);
case
'g'
:
gop_size
=
atoi
(
optarg
);
break
;
case
'r'
:
scaling_factor
=
optarg
;
break
;
case
'q'
:
quantizer
=
optarg
;
break
;
case
'z'
:
use_dummy_frame
=
atoi
(
optarg
);
break
;
case
'?'
:
usage
(
argv
[
0
]);
...
...
@@ -191,14 +221,28 @@ static void parse_command_line(int argc, char **argv,
usage
(
argv
[
0
]);
}
if
((
r
!=
0
&&
q
!=
0
&&
r
!=
q
)
||
(
r
!=
number_spatial_layers
&&
r
!=
0
))
{
usage
(
argv
[
0
]);
}
input_filename
=
argv
[
optind
];
output_filename
=
argv
[
optind
+
1
];
if
(
width
<
16
||
width
%
2
||
height
<
16
||
height
%
2
)
die
(
"Invalid resolution: %d x %d"
,
width
,
height
);
// initialize SvcContext
svc_ctx
->
log_level
=
SVC_LOG_DEBUG
;
svc_ctx
->
spatial_layers
=
number_spatial_layers
;
svc_ctx
->
encoding_mode
=
encoding_mode
;
svc_ctx
->
gop_size
=
gop_size
;
svc_ctx
->
quantizer_values
=
quantizer
;
svc_ctx
->
scale_factors
=
scaling_factor
;
// when using a dummy frame, that frame is only encoded to be full size
svc_ctx
->
first_frame_full_size
=
use_dummy_frame
;
/* Populate encoder configuration */
res
=
vpx_codec_enc_config_default
(
interface
,
cfg
,
0
);
res
=
vpx_codec_enc_config_default
(
interface
,
enc_
cfg
,
0
);
if
(
res
)
{
die
(
"Failed to get config: %s
\n
"
,
vpx_codec_err_to_string
(
res
));
}
...
...
@@ -206,200 +250,52 @@ static void parse_command_line(int argc, char **argv,
"Codec %s
\n
frames: %d, skip: %d, layers: %d
\n
"
"width %d, height: %d,
\n
"
"num: %d, den: %d, bitrate: %d,
\n
"
"
key period
: %d
\n
"
,
"
gop size: %d, use_dummy_frame
: %d
\n
"
,