Adds config opt for highbitdepth + misc. vpx
Adds config parameter vp9_highbitdepth, to support highbitdepth profiles. Also includes most vpx level high bit-depth functions. However encode/decode in the highbitdepth profiles will not work until the rest of the code is in place. Change-Id: I34c53b253c38873611057a6cbc89a1361b8985a6
This commit is contained in:
Родитель
72037944df
Коммит
5acfafb18e
|
@ -334,6 +334,7 @@ CONFIG_LIST="
|
|||
multi_res_encoding
|
||||
temporal_denoising
|
||||
coefficient_range_checking
|
||||
vp9_highbitdepth
|
||||
experimental
|
||||
size_limit
|
||||
${EXPERIMENT_LIST}
|
||||
|
@ -392,6 +393,7 @@ CMDLINE_SELECT="
|
|||
multi_res_encoding
|
||||
temporal_denoising
|
||||
coefficient_range_checking
|
||||
vp9_highbitdepth
|
||||
experimental
|
||||
"
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ class MD5 {
|
|||
// plane, we never want to round down and thus skip a pixel so if
|
||||
// we are shifting by 1 (chroma_shift) we add 1 before doing the shift.
|
||||
// This works only for chroma_shift of 0 and 1.
|
||||
const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
|
||||
const int bytes_per_sample =
|
||||
(img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
|
||||
const int h = plane ? (img->d_h + img->y_chroma_shift) >>
|
||||
img->y_chroma_shift : img->d_h;
|
||||
const int w = (plane ? (img->d_w + img->x_chroma_shift) >>
|
||||
|
|
|
@ -57,7 +57,7 @@ static void write_image_file(const vpx_image_t *img, FILE *file) {
|
|||
for (plane = 0; plane < 3; ++plane) {
|
||||
const unsigned char *buf = img->planes[plane];
|
||||
const int stride = img->stride[plane];
|
||||
const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
|
||||
const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
|
||||
const int h = (plane ? (img->d_h + img->y_chroma_shift) >>
|
||||
img->y_chroma_shift : img->d_h);
|
||||
const int w = (plane ? (img->d_w + img->x_chroma_shift) >>
|
||||
|
|
|
@ -83,7 +83,7 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
|
|||
struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
|
||||
int plane = 0;
|
||||
int shortread = 0;
|
||||
const int bytespp = (yuv_frame->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
|
||||
const int bytespp = (yuv_frame->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
|
||||
|
||||
for (plane = 0; plane < 3; ++plane) {
|
||||
uint8_t *ptr;
|
||||
|
@ -241,7 +241,8 @@ int vpx_img_read(vpx_image_t *img, FILE *file) {
|
|||
for (plane = 0; plane < 3; ++plane) {
|
||||
unsigned char *buf = img->planes[plane];
|
||||
const int stride = img->stride[plane];
|
||||
const int w = vpx_img_plane_width(img, plane);
|
||||
const int w = vpx_img_plane_width(img, plane) *
|
||||
((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
|
||||
const int h = vpx_img_plane_height(img, plane);
|
||||
int y;
|
||||
|
||||
|
|
|
@ -1244,6 +1244,9 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
|
|||
|
||||
320, /* g_width */
|
||||
240, /* g_height */
|
||||
VPX_BITS_8, /* g_bit_depth */
|
||||
8, /* g_input_bit_depth */
|
||||
|
||||
{1, 30}, /* g_timebase */
|
||||
|
||||
0, /* g_error_resilient */
|
||||
|
|
|
@ -177,7 +177,11 @@ int vp9_alloc_ref_frame_buffers(VP9_COMMON *cm, int width, int height) {
|
|||
for (i = 0; i < FRAME_BUFFERS; ++i) {
|
||||
cm->frame_bufs[i].ref_count = 0;
|
||||
if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height,
|
||||
ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0)
|
||||
ss_x, ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -185,6 +189,9 @@ int vp9_alloc_ref_frame_buffers(VP9_COMMON *cm, int width, int height) {
|
|||
|
||||
#if CONFIG_INTERNAL_STATS || CONFIG_VP9_POSTPROC
|
||||
if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS) < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,11 @@ static INLINE int get_unsigned_bits(unsigned int num_values) {
|
|||
return num_values > 0 ? get_msb(num_values) + 1 : 0;
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
#define CONVERT_TO_SHORTPTR(x) ((uint16_t*)(((uintptr_t)x) << 1))
|
||||
#define CONVERT_TO_BYTEPTR(x) ((uint8_t*)(((uintptr_t)x) >> 1 ))
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
#define CHECK_MEM_ERROR(cm, lval, expr) do { \
|
||||
lval = (expr); \
|
||||
|
|
|
@ -40,12 +40,6 @@ typedef enum BITSTREAM_PROFILE {
|
|||
MAX_PROFILES
|
||||
} BITSTREAM_PROFILE;
|
||||
|
||||
typedef enum BIT_DEPTH {
|
||||
BITS_8,
|
||||
BITS_10,
|
||||
BITS_12
|
||||
} BIT_DEPTH;
|
||||
|
||||
typedef enum BLOCK_SIZE {
|
||||
BLOCK_4X4,
|
||||
BLOCK_4X8,
|
||||
|
|
|
@ -84,6 +84,10 @@ typedef struct VP9Common {
|
|||
int subsampling_x;
|
||||
int subsampling_y;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth; // Marks if we need to use 16bit frame buffers.
|
||||
#endif
|
||||
|
||||
YV12_BUFFER_CONFIG *frame_to_show;
|
||||
|
||||
RefCntBuffer frame_bufs[FRAME_BUFFERS];
|
||||
|
@ -179,8 +183,8 @@ typedef struct VP9Common {
|
|||
unsigned int current_video_frame;
|
||||
BITSTREAM_PROFILE profile;
|
||||
|
||||
// BITS_8 in versions 0 and 1, BITS_10 or BITS_12 in version 2
|
||||
BIT_DEPTH bit_depth;
|
||||
// VPX_BITS_8 in profile 0 or 1, VPX_BITS_10 or VPX_BITS_12 in profile 2 or 3.
|
||||
vpx_bit_depth_t bit_depth;
|
||||
|
||||
#if CONFIG_VP9_POSTPROC
|
||||
struct postproc_state postproc_state;
|
||||
|
|
|
@ -653,7 +653,11 @@ static void setup_frame_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
|
|||
|
||||
if (vp9_realloc_frame_buffer(
|
||||
get_frame_new_buffer(cm), cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_DEC_BORDER_IN_PIXELS,
|
||||
&cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb,
|
||||
cm->cb_priv)) {
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
|
@ -700,7 +704,11 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm,
|
|||
|
||||
if (vp9_realloc_frame_buffer(
|
||||
get_frame_new_buffer(cm), cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_DEC_BORDER_IN_PIXELS,
|
||||
&cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb,
|
||||
cm->cb_priv)) {
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
|
@ -1100,7 +1108,7 @@ BITSTREAM_PROFILE vp9_read_profile(struct vp9_read_bit_buffer *rb) {
|
|||
static void read_bitdepth_colorspace_sampling(
|
||||
VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
|
||||
if (cm->profile >= PROFILE_2)
|
||||
cm->bit_depth = vp9_rb_read_bit(rb) ? BITS_12 : BITS_10;
|
||||
cm->bit_depth = vp9_rb_read_bit(rb) ? VPX_BITS_12 : VPX_BITS_10;
|
||||
cm->color_space = (COLOR_SPACE)vp9_rb_read_literal(rb, 3);
|
||||
if (cm->color_space != SRGB) {
|
||||
vp9_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range
|
||||
|
@ -1144,6 +1152,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
|
|||
"Invalid frame marker");
|
||||
|
||||
cm->profile = vp9_read_profile(rb);
|
||||
|
||||
if (cm->profile >= MAX_PROFILES)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
|
||||
"Unsupported bitstream profile");
|
||||
|
@ -1402,7 +1411,7 @@ void vp9_decode_frame(VP9Decoder *pbi,
|
|||
|
||||
if (!first_partition_size) {
|
||||
// showing a frame directly
|
||||
*p_data_end = data + 1;
|
||||
*p_data_end = data + (cm->profile <= PROFILE_2 ? 1 : 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ VP9Decoder *vp9_decoder_create() {
|
|||
|
||||
cm->current_video_frame = 0;
|
||||
pbi->ready_for_new_data = 1;
|
||||
cm->bit_depth = VPX_BITS_8;
|
||||
|
||||
// vp9_init_dequantizer() is first called here. Add check in
|
||||
// frame_init_dequantizer() to avoid unnecessary calling of
|
||||
|
|
|
@ -1046,8 +1046,8 @@ static void write_profile(BITSTREAM_PROFILE profile,
|
|||
static void write_bitdepth_colorspace_sampling(
|
||||
VP9_COMMON *const cm, struct vp9_write_bit_buffer *wb) {
|
||||
if (cm->profile >= PROFILE_2) {
|
||||
assert(cm->bit_depth > BITS_8);
|
||||
vp9_wb_write_bit(wb, cm->bit_depth - BITS_10);
|
||||
assert(cm->bit_depth > VPX_BITS_8);
|
||||
vp9_wb_write_bit(wb, cm->bit_depth == VPX_BITS_10 ? 0 : 1);
|
||||
}
|
||||
vp9_wb_write_literal(wb, cm->color_space, 3);
|
||||
if (cm->color_space != SRGB) {
|
||||
|
|
|
@ -388,13 +388,21 @@ void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse,
|
|||
}
|
||||
|
||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
int ssx, int ssy, int border) {
|
||||
int ssx, int ssy,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border) {
|
||||
int i, fail;
|
||||
assert(denoiser != NULL);
|
||||
|
||||
for (i = 0; i < MAX_REF_FRAMES; ++i) {
|
||||
fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
|
||||
ssx, ssy, border);
|
||||
ssx, ssy,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif
|
||||
border);
|
||||
if (fail) {
|
||||
vp9_denoiser_free(denoiser);
|
||||
return 1;
|
||||
|
@ -405,7 +413,11 @@ int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
|||
}
|
||||
|
||||
fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
|
||||
ssx, ssy, border);
|
||||
ssx, ssy,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif
|
||||
border);
|
||||
if (fail) {
|
||||
vp9_denoiser_free(denoiser);
|
||||
return 1;
|
||||
|
|
|
@ -47,7 +47,11 @@ void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi,
|
|||
PICK_MODE_CONTEXT *ctx);
|
||||
|
||||
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
|
||||
int ssx, int ssy, int border);
|
||||
int ssx, int ssy,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border);
|
||||
|
||||
void vp9_denoiser_free(VP9_DENOISER *denoiser);
|
||||
|
||||
|
|
|
@ -443,6 +443,9 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
|
|||
|
||||
cpi->lookahead = vp9_lookahead_init(oxcf->width, oxcf->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
oxcf->lag_in_frames);
|
||||
if (!cpi->lookahead)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
|
@ -451,6 +454,9 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
|
||||
oxcf->width, oxcf->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate altref buffer");
|
||||
|
@ -468,6 +474,9 @@ static void alloc_util_frame_buffers(VP9_COMP *cpi) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate last frame buffer");
|
||||
|
@ -475,6 +484,9 @@ static void alloc_util_frame_buffers(VP9_COMP *cpi) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->scaled_source,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate scaled source buffer");
|
||||
|
@ -482,6 +494,9 @@ static void alloc_util_frame_buffers(VP9_COMP *cpi) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate scaled last source buffer");
|
||||
|
@ -514,6 +529,9 @@ static void update_frame_size(VP9_COMP *cpi) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to reallocate alt_ref_buffer");
|
||||
|
@ -600,9 +618,9 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
|
|||
cm->bit_depth = oxcf->bit_depth;
|
||||
|
||||
if (cm->profile <= PROFILE_1)
|
||||
assert(cm->bit_depth == BITS_8);
|
||||
assert(cm->bit_depth == VPX_BITS_8);
|
||||
else
|
||||
assert(cm->bit_depth > BITS_8);
|
||||
assert(cm->bit_depth > VPX_BITS_8);
|
||||
|
||||
cpi->oxcf = *oxcf;
|
||||
|
||||
|
@ -677,6 +695,9 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
|
|||
if (cpi->oxcf.noise_sensitivity > 0) {
|
||||
vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS);
|
||||
}
|
||||
#endif
|
||||
|
@ -1604,6 +1625,9 @@ void vp9_scale_references(VP9_COMP *cpi) {
|
|||
vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
||||
scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
|
||||
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
|
||||
|
@ -2699,6 +2723,9 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
|||
vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
|
||||
|
||||
alloc_util_frame_buffers(cpi);
|
||||
|
|
|
@ -114,9 +114,10 @@ typedef enum {
|
|||
|
||||
typedef struct VP9EncoderConfig {
|
||||
BITSTREAM_PROFILE profile;
|
||||
BIT_DEPTH bit_depth;
|
||||
vpx_bit_depth_t bit_depth; // Codec bit-depth.
|
||||
int width; // width of data passed to the compressor
|
||||
int height; // height of data passed to the compressor
|
||||
unsigned int input_bit_depth; // Input bit depth.
|
||||
double init_framerate; // set to passed in framerate
|
||||
int64_t target_bandwidth; // bandwidth to be used in kilobits per second
|
||||
|
||||
|
|
|
@ -50,6 +50,9 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
|
|||
unsigned int height,
|
||||
unsigned int subsampling_x,
|
||||
unsigned int subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
unsigned int depth) {
|
||||
struct lookahead_ctx *ctx = NULL;
|
||||
|
||||
|
@ -70,6 +73,9 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
|
|||
for (i = 0; i < depth; i++)
|
||||
if (vp9_alloc_frame_buffer(&ctx->buf[i].img,
|
||||
width, height, subsampling_x, subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS))
|
||||
goto bail;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,9 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
|
|||
unsigned int height,
|
||||
unsigned int subsampling_x,
|
||||
unsigned int subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
unsigned int depth);
|
||||
|
||||
|
||||
|
|
|
@ -465,6 +465,9 @@ void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
|
|||
if (vp9_realloc_frame_buffer(&cpi->svc.scaled_frames[frame_used],
|
||||
cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL,
|
||||
NULL))
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
|
|
|
@ -37,7 +37,7 @@ struct vp9_extracfg {
|
|||
unsigned int frame_parallel_decoding_mode;
|
||||
AQ_MODE aq_mode;
|
||||
unsigned int frame_periodic_boost;
|
||||
BIT_DEPTH bit_depth;
|
||||
vpx_bit_depth_t bit_depth;
|
||||
vp9e_tune_content content;
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,7 @@ static struct vp9_extracfg default_extra_cfg = {
|
|||
0, // frame_parallel_decoding_mode
|
||||
NO_AQ, // aq_mode
|
||||
0, // frame_periodic_delta_q
|
||||
BITS_8, // Bit depth
|
||||
VPX_BITS_8, // Bit depth
|
||||
VP9E_CONTENT_DEFAULT // content
|
||||
};
|
||||
|
||||
|
@ -208,6 +208,8 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||
RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
|
||||
RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
|
||||
RANGE_CHECK(extra_cfg, cq_level, 0, 63);
|
||||
RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
|
||||
RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
|
||||
RANGE_CHECK(extra_cfg, content,
|
||||
VP9E_CONTENT_DEFAULT, VP9E_CONTENT_INVALID - 1);
|
||||
|
||||
|
@ -266,12 +268,16 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cfg->g_profile > (unsigned int)PROFILE_1)
|
||||
ERROR("Profile > 1 not supported in this build configuration");
|
||||
#endif
|
||||
if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
|
||||
extra_cfg->bit_depth > BITS_8)
|
||||
ERROR("High bit-depth not supported in profile < 2");
|
||||
extra_cfg->bit_depth > VPX_BITS_8)
|
||||
ERROR("Codec high bit-depth not supported in profile < 2");
|
||||
if (cfg->g_profile > (unsigned int)PROFILE_1 &&
|
||||
extra_cfg->bit_depth == BITS_8)
|
||||
ERROR("Bit-depth 8 not supported in profile > 1");
|
||||
extra_cfg->bit_depth == VPX_BITS_8)
|
||||
ERROR("Codec bit-depth 8 not supported in profile > 1");
|
||||
|
||||
return VPX_CODEC_OK;
|
||||
}
|
||||
|
@ -303,6 +309,9 @@ static int get_image_bps(const vpx_image_t *img) {
|
|||
case VPX_IMG_FMT_I420: return 12;
|
||||
case VPX_IMG_FMT_I422: return 16;
|
||||
case VPX_IMG_FMT_I444: return 24;
|
||||
case VPX_IMG_FMT_I42016: return 24;
|
||||
case VPX_IMG_FMT_I42216: return 32;
|
||||
case VPX_IMG_FMT_I44416: return 48;
|
||||
default: assert(0 && "Invalid image format"); break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -317,6 +326,7 @@ static vpx_codec_err_t set_encoder_config(
|
|||
oxcf->width = cfg->g_w;
|
||||
oxcf->height = cfg->g_h;
|
||||
oxcf->bit_depth = extra_cfg->bit_depth;
|
||||
oxcf->input_bit_depth = cfg->g_input_bit_depth;
|
||||
// guess a frame rate if out of whack, use 30
|
||||
oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
|
||||
if (oxcf->init_framerate > 180)
|
||||
|
@ -1246,6 +1256,9 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
|
|||
|
||||
320, // g_width
|
||||
240, // g_height
|
||||
VPX_BITS_8, // g_bit_depth
|
||||
8, // g_input_bit_depth
|
||||
|
||||
{1, 30}, // g_timebase
|
||||
|
||||
0, // g_error_resilient
|
||||
|
|
|
@ -440,6 +440,7 @@ static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
|
|||
// call to get_frame.
|
||||
if (!(*iter)) {
|
||||
img = &ctx->img;
|
||||
img->bit_depth = (int)ctx->pbi->common.bit_depth;
|
||||
*iter = img;
|
||||
}
|
||||
}
|
||||
|
@ -588,6 +589,23 @@ static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx,
|
||||
va_list args) {
|
||||
unsigned int *const bit_depth = va_arg(args, unsigned int *);
|
||||
|
||||
if (bit_depth) {
|
||||
if (ctx->pbi) {
|
||||
const VP9_COMMON *const cm = &ctx->pbi->common;
|
||||
*bit_depth = cm->bit_depth;
|
||||
return VPX_CODEC_OK;
|
||||
} else {
|
||||
return VPX_CODEC_ERROR;
|
||||
}
|
||||
} else {
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
|
||||
va_list args) {
|
||||
ctx->invert_tile_order = va_arg(args, int);
|
||||
|
@ -620,6 +638,7 @@ static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
|
|||
{VP8D_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted},
|
||||
{VP9_GET_REFERENCE, ctrl_get_reference},
|
||||
{VP9D_GET_DISPLAY_SIZE, ctrl_get_display_size},
|
||||
{VP9D_GET_BIT_DEPTH, ctrl_get_bit_depth},
|
||||
|
||||
{ -1, NULL},
|
||||
};
|
||||
|
|
|
@ -154,7 +154,7 @@ static vpx_image_t *img_alloc_helper(vpx_image_t *img,
|
|||
goto fail;
|
||||
|
||||
img->fmt = fmt;
|
||||
img->bit_depth = (fmt & VPX_IMG_FMT_HIGH) ? 16 : 8;
|
||||
img->bit_depth = (fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 16 : 8;
|
||||
img->w = w;
|
||||
img->h = h;
|
||||
img->x_chroma_shift = xcs;
|
||||
|
|
|
@ -75,6 +75,9 @@ enum vp8_dec_control_id {
|
|||
/** control function to get the display dimensions for the current frame. */
|
||||
VP9D_GET_DISPLAY_SIZE,
|
||||
|
||||
/** control function to get the bit depth of the stream. */
|
||||
VP9D_GET_BIT_DEPTH,
|
||||
|
||||
/** For testing. */
|
||||
VP9_INVERT_TILE_DECODE_ORDER,
|
||||
|
||||
|
@ -118,6 +121,7 @@ VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *)
|
|||
VPX_CTRL_USE_TYPE(VPXD_SET_DECRYPTOR, vpx_decrypt_init *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vpx_decrypt_init *)
|
||||
VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE, int *)
|
||||
VPX_CTRL_USE_TYPE(VP9D_GET_BIT_DEPTH, unsigned int *)
|
||||
VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int)
|
||||
|
||||
/*! @} - end defgroup vp8_decoder */
|
||||
|
|
|
@ -217,9 +217,9 @@ extern "C" {
|
|||
* This enumeration determines the bit depth of the codec.
|
||||
*/
|
||||
typedef enum vpx_bit_depth {
|
||||
VPX_BITS_8, /**< 8 bits */
|
||||
VPX_BITS_10, /**< 10 bits */
|
||||
VPX_BITS_12 /**< 12 bits */
|
||||
VPX_BITS_8 = 8, /**< 8 bits */
|
||||
VPX_BITS_10 = 10, /**< 10 bits */
|
||||
VPX_BITS_12 = 12, /**< 12 bits */
|
||||
} vpx_bit_depth_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -80,6 +80,9 @@ extern "C" {
|
|||
*/
|
||||
#define VPX_CODEC_CAP_OUTPUT_PARTITION 0x20000
|
||||
|
||||
/*! Can support input images at greater than 8 bitdepth.
|
||||
*/
|
||||
#define VPX_CODEC_CAP_HIGHBITDEPTH 0x40000
|
||||
|
||||
/*! \brief Initialization-time Feature Enabling
|
||||
*
|
||||
|
@ -91,6 +94,7 @@ extern "C" {
|
|||
#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
|
||||
#define VPX_CODEC_USE_OUTPUT_PARTITION 0x20000 /**< Make the encoder output one
|
||||
partition at a time. */
|
||||
#define VPX_CODEC_USE_HIGHBITDEPTH 0x40000 /**< Use high bitdepth */
|
||||
|
||||
|
||||
/*!\brief Generic fixed size buffer structure
|
||||
|
@ -324,6 +328,21 @@ extern "C" {
|
|||
*/
|
||||
unsigned int g_h;
|
||||
|
||||
/*!\brief Bit-depth of the codec
|
||||
*
|
||||
* This value identifies the bit_depth of the codec,
|
||||
* Only certain bit-depths are supported as identified in the
|
||||
* vpx_bit_depth_t enum.
|
||||
*/
|
||||
vpx_bit_depth_t g_bit_depth;
|
||||
|
||||
/*!\brief Bit-depth of the input frames
|
||||
*
|
||||
* This value identifies the bit_depth of the input frames in bits.
|
||||
* Note that the frames passed as input to the encoder must have
|
||||
* this bit-depth.
|
||||
*/
|
||||
unsigned int g_input_bit_depth;
|
||||
|
||||
/*!\brief Stream timebase units
|
||||
*
|
||||
|
|
|
@ -31,10 +31,10 @@ extern "C" {
|
|||
#define VPX_IMAGE_ABI_VERSION (2) /**<\hideinitializer*/
|
||||
|
||||
|
||||
#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format */
|
||||
#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U plane in memory */
|
||||
#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel component */
|
||||
#define VPX_IMG_FMT_HIGH 0x800 /**< Image uses 16bit framebuffer */
|
||||
#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format. */
|
||||
#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U in memory. */
|
||||
#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel. */
|
||||
#define VPX_IMG_FMT_HIGHBITDEPTH 0x800 /**< Image uses 16bit framebuffer. */
|
||||
|
||||
/*!\brief List of supported image formats */
|
||||
typedef enum vpx_img_fmt {
|
||||
|
@ -59,9 +59,9 @@ extern "C" {
|
|||
VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5,
|
||||
VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6,
|
||||
VPX_IMG_FMT_444A = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_HAS_ALPHA | 7,
|
||||
VPX_IMG_FMT_I42016 = VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGH,
|
||||
VPX_IMG_FMT_I42216 = VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGH,
|
||||
VPX_IMG_FMT_I44416 = VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGH
|
||||
VPX_IMG_FMT_I42016 = VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
VPX_IMG_FMT_I42216 = VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
VPX_IMG_FMT_I44416 = VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGHBITDEPTH
|
||||
} vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
|
||||
|
||||
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "include/vpx_mem_intrnl.h"
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
#if CONFIG_MEM_TRACKER
|
||||
#ifndef VPX_NO_GLOBALS
|
||||
|
@ -452,6 +453,29 @@ void *vpx_memset(void *dest, int val, size_t length) {
|
|||
return VPX_MEMSET_L(dest, val, length);
|
||||
}
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
void *vpx_memset16(void *dest, int val, size_t length) {
|
||||
#if CONFIG_MEM_CHECKS
|
||||
if ((int)dest < 0x4000) {
|
||||
_P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n",
|
||||
(int)dest, val, length);)
|
||||
|
||||
#if defined(VXWORKS)
|
||||
sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
vx_sleep(10000);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
int i;
|
||||
void *orig = dest;
|
||||
uint16_t *dest16 = dest;
|
||||
for (i = 0; i < length; i++)
|
||||
*dest16++ = val;
|
||||
return orig;
|
||||
}
|
||||
#endif // CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
void *vpx_memmove(void *dest, const void *src, size_t count) {
|
||||
#if CONFIG_MEM_CHECKS
|
||||
|
||||
|
|
|
@ -73,6 +73,9 @@ extern "C" {
|
|||
|
||||
void *vpx_memcpy(void *dest, const void *src, size_t length);
|
||||
void *vpx_memset(void *dest, int val, size_t length);
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
void *vpx_memset16(void *dest, int val, size_t length);
|
||||
#endif
|
||||
void *vpx_memmove(void *dest, const void *src, size_t count);
|
||||
|
||||
/* special memory functions */
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "./vpx_config.h"
|
||||
#include "vpx_scale/yv12config.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
#include "vp9/common/vp9_common.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Exports
|
||||
|
@ -136,7 +139,11 @@ int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
|
|||
|
||||
int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
int width, int height,
|
||||
int ss_x, int ss_y, int border,
|
||||
int ss_x, int ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border,
|
||||
vpx_codec_frame_buffer_t *fb,
|
||||
vpx_get_frame_buffer_cb_fn_t cb,
|
||||
void *cb_priv) {
|
||||
|
@ -161,11 +168,21 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
|||
const int alpha_border_h = border;
|
||||
const uint64_t alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
|
||||
(uint64_t)alpha_stride;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint64_t frame_size = (1 + use_highbitdepth) *
|
||||
(yplane_size + 2 * uvplane_size + alpha_plane_size);
|
||||
#else
|
||||
const uint64_t frame_size = yplane_size + 2 * uvplane_size +
|
||||
alpha_plane_size;
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#else
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
const uint64_t frame_size =
|
||||
(1 + use_highbitdepth) * (yplane_size + 2 * uvplane_size);
|
||||
#else
|
||||
const uint64_t frame_size = yplane_size + 2 * uvplane_size;
|
||||
#endif
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // CONFIG_ALPHA
|
||||
if (cb != NULL) {
|
||||
const int align_addr_extra_size = 31;
|
||||
const uint64_t external_frame_size = frame_size + align_addr_extra_size;
|
||||
|
@ -231,11 +248,31 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
|||
ybf->border = border;
|
||||
ybf->frame_size = (int)frame_size;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (use_highbitdepth) {
|
||||
// Store uint16 addresses when using 16bit framebuffers
|
||||
uint8_t *p = CONVERT_TO_BYTEPTR(ybf->buffer_alloc);
|
||||
ybf->y_buffer = p + (border * y_stride) + border;
|
||||
ybf->u_buffer = p + yplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
ybf->v_buffer = p + yplane_size + uvplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
ybf->flags = YV12_FLAG_HIGHBITDEPTH;
|
||||
} else {
|
||||
ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
|
||||
ybf->u_buffer = ybf->buffer_alloc + yplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
ybf->flags = 0;
|
||||
}
|
||||
#else
|
||||
ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
|
||||
ybf->u_buffer = ybf->buffer_alloc + yplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
|
||||
(uv_border_h * uv_stride) + uv_border_w;
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_ALPHA
|
||||
ybf->alpha_width = alpha_width;
|
||||
|
@ -252,11 +289,18 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
|||
|
||||
int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
int width, int height,
|
||||
int ss_x, int ss_y, int border) {
|
||||
int ss_x, int ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border) {
|
||||
if (ybf) {
|
||||
vp9_free_frame_buffer(ybf);
|
||||
return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border,
|
||||
NULL, NULL, NULL);
|
||||
return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif
|
||||
border, NULL, NULL, NULL);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "vpx/vpx_integer.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "vpx_scale/yv12config.h"
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
#include "vp9/common/vp9_common.h"
|
||||
#endif
|
||||
|
||||
static void extend_plane(uint8_t *const src, int src_stride,
|
||||
int width, int height,
|
||||
|
@ -55,6 +58,50 @@ static void extend_plane(uint8_t *const src, int src_stride,
|
|||
}
|
||||
}
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static void extend_plane_high(uint8_t *const src8, int src_stride,
|
||||
int width, int height,
|
||||
int extend_top, int extend_left,
|
||||
int extend_bottom, int extend_right) {
|
||||
int i;
|
||||
const int linesize = extend_left + extend_right + width;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
|
||||
/* copy the left and right most columns out */
|
||||
uint16_t *src_ptr1 = src;
|
||||
uint16_t *src_ptr2 = src + width - 1;
|
||||
uint16_t *dst_ptr1 = src - extend_left;
|
||||
uint16_t *dst_ptr2 = src + width;
|
||||
|
||||
for (i = 0; i < height; ++i) {
|
||||
vpx_memset16(dst_ptr1, src_ptr1[0], extend_left);
|
||||
vpx_memset16(dst_ptr2, src_ptr2[0], extend_right);
|
||||
src_ptr1 += src_stride;
|
||||
src_ptr2 += src_stride;
|
||||
dst_ptr1 += src_stride;
|
||||
dst_ptr2 += src_stride;
|
||||
}
|
||||
|
||||
/* Now copy the top and bottom lines into each line of the respective
|
||||
* borders
|
||||
*/
|
||||
src_ptr1 = src - extend_left;
|
||||
src_ptr2 = src + src_stride * (height - 1) - extend_left;
|
||||
dst_ptr1 = src + src_stride * -extend_top - extend_left;
|
||||
dst_ptr2 = src + src_stride * height - extend_left;
|
||||
|
||||
for (i = 0; i < extend_top; ++i) {
|
||||
vpx_memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
|
||||
dst_ptr1 += src_stride;
|
||||
}
|
||||
|
||||
for (i = 0; i < extend_bottom; ++i) {
|
||||
vpx_memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
|
||||
dst_ptr2 += src_stride;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
|
||||
const int uv_border = ybf->border / 2;
|
||||
|
||||
|
@ -64,6 +111,31 @@ void vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
|
|||
assert(ybf->y_height - ybf->y_crop_height >= 0);
|
||||
assert(ybf->y_width - ybf->y_crop_width >= 0);
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
|
||||
extend_plane_high(
|
||||
ybf->y_buffer, ybf->y_stride,
|
||||
ybf->y_crop_width, ybf->y_crop_height,
|
||||
ybf->border, ybf->border,
|
||||
ybf->border + ybf->y_height - ybf->y_crop_height,
|
||||
ybf->border + ybf->y_width - ybf->y_crop_width);
|
||||
|
||||
extend_plane_high(
|
||||
ybf->u_buffer, ybf->uv_stride,
|
||||
(ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
|
||||
ybf->border / 2, ybf->border / 2,
|
||||
(ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
|
||||
(ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
|
||||
|
||||
extend_plane_high(
|
||||
ybf->v_buffer, ybf->uv_stride,
|
||||
(ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
|
||||
ybf->border / 2, ybf->border / 2,
|
||||
(ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
|
||||
(ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
extend_plane(ybf->y_buffer, ybf->y_stride,
|
||||
ybf->y_crop_width, ybf->y_crop_height,
|
||||
ybf->border, ybf->border,
|
||||
|
@ -99,6 +171,20 @@ static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
|
|||
assert(ybf->y_height - ybf->y_crop_height >= 0);
|
||||
assert(ybf->y_width - ybf->y_crop_width >= 0);
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
|
||||
extend_plane_high(ybf->y_buffer, ybf->y_stride,
|
||||
ybf->y_crop_width, ybf->y_crop_height,
|
||||
ext_size, ext_size,
|
||||
ext_size + ybf->y_height - ybf->y_crop_height,
|
||||
ext_size + ybf->y_width - ybf->y_crop_width);
|
||||
extend_plane_high(ybf->u_buffer, ybf->uv_stride,
|
||||
c_w, c_h, c_et, c_el, c_eb, c_er);
|
||||
extend_plane_high(ybf->v_buffer, ybf->uv_stride,
|
||||
c_w, c_h, c_et, c_el, c_eb, c_er);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
extend_plane(ybf->y_buffer, ybf->y_stride,
|
||||
ybf->y_crop_width, ybf->y_crop_height,
|
||||
ext_size, ext_size,
|
||||
|
@ -121,6 +207,14 @@ void vp9_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf) {
|
|||
VP9INNERBORDERINPIXELS : ybf->border;
|
||||
extend_frame(ybf, inner_bw);
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
vpx_memcpy(dst, src, num * sizeof(uint16_t));
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
#endif // CONFIG_VP9
|
||||
|
||||
// Copies the source image into the destination image and updates the
|
||||
|
@ -140,6 +234,40 @@ void vp8_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_ybc,
|
|||
assert(src_ybc->y_height == dst_ybc->y_height);
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
|
||||
assert(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH);
|
||||
for (row = 0; row < src_ybc->y_height; ++row) {
|
||||
memcpy_short_addr(dst, src, src_ybc->y_width);
|
||||
src += src_ybc->y_stride;
|
||||
dst += dst_ybc->y_stride;
|
||||
}
|
||||
|
||||
src = src_ybc->u_buffer;
|
||||
dst = dst_ybc->u_buffer;
|
||||
|
||||
for (row = 0; row < src_ybc->uv_height; ++row) {
|
||||
memcpy_short_addr(dst, src, src_ybc->uv_width);
|
||||
src += src_ybc->uv_stride;
|
||||
dst += dst_ybc->uv_stride;
|
||||
}
|
||||
|
||||
src = src_ybc->v_buffer;
|
||||
dst = dst_ybc->v_buffer;
|
||||
|
||||
for (row = 0; row < src_ybc->uv_height; ++row) {
|
||||
memcpy_short_addr(dst, src, src_ybc->uv_width);
|
||||
src += src_ybc->uv_stride;
|
||||
dst += dst_ybc->uv_stride;
|
||||
}
|
||||
|
||||
vp8_yv12_extend_frame_borders_c(dst_ybc);
|
||||
return;
|
||||
} else {
|
||||
assert(!(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (row = 0; row < src_ybc->y_height; ++row) {
|
||||
vpx_memcpy(dst, src, src_ybc->y_width);
|
||||
src += src_ybc->y_stride;
|
||||
|
@ -173,6 +301,19 @@ void vpx_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
|
|||
const uint8_t *src = src_ybc->y_buffer;
|
||||
uint8_t *dst = dst_ybc->y_buffer;
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
|
||||
const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
|
||||
uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
|
||||
for (row = 0; row < src_ybc->y_height; ++row) {
|
||||
vpx_memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
|
||||
src16 += src_ybc->y_stride;
|
||||
dst16 += dst_ybc->y_stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (row = 0; row < src_ybc->y_height; ++row) {
|
||||
vpx_memcpy(dst, src, src_ybc->y_width);
|
||||
src += src_ybc->y_stride;
|
||||
|
|
|
@ -55,6 +55,8 @@ typedef struct yv12_buffer_config {
|
|||
int flags;
|
||||
} YV12_BUFFER_CONFIG;
|
||||
|
||||
#define YV12_FLAG_HIGHBITDEPTH 1
|
||||
|
||||
int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
int width, int height, int border);
|
||||
int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
|
@ -63,6 +65,9 @@ int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf);
|
|||
|
||||
int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
int width, int height, int ss_x, int ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border);
|
||||
|
||||
// Updates the yv12 buffer config with the frame buffer. If cb is not
|
||||
|
@ -73,6 +78,9 @@ int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
|||
// on failure.
|
||||
int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
|
||||
int width, int height, int ss_x, int ss_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
int border,
|
||||
vpx_codec_frame_buffer_t *fb,
|
||||
vpx_get_frame_buffer_cb_fn_t cb,
|
||||
|
|
251
vpxdec.c
251
vpxdec.c
|
@ -90,12 +90,20 @@ static const arg_def_t fb_arg =
|
|||
|
||||
static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
|
||||
"Compute the MD5 sum of the decoded frame");
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static const arg_def_t outbitdeptharg = ARG_DEF(
|
||||
NULL, "output-bit-depth", 1,
|
||||
"Output bit-depth for decoded frames");
|
||||
#endif
|
||||
|
||||
static const arg_def_t *all_args[] = {
|
||||
&codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg,
|
||||
&progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
|
||||
&threadsarg, &verbosearg, &scalearg, &fb_arg,
|
||||
&md5arg, &error_concealment, &continuearg,
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
&outbitdeptharg,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -129,6 +137,26 @@ static const arg_def_t *vp8_pp_args[] = {
|
|||
#if CONFIG_LIBYUV
|
||||
static INLINE int vpx_image_scale(vpx_image_t *src, vpx_image_t *dst,
|
||||
FilterModeEnum mode) {
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (src->fmt == VPX_IMG_FMT_I42016) {
|
||||
assert(dst->fmt == VPX_IMG_FMT_I42016);
|
||||
return I420Scale_16((uint16_t*)src->planes[VPX_PLANE_Y],
|
||||
src->stride[VPX_PLANE_Y]/2,
|
||||
(uint16_t*)src->planes[VPX_PLANE_U],
|
||||
src->stride[VPX_PLANE_U]/2,
|
||||
(uint16_t*)src->planes[VPX_PLANE_V],
|
||||
src->stride[VPX_PLANE_V]/2,
|
||||
src->d_w, src->d_h,
|
||||
(uint16_t*)dst->planes[VPX_PLANE_Y],
|
||||
dst->stride[VPX_PLANE_Y]/2,
|
||||
(uint16_t*)dst->planes[VPX_PLANE_U],
|
||||
dst->stride[VPX_PLANE_U]/2,
|
||||
(uint16_t*)dst->planes[VPX_PLANE_V],
|
||||
dst->stride[VPX_PLANE_V]/2,
|
||||
dst->d_w, dst->d_h,
|
||||
mode);
|
||||
}
|
||||
#endif
|
||||
assert(src->fmt == VPX_IMG_FMT_I420);
|
||||
assert(dst->fmt == VPX_IMG_FMT_I420);
|
||||
return I420Scale(src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y],
|
||||
|
@ -265,6 +293,11 @@ static void update_image_md5(const vpx_image_t *img, const int planes[3],
|
|||
static void write_image_file(const vpx_image_t *img, const int planes[3],
|
||||
FILE *file) {
|
||||
int i, y;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
const int bytes_per_sample = ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
|
||||
#else
|
||||
const int bytes_per_sample = 1;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
const int plane = planes[i];
|
||||
|
@ -274,7 +307,7 @@ static void write_image_file(const vpx_image_t *img, const int planes[3],
|
|||
const int h = vpx_img_plane_height(img, plane);
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
fwrite(buf, 1, w, file);
|
||||
fwrite(buf, bytes_per_sample, w, file);
|
||||
buf += stride;
|
||||
}
|
||||
}
|
||||
|
@ -494,6 +527,178 @@ static FILE *open_outfile(const char *name) {
|
|||
}
|
||||
}
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static void high_img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
const int offset = input_shift > 0 ? (1 << (input_shift - 1)) : 0;
|
||||
int plane;
|
||||
if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
dst->fmt != src->fmt || input_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (src->fmt) {
|
||||
case VPX_IMG_FMT_I42016:
|
||||
case VPX_IMG_FMT_I42216:
|
||||
case VPX_IMG_FMT_I44416:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->d_w;
|
||||
int h = src->d_h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
|
||||
y * src->stride[plane]);
|
||||
uint16_t *p_dst = (uint16_t *)(dst->planes[plane] +
|
||||
y * dst->stride[plane]);
|
||||
for (x = 0; x < w; x++)
|
||||
*p_dst++ = (*p_src++ << input_shift) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void low_img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
const int offset = input_shift > 0 ? (1 << (input_shift - 1)) : 0;
|
||||
int plane;
|
||||
if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH ||
|
||||
input_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (src->fmt) {
|
||||
case VPX_IMG_FMT_I420:
|
||||
case VPX_IMG_FMT_I422:
|
||||
case VPX_IMG_FMT_I444:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->d_w;
|
||||
int h = src->d_h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
|
||||
uint16_t *p_dst = (uint16_t *)(dst->planes[plane] +
|
||||
y * dst->stride[plane]);
|
||||
for (x = 0; x < w; x++) {
|
||||
*p_dst++ = (*p_src++ << input_shift) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
high_img_upshift(dst, src, input_shift);
|
||||
} else {
|
||||
low_img_upshift(dst, src, input_shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void high_img_downshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int down_shift) {
|
||||
int plane;
|
||||
if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
dst->fmt != src->fmt || down_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (src->fmt) {
|
||||
case VPX_IMG_FMT_I42016:
|
||||
case VPX_IMG_FMT_I42216:
|
||||
case VPX_IMG_FMT_I44416:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->d_w;
|
||||
int h = src->d_h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
|
||||
y * src->stride[plane]);
|
||||
uint16_t *p_dst = (uint16_t *)(dst->planes[plane] +
|
||||
y * dst->stride[plane]);
|
||||
for (x = 0; x < w; x++)
|
||||
*p_dst++ = *p_src++ >> down_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void low_img_downshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int down_shift) {
|
||||
int plane;
|
||||
if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH ||
|
||||
down_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (dst->fmt) {
|
||||
case VPX_IMG_FMT_I420:
|
||||
case VPX_IMG_FMT_I422:
|
||||
case VPX_IMG_FMT_I444:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->d_w;
|
||||
int h = src->d_h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
|
||||
y * src->stride[plane]);
|
||||
uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
|
||||
for (x = 0; x < w; x++) {
|
||||
*p_dst++ = *p_src++ >> down_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void img_downshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int down_shift) {
|
||||
if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
high_img_downshift(dst, src, down_shift);
|
||||
} else {
|
||||
low_img_downshift(dst, src, down_shift);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main_loop(int argc, const char **argv_) {
|
||||
vpx_codec_ctx_t decoder;
|
||||
char *fn = NULL;
|
||||
|
@ -518,6 +723,9 @@ int main_loop(int argc, const char **argv_) {
|
|||
int opt_yv12 = 0;
|
||||
int opt_i420 = 0;
|
||||
vpx_codec_dec_cfg_t cfg = {0, 0, 0};
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
int output_bit_depth = 0;
|
||||
#endif
|
||||
#if CONFIG_VP8_DECODER
|
||||
vp8_postproc_cfg_t vp8_pp_cfg = {0};
|
||||
int vp8_dbg_color_ref_frame = 0;
|
||||
|
@ -529,6 +737,9 @@ int main_loop(int argc, const char **argv_) {
|
|||
int dec_flags = 0;
|
||||
int do_scale = 0;
|
||||
vpx_image_t *scaled_img = NULL;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_image_t *img_shifted = NULL;
|
||||
#endif
|
||||
int frame_avail, got_data;
|
||||
int num_external_frame_buffers = 0;
|
||||
struct ExternalFrameBufferList ext_fb_list = {0, NULL};
|
||||
|
@ -569,6 +780,9 @@ int main_loop(int argc, const char **argv_) {
|
|||
use_y4m = 0;
|
||||
flipuv = 1;
|
||||
opt_yv12 = 1;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
output_bit_depth = 8; // For yv12 8-bit depth output is assumed
|
||||
#endif
|
||||
} else if (arg_match(&arg, &use_i420, argi)) {
|
||||
use_y4m = 0;
|
||||
flipuv = 0;
|
||||
|
@ -601,6 +815,11 @@ int main_loop(int argc, const char **argv_) {
|
|||
num_external_frame_buffers = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &continuearg, argi))
|
||||
keep_going = 1;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
else if (arg_match(&arg, &outbitdeptharg, argi)) {
|
||||
output_bit_depth = arg_parse_uint(&arg);
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_VP8_DECODER
|
||||
else if (arg_match(&arg, &addnoise_level, argi)) {
|
||||
postproc = 1;
|
||||
|
@ -905,6 +1124,33 @@ int main_loop(int argc, const char **argv_) {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
// Default to codec bit depth if output bit depth not set
|
||||
if (!output_bit_depth) {
|
||||
output_bit_depth = img->bit_depth;
|
||||
}
|
||||
// Shift up or down if necessary
|
||||
if (output_bit_depth != img->bit_depth) {
|
||||
if (!img_shifted) {
|
||||
if (output_bit_depth == 8) {
|
||||
img_shifted = vpx_img_alloc(
|
||||
NULL, img->fmt - VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
img->d_w, img->d_h, 16);
|
||||
} else {
|
||||
img_shifted = vpx_img_alloc(
|
||||
NULL, img->fmt | VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
img->d_w, img->d_h, 16);
|
||||
}
|
||||
img_shifted->bit_depth = output_bit_depth;
|
||||
}
|
||||
if (output_bit_depth > img->bit_depth) {
|
||||
img_upshift(img_shifted, img, output_bit_depth - img->bit_depth);
|
||||
} else {
|
||||
img_downshift(img_shifted, img, img->bit_depth - output_bit_depth);
|
||||
}
|
||||
img = img_shifted;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (single_file) {
|
||||
if (use_y4m) {
|
||||
|
@ -1011,6 +1257,9 @@ fail:
|
|||
free(buf);
|
||||
|
||||
if (scaled_img) vpx_img_free(scaled_img);
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (img_shifted) vpx_img_free(img_shifted);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ext_fb_list.num_external_frame_buffers; ++i) {
|
||||
free(ext_fb_list.ext_fb[i].data);
|
||||
|
|
458
vpxenc.c
458
vpxenc.c
|
@ -200,6 +200,10 @@ static const arg_def_t experimental_bitstream =
|
|||
ARG_DEF(NULL, "experimental-bitstream", 0,
|
||||
"Allow experimental bitstream features.");
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static const arg_def_t test16bitinternalarg = ARG_DEF(
|
||||
NULL, "test-16bit-internal", 0, "Force use of 16 bit internal buffer");
|
||||
#endif
|
||||
|
||||
static const arg_def_t *main_args[] = {
|
||||
&debugmode,
|
||||
|
@ -248,6 +252,9 @@ static const arg_def_t *global_args[] = {
|
|||
#endif
|
||||
&timebase, &framerate,
|
||||
&error_resilient,
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
&test16bitinternalarg,
|
||||
#endif
|
||||
&lag_in_frames, NULL
|
||||
};
|
||||
|
||||
|
@ -381,6 +388,23 @@ static const arg_def_t frame_periodic_boost = ARG_DEF(
|
|||
NULL, "frame-boost", 1,
|
||||
"Enable frame periodic boost (0: off (default), 1: on)");
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static const struct arg_enum_list bitdepth_enum[] = {
|
||||
{"8", VPX_BITS_8},
|
||||
{"10", VPX_BITS_10},
|
||||
{"12", VPX_BITS_12},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static const arg_def_t bitdeptharg = ARG_DEF_ENUM("b", "bit-depth", 1,
|
||||
"Bit depth for codec "
|
||||
"(8 for version <=1, "
|
||||
"10 or 12 for version 2)",
|
||||
bitdepth_enum);
|
||||
static const arg_def_t inbitdeptharg = ARG_DEF(NULL, "input-bit-depth", 1,
|
||||
"Bit depth of input");
|
||||
#endif
|
||||
|
||||
static const struct arg_enum_list tune_content_enum[] = {
|
||||
{"default", VP9E_CONTENT_DEFAULT},
|
||||
{"screen", VP9E_CONTENT_SCREEN},
|
||||
|
@ -395,6 +419,9 @@ static const arg_def_t *vp9_args[] = {
|
|||
&tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
|
||||
&tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
|
||||
&frame_parallel_decoding, &aq_mode, &frame_periodic_boost, &tune_content,
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
&bitdeptharg, &inbitdeptharg,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
static const int vp9_arg_ctrl_map[] = {
|
||||
|
@ -450,6 +477,102 @@ void usage_exit() {
|
|||
}
|
||||
|
||||
#define mmin(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static void find_mismatch_high(const vpx_image_t *const img1,
|
||||
const vpx_image_t *const img2,
|
||||
int yloc[4], int uloc[4], int vloc[4]) {
|
||||
uint16_t *plane1, *plane2;
|
||||
uint32_t stride1, stride2;
|
||||
const uint32_t bsize = 64;
|
||||
const uint32_t bsizey = bsize >> img1->y_chroma_shift;
|
||||
const uint32_t bsizex = bsize >> img1->x_chroma_shift;
|
||||
const uint32_t c_w =
|
||||
(img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
|
||||
const uint32_t c_h =
|
||||
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
|
||||
int match = 1;
|
||||
uint32_t i, j;
|
||||
yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
|
||||
plane1 = (uint16_t*)img1->planes[VPX_PLANE_Y];
|
||||
plane2 = (uint16_t*)img2->planes[VPX_PLANE_Y];
|
||||
stride1 = img1->stride[VPX_PLANE_Y]/2;
|
||||
stride2 = img2->stride[VPX_PLANE_Y]/2;
|
||||
for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
|
||||
for (j = 0; match && j < img1->d_w; j += bsize) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsize, img1->d_h) - i;
|
||||
const int sj = mmin(j + bsize, img1->d_w) - j;
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(plane1 + (i + k) * stride1 + j + l) !=
|
||||
*(plane2 + (i + k) * stride2 + j + l)) {
|
||||
yloc[0] = i + k;
|
||||
yloc[1] = j + l;
|
||||
yloc[2] = *(plane1 + (i + k) * stride1 + j + l);
|
||||
yloc[3] = *(plane2 + (i + k) * stride2 + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
|
||||
plane1 = (uint16_t*)img1->planes[VPX_PLANE_U];
|
||||
plane2 = (uint16_t*)img2->planes[VPX_PLANE_U];
|
||||
stride1 = img1->stride[VPX_PLANE_U]/2;
|
||||
stride2 = img2->stride[VPX_PLANE_U]/2;
|
||||
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
|
||||
for (j = 0; match && j < c_w; j += bsizex) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsizey, c_h - i);
|
||||
const int sj = mmin(j + bsizex, c_w - j);
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(plane1 + (i + k) * stride1 + j + l) !=
|
||||
*(plane2 + (i + k) * stride2 + j + l)) {
|
||||
uloc[0] = i + k;
|
||||
uloc[1] = j + l;
|
||||
uloc[2] = *(plane1 + (i + k) * stride1 + j + l);
|
||||
uloc[3] = *(plane2 + (i + k) * stride2 + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
|
||||
plane1 = (uint16_t*)img1->planes[VPX_PLANE_V];
|
||||
plane2 = (uint16_t*)img2->planes[VPX_PLANE_V];
|
||||
stride1 = img1->stride[VPX_PLANE_V]/2;
|
||||
stride2 = img2->stride[VPX_PLANE_V]/2;
|
||||
for (i = 0, match = 1; match && i < c_h; i += bsizey) {
|
||||
for (j = 0; match && j < c_w; j += bsizex) {
|
||||
int k, l;
|
||||
const int si = mmin(i + bsizey, c_h - i);
|
||||
const int sj = mmin(j + bsizex, c_w - j);
|
||||
for (k = 0; match && k < si; ++k) {
|
||||
for (l = 0; match && l < sj; ++l) {
|
||||
if (*(plane1 + (i + k) * stride1 + j + l) !=
|
||||
*(plane2 + (i + k) * stride2 + j + l)) {
|
||||
vloc[0] = i + k;
|
||||
vloc[1] = j + l;
|
||||
vloc[2] = *(plane1 + (i + k) * stride1 + j + l);
|
||||
vloc[3] = *(plane2 + (i + k) * stride2 + j + l);
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void find_mismatch(const vpx_image_t *const img1,
|
||||
const vpx_image_t *const img2,
|
||||
int yloc[4], int uloc[4], int vloc[4]) {
|
||||
|
@ -542,7 +665,8 @@ static void find_mismatch(const vpx_image_t *const img1,
|
|||
|
||||
static int compare_img(const vpx_image_t *const img1,
|
||||
const vpx_image_t *const img2) {
|
||||
const uint32_t c_w =
|
||||
uint32_t l_w = img1->d_w;
|
||||
uint32_t c_w =
|
||||
(img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
|
||||
const uint32_t c_h =
|
||||
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
|
||||
|
@ -552,11 +676,17 @@ static int compare_img(const vpx_image_t *const img1,
|
|||
match &= (img1->fmt == img2->fmt);
|
||||
match &= (img1->d_w == img2->d_w);
|
||||
match &= (img1->d_h == img2->d_h);
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (img1->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
l_w *= 2;
|
||||
c_w *= 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < img1->d_h; ++i)
|
||||
match &= (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
|
||||
img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
|
||||
img1->d_w) == 0);
|
||||
l_w) == 0);
|
||||
|
||||
for (i = 0; i < c_h; ++i)
|
||||
match &= (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
|
||||
|
@ -601,6 +731,10 @@ struct stream_config {
|
|||
int arg_ctrl_cnt;
|
||||
int write_webm;
|
||||
int have_kf_max_dist;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
// whether to use 16bit internal buffers
|
||||
int use_16bit_internal;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -873,6 +1007,9 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
|
|||
static const int *ctrl_args_map = NULL;
|
||||
struct stream_config *config = &stream->config;
|
||||
int eos_mark_found = 0;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
int test_16bit_internal = 0;
|
||||
#endif
|
||||
|
||||
// Handle codec specific options
|
||||
if (0) {
|
||||
|
@ -921,6 +1058,12 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
|
|||
config->cfg.g_w = arg_parse_uint(&arg);
|
||||
} else if (arg_match(&arg, &height, argi)) {
|
||||
config->cfg.g_h = arg_parse_uint(&arg);
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
} else if (arg_match(&arg, &bitdeptharg, argi)) {
|
||||
config->cfg.g_bit_depth = arg_parse_enum_or_int(&arg);
|
||||
} else if (arg_match(&arg, &inbitdeptharg, argi)) {
|
||||
config->cfg.g_input_bit_depth = arg_parse_uint(&arg);
|
||||
#endif
|
||||
#if CONFIG_WEBM_IO
|
||||
} else if (arg_match(&arg, &stereo_mode, argi)) {
|
||||
config->stereo_fmt = arg_parse_enum_or_int(&arg);
|
||||
|
@ -988,6 +1131,12 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
|
|||
config->have_kf_max_dist = 1;
|
||||
} else if (arg_match(&arg, &kf_disabled, argi)) {
|
||||
config->cfg.kf_mode = VPX_KF_DISABLED;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
} else if (arg_match(&arg, &test16bitinternalarg, argi)) {
|
||||
if (strcmp(global->codec->name, "vp9") == 0) {
|
||||
test_16bit_internal = 1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
int i, match = 0;
|
||||
for (i = 0; ctrl_args[i]; i++) {
|
||||
|
@ -1018,6 +1167,12 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
|
|||
argj++;
|
||||
}
|
||||
}
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (strcmp(global->codec->name, "vp9") == 0) {
|
||||
config->use_16bit_internal = test_16bit_internal |
|
||||
(config->cfg.g_profile > 1);
|
||||
}
|
||||
#endif
|
||||
return eos_mark_found;
|
||||
}
|
||||
|
||||
|
@ -1045,6 +1200,14 @@ static void validate_stream_config(const struct stream_state *stream,
|
|||
experimental_bitstream.long_name);
|
||||
}
|
||||
|
||||
// Check that the codec bit depth is greater than the input bit depth.
|
||||
if (stream->config.cfg.g_input_bit_depth >
|
||||
(int)stream->config.cfg.g_bit_depth) {
|
||||
fatal("Stream %d: codec bit depth (%d) less than input bit depth (%d)",
|
||||
stream->index, (int)stream->config.cfg.g_bit_depth,
|
||||
stream->config.cfg.g_input_bit_depth);
|
||||
}
|
||||
|
||||
for (streami = stream; streami; streami = streami->next) {
|
||||
/* All streams require output files */
|
||||
if (!streami->config.out_fn)
|
||||
|
@ -1153,6 +1316,8 @@ static void show_stream_config(struct stream_state *stream,
|
|||
SHOW(g_profile);
|
||||
SHOW(g_w);
|
||||
SHOW(g_h);
|
||||
SHOW(g_bit_depth);
|
||||
SHOW(g_input_bit_depth);
|
||||
SHOW(g_timebase.num);
|
||||
SHOW(g_timebase.den);
|
||||
SHOW(g_error_resilient);
|
||||
|
@ -1285,6 +1450,9 @@ static void initialize_encoder(struct stream_state *stream,
|
|||
|
||||
flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
|
||||
flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
flags |= stream->config.use_16bit_internal ? VPX_CODEC_USE_HIGHBITDEPTH : 0;
|
||||
#endif
|
||||
|
||||
/* Construct Encoder Context */
|
||||
vpx_codec_enc_init(&stream->encoder, global->codec->codec_interface(),
|
||||
|
@ -1330,6 +1498,46 @@ static void encode_frame(struct stream_state *stream,
|
|||
/ cfg->g_timebase.num / global->framerate.num;
|
||||
|
||||
/* Scale if necessary */
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (img) {
|
||||
if ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) &&
|
||||
(img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
|
||||
if (img->fmt != VPX_IMG_FMT_I42016) {
|
||||
fprintf(stderr, "%s can only scale 4:2:0 inputs\n", exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#if CONFIG_LIBYUV
|
||||
if (!stream->img) {
|
||||
stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I42016,
|
||||
cfg->g_w, cfg->g_h, 16);
|
||||
}
|
||||
I420Scale_16((uint16*)img->planes[VPX_PLANE_Y],
|
||||
img->stride[VPX_PLANE_Y]/2,
|
||||
(uint16*)img->planes[VPX_PLANE_U],
|
||||
img->stride[VPX_PLANE_U]/2,
|
||||
(uint16*)img->planes[VPX_PLANE_V],
|
||||
img->stride[VPX_PLANE_V]/2,
|
||||
img->d_w, img->d_h,
|
||||
(uint16*)stream->img->planes[VPX_PLANE_Y],
|
||||
stream->img->stride[VPX_PLANE_Y]/2,
|
||||
(uint16*)stream->img->planes[VPX_PLANE_U],
|
||||
stream->img->stride[VPX_PLANE_U]/2,
|
||||
(uint16*)stream->img->planes[VPX_PLANE_V],
|
||||
stream->img->stride[VPX_PLANE_V]/2,
|
||||
stream->img->d_w, stream->img->d_h,
|
||||
kFilterBox);
|
||||
img = stream->img;
|
||||
#else
|
||||
stream->encoder.err = 1;
|
||||
ctx_exit_on_error(&stream->encoder,
|
||||
"Stream %d: Failed to encode frame.\n"
|
||||
"Scaling disabled in this configuration. \n"
|
||||
"To enable, configure with --enable-libyuv\n",
|
||||
stream->index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
|
||||
if (img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_YV12) {
|
||||
fprintf(stderr, "%s can only scale 4:2:0 8bpp inputs\n", exec_name);
|
||||
|
@ -1508,6 +1716,131 @@ static float usec_to_fps(uint64_t usec, unsigned int frames) {
|
|||
return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
|
||||
}
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
static void high_img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
// Note the offset is 1 less than half
|
||||
const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
|
||||
int plane;
|
||||
if (dst->w != src->w || dst->h != src->h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
dst->fmt != src->fmt || input_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (src->fmt) {
|
||||
case VPX_IMG_FMT_I42016:
|
||||
case VPX_IMG_FMT_I42216:
|
||||
case VPX_IMG_FMT_I44416:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->w;
|
||||
int h = src->h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
|
||||
y * src->stride[plane]);
|
||||
uint16_t *p_dst = (uint16_t *)(dst->planes[plane] +
|
||||
y * dst->stride[plane]);
|
||||
for (x = 0; x < w; x++)
|
||||
*p_dst++ = (*p_src++ << input_shift) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void low_img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
// Note the offset is 1 less than half
|
||||
const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
|
||||
int plane;
|
||||
if (dst->w != src->w || dst->h != src->h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift ||
|
||||
dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH ||
|
||||
input_shift < 0) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (src->fmt) {
|
||||
case VPX_IMG_FMT_I420:
|
||||
case VPX_IMG_FMT_I422:
|
||||
case VPX_IMG_FMT_I444:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->w;
|
||||
int h = src->h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
|
||||
uint16_t *p_dst = (uint16_t *)(dst->planes[plane] +
|
||||
y * dst->stride[plane]);
|
||||
for (x = 0; x < w; x++) {
|
||||
*p_dst++ = (*p_src++ << input_shift) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void img_upshift(vpx_image_t *dst, vpx_image_t *src,
|
||||
int input_shift) {
|
||||
if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
high_img_upshift(dst, src, input_shift);
|
||||
} else {
|
||||
low_img_upshift(dst, src, input_shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void img_cast_16_to_8(vpx_image_t *dst, vpx_image_t *src) {
|
||||
int plane;
|
||||
if (dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH != src->fmt ||
|
||||
dst->d_w != src->d_w || dst->d_h != src->d_h ||
|
||||
dst->x_chroma_shift != src->x_chroma_shift ||
|
||||
dst->y_chroma_shift != src->y_chroma_shift) {
|
||||
fatal("Unsupported image conversion");
|
||||
}
|
||||
switch (dst->fmt) {
|
||||
case VPX_IMG_FMT_I420:
|
||||
case VPX_IMG_FMT_I422:
|
||||
case VPX_IMG_FMT_I444:
|
||||
break;
|
||||
default:
|
||||
fatal("Unsupported image conversion");
|
||||
break;
|
||||
}
|
||||
for (plane = 0; plane < 3; plane++) {
|
||||
int w = src->d_w;
|
||||
int h = src->d_h;
|
||||
int x, y;
|
||||
if (plane) {
|
||||
w >>= src->x_chroma_shift;
|
||||
h >>= src->y_chroma_shift;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
uint16_t *p_src = (uint16_t *)(src->planes[plane] +
|
||||
y * src->stride[plane]);
|
||||
uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
|
||||
for (x = 0; x < w; x++) {
|
||||
*p_dst++ = *p_src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_decode(struct stream_state *stream,
|
||||
enum TestDecodeFatality fatal,
|
||||
|
@ -1534,20 +1867,44 @@ static void test_decode(struct stream_state *stream,
|
|||
vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc);
|
||||
vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec);
|
||||
} else {
|
||||
struct vp9_ref_frame ref;
|
||||
struct vp9_ref_frame ref_enc, ref_dec;
|
||||
|
||||
ref.idx = 0;
|
||||
vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref);
|
||||
enc_img = ref.img;
|
||||
vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref);
|
||||
dec_img = ref.img;
|
||||
ref_enc.idx = 0;
|
||||
ref_dec.idx = 0;
|
||||
vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref_enc);
|
||||
enc_img = ref_enc.img;
|
||||
vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref_dec);
|
||||
dec_img = ref_dec.img;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if ((enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) !=
|
||||
(dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH)) {
|
||||
if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
vpx_img_alloc(&enc_img, enc_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
enc_img.d_w, enc_img.d_h, 16);
|
||||
img_cast_16_to_8(&enc_img, &ref_enc.img);
|
||||
}
|
||||
if (dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
vpx_img_alloc(&dec_img, dec_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
dec_img.d_w, dec_img.d_h, 16);
|
||||
img_cast_16_to_8(&dec_img, &ref_dec.img);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
|
||||
ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
|
||||
|
||||
if (!compare_img(&enc_img, &dec_img)) {
|
||||
int y[4], u[4], v[4];
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
|
||||
find_mismatch_high(&enc_img, &dec_img, y, u, v);
|
||||
} else {
|
||||
find_mismatch(&enc_img, &dec_img, y, u, v);
|
||||
}
|
||||
#else
|
||||
find_mismatch(&enc_img, &dec_img, y, u, v);
|
||||
#endif
|
||||
stream->decoder.err = 1;
|
||||
warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
|
||||
"Stream %d: Encode/decode mismatch on frame %d at"
|
||||
|
@ -1589,6 +1946,12 @@ static void print_time(const char *label, int64_t etl) {
|
|||
int main(int argc, const char **argv_) {
|
||||
int pass;
|
||||
vpx_image_t raw;
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_image_t raw_shift;
|
||||
int allocated_raw_shift = 0;
|
||||
int use_16bit_internal = 0;
|
||||
int input_shift = 0;
|
||||
#endif
|
||||
int frame_avail, got_data;
|
||||
|
||||
struct VpxInputContext input;
|
||||
|
@ -1690,6 +2053,27 @@ int main(int argc, const char **argv_) {
|
|||
if (!input.width || !input.height)
|
||||
fatal("Specify stream dimensions with --width (-w) "
|
||||
" and --height (-h)");
|
||||
|
||||
/* If input file does not specify bit-depth but input-bit-depth parameter
|
||||
* exists, assume that to be the input bit-depth. However, if the
|
||||
* input-bit-depth paramter does not exist, assume the input bit-depth
|
||||
* to be the same as the codec bit-depth.
|
||||
*/
|
||||
if (!input.bit_depth) {
|
||||
FOREACH_STREAM({
|
||||
if (stream->config.cfg.g_input_bit_depth)
|
||||
input.bit_depth = stream->config.cfg.g_input_bit_depth;
|
||||
else
|
||||
input.bit_depth = stream->config.cfg.g_input_bit_depth =
|
||||
(int)stream->config.cfg.g_bit_depth;
|
||||
});
|
||||
if (input.bit_depth > 8) input.fmt |= VPX_IMG_FMT_HIGHBITDEPTH;
|
||||
} else {
|
||||
FOREACH_STREAM({
|
||||
stream->config.cfg.g_input_bit_depth = input.bit_depth;
|
||||
});
|
||||
}
|
||||
|
||||
FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
|
||||
FOREACH_STREAM(validate_stream_config(stream, &global));
|
||||
|
||||
|
@ -1743,6 +2127,25 @@ int main(int argc, const char **argv_) {
|
|||
FOREACH_STREAM(open_output_file(stream, &global));
|
||||
FOREACH_STREAM(initialize_encoder(stream, &global));
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (strcmp(global.codec->name, "vp9") == 0) {
|
||||
// Check to see if at least one stream uses 16 bit internal.
|
||||
// Currently assume that the bit_depths for all streams using
|
||||
// highbitdepth are the same.
|
||||
FOREACH_STREAM({
|
||||
if (stream->config.use_16bit_internal) {
|
||||
use_16bit_internal = 1;
|
||||
}
|
||||
if (stream->config.cfg.g_profile == 0) {
|
||||
input_shift = 0;
|
||||
} else {
|
||||
input_shift = (int)stream->config.cfg.g_bit_depth -
|
||||
stream->config.cfg.g_input_bit_depth;
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
|
||||
|
@ -1780,10 +2183,45 @@ int main(int argc, const char **argv_) {
|
|||
frame_avail = 0;
|
||||
|
||||
if (frames_in > global.skip_frames) {
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_image_t *frame_to_encode;
|
||||
if (input_shift || (use_16bit_internal && input.bit_depth == 8)) {
|
||||
assert(use_16bit_internal);
|
||||
// Input bit depth and stream bit depth do not match, so up
|
||||
// shift frame to stream bit depth
|
||||
if (!allocated_raw_shift) {
|
||||
vpx_img_alloc(&raw_shift, raw.fmt | VPX_IMG_FMT_HIGHBITDEPTH,
|
||||
input.width, input.height, 32);
|
||||
allocated_raw_shift = 1;
|
||||
}
|
||||
img_upshift(&raw_shift, &raw, input_shift);
|
||||
frame_to_encode = &raw_shift;
|
||||
} else {
|
||||
frame_to_encode = &raw;
|
||||
}
|
||||
vpx_usec_timer_start(&timer);
|
||||
if (use_16bit_internal) {
|
||||
assert(frame_to_encode->fmt & VPX_IMG_FMT_HIGHBITDEPTH);
|
||||
FOREACH_STREAM({
|
||||
if (stream->config.use_16bit_internal)
|
||||
encode_frame(stream, &global,
|
||||
frame_avail ? frame_to_encode : NULL,
|
||||
frames_in);
|
||||
else
|
||||
assert(0);
|
||||
});
|
||||
} else {
|
||||
assert((frame_to_encode->fmt & VPX_IMG_FMT_HIGHBITDEPTH) == 0);
|
||||
FOREACH_STREAM(encode_frame(stream, &global,
|
||||
frame_avail ? frame_to_encode : NULL,
|
||||
frames_in));
|
||||
}
|
||||
#else
|
||||
vpx_usec_timer_start(&timer);
|
||||
FOREACH_STREAM(encode_frame(stream, &global,
|
||||
frame_avail ? &raw : NULL,
|
||||
frames_in));
|
||||
#endif
|
||||
vpx_usec_timer_mark(&timer);
|
||||
cx_time += vpx_usec_timer_elapsed(&timer);
|
||||
|
||||
|
@ -1901,6 +2339,10 @@ int main(int argc, const char **argv_) {
|
|||
});
|
||||
#endif
|
||||
|
||||
#if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
|
||||
if (allocated_raw_shift)
|
||||
vpx_img_free(&raw_shift);
|
||||
#endif
|
||||
vpx_img_free(&raw);
|
||||
free(argv);
|
||||
free(streams);
|
||||
|
|
Загрузка…
Ссылка в новой задаче