diff options
-rw-r--r-- | build/make/configure.sh | 4 | ||||
-rw-r--r-- | test/resize_test.cc | 4 | ||||
-rw-r--r-- | test/vp9_ext_ratectrl_test.cc | 18 | ||||
-rw-r--r-- | test/y4m_test.cc | 25 | ||||
-rw-r--r-- | vp8/encoder/encodeframe.c | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 41 | ||||
-rw-r--r-- | vp9/encoder/vp9_ext_ratectrl.c | 101 | ||||
-rw-r--r-- | vp9/encoder/vp9_ext_ratectrl.h | 28 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 4 | ||||
-rw-r--r-- | vp9/simple_encode.cc | 10 | ||||
-rw-r--r-- | vp9/simple_encode.h | 43 | ||||
-rw-r--r-- | vp9/vp9_cx_iface.c | 6 | ||||
-rw-r--r-- | vpx/vpx_encoder.h | 4 | ||||
-rw-r--r-- | vpx/vpx_ext_ratectrl.h | 227 | ||||
-rw-r--r-- | vpx_dsp/arm/highbd_loopfilter_neon.c | 15 | ||||
-rw-r--r-- | vpx_dsp/arm/loopfilter_neon.c | 15 | ||||
-rw-r--r-- | vpxenc.c | 11 | ||||
-rw-r--r-- | y4minput.c | 394 | ||||
-rw-r--r-- | y4minput.h | 12 |
19 files changed, 667 insertions, 300 deletions
diff --git a/build/make/configure.sh b/build/make/configure.sh index 91a64b504..c4e938fc7 100644 --- a/build/make/configure.sh +++ b/build/make/configure.sh @@ -919,8 +919,8 @@ process_common_toolchain() { add_ldflags "-mmacosx-version-min=10.15" ;; *-darwin20-*) - add_cflags "-mmacosx-version-min=10.16" - add_ldflags "-mmacosx-version-min=10.16" + add_cflags "-mmacosx-version-min=10.16 -arch ${toolchain%%-*}" + add_ldflags "-mmacosx-version-min=10.16 -arch ${toolchain%%-*}" ;; *-iphonesimulator-*) add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}" diff --git a/test/resize_test.cc b/test/resize_test.cc index 65b94fa4f..c57170ff9 100644 --- a/test/resize_test.cc +++ b/test/resize_test.cc @@ -271,8 +271,8 @@ class ResizingVideoSource : public ::libvpx_test::DummyVideoSource { protected: virtual void Next() { ++frame_; - unsigned int width; - unsigned int height; + unsigned int width = 0; + unsigned int height = 0; ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height, flag_codec_, smaller_width_larger_size_); SetSize(width, height); diff --git a/test/vp9_ext_ratectrl_test.cc b/test/vp9_ext_ratectrl_test.cc index 8db0a358d..4b3693a34 100644 --- a/test/vp9_ext_ratectrl_test.cc +++ b/test/vp9_ext_ratectrl_test.cc @@ -44,7 +44,7 @@ vpx_rc_status_t rc_create_model(void *priv, EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 24000); EXPECT_EQ(ratectrl_config->frame_rate_num, 30); EXPECT_EQ(ratectrl_config->frame_rate_den, 1); - return vpx_rc_ok; + return VPX_RC_OK; } vpx_rc_status_t rc_send_firstpass_stats( @@ -57,7 +57,7 @@ vpx_rc_status_t rc_send_firstpass_stats( for (int i = 0; i < first_pass_stats->num_frames; ++i) { EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i); } - return vpx_rc_ok; + return VPX_RC_OK; } vpx_rc_status_t rc_get_encodeframe_decision( @@ -73,6 +73,8 @@ vpx_rc_status_t rc_get_encodeframe_decision( EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index); if (encode_frame_info->coding_index == 0) { + EXPECT_EQ(encode_frame_info->show_index, 0); + EXPECT_EQ(encode_frame_info->gop_index, 0); EXPECT_EQ(encode_frame_info->frame_type, 0 /*kFrameTypeKey*/); EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0], 0); // kRefFrameTypeLast @@ -83,6 +85,8 @@ vpx_rc_status_t rc_get_encodeframe_decision( } if (encode_frame_info->coding_index == 1) { + EXPECT_EQ(encode_frame_info->show_index, 4); + EXPECT_EQ(encode_frame_info->gop_index, 1); EXPECT_EQ(encode_frame_info->frame_type, 2 /*kFrameTypeAltRef*/); EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0], 1); // kRefFrameTypeLast @@ -96,10 +100,14 @@ vpx_rc_status_t rc_get_encodeframe_decision( if (encode_frame_info->coding_index >= 2 && encode_frame_info->coding_index < 5) { + // In the first group of pictures, coding_index and gop_index are equal. + EXPECT_EQ(encode_frame_info->gop_index, encode_frame_info->coding_index); EXPECT_EQ(encode_frame_info->frame_type, 1 /*kFrameTypeInter*/); } if (encode_frame_info->coding_index == 5) { + EXPECT_EQ(encode_frame_info->show_index, 4); + EXPECT_EQ(encode_frame_info->gop_index, 0); EXPECT_EQ(encode_frame_info->frame_type, 3 /*kFrameTypeOverlay*/); EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0], 1); // kRefFrameTypeLast @@ -120,7 +128,7 @@ vpx_rc_status_t rc_get_encodeframe_decision( } else { frame_decision->q_index = 100; } - return vpx_rc_ok; + return VPX_RC_OK; } vpx_rc_status_t rc_update_encodeframe_result( @@ -135,14 +143,14 @@ vpx_rc_status_t rc_update_encodeframe_result( if (toy_rate_ctrl->coding_index == kLosslessCodingIndex) { EXPECT_EQ(encode_frame_result->sse, 0); } - return vpx_rc_ok; + return VPX_RC_OK; } vpx_rc_status_t rc_delete_model(vpx_rc_model_t rate_ctrl_model) { ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model); EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber); delete toy_rate_ctrl; - return vpx_rc_ok; + return VPX_RC_OK; } class ExtRateCtrlTest : public ::libvpx_test::EncoderTest, diff --git a/test/y4m_test.cc b/test/y4m_test.cc index 46cb5cff8..5df389f52 100644 --- a/test/y4m_test.cc +++ b/test/y4m_test.cc @@ -188,4 +188,29 @@ TEST_P(Y4mVideoWriteTest, WriteTest) { INSTANTIATE_TEST_SUITE_P(C, Y4mVideoWriteTest, ::testing::ValuesIn(kY4mTestVectors)); + +static const char kY4MRegularHeader[] = + "YUV4MPEG2 W4 H4 F30:1 Ip A0:0 C420jpeg XYSCSS=420JPEG\n" + "FRAME\n" + "012345678912345601230123"; + +TEST(Y4MHeaderTest, RegularHeader) { + libvpx_test::TempOutFile f; + fwrite(kY4MRegularHeader, 1, sizeof(kY4MRegularHeader), f.file()); + fflush(f.file()); + EXPECT_EQ(0, fseek(f.file(), 0, 0)); + + y4m_input y4m; + EXPECT_EQ(y4m_input_open(&y4m, f.file(), /*skip_buffer=*/NULL, + /*num_skip=*/0, /*only_420=*/0), + 0); + EXPECT_EQ(y4m.pic_w, 4); + EXPECT_EQ(y4m.pic_h, 4); + EXPECT_EQ(y4m.fps_n, 30); + EXPECT_EQ(y4m.fps_d, 1); + EXPECT_EQ(y4m.interlace, 'p'); + EXPECT_EQ(strcmp("420jpeg", y4m.chroma_type), 0); + y4m_input_close(&y4m); +} + } // namespace diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 2b3d9564c..2f84381d2 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -343,8 +343,11 @@ static void encode_mb_row(VP8_COMP *cpi, VP8_COMMON *cm, int mb_row, const int nsync = cpi->mt_sync_range; vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync); const vpx_atomic_int *last_row_current_mb_col; - vpx_atomic_int *current_mb_col = &cpi->mt_current_mb_col[mb_row]; + vpx_atomic_int *current_mb_col = NULL; + if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) { + current_mb_col = &cpi->mt_current_mb_col[mb_row]; + } if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0 && mb_row != 0) { last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1]; } else { diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 4750f5b7b..6a21a1c18 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2464,7 +2464,12 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf, cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED; - vp9_extrc_init(&cpi->ext_ratectrl); + { + vpx_codec_err_t codec_status = vp9_extrc_init(&cpi->ext_ratectrl); + if (codec_status != VPX_CODEC_OK) { + vpx_internal_error(&cm->error, codec_status, "vp9_extrc_init() failed"); + } + } #if !CONFIG_REALTIME_ONLY if (oxcf->pass == 1) { @@ -4503,16 +4508,23 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest } #endif if (cpi->ext_ratectrl.ready) { + vpx_codec_err_t codec_status; const GF_GROUP *gf_group = &cpi->twopass.gf_group; vpx_rc_encodeframe_decision_t encode_frame_decision; FRAME_UPDATE_TYPE update_type = gf_group->update_type[gf_group->index]; const int ref_frame_flags = get_ref_frame_flags(cpi); RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES]; + const RefCntBuffer *curr_frame_buf = + get_ref_cnt_buffer(cm, cm->new_fb_idx); get_ref_frame_bufs(cpi, ref_frame_bufs); - vp9_extrc_get_encodeframe_decision( - &cpi->ext_ratectrl, cm->current_video_frame, - cm->current_frame_coding_index, update_type, ref_frame_bufs, - ref_frame_flags, &encode_frame_decision); + codec_status = vp9_extrc_get_encodeframe_decision( + &cpi->ext_ratectrl, curr_frame_buf->frame_index, + cm->current_frame_coding_index, gf_group->index, update_type, + ref_frame_bufs, ref_frame_flags, &encode_frame_decision); + if (codec_status != VPX_CODEC_OK) { + vpx_internal_error(&cm->error, codec_status, + "vp9_extrc_get_encodeframe_decision() failed"); + } q = encode_frame_decision.q_index; } @@ -5487,9 +5499,13 @@ static void encode_frame_to_data_rate( { const RefCntBuffer *coded_frame_buf = get_ref_cnt_buffer(cm, cm->new_fb_idx); - vp9_extrc_update_encodeframe_result( + vpx_codec_err_t codec_status = vp9_extrc_update_encodeframe_result( &cpi->ext_ratectrl, (*size) << 3, cpi->Source, &coded_frame_buf->buf, cm->bit_depth, cpi->oxcf.input_bit_depth); + if (codec_status != VPX_CODEC_OK) { + vpx_internal_error(&cm->error, codec_status, + "vp9_extrc_update_encodeframe_result() failed"); + } } #if CONFIG_REALTIME_ONLY (void)encode_frame_result; @@ -5680,8 +5696,13 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest, cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED; if (cpi->common.current_frame_coding_index == 0) { - vp9_extrc_send_firstpass_stats(&cpi->ext_ratectrl, - &cpi->twopass.first_pass_info); + VP9_COMMON *cm = &cpi->common; + const vpx_codec_err_t codec_status = vp9_extrc_send_firstpass_stats( + &cpi->ext_ratectrl, &cpi->twopass.first_pass_info); + if (codec_status != VPX_CODEC_OK) { + vpx_internal_error(&cm->error, codec_status, + "vp9_extrc_send_firstpass_stats() failed"); + } } #if CONFIG_MISMATCH_DEBUG mismatch_move_frame_idx_w(); @@ -7383,8 +7404,6 @@ static void accumulate_frame_tpl_stats(VP9_COMP *cpi) { // Accumulate tpl stats for each frame in the current group of picture. for (frame_idx = 1; frame_idx < gf_group->gf_group_size; ++frame_idx) { TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx]; - if (!tpl_frame->is_valid) continue; - TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr; const int tpl_stride = tpl_frame->stride; int64_t intra_cost_base = 0; @@ -7394,6 +7413,8 @@ static void accumulate_frame_tpl_stats(VP9_COMP *cpi) { int64_t mc_flow_base = 0; int row, col; + if (!tpl_frame->is_valid) continue; + for (row = 0; row < cm->mi_rows && tpl_frame->is_valid; ++row) { for (col = 0; col < cm->mi_cols; ++col) { TplDepStats *this_stats = &tpl_stats[row * tpl_stride + col]; diff --git a/vp9/encoder/vp9_ext_ratectrl.c b/vp9/encoder/vp9_ext_ratectrl.c index 94c2addd2..a27eb653b 100644 --- a/vp9/encoder/vp9_ext_ratectrl.c +++ b/vp9/encoder/vp9_ext_ratectrl.c @@ -13,31 +13,56 @@ #include "vp9/common/vp9_common.h" #include "vpx_dsp/psnr.h" -void vp9_extrc_init(EXT_RATECTRL *ext_ratectrl) { vp9_zero(*ext_ratectrl); } +vpx_codec_err_t vp9_extrc_init(EXT_RATECTRL *ext_ratectrl) { + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } + vp9_zero(*ext_ratectrl); + return VPX_CODEC_OK; +} -void vp9_extrc_create(vpx_rc_funcs_t funcs, vpx_rc_config_t ratectrl_config, - EXT_RATECTRL *ext_ratectrl) { +vpx_codec_err_t vp9_extrc_create(vpx_rc_funcs_t funcs, + vpx_rc_config_t ratectrl_config, + EXT_RATECTRL *ext_ratectrl) { + vpx_rc_status_t rc_status; vpx_rc_firstpass_stats_t *rc_firstpass_stats; + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } vp9_extrc_delete(ext_ratectrl); ext_ratectrl->funcs = funcs; ext_ratectrl->ratectrl_config = ratectrl_config; - ext_ratectrl->funcs.create_model(ext_ratectrl->funcs.priv, - &ext_ratectrl->ratectrl_config, - &ext_ratectrl->model); + rc_status = ext_ratectrl->funcs.create_model(ext_ratectrl->funcs.priv, + &ext_ratectrl->ratectrl_config, + &ext_ratectrl->model); + if (rc_status == VPX_RC_ERROR) { + return VPX_CODEC_ERROR; + } rc_firstpass_stats = &ext_ratectrl->rc_firstpass_stats; rc_firstpass_stats->num_frames = ratectrl_config.show_frame_count; rc_firstpass_stats->frame_stats = vpx_malloc(sizeof(*rc_firstpass_stats->frame_stats) * rc_firstpass_stats->num_frames); + if (rc_firstpass_stats->frame_stats == NULL) { + return VPX_CODEC_MEM_ERROR; + } ext_ratectrl->ready = 1; + return VPX_CODEC_OK; } -void vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl) { +vpx_codec_err_t vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl) { + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } if (ext_ratectrl->ready) { - ext_ratectrl->funcs.delete_model(ext_ratectrl->model); + vpx_rc_status_t rc_status = + ext_ratectrl->funcs.delete_model(ext_ratectrl->model); + if (rc_status == VPX_RC_ERROR) { + return VPX_CODEC_ERROR; + } vpx_free(ext_ratectrl->rc_firstpass_stats.frame_stats); } - vp9_extrc_init(ext_ratectrl); + return vp9_extrc_init(ext_ratectrl); } static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats, @@ -69,9 +94,13 @@ static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats, rc_frame_stats->count = stats->count; } -void vp9_extrc_send_firstpass_stats(EXT_RATECTRL *ext_ratectrl, - const FIRST_PASS_INFO *first_pass_info) { +vpx_codec_err_t vp9_extrc_send_firstpass_stats( + EXT_RATECTRL *ext_ratectrl, const FIRST_PASS_INFO *first_pass_info) { + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } if (ext_ratectrl->ready) { + vpx_rc_status_t rc_status; vpx_rc_firstpass_stats_t *rc_firstpass_stats = &ext_ratectrl->rc_firstpass_stats; int i; @@ -80,9 +109,13 @@ void vp9_extrc_send_firstpass_stats(EXT_RATECTRL *ext_ratectrl, gen_rc_firstpass_stats(&first_pass_info->stats[i], &rc_firstpass_stats->frame_stats[i]); } - ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model, - rc_firstpass_stats); + rc_status = ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model, + rc_firstpass_stats); + if (rc_status == VPX_RC_ERROR) { + return VPX_CODEC_ERROR; + } } + return VPX_CODEC_OK; } static int extrc_get_frame_type(FRAME_UPDATE_TYPE update_type) { @@ -102,39 +135,51 @@ static int extrc_get_frame_type(FRAME_UPDATE_TYPE update_type) { } } -void vp9_extrc_get_encodeframe_decision( - EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, +vpx_codec_err_t vp9_extrc_get_encodeframe_decision( + EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index, FRAME_UPDATE_TYPE update_type, RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags, vpx_rc_encodeframe_decision_t *encode_frame_decision) { + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } if (ext_ratectrl->ready) { + vpx_rc_status_t rc_status; vpx_rc_encodeframe_info_t encode_frame_info; encode_frame_info.show_index = show_index; encode_frame_info.coding_index = coding_index; + encode_frame_info.gop_index = gop_index; encode_frame_info.frame_type = extrc_get_frame_type(update_type); vp9_get_ref_frame_info(update_type, ref_frame_flags, ref_frame_bufs, encode_frame_info.ref_frame_coding_indexes, encode_frame_info.ref_frame_valid_list); - ext_ratectrl->funcs.get_encodeframe_decision( + rc_status = ext_ratectrl->funcs.get_encodeframe_decision( ext_ratectrl->model, &encode_frame_info, encode_frame_decision); + if (rc_status == VPX_RC_ERROR) { + return VPX_CODEC_ERROR; + } } + return VPX_CODEC_OK; } -void vp9_extrc_update_encodeframe_result(EXT_RATECTRL *ext_ratectrl, - int64_t bit_count, - const YV12_BUFFER_CONFIG *source_frame, - const YV12_BUFFER_CONFIG *coded_frame, - uint32_t bit_depth, - uint32_t input_bit_depth) { +vpx_codec_err_t vp9_extrc_update_encodeframe_result( + EXT_RATECTRL *ext_ratectrl, int64_t bit_count, + const YV12_BUFFER_CONFIG *source_frame, + const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth, + uint32_t input_bit_depth) { + if (ext_ratectrl == NULL) { + return VPX_CODEC_INVALID_PARAM; + } if (ext_ratectrl->ready) { PSNR_STATS psnr; + vpx_rc_status_t rc_status; vpx_rc_encodeframe_result_t encode_frame_result; encode_frame_result.bit_count = bit_count; encode_frame_result.pixel_count = - source_frame->y_width * source_frame->y_height + - 2 * source_frame->uv_width * source_frame->uv_height; + source_frame->y_crop_width * source_frame->y_crop_height + + 2 * source_frame->uv_crop_width * source_frame->uv_crop_height; #if CONFIG_VP9_HIGHBITDEPTH vpx_calc_highbd_psnr(source_frame, coded_frame, &psnr, bit_depth, input_bit_depth); @@ -144,7 +189,11 @@ void vp9_extrc_update_encodeframe_result(EXT_RATECTRL *ext_ratectrl, vpx_calc_psnr(source_frame, coded_frame, &psnr); #endif encode_frame_result.sse = psnr.sse[0]; - ext_ratectrl->funcs.update_encodeframe_result(ext_ratectrl->model, - &encode_frame_result); + rc_status = ext_ratectrl->funcs.update_encodeframe_result( + ext_ratectrl->model, &encode_frame_result); + if (rc_status == VPX_RC_ERROR) { + return VPX_CODEC_ERROR; + } } + return VPX_CODEC_OK; } diff --git a/vp9/encoder/vp9_ext_ratectrl.h b/vp9/encoder/vp9_ext_ratectrl.h index fb6cfe1ac..11e9102a6 100644 --- a/vp9/encoder/vp9_ext_ratectrl.h +++ b/vp9/encoder/vp9_ext_ratectrl.h @@ -22,27 +22,27 @@ typedef struct EXT_RATECTRL { vpx_rc_firstpass_stats_t rc_firstpass_stats; } EXT_RATECTRL; -void vp9_extrc_init(EXT_RATECTRL *ext_ratectrl); +vpx_codec_err_t vp9_extrc_init(EXT_RATECTRL *ext_ratectrl); -void vp9_extrc_create(vpx_rc_funcs_t funcs, vpx_rc_config_t ratectrl_config, - EXT_RATECTRL *ext_ratectrl); +vpx_codec_err_t vp9_extrc_create(vpx_rc_funcs_t funcs, + vpx_rc_config_t ratectrl_config, + EXT_RATECTRL *ext_ratectrl); -void vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl); +vpx_codec_err_t vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl); -void vp9_extrc_send_firstpass_stats(EXT_RATECTRL *ext_ratectrl, - const FIRST_PASS_INFO *first_pass_info); +vpx_codec_err_t vp9_extrc_send_firstpass_stats( + EXT_RATECTRL *ext_ratectrl, const FIRST_PASS_INFO *first_pass_info); -void vp9_extrc_get_encodeframe_decision( - EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, +vpx_codec_err_t vp9_extrc_get_encodeframe_decision( + EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index, FRAME_UPDATE_TYPE update_type, RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags, vpx_rc_encodeframe_decision_t *encode_frame_decision); -void vp9_extrc_update_encodeframe_result(EXT_RATECTRL *ext_ratectrl, - int64_t bit_count, - const YV12_BUFFER_CONFIG *source_frame, - const YV12_BUFFER_CONFIG *coded_frame, - uint32_t bit_depth, - uint32_t input_bit_depth); +vpx_codec_err_t vp9_extrc_update_encodeframe_result( + EXT_RATECTRL *ext_ratectrl, int64_t bit_count, + const YV12_BUFFER_CONFIG *source_frame, + const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth, + uint32_t input_bit_depth); #endif // VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_ diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index de954f757..2a9cf5289 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -1081,8 +1081,8 @@ void vp9_first_pass_encode_tile_mb_row(VP9_COMP *cpi, ThreadData *td, x->mv_limits.col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16; - // Other than for the first frame do a motion search. - if (cm->current_video_frame > 0) { + // Other than for intra-only frame do a motion search. + if (!frame_is_intra_only(cm)) { int tmp_err, motion_error, this_motion_error, raw_motion_error; // Assume 0,0 motion with no mv overhead. MV mv = { 0, 0 }, tmp_mv = { 0, 0 }; diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index afda6e203..d4eb0c669 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -765,6 +765,16 @@ static void UpdateEncodeConfig(const EncodeConfig &config, SET_STRUCT_VALUE(config, oxcf, ret, encode_breakout); SET_STRUCT_VALUE(config, oxcf, ret, enable_tpl_model); SET_STRUCT_VALUE(config, oxcf, ret, enable_auto_arf); + if (strcmp(config.name, "rc_mode") == 0) { + int rc_mode = atoi(config.value); + if (rc_mode >= VPX_VBR && rc_mode <= VPX_Q) { + oxcf->rc_mode = (enum vpx_rc_mode)rc_mode; + ret = 1; + } else { + fprintf(stderr, "Invalid rc_mode value: %d\n", rc_mode); + } + } + SET_STRUCT_VALUE(config, oxcf, ret, cq_level); if (ret == 0) { fprintf(stderr, "Ignored unsupported encode_config %s\n", config.name); } diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 380e8118f..8ec7069e8 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -281,7 +281,7 @@ struct EncodeFrameResult { std::vector<MotionVectorInfo> motion_vector_info; // A vector of the tpl stats information. // The tpl stats measure the complexity of a frame, as well as the - // informatioin propagated along the motion trajactory between frames, in + // information propagated along the motion trajectory between frames, in // the reference frame structure. // The tpl stats could be used as a more accurate spatial and temporal // complexity measure in addition to the first pass stats. @@ -361,21 +361,32 @@ class SimpleEncode { // The following configs in VP9EncoderConfig are allowed to change in this // function. See https://ffmpeg.org/ffmpeg-codecs.html#libvpx for each // config's meaning. - // Configs in VP9EncoderConfig: Equivalent configs in ffmpeg: - // 1 key_freq -g - // 2 two_pass_vbrmin_section -minrate * 100LL / bit_rate - // 3 two_pass_vbrmax_section -maxrate * 100LL / bit_rate - // 4 under_shoot_pct -undershoot-pct - // 5 over_shoot_pct -overshoot-pct - // 6 max_threads -threads - // 7 frame_parallel_decoding_mode -frame-parallel - // 8 tile_column -tile-columns - // 9 arnr_max_frames -arnr-maxframes - // 10 arnr_strength -arnr-strength - // 11 lag_in_frames -rc_lookahead - // 12 encode_breakout -static-thresh - // 13 enable_tpl_model -enable-tpl - // 14 enable_auto_arf -auto-alt-ref + // Configs in VP9EncoderConfig: Equivalent configs in ffmpeg: + // 1 key_freq -g + // 2 two_pass_vbrmin_section -minrate * 100LL / bit_rate + // 3 two_pass_vbrmax_section -maxrate * 100LL / bit_rate + // 4 under_shoot_pct -undershoot-pct + // 5 over_shoot_pct -overshoot-pct + // 6 max_threads -threads + // 7 frame_parallel_decoding_mode -frame-parallel + // 8 tile_column -tile-columns + // 9 arnr_max_frames -arnr-maxframes + // 10 arnr_strength -arnr-strength + // 11 lag_in_frames -rc_lookahead + // 12 encode_breakout -static-thresh + // 13 enable_tpl_model -enable-tpl + // 14 enable_auto_arf -auto-alt-ref + // 15 rc_mode + // Possible Settings: + // 0 - Variable Bit Rate (VPX_VBR) -b:v <bit_rate> + // 1 - Constant Bit Rate (VPX_CBR) -b:v <bit_rate> -minrate <bit_rate> + // -maxrate <bit_rate> + // two_pass_vbrmin_section == 100 i.e. bit_rate == minrate == maxrate + // two_pass_vbrmax_section == 100 + // 2 - Constrained Quality (VPX_CQ) -crf <cq_level> -b:v bit_rate + // 3 - Constant Quality (VPX_Q) -crf <cq_level> -b:v 0 + // See https://trac.ffmpeg.org/wiki/Encode/VP9 for more details. + // 16 cq_level see rc_mode for details. StatusCode SetEncodeConfig(const char *name, const char *value); // A debug function that dumps configs from VP9EncoderConfig diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index a73683dfe..ecfacfaf4 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -1744,6 +1744,7 @@ static vpx_codec_err_t ctrl_set_external_rate_control(vpx_codec_alg_priv_t *ctx, if (oxcf->pass == 2) { const FRAME_INFO *frame_info = &cpi->frame_info; vpx_rc_config_t ratectrl_config; + vpx_codec_err_t codec_status; ratectrl_config.frame_width = frame_info->frame_width; ratectrl_config.frame_height = frame_info->frame_height; @@ -1755,7 +1756,10 @@ static vpx_codec_err_t ctrl_set_external_rate_control(vpx_codec_alg_priv_t *ctx, ratectrl_config.frame_rate_num = oxcf->g_timebase.den; ratectrl_config.frame_rate_den = oxcf->g_timebase.num; - vp9_extrc_create(funcs, ratectrl_config, ext_ratectrl); + codec_status = vp9_extrc_create(funcs, ratectrl_config, ext_ratectrl); + if (codec_status != VPX_CODEC_OK) { + return codec_status; + } } return VPX_CODEC_OK; } diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h index 39b2aef62..da3609577 100644 --- a/vpx/vpx_encoder.h +++ b/vpx/vpx_encoder.h @@ -30,6 +30,7 @@ extern "C" { #endif #include "./vpx_codec.h" +#include "./vpx_ext_ratectrl.h" /*! Temporal Scalability: Maximum length of the sequence defining frame * layer membership @@ -57,7 +58,8 @@ extern "C" { * fields to structures */ #define VPX_ENCODER_ABI_VERSION \ - (14 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/ + (14 + VPX_CODEC_ABI_VERSION + \ + VPX_EXT_RATECTRL_ABI_VERSION) /**<\hideinitializer*/ /*! \brief Encoder capabilities bitfield * diff --git a/vpx/vpx_ext_ratectrl.h b/vpx/vpx_ext_ratectrl.h index 5d5a7c92d..dc4d856a8 100644 --- a/vpx/vpx_ext_ratectrl.h +++ b/vpx/vpx_ext_ratectrl.h @@ -17,77 +17,238 @@ extern "C" { #include "./vpx_integer.h" -/*!\cond - TODO(angiebird): document these structures and fields to clear doxygen - warnings.*/ +/*!\brief Current ABI version number + * + * \internal + * If this file is altered in any way that changes the ABI, this value + * must be bumped. Examples include, but are not limited to, changing + * types, removing or reassigning enums, adding/removing/rearranging + * fields to structures. + */ +#define VPX_EXT_RATECTRL_ABI_VERSION (1) +/*!\brief Abstract rate control model handler + * + * The encoder will receive the model handler from create_model() defined in + * vpx_rc_funcs_t. + */ typedef void *vpx_rc_model_t; +/*!\brief Encode frame decision made by the external rate control model + * + * The encoder will receive the decision from the external rate control model + * through get_encodeframe_decision() defined in vpx_rc_funcs_t. + */ typedef struct vpx_rc_encodeframe_decision { - int q_index; + int q_index; /**< Quantizer step index [0..255]*/ } vpx_rc_encodeframe_decision_t; +/*!\brief Information for the frame to be encoded. + * + * The encoder will send the information to external rate control model through + * get_encodeframe_decision() defined in vpx_rc_funcs_t. + * + */ typedef struct vpx_rc_encodeframe_info { + /*! + * 0: Key frame + * 1: Inter frame + * 2: Alternate reference frame + * 3: Overlay frame + * 4: Golden frame + */ int frame_type; - int show_index; - int coding_index; - int ref_frame_coding_indexes[3]; + int show_index; /**< display index, starts from zero*/ + int coding_index; /**< coding index, starts from zero*/ + /*! + * index in group of picture, starts from zero. + */ + int gop_index; + int ref_frame_coding_indexes[3]; /**< three reference frames' coding indices*/ + /*! + * The validity of the three reference frames. + * 0: Invalid + * 1: Valid + */ int ref_frame_valid_list[3]; } vpx_rc_encodeframe_info_t; +/*!\brief Frame coding result + * + * The encoder will send the result to the external rate control model through + * update_encodeframe_result() defined in vpx_rc_funcs_t. + */ typedef struct vpx_rc_encodeframe_result { - int64_t sse; - int64_t bit_count; - int64_t pixel_count; + int64_t sse; /**< sum of squared error of the reconstructed frame */ + int64_t bit_count; /**< number of bits spent on coding the frame*/ + int64_t pixel_count; /**< number of pixels in YUV planes of the frame*/ } vpx_rc_encodeframe_result_t; +/*!\brief Status returned by rate control callback functions. + */ typedef enum vpx_rc_status { - vpx_rc_ok = 0, - vpx_rc_error = 1, + VPX_RC_OK = 0, + VPX_RC_ERROR = 1, } vpx_rc_status_t; -// This is a mirror of vp9's FIRSTPASS_STATS -// Only spatial_layer_id is omitted +/*!\brief First pass frame stats + * This is a mirror of vp9's FIRSTPASS_STATS except that spatial_layer_id is + * omitted + */ typedef struct vpx_rc_frame_stats { + /*! + * Frame number in display order, if stats are for a single frame. + * No real meaning for a collection of frames. + */ double frame; + /*! + * Weight assigned to this frame (or total weight for the collection of + * frames) currently based on intra factor and brightness factor. This is used + * to distribute bits between easier and harder frames. + */ double weight; + /*! + * Intra prediction error. + */ double intra_error; + /*! + * Best of intra pred error and inter pred error using last frame as ref. + */ double coded_error; + /*! + * Best of intra pred error and inter pred error using golden frame as ref. + */ double sr_coded_error; + /*! + * Estimate the noise energy of the current frame. + */ double frame_noise_energy; + /*! + * Percentage of blocks with inter pred error < intra pred error. + */ double pcnt_inter; + /*! + * Percentage of blocks using (inter prediction and) non-zero motion vectors. + */ double pcnt_motion; + /*! + * Percentage of blocks where golden frame was better than last or intra: + * inter pred error using golden frame < inter pred error using last frame and + * inter pred error using golden frame < intra pred error + */ double pcnt_second_ref; + /*! + * Percentage of blocks where intra and inter prediction errors were very + * close. + */ double pcnt_neutral; + /*! + * Percentage of blocks that have intra error < inter error and inter error < + * LOW_I_THRESH + * - bit_depth 8: LOW_I_THRESH = 24000 + * - bit_depth 10: LOW_I_THRESH = 24000 << 4 + * - bit_depth 12: LOW_I_THRESH = 24000 << 8 + */ double pcnt_intra_low; + /*! + * Percentage of blocks that have intra error < inter error and intra error < + * LOW_I_THRESH but inter error >= LOW_I_THRESH LOW_I_THRESH + * - bit_depth 8: LOW_I_THRESH = 24000 + * - bit_depth 10: LOW_I_THRESH = 24000 << 4 + * - bit_depth 12: LOW_I_THRESH = 24000 << 8 + */ double pcnt_intra_high; + /*! + * Percentage of blocks that have almost no intra error residual + * (i.e. are in effect completely flat and untextured in the intra + * domain). In natural videos this is uncommon, but it is much more + * common in animations, graphics and screen content, so may be used + * as a signal to detect these types of content. + */ double intra_skip_pct; + /*! + * Percentage of blocks that have intra error < SMOOTH_INTRA_THRESH + * - bit_depth 8: SMOOTH_INTRA_THRESH = 4000 + * - bit_depth 10: SMOOTH_INTRA_THRESH = 4000 << 4 + * - bit_depth 12: SMOOTH_INTRA_THRESH = 4000 << 8 + */ double intra_smooth_pct; + /*! + * Image mask rows top and bottom. + */ double inactive_zone_rows; + /*! + * Image mask columns at left and right edges. + */ double inactive_zone_cols; + /*! + * Mean of row motion vectors. + */ double MVr; + /*! + * Mean of absolute value of row motion vectors. + */ double mvr_abs; + /*! + * Mean of column motion vectors. + */ double MVc; + /*! + * Mean of absolute value of column motion vectors. + */ double mvc_abs; + /*! + * Variance of row motion vectors. + */ double MVrv; + /*! + * Variance of column motion vectors. + */ double MVcv; + /*! + * Value in range [-1,1] indicating fraction of row and column motion vectors + * that point inwards (negative MV value) or outwards (positive MV value). + * For example, value of 1 indicates, all row/column MVs are inwards. + */ double mv_in_out_count; + /*! + * Duration of the frame / collection of frames. + */ double duration; + /*! + * 1.0 if stats are for a single frame, or + * number of frames whose stats are accumulated. + */ double count; } vpx_rc_frame_stats_t; +/*!\brief Collection of first pass frame stats + */ typedef struct vpx_rc_firstpass_stats { + /*! + * Pointer to first pass frame stats. + * The pointed array of vpx_rc_frame_stats_t should have length equal to + * number of show frames in the video. + */ vpx_rc_frame_stats_t *frame_stats; + /*! + * Number of show frames in the video. + */ int num_frames; } vpx_rc_firstpass_stats_t; +/*!\brief Encode config sent to external rate control model + */ typedef struct vpx_rc_config { - int frame_width; - int frame_height; - int show_frame_count; + int frame_width; /**< frame width */ + int frame_height; /**< frame height */ + int show_frame_count; /**< number of visible frames in the video */ + /*! + * Target bitrate in kilobytes per second + */ int target_bitrate_kbps; - int frame_rate_num; - int frame_rate_den; + int frame_rate_num; /**< numerator of frame rate */ + int frame_rate_den; /**< denominator of frame rate */ } vpx_rc_config_t; /*!\brief Create an external rate control model callback prototype @@ -152,19 +313,39 @@ typedef vpx_rc_status_t (*vpx_rc_update_encodeframe_result_cb_fn_t)( typedef vpx_rc_status_t (*vpx_rc_delete_model_cb_fn_t)( vpx_rc_model_t rate_ctrl_model); +/*!\brief Callback function set for external rate control. + * + * The user can enable external rate control by registering + * a set of callback functions with the codec control flag + * VP9E_SET_EXTERNAL_RATE_CONTROL. + */ typedef struct vpx_rc_funcs { + /*! + * Create an external rate control model. + */ vpx_rc_create_model_cb_fn_t create_model; + /*! + * Send first pass stats to the external rate control model. + */ vpx_rc_send_firstpass_stats_cb_fn_t send_firstpass_stats; + /*! + * Get encodeframe decision from the external rate control model. + */ vpx_rc_get_encodeframe_decision_cb_fn_t get_encodeframe_decision; + /*! + * Update encodeframe result to the external rate control model. + */ vpx_rc_update_encodeframe_result_cb_fn_t update_encodeframe_result; + /*! + * Delete the external rate control model. + */ vpx_rc_delete_model_cb_fn_t delete_model; + /*! + * Private data for the external rate control model. + */ void *priv; } vpx_rc_funcs_t; -/*!\endcond - TODO(angiebird): document these structures and fields to clear doxygen - warnings.*/ - #ifdef __cplusplus } // extern "C" #endif diff --git a/vpx_dsp/arm/highbd_loopfilter_neon.c b/vpx_dsp/arm/highbd_loopfilter_neon.c index 5530c6425..8d6e8acc4 100644 --- a/vpx_dsp/arm/highbd_loopfilter_neon.c +++ b/vpx_dsp/arm/highbd_loopfilter_neon.c @@ -661,6 +661,17 @@ void vpx_highbd_lpf_vertical_8_dual_neon( vpx_highbd_lpf_vertical_8_neon(s + 8 * p, p, blimit1, limit1, thresh1, bd); } +// Quiet warnings of the form: 'vpx_dsp/arm/highbd_loopfilter_neon.c|675 col 67| +// warning: 'oq1' may be used uninitialized in this function +// [-Wmaybe-uninitialized]', for oq1-op1. Without reworking the code or adding +// an additional branch this warning cannot be silenced otherwise. The +// loopfilter is only called when needed for a block so these output pixels +// will be set. +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + static void lpf_horizontal_16_kernel(uint16_t *s, int p, const uint16x8_t blimit_vec, const uint16x8_t limit_vec, @@ -723,6 +734,10 @@ static void lpf_vertical_16_kernel(uint16_t *s, int p, } } +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + void vpx_highbd_lpf_horizontal_16_neon(uint16_t *s, int p, const uint8_t *blimit, const uint8_t *limit, diff --git a/vpx_dsp/arm/loopfilter_neon.c b/vpx_dsp/arm/loopfilter_neon.c index 7419cea02..c54e58823 100644 --- a/vpx_dsp/arm/loopfilter_neon.c +++ b/vpx_dsp/arm/loopfilter_neon.c @@ -975,6 +975,17 @@ FUN_LPF_16_KERNEL(_, 8) // lpf_16_kernel FUN_LPF_16_KERNEL(_dual_, 16) // lpf_16_dual_kernel #undef FUN_LPF_16_KERNEL +// Quiet warnings of the form: 'vpx_dsp/arm/loopfilter_neon.c|981 col 42| +// warning: 'oq1' may be used uninitialized in this function +// [-Wmaybe-uninitialized]', for oq1-op1. Without reworking the code or adding +// an additional branch this warning cannot be silenced otherwise. The +// loopfilter is only called when needed for a block so these output pixels +// will be set. +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + void vpx_lpf_horizontal_16_neon(uint8_t *s, int p, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh) { uint8x8_t p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7, op6, @@ -1090,3 +1101,7 @@ void vpx_lpf_vertical_16_dual_neon(uint8_t *s, int p, const uint8_t *blimit, vget_high_u8(oq0), vget_high_u8(oq1)); } } + +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__) +#pragma GCC diagnostic pop +#endif @@ -1636,6 +1636,7 @@ int main(int argc, const char **argv_) { int res = 0; memset(&input, 0, sizeof(input)); + memset(&raw, 0, sizeof(raw)); exec_name = argv_[0]; /* Setup default input stream settings */ @@ -1781,14 +1782,10 @@ int main(int argc, const char **argv_) { FOREACH_STREAM(show_stream_config(stream, &global, &input)); if (pass == (global.pass ? global.pass - 1 : 0)) { - if (input.file_type == FILE_TYPE_Y4M) - /*The Y4M reader does its own allocation. - Just initialize this here to avoid problems if we never read any - frames.*/ - memset(&raw, 0, sizeof(raw)); - else + // The Y4M reader does its own allocation. + if (input.file_type != FILE_TYPE_Y4M) { vpx_img_alloc(&raw, input.fmt, input.width, input.height, 32); - + } FOREACH_STREAM(stream->rate_hist = init_rate_histogram( &stream->config.cfg, &global.framerate)); } diff --git a/y4minput.c b/y4minput.c index 007bd9971..68000768c 100644 --- a/y4minput.c +++ b/y4minput.c @@ -10,6 +10,7 @@ * Based on code from the OggTheora software codec source code, * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors. */ +#include <assert.h> #include <errno.h> #include <stdlib.h> #include <string.h> @@ -784,277 +785,294 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst, (void)_aux; } -int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip, - int only_420) { +static const char TAG[] = "YUV4MPEG2"; + +int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer, + int num_skip, int only_420) { + // File must start with |TAG|. + char tag_buffer[9]; // 9 == strlen(TAG) char buffer[80] = { 0 }; int ret; int i; + // Read as much as possible from |skip_buffer|, which were characters + // that were previously read from the file to do input-type detection. + assert(num_skip >= 0 && num_skip <= 8); + if (num_skip > 0) { + memcpy(tag_buffer, skip_buffer, num_skip); + } + // Start reading from the file now that the |skip_buffer| is depleted. + if (!file_read(tag_buffer + num_skip, 9 - num_skip, file)) { + return -1; + } + if (memcmp(TAG, tag_buffer, 9) != 0) { + fprintf(stderr, "Error parsing header: must start with %s\n", TAG); + return -1; + } + // Next character must be a space. + if (!file_read(buffer, 1, file) || buffer[0] != ' ') { + fprintf(stderr, "Error parsing header: space must follow %s\n", TAG); + return -1; + } /*Read until newline, or 80 cols, whichever happens first.*/ for (i = 0; i < 79; i++) { - if (_nskip > 0) { - buffer[i] = *_skip++; - _nskip--; - } else { - if (!file_read(buffer + i, 1, _fin)) return -1; - } + if (!file_read(buffer + i, 1, file)) return -1; if (buffer[i] == '\n') break; } /*We skipped too much header data.*/ - if (_nskip > 0) return -1; if (i == 79) { - fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n"); + fprintf(stderr, "Error parsing header; not a YUV4MPEG2 file?\n"); return -1; } buffer[i] = '\0'; - if (memcmp(buffer, "YUV4MPEG", 8)) { - fprintf(stderr, "Incomplete magic for YUV4MPEG file.\n"); - return -1; - } - if (buffer[8] != '2') { - fprintf(stderr, "Incorrect YUV input file version; YUV4MPEG2 required.\n"); - } - ret = y4m_parse_tags(_y4m, buffer + 5); + ret = y4m_parse_tags(y4m_ctx, buffer); if (ret < 0) { fprintf(stderr, "Error parsing YUV4MPEG2 header.\n"); return ret; } - if (_y4m->interlace == '?') { + if (y4m_ctx->interlace == '?') { fprintf(stderr, "Warning: Input video interlacing format unknown; " "assuming progressive scan.\n"); - } else if (_y4m->interlace != 'p') { + } else if (y4m_ctx->interlace != 'p') { fprintf(stderr, "Input video is interlaced; " "Only progressive scan handled.\n"); return -1; } - _y4m->vpx_fmt = VPX_IMG_FMT_I420; - _y4m->bps = 12; - _y4m->bit_depth = 8; - if (strcmp(_y4m->chroma_type, "420") == 0 || - strcmp(_y4m->chroma_type, "420jpeg") == 0) { - _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = - _y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I420; + y4m_ctx->bps = 12; + y4m_ctx->bit_depth = 8; + y4m_ctx->aux_buf = NULL; + y4m_ctx->dst_buf = NULL; + if (strcmp(y4m_ctx->chroma_type, "420") == 0 || + strcmp(y4m_ctx->chroma_type, "420jpeg") == 0) { + y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v = + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = + y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2); /* Natively supported: no conversion required. */ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; - } else if (strcmp(_y4m->chroma_type, "420p10") == 0) { - _y4m->src_c_dec_h = 2; - _y4m->dst_c_dec_h = 2; - _y4m->src_c_dec_v = 2; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = - 2 * (_y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2)); + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; + } else if (strcmp(y4m_ctx->chroma_type, "420p10") == 0) { + y4m_ctx->src_c_dec_h = 2; + y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 2; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = + 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2)); /* Natively supported: no conversion required. */ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; - _y4m->bit_depth = 10; - _y4m->bps = 15; - _y4m->vpx_fmt = VPX_IMG_FMT_I42016; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; + y4m_ctx->bit_depth = 10; + y4m_ctx->bps = 15; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016; if (only_420) { fprintf(stderr, "Unsupported conversion from 420p10 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "420p12") == 0) { - _y4m->src_c_dec_h = 2; - _y4m->dst_c_dec_h = 2; - _y4m->src_c_dec_v = 2; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = - 2 * (_y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2)); + } else if (strcmp(y4m_ctx->chroma_type, "420p12") == 0) { + y4m_ctx->src_c_dec_h = 2; + y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 2; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = + 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2)); /* Natively supported: no conversion required. */ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; - _y4m->bit_depth = 12; - _y4m->bps = 18; - _y4m->vpx_fmt = VPX_IMG_FMT_I42016; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; + y4m_ctx->bit_depth = 12; + y4m_ctx->bps = 18; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42016; if (only_420) { fprintf(stderr, "Unsupported conversion from 420p12 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) { - _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + } else if (strcmp(y4m_ctx->chroma_type, "420mpeg2") == 0) { + y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v = + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first.*/ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = - 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); - _y4m->convert = y4m_convert_42xmpeg2_42xjpeg; - } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) { - _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = + 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2); + y4m_ctx->convert = y4m_convert_42xmpeg2_42xjpeg; + } else if (strcmp(y4m_ctx->chroma_type, "420paldv") == 0) { + y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_v = + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first. We need to make two filter passes, so we need some extra space in the aux buffer.*/ - _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); - _y4m->aux_buf_read_sz = - 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); - _y4m->convert = y4m_convert_42xpaldv_42xjpeg; - } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) { - _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2; - _y4m->src_c_dec_v = 1; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + y4m_ctx->aux_buf_sz = + 3 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2); + y4m_ctx->aux_buf_read_sz = + 2 * ((y4m_ctx->pic_w + 1) / 2) * ((y4m_ctx->pic_h + 1) / 2); + y4m_ctx->convert = y4m_convert_42xpaldv_42xjpeg; + } else if (strcmp(y4m_ctx->chroma_type, "422jpeg") == 0) { + y4m_ctx->src_c_dec_h = y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first.*/ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = - 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; - _y4m->convert = y4m_convert_422jpeg_420jpeg; - } else if (strcmp(_y4m->chroma_type, "422") == 0) { - _y4m->src_c_dec_h = 2; - _y4m->src_c_dec_v = 1; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = + 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; + y4m_ctx->convert = y4m_convert_422jpeg_420jpeg; + } else if (strcmp(y4m_ctx->chroma_type, "422") == 0) { + y4m_ctx->src_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 1; if (only_420) { - _y4m->dst_c_dec_h = 2; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first. We need to make two filter passes, so we need some extra space in the aux buffer.*/ - _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; - _y4m->aux_buf_sz = - _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; - _y4m->convert = y4m_convert_422_420jpeg; + y4m_ctx->aux_buf_read_sz = + 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz + + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; + y4m_ctx->convert = y4m_convert_422_420jpeg; } else { - _y4m->vpx_fmt = VPX_IMG_FMT_I422; - _y4m->bps = 16; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = - _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I422; + y4m_ctx->bps = 16; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = + y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; /*Natively supported: no conversion required.*/ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; } - } else if (strcmp(_y4m->chroma_type, "422p10") == 0) { - _y4m->src_c_dec_h = 2; - _y4m->src_c_dec_v = 1; - _y4m->vpx_fmt = VPX_IMG_FMT_I42216; - _y4m->bps = 20; - _y4m->bit_depth = 10; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h); - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + } else if (strcmp(y4m_ctx->chroma_type, "422p10") == 0) { + y4m_ctx->src_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216; + y4m_ctx->bps = 20; + y4m_ctx->bit_depth = 10; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = + 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h); + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; if (only_420) { fprintf(stderr, "Unsupported conversion from 422p10 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "422p12") == 0) { - _y4m->src_c_dec_h = 2; - _y4m->src_c_dec_v = 1; - _y4m->vpx_fmt = VPX_IMG_FMT_I42216; - _y4m->bps = 24; - _y4m->bit_depth = 12; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h); - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + } else if (strcmp(y4m_ctx->chroma_type, "422p12") == 0) { + y4m_ctx->src_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I42216; + y4m_ctx->bps = 24; + y4m_ctx->bit_depth = 12; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = + 2 * (y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h); + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; if (only_420) { fprintf(stderr, "Unsupported conversion from 422p12 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "411") == 0) { - _y4m->src_c_dec_h = 4; - _y4m->dst_c_dec_h = 2; - _y4m->src_c_dec_v = 1; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + } else if (strcmp(y4m_ctx->chroma_type, "411") == 0) { + y4m_ctx->src_c_dec_h = 4; + y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first. We need to make two filter passes, so we need some extra space in the aux buffer.*/ - _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h; - _y4m->aux_buf_sz = - _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; - _y4m->convert = y4m_convert_411_420jpeg; + y4m_ctx->aux_buf_read_sz = 2 * ((y4m_ctx->pic_w + 3) / 4) * y4m_ctx->pic_h; + y4m_ctx->aux_buf_sz = + y4m_ctx->aux_buf_read_sz + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; + y4m_ctx->convert = y4m_convert_411_420jpeg; fprintf(stderr, "Unsupported conversion from yuv 411\n"); return -1; - } else if (strcmp(_y4m->chroma_type, "444") == 0) { - _y4m->src_c_dec_h = 1; - _y4m->src_c_dec_v = 1; + } else if (strcmp(y4m_ctx->chroma_type, "444") == 0) { + y4m_ctx->src_c_dec_h = 1; + y4m_ctx->src_c_dec_v = 1; if (only_420) { - _y4m->dst_c_dec_h = 2; - _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + y4m_ctx->dst_c_dec_h = 2; + y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*Chroma filter required: read into the aux buf first. We need to make two filter passes, so we need some extra space in the aux buffer.*/ - _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h; - _y4m->aux_buf_sz = - _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; - _y4m->convert = y4m_convert_444_420jpeg; + y4m_ctx->aux_buf_read_sz = 2 * y4m_ctx->pic_w * y4m_ctx->pic_h; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz + + ((y4m_ctx->pic_w + 1) / 2) * y4m_ctx->pic_h; + y4m_ctx->convert = y4m_convert_444_420jpeg; } else { - _y4m->vpx_fmt = VPX_IMG_FMT_I444; - _y4m->bps = 24; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I444; + y4m_ctx->bps = 24; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = 3 * y4m_ctx->pic_w * y4m_ctx->pic_h; /*Natively supported: no conversion required.*/ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; } - } else if (strcmp(_y4m->chroma_type, "444p10") == 0) { - _y4m->src_c_dec_h = 1; - _y4m->src_c_dec_v = 1; - _y4m->vpx_fmt = VPX_IMG_FMT_I44416; - _y4m->bps = 30; - _y4m->bit_depth = 10; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h; - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + } else if (strcmp(y4m_ctx->chroma_type, "444p10") == 0) { + y4m_ctx->src_c_dec_h = 1; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416; + y4m_ctx->bps = 30; + y4m_ctx->bit_depth = 10; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; if (only_420) { fprintf(stderr, "Unsupported conversion from 444p10 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "444p12") == 0) { - _y4m->src_c_dec_h = 1; - _y4m->src_c_dec_v = 1; - _y4m->vpx_fmt = VPX_IMG_FMT_I44416; - _y4m->bps = 36; - _y4m->bit_depth = 12; - _y4m->dst_c_dec_h = _y4m->src_c_dec_h; - _y4m->dst_c_dec_v = _y4m->src_c_dec_v; - _y4m->dst_buf_read_sz = 2 * 3 * _y4m->pic_w * _y4m->pic_h; - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_null; + } else if (strcmp(y4m_ctx->chroma_type, "444p12") == 0) { + y4m_ctx->src_c_dec_h = 1; + y4m_ctx->src_c_dec_v = 1; + y4m_ctx->vpx_fmt = VPX_IMG_FMT_I44416; + y4m_ctx->bps = 36; + y4m_ctx->bit_depth = 12; + y4m_ctx->dst_c_dec_h = y4m_ctx->src_c_dec_h; + y4m_ctx->dst_c_dec_v = y4m_ctx->src_c_dec_v; + y4m_ctx->dst_buf_read_sz = 2 * 3 * y4m_ctx->pic_w * y4m_ctx->pic_h; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_null; if (only_420) { fprintf(stderr, "Unsupported conversion from 444p12 to 420jpeg\n"); return -1; } - } else if (strcmp(_y4m->chroma_type, "mono") == 0) { - _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0; - _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2; - _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; + } else if (strcmp(y4m_ctx->chroma_type, "mono") == 0) { + y4m_ctx->src_c_dec_h = y4m_ctx->src_c_dec_v = 0; + y4m_ctx->dst_c_dec_h = y4m_ctx->dst_c_dec_v = 2; + y4m_ctx->dst_buf_read_sz = y4m_ctx->pic_w * y4m_ctx->pic_h; /*No extra space required, but we need to clear the chroma planes.*/ - _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; - _y4m->convert = y4m_convert_mono_420jpeg; + y4m_ctx->aux_buf_sz = y4m_ctx->aux_buf_read_sz = 0; + y4m_ctx->convert = y4m_convert_mono_420jpeg; } else { - fprintf(stderr, "Unknown chroma sampling type: %s\n", _y4m->chroma_type); + fprintf(stderr, "Unknown chroma sampling type: %s\n", y4m_ctx->chroma_type); return -1; } /*The size of the final frame buffers is always computed from the destination chroma decimation type.*/ - _y4m->dst_buf_sz = - _y4m->pic_w * _y4m->pic_h + - 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) * - ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v); - if (_y4m->bit_depth == 8) - _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz); + y4m_ctx->dst_buf_sz = + y4m_ctx->pic_w * y4m_ctx->pic_h + + 2 * ((y4m_ctx->pic_w + y4m_ctx->dst_c_dec_h - 1) / y4m_ctx->dst_c_dec_h) * + ((y4m_ctx->pic_h + y4m_ctx->dst_c_dec_v - 1) / y4m_ctx->dst_c_dec_v); + if (y4m_ctx->bit_depth == 8) + y4m_ctx->dst_buf = (unsigned char *)malloc(y4m_ctx->dst_buf_sz); else - _y4m->dst_buf = (unsigned char *)malloc(2 * _y4m->dst_buf_sz); + y4m_ctx->dst_buf = (unsigned char *)malloc(2 * y4m_ctx->dst_buf_sz); - if (_y4m->aux_buf_sz > 0) - _y4m->aux_buf = (unsigned char *)malloc(_y4m->aux_buf_sz); + if (y4m_ctx->aux_buf_sz > 0) + y4m_ctx->aux_buf = (unsigned char *)malloc(y4m_ctx->aux_buf_sz); return 0; } diff --git a/y4minput.h b/y4minput.h index a4a8b18dc..573750d74 100644 --- a/y4minput.h +++ b/y4minput.h @@ -56,8 +56,16 @@ struct y4m_input { unsigned int bit_depth; }; -int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip, - int only_420); +/** + * Open the input file, treating it as Y4M. |y4m_ctx| is filled in after + * reading it. The |skip_buffer| indicates bytes that were previously read + * from |file|, to do input-type detection; this buffer will be read before + * the |file| is read. It is of size |num_skip|, which *must* be 8 or less. + * + * Returns 0 on success, -1 on failure. + */ +int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer, + int num_skip, int only_420); void y4m_input_close(y4m_input *_y4m); int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img); |