Commit 2eeadab1 authored by Soo-Chul Han's avatar Soo-Chul Han

add scalability experiment

configure:  --enable-experimental --enable-scalability

New applications:  scalable_encoder, scalable_decoder

scalable_encoder:
  * Encodes inputs as 2-layer (same size) stream
  * Encodes as obu file (OBU_NO_IVF must be enabled)
  * Base layer encoded in IPPPP where P's reference
    only the previous (in time) base layer
  * Enhancement layer encoded using its base layer as
    sole reference frame
  * Base layer encoded with fixed high QP
  * Enhancement layer encoded with fixed low QP

scalable_decoder:
  * Able to decode scalable stream generated by
    scalable_encoder
  * Able to decode any single-layer stream encoded
    by aomenc
  * Outputs base layer as out_lyr0.yuv, and enhancement
    layer (if they exist) as out_lyrN.yuv (N = 1, 2, 3, ..)
  * Able to decode N layers (more than 2)

Change-Id: I8555735db71e5b9b6f900ffdf978e0ad6f6bfc00
parent a8975df5
......@@ -330,6 +330,10 @@ if (CONFIG_AV1_DECODER AND ENABLE_EXAMPLES)
"${AOM_ROOT}/examples/simple_decoder.c"
$<TARGET_OBJECTS:aom_common_app_util>
$<TARGET_OBJECTS:aom_decoder_app_util>)
add_executable(scalable_decoder
"${AOM_ROOT}/examples/scalable_decoder.c"
$<TARGET_OBJECTS:aom_common_app_util>
$<TARGET_OBJECTS:aom_decoder_app_util>)
if (CONFIG_ANALYZER)
add_executable(analyzer
......@@ -368,7 +372,7 @@ if (CONFIG_AV1_DECODER AND ENABLE_EXAMPLES)
# Maintain a list of decoder example targets.
set(AOM_DECODER_EXAMPLE_TARGETS ${AOM_DECODER_EXAMPLE_TARGETS}
aomdec decode_to_md5 decode_with_drops simple_decoder)
aomdec decode_to_md5 decode_with_drops simple_decoder scalable_decoder)
# Add decoder examples to the app targets list.
set(AOM_APP_TARGETS ${AOM_APP_TARGETS} ${AOM_DECODER_EXAMPLE_TARGETS})
......@@ -393,6 +397,10 @@ if (CONFIG_AV1_ENCODER)
"${AOM_ROOT}/examples/simple_encoder.c"
$<TARGET_OBJECTS:aom_common_app_util>
$<TARGET_OBJECTS:aom_encoder_app_util>)
add_executable(scalable_encoder
"${AOM_ROOT}/examples/scalable_encoder.c"
$<TARGET_OBJECTS:aom_common_app_util>
$<TARGET_OBJECTS:aom_encoder_app_util>)
add_executable(twopass_encoder
"${AOM_ROOT}/examples/twopass_encoder.c"
$<TARGET_OBJECTS:aom_common_app_util>
......@@ -400,7 +408,7 @@ if (CONFIG_AV1_ENCODER)
# Maintain a list of encoder example targets.
set(AOM_ENCODER_EXAMPLE_TARGETS
aomenc lossless_encoder set_maps simple_encoder twopass_encoder)
aomenc lossless_encoder set_maps simple_encoder scalable_encoder twopass_encoder)
endif ()
if (ENABLE_TOOLS)
......
......@@ -496,6 +496,7 @@ typedef enum {
OBU_METADATA_TYPE_PRIVATE_DATA = 0,
OBU_METADATA_TYPE_HDR_CLL = 1,
OBU_METADATA_TYPE_HDR_MDCV = 2,
OBU_METADATA_TYPE_SCALABILITY = 3,
} OBU_METADATA_TYPE;
/*!@} - end defgroup codec*/
......
......@@ -86,6 +86,9 @@ typedef struct aom_codec_stream_info {
unsigned int w; /**< Width (or 0 for unknown/default) */
unsigned int h; /**< Height (or 0 for unknown/default) */
unsigned int is_kf; /**< Current frame is a keyframe */
#if CONFIG_SCALABILITY
unsigned int enhancement_layers_cnt; /**< Enhancement layers */
#endif
} aom_codec_stream_info_t;
/* REQUIRED FUNCTIONS
......
......@@ -213,6 +213,9 @@ typedef struct aom_image {
int bps; /**< bits per sample (for packed formats) */
int temporal_id; /**< Temporal layer Id of image */
int enhancement_id; /**< Spatial layer Id of image */
/*!\brief The following member may be set by the application to associate
* data with this image.
*/
......
......@@ -143,6 +143,10 @@ enum aome_enc_control_id {
*/
AOME_SET_SCALEMODE = 11,
/*!\brief Codec control function to set encoder enhancement layer id.
*/
AOME_SET_ENHANCEMENT_LAYER_ID = 12,
/*!\brief Codec control function to set encoder internal speed settings.
*
* Changes in this value influences, among others, the encoder's selection
......@@ -215,6 +219,10 @@ enum aome_enc_control_id {
*/
AOME_SET_MAX_INTRA_BITRATE_PCT,
/*!\brief Codec control function to set number of spatial layers.
*/
AOME_SET_NUMBER_SPATIAL_LAYERS,
/*!\brief Codec control function to set max data rate for Inter frames.
*
* This value controls additional clamping on the maximum size of an
......@@ -782,6 +790,9 @@ AOM_CTRL_USE_TYPE(AOME_SET_ACTIVEMAP, aom_active_map_t *)
AOM_CTRL_USE_TYPE(AOME_SET_SCALEMODE, aom_scaling_mode_t *)
#define AOM_CTRL_AOME_SET_SCALEMODE
AOM_CTRL_USE_TYPE(AOME_SET_ENHANCEMENT_LAYER_ID, int)
#define AOM_CTRL_AOME_SET_ENHANCEMENT_LAYER_ID
AOM_CTRL_USE_TYPE(AOME_SET_CPUUSED, int)
#define AOM_CTRL_AOME_SET_CPUUSED
AOM_CTRL_USE_TYPE(AOME_SET_DEVSF, int)
......@@ -831,6 +842,9 @@ AOM_CTRL_USE_TYPE(AOME_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
AOM_CTRL_USE_TYPE(AOME_SET_MAX_INTER_BITRATE_PCT, unsigned int)
#define AOM_CTRL_AOME_SET_MAX_INTER_BITRATE_PCT
AOM_CTRL_USE_TYPE(AOME_SET_NUMBER_SPATIAL_LAYERS, int)
#define AOME_CTRL_AOME_SET_NUMBER_SPATIAL_LAYERS
AOM_CTRL_USE_TYPE(AV1E_SET_GF_CBR_BOOST_PCT, unsigned int)
#define AOM_CTRL_AV1E_SET_GF_CBR_BOOST_PCT
......
......@@ -255,7 +255,11 @@ static int read_frame(struct AvxDecInputContext *input, uint8_t **buf,
#if CONFIG_OBU_NO_IVF
case FILE_TYPE_OBU:
return obu_read_temporal_unit(input->aom_input_ctx->file, buf,
#if CONFIG_SCALABILITY
bytes_in_buffer, buffer_size, 0);
#else
bytes_in_buffer, buffer_size);
#endif
#endif
default: return 1;
}
......
......@@ -1382,21 +1382,28 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
pkt.data.frame.partition_id = -1;
#if CONFIG_OBU
// move data PRE_OBU_SIZE_BYTES + 1 bytes and insert OBU_TD preceded by
// optional 4 byte size
uint32_t obu_size = 1;
if (ctx->pending_cx_data) {
const size_t index_sz = PRE_OBU_SIZE_BYTES + 1;
memmove(ctx->pending_cx_data + index_sz, ctx->pending_cx_data,
ctx->pending_cx_data_sz);
int write_temporal_delimiter = 1;
#if CONFIG_SCALABILITY
// only write OBU_TD if base layer
write_temporal_delimiter = !cpi->common.enhancement_layer_id;
#endif // CONFIG_SCALABILITY
if (write_temporal_delimiter) {
// move data PRE_OBU_SIZE_BYTES + 1 bytes and insert OBU_TD preceded by
// optional 4 byte size
uint32_t obu_size = 1;
if (ctx->pending_cx_data) {
const size_t index_sz = PRE_OBU_SIZE_BYTES + 1;
memmove(ctx->pending_cx_data + index_sz, ctx->pending_cx_data,
ctx->pending_cx_data_sz);
}
obu_size = write_obu_header(
OBU_TEMPORAL_DELIMITER, 0,
(uint8_t *)(ctx->pending_cx_data + PRE_OBU_SIZE_BYTES));
obu_size += write_temporal_delimiter_obu();
mem_put_le32(ctx->pending_cx_data, obu_size);
pkt.data.frame.sz += (obu_size + PRE_OBU_SIZE_BYTES);
}
obu_size = write_obu_header(
OBU_TEMPORAL_DELIMITER, 0,
(uint8_t *)(ctx->pending_cx_data + PRE_OBU_SIZE_BYTES));
obu_size += write_temporal_delimiter_obu();
mem_put_le32(ctx->pending_cx_data, obu_size);
pkt.data.frame.sz += (obu_size + PRE_OBU_SIZE_BYTES);
#endif
#endif // CONFIG_OBU
pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
......@@ -1562,6 +1569,32 @@ static aom_codec_err_t ctrl_set_scale_mode(aom_codec_alg_priv_t *ctx,
}
}
static aom_codec_err_t ctrl_set_enhancement_layer_id(aom_codec_alg_priv_t *ctx,
va_list args) {
#if CONFIG_SCALABILITY
const int enhancement_layer_id = va_arg(args, int);
ctx->cpi->common.enhancement_layer_id = enhancement_layer_id;
return AOM_CODEC_OK;
#else
(void)ctx;
(void)args;
return AOM_CODEC_UNSUP_FEATURE;
#endif
}
static aom_codec_err_t ctrl_set_number_spatial_layers(aom_codec_alg_priv_t *ctx,
va_list args) {
#if CONFIG_SCALABILITY
const int number_spatial_layers = va_arg(args, int);
ctx->cpi->common.enhancement_layers_cnt = number_spatial_layers - 1;
return AOM_CODEC_OK;
#else
(void)ctx;
(void)args;
return AOM_CODEC_UNSUP_FEATURE;
#endif
}
static aom_codec_err_t ctrl_set_tune_content(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
......@@ -1661,6 +1694,7 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ AOME_SET_ROI_MAP, ctrl_set_roi_map },
{ AOME_SET_ACTIVEMAP, ctrl_set_active_map },
{ AOME_SET_SCALEMODE, ctrl_set_scale_mode },
{ AOME_SET_ENHANCEMENT_LAYER_ID, ctrl_set_enhancement_layer_id },
{ AOME_SET_CPUUSED, ctrl_set_cpuused },
{ AOME_SET_DEVSF, ctrl_set_devsf },
{ AOME_SET_ENABLEAUTOALTREF, ctrl_set_enable_auto_alt_ref },
......@@ -1685,6 +1719,7 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ AOME_SET_TUNING, ctrl_set_tuning },
{ AOME_SET_CQ_LEVEL, ctrl_set_cq_level },
{ AOME_SET_MAX_INTRA_BITRATE_PCT, ctrl_set_rc_max_intra_bitrate_pct },
{ AOME_SET_NUMBER_SPATIAL_LAYERS, ctrl_set_number_spatial_layers },
{ AV1E_SET_MAX_INTER_BITRATE_PCT, ctrl_set_rc_max_inter_bitrate_pct },
{ AV1E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct },
{ AV1E_SET_LOSSLESS, ctrl_set_lossless },
......
......@@ -31,6 +31,10 @@
#include "av1/av1_iface_common.h"
#if CONFIG_OBU
#include "aom_ports/mem_ops.h"
#endif
// This limit is due to framebuffer numbers.
// TODO(hkuang): Remove this limit after implementing ondemand framebuffers.
#define FRAME_CACHE_SIZE 6 // Cache maximum 6 decoded frames.
......@@ -292,10 +296,33 @@ static aom_codec_err_t decoder_peek_si_internal(const uint8_t *data,
{
#if CONFIG_OBU
// Proper fix needed
si->is_kf = 1;
intra_only_flag = 1;
si->h = 1;
struct aom_read_bit_buffer rb = { data + PRE_OBU_SIZE_BYTES, data + data_sz,
0, NULL, NULL };
mem_get_le32(data);
aom_rb_read_literal(&rb, 8); // obu_header
av1_read_profile(&rb); // profile
aom_rb_read_literal(&rb, 4); // level
#if CONFIG_SCALABILITY
int i;
si->enhancement_layers_cnt = aom_rb_read_literal(&rb, 2);
for (i = 1; i <= (int)si->enhancement_layers_cnt; i++) {
aom_rb_read_literal(&rb, 4); // level for each enhancement layer
}
#endif // CONFIG_SCALABILITY
#if CONFIG_FRAME_SIZE
int num_bits_width = aom_rb_read_literal(&rb, 4) + 1;
int num_bits_height = aom_rb_read_literal(&rb, 4) + 1;
int max_frame_width = aom_rb_read_literal(&rb, num_bits_width) + 1;
int max_frame_height = aom_rb_read_literal(&rb, num_bits_height) + 1;
si->w = max_frame_width;
si->h = max_frame_height;
#endif // CONFIG_FRAME_SIZE
#else
int show_frame;
int error_resilient;
......@@ -925,6 +952,10 @@ static aom_image_t *decoder_get_frame(aom_codec_alg_priv_t *ctx,
ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
img = &ctx->img;
#if CONFIG_SCALABILITY
img->temporal_id = cm->temporal_layer_id;
img->enhancement_id = cm->enhancement_layer_id;
#endif
return img;
}
} else {
......
......@@ -591,6 +591,12 @@ typedef struct AV1Common {
DqType dq_type;
#endif // CONFIG_NEW_QUANT
#if CONFIG_SCALABILITY
int temporal_layer_id;
int enhancement_layer_id;
int enhancement_layers_cnt;
#endif
#if TXCOEFF_TIMER
int64_t cum_txcoeff_timer;
int64_t txcoeff_timer;
......
......@@ -21,8 +21,28 @@
#include "av1/decoder/decoder.h"
#include "av1/decoder/decodeframe.h"
#if CONFIG_SCALABILITY
typedef enum {
SCALABILITY_L1T2 = 0,
SCALABILITY_L1T3 = 1,
SCALABILITY_L2T1 = 2,
SCALABILITY_L2T2 = 3,
SCALABILITY_L2T3 = 4,
SCALABILITY_S2T1 = 5,
SCALABILITY_S2T2 = 6,
SCALABILITY_S2T3 = 7,
SCALABILITY_L2T2h = 8,
SCALABILITY_L2T3h = 9,
SCALABILITY_S2T1h = 10,
SCALABILITY_S2T2h = 11,
SCALABILITY_S2T3h = 12,
SCALABILITY_SS = 13
} SCALABILITY_STRUCTURES;
#endif
static OBU_TYPE read_obu_header(struct aom_read_bit_buffer *rb,
size_t *header_size) {
size_t *header_size,
uint8_t *obu_extension_header) {
*header_size = 1;
// first bit is obu_forbidden_bit (0) according to R19
......@@ -31,12 +51,17 @@ static OBU_TYPE read_obu_header(struct aom_read_bit_buffer *rb,
const OBU_TYPE obu_type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
aom_rb_read_literal(rb, 2); // reserved
const int obu_extension_flag = aom_rb_read_bit(rb);
if (obu_extension_header) *obu_extension_header = 0;
if (obu_extension_flag) {
*header_size += 1;
#if !CONFIG_SCALABILITY
aom_rb_read_literal(rb, 3); // temporal_id
aom_rb_read_literal(rb, 2);
aom_rb_read_literal(rb, 2);
aom_rb_read_literal(rb, 1); // reserved
#else
*obu_extension_header = (uint8_t)aom_rb_read_literal(rb, 8);
#endif
}
return obu_type;
......@@ -48,10 +73,20 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
struct aom_read_bit_buffer *rb) {
AV1_COMMON *const cm = &pbi->common;
uint32_t saved_bit_offset = rb->bit_offset;
#if CONFIG_SCALABILITY
int i;
#endif
cm->profile = av1_read_profile(rb);
aom_rb_read_literal(rb, 4); // level
#if CONFIG_SCALABILITY
pbi->common.enhancement_layers_cnt = aom_rb_read_literal(rb, 2);
for (i = 1; i <= pbi->common.enhancement_layers_cnt; i++) {
aom_rb_read_literal(rb, 4); // level for each enhancement layer
}
#endif
read_sequence_header(&cm->seq_params, rb);
av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth);
......@@ -137,6 +172,51 @@ static void read_metadata_hdr_mdcv(const uint8_t *data) {
mem_get_le16(data);
}
#if CONFIG_SCALABILITY
static void scalability_structure(struct aom_read_bit_buffer *rb) {
int enhancement_layers_cnt = aom_rb_read_literal(rb, 2);
int enhancement_layer_dimensions_present_flag = aom_rb_read_literal(rb, 1);
int enhancement_layer_description_pressent_flag = aom_rb_read_literal(rb, 1);
int temporal_group_description_flag = aom_rb_read_literal(rb, 1);
aom_rb_read_literal(rb, 3); // reserved
if (enhancement_layer_dimensions_present_flag) {
int i;
for (i = 0; i < enhancement_layers_cnt + 1; i++) {
aom_rb_read_literal(rb, 16);
aom_rb_read_literal(rb, 16);
}
}
if (enhancement_layer_description_pressent_flag) {
int i;
for (i = 0; i < enhancement_layers_cnt + 1; i++) {
aom_rb_read_literal(rb, 8);
}
}
if (temporal_group_description_flag) {
int i, j, temporal_group_size;
temporal_group_size = aom_rb_read_literal(rb, 8);
for (i = 0; i < temporal_group_size; i++) {
aom_rb_read_literal(rb, 3);
aom_rb_read_literal(rb, 1);
int temporal_group_ref_cnt = aom_rb_read_literal(rb, 2);
aom_rb_read_literal(rb, 2);
for (j = 0; j < temporal_group_ref_cnt; j++) {
aom_rb_read_literal(rb, 8);
}
}
}
}
static void read_metadata_scalability(const uint8_t *data, size_t sz) {
struct aom_read_bit_buffer rb = { data, data + sz, 0, NULL, NULL };
int scalability_mode_idc = aom_rb_read_literal(&rb, 8);
if (scalability_mode_idc == SCALABILITY_SS) {
scalability_structure(&rb);
}
}
#endif
static size_t read_metadata(const uint8_t *data, size_t sz) {
assert(sz >= 2);
const OBU_METADATA_TYPE metadata_type = (OBU_METADATA_TYPE)mem_get_le16(data);
......@@ -147,6 +227,10 @@ static size_t read_metadata(const uint8_t *data, size_t sz) {
read_metadata_hdr_cll(data + 2);
} else if (metadata_type == OBU_METADATA_TYPE_HDR_MDCV) {
read_metadata_hdr_mdcv(data + 2);
#if CONFIG_SCALABILITY
} else if (metadata_type == OBU_METADATA_TYPE_SCALABILITY) {
read_metadata_scalability(data + 2, sz - 2);
#endif
}
return sz;
......@@ -160,6 +244,9 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
int is_first_tg_obu_received = 1;
int frame_header_received = 0;
int frame_header_size = 0;
#if CONFIG_SCALABILITY
uint8_t obu_extension_header = 0;
#endif
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
......@@ -175,12 +262,25 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
// + payload size)
// The obu size is only needed for tile group OBUs
const size_t obu_size = mem_get_le32(data);
const OBU_TYPE obu_type = read_obu_header(&rb, &obu_header_size);
#if !CONFIG_SCALABILITY
const OBU_TYPE obu_type = read_obu_header(&rb, &obu_header_size, NULL);
#else
const OBU_TYPE obu_type =
read_obu_header(&rb, &obu_header_size, &obu_extension_header);
#endif
data += (PRE_OBU_SIZE_BYTES + obu_header_size);
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return;
}
#if CONFIG_SCALABILITY
cm->temporal_layer_id = (obu_extension_header & 0xE0) >> 5;
cm->enhancement_layer_id = (obu_extension_header & 0x18) >> 3;
#endif
switch (obu_type) {
case OBU_TEMPORAL_DELIMITER:
obu_payload_size = read_temporal_delimiter_obu();
......
......@@ -4338,14 +4338,29 @@ uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
return size;
}
static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) {
static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst
#if CONFIG_SCALABILITY
,
uint8_t enhancement_layers_cnt) {
#else
) {
#endif
AV1_COMMON *const cm = &cpi->common;
struct aom_write_bit_buffer wb = { dst, 0 };
uint32_t size = 0;
#if CONFIG_SCALABILITY
int i;
#endif
write_profile(cm->profile, &wb);
aom_wb_write_literal(&wb, 0, 4);
#if CONFIG_SCALABILITY
aom_wb_write_literal(&wb, enhancement_layers_cnt, 2);
for (i = 1; i <= enhancement_layers_cnt; i++) {
aom_wb_write_literal(&wb, 0, 4);
}
#endif
write_sequence_header(cpi, &wb);
......@@ -4410,7 +4425,8 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
#if CONFIG_EXT_TILE
struct aom_write_bit_buffer *saved_wb,
#endif
int insert_frame_header_obu_flag) {
int insert_frame_header_obu_flag,
uint8_t obu_extension_header) {
AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
aom_writer mode_bc;
......@@ -4577,8 +4593,8 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
data = dst + total_size;
// A new tile group begins at this tile. Write the obu header and
// tile group header
curr_tg_data_size =
write_obu_header(OBU_TILE_GROUP, 0, data + PRE_OBU_SIZE_BYTES);
curr_tg_data_size = write_obu_header(
OBU_TILE_GROUP, obu_extension_header, data + PRE_OBU_SIZE_BYTES);
if (n_log2_tiles)
curr_tg_data_size += write_tile_group_header(
data + curr_tg_data_size + PRE_OBU_SIZE_BYTES, tile_idx,
......@@ -4656,13 +4672,20 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
uint32_t data_size;
unsigned int max_tile_size;
unsigned int max_tile_col_size;
AV1_COMMON *const cm = &cpi->common;
#if CONFIG_OBU
AV1_COMMON *const cm = &cpi->common;
uint32_t obu_size;
uint8_t *frame_header_location;
uint32_t frame_header_size;
#endif
(void)cm;
#if CONFIG_SCALABILITY
uint8_t enhancement_layers_cnt = cm->enhancement_layers_cnt;
uint8_t obu_extension_header =
cm->temporal_layer_id << 5 | cm->enhancement_layer_id << 3 | 0;
#else
uint8_t obu_extension_header = 0;
#endif // CONFIG_SCALABILITY
#endif // CONFIG_OBU
#if CONFIG_BITSTREAM_DEBUG
bitstream_queue_reset_write();
#endif
......@@ -4674,8 +4697,13 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
if (cm->frame_type == KEY_FRAME) {
obu_size =
write_obu_header(OBU_SEQUENCE_HEADER, 0, data + PRE_OBU_SIZE_BYTES);
obu_size +=
write_sequence_header_obu(cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
obu_size += write_sequence_header_obu(
#if CONFIG_SCALABILITY
cpi, data + PRE_OBU_SIZE_BYTES + obu_size, enhancement_layers_cnt);
#else
cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
#endif // CONFIG_SCALABILITY
mem_put_le32(data, obu_size);
data += obu_size + PRE_OBU_SIZE_BYTES;
}
......@@ -4686,7 +4714,8 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
// write frame header obu, preceded by 4-byte size
frame_header_location = data + PRE_OBU_SIZE_BYTES;
obu_size = write_obu_header(OBU_FRAME_HEADER, 0, frame_header_location);
obu_size = write_obu_header(OBU_FRAME_HEADER, obu_extension_header,
frame_header_location);
frame_header_size =
write_frame_header_obu(cpi,
#if CONFIG_EXT_TILE
......@@ -4702,17 +4731,17 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
} else {
// Each tile group obu will be preceded by 4-byte size of the tile group
// obu
data_size =
write_tiles_in_tg_obus(cpi, data, &max_tile_size, &max_tile_col_size,
frame_header_location - PRE_OBU_SIZE_BYTES,
obu_size + PRE_OBU_SIZE_BYTES,
data_size = write_tiles_in_tg_obus(
cpi, data, &max_tile_size, &max_tile_col_size,
frame_header_location - PRE_OBU_SIZE_BYTES,
obu_size + PRE_OBU_SIZE_BYTES,
#if CONFIG_EXT_TILE
&saved_wb,
&saved_wb,
#endif
1 /* cm->error_resilient_mode */);
1 /* cm->error_resilient_mode */, obu_extension_header);
}
#endif
#endif // CONFIG_OBU
#if CONFIG_EXT_TILE && !CONFIG_OBU
uint32_t uncompressed_hdr_size;
......
......@@ -170,6 +170,7 @@ set(CONFIG_RD_DEBUG 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_RECT_TX_EXT 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_RECT_TX_EXT_INTRA 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_REFERENCE_BUFFER 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SCALABILITY 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SEGMENT_GLOBALMV 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SEGMENT_PRED_LAST 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_SHORT_FILTER 1 CACHE NUMBER "AV1 experiment flag.")
......
......@@ -20,6 +20,15 @@ macro (fix_experiment_configs)
endif ()
endif ()
if (CONFIG_SCALABILITY)
if (NOT CONFIG_OBU)
change_config_and_warn(CONFIG_OBU 1 CONFIG_SCALABILITY)
endif ()
if (NOT CONFIG_OBU_NO_IVF)
change_config_and_warn(CONFIG_OBU_NO_IVF 1 CONFIG_SCALABILITY)
endif ()
endif ()
if (CONFIG_ANALYZER)
if (NOT CONFIG_INSPECTION)
change_config_and_warn(CONFIG_INSPECTION 1 CONFIG_ANALYZER)
......
......@@ -79,6 +79,7 @@ if (CONFIG_AV1_ENCODER)
"${AOM_ROOT}/examples/lossless_encoder.c"
"${AOM_ROOT}/examples/set_maps.c"
"${AOM_ROOT}/examples/simple_encoder.c"
"${AOM_ROOT}/examples/scalable_encoder.c"
"${AOM_ROOT}/examples/twopass_encoder.c")
set(AOM_DOXYGEN_EXAMPLE_DESCRIPTIONS
......@@ -87,6 +88,7 @@ if (CONFIG_AV1_ENCODER)
"Simplified lossless encoder."
"Set active and ROI maps."
"Simplified encoder loop."
"Scalable encoder loop."
"Two-pass encoder loop.")
set(AOM_DOXYGEN_SECTIONS ${AOM_DOXYGEN_SECTIONS} "av1_encoder encoder")
......
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
// Scalable Decoder
// ==============
//
// This is an example of a scalable decoder loop. It takes a 2-spatial-layer
// input file
// containing the compressed data (in OBU format), passes it through the
// decoder, and writes the decompressed frames to disk. The base layer and
// enhancement layers are stored as separate files, lyr0.yuv and lyr1.yuv,
// respectively.
//
// Standard Includes
// -----------------
// For decoders, you only have to include `aom_decoder.h` and then any
// header files for the specific codecs you use. In this case, we're using
// aom.
//
// Initializing The Codec
// ----------------------
// The libaom decoder is initialized by the call to aom_codec_dec_init().
// Determining the codec interface to use is handled by AvxVideoReader and the
// functions prefixed with aom_video_reader_. Discussion of those functions is
// beyond the scope of this example, but the main gist is to open the input file
// and parse just enough of it to determine if it's a AVx file and which AVx
// codec is contained within the file.
// Note the NULL pointer passed to aom_codec_dec_init(). We do that in this
// example because we want the algorithm to determine the stream configuration
// (width/height) and allocate memory automatically.
//
// Decoding A Frame
// ----------------
// Once the frame has been read into memory, it is decoded using the
// `aom_codec_decode` function. The call takes a pointer to the data
// (`frame`) and the length of the data (`frame_size`). No application data
// is associated with the frame in this example, so the `user_priv`
// parameter is NULL. The `deadline` parameter is left at zero for this
// example. This parameter is generally only used when doing adaptive post
// processing.
//
// Codecs may produce a variable number of output frames for every call to
// `aom_codec_decode`. These frames are retrieved by the
// `aom_codec_get_frame` iterator function. The iterator variable `iter` is
// initialized to NULL each time `aom_codec_decode` is called.
// `aom_codec_get_frame` is called in a loop, returning a pointer to a
// decoded image or NULL to indicate the end of list.
//
// Processing The Decoded Data
// ---------------------------
// In this example, we simply write the encoded data to disk. It is
// important to honor the image's `stride` values.
//
// Cleanup
// -------
// The `aom_codec_destroy` call frees any memory allocated by the codec.
//
// Error Handling
// --------------
// This example does not special case any error return codes. If there was
// an error, a descriptive message is printed and the program exits. With
// few exceptions, aom_codec functions return an enumerated error status,
// with the value `0` indicating success.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aom/aom_decoder.h"
#include "../tools_common.h"
#include "../video_reader.h"
#include "./aom_config.h"
#if CONFIG_SCALABILITY
#include "./obudec.h"
#endif
static const char *exec_name;
#define MAX_LAYERS 5
struct AvxDecInputContext {
struct AvxInputContext *aom_input_ctx;
struct WebmInputContext *webm_ctx;
};
void usage_exit(void) {
fprintf(stderr, "Usage: %s <infile>\n", exec_name);
exit(EXIT_FAILURE);
}
#if !CONFIG_SCALABILITY || !CONFIG_OBU
int main() {
warn("scalable_decoder needs CONFIG_SCALABILITY and CONFIG_OBU");
return 0;
#else
int main(int argc, char **argv) {
int frame_cnt = 0;
FILE *outfile[MAX_LAYERS];
char filename[80];
aom_codec_ctx_t codec;
const AvxInterface *decoder = NULL;
FILE *inputfile = NULL;
uint8_t *buf = NULL;
size_t bytes_in_buffer = 0;
size_t buffer_size = 0;
int next_layer_id = 0;
struct AvxDecInputContext input = { NULL, NULL };
struct AvxInputContext aom_input_ctx;
input.aom_input_ctx = &aom_input_ctx;
aom_codec_stream_info_t si;
uint8_t tmpbuf[32];
unsigned int i;
exec_name = argv[0];
if (argc != 2) die("Invalid number of arguments.");