blob: 1be7e337fc59592ca9f6eaae7cd560fcade6adbe [file] [log] [blame]
John Koleszar0ea50ce2010-05-18 11:58:33 -04001/*
John Koleszarc2140b82010-09-09 08:16:39 -04002 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar0ea50ce2010-05-18 11:58:33 -04003 *
John Koleszar94c52e42010-06-18 12:39:21 -04004 * Use of this source code is governed by a BSD-style license
John Koleszar09202d82010-06-04 16:19:40 -04005 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
John Koleszar94c52e42010-06-18 12:39:21 -04007 * in the file PATENTS. All contributing project authors may
John Koleszar09202d82010-06-04 16:19:40 -04008 * be found in the AUTHORS file in the root of the source tree.
John Koleszar0ea50ce2010-05-18 11:58:33 -04009 */
10
11
John Koleszarb7492342010-05-24 11:39:59 -040012#include "vpx/vpx_codec.h"
13#include "vpx/internal/vpx_codec_internal.h"
John Koleszar0ea50ce2010-05-18 11:58:33 -040014#include "vpx_version.h"
John Koleszar02321de2011-02-10 14:41:38 -050015#include "vp8/encoder/onyx_int.h"
John Koleszarb7492342010-05-24 11:39:59 -040016#include "vpx/vp8e.h"
John Koleszarbb7dd5b2010-10-14 16:40:12 -040017#include "vp8/encoder/firstpass.h"
John Koleszar02321de2011-02-10 14:41:38 -050018#include "vp8/common/onyx.h"
John Koleszar0ea50ce2010-05-18 11:58:33 -040019#include <stdlib.h>
20#include <string.h>
21
22/* This value is a sentinel for determining whether the user has set a mode
23 * directly through the deprecated VP8E_SET_ENCODING_MODE control.
24 */
25#define NO_MODE_SET 255
26
27struct vp8_extracfg
28{
29 struct vpx_codec_pkt_list *pkt_list;
30 vp8e_encoding_mode encoding_mode; /** best, good, realtime */
31 int cpu_used; /** available cpu percentage in 1/16*/
32 unsigned int enable_auto_alt_ref; /** if encoder decides to uses alternate reference frame */
33 unsigned int noise_sensitivity;
34 unsigned int Sharpness;
35 unsigned int static_thresh;
36 unsigned int token_partitions;
37 unsigned int arnr_max_frames; /* alt_ref Noise Reduction Max Frame Count */
38 unsigned int arnr_strength; /* alt_ref Noise Reduction Strength */
39 unsigned int arnr_type; /* alt_ref filter type */
John Koleszarb0da9b32010-12-17 09:43:39 -050040 vp8e_tuning tuning;
Paul Wilkinse0846c92011-01-07 18:29:37 +000041 unsigned int cq_level; /* constrained quality level */
John Koleszar1654ae92011-07-28 09:17:32 -040042 unsigned int rc_max_intra_bitrate_pct;
John Koleszar0ea50ce2010-05-18 11:58:33 -040043
44};
45
46struct extraconfig_map
47{
48 int usage;
49 struct vp8_extracfg cfg;
50};
51
52static const struct extraconfig_map extracfg_map[] =
53{
54 {
55 0,
56 {
57 NULL,
58#if !(CONFIG_REALTIME_ONLY)
59 VP8_BEST_QUALITY_ENCODING, /* Encoding Mode */
John Koleszar89c8b3d2010-06-14 10:22:55 -040060 0, /* cpu_used */
John Koleszar0ea50ce2010-05-18 11:58:33 -040061#else
62 VP8_REAL_TIME_ENCODING, /* Encoding Mode */
John Koleszar89c8b3d2010-06-14 10:22:55 -040063 4, /* cpu_used */
John Koleszar0ea50ce2010-05-18 11:58:33 -040064#endif
65 0, /* enable_auto_alt_ref */
66 0, /* noise_sensitivity */
67 0, /* Sharpness */
John Koleszar89c8b3d2010-06-14 10:22:55 -040068 0, /* static_thresh */
John Koleszar0ea50ce2010-05-18 11:58:33 -040069 VP8_ONE_TOKENPARTITION, /* token_partitions */
Adrian Grange8ee72842010-09-30 10:06:09 +010070 0, /* arnr_max_frames */
71 3, /* arnr_strength */
72 3, /* arnr_type*/
John Koleszarb0da9b32010-12-17 09:43:39 -050073 0, /* tuning*/
Paul Wilkinse0846c92011-01-07 18:29:37 +000074 10, /* cq_level */
John Koleszar1654ae92011-07-28 09:17:32 -040075 0, /* rc_max_intra_bitrate_pct */
John Koleszar0ea50ce2010-05-18 11:58:33 -040076 }
77 }
78};
79
80struct vpx_codec_alg_priv
81{
82 vpx_codec_priv_t base;
83 vpx_codec_enc_cfg_t cfg;
84 struct vp8_extracfg vp8_cfg;
85 VP8_CONFIG oxcf;
86 VP8_PTR cpi;
87 unsigned char *cx_data;
88 unsigned int cx_data_sz;
89 vpx_image_t preview_img;
90 unsigned int next_frame_flag;
91 vp8_postproc_cfg_t preview_ppcfg;
Yaowu Xu8caa5c22010-05-27 10:04:36 -070092 vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed
John Koleszar0ea50ce2010-05-18 11:58:33 -040093 int deprecated_mode;
94 unsigned int fixed_kf_cntr;
95};
96
97
98static vpx_codec_err_t
99update_error_state(vpx_codec_alg_priv_t *ctx,
100 const struct vpx_internal_error_info *error)
101{
102 vpx_codec_err_t res;
103
104 if ((res = error->error_code))
105 ctx->base.err_detail = error->has_detail
106 ? error->detail
107 : NULL;
108
109 return res;
110}
111
112
John Koleszar79e2b1f2010-11-17 09:08:47 -0500113#undef ERROR
John Koleszar0ea50ce2010-05-18 11:58:33 -0400114#define ERROR(str) do {\
115 ctx->base.err_detail = str;\
116 return VPX_CODEC_INVALID_PARAM;\
117 } while(0)
118
119#define RANGE_CHECK(p,memb,lo,hi) do {\
Guillermo Ballester Valor5a726202010-06-11 14:33:49 -0400120 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
John Koleszar0ea50ce2010-05-18 11:58:33 -0400121 ERROR(#memb " out of range ["#lo".."#hi"]");\
122 } while(0)
123
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400124#define RANGE_CHECK_HI(p,memb,hi) do {\
125 if(!((p)->memb <= (hi))) \
126 ERROR(#memb " out of range [.."#hi"]");\
127 } while(0)
128
John Koleszar0ea50ce2010-05-18 11:58:33 -0400129#define RANGE_CHECK_LO(p,memb,lo) do {\
130 if(!((p)->memb >= (lo))) \
131 ERROR(#memb " out of range ["#lo"..]");\
132 } while(0)
133
134#define RANGE_CHECK_BOOL(p,memb) do {\
135 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
136 } while(0)
137
138static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
139 const vpx_codec_enc_cfg_t *cfg,
140 const struct vp8_extracfg *vp8_cfg)
141{
Attila Nagy1aadced2011-04-12 15:01:22 +0300142 RANGE_CHECK(cfg, g_w, 1, 16383); /* 14 bits available */
143 RANGE_CHECK(cfg, g_h, 1, 16383); /* 14 bits available */
John Koleszar0ea50ce2010-05-18 11:58:33 -0400144 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
145 RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400146 RANGE_CHECK_HI(cfg, g_profile, 3);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400147 RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
John Koleszar2d03f072011-01-28 11:56:18 -0500148 RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400149 RANGE_CHECK_HI(cfg, g_threads, 64);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400150#if !(CONFIG_REALTIME_ONLY)
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400151 RANGE_CHECK_HI(cfg, g_lag_in_frames, 25);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400152#else
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400153 RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400154#endif
Paul Wilkinse0846c92011-01-07 18:29:37 +0000155 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_CQ);
John Koleszarc99f9d72011-04-11 11:29:23 -0400156 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
157 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400158 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400159 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
160 //RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile);
161 RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400162 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
163 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
164 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400165#if !(CONFIG_REALTIME_ONLY)
166 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
167#else
168 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
169#endif
170
171 /* VP8 does not support a lower bound on the keyframe interval in
172 * automatic keyframe placement mode.
173 */
174 if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
175 && cfg->kf_min_dist > 0)
176 ERROR("kf_min_dist not supported in auto mode, use 0 "
177 "or kf_max_dist instead.");
178
179 RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
Yunqing Wang4fd81a92011-04-11 15:55:04 -0400180 RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
181
John Koleszar0ea50ce2010-05-18 11:58:33 -0400182#if !(CONFIG_REALTIME_ONLY)
183 RANGE_CHECK(vp8_cfg, encoding_mode, VP8_BEST_QUALITY_ENCODING, VP8_REAL_TIME_ENCODING);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400184 RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400185#else
186 RANGE_CHECK(vp8_cfg, encoding_mode, VP8_REAL_TIME_ENCODING, VP8_REAL_TIME_ENCODING);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400187 RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0);
188#endif
189
190 RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
Guillermo Ballester Valor23690682010-06-11 14:33:49 -0400191 RANGE_CHECK_HI(vp8_cfg, Sharpness, 7);
Adrian Grange8ee72842010-09-30 10:06:09 +0100192 RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
Frank Galligan15542722010-10-04 21:12:22 -0400193 RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
Adrian Grange8ee72842010-09-30 10:06:09 +0100194 RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
Paul Wilkinse0846c92011-01-07 18:29:37 +0000195 RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400196
Attila Nagycb791aa2011-01-10 11:14:10 +0200197#if !(CONFIG_REALTIME_ONLY)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400198 if (cfg->g_pass == VPX_RC_LAST_PASS)
199 {
Adrian Grangeed40ff92011-03-10 11:32:48 -0800200 size_t packet_sz = sizeof(FIRSTPASS_STATS);
John Koleszarbb7dd5b2010-10-14 16:40:12 -0400201 int n_packets = cfg->rc_twopass_stats_in.sz / packet_sz;
202 FIRSTPASS_STATS *stats;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400203
204 if (!cfg->rc_twopass_stats_in.buf)
205 ERROR("rc_twopass_stats_in.buf not set.");
206
John Koleszarbb7dd5b2010-10-14 16:40:12 -0400207 if (cfg->rc_twopass_stats_in.sz % packet_sz)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400208 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
209
John Koleszarbb7dd5b2010-10-14 16:40:12 -0400210 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400211 ERROR("rc_twopass_stats_in requires at least two packets.");
212
John Koleszarbb7dd5b2010-10-14 16:40:12 -0400213 stats = (void*)((char *)cfg->rc_twopass_stats_in.buf
214 + (n_packets - 1) * packet_sz);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400215
John Koleszarbb7dd5b2010-10-14 16:40:12 -0400216 if ((int)(stats->count + 0.5) != n_packets - 1)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400217 ERROR("rc_twopass_stats_in missing EOS stats packet");
218 }
Attila Nagycb791aa2011-01-10 11:14:10 +0200219#endif
John Koleszar0ea50ce2010-05-18 11:58:33 -0400220
Adrian Grange217591f2011-10-06 15:49:11 -0700221 RANGE_CHECK(cfg, ts_number_layers, 1, 5);
222
223 if (cfg->ts_number_layers > 1)
224 {
225 int i;
226 RANGE_CHECK_HI(cfg, ts_periodicity, 16);
227
228 for (i=1; i<cfg->ts_number_layers; i++)
229 if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1])
230 ERROR("ts_target_bitrate entries are not strictly increasing");
231
232 RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
233 for (i=cfg->ts_number_layers-2; i>0; i--)
234 if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i])
235 ERROR("ts_rate_decimator factors are not powers of 2");
236
237 RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1);
238 }
239
John Koleszar0ea50ce2010-05-18 11:58:33 -0400240 return VPX_CODEC_OK;
241}
242
243
244static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
245 const vpx_image_t *img)
246{
247 switch (img->fmt)
248 {
James Zern6cd4a102010-05-20 23:22:39 -0400249 case VPX_IMG_FMT_YV12:
250 case VPX_IMG_FMT_I420:
251 case VPX_IMG_FMT_VPXI420:
252 case VPX_IMG_FMT_VPXYV12:
John Koleszar0ea50ce2010-05-18 11:58:33 -0400253 break;
254 default:
255 ERROR("Invalid image format. Only YV12 and I420 images are supported");
256 }
257
258 if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
259 ERROR("Image size must match encoder init configuration size");
260
261 return VPX_CODEC_OK;
262}
263
264
265static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
266 vpx_codec_enc_cfg_t cfg,
267 struct vp8_extracfg vp8_cfg)
268{
269 oxcf->multi_threaded = cfg.g_threads;
270 oxcf->Version = cfg.g_profile;
271
272 oxcf->Width = cfg.g_w;
273 oxcf->Height = cfg.g_h;
274 /* guess a frame rate if out of whack, use 30 */
Adrian Grange217591f2011-10-06 15:49:11 -0700275 oxcf->frame_rate = (double)(cfg.g_timebase.den) /
276 (double)(cfg.g_timebase.num);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400277
278 if (oxcf->frame_rate > 180)
279 {
280 oxcf->frame_rate = 30;
281 }
282
Adrian Grange217591f2011-10-06 15:49:11 -0700283 oxcf->error_resilient_mode = cfg.g_error_resilient;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400284
285 switch (cfg.g_pass)
286 {
287 case VPX_RC_ONE_PASS:
288 oxcf->Mode = MODE_BESTQUALITY;
289 break;
290 case VPX_RC_FIRST_PASS:
291 oxcf->Mode = MODE_FIRSTPASS;
292 break;
293 case VPX_RC_LAST_PASS:
294 oxcf->Mode = MODE_SECONDPASS_BEST;
295 break;
296 }
297
298 if (cfg.g_pass == VPX_RC_FIRST_PASS)
299 {
Adrian Grange217591f2011-10-06 15:49:11 -0700300 oxcf->allow_lag = 0;
301 oxcf->lag_in_frames = 0;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400302 }
303 else
304 {
Adrian Grange217591f2011-10-06 15:49:11 -0700305 oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
306 oxcf->lag_in_frames = cfg.g_lag_in_frames;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400307 }
308
309 oxcf->allow_df = (cfg.rc_dropframe_thresh > 0);
310 oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh;
311
312 oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
313 oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh;
314 oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
315
316 if (cfg.rc_end_usage == VPX_VBR)
317 {
Adrian Grange217591f2011-10-06 15:49:11 -0700318 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400319 }
320 else if (cfg.rc_end_usage == VPX_CBR)
321 {
Adrian Grange217591f2011-10-06 15:49:11 -0700322 oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400323 }
Paul Wilkinse0846c92011-01-07 18:29:37 +0000324 else if (cfg.rc_end_usage == VPX_CQ)
325 {
Adrian Grange217591f2011-10-06 15:49:11 -0700326 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
Paul Wilkinse0846c92011-01-07 18:29:37 +0000327 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400328
Adrian Grange217591f2011-10-06 15:49:11 -0700329 oxcf->target_bandwidth = cfg.rc_target_bitrate;
John Koleszar1654ae92011-07-28 09:17:32 -0400330 oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400331
Adrian Grange217591f2011-10-06 15:49:11 -0700332 oxcf->best_allowed_q = cfg.rc_min_quantizer;
333 oxcf->worst_allowed_q = cfg.rc_max_quantizer;
334 oxcf->cq_level = vp8_cfg.cq_level;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400335 oxcf->fixed_q = -1;
336
Adrian Grange217591f2011-10-06 15:49:11 -0700337 oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
338 oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400339
Adrian Grange217591f2011-10-06 15:49:11 -0700340 oxcf->maximum_buffer_size = cfg.rc_buf_sz;
341 oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
342 oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400343
Adrian Grange217591f2011-10-06 15:49:11 -0700344 oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400345 oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
346 oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
347
Adrian Grange217591f2011-10-06 15:49:11 -0700348 oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
349 && cfg.kf_min_dist != cfg.kf_max_dist;
350 //oxcf->kf_min_dist = cfg.kf_min_dis;
351 oxcf->key_freq = cfg.kf_max_dist;
352
353 oxcf->number_of_layers = cfg.ts_number_layers;
354 oxcf->periodicity = cfg.ts_periodicity;
355
356 if (oxcf->number_of_layers > 1)
357 {
358 memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate,
359 sizeof(cfg.ts_target_bitrate));
360 memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator,
361 sizeof(cfg.ts_rate_decimator));
362 memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
363 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400364
365 //oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
366 //strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
367
Adrian Grange217591f2011-10-06 15:49:11 -0700368 oxcf->cpu_used = vp8_cfg.cpu_used;
369 oxcf->encode_breakout = vp8_cfg.static_thresh;
370 oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
371 oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
372 oxcf->Sharpness = vp8_cfg.Sharpness;
373 oxcf->token_partitions = vp8_cfg.token_partitions;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400374
Adrian Grange217591f2011-10-06 15:49:11 -0700375 oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
376 oxcf->output_pkt_list = vp8_cfg.pkt_list;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400377
Adrian Grange217591f2011-10-06 15:49:11 -0700378 oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
379 oxcf->arnr_strength = vp8_cfg.arnr_strength;
380 oxcf->arnr_type = vp8_cfg.arnr_type;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400381
Adrian Grange217591f2011-10-06 15:49:11 -0700382 oxcf->tuning = vp8_cfg.tuning;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400383
384 /*
385 printf("Current VP8 Settings: \n");
386 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
387 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
388 printf("Sharpness: %d\n", oxcf->Sharpness);
389 printf("cpu_used: %d\n", oxcf->cpu_used);
390 printf("Mode: %d\n", oxcf->Mode);
391 printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
392 printf("auto_key: %d\n", oxcf->auto_key);
393 printf("key_freq: %d\n", oxcf->key_freq);
394 printf("end_usage: %d\n", oxcf->end_usage);
395 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
John Koleszarc99f9d72011-04-11 11:29:23 -0400396 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400397 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
398 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
399 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
400 printf("fixed_q: %d\n", oxcf->fixed_q);
401 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
402 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
403 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
404 printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
405 printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
406 printf("allow_df: %d\n", oxcf->allow_df);
407 printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
408 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
409 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
410 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
411 printf("allow_lag: %d\n", oxcf->allow_lag);
412 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
413 printf("play_alternate: %d\n", oxcf->play_alternate);
414 printf("Version: %d\n", oxcf->Version);
415 printf("multi_threaded: %d\n", oxcf->multi_threaded);
416 printf("encode_breakout: %d\n", oxcf->encode_breakout);
417 */
418 return VPX_CODEC_OK;
419}
420
421static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx,
422 const vpx_codec_enc_cfg_t *cfg)
423{
424 vpx_codec_err_t res;
425
426 if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
427 ERROR("Cannot change width or height after initialization");
428
429 /* Prevent increasing lag_in_frames. This check is stricter than it needs
430 * to be -- the limit is not increasing past the first lag_in_frames
431 * value, but we don't track the initial config, only the last successful
432 * config.
433 */
434 if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
435 ERROR("Cannot increase lag_in_frames");
436
437 res = validate_config(ctx, cfg, &ctx->vp8_cfg);
438
439 if (!res)
440 {
441 ctx->cfg = *cfg;
442 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
443 vp8_change_config(ctx->cpi, &ctx->oxcf);
444 }
445
446 return res;
447}
448
449
450int vp8_reverse_trans(int);
451
452
453static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
454 int ctrl_id,
455 va_list args)
456{
457 void *arg = va_arg(args, void *);
458
459#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
460
461 if (!arg)
462 return VPX_CODEC_INVALID_PARAM;
463
464 switch (ctrl_id)
465 {
466 MAP(VP8E_GET_LAST_QUANTIZER, vp8_get_quantizer(ctx->cpi));
467 MAP(VP8E_GET_LAST_QUANTIZER_64, vp8_reverse_trans(vp8_get_quantizer(ctx->cpi)));
468 }
469
470 return VPX_CODEC_OK;
471#undef MAP
472}
473
474
475static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
476 int ctrl_id,
477 va_list args)
478{
479 vpx_codec_err_t res = VPX_CODEC_OK;
480 struct vp8_extracfg xcfg = ctx->vp8_cfg;
481
482#define MAP(id, var) case id: var = CAST(id, args); break;
483
484 switch (ctrl_id)
485 {
486 MAP(VP8E_SET_ENCODING_MODE, ctx->deprecated_mode);
487 MAP(VP8E_SET_CPUUSED, xcfg.cpu_used);
488 MAP(VP8E_SET_ENABLEAUTOALTREF, xcfg.enable_auto_alt_ref);
489 MAP(VP8E_SET_NOISE_SENSITIVITY, xcfg.noise_sensitivity);
490 MAP(VP8E_SET_SHARPNESS, xcfg.Sharpness);
491 MAP(VP8E_SET_STATIC_THRESHOLD, xcfg.static_thresh);
492 MAP(VP8E_SET_TOKEN_PARTITIONS, xcfg.token_partitions);
493
494 MAP(VP8E_SET_ARNR_MAXFRAMES, xcfg.arnr_max_frames);
495 MAP(VP8E_SET_ARNR_STRENGTH , xcfg.arnr_strength);
496 MAP(VP8E_SET_ARNR_TYPE , xcfg.arnr_type);
John Koleszarb0da9b32010-12-17 09:43:39 -0500497 MAP(VP8E_SET_TUNING, xcfg.tuning);
Paul Wilkinse0846c92011-01-07 18:29:37 +0000498 MAP(VP8E_SET_CQ_LEVEL, xcfg.cq_level);
John Koleszar1654ae92011-07-28 09:17:32 -0400499 MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400500
501 }
502
503 res = validate_config(ctx, &ctx->cfg, &xcfg);
504
505 if (!res)
506 {
507 ctx->vp8_cfg = xcfg;
508 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
509 vp8_change_config(ctx->cpi, &ctx->oxcf);
510 }
511
512 return res;
513#undef MAP
514}
515static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
516{
517 vpx_codec_err_t res = VPX_DEC_OK;
518 struct vpx_codec_alg_priv *priv;
519 vpx_codec_enc_cfg_t *cfg;
520 unsigned int i;
521
522 VP8_PTR optr;
523
524 if (!ctx->priv)
525 {
526 priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
527
Attila Nagye6db21e2011-02-22 15:02:05 +0200528 if (!priv)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400529 {
Attila Nagye6db21e2011-02-22 15:02:05 +0200530 return VPX_CODEC_MEM_ERROR;
531 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400532
Attila Nagye6db21e2011-02-22 15:02:05 +0200533 ctx->priv = &priv->base;
534 ctx->priv->sz = sizeof(*ctx->priv);
535 ctx->priv->iface = ctx->iface;
536 ctx->priv->alg_priv = priv;
537 ctx->priv->init_flags = ctx->init_flags;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400538
Attila Nagye6db21e2011-02-22 15:02:05 +0200539 if (ctx->config.enc)
540 {
541 /* Update the reference to the config structure to an
542 * internal copy.
John Koleszar0ea50ce2010-05-18 11:58:33 -0400543 */
Attila Nagye6db21e2011-02-22 15:02:05 +0200544 ctx->priv->alg_priv->cfg = *ctx->config.enc;
545 ctx->config.enc = &ctx->priv->alg_priv->cfg;
546 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400547
Attila Nagye6db21e2011-02-22 15:02:05 +0200548 cfg = &ctx->priv->alg_priv->cfg;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400549
Adrian Grange217591f2011-10-06 15:49:11 -0700550 /* Select the extra vp8 configuration table based on the current
Attila Nagye6db21e2011-02-22 15:02:05 +0200551 * usage value. If the current usage value isn't found, use the
552 * values for usage case 0.
553 */
554 for (i = 0;
555 extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
556 i++);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400557
Attila Nagye6db21e2011-02-22 15:02:05 +0200558 priv->vp8_cfg = extracfg_map[i].cfg;
559 priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400560
Attila Nagye6db21e2011-02-22 15:02:05 +0200561 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400562
Attila Nagye6db21e2011-02-22 15:02:05 +0200563 if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400564
Attila Nagye6db21e2011-02-22 15:02:05 +0200565 priv->cx_data = malloc(priv->cx_data_sz);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400566
Attila Nagye6db21e2011-02-22 15:02:05 +0200567 if (!priv->cx_data)
568 {
569 return VPX_CODEC_MEM_ERROR;
570 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400571
Attila Nagye6db21e2011-02-22 15:02:05 +0200572 priv->deprecated_mode = NO_MODE_SET;
573
574 vp8_initialize();
575
576 res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
577
578 if (!res)
579 {
580 set_vp8e_config(&ctx->priv->alg_priv->oxcf,
581 ctx->priv->alg_priv->cfg,
582 ctx->priv->alg_priv->vp8_cfg);
583 optr = vp8_create_compressor(&ctx->priv->alg_priv->oxcf);
584
585 if (!optr)
586 res = VPX_CODEC_MEM_ERROR;
587 else
588 ctx->priv->alg_priv->cpi = optr;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400589 }
590 }
591
592 return res;
593}
594
595static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
596{
597
598 free(ctx->cx_data);
599 vp8_remove_compressor(&ctx->cpi);
600 free(ctx);
601 return VPX_CODEC_OK;
602}
603
604static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
605 YV12_BUFFER_CONFIG *yv12)
606{
607 vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszarb6c71912010-05-24 21:45:05 -0400608 yv12->y_buffer = img->planes[VPX_PLANE_Y];
609 yv12->u_buffer = img->planes[VPX_PLANE_U];
610 yv12->v_buffer = img->planes[VPX_PLANE_V];
John Koleszar0ea50ce2010-05-18 11:58:33 -0400611
612 yv12->y_width = img->d_w;
613 yv12->y_height = img->d_h;
614 yv12->uv_width = (1 + yv12->y_width) / 2;
615 yv12->uv_height = (1 + yv12->y_height) / 2;
616
John Koleszarb6c71912010-05-24 21:45:05 -0400617 yv12->y_stride = img->stride[VPX_PLANE_Y];
618 yv12->uv_stride = img->stride[VPX_PLANE_U];
John Koleszar0ea50ce2010-05-18 11:58:33 -0400619
John Koleszarb6c71912010-05-24 21:45:05 -0400620 yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
James Zern6cd4a102010-05-20 23:22:39 -0400621 yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12); //REG_YUV = 0
John Koleszar0ea50ce2010-05-18 11:58:33 -0400622 return res;
623}
624
625static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
626 unsigned long duration,
627 unsigned long deadline)
628{
629 unsigned int new_qc;
630
631#if !(CONFIG_REALTIME_ONLY)
632 /* Use best quality mode if no deadline is given. */
633 new_qc = MODE_BESTQUALITY;
634
635 if (deadline)
636 {
637 uint64_t duration_us;
638
639 /* Convert duration parameter from stream timebase to microseconds */
640 duration_us = (uint64_t)duration * 1000000
641 * (uint64_t)ctx->cfg.g_timebase.num
642 / (uint64_t)ctx->cfg.g_timebase.den;
643
644 /* If the deadline is more that the duration this frame is to be shown,
645 * use good quality mode. Otherwise use realtime mode.
646 */
647 new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
648 }
649
650#else
651 new_qc = MODE_REALTIME;
652#endif
653
654 switch (ctx->deprecated_mode)
655 {
656 case VP8_BEST_QUALITY_ENCODING:
657 new_qc = MODE_BESTQUALITY;
658 break;
659 case VP8_GOOD_QUALITY_ENCODING:
660 new_qc = MODE_GOODQUALITY;
661 break;
662 case VP8_REAL_TIME_ENCODING:
663 new_qc = MODE_REALTIME;
664 break;
665 }
666
667 if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
668 new_qc = MODE_FIRSTPASS;
669 else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
670 new_qc = (new_qc == MODE_BESTQUALITY)
671 ? MODE_SECONDPASS_BEST
672 : MODE_SECONDPASS;
673
674 if (ctx->oxcf.Mode != new_qc)
675 {
676 ctx->oxcf.Mode = new_qc;
677 vp8_change_config(ctx->cpi, &ctx->oxcf);
678 }
679}
680
681
682static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
683 const vpx_image_t *img,
684 vpx_codec_pts_t pts,
685 unsigned long duration,
686 vpx_enc_frame_flags_t flags,
687 unsigned long deadline)
688{
689 vpx_codec_err_t res = VPX_CODEC_OK;
690
691 if (img)
692 res = validate_img(ctx, img);
693
694 pick_quickcompress_mode(ctx, duration, deadline);
695 vpx_codec_pkt_list_init(&ctx->pkt_list);
696
697 /* Handle Flags */
698 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
699 || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF)))
700 {
701 ctx->base.err_detail = "Conflicting flags.";
702 return VPX_CODEC_INVALID_PARAM;
703 }
704
705 if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
706 | VP8_EFLAG_NO_REF_ARF))
707 {
708 int ref = 7;
709
710 if (flags & VP8_EFLAG_NO_REF_LAST)
711 ref ^= VP8_LAST_FLAG;
712
713 if (flags & VP8_EFLAG_NO_REF_GF)
714 ref ^= VP8_GOLD_FLAG;
715
716 if (flags & VP8_EFLAG_NO_REF_ARF)
717 ref ^= VP8_ALT_FLAG;
718
719 vp8_use_as_reference(ctx->cpi, ref);
720 }
721
722 if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
723 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
724 | VP8_EFLAG_FORCE_ARF))
725 {
726 int upd = 7;
727
728 if (flags & VP8_EFLAG_NO_UPD_LAST)
729 upd ^= VP8_LAST_FLAG;
730
731 if (flags & VP8_EFLAG_NO_UPD_GF)
732 upd ^= VP8_GOLD_FLAG;
733
734 if (flags & VP8_EFLAG_NO_UPD_ARF)
735 upd ^= VP8_ALT_FLAG;
736
737 vp8_update_reference(ctx->cpi, upd);
738 }
739
740 if (flags & VP8_EFLAG_NO_UPD_ENTROPY)
741 {
742 vp8_update_entropy(ctx->cpi, 0);
743 }
744
745 /* Handle fixed keyframe intervals */
746 if (ctx->cfg.kf_mode == VPX_KF_AUTO
747 && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
748 {
749 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist)
750 {
751 flags |= VPX_EFLAG_FORCE_KF;
Andoni Morales Alastruey48140162011-02-07 18:04:02 +0100752 ctx->fixed_kf_cntr = 1;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400753 }
754 }
755
756 /* Initialize the encoder instance on the first frame*/
757 if (!res && ctx->cpi)
758 {
759 unsigned int lib_flags;
760 YV12_BUFFER_CONFIG sd;
James Zernb45065d2011-07-25 18:44:59 -0700761 int64_t dst_time_stamp, dst_end_time_stamp;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400762 unsigned long size, cx_data_sz;
763 unsigned char *cx_data;
James Berrybc715112011-10-12 11:18:50 -0400764 unsigned char *cx_data_end;
765 int comp_data_state = 0;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400766
767 /* Set up internal flags */
768 if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
769 ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
770
Stefan Holmer7296b3f2011-06-13 16:42:27 +0200771 if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
772 ((VP8_COMP *)ctx->cpi)->output_partition = 1;
773
John Koleszar0ea50ce2010-05-18 11:58:33 -0400774 /* Convert API flags to internal codec lib flags */
775 lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
776
777 /* vp8 use 10,000,000 ticks/second as time stamp */
778 dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
779 dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
780
781 if (img != NULL)
782 {
783 res = image2yuvconfig(img, &sd);
784
785 if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
786 &sd, dst_time_stamp, dst_end_time_stamp))
787 {
788 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
789 res = update_error_state(ctx, &cpi->common.error);
790 }
791
792 /* reset for next frame */
793 ctx->next_frame_flag = 0;
794 }
795
796 cx_data = ctx->cx_data;
797 cx_data_sz = ctx->cx_data_sz;
James Berrybc715112011-10-12 11:18:50 -0400798 cx_data_end = ctx->cx_data + cx_data_sz;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400799 lib_flags = 0;
800
James Berrybc715112011-10-12 11:18:50 -0400801 while (cx_data_sz >= ctx->cx_data_sz / 2)
John Koleszar0ea50ce2010-05-18 11:58:33 -0400802 {
James Berrybc715112011-10-12 11:18:50 -0400803 comp_data_state = vp8_get_compressed_data(ctx->cpi,
804 &lib_flags,
805 &size,
806 cx_data,
807 cx_data_end,
808 &dst_time_stamp,
809 &dst_end_time_stamp,
810 !img);
811
812 if(comp_data_state == VPX_CODEC_CORRUPT_FRAME)
813 return VPX_CODEC_CORRUPT_FRAME;
814 else if(comp_data_state == -1)
815 break;
816
John Koleszar0ea50ce2010-05-18 11:58:33 -0400817 if (size)
818 {
819 vpx_codec_pts_t round, delta;
820 vpx_codec_cx_pkt_t pkt;
821 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
822
823 /* Add the frame packet to the list of returned packets. */
824 round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
825 delta = (dst_end_time_stamp - dst_time_stamp);
826 pkt.kind = VPX_CODEC_CX_FRAME_PKT;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400827 pkt.data.frame.pts =
828 (dst_time_stamp * ctx->cfg.g_timebase.den + round)
829 / ctx->cfg.g_timebase.num / 10000000;
830 pkt.data.frame.duration =
831 (delta * ctx->cfg.g_timebase.den + round)
832 / ctx->cfg.g_timebase.num / 10000000;
833 pkt.data.frame.flags = lib_flags << 16;
834
835 if (lib_flags & FRAMEFLAGS_KEY)
836 pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
837
838 if (!cpi->common.show_frame)
839 {
840 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
841
Frank Galligan45e64942010-10-05 17:46:37 -0400842 // This timestamp should be as close as possible to the
843 // prior PTS so that if a decoder uses pts to schedule when
844 // to do this, we start right after last frame was decoded.
845 // Invisible frames have no duration.
846 pkt.data.frame.pts = ((cpi->last_time_stamp_seen
847 * ctx->cfg.g_timebase.den + round)
848 / ctx->cfg.g_timebase.num / 10000000) + 1;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400849 pkt.data.frame.duration = 0;
850 }
851
John Koleszar37de0b82011-07-07 10:38:23 -0400852 if (cpi->droppable)
853 pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
854
Stefan Holmer7296b3f2011-06-13 16:42:27 +0200855 if (cpi->output_partition)
856 {
857 int i;
858 const int num_partitions =
859 (1 << cpi->common.multi_token_partition) + 1;
Attila Nagy0afcc762011-07-20 14:09:42 +0300860
861 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
862
Stefan Holmer7296b3f2011-06-13 16:42:27 +0200863 for (i = 0; i < num_partitions; ++i)
864 {
865 pkt.data.frame.buf = cx_data;
866 pkt.data.frame.sz = cpi->partition_sz[i];
867 pkt.data.frame.partition_id = i;
868 /* don't set the fragment bit for the last partition */
Attila Nagy0afcc762011-07-20 14:09:42 +0300869 if (i == (num_partitions - 1))
870 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
Stefan Holmer7296b3f2011-06-13 16:42:27 +0200871 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
872 cx_data += cpi->partition_sz[i];
873 cx_data_sz -= cpi->partition_sz[i];
874 }
875 }
876 else
877 {
878 pkt.data.frame.buf = cx_data;
879 pkt.data.frame.sz = size;
880 pkt.data.frame.partition_id = -1;
881 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
882 cx_data += size;
883 cx_data_sz -= size;
884 }
John Koleszar0ea50ce2010-05-18 11:58:33 -0400885
886 //printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400887 }
888 }
889 }
890
891 return res;
892}
893
894
895static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx,
896 vpx_codec_iter_t *iter)
897{
898 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
899}
900
901static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
902 int ctr_id,
903 va_list args)
904{
905 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
906
907 if (data)
908 {
909 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
910 YV12_BUFFER_CONFIG sd;
911
912 image2yuvconfig(&frame->img, &sd);
913 vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
914 return VPX_CODEC_OK;
915 }
916 else
917 return VPX_CODEC_INVALID_PARAM;
918
919}
920
921static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx,
922 int ctr_id,
923 va_list args)
924{
925
926 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
927
928 if (data)
929 {
930 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
931 YV12_BUFFER_CONFIG sd;
932
933 image2yuvconfig(&frame->img, &sd);
934 vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
935 return VPX_CODEC_OK;
936 }
937 else
938 return VPX_CODEC_INVALID_PARAM;
939}
940
941static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx,
942 int ctr_id,
943 va_list args)
944{
James Zern76640f82010-08-20 16:06:56 -0400945#if CONFIG_POSTPROC
John Koleszar0ea50ce2010-05-18 11:58:33 -0400946 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
James Zern76640f82010-08-20 16:06:56 -0400947 (void)ctr_id;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400948
949 if (data)
950 {
951 ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
952 return VPX_CODEC_OK;
953 }
954 else
955 return VPX_CODEC_INVALID_PARAM;
James Zern76640f82010-08-20 16:06:56 -0400956#else
957 (void)ctx;
958 (void)ctr_id;
959 (void)args;
960 return VPX_CODEC_INCAPABLE;
961#endif
John Koleszar0ea50ce2010-05-18 11:58:33 -0400962}
963
964
965static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
966{
967
968 YV12_BUFFER_CONFIG sd;
Fritz Koenig647df002010-11-04 16:03:36 -0700969 vp8_ppflags_t flags = {0};
John Koleszar0ea50ce2010-05-18 11:58:33 -0400970
Fritz Koenig647df002010-11-04 16:03:36 -0700971 if (ctx->preview_ppcfg.post_proc_flag)
972 {
973 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
974 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
975 flags.noise_level = ctx->preview_ppcfg.noise_level;
976 }
977
978 if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags))
John Koleszar0ea50ce2010-05-18 11:58:33 -0400979 {
980
981 /*
James Zern6cd4a102010-05-20 23:22:39 -0400982 vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
John Koleszar0ea50ce2010-05-18 11:58:33 -0400983 sd.y_width + 2*VP8BORDERINPIXELS,
984 sd.y_height + 2*VP8BORDERINPIXELS,
985 1,
986 sd.buffer_alloc);
987 vpx_img_set_rect(&ctx->preview_img,
988 VP8BORDERINPIXELS, VP8BORDERINPIXELS,
989 sd.y_width, sd.y_height);
990 */
991
992 ctx->preview_img.bps = 12;
John Koleszarb6c71912010-05-24 21:45:05 -0400993 ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
994 ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
995 ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400996
997 if (sd.clrtype == REG_YUV)
James Zern6cd4a102010-05-20 23:22:39 -0400998 ctx->preview_img.fmt = VPX_IMG_FMT_I420;
John Koleszar0ea50ce2010-05-18 11:58:33 -0400999 else
James Zern6cd4a102010-05-20 23:22:39 -04001000 ctx->preview_img.fmt = VPX_IMG_FMT_VPXI420;
John Koleszar0ea50ce2010-05-18 11:58:33 -04001001
1002 ctx->preview_img.x_chroma_shift = 1;
1003 ctx->preview_img.y_chroma_shift = 1;
1004
James Berryddacf1c2011-02-08 14:23:18 -05001005 ctx->preview_img.d_w = sd.y_width;
1006 ctx->preview_img.d_h = sd.y_height;
John Koleszarb6c71912010-05-24 21:45:05 -04001007 ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
1008 ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
1009 ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
John Koleszar0ea50ce2010-05-18 11:58:33 -04001010 ctx->preview_img.w = sd.y_width;
1011 ctx->preview_img.h = sd.y_height;
1012
1013 return &ctx->preview_img;
1014 }
1015 else
1016 return NULL;
1017}
1018
1019static vpx_codec_err_t vp8e_update_entropy(vpx_codec_alg_priv_t *ctx,
1020 int ctr_id,
1021 va_list args)
1022{
1023 int update = va_arg(args, int);
1024 vp8_update_entropy(ctx->cpi, update);
1025 return VPX_CODEC_OK;
1026
1027}
1028
1029static vpx_codec_err_t vp8e_update_reference(vpx_codec_alg_priv_t *ctx,
1030 int ctr_id,
1031 va_list args)
1032{
1033 int update = va_arg(args, int);
1034 vp8_update_reference(ctx->cpi, update);
1035 return VPX_CODEC_OK;
1036}
1037
1038static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx,
1039 int ctr_id,
1040 va_list args)
1041{
1042 int reference_flag = va_arg(args, int);
1043 vp8_use_as_reference(ctx->cpi, reference_flag);
1044 return VPX_CODEC_OK;
1045}
1046
1047static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
1048 int ctr_id,
1049 va_list args)
1050{
1051 vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
1052
1053 if (data)
1054 {
1055 vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
1056
1057 if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, roi->delta_q, roi->delta_lf, roi->static_threshold))
1058 return VPX_CODEC_OK;
1059 else
1060 return VPX_CODEC_INVALID_PARAM;
1061 }
1062 else
1063 return VPX_CODEC_INVALID_PARAM;
1064}
1065
1066
1067static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx,
1068 int ctr_id,
1069 va_list args)
1070{
1071 vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
1072
1073 if (data)
1074 {
1075
1076 vpx_active_map_t *map = (vpx_active_map_t *)data;
1077
1078 if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
1079 return VPX_CODEC_OK;
1080 else
1081 return VPX_CODEC_INVALID_PARAM;
1082 }
1083 else
1084 return VPX_CODEC_INVALID_PARAM;
1085}
1086
1087static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
1088 int ctr_id,
1089 va_list args)
1090{
1091
1092 vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *);
1093
1094 if (data)
1095 {
1096 int res;
1097 vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data ;
1098 res = vp8_set_internal_size(ctx->cpi, scalemode.h_scaling_mode, scalemode.v_scaling_mode);
1099
1100 if (!res)
1101 {
1102 /*force next frame a key frame to effect scaling mode */
1103 ctx->next_frame_flag |= FRAMEFLAGS_KEY;
1104 return VPX_CODEC_OK;
1105 }
1106 else
1107 return VPX_CODEC_INVALID_PARAM;
1108 }
1109 else
1110 return VPX_CODEC_INVALID_PARAM;
1111}
1112
1113
1114static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
1115{
1116 {VP8_SET_REFERENCE, vp8e_set_reference},
1117 {VP8_COPY_REFERENCE, vp8e_get_reference},
1118 {VP8_SET_POSTPROC, vp8e_set_previewpp},
1119 {VP8E_UPD_ENTROPY, vp8e_update_entropy},
1120 {VP8E_UPD_REFERENCE, vp8e_update_reference},
1121 {VP8E_USE_REFERENCE, vp8e_use_reference},
1122 {VP8E_SET_ROI_MAP, vp8e_set_roi_map},
1123 {VP8E_SET_ACTIVEMAP, vp8e_set_activemap},
1124 {VP8E_SET_SCALEMODE, vp8e_set_scalemode},
1125 {VP8E_SET_ENCODING_MODE, set_param},
1126 {VP8E_SET_CPUUSED, set_param},
1127 {VP8E_SET_NOISE_SENSITIVITY, set_param},
1128 {VP8E_SET_ENABLEAUTOALTREF, set_param},
1129 {VP8E_SET_SHARPNESS, set_param},
1130 {VP8E_SET_STATIC_THRESHOLD, set_param},
1131 {VP8E_SET_TOKEN_PARTITIONS, set_param},
1132 {VP8E_GET_LAST_QUANTIZER, get_param},
1133 {VP8E_GET_LAST_QUANTIZER_64, get_param},
1134 {VP8E_SET_ARNR_MAXFRAMES, set_param},
1135 {VP8E_SET_ARNR_STRENGTH , set_param},
1136 {VP8E_SET_ARNR_TYPE , set_param},
John Koleszarb0da9b32010-12-17 09:43:39 -05001137 {VP8E_SET_TUNING, set_param},
Paul Wilkinse0846c92011-01-07 18:29:37 +00001138 {VP8E_SET_CQ_LEVEL, set_param},
John Koleszar1654ae92011-07-28 09:17:32 -04001139 {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param},
John Koleszar0ea50ce2010-05-18 11:58:33 -04001140 { -1, NULL},
1141};
1142
1143static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
1144{
1145 {
1146 0,
1147 {
1148 0, /* g_usage */
1149 0, /* g_threads */
1150 0, /* g_profile */
1151
1152 320, /* g_width */
1153 240, /* g_height */
1154 {1, 30}, /* g_timebase */
1155
1156 0, /* g_error_resilient */
1157
1158 VPX_RC_ONE_PASS, /* g_pass */
1159
1160 0, /* g_lag_in_frames */
1161
John Koleszar23216212010-09-02 09:32:03 -04001162 0, /* rc_dropframe_thresh */
John Koleszar0ea50ce2010-05-18 11:58:33 -04001163 0, /* rc_resize_allowed */
1164 60, /* rc_resize_down_thresold */
1165 30, /* rc_resize_up_thresold */
1166
1167 VPX_VBR, /* rc_end_usage */
1168#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1169 {0}, /* rc_twopass_stats_in */
1170#endif
1171 256, /* rc_target_bandwidth */
John Koleszar0ea50ce2010-05-18 11:58:33 -04001172 4, /* rc_min_quantizer */
1173 63, /* rc_max_quantizer */
John Koleszarc99f9d72011-04-11 11:29:23 -04001174 100, /* rc_undershoot_pct */
1175 100, /* rc_overshoot_pct */
John Koleszar0ea50ce2010-05-18 11:58:33 -04001176
1177 6000, /* rc_max_buffer_size */
1178 4000, /* rc_buffer_initial_size; */
1179 5000, /* rc_buffer_optimal_size; */
1180
1181 50, /* rc_two_pass_vbrbias */
1182 0, /* rc_two_pass_vbrmin_section */
1183 400, /* rc_two_pass_vbrmax_section */
1184
1185 /* keyframing settings (kf) */
1186 VPX_KF_AUTO, /* g_kfmode*/
1187 0, /* kf_min_dist */
1188 9999, /* kf_max_dist */
1189
1190#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1191 1, /* g_delete_first_pass_file */
1192 "vp8.fpf" /* first pass filename */
1193#endif
Adrian Grange217591f2011-10-06 15:49:11 -07001194
1195 1, /* ts_number_layers */
1196 {0}, /* ts_target_bitrate */
1197 {0}, /* ts_rate_decimator */
1198 0, /* ts_periodicity */
1199 {0}, /* ts_layer_id */
John Koleszar0ea50ce2010-05-18 11:58:33 -04001200 }},
1201 { -1, {NOT_IMPLEMENTED}}
1202};
1203
1204
1205#ifndef VERSION_STRING
1206#define VERSION_STRING
1207#endif
John Koleszarfa7a55b2010-09-21 10:35:52 -04001208CODEC_INTERFACE(vpx_codec_vp8_cx) =
John Koleszar0ea50ce2010-05-18 11:58:33 -04001209{
John Koleszar317a6662010-06-10 12:08:01 -04001210 "WebM Project VP8 Encoder" VERSION_STRING,
John Koleszar0ea50ce2010-05-18 11:58:33 -04001211 VPX_CODEC_INTERNAL_ABI_VERSION,
Stefan Holmer7296b3f2011-06-13 16:42:27 +02001212 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
1213 VPX_CODEC_CAP_OUTPUT_PARTITION,
John Koleszar0ea50ce2010-05-18 11:58:33 -04001214 /* vpx_codec_caps_t caps; */
1215 vp8e_init, /* vpx_codec_init_fn_t init; */
1216 vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1217 vp8e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1218 NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */
1219 NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */
1220 {
1221 NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */
1222 NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */
1223 NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */
1224 NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */
1225 },
1226 {
1227 vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1228 vp8e_encode, /* vpx_codec_encode_fn_t encode; */
1229 vp8e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1230 vp8e_set_config,
1231 NOT_IMPLEMENTED,
1232 vp8e_get_preview,
1233 } /* encoder functions */
1234};
1235
1236
1237/*
1238 * BEGIN BACKWARDS COMPATIBILITY SHIM.
1239 */
1240#define FORCE_KEY 2
1241static vpx_codec_err_t api1_control(vpx_codec_alg_priv_t *ctx,
1242 int ctrl_id,
1243 va_list args)
1244{
1245 vpx_codec_ctrl_fn_map_t *entry;
1246
1247 switch (ctrl_id)
1248 {
1249 case VP8E_SET_FLUSHFLAG:
1250 /* VP8 sample code did VP8E_SET_FLUSHFLAG followed by
1251 * vpx_codec_get_cx_data() rather than vpx_codec_encode().
1252 */
1253 return vp8e_encode(ctx, NULL, 0, 0, 0, 0);
1254 case VP8E_SET_FRAMETYPE:
1255 ctx->base.enc.tbd |= FORCE_KEY;
1256 return VPX_CODEC_OK;
1257 }
1258
1259 for (entry = vp8e_ctf_maps; entry && entry->fn; entry++)
1260 {
1261 if (!entry->ctrl_id || entry->ctrl_id == ctrl_id)
1262 {
1263 return entry->fn(ctx, ctrl_id, args);
1264 }
1265 }
1266
1267 return VPX_CODEC_ERROR;
1268}
1269
1270
1271static vpx_codec_ctrl_fn_map_t api1_ctrl_maps[] =
1272{
1273 {0, api1_control},
1274 { -1, NULL}
1275};
1276
1277
1278static vpx_codec_err_t api1_encode(vpx_codec_alg_priv_t *ctx,
1279 const vpx_image_t *img,
1280 vpx_codec_pts_t pts,
1281 unsigned long duration,
1282 vpx_enc_frame_flags_t flags,
1283 unsigned long deadline)
1284{
1285 int force = ctx->base.enc.tbd;
1286
1287 ctx->base.enc.tbd = 0;
1288 return vp8e_encode
1289 (ctx,
1290 img,
1291 pts,
1292 duration,
1293 flags | ((force & FORCE_KEY) ? VPX_EFLAG_FORCE_KF : 0),
1294 deadline);
1295}
1296
1297
1298vpx_codec_iface_t vpx_enc_vp8_algo =
1299{
John Koleszar317a6662010-06-10 12:08:01 -04001300 "WebM Project VP8 Encoder (Deprecated API)" VERSION_STRING,
John Koleszar0ea50ce2010-05-18 11:58:33 -04001301 VPX_CODEC_INTERNAL_ABI_VERSION,
1302 VPX_CODEC_CAP_ENCODER,
1303 /* vpx_codec_caps_t caps; */
1304 vp8e_init, /* vpx_codec_init_fn_t init; */
1305 vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1306 api1_ctrl_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1307 NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */
1308 NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */
1309 {NOT_IMPLEMENTED}, /* decoder functions */
1310 {
1311 vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1312 api1_encode, /* vpx_codec_encode_fn_t encode; */
1313 vp8e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1314 vp8e_set_config,
1315 NOT_IMPLEMENTED,
1316 vp8e_get_preview,
1317 } /* encoder functions */
1318};