Merge "Allow larger encoder configurations."
This commit is contained in:
Коммит
a79db92c07
|
@ -140,6 +140,12 @@ class Encoder {
|
|||
}
|
||||
#endif
|
||||
|
||||
void Config(const vpx_codec_enc_cfg_t *cfg) {
|
||||
const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
|
||||
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
|
||||
cfg_ = *cfg;
|
||||
}
|
||||
|
||||
void set_deadline(unsigned long deadline) {
|
||||
deadline_ = deadline;
|
||||
}
|
||||
|
|
|
@ -261,9 +261,115 @@ TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
|
|||
}
|
||||
}
|
||||
|
||||
vpx_img_fmt_t CspForFrameNumber(int frame) {
|
||||
if (frame < 10)
|
||||
return VPX_IMG_FMT_I420;
|
||||
if (frame < 20)
|
||||
return VPX_IMG_FMT_I444;
|
||||
return VPX_IMG_FMT_I420;
|
||||
}
|
||||
|
||||
class ResizeCspTest : public ResizeTest {
|
||||
protected:
|
||||
#if WRITE_COMPRESSED_STREAM
|
||||
ResizeCspTest()
|
||||
: ResizeTest(),
|
||||
frame0_psnr_(0.0),
|
||||
outfile_(NULL),
|
||||
out_frames_(0) {}
|
||||
#else
|
||||
ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
|
||||
#endif
|
||||
|
||||
virtual ~ResizeCspTest() {}
|
||||
|
||||
virtual void BeginPassHook(unsigned int /*pass*/) {
|
||||
#if WRITE_COMPRESSED_STREAM
|
||||
outfile_ = fopen("vp91-2-05-cspchape.ivf", "wb");
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void EndPassHook() {
|
||||
#if WRITE_COMPRESSED_STREAM
|
||||
if (outfile_) {
|
||||
if (!fseek(outfile_, 0, SEEK_SET))
|
||||
write_ivf_file_header(&cfg_, out_frames_, outfile_);
|
||||
fclose(outfile_);
|
||||
outfile_ = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
|
||||
libvpx_test::Encoder *encoder) {
|
||||
if (CspForFrameNumber(video->frame()) != VPX_IMG_FMT_I420 &&
|
||||
cfg_.g_profile != 1) {
|
||||
cfg_.g_profile = 1;
|
||||
encoder->Config(&cfg_);
|
||||
}
|
||||
if (CspForFrameNumber(video->frame()) == VPX_IMG_FMT_I420 &&
|
||||
cfg_.g_profile != 0) {
|
||||
cfg_.g_profile = 0;
|
||||
encoder->Config(&cfg_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
if (!frame0_psnr_)
|
||||
frame0_psnr_ = pkt->data.psnr.psnr[0];
|
||||
EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
|
||||
}
|
||||
|
||||
#if WRITE_COMPRESSED_STREAM
|
||||
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
|
||||
++out_frames_;
|
||||
|
||||
// Write initial file header if first frame.
|
||||
if (pkt->data.frame.pts == 0)
|
||||
write_ivf_file_header(&cfg_, 0, outfile_);
|
||||
|
||||
// Write frame header and data.
|
||||
write_ivf_frame_header(pkt, outfile_);
|
||||
(void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
|
||||
}
|
||||
#endif
|
||||
|
||||
double frame0_psnr_;
|
||||
#if WRITE_COMPRESSED_STREAM
|
||||
FILE *outfile_;
|
||||
unsigned int out_frames_;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ResizingCspVideoSource : public ::libvpx_test::DummyVideoSource {
|
||||
public:
|
||||
ResizingCspVideoSource() {
|
||||
SetSize(kInitialWidth, kInitialHeight);
|
||||
limit_ = 30;
|
||||
}
|
||||
|
||||
virtual ~ResizingCspVideoSource() {}
|
||||
|
||||
protected:
|
||||
virtual void Next() {
|
||||
++frame_;
|
||||
SetImageFormat(CspForFrameNumber(frame_));
|
||||
FillFrame();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(ResizeCspTest, TestResizeCspWorks) {
|
||||
ResizingCspVideoSource video;
|
||||
cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
|
||||
cfg_.g_lag_in_frames = 0;
|
||||
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
|
||||
}
|
||||
|
||||
VP8_INSTANTIATE_TEST_CASE(ResizeTest, ONE_PASS_TEST_MODES);
|
||||
VP9_INSTANTIATE_TEST_CASE(ResizeTest,
|
||||
::testing::Values(::libvpx_test::kRealTime));
|
||||
VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
|
||||
::testing::Values(::libvpx_test::kOnePassBest));
|
||||
VP9_INSTANTIATE_TEST_CASE(ResizeCspTest,
|
||||
::testing::Values(::libvpx_test::kRealTime));
|
||||
} // namespace
|
||||
|
|
|
@ -134,8 +134,13 @@ class VideoSource {
|
|||
|
||||
class DummyVideoSource : public VideoSource {
|
||||
public:
|
||||
DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) {
|
||||
SetSize(80, 64);
|
||||
DummyVideoSource()
|
||||
: img_(NULL),
|
||||
limit_(100),
|
||||
width_(80),
|
||||
height_(64),
|
||||
format_(VPX_IMG_FMT_I420) {
|
||||
ReallocImage();
|
||||
}
|
||||
|
||||
virtual ~DummyVideoSource() { vpx_img_free(img_); }
|
||||
|
@ -174,23 +179,35 @@ class DummyVideoSource : public VideoSource {
|
|||
|
||||
void SetSize(unsigned int width, unsigned int height) {
|
||||
if (width != width_ || height != height_) {
|
||||
vpx_img_free(img_);
|
||||
img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, width, height, 32);
|
||||
raw_sz_ = ((img_->w + 31) & ~31) * img_->h * 3 / 2;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
ReallocImage();
|
||||
}
|
||||
}
|
||||
|
||||
void SetImageFormat(vpx_img_fmt_t format) {
|
||||
if (format_ != format) {
|
||||
format_ = format;
|
||||
ReallocImage();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void FillFrame() { if (img_) memset(img_->img_data, 0, raw_sz_); }
|
||||
|
||||
void ReallocImage() {
|
||||
vpx_img_free(img_);
|
||||
img_ = vpx_img_alloc(NULL, format_, width_, height_, 32);
|
||||
raw_sz_ = ((img_->w + 31) & ~31) * img_->h * img_->bps / 8;
|
||||
}
|
||||
|
||||
vpx_image_t *img_;
|
||||
size_t raw_sz_;
|
||||
unsigned int limit_;
|
||||
unsigned int frame_;
|
||||
unsigned int width_;
|
||||
unsigned int height_;
|
||||
vpx_img_fmt_t format_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -469,8 +469,9 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
|
|||
VP9_COMMON *cm = &cpi->common;
|
||||
const VP9EncoderConfig *oxcf = &cpi->oxcf;
|
||||
|
||||
cpi->lookahead = vp9_lookahead_init(oxcf->width, oxcf->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
if (!cpi->lookahead)
|
||||
cpi->lookahead = vp9_lookahead_init(oxcf->width, oxcf->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
|
@ -1314,11 +1315,11 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
|
|||
cm->height = cpi->oxcf.height;
|
||||
|
||||
if (cpi->initial_width) {
|
||||
// Increasing the size of the frame beyond the first seen frame, or some
|
||||
// otherwise signaled maximum size, is not supported.
|
||||
// TODO(jkoleszar): exit gracefully.
|
||||
assert(cm->width <= cpi->initial_width);
|
||||
assert(cm->height <= cpi->initial_height);
|
||||
if (cm->width > cpi->initial_width || cm->height > cpi->initial_height) {
|
||||
vp9_free_context_buffers(cm);
|
||||
vp9_alloc_context_buffers(cm, cm->width, cm->height);
|
||||
cpi->initial_width = cpi->initial_height = 0;
|
||||
}
|
||||
}
|
||||
update_frame_size(cpi);
|
||||
|
||||
|
@ -3441,7 +3442,11 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
|
|||
#endif
|
||||
vpx_usec_timer_start(&timer);
|
||||
|
||||
if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, frame_flags))
|
||||
if (vp9_lookahead_push(cpi->lookahead, sd, time_stamp, end_time,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
frame_flags))
|
||||
res = -1;
|
||||
vpx_usec_timer_mark(&timer);
|
||||
cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
|
||||
|
|
|
@ -90,19 +90,40 @@ struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
|
|||
#define USE_PARTIAL_COPY 0
|
||||
|
||||
int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
|
||||
int64_t ts_start, int64_t ts_end, unsigned int flags) {
|
||||
int64_t ts_start, int64_t ts_end,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
unsigned int flags) {
|
||||
struct lookahead_entry *buf;
|
||||
#if USE_PARTIAL_COPY
|
||||
int row, col, active_end;
|
||||
int mb_rows = (src->y_height + 15) >> 4;
|
||||
int mb_cols = (src->y_width + 15) >> 4;
|
||||
#endif
|
||||
int width = src->y_crop_width;
|
||||
int height = src->y_crop_height;
|
||||
int uv_width = src->uv_crop_width;
|
||||
int uv_height = src->uv_crop_height;
|
||||
int subsampling_x = src->subsampling_x;
|
||||
int subsampling_y = src->subsampling_y;
|
||||
int larger_dimensions, new_dimensions;
|
||||
|
||||
if (ctx->sz + 1 + MAX_PRE_FRAMES > ctx->max_sz)
|
||||
return 1;
|
||||
ctx->sz++;
|
||||
buf = pop(ctx, &ctx->write_idx);
|
||||
|
||||
new_dimensions = width != buf->img.y_crop_width ||
|
||||
height != buf->img.y_crop_height ||
|
||||
uv_width != buf->img.uv_crop_width ||
|
||||
uv_height != buf->img.uv_crop_height;
|
||||
larger_dimensions = width > buf->img.y_width ||
|
||||
height > buf->img.y_height ||
|
||||
uv_width > buf->img.uv_width ||
|
||||
uv_height > buf->img.uv_height;
|
||||
assert(!larger_dimensions || new_dimensions);
|
||||
|
||||
#if USE_PARTIAL_COPY
|
||||
// TODO(jkoleszar): This is disabled for now, as
|
||||
// vp9_copy_and_extend_frame_with_rect is not subsampling/alpha aware.
|
||||
|
@ -111,7 +132,7 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
|
|||
// 1. Lookahead queue has has size of 1.
|
||||
// 2. Active map is provided.
|
||||
// 3. This is not a key frame, golden nor altref frame.
|
||||
if (ctx->max_sz == 1 && active_map && !flags) {
|
||||
if (!new_dimensions && ctx->max_sz == 1 && active_map && !flags) {
|
||||
for (row = 0; row < mb_rows; ++row) {
|
||||
col = 0;
|
||||
|
||||
|
@ -147,11 +168,32 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
|
|||
active_map += mb_cols;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
if (larger_dimensions) {
|
||||
YV12_BUFFER_CONFIG new_img;
|
||||
memset(&new_img, 0, sizeof(new_img));
|
||||
if (vp9_alloc_frame_buffer(&new_img,
|
||||
width, height, subsampling_x, subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS,
|
||||
0))
|
||||
return 1;
|
||||
vp9_free_frame_buffer(&buf->img);
|
||||
buf->img = new_img;
|
||||
} else if (new_dimensions) {
|
||||
buf->img.y_crop_width = src->y_crop_width;
|
||||
buf->img.y_crop_height = src->y_crop_height;
|
||||
buf->img.uv_crop_width = src->uv_crop_width;
|
||||
buf->img.uv_crop_height = src->uv_crop_height;
|
||||
buf->img.subsampling_x = src->subsampling_x;
|
||||
buf->img.subsampling_y = src->subsampling_y;
|
||||
}
|
||||
// Partial copy not implemented yet
|
||||
vp9_copy_and_extend_frame(src, &buf->img);
|
||||
#if USE_PARTIAL_COPY
|
||||
}
|
||||
#else
|
||||
// Partial copy not implemented yet
|
||||
vp9_copy_and_extend_frame(src, &buf->img);
|
||||
#endif
|
||||
|
||||
buf->ts_start = ts_start;
|
||||
|
|
|
@ -79,7 +79,11 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx);
|
|||
* \param[in] active_map Map that specifies which macroblock is active
|
||||
*/
|
||||
int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
|
||||
int64_t ts_start, int64_t ts_end, unsigned int flags);
|
||||
int64_t ts_start, int64_t ts_end,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
int use_highbitdepth,
|
||||
#endif
|
||||
unsigned int flags);
|
||||
|
||||
|
||||
/**\brief Get the next source buffer to encode
|
||||
|
|
|
@ -532,10 +532,9 @@ static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
|
|||
if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
|
||||
if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
|
||||
ERROR("Cannot change width or height after initialization");
|
||||
if ((ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
|
||||
if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h) ||
|
||||
(ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
|
||||
(ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
|
||||
ERROR("Cannot increase width or height larger than their initial values");
|
||||
if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h))
|
||||
force_key = 1;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче