Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1010)

Side by Side Diff: source/libvpx/vpx/src/svc_encodeframe.c

Issue 592203002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vpx/exports_enc ('k') | source/libvpx/vpx/src/vpx_encoder.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 /** 11 /**
12 * @file 12 * @file
13 * VP9 SVC encoding support via libvpx 13 * VP9 SVC encoding support via libvpx
14 */ 14 */
15 15
16 #include <assert.h> 16 #include <assert.h>
17 #include <math.h> 17 #include <math.h>
18 #include <limits.h>
18 #include <stdarg.h> 19 #include <stdarg.h>
19 #include <stdio.h> 20 #include <stdio.h>
20 #include <stdlib.h> 21 #include <stdlib.h>
21 #include <string.h> 22 #include <string.h>
22 #define VPX_DISABLE_CTRL_TYPECHECKS 1 23 #define VPX_DISABLE_CTRL_TYPECHECKS 1
23 #define VPX_CODEC_DISABLE_COMPAT 1
24 #include "./vpx_config.h" 24 #include "./vpx_config.h"
25 #include "vpx/svc_context.h" 25 #include "vpx/svc_context.h"
26 #include "vpx/vp8cx.h" 26 #include "vpx/vp8cx.h"
27 #include "vpx/vpx_encoder.h" 27 #include "vpx/vpx_encoder.h"
28 #include "vpx_mem/vpx_mem.h" 28 #include "vpx_mem/vpx_mem.h"
29 #include "vp9/common/vp9_onyxc_int.h" 29 #include "vp9/common/vp9_onyxc_int.h"
30 30
31 #ifdef __MINGW32__ 31 #ifdef __MINGW32__
32 #define strtok_r strtok_s 32 #define strtok_r strtok_s
33 #ifndef MINGW_HAS_SECURE_API 33 #ifndef MINGW_HAS_SECURE_API
34 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h 34 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h
35 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context); 35 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
36 #endif /* MINGW_HAS_SECURE_API */ 36 #endif /* MINGW_HAS_SECURE_API */
37 #endif /* __MINGW32__ */ 37 #endif /* __MINGW32__ */
38 38
39 #ifdef _MSC_VER 39 #ifdef _MSC_VER
40 #define strdup _strdup 40 #define strdup _strdup
41 #define strtok_r strtok_s 41 #define strtok_r strtok_s
42 #endif 42 #endif
43 43
44 #define SVC_REFERENCE_FRAMES 8 44 #define SVC_REFERENCE_FRAMES 8
45 #define SUPERFRAME_SLOTS (8) 45 #define SUPERFRAME_SLOTS (8)
46 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) 46 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
47 #define OPTION_BUFFER_SIZE 256 47 #define OPTION_BUFFER_SIZE 1024
48 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v 48 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v
49 49
50 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27"; 50 #define MAX_QUANTIZER 63
51 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16"; 51
52 static const int DEFAULT_SCALE_FACTORS_NUM[VPX_SS_MAX_LAYERS] = {
53 4, 5, 7, 11, 16
54 };
55
56 static const int DEFAULT_SCALE_FACTORS_DEN[VPX_SS_MAX_LAYERS] = {
57 16, 16, 16, 16, 16
58 };
59
60 typedef enum {
61 QUANTIZER = 0,
62 BITRATE,
63 SCALE_FACTOR,
64 AUTO_ALT_REF,
65 ALL_OPTION_TYPES
66 } LAYER_OPTION_TYPE;
67
68 static const int option_max_values[ALL_OPTION_TYPES] = {
69 63, INT_MAX, INT_MAX, 1
70 };
71
72 static const int option_min_values[ALL_OPTION_TYPES] = {
73 0, 0, 1, 0
74 };
52 75
53 // One encoded frame 76 // One encoded frame
54 typedef struct FrameData { 77 typedef struct FrameData {
55 void *buf; // compressed data buffer 78 void *buf; // compressed data buffer
56 size_t size; // length of compressed data 79 size_t size; // length of compressed data
57 vpx_codec_frame_flags_t flags; /**< flags for this frame */ 80 vpx_codec_frame_flags_t flags; /**< flags for this frame */
58 struct FrameData *next; 81 struct FrameData *next;
59 } FrameData; 82 } FrameData;
60 83
61 typedef struct SvcInternal { 84 typedef struct SvcInternal {
62 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options 85 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
63 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers
64 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors
65 86
66 // values extracted from option, quantizers 87 // values extracted from option, quantizers
67 int scaling_factor_num[VPX_SS_MAX_LAYERS]; 88 vpx_svc_extra_cfg_t svc_params;
68 int scaling_factor_den[VPX_SS_MAX_LAYERS];
69 int quantizer[VPX_SS_MAX_LAYERS];
70 int enable_auto_alt_ref[VPX_SS_MAX_LAYERS]; 89 int enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
90 int bitrates[VPX_SS_MAX_LAYERS];
71 91
72 // accumulated statistics 92 // accumulated statistics
73 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V 93 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V
74 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; 94 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS];
75 uint32_t bytes_sum[VPX_SS_MAX_LAYERS]; 95 uint32_t bytes_sum[VPX_SS_MAX_LAYERS];
76 96
77 // codec encoding values 97 // codec encoding values
78 int width; // width of highest layer 98 int width; // width of highest layer
79 int height; // height of highest layer 99 int height; // height of highest layer
80 int kf_dist; // distance between keyframes 100 int kf_dist; // distance between keyframes
81 101
82 // state variables 102 // state variables
83 int encode_frame_count; 103 int psnr_pkt_received;
84 int frame_received;
85 int frame_within_gop;
86 int layers;
87 int layer; 104 int layer;
88 int is_keyframe;
89 int use_multiple_frame_contexts; 105 int use_multiple_frame_contexts;
90 106
91 FrameData *frame_list;
92 FrameData *frame_temp;
93
94 char *rc_stats_buf;
95 size_t rc_stats_buf_size;
96 size_t rc_stats_buf_used;
97
98 char message_buffer[2048]; 107 char message_buffer[2048];
99 vpx_codec_ctx_t *codec_ctx; 108 vpx_codec_ctx_t *codec_ctx;
100 } SvcInternal; 109 } SvcInternal;
101 110
102 // create FrameData from encoder output
103 static struct FrameData *fd_create(void *buf, size_t size,
104 vpx_codec_frame_flags_t flags) {
105 struct FrameData *const frame_data =
106 (struct FrameData *)vpx_malloc(sizeof(*frame_data));
107 if (frame_data == NULL) {
108 return NULL;
109 }
110 frame_data->buf = vpx_malloc(size);
111 if (frame_data->buf == NULL) {
112 vpx_free(frame_data);
113 return NULL;
114 }
115 vpx_memcpy(frame_data->buf, buf, size);
116 frame_data->size = size;
117 frame_data->flags = flags;
118 return frame_data;
119 }
120
121 // free FrameData
122 static void fd_free(struct FrameData *p) {
123 if (p) {
124 if (p->buf)
125 vpx_free(p->buf);
126 vpx_free(p);
127 }
128 }
129
130 // add FrameData to list
131 static void fd_list_add(struct FrameData **list, struct FrameData *layer_data) {
132 struct FrameData **p = list;
133
134 while (*p != NULL) p = &(*p)->next;
135 *p = layer_data;
136 layer_data->next = NULL;
137 }
138
139 // free FrameData list
140 static void fd_free_list(struct FrameData *list) {
141 struct FrameData *p = list;
142
143 while (p) {
144 list = list->next;
145 fd_free(p);
146 p = list;
147 }
148 }
149
150 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) { 111 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) {
151 if (svc_ctx == NULL) return NULL; 112 if (svc_ctx == NULL) return NULL;
152 if (svc_ctx->internal == NULL) { 113 if (svc_ctx->internal == NULL) {
153 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si)); 114 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si));
154 if (si != NULL) { 115 if (si != NULL) {
155 memset(si, 0, sizeof(*si)); 116 memset(si, 0, sizeof(*si));
156 } 117 }
157 svc_ctx->internal = si; 118 svc_ctx->internal = si;
158 } 119 }
159 return (SvcInternal *)svc_ctx->internal; 120 return (SvcInternal *)svc_ctx->internal;
(...skipping 30 matching lines...) Expand all
190 strncat(si->message_buffer, buf, 151 strncat(si->message_buffer, buf,
191 sizeof(si->message_buffer) - strlen(si->message_buffer) - 1); 152 sizeof(si->message_buffer) - strlen(si->message_buffer) - 1);
192 } 153 }
193 154
194 if (level == SVC_LOG_ERROR) { 155 if (level == SVC_LOG_ERROR) {
195 si->codec_ctx->err_detail = si->message_buffer; 156 si->codec_ctx->err_detail = si->message_buffer;
196 } 157 }
197 return retval; 158 return retval;
198 } 159 }
199 160
200 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx, 161 static vpx_codec_err_t extract_option(LAYER_OPTION_TYPE type,
201 const char *quantizer_values) { 162 char *input,
163 int *value0,
164 int *value1) {
165 if (type == SCALE_FACTOR) {
166 *value0 = strtol(input, &input, 10);
167 if (*input++ != '/')
168 return VPX_CODEC_INVALID_PARAM;
169 *value1 = strtol(input, &input, 10);
170
171 if (*value0 < option_min_values[SCALE_FACTOR] ||
172 *value1 < option_min_values[SCALE_FACTOR] ||
173 *value0 > option_max_values[SCALE_FACTOR] ||
174 *value1 > option_max_values[SCALE_FACTOR] ||
175 *value0 > *value1) // num shouldn't be greater than den
176 return VPX_CODEC_INVALID_PARAM;
177 } else {
178 *value0 = atoi(input);
179 if (*value0 < option_min_values[type] ||
180 *value0 > option_max_values[type])
181 return VPX_CODEC_INVALID_PARAM;
182 }
183 return VPX_CODEC_OK;
184 }
185
186 static vpx_codec_err_t parse_layer_options_from_string(SvcContext *svc_ctx,
187 LAYER_OPTION_TYPE type,
188 const char *input,
189 int *option0,
190 int *option1) {
191 int i;
192 vpx_codec_err_t res = VPX_CODEC_OK;
202 char *input_string; 193 char *input_string;
203 char *token; 194 char *token;
204 const char *delim = ","; 195 const char *delim = ",";
205 char *save_ptr; 196 char *save_ptr;
206 int found = 0;
207 int i, q;
208 vpx_codec_err_t res = VPX_CODEC_OK;
209 SvcInternal *const si = get_svc_internal(svc_ctx);
210 197
211 if (quantizer_values == NULL || strlen(quantizer_values) == 0) { 198 if (input == NULL || option0 == NULL ||
212 input_string = strdup(DEFAULT_QUANTIZER_VALUES); 199 (option1 == NULL && type == SCALE_FACTOR))
213 } else { 200 return VPX_CODEC_INVALID_PARAM;
214 input_string = strdup(quantizer_values);
215 }
216 201
202 input_string = strdup(input);
217 token = strtok_r(input_string, delim, &save_ptr); 203 token = strtok_r(input_string, delim, &save_ptr);
218 for (i = 0; i < svc_ctx->spatial_layers; ++i) { 204 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
219 if (token != NULL) { 205 if (token != NULL) {
220 q = atoi(token); 206 res = extract_option(type, token, option0 + i, option1 + i);
221 if (q <= 0 || q > 100) { 207 if (res != VPX_CODEC_OK)
222 svc_log(svc_ctx, SVC_LOG_ERROR,
223 "svc-quantizer-values: invalid value %s\n", token);
224 res = VPX_CODEC_INVALID_PARAM;
225 break; 208 break;
226 }
227 token = strtok_r(NULL, delim, &save_ptr); 209 token = strtok_r(NULL, delim, &save_ptr);
228 found = i + 1;
229 } else { 210 } else {
230 q = 0; 211 break;
231 } 212 }
232 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
233 } 213 }
234 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) { 214 if (res == VPX_CODEC_OK && i != svc_ctx->spatial_layers) {
235 svc_log(svc_ctx, SVC_LOG_ERROR, 215 svc_log(svc_ctx, SVC_LOG_ERROR,
236 "svc: quantizers: %d values required, but only %d specified\n", 216 "svc: layer params type: %d %d values required, "
237 svc_ctx->spatial_layers, found); 217 "but only %d specified\n", type, svc_ctx->spatial_layers, i);
238 res = VPX_CODEC_INVALID_PARAM;
239 }
240 free(input_string);
241 return res;
242 }
243
244 static vpx_codec_err_t parse_auto_alt_ref(SvcContext *svc_ctx,
245 const char *alt_ref_options) {
246 char *input_string;
247 char *token;
248 const char *delim = ",";
249 char *save_ptr;
250 int found = 0, enabled = 0;
251 int i, value;
252 vpx_codec_err_t res = VPX_CODEC_OK;
253 SvcInternal *const si = get_svc_internal(svc_ctx);
254
255 if (alt_ref_options == NULL || strlen(alt_ref_options) == 0) {
256 return VPX_CODEC_INVALID_PARAM;
257 } else {
258 input_string = strdup(alt_ref_options);
259 }
260
261 token = strtok_r(input_string, delim, &save_ptr);
262 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
263 if (token != NULL) {
264 value = atoi(token);
265 if (value < 0 || value > 1) {
266 svc_log(svc_ctx, SVC_LOG_ERROR,
267 "enable auto alt ref values: invalid value %s\n", token);
268 res = VPX_CODEC_INVALID_PARAM;
269 break;
270 }
271 token = strtok_r(NULL, delim, &save_ptr);
272 found = i + 1;
273 } else {
274 value = 0;
275 }
276 si->enable_auto_alt_ref[i] = value;
277 if (value > 0)
278 ++enabled;
279 }
280 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
281 svc_log(svc_ctx, SVC_LOG_ERROR,
282 "svc: quantizers: %d values required, but only %d specified\n",
283 svc_ctx->spatial_layers, found);
284 res = VPX_CODEC_INVALID_PARAM;
285 }
286 if (enabled > REF_FRAMES - svc_ctx->spatial_layers) {
287 svc_log(svc_ctx, SVC_LOG_ERROR,
288 "svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could"
289 "enabled auto alt reference frame, but % layers are enabled\n",
290 REF_FRAMES - svc_ctx->spatial_layers, enabled);
291 res = VPX_CODEC_INVALID_PARAM;
292 }
293 free(input_string);
294 return res;
295 }
296
297 static void log_invalid_scale_factor(SvcContext *svc_ctx, const char *value) {
298 svc_log(svc_ctx, SVC_LOG_ERROR, "svc scale-factors: invalid value %s\n",
299 value);
300 }
301
302 static vpx_codec_err_t parse_scale_factors(SvcContext *svc_ctx,
303 const char *scale_factors) {
304 char *input_string;
305 char *token;
306 const char *delim = ",";
307 char *save_ptr;
308 int found = 0;
309 int i;
310 int64_t num, den;
311 vpx_codec_err_t res = VPX_CODEC_OK;
312 SvcInternal *const si = get_svc_internal(svc_ctx);
313
314 if (scale_factors == NULL || strlen(scale_factors) == 0) {
315 input_string = strdup(DEFAULT_SCALE_FACTORS);
316 } else {
317 input_string = strdup(scale_factors);
318 }
319 token = strtok_r(input_string, delim, &save_ptr);
320 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
321 num = den = 0;
322 if (token != NULL) {
323 num = strtol(token, &token, 10);
324 if (num <= 0) {
325 log_invalid_scale_factor(svc_ctx, token);
326 res = VPX_CODEC_INVALID_PARAM;
327 break;
328 }
329 if (*token++ != '/') {
330 log_invalid_scale_factor(svc_ctx, token);
331 res = VPX_CODEC_INVALID_PARAM;
332 break;
333 }
334 den = strtol(token, &token, 10);
335 if (den <= 0) {
336 log_invalid_scale_factor(svc_ctx, token);
337 res = VPX_CODEC_INVALID_PARAM;
338 break;
339 }
340 token = strtok_r(NULL, delim, &save_ptr);
341 found = i + 1;
342 }
343 si->scaling_factor_num[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
344 (int)num;
345 si->scaling_factor_den[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
346 (int)den;
347 }
348 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
349 svc_log(svc_ctx, SVC_LOG_ERROR,
350 "svc: scale-factors: %d values required, but only %d specified\n",
351 svc_ctx->spatial_layers, found);
352 res = VPX_CODEC_INVALID_PARAM; 218 res = VPX_CODEC_INVALID_PARAM;
353 } 219 }
354 free(input_string); 220 free(input_string);
355 return res; 221 return res;
356 } 222 }
357 223
358 /** 224 /**
359 * Parse SVC encoding options 225 * Parse SVC encoding options
360 * Format: encoding-mode=<svc_mode>,layers=<layer_count> 226 * Format: encoding-mode=<svc_mode>,layers=<layer_count>
361 * scale-factors=<n1>/<d1>,<n2>/<d2>,... 227 * scale-factors=<n1>/<d1>,<n2>/<d2>,...
362 * quantizers=<q1>,<q2>,... 228 * quantizers=<q1>,<q2>,...
363 * svc_mode = [i|ip|alt_ip|gf] 229 * svc_mode = [i|ip|alt_ip|gf]
364 */ 230 */
365 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { 231 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
366 char *input_string; 232 char *input_string;
367 char *option_name; 233 char *option_name;
368 char *option_value; 234 char *option_value;
369 char *input_ptr; 235 char *input_ptr;
370 SvcInternal *const si = get_svc_internal(svc_ctx); 236 SvcInternal *const si = get_svc_internal(svc_ctx);
371 vpx_codec_err_t res = VPX_CODEC_OK; 237 vpx_codec_err_t res = VPX_CODEC_OK;
238 int i, alt_ref_enabled = 0;
372 239
373 if (options == NULL) return VPX_CODEC_OK; 240 if (options == NULL) return VPX_CODEC_OK;
374 input_string = strdup(options); 241 input_string = strdup(options);
375 242
376 // parse option name 243 // parse option name
377 option_name = strtok_r(input_string, "=", &input_ptr); 244 option_name = strtok_r(input_string, "=", &input_ptr);
378 while (option_name != NULL) { 245 while (option_name != NULL) {
379 // parse option value 246 // parse option value
380 option_value = strtok_r(NULL, " ", &input_ptr); 247 option_value = strtok_r(NULL, " ", &input_ptr);
381 if (option_value == NULL) { 248 if (option_value == NULL) {
382 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n", 249 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n",
383 option_name); 250 option_name);
384 res = VPX_CODEC_INVALID_PARAM; 251 res = VPX_CODEC_INVALID_PARAM;
385 break; 252 break;
386 } 253 }
387 if (strcmp("spatial-layers", option_name) == 0) { 254 if (strcmp("spatial-layers", option_name) == 0) {
388 svc_ctx->spatial_layers = atoi(option_value); 255 svc_ctx->spatial_layers = atoi(option_value);
389 } else if (strcmp("temporal-layers", option_name) == 0) { 256 } else if (strcmp("temporal-layers", option_name) == 0) {
390 svc_ctx->temporal_layers = atoi(option_value); 257 svc_ctx->temporal_layers = atoi(option_value);
391 } else if (strcmp("scale-factors", option_name) == 0) { 258 } else if (strcmp("scale-factors", option_name) == 0) {
392 res = parse_scale_factors(svc_ctx, option_value); 259 res = parse_layer_options_from_string(svc_ctx, SCALE_FACTOR, option_value,
260 si->svc_params.scaling_factor_num,
261 si->svc_params.scaling_factor_den);
393 if (res != VPX_CODEC_OK) break; 262 if (res != VPX_CODEC_OK) break;
394 } else if (strcmp("quantizers", option_name) == 0) { 263 } else if (strcmp("max-quantizers", option_name) == 0) {
395 res = parse_quantizer_values(svc_ctx, option_value); 264 res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
265 si->svc_params.max_quantizers,
266 NULL);
267 if (res != VPX_CODEC_OK) break;
268 } else if (strcmp("min-quantizers", option_name) == 0) {
269 res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
270 si->svc_params.min_quantizers,
271 NULL);
396 if (res != VPX_CODEC_OK) break; 272 if (res != VPX_CODEC_OK) break;
397 } else if (strcmp("auto-alt-refs", option_name) == 0) { 273 } else if (strcmp("auto-alt-refs", option_name) == 0) {
398 res = parse_auto_alt_ref(svc_ctx, option_value); 274 res = parse_layer_options_from_string(svc_ctx, AUTO_ALT_REF, option_value,
275 si->enable_auto_alt_ref, NULL);
276 if (res != VPX_CODEC_OK) break;
277 } else if (strcmp("bitrates", option_name) == 0) {
278 res = parse_layer_options_from_string(svc_ctx, BITRATE, option_value,
279 si->bitrates, NULL);
399 if (res != VPX_CODEC_OK) break; 280 if (res != VPX_CODEC_OK) break;
400 } else if (strcmp("multi-frame-contexts", option_name) == 0) { 281 } else if (strcmp("multi-frame-contexts", option_name) == 0) {
401 si->use_multiple_frame_contexts = atoi(option_value); 282 si->use_multiple_frame_contexts = atoi(option_value);
402 } else { 283 } else {
403 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name); 284 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
404 res = VPX_CODEC_INVALID_PARAM; 285 res = VPX_CODEC_INVALID_PARAM;
405 break; 286 break;
406 } 287 }
407 option_name = strtok_r(NULL, "=", &input_ptr); 288 option_name = strtok_r(NULL, "=", &input_ptr);
408 } 289 }
409 free(input_string); 290 free(input_string);
410 291
292 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
293 if (si->svc_params.max_quantizers[i] > MAX_QUANTIZER ||
294 si->svc_params.max_quantizers[i] < 0 ||
295 si->svc_params.min_quantizers[i] > si->svc_params.max_quantizers[i] ||
296 si->svc_params.min_quantizers[i] < 0)
297 res = VPX_CODEC_INVALID_PARAM;
298 }
299
411 if (si->use_multiple_frame_contexts && 300 if (si->use_multiple_frame_contexts &&
412 (svc_ctx->spatial_layers > 3 || 301 (svc_ctx->spatial_layers > 3 ||
413 svc_ctx->spatial_layers * svc_ctx->temporal_layers > 4)) 302 svc_ctx->spatial_layers * svc_ctx->temporal_layers > 4))
414 res = VPX_CODEC_INVALID_PARAM; 303 res = VPX_CODEC_INVALID_PARAM;
415 304
305 for (i = 0; i < svc_ctx->spatial_layers; ++i)
306 alt_ref_enabled += si->enable_auto_alt_ref[i];
307 if (alt_ref_enabled > REF_FRAMES - svc_ctx->spatial_layers) {
308 svc_log(svc_ctx, SVC_LOG_ERROR,
309 "svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could"
310 "enabled auto alt reference frame, but % layers are enabled\n",
311 REF_FRAMES - svc_ctx->spatial_layers, alt_ref_enabled);
312 res = VPX_CODEC_INVALID_PARAM;
313 }
314
416 return res; 315 return res;
417 } 316 }
418 317
419 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) { 318 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) {
420 SvcInternal *const si = get_svc_internal(svc_ctx); 319 SvcInternal *const si = get_svc_internal(svc_ctx);
421 if (svc_ctx == NULL || options == NULL || si == NULL) { 320 if (svc_ctx == NULL || options == NULL || si == NULL) {
422 return VPX_CODEC_INVALID_PARAM; 321 return VPX_CODEC_INVALID_PARAM;
423 } 322 }
424 strncpy(si->options, options, sizeof(si->options)); 323 strncpy(si->options, options, sizeof(si->options));
425 si->options[sizeof(si->options) - 1] = '\0'; 324 si->options[sizeof(si->options) - 1] = '\0';
426 return VPX_CODEC_OK; 325 return VPX_CODEC_OK;
427 } 326 }
428 327
429 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx, 328 void assign_layer_bitrates(const SvcContext *svc_ctx,
430 const char *quantizers) { 329 vpx_codec_enc_cfg_t *const enc_cfg) {
431 SvcInternal *const si = get_svc_internal(svc_ctx); 330 int i;
432 if (svc_ctx == NULL || quantizers == NULL || si == NULL) { 331 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
433 return VPX_CODEC_INVALID_PARAM; 332
333 if (si->bitrates[0] != 0) {
334 enc_cfg->rc_target_bitrate = 0;
335 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
336 enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i];
337 enc_cfg->rc_target_bitrate += si->bitrates[i];
338 }
339 } else {
340 float total = 0;
341 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
342
343 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
344 if (si->svc_params.scaling_factor_den[i] > 0) {
345 alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 /
346 si->svc_params.scaling_factor_den[i]);
347
348 alloc_ratio[i] *= alloc_ratio[i];
349 total += alloc_ratio[i];
350 }
351 }
352
353 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
354 if (total > 0) {
355 enc_cfg->ss_target_bitrate[i] = (unsigned int)
356 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
357 }
358 }
434 } 359 }
435 strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
436 si->quantizers[sizeof(si->quantizers) - 1] = '\0';
437 return VPX_CODEC_OK;
438 }
439
440 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx,
441 const char *scale_factors) {
442 SvcInternal *const si = get_svc_internal(svc_ctx);
443 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) {
444 return VPX_CODEC_INVALID_PARAM;
445 }
446 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors));
447 si->scale_factors[sizeof(si->scale_factors) - 1] = '\0';
448 return VPX_CODEC_OK;
449 } 360 }
450 361
451 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, 362 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
452 vpx_codec_iface_t *iface, 363 vpx_codec_iface_t *iface,
453 vpx_codec_enc_cfg_t *enc_cfg) { 364 vpx_codec_enc_cfg_t *enc_cfg) {
454 vpx_codec_err_t res; 365 vpx_codec_err_t res;
455 int i; 366 int i;
456 SvcInternal *const si = get_svc_internal(svc_ctx); 367 SvcInternal *const si = get_svc_internal(svc_ctx);
457 if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL || 368 if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL ||
458 enc_cfg == NULL) { 369 enc_cfg == NULL) {
(...skipping 15 matching lines...) Expand all
474 385
475 if (svc_ctx->spatial_layers == 0) 386 if (svc_ctx->spatial_layers == 0)
476 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; 387 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS;
477 if (svc_ctx->spatial_layers < 1 || 388 if (svc_ctx->spatial_layers < 1 ||
478 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { 389 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
479 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", 390 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
480 svc_ctx->spatial_layers); 391 svc_ctx->spatial_layers);
481 return VPX_CODEC_INVALID_PARAM; 392 return VPX_CODEC_INVALID_PARAM;
482 } 393 }
483 394
484 res = parse_quantizer_values(svc_ctx, si->quantizers); 395 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
485 if (res != VPX_CODEC_OK) return res; 396 si->svc_params.max_quantizers[i] = MAX_QUANTIZER;
486 397 si->svc_params.min_quantizers[i] = 0;
487 res = parse_scale_factors(svc_ctx, si->scale_factors); 398 si->svc_params.scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i];
488 if (res != VPX_CODEC_OK) return res; 399 si->svc_params.scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i];
400 }
489 401
490 // Parse aggregate command line options. Options must start with 402 // Parse aggregate command line options. Options must start with
491 // "layers=xx" then followed by other options 403 // "layers=xx" then followed by other options
492 res = parse_options(svc_ctx, si->options); 404 res = parse_options(svc_ctx, si->options);
493 if (res != VPX_CODEC_OK) return res; 405 if (res != VPX_CODEC_OK) return res;
494 406
495 if (svc_ctx->spatial_layers < 1) 407 if (svc_ctx->spatial_layers < 1)
496 svc_ctx->spatial_layers = 1; 408 svc_ctx->spatial_layers = 1;
497 if (svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) 409 if (svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS)
498 svc_ctx->spatial_layers = VPX_SS_MAX_LAYERS; 410 svc_ctx->spatial_layers = VPX_SS_MAX_LAYERS;
499 411
500 if (svc_ctx->temporal_layers < 1) 412 if (svc_ctx->temporal_layers < 1)
501 svc_ctx->temporal_layers = 1; 413 svc_ctx->temporal_layers = 1;
502 if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS) 414 if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS)
503 svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS; 415 svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS;
504 416
505 si->layers = svc_ctx->spatial_layers; 417 assign_layer_bitrates(svc_ctx, enc_cfg);
506
507 // Assign target bitrate for each layer. We calculate the ratio
508 // from the resolution for now.
509 // TODO(Minghai): Optimize the mechanism of allocating bits after
510 // implementing svc two pass rate control.
511 if (si->layers > 1) {
512 float total = 0;
513 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
514
515 assert(si->layers <= VPX_SS_MAX_LAYERS);
516 for (i = 0; i < si->layers; ++i) {
517 int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers;
518 if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) {
519 alloc_ratio[i] = (float)(si->scaling_factor_num[pos] * 1.0 /
520 si->scaling_factor_den[pos]);
521
522 alloc_ratio[i] *= alloc_ratio[i];
523 total += alloc_ratio[i];
524 }
525 }
526
527 for (i = 0; i < si->layers; ++i) {
528 if (total > 0) {
529 enc_cfg->ss_target_bitrate[i] = (unsigned int)
530 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
531 }
532 }
533 }
534 418
535 #if CONFIG_SPATIAL_SVC 419 #if CONFIG_SPATIAL_SVC
536 for (i = 0; i < si->layers; ++i) 420 for (i = 0; i < svc_ctx->spatial_layers; ++i)
537 enc_cfg->ss_enable_auto_alt_ref[i] = si->enable_auto_alt_ref[i]; 421 enc_cfg->ss_enable_auto_alt_ref[i] = si->enable_auto_alt_ref[i];
538 #endif 422 #endif
539 423
540 if (svc_ctx->temporal_layers > 1) { 424 if (svc_ctx->temporal_layers > 1) {
541 int i; 425 int i;
542 for (i = 0; i < svc_ctx->temporal_layers; ++i) { 426 for (i = 0; i < svc_ctx->temporal_layers; ++i) {
543 enc_cfg->ts_target_bitrate[i] = enc_cfg->rc_target_bitrate / 427 enc_cfg->ts_target_bitrate[i] = enc_cfg->rc_target_bitrate /
544 svc_ctx->temporal_layers; 428 svc_ctx->temporal_layers;
545 enc_cfg->ts_rate_decimator[i] = 1 << (svc_ctx->temporal_layers - 1 - i); 429 enc_cfg->ts_rate_decimator[i] = 1 << (svc_ctx->temporal_layers - 1 - i);
546 } 430 }
547 } 431 }
548 432
549 // modify encoder configuration 433 // modify encoder configuration
550 enc_cfg->ss_number_layers = si->layers; 434 enc_cfg->ss_number_layers = svc_ctx->spatial_layers;
551 enc_cfg->ts_number_layers = svc_ctx->temporal_layers; 435 enc_cfg->ts_number_layers = svc_ctx->temporal_layers;
552 436
553 // TODO(ivanmaltz): determine if these values need to be set explicitly for
554 // svc, or if the normal default/override mechanism can be used
555 enc_cfg->rc_dropframe_thresh = 0;
556 enc_cfg->rc_resize_allowed = 0;
557
558 if (enc_cfg->g_pass == VPX_RC_ONE_PASS) {
559 enc_cfg->rc_min_quantizer = 33;
560 enc_cfg->rc_max_quantizer = 33;
561 }
562
563 enc_cfg->rc_undershoot_pct = 100;
564 enc_cfg->rc_overshoot_pct = 15;
565 enc_cfg->rc_buf_initial_sz = 500;
566 enc_cfg->rc_buf_optimal_sz = 600;
567 enc_cfg->rc_buf_sz = 1000;
568 if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0) 437 if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0)
569 enc_cfg->g_error_resilient = 1; 438 enc_cfg->g_error_resilient = 1;
570 439
571 // Initialize codec 440 // Initialize codec
572 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR); 441 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR);
573 if (res != VPX_CODEC_OK) { 442 if (res != VPX_CODEC_OK) {
574 svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n"); 443 svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n");
575 return res; 444 return res;
576 } 445 }
577 446
578 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1); 447 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
579 vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1); 448 vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &si->svc_params);
580 449
581 return VPX_CODEC_OK; 450 return VPX_CODEC_OK;
582 } 451 }
583 452
584 vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
585 int layer,
586 unsigned int *width,
587 unsigned int *height) {
588 int w, h, index, num, den;
589 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
590
591 if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) {
592 return VPX_CODEC_INVALID_PARAM;
593 }
594 if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
595
596 index = layer + VPX_SS_MAX_LAYERS - si->layers;
597 num = si->scaling_factor_num[index];
598 den = si->scaling_factor_den[index];
599 if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
600
601 w = si->width * num / den;
602 h = si->height * num / den;
603
604 // make height and width even to make chrome player happy
605 w += w % 2;
606 h += h % 2;
607
608 *width = w;
609 *height = h;
610
611 return VPX_CODEC_OK;
612 }
613
614 static void set_svc_parameters(SvcContext *svc_ctx,
615 vpx_codec_ctx_t *codec_ctx) {
616 int layer, layer_index;
617 vpx_svc_parameters_t svc_params;
618 SvcInternal *const si = get_svc_internal(svc_ctx);
619
620 memset(&svc_params, 0, sizeof(svc_params));
621 svc_params.temporal_layer = 0;
622 svc_params.spatial_layer = si->layer;
623
624 layer = si->layer;
625 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
626 &svc_params.width,
627 &svc_params.height)) {
628 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
629 }
630 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
631
632 if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) {
633 svc_params.min_quantizer = si->quantizer[layer_index];
634 svc_params.max_quantizer = si->quantizer[layer_index];
635 } else {
636 svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer;
637 svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer;
638 }
639
640 svc_params.distance_from_i_frame = si->frame_within_gop;
641 vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &svc_params);
642 }
643
644 /** 453 /**
645 * Encode a frame into multiple layers 454 * Encode a frame into multiple layers
646 * Create a superframe containing the individual layers 455 * Create a superframe containing the individual layers
647 */ 456 */
648 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, 457 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
649 struct vpx_image *rawimg, vpx_codec_pts_t pts, 458 struct vpx_image *rawimg, vpx_codec_pts_t pts,
650 int64_t duration, int deadline) { 459 int64_t duration, int deadline) {
651 vpx_codec_err_t res; 460 vpx_codec_err_t res;
652 vpx_codec_iter_t iter; 461 vpx_codec_iter_t iter;
653 const vpx_codec_cx_pkt_t *cx_pkt; 462 const vpx_codec_cx_pkt_t *cx_pkt;
654 int layer_for_psnr = 0;
655 SvcInternal *const si = get_svc_internal(svc_ctx); 463 SvcInternal *const si = get_svc_internal(svc_ctx);
656 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { 464 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) {
657 return VPX_CODEC_INVALID_PARAM; 465 return VPX_CODEC_INVALID_PARAM;
658 } 466 }
659 467
660 svc_log_reset(svc_ctx); 468 svc_log_reset(svc_ctx);
661 si->rc_stats_buf_used = 0;
662
663 si->layers = svc_ctx->spatial_layers;
664 if (si->encode_frame_count == 0) {
665 si->frame_within_gop = 0;
666 }
667 si->is_keyframe = (si->frame_within_gop == 0);
668
669 if (rawimg != NULL) {
670 svc_log(svc_ctx, SVC_LOG_DEBUG,
671 "vpx_svc_encode layers: %d, frame_count: %d, "
672 "frame_within_gop: %d\n", si->layers, si->encode_frame_count,
673 si->frame_within_gop);
674 }
675
676 if (rawimg != NULL) {
677 // encode each layer
678 for (si->layer = 0; si->layer < si->layers; ++si->layer) {
679 set_svc_parameters(svc_ctx, codec_ctx);
680 }
681 }
682 469
683 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, 470 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0,
684 deadline); 471 deadline);
685 if (res != VPX_CODEC_OK) { 472 if (res != VPX_CODEC_OK) {
686 return res; 473 return res;
687 } 474 }
688 // save compressed data 475 // save compressed data
689 iter = NULL; 476 iter = NULL;
690 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { 477 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
691 switch (cx_pkt->kind) { 478 switch (cx_pkt->kind) {
692 case VPX_CODEC_CX_FRAME_PKT: { 479 #if CONFIG_SPATIAL_SVC
693 fd_list_add(&si->frame_list, fd_create(cx_pkt->data.frame.buf, 480 case VPX_CODEC_SPATIAL_SVC_LAYER_PSNR: {
694 cx_pkt->data.frame.sz, 481 int i;
695 cx_pkt->data.frame.flags)); 482 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
483 int j;
484 svc_log(svc_ctx, SVC_LOG_DEBUG,
485 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
486 "%2.3f %2.3f %2.3f %2.3f \n",
487 si->psnr_pkt_received, i,
488 cx_pkt->data.layer_psnr[i].psnr[0],
489 cx_pkt->data.layer_psnr[i].psnr[1],
490 cx_pkt->data.layer_psnr[i].psnr[2],
491 cx_pkt->data.layer_psnr[i].psnr[3]);
492 svc_log(svc_ctx, SVC_LOG_DEBUG,
493 "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
494 "%2.3f %2.3f %2.3f %2.3f \n",
495 si->psnr_pkt_received, i,
496 cx_pkt->data.layer_psnr[i].sse[0],
497 cx_pkt->data.layer_psnr[i].sse[1],
498 cx_pkt->data.layer_psnr[i].sse[2],
499 cx_pkt->data.layer_psnr[i].sse[3]);
696 500
697 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, " 501 for (j = 0; j < COMPONENTS; ++j) {
698 "pts: %d\n", si->frame_received, 502 si->psnr_sum[i][j] +=
699 (cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? 1 : 0, 503 cx_pkt->data.layer_psnr[i].psnr[j];
700 (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts); 504 si->sse_sum[i][j] += cx_pkt->data.layer_psnr[i].sse[j];
701 505 }
702 ++si->frame_received; 506 }
703 layer_for_psnr = 0; 507 ++si->psnr_pkt_received;
704 break; 508 break;
705 } 509 }
706 case VPX_CODEC_PSNR_PKT: {
707 int i;
708 svc_log(svc_ctx, SVC_LOG_DEBUG,
709 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
710 "%2.3f %2.3f %2.3f %2.3f \n",
711 si->frame_received, layer_for_psnr,
712 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
713 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
714 svc_log(svc_ctx, SVC_LOG_DEBUG,
715 "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
716 "%2.3f %2.3f %2.3f %2.3f \n",
717 si->frame_received, layer_for_psnr,
718 cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1],
719 cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]);
720 for (i = 0; i < COMPONENTS; i++) {
721 si->psnr_sum[layer_for_psnr][i] += cx_pkt->data.psnr.psnr[i];
722 si->sse_sum[layer_for_psnr][i] += cx_pkt->data.psnr.sse[i];
723 }
724 ++layer_for_psnr;
725 break;
726 }
727 case VPX_CODEC_STATS_PKT: {
728 size_t new_size = si->rc_stats_buf_used +
729 cx_pkt->data.twopass_stats.sz;
730
731 if (new_size > si->rc_stats_buf_size) {
732 char *p = (char*)realloc(si->rc_stats_buf, new_size);
733 if (p == NULL) {
734 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n");
735 return VPX_CODEC_MEM_ERROR;
736 }
737 si->rc_stats_buf = p;
738 si->rc_stats_buf_size = new_size;
739 }
740
741 memcpy(si->rc_stats_buf + si->rc_stats_buf_used,
742 cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz);
743 si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz;
744 break;
745 }
746 #if CONFIG_SPATIAL_SVC
747 case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: { 510 case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: {
748 int i; 511 int i;
749 for (i = 0; i < si->layers; ++i) 512 for (i = 0; i < svc_ctx->spatial_layers; ++i)
750 si->bytes_sum[i] += cx_pkt->data.layer_sizes[i]; 513 si->bytes_sum[i] += cx_pkt->data.layer_sizes[i];
751 break; 514 break;
752 } 515 }
753 #endif 516 #endif
754 default: { 517 default: {
755 break; 518 break;
756 } 519 }
757 } 520 }
758 } 521 }
759 522
760 if (rawimg != NULL) {
761 ++si->frame_within_gop;
762 ++si->encode_frame_count;
763 }
764
765 return VPX_CODEC_OK; 523 return VPX_CODEC_OK;
766 } 524 }
767 525
768 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { 526 const char *vpx_svc_get_message(const SvcContext *svc_ctx) {
769 const SvcInternal *const si = get_const_svc_internal(svc_ctx); 527 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
770 if (svc_ctx == NULL || si == NULL) return NULL; 528 if (svc_ctx == NULL || si == NULL) return NULL;
771 return si->message_buffer; 529 return si->message_buffer;
772 } 530 }
773 531
774 // We will maintain a list of output frame buffers since with lag_in_frame
775 // we need to output all frame buffers at the end. vpx_svc_get_buffer() will
776 // remove a frame buffer from the list the put it to a temporal pointer, which
777 // will be removed at the next vpx_svc_get_buffer() or when closing encoder.
778 void *vpx_svc_get_buffer(SvcContext *svc_ctx) {
779 SvcInternal *const si = get_svc_internal(svc_ctx);
780 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return NULL;
781
782 if (si->frame_temp)
783 fd_free(si->frame_temp);
784
785 si->frame_temp = si->frame_list;
786 si->frame_list = si->frame_list->next;
787
788 return si->frame_temp->buf;
789 }
790
791 size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) {
792 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
793 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0;
794 return si->frame_list->size;
795 }
796
797 int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) {
798 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
799 if (svc_ctx == NULL || si == NULL) return 0;
800 return si->encode_frame_count;
801 }
802
803 int vpx_svc_is_keyframe(const SvcContext *svc_ctx) {
804 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
805 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0;
806 return (si->frame_list->flags & VPX_FRAME_IS_KEY) != 0;
807 }
808
809 void vpx_svc_set_keyframe(SvcContext *svc_ctx) {
810 SvcInternal *const si = get_svc_internal(svc_ctx);
811 if (svc_ctx == NULL || si == NULL) return;
812 si->frame_within_gop = 0;
813 }
814
815 static double calc_psnr(double d) { 532 static double calc_psnr(double d) {
816 if (d == 0) return 100; 533 if (d == 0) return 100;
817 return -10.0 * log(d) / log(10.0); 534 return -10.0 * log(d) / log(10.0);
818 } 535 }
819 536
820 // dump accumulated statistics and reset accumulated values 537 // dump accumulated statistics and reset accumulated values
821 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { 538 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
822 int number_of_frames, encode_frame_count; 539 int number_of_frames;
823 int i, j; 540 int i, j;
824 uint32_t bytes_total = 0; 541 uint32_t bytes_total = 0;
825 double scale[COMPONENTS]; 542 double scale[COMPONENTS];
826 double psnr[COMPONENTS]; 543 double psnr[COMPONENTS];
827 double mse[COMPONENTS]; 544 double mse[COMPONENTS];
828 double y_scale; 545 double y_scale;
829 546
830 SvcInternal *const si = get_svc_internal(svc_ctx); 547 SvcInternal *const si = get_svc_internal(svc_ctx);
831 if (svc_ctx == NULL || si == NULL) return NULL; 548 if (svc_ctx == NULL || si == NULL) return NULL;
832 549
833 svc_log_reset(svc_ctx); 550 svc_log_reset(svc_ctx);
834 551
835 encode_frame_count = si->encode_frame_count; 552 number_of_frames = si->psnr_pkt_received;
836 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx); 553 if (number_of_frames <= 0) return vpx_svc_get_message(svc_ctx);
837 554
838 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); 555 svc_log(svc_ctx, SVC_LOG_INFO, "\n");
839 for (i = 0; i < si->layers; ++i) { 556 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
840 number_of_frames = encode_frame_count;
841 557
842 svc_log(svc_ctx, SVC_LOG_INFO, 558 svc_log(svc_ctx, SVC_LOG_INFO,
843 "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n", 559 "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n",
844 i, (double)si->psnr_sum[i][0] / number_of_frames, 560 i, (double)si->psnr_sum[i][0] / number_of_frames,
845 (double)si->psnr_sum[i][1] / number_of_frames, 561 (double)si->psnr_sum[i][1] / number_of_frames,
846 (double)si->psnr_sum[i][2] / number_of_frames, 562 (double)si->psnr_sum[i][2] / number_of_frames,
847 (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]); 563 (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]);
848 // the following psnr calculation is deduced from ffmpeg.c#print_report 564 // the following psnr calculation is deduced from ffmpeg.c#print_report
849 y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames; 565 y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames;
850 scale[1] = y_scale; 566 scale[1] = y_scale;
(...skipping 14 matching lines...) Expand all
865 bytes_total += si->bytes_sum[i]; 581 bytes_total += si->bytes_sum[i];
866 // clear sums for next time 582 // clear sums for next time
867 si->bytes_sum[i] = 0; 583 si->bytes_sum[i] = 0;
868 for (j = 0; j < COMPONENTS; ++j) { 584 for (j = 0; j < COMPONENTS; ++j) {
869 si->psnr_sum[i][j] = 0; 585 si->psnr_sum[i][j] = 0;
870 si->sse_sum[i][j] = 0; 586 si->sse_sum[i][j] = 0;
871 } 587 }
872 } 588 }
873 589
874 // only display statistics once 590 // only display statistics once
875 si->encode_frame_count = 0; 591 si->psnr_pkt_received = 0;
876 592
877 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); 593 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
878 return vpx_svc_get_message(svc_ctx); 594 return vpx_svc_get_message(svc_ctx);
879 } 595 }
880 596
881 void vpx_svc_release(SvcContext *svc_ctx) { 597 void vpx_svc_release(SvcContext *svc_ctx) {
882 SvcInternal *si; 598 SvcInternal *si;
883 if (svc_ctx == NULL) return; 599 if (svc_ctx == NULL) return;
884 // do not use get_svc_internal as it will unnecessarily allocate an 600 // do not use get_svc_internal as it will unnecessarily allocate an
885 // SvcInternal if it was not already allocated 601 // SvcInternal if it was not already allocated
886 si = (SvcInternal *)svc_ctx->internal; 602 si = (SvcInternal *)svc_ctx->internal;
887 if (si != NULL) { 603 if (si != NULL) {
888 fd_free(si->frame_temp);
889 fd_free_list(si->frame_list);
890 if (si->rc_stats_buf) {
891 free(si->rc_stats_buf);
892 }
893 free(si); 604 free(si);
894 svc_ctx->internal = NULL; 605 svc_ctx->internal = NULL;
895 } 606 }
896 } 607 }
897 608
898 size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx) {
899 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
900 if (svc_ctx == NULL || si == NULL) return 0;
901 return si->rc_stats_buf_used;
902 }
903
904 char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx) {
905 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
906 if (svc_ctx == NULL || si == NULL) return NULL;
907 return si->rc_stats_buf;
908 }
909
910
OLDNEW
« no previous file with comments | « source/libvpx/vpx/exports_enc ('k') | source/libvpx/vpx/src/vpx_encoder.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698