OLD | NEW |
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 <stdarg.h> | 18 #include <stdarg.h> |
19 #include <stdio.h> | 19 #include <stdio.h> |
20 #include <stdlib.h> | 20 #include <stdlib.h> |
21 #include <string.h> | 21 #include <string.h> |
22 #define VPX_DISABLE_CTRL_TYPECHECKS 1 | 22 #define VPX_DISABLE_CTRL_TYPECHECKS 1 |
23 #define VPX_CODEC_DISABLE_COMPAT 1 | 23 #define VPX_CODEC_DISABLE_COMPAT 1 |
24 #include "vpx/svc_context.h" | 24 #include "vpx/svc_context.h" |
25 #include "vpx/vp8cx.h" | 25 #include "vpx/vp8cx.h" |
26 #include "vpx/vpx_encoder.h" | 26 #include "vpx/vpx_encoder.h" |
| 27 #include "vpx_mem/vpx_mem.h" |
27 | 28 |
28 #ifdef __MINGW32__ | 29 #ifdef __MINGW32__ |
29 #define strtok_r strtok_s | 30 #define strtok_r strtok_s |
30 #ifndef MINGW_HAS_SECURE_API | 31 #ifndef MINGW_HAS_SECURE_API |
31 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h | 32 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h |
32 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context); | 33 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context); |
33 #endif /* MINGW_HAS_SECURE_API */ | 34 #endif /* MINGW_HAS_SECURE_API */ |
34 #endif /* __MINGW32__ */ | 35 #endif /* __MINGW32__ */ |
35 | 36 |
36 #ifdef _MSC_VER | 37 #ifdef _MSC_VER |
37 #define strdup _strdup | 38 #define strdup _strdup |
38 #define strtok_r strtok_s | 39 #define strtok_r strtok_s |
39 #endif | 40 #endif |
40 | 41 |
41 #define SVC_REFERENCE_FRAMES 8 | 42 #define SVC_REFERENCE_FRAMES 8 |
42 #define SUPERFRAME_SLOTS (8) | 43 #define SUPERFRAME_SLOTS (8) |
43 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) | 44 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) |
44 #define OPTION_BUFFER_SIZE 256 | 45 #define OPTION_BUFFER_SIZE 256 |
45 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v | 46 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v |
46 | 47 |
47 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27"; | 48 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27"; |
48 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16"; | 49 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16"; |
49 | 50 |
| 51 // One encoded frame |
| 52 typedef struct FrameData { |
| 53 void *buf; // compressed data buffer |
| 54 size_t size; // length of compressed data |
| 55 vpx_codec_frame_flags_t flags; /**< flags for this frame */ |
| 56 struct FrameData *next; |
| 57 } FrameData; |
| 58 |
50 typedef struct SvcInternal { | 59 typedef struct SvcInternal { |
51 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options | 60 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options |
52 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers | 61 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers |
53 char quantizers_keyframe[OPTION_BUFFER_SIZE]; // set by | |
54 // vpx_svc_set_quantizers | |
55 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors | 62 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors |
56 | 63 |
57 // values extracted from option, quantizers | 64 // values extracted from option, quantizers |
58 int scaling_factor_num[VPX_SS_MAX_LAYERS]; | 65 int scaling_factor_num[VPX_SS_MAX_LAYERS]; |
59 int scaling_factor_den[VPX_SS_MAX_LAYERS]; | 66 int scaling_factor_den[VPX_SS_MAX_LAYERS]; |
60 int quantizer_keyframe[VPX_SS_MAX_LAYERS]; | |
61 int quantizer[VPX_SS_MAX_LAYERS]; | 67 int quantizer[VPX_SS_MAX_LAYERS]; |
62 | 68 |
63 // accumulated statistics | 69 // accumulated statistics |
64 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V | 70 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V |
65 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; | 71 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; |
66 uint32_t bytes_sum[VPX_SS_MAX_LAYERS]; | 72 uint32_t bytes_sum[VPX_SS_MAX_LAYERS]; |
67 | 73 |
68 // codec encoding values | 74 // codec encoding values |
69 int width; // width of highest layer | 75 int width; // width of highest layer |
70 int height; // height of highest layer | 76 int height; // height of highest layer |
71 int kf_dist; // distance between keyframes | 77 int kf_dist; // distance between keyframes |
72 | 78 |
73 // state variables | 79 // state variables |
74 int encode_frame_count; | 80 int encode_frame_count; |
| 81 int frame_received; |
75 int frame_within_gop; | 82 int frame_within_gop; |
76 vpx_enc_frame_flags_t enc_frame_flags; | 83 vpx_enc_frame_flags_t enc_frame_flags; |
77 int layers; | 84 int layers; |
78 int layer; | 85 int layer; |
79 int is_keyframe; | 86 int is_keyframe; |
80 | 87 |
81 size_t frame_size; | 88 FrameData *frame_list; |
82 size_t buffer_size; | 89 FrameData *frame_temp; |
83 void *buffer; | |
84 | 90 |
85 char *rc_stats_buf; | 91 char *rc_stats_buf; |
86 size_t rc_stats_buf_size; | 92 size_t rc_stats_buf_size; |
87 size_t rc_stats_buf_used; | 93 size_t rc_stats_buf_used; |
88 | 94 |
89 char message_buffer[2048]; | 95 char message_buffer[2048]; |
90 vpx_codec_ctx_t *codec_ctx; | 96 vpx_codec_ctx_t *codec_ctx; |
91 } SvcInternal; | 97 } SvcInternal; |
92 | 98 |
93 // Superframe is used to generate an index of individual frames (i.e., layers) | 99 // create FrameData from encoder output |
94 struct Superframe { | 100 static struct FrameData *fd_create(void *buf, size_t size, |
95 int count; | 101 vpx_codec_frame_flags_t flags) { |
96 uint32_t sizes[SUPERFRAME_SLOTS]; | 102 struct FrameData *const frame_data = |
97 uint32_t magnitude; | 103 (struct FrameData *)vpx_malloc(sizeof(*frame_data)); |
98 uint8_t buffer[SUPERFRAME_BUFFER_SIZE]; | 104 if (frame_data == NULL) { |
99 size_t index_size; | |
100 }; | |
101 | |
102 // One encoded frame layer | |
103 struct LayerData { | |
104 void *buf; // compressed data buffer | |
105 size_t size; // length of compressed data | |
106 struct LayerData *next; | |
107 }; | |
108 | |
109 // create LayerData from encoder output | |
110 static struct LayerData *ld_create(void *buf, size_t size) { | |
111 struct LayerData *const layer_data = | |
112 (struct LayerData *)malloc(sizeof(*layer_data)); | |
113 if (layer_data == NULL) { | |
114 return NULL; | 105 return NULL; |
115 } | 106 } |
116 layer_data->buf = malloc(size); | 107 frame_data->buf = vpx_malloc(size); |
117 if (layer_data->buf == NULL) { | 108 if (frame_data->buf == NULL) { |
118 free(layer_data); | 109 vpx_free(frame_data); |
119 return NULL; | 110 return NULL; |
120 } | 111 } |
121 memcpy(layer_data->buf, buf, size); | 112 vpx_memcpy(frame_data->buf, buf, size); |
122 layer_data->size = size; | 113 frame_data->size = size; |
123 return layer_data; | 114 frame_data->flags = flags; |
| 115 return frame_data; |
124 } | 116 } |
125 | 117 |
126 // free LayerData | 118 // free FrameData |
127 static void ld_free(struct LayerData *layer_data) { | 119 static void fd_free(struct FrameData *p) { |
128 if (layer_data) { | 120 if (p) { |
129 if (layer_data->buf) { | 121 if (p->buf) |
130 free(layer_data->buf); | 122 vpx_free(p->buf); |
131 layer_data->buf = NULL; | 123 vpx_free(p); |
132 } | |
133 free(layer_data); | |
134 } | 124 } |
135 } | 125 } |
136 | 126 |
137 // add layer data to list | 127 // add FrameData to list |
138 static void ld_list_add(struct LayerData **list, struct LayerData *layer_data) { | 128 static void fd_list_add(struct FrameData **list, struct FrameData *layer_data) { |
139 struct LayerData **p = list; | 129 struct FrameData **p = list; |
140 | 130 |
141 while (*p != NULL) p = &(*p)->next; | 131 while (*p != NULL) p = &(*p)->next; |
142 *p = layer_data; | 132 *p = layer_data; |
143 layer_data->next = NULL; | 133 layer_data->next = NULL; |
144 } | 134 } |
145 | 135 |
146 // get accumulated size of layer data | 136 // free FrameData list |
147 static size_t ld_list_get_buffer_size(struct LayerData *list) { | 137 static void fd_free_list(struct FrameData *list) { |
148 struct LayerData *p; | 138 struct FrameData *p = list; |
149 size_t size = 0; | |
150 | |
151 for (p = list; p != NULL; p = p->next) { | |
152 size += p->size; | |
153 } | |
154 return size; | |
155 } | |
156 | |
157 // copy layer data to buffer | |
158 static void ld_list_copy_to_buffer(struct LayerData *list, uint8_t *buffer) { | |
159 struct LayerData *p; | |
160 | |
161 for (p = list; p != NULL; p = p->next) { | |
162 buffer[0] = 1; | |
163 memcpy(buffer, p->buf, p->size); | |
164 buffer += p->size; | |
165 } | |
166 } | |
167 | |
168 // free layer data list | |
169 static void ld_list_free(struct LayerData *list) { | |
170 struct LayerData *p = list; | |
171 | 139 |
172 while (p) { | 140 while (p) { |
173 list = list->next; | 141 list = list->next; |
174 ld_free(p); | 142 fd_free(p); |
175 p = list; | 143 p = list; |
176 } | 144 } |
177 } | 145 } |
178 | 146 |
179 static void sf_create_index(struct Superframe *sf) { | |
180 uint8_t marker = 0xc0; | |
181 int i; | |
182 uint32_t mag, mask; | |
183 uint8_t *bufp; | |
184 | |
185 if (sf->count == 0 || sf->count >= 8) return; | |
186 | |
187 // Add the number of frames to the marker byte | |
188 marker |= sf->count - 1; | |
189 | |
190 // Choose the magnitude | |
191 for (mag = 0, mask = 0xff; mag < 4; ++mag) { | |
192 if (sf->magnitude < mask) break; | |
193 mask <<= 8; | |
194 mask |= 0xff; | |
195 } | |
196 marker |= mag << 3; | |
197 | |
198 // Write the index | |
199 sf->index_size = 2 + (mag + 1) * sf->count; | |
200 bufp = sf->buffer; | |
201 | |
202 *bufp++ = marker; | |
203 for (i = 0; i < sf->count; ++i) { | |
204 int this_sz = sf->sizes[i]; | |
205 uint32_t j; | |
206 | |
207 for (j = 0; j <= mag; ++j) { | |
208 *bufp++ = this_sz & 0xff; | |
209 this_sz >>= 8; | |
210 } | |
211 } | |
212 *bufp++ = marker; | |
213 } | |
214 | |
215 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) { | 147 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) { |
216 if (svc_ctx == NULL) return NULL; | 148 if (svc_ctx == NULL) return NULL; |
217 if (svc_ctx->internal == NULL) { | 149 if (svc_ctx->internal == NULL) { |
218 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si)); | 150 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si)); |
219 if (si != NULL) { | 151 if (si != NULL) { |
220 memset(si, 0, sizeof(*si)); | 152 memset(si, 0, sizeof(*si)); |
221 } | 153 } |
222 svc_ctx->internal = si; | 154 svc_ctx->internal = si; |
223 } | 155 } |
224 return (SvcInternal *)svc_ctx->internal; | 156 return (SvcInternal *)svc_ctx->internal; |
(...skipping 30 matching lines...) Expand all Loading... |
255 strncat(si->message_buffer, buf, | 187 strncat(si->message_buffer, buf, |
256 sizeof(si->message_buffer) - strlen(si->message_buffer) - 1); | 188 sizeof(si->message_buffer) - strlen(si->message_buffer) - 1); |
257 } | 189 } |
258 | 190 |
259 if (level == SVC_LOG_ERROR) { | 191 if (level == SVC_LOG_ERROR) { |
260 si->codec_ctx->err_detail = si->message_buffer; | 192 si->codec_ctx->err_detail = si->message_buffer; |
261 } | 193 } |
262 return retval; | 194 return retval; |
263 } | 195 } |
264 | 196 |
265 static vpx_codec_err_t set_option_encoding_mode(SvcContext *svc_ctx, | |
266 const char *value_str) { | |
267 if (strcmp(value_str, "i") == 0) { | |
268 svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_I; | |
269 } else if (strcmp(value_str, "alt-ip") == 0) { | |
270 svc_ctx->encoding_mode = ALT_INTER_LAYER_PREDICTION_IP; | |
271 } else if (strcmp(value_str, "ip") == 0) { | |
272 svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_IP; | |
273 } else if (strcmp(value_str, "gf") == 0) { | |
274 svc_ctx->encoding_mode = USE_GOLDEN_FRAME; | |
275 } else { | |
276 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str); | |
277 return VPX_CODEC_INVALID_PARAM; | |
278 } | |
279 return VPX_CODEC_OK; | |
280 } | |
281 | |
282 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx, | 197 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx, |
283 const char *quantizer_values, | 198 const char *quantizer_values) { |
284 const int is_keyframe) { | |
285 char *input_string; | 199 char *input_string; |
286 char *token; | 200 char *token; |
287 const char *delim = ","; | 201 const char *delim = ","; |
288 char *save_ptr; | 202 char *save_ptr; |
289 int found = 0; | 203 int found = 0; |
290 int i, q; | 204 int i, q; |
291 vpx_codec_err_t res = VPX_CODEC_OK; | 205 vpx_codec_err_t res = VPX_CODEC_OK; |
292 SvcInternal *const si = get_svc_internal(svc_ctx); | 206 SvcInternal *const si = get_svc_internal(svc_ctx); |
293 | 207 |
294 if (quantizer_values == NULL || strlen(quantizer_values) == 0) { | 208 if (quantizer_values == NULL || strlen(quantizer_values) == 0) { |
295 if (is_keyframe) { | |
296 // If there non settings for key frame, we will apply settings from | |
297 // non key frame. So just simply return here. | |
298 return VPX_CODEC_INVALID_PARAM; | |
299 } | |
300 input_string = strdup(DEFAULT_QUANTIZER_VALUES); | 209 input_string = strdup(DEFAULT_QUANTIZER_VALUES); |
301 } else { | 210 } else { |
302 input_string = strdup(quantizer_values); | 211 input_string = strdup(quantizer_values); |
303 } | 212 } |
304 | 213 |
305 token = strtok_r(input_string, delim, &save_ptr); | 214 token = strtok_r(input_string, delim, &save_ptr); |
306 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 215 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
307 if (token != NULL) { | 216 if (token != NULL) { |
308 q = atoi(token); | 217 q = atoi(token); |
309 if (q <= 0 || q > 100) { | 218 if (q <= 0 || q > 100) { |
310 svc_log(svc_ctx, SVC_LOG_ERROR, | 219 svc_log(svc_ctx, SVC_LOG_ERROR, |
311 "svc-quantizer-values: invalid value %s\n", token); | 220 "svc-quantizer-values: invalid value %s\n", token); |
312 res = VPX_CODEC_INVALID_PARAM; | 221 res = VPX_CODEC_INVALID_PARAM; |
313 break; | 222 break; |
314 } | 223 } |
315 token = strtok_r(NULL, delim, &save_ptr); | 224 token = strtok_r(NULL, delim, &save_ptr); |
316 found = i + 1; | 225 found = i + 1; |
317 } else { | 226 } else { |
318 q = 0; | 227 q = 0; |
319 } | 228 } |
320 if (is_keyframe) { | 229 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q; |
321 si->quantizer_keyframe[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] | |
322 = q; | |
323 } else { | |
324 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q; | |
325 } | |
326 } | 230 } |
327 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) { | 231 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) { |
328 svc_log(svc_ctx, SVC_LOG_ERROR, | 232 svc_log(svc_ctx, SVC_LOG_ERROR, |
329 "svc: quantizers: %d values required, but only %d specified\n", | 233 "svc: quantizers: %d values required, but only %d specified\n", |
330 svc_ctx->spatial_layers, found); | 234 svc_ctx->spatial_layers, found); |
331 res = VPX_CODEC_INVALID_PARAM; | 235 res = VPX_CODEC_INVALID_PARAM; |
332 } | 236 } |
333 free(input_string); | 237 free(input_string); |
334 return res; | 238 return res; |
335 } | 239 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 * Format: encoding-mode=<svc_mode>,layers=<layer_count> | 304 * Format: encoding-mode=<svc_mode>,layers=<layer_count> |
401 * scale-factors=<n1>/<d1>,<n2>/<d2>,... | 305 * scale-factors=<n1>/<d1>,<n2>/<d2>,... |
402 * quantizers=<q1>,<q2>,... | 306 * quantizers=<q1>,<q2>,... |
403 * svc_mode = [i|ip|alt_ip|gf] | 307 * svc_mode = [i|ip|alt_ip|gf] |
404 */ | 308 */ |
405 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { | 309 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { |
406 char *input_string; | 310 char *input_string; |
407 char *option_name; | 311 char *option_name; |
408 char *option_value; | 312 char *option_value; |
409 char *input_ptr; | 313 char *input_ptr; |
410 int is_keyframe_qaunt_set = 0; | |
411 vpx_codec_err_t res = VPX_CODEC_OK; | 314 vpx_codec_err_t res = VPX_CODEC_OK; |
412 | 315 |
413 if (options == NULL) return VPX_CODEC_OK; | 316 if (options == NULL) return VPX_CODEC_OK; |
414 input_string = strdup(options); | 317 input_string = strdup(options); |
415 | 318 |
416 // parse option name | 319 // parse option name |
417 option_name = strtok_r(input_string, "=", &input_ptr); | 320 option_name = strtok_r(input_string, "=", &input_ptr); |
418 while (option_name != NULL) { | 321 while (option_name != NULL) { |
419 // parse option value | 322 // parse option value |
420 option_value = strtok_r(NULL, " ", &input_ptr); | 323 option_value = strtok_r(NULL, " ", &input_ptr); |
421 if (option_value == NULL) { | 324 if (option_value == NULL) { |
422 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n", | 325 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n", |
423 option_name); | 326 option_name); |
424 res = VPX_CODEC_INVALID_PARAM; | 327 res = VPX_CODEC_INVALID_PARAM; |
425 break; | 328 break; |
426 } | 329 } |
427 if (strcmp("encoding-mode", option_name) == 0) { | 330 if (strcmp("layers", option_name) == 0) { |
428 res = set_option_encoding_mode(svc_ctx, option_value); | |
429 if (res != VPX_CODEC_OK) break; | |
430 } else if (strcmp("layers", option_name) == 0) { | |
431 svc_ctx->spatial_layers = atoi(option_value); | 331 svc_ctx->spatial_layers = atoi(option_value); |
432 } else if (strcmp("scale-factors", option_name) == 0) { | 332 } else if (strcmp("scale-factors", option_name) == 0) { |
433 res = parse_scale_factors(svc_ctx, option_value); | 333 res = parse_scale_factors(svc_ctx, option_value); |
434 if (res != VPX_CODEC_OK) break; | 334 if (res != VPX_CODEC_OK) break; |
435 } else if (strcmp("quantizers", option_name) == 0) { | 335 } else if (strcmp("quantizers", option_name) == 0) { |
436 res = parse_quantizer_values(svc_ctx, option_value, 0); | 336 res = parse_quantizer_values(svc_ctx, option_value); |
437 if (res != VPX_CODEC_OK) break; | 337 if (res != VPX_CODEC_OK) break; |
438 if (!is_keyframe_qaunt_set) { | |
439 SvcInternal *const si = get_svc_internal(svc_ctx); | |
440 memcpy(get_svc_internal(svc_ctx)->quantizer_keyframe, si->quantizer, | |
441 sizeof(si->quantizer)); | |
442 } | |
443 } else if (strcmp("quantizers-keyframe", option_name) == 0) { | |
444 res = parse_quantizer_values(svc_ctx, option_value, 1); | |
445 if (res != VPX_CODEC_OK) break; | |
446 is_keyframe_qaunt_set = 1; | |
447 } else { | 338 } else { |
448 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name); | 339 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name); |
449 res = VPX_CODEC_INVALID_PARAM; | 340 res = VPX_CODEC_INVALID_PARAM; |
450 break; | 341 break; |
451 } | 342 } |
452 option_name = strtok_r(NULL, "=", &input_ptr); | 343 option_name = strtok_r(NULL, "=", &input_ptr); |
453 } | 344 } |
454 free(input_string); | 345 free(input_string); |
455 return res; | 346 return res; |
456 } | 347 } |
457 | 348 |
458 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) { | 349 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) { |
459 SvcInternal *const si = get_svc_internal(svc_ctx); | 350 SvcInternal *const si = get_svc_internal(svc_ctx); |
460 if (svc_ctx == NULL || options == NULL || si == NULL) { | 351 if (svc_ctx == NULL || options == NULL || si == NULL) { |
461 return VPX_CODEC_INVALID_PARAM; | 352 return VPX_CODEC_INVALID_PARAM; |
462 } | 353 } |
463 strncpy(si->options, options, sizeof(si->options)); | 354 strncpy(si->options, options, sizeof(si->options)); |
464 si->options[sizeof(si->options) - 1] = '\0'; | 355 si->options[sizeof(si->options) - 1] = '\0'; |
465 return VPX_CODEC_OK; | 356 return VPX_CODEC_OK; |
466 } | 357 } |
467 | 358 |
468 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx, | 359 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx, |
469 const char *quantizers, | 360 const char *quantizers) { |
470 const int is_for_keyframe) { | |
471 SvcInternal *const si = get_svc_internal(svc_ctx); | 361 SvcInternal *const si = get_svc_internal(svc_ctx); |
472 if (svc_ctx == NULL || quantizers == NULL || si == NULL) { | 362 if (svc_ctx == NULL || quantizers == NULL || si == NULL) { |
473 return VPX_CODEC_INVALID_PARAM; | 363 return VPX_CODEC_INVALID_PARAM; |
474 } | 364 } |
475 if (is_for_keyframe) { | 365 strncpy(si->quantizers, quantizers, sizeof(si->quantizers)); |
476 strncpy(si->quantizers_keyframe, quantizers, sizeof(si->quantizers)); | 366 si->quantizers[sizeof(si->quantizers) - 1] = '\0'; |
477 si->quantizers_keyframe[sizeof(si->quantizers_keyframe) - 1] = '\0'; | |
478 } else { | |
479 strncpy(si->quantizers, quantizers, sizeof(si->quantizers)); | |
480 si->quantizers[sizeof(si->quantizers) - 1] = '\0'; | |
481 } | |
482 return VPX_CODEC_OK; | 367 return VPX_CODEC_OK; |
483 } | 368 } |
484 | 369 |
485 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx, | 370 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx, |
486 const char *scale_factors) { | 371 const char *scale_factors) { |
487 SvcInternal *const si = get_svc_internal(svc_ctx); | 372 SvcInternal *const si = get_svc_internal(svc_ctx); |
488 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) { | 373 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) { |
489 return VPX_CODEC_INVALID_PARAM; | 374 return VPX_CODEC_INVALID_PARAM; |
490 } | 375 } |
491 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors)); | 376 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors)); |
(...skipping 26 matching lines...) Expand all Loading... |
518 | 403 |
519 if (svc_ctx->spatial_layers == 0) | 404 if (svc_ctx->spatial_layers == 0) |
520 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; | 405 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; |
521 if (svc_ctx->spatial_layers < 1 || | 406 if (svc_ctx->spatial_layers < 1 || |
522 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { | 407 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { |
523 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", | 408 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", |
524 svc_ctx->spatial_layers); | 409 svc_ctx->spatial_layers); |
525 return VPX_CODEC_INVALID_PARAM; | 410 return VPX_CODEC_INVALID_PARAM; |
526 } | 411 } |
527 | 412 |
528 res = parse_quantizer_values(svc_ctx, si->quantizers, 0); | 413 res = parse_quantizer_values(svc_ctx, si->quantizers); |
529 if (res != VPX_CODEC_OK) return res; | 414 if (res != VPX_CODEC_OK) return res; |
530 | 415 |
531 res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1); | |
532 if (res != VPX_CODEC_OK) | |
533 memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer)); | |
534 | |
535 res = parse_scale_factors(svc_ctx, si->scale_factors); | 416 res = parse_scale_factors(svc_ctx, si->scale_factors); |
536 if (res != VPX_CODEC_OK) return res; | 417 if (res != VPX_CODEC_OK) return res; |
537 | 418 |
538 // Parse aggregate command line options. Options must start with | 419 // Parse aggregate command line options. Options must start with |
539 // "layers=xx" then followed by other options | 420 // "layers=xx" then followed by other options |
540 res = parse_options(svc_ctx, si->options); | 421 res = parse_options(svc_ctx, si->options); |
541 if (res != VPX_CODEC_OK) return res; | 422 if (res != VPX_CODEC_OK) return res; |
542 | 423 |
543 si->layers = svc_ctx->spatial_layers; | 424 si->layers = svc_ctx->spatial_layers; |
544 | 425 |
(...skipping 22 matching lines...) Expand all Loading... |
567 if (total > 0) { | 448 if (total > 0) { |
568 enc_cfg->ss_target_bitrate[i] = (unsigned int) | 449 enc_cfg->ss_target_bitrate[i] = (unsigned int) |
569 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); | 450 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); |
570 } | 451 } |
571 } | 452 } |
572 } | 453 } |
573 | 454 |
574 // modify encoder configuration | 455 // modify encoder configuration |
575 enc_cfg->ss_number_layers = si->layers; | 456 enc_cfg->ss_number_layers = si->layers; |
576 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. | 457 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. |
577 // Lag in frames not currently supported | |
578 enc_cfg->g_lag_in_frames = 0; | |
579 | 458 |
580 // TODO(ivanmaltz): determine if these values need to be set explicitly for | 459 // TODO(ivanmaltz): determine if these values need to be set explicitly for |
581 // svc, or if the normal default/override mechanism can be used | 460 // svc, or if the normal default/override mechanism can be used |
582 enc_cfg->rc_dropframe_thresh = 0; | 461 enc_cfg->rc_dropframe_thresh = 0; |
583 enc_cfg->rc_resize_allowed = 0; | 462 enc_cfg->rc_resize_allowed = 0; |
584 | 463 |
585 if (enc_cfg->g_pass == VPX_RC_ONE_PASS) { | 464 if (enc_cfg->g_pass == VPX_RC_ONE_PASS) { |
586 enc_cfg->rc_min_quantizer = 33; | 465 enc_cfg->rc_min_quantizer = 33; |
587 enc_cfg->rc_max_quantizer = 33; | 466 enc_cfg->rc_max_quantizer = 33; |
588 } | 467 } |
(...skipping 12 matching lines...) Expand all Loading... |
601 return res; | 480 return res; |
602 } | 481 } |
603 | 482 |
604 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1); | 483 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1); |
605 vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1); | 484 vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1); |
606 vpx_codec_control(codec_ctx, VP8E_SET_ENABLEAUTOALTREF, 0); | 485 vpx_codec_control(codec_ctx, VP8E_SET_ENABLEAUTOALTREF, 0); |
607 | 486 |
608 return VPX_CODEC_OK; | 487 return VPX_CODEC_OK; |
609 } | 488 } |
610 | 489 |
| 490 static void accumulate_frame_size_for_each_layer(SvcInternal *const si, |
| 491 const uint8_t *const buf, |
| 492 const size_t size) { |
| 493 uint8_t marker = buf[size - 1]; |
| 494 if ((marker & 0xe0) == 0xc0) { |
| 495 const uint32_t frames = (marker & 0x7) + 1; |
| 496 const uint32_t mag = ((marker >> 3) & 0x3) + 1; |
| 497 const size_t index_sz = 2 + mag * frames; |
| 498 |
| 499 uint8_t marker2 = buf[size - index_sz]; |
| 500 |
| 501 if (size >= index_sz && marker2 == marker) { |
| 502 // found a valid superframe index |
| 503 uint32_t i, j; |
| 504 const uint8_t *x = &buf[size - index_sz + 1]; |
| 505 |
| 506 // frames has a maximum of 8 and mag has a maximum of 4. |
| 507 for (i = 0; i < frames; i++) { |
| 508 uint32_t this_sz = 0; |
| 509 |
| 510 for (j = 0; j < mag; j++) |
| 511 this_sz |= (*x++) << (j * 8); |
| 512 si->bytes_sum[i] += this_sz; |
| 513 } |
| 514 } |
| 515 } |
| 516 } |
| 517 |
611 // SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h | 518 // SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h |
612 | 519 |
613 // encoder should reference the last frame | 520 // encoder should reference the last frame |
614 #define USE_LAST (1 << 0) | 521 #define USE_LAST (1 << 0) |
615 | 522 |
616 // encoder should reference the alt ref frame | 523 // encoder should reference the alt ref frame |
617 #define USE_ARF (1 << 1) | 524 #define USE_ARF (1 << 1) |
618 | 525 |
619 // encoder should reference the golden frame | 526 // encoder should reference the golden frame |
620 #define USE_GF (1 << 2) | 527 #define USE_GF (1 << 2) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 vpx_enc_frame_flags_t flags = VPX_EFLAG_FORCE_KF; | 564 vpx_enc_frame_flags_t flags = VPX_EFLAG_FORCE_KF; |
658 SvcInternal *const si = get_svc_internal(svc_ctx); | 565 SvcInternal *const si = get_svc_internal(svc_ctx); |
659 const int is_keyframe = (si->frame_within_gop == 0); | 566 const int is_keyframe = (si->frame_within_gop == 0); |
660 | 567 |
661 // keyframe layer zero is identical for all modes | 568 // keyframe layer zero is identical for all modes |
662 if (is_keyframe && si->layer == 0) { | 569 if (is_keyframe && si->layer == 0) { |
663 si->enc_frame_flags = VPX_EFLAG_FORCE_KF; | 570 si->enc_frame_flags = VPX_EFLAG_FORCE_KF; |
664 return; | 571 return; |
665 } | 572 } |
666 | 573 |
667 switch (svc_ctx->encoding_mode) { | 574 if (si->layer == 0) { |
668 case ALT_INTER_LAYER_PREDICTION_IP: | 575 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); |
669 if (si->layer == 0) { | 576 } else if (is_keyframe) { |
670 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | 577 flags = map_vp8_flags(USE_ARF | UPDATE_LAST); |
671 } else if (is_keyframe) { | 578 } else { |
672 if (si->layer == si->layers - 1) { | 579 flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST); |
673 flags = map_vp8_flags(USE_ARF | UPDATE_LAST); | |
674 } else { | |
675 flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF); | |
676 } | |
677 } else { | |
678 flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST); | |
679 } | |
680 break; | |
681 case INTER_LAYER_PREDICTION_I: | |
682 if (si->layer == 0) { | |
683 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | |
684 } else if (is_keyframe) { | |
685 flags = map_vp8_flags(USE_ARF | UPDATE_LAST); | |
686 } else { | |
687 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | |
688 } | |
689 break; | |
690 case INTER_LAYER_PREDICTION_IP: | |
691 if (si->layer == 0) { | |
692 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | |
693 } else if (is_keyframe) { | |
694 flags = map_vp8_flags(USE_ARF | UPDATE_LAST); | |
695 } else { | |
696 flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST); | |
697 } | |
698 break; | |
699 case USE_GOLDEN_FRAME: | |
700 if (2 * si->layers - SVC_REFERENCE_FRAMES <= si->layer) { | |
701 if (si->layer == 0) { | |
702 flags = map_vp8_flags(USE_LAST | USE_GF | UPDATE_LAST); | |
703 } else if (is_keyframe) { | |
704 flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF); | |
705 } else { | |
706 flags = map_vp8_flags(USE_LAST | USE_ARF | USE_GF | UPDATE_LAST); | |
707 } | |
708 } else { | |
709 if (si->layer == 0) { | |
710 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | |
711 } else if (is_keyframe) { | |
712 flags = map_vp8_flags(USE_ARF | UPDATE_LAST); | |
713 } else { | |
714 flags = map_vp8_flags(USE_LAST | UPDATE_LAST); | |
715 } | |
716 } | |
717 break; | |
718 default: | |
719 svc_log(svc_ctx, SVC_LOG_ERROR, "unexpected encoding mode: %d\n", | |
720 svc_ctx->encoding_mode); | |
721 break; | |
722 } | 580 } |
| 581 |
723 si->enc_frame_flags = flags; | 582 si->enc_frame_flags = flags; |
724 } | 583 } |
725 | 584 |
726 vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx, | 585 vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx, |
727 int layer, | 586 int layer, |
728 unsigned int *width, | 587 unsigned int *width, |
729 unsigned int *height) { | 588 unsigned int *height) { |
730 int w, h, index, num, den; | 589 int w, h, index, num, den; |
731 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 590 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
732 | 591 |
(...skipping 25 matching lines...) Expand all Loading... |
758 int layer, layer_index; | 617 int layer, layer_index; |
759 vpx_svc_parameters_t svc_params; | 618 vpx_svc_parameters_t svc_params; |
760 SvcInternal *const si = get_svc_internal(svc_ctx); | 619 SvcInternal *const si = get_svc_internal(svc_ctx); |
761 | 620 |
762 memset(&svc_params, 0, sizeof(svc_params)); | 621 memset(&svc_params, 0, sizeof(svc_params)); |
763 svc_params.temporal_layer = 0; | 622 svc_params.temporal_layer = 0; |
764 svc_params.spatial_layer = si->layer; | 623 svc_params.spatial_layer = si->layer; |
765 svc_params.flags = si->enc_frame_flags; | 624 svc_params.flags = si->enc_frame_flags; |
766 | 625 |
767 layer = si->layer; | 626 layer = si->layer; |
768 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && | |
769 si->frame_within_gop == 0) { | |
770 // layers 1 & 3 don't exist in this mode, use the higher one | |
771 if (layer == 0 || layer == 2) { | |
772 layer += 1; | |
773 } | |
774 } | |
775 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer, | 627 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer, |
776 &svc_params.width, | 628 &svc_params.width, |
777 &svc_params.height)) { | 629 &svc_params.height)) { |
778 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n"); | 630 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n"); |
779 } | 631 } |
780 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; | 632 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; |
781 | 633 |
782 if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) { | 634 if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) { |
783 if (vpx_svc_is_keyframe(svc_ctx)) { | 635 svc_params.min_quantizer = si->quantizer[layer_index]; |
784 svc_params.min_quantizer = si->quantizer_keyframe[layer_index]; | 636 svc_params.max_quantizer = si->quantizer[layer_index]; |
785 svc_params.max_quantizer = si->quantizer_keyframe[layer_index]; | |
786 } else { | |
787 svc_params.min_quantizer = si->quantizer[layer_index]; | |
788 svc_params.max_quantizer = si->quantizer[layer_index]; | |
789 } | |
790 } else { | 637 } else { |
791 svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer; | 638 svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer; |
792 svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer; | 639 svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer; |
793 } | 640 } |
794 | 641 |
795 svc_params.distance_from_i_frame = si->frame_within_gop; | 642 svc_params.distance_from_i_frame = si->frame_within_gop; |
796 | 643 |
797 // Use buffer i for layer i LST | 644 // Use buffer i for layer i LST |
798 svc_params.lst_fb_idx = si->layer; | 645 svc_params.lst_fb_idx = si->layer; |
799 | 646 |
800 // Use buffer i-1 for layer i Alt (Inter-layer prediction) | 647 // Use buffer i-1 for layer i Alt (Inter-layer prediction) |
801 if (si->layer != 0) { | 648 svc_params.alt_fb_idx = (si->layer > 0) ? si->layer - 1 : 0; |
802 const int use_higher_layer = | 649 svc_params.gld_fb_idx = svc_params.lst_fb_idx; |
803 svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && | |
804 si->frame_within_gop == 0; | |
805 svc_params.alt_fb_idx = use_higher_layer ? si->layer - 2 : si->layer - 1; | |
806 } | |
807 | |
808 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP) { | |
809 svc_params.gld_fb_idx = si->layer + 1; | |
810 } else { | |
811 if (si->layer < 2 * si->layers - SVC_REFERENCE_FRAMES) | |
812 svc_params.gld_fb_idx = svc_params.lst_fb_idx; | |
813 else | |
814 svc_params.gld_fb_idx = 2 * si->layers - 1 - si->layer; | |
815 } | |
816 | 650 |
817 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, layer: %d, %dx%d, q: %d\n", | 651 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, layer: %d, %dx%d, q: %d\n", |
818 si->encode_frame_count, si->layer, svc_params.width, | 652 si->encode_frame_count, si->layer, svc_params.width, |
819 svc_params.height, svc_params.min_quantizer); | 653 svc_params.height, svc_params.min_quantizer); |
820 | 654 |
821 if (svc_params.flags == VPX_EFLAG_FORCE_KF) { | 655 if (svc_params.flags == VPX_EFLAG_FORCE_KF) { |
822 svc_log(svc_ctx, SVC_LOG_DEBUG, "flags == VPX_EFLAG_FORCE_KF\n"); | 656 svc_log(svc_ctx, SVC_LOG_DEBUG, "flags == VPX_EFLAG_FORCE_KF\n"); |
823 } else { | 657 } else { |
824 svc_log( | 658 svc_log( |
825 svc_ctx, SVC_LOG_DEBUG, "Using: LST/GLD/ALT [%2d|%2d|%2d]\n", | 659 svc_ctx, SVC_LOG_DEBUG, "Using: LST/GLD/ALT [%2d|%2d|%2d]\n", |
(...skipping 13 matching lines...) Expand all Loading... |
839 /** | 673 /** |
840 * Encode a frame into multiple layers | 674 * Encode a frame into multiple layers |
841 * Create a superframe containing the individual layers | 675 * Create a superframe containing the individual layers |
842 */ | 676 */ |
843 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, | 677 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, |
844 struct vpx_image *rawimg, vpx_codec_pts_t pts, | 678 struct vpx_image *rawimg, vpx_codec_pts_t pts, |
845 int64_t duration, int deadline) { | 679 int64_t duration, int deadline) { |
846 vpx_codec_err_t res; | 680 vpx_codec_err_t res; |
847 vpx_codec_iter_t iter; | 681 vpx_codec_iter_t iter; |
848 const vpx_codec_cx_pkt_t *cx_pkt; | 682 const vpx_codec_cx_pkt_t *cx_pkt; |
849 struct LayerData *cx_layer_list = NULL; | 683 int layer_for_psnr = 0; |
850 struct LayerData *layer_data; | |
851 struct Superframe superframe; | |
852 SvcInternal *const si = get_svc_internal(svc_ctx); | 684 SvcInternal *const si = get_svc_internal(svc_ctx); |
853 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { | 685 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { |
854 return VPX_CODEC_INVALID_PARAM; | 686 return VPX_CODEC_INVALID_PARAM; |
855 } | 687 } |
856 | 688 |
857 memset(&superframe, 0, sizeof(superframe)); | |
858 svc_log_reset(svc_ctx); | 689 svc_log_reset(svc_ctx); |
859 si->rc_stats_buf_used = 0; | 690 si->rc_stats_buf_used = 0; |
860 | 691 |
861 si->layers = svc_ctx->spatial_layers; | 692 si->layers = svc_ctx->spatial_layers; |
862 if (si->encode_frame_count == 0) { | 693 if (si->encode_frame_count == 0) { |
863 si->frame_within_gop = 0; | 694 si->frame_within_gop = 0; |
864 } | 695 } |
865 si->is_keyframe = (si->frame_within_gop == 0); | 696 si->is_keyframe = (si->frame_within_gop == 0); |
866 si->frame_size = 0; | |
867 | 697 |
868 if (rawimg != NULL) { | 698 if (rawimg != NULL) { |
869 svc_log(svc_ctx, SVC_LOG_DEBUG, | 699 svc_log(svc_ctx, SVC_LOG_DEBUG, |
870 "vpx_svc_encode layers: %d, frame_count: %d, " | 700 "vpx_svc_encode layers: %d, frame_count: %d, " |
871 "frame_within_gop: %d\n", si->layers, si->encode_frame_count, | 701 "frame_within_gop: %d\n", si->layers, si->encode_frame_count, |
872 si->frame_within_gop); | 702 si->frame_within_gop); |
873 } | 703 } |
874 | 704 |
875 // encode each layer | 705 if (rawimg != NULL) { |
876 for (si->layer = 0; si->layer < si->layers; ++si->layer) { | 706 // encode each layer |
877 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && | 707 for (si->layer = 0; si->layer < si->layers; ++si->layer) { |
878 si->is_keyframe && (si->layer == 1 || si->layer == 3)) { | |
879 svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer); | |
880 continue; | |
881 } | |
882 | |
883 if (rawimg != NULL) { | |
884 calculate_enc_frame_flags(svc_ctx); | 708 calculate_enc_frame_flags(svc_ctx); |
885 set_svc_parameters(svc_ctx, codec_ctx); | 709 set_svc_parameters(svc_ctx, codec_ctx); |
886 } | 710 } |
| 711 } |
887 | 712 |
888 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, | 713 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, |
889 si->enc_frame_flags, deadline); | 714 deadline); |
890 if (res != VPX_CODEC_OK) { | 715 if (res != VPX_CODEC_OK) { |
891 return res; | 716 return res; |
892 } | 717 } |
893 // save compressed data | 718 // save compressed data |
894 iter = NULL; | 719 iter = NULL; |
895 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { | 720 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { |
896 switch (cx_pkt->kind) { | 721 switch (cx_pkt->kind) { |
897 case VPX_CODEC_CX_FRAME_PKT: { | 722 case VPX_CODEC_CX_FRAME_PKT: { |
898 const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz); | 723 fd_list_add(&si->frame_list, fd_create(cx_pkt->data.frame.buf, |
899 si->bytes_sum[si->layer] += frame_pkt_size; | 724 cx_pkt->data.frame.sz, |
900 svc_log(svc_ctx, SVC_LOG_DEBUG, | 725 cx_pkt->data.frame.flags)); |
901 "SVC frame: %d, layer: %d, size: %u\n", | 726 accumulate_frame_size_for_each_layer(si, cx_pkt->data.frame.buf, |
902 si->encode_frame_count, si->layer, frame_pkt_size); | 727 cx_pkt->data.frame.sz); |
903 layer_data = | 728 |
904 ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size); | 729 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, " |
905 if (layer_data == NULL) { | 730 "pts: %d\n", si->frame_received, |
906 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n"); | 731 (cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? 1 : 0, |
907 return VPX_CODEC_OK; | 732 (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts); |
| 733 |
| 734 ++si->frame_received; |
| 735 layer_for_psnr = 0; |
| 736 break; |
| 737 } |
| 738 case VPX_CODEC_PSNR_PKT: { |
| 739 int i; |
| 740 svc_log(svc_ctx, SVC_LOG_DEBUG, |
| 741 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): " |
| 742 "%2.3f %2.3f %2.3f %2.3f \n", |
| 743 si->frame_received, layer_for_psnr, |
| 744 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1], |
| 745 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]); |
| 746 svc_log(svc_ctx, SVC_LOG_DEBUG, |
| 747 "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): " |
| 748 "%2.3f %2.3f %2.3f %2.3f \n", |
| 749 si->frame_received, layer_for_psnr, |
| 750 cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1], |
| 751 cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]); |
| 752 for (i = 0; i < COMPONENTS; i++) { |
| 753 si->psnr_sum[layer_for_psnr][i] += cx_pkt->data.psnr.psnr[i]; |
| 754 si->sse_sum[layer_for_psnr][i] += cx_pkt->data.psnr.sse[i]; |
| 755 } |
| 756 ++layer_for_psnr; |
| 757 break; |
| 758 } |
| 759 case VPX_CODEC_STATS_PKT: { |
| 760 size_t new_size = si->rc_stats_buf_used + |
| 761 cx_pkt->data.twopass_stats.sz; |
| 762 |
| 763 if (new_size > si->rc_stats_buf_size) { |
| 764 char *p = (char*)realloc(si->rc_stats_buf, new_size); |
| 765 if (p == NULL) { |
| 766 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n"); |
| 767 return VPX_CODEC_MEM_ERROR; |
908 } | 768 } |
909 ld_list_add(&cx_layer_list, layer_data); | 769 si->rc_stats_buf = p; |
| 770 si->rc_stats_buf_size = new_size; |
| 771 } |
910 | 772 |
911 // save layer size in superframe index | 773 memcpy(si->rc_stats_buf + si->rc_stats_buf_used, |
912 superframe.sizes[superframe.count++] = frame_pkt_size; | 774 cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz); |
913 superframe.magnitude |= frame_pkt_size; | 775 si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz; |
914 break; | 776 break; |
915 } | 777 } |
916 case VPX_CODEC_PSNR_PKT: { | 778 default: { |
917 int i; | 779 break; |
918 svc_log(svc_ctx, SVC_LOG_DEBUG, | |
919 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): " | |
920 "%2.3f %2.3f %2.3f %2.3f \n", | |
921 si->encode_frame_count, si->layer, | |
922 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1], | |
923 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]); | |
924 svc_log(svc_ctx, SVC_LOG_DEBUG, | |
925 "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): " | |
926 "%2.3f %2.3f %2.3f %2.3f \n", | |
927 si->encode_frame_count, si->layer, | |
928 cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1], | |
929 cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]); | |
930 for (i = 0; i < COMPONENTS; i++) { | |
931 si->psnr_sum[si->layer][i] += cx_pkt->data.psnr.psnr[i]; | |
932 si->sse_sum[si->layer][i] += cx_pkt->data.psnr.sse[i]; | |
933 } | |
934 break; | |
935 } | |
936 case VPX_CODEC_STATS_PKT: { | |
937 size_t new_size = si->rc_stats_buf_used + | |
938 cx_pkt->data.twopass_stats.sz; | |
939 | |
940 if (new_size > si->rc_stats_buf_size) { | |
941 char *p = (char*)realloc(si->rc_stats_buf, new_size); | |
942 if (p == NULL) { | |
943 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n"); | |
944 break; | |
945 } | |
946 si->rc_stats_buf = p; | |
947 si->rc_stats_buf_size = new_size; | |
948 } | |
949 | |
950 memcpy(si->rc_stats_buf + si->rc_stats_buf_used, | |
951 cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz); | |
952 si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz; | |
953 break; | |
954 } | |
955 default: { | |
956 break; | |
957 } | |
958 } | 780 } |
959 } | 781 } |
960 if (rawimg == NULL) { | |
961 break; | |
962 } | |
963 } | 782 } |
964 if (codec_ctx->config.enc->g_pass != VPX_RC_FIRST_PASS) { | |
965 // add superframe index to layer data list | |
966 sf_create_index(&superframe); | |
967 layer_data = ld_create(superframe.buffer, superframe.index_size); | |
968 ld_list_add(&cx_layer_list, layer_data); | |
969 | 783 |
970 // get accumulated size of layer data | |
971 si->frame_size = ld_list_get_buffer_size(cx_layer_list); | |
972 if (si->frame_size > 0) { | |
973 // all layers encoded, create single buffer with concatenated layers | |
974 if (si->frame_size > si->buffer_size) { | |
975 free(si->buffer); | |
976 si->buffer = malloc(si->frame_size); | |
977 if (si->buffer == NULL) { | |
978 ld_list_free(cx_layer_list); | |
979 return VPX_CODEC_MEM_ERROR; | |
980 } | |
981 si->buffer_size = si->frame_size; | |
982 } | |
983 // copy layer data into packet | |
984 ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer); | |
985 | |
986 ld_list_free(cx_layer_list); | |
987 | |
988 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, " | |
989 "pts: %d\n", si->encode_frame_count, si->is_keyframe, | |
990 (int)si->frame_size, (int)pts); | |
991 } | |
992 } | |
993 if (rawimg != NULL) { | 784 if (rawimg != NULL) { |
994 ++si->frame_within_gop; | 785 ++si->frame_within_gop; |
995 ++si->encode_frame_count; | 786 ++si->encode_frame_count; |
996 } | 787 } |
997 | 788 |
998 return VPX_CODEC_OK; | 789 return VPX_CODEC_OK; |
999 } | 790 } |
1000 | 791 |
1001 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { | 792 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { |
1002 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 793 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1003 if (svc_ctx == NULL || si == NULL) return NULL; | 794 if (svc_ctx == NULL || si == NULL) return NULL; |
1004 return si->message_buffer; | 795 return si->message_buffer; |
1005 } | 796 } |
1006 | 797 |
1007 void *vpx_svc_get_buffer(const SvcContext *svc_ctx) { | 798 // We will maintain a list of output frame buffers since with lag_in_frame |
1008 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 799 // we need to output all frame buffers at the end. vpx_svc_get_buffer() will |
1009 if (svc_ctx == NULL || si == NULL) return NULL; | 800 // remove a frame buffer from the list the put it to a temporal pointer, which |
1010 return si->buffer; | 801 // will be removed at the next vpx_svc_get_buffer() or when closing encoder. |
| 802 void *vpx_svc_get_buffer(SvcContext *svc_ctx) { |
| 803 SvcInternal *const si = get_svc_internal(svc_ctx); |
| 804 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return NULL; |
| 805 |
| 806 if (si->frame_temp) |
| 807 fd_free(si->frame_temp); |
| 808 |
| 809 si->frame_temp = si->frame_list; |
| 810 si->frame_list = si->frame_list->next; |
| 811 |
| 812 return si->frame_temp->buf; |
1011 } | 813 } |
1012 | 814 |
1013 size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) { | 815 size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) { |
1014 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 816 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1015 if (svc_ctx == NULL || si == NULL) return 0; | 817 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0; |
1016 return si->frame_size; | 818 return si->frame_list->size; |
1017 } | 819 } |
1018 | 820 |
1019 int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) { | 821 int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) { |
1020 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 822 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1021 if (svc_ctx == NULL || si == NULL) return 0; | 823 if (svc_ctx == NULL || si == NULL) return 0; |
1022 return si->encode_frame_count; | 824 return si->encode_frame_count; |
1023 } | 825 } |
1024 | 826 |
1025 int vpx_svc_is_keyframe(const SvcContext *svc_ctx) { | 827 int vpx_svc_is_keyframe(const SvcContext *svc_ctx) { |
1026 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 828 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1027 if (svc_ctx == NULL || si == NULL) return 0; | 829 if (svc_ctx == NULL || si == NULL || si->frame_list == NULL) return 0; |
1028 return si->is_keyframe; | 830 return (si->frame_list->flags & VPX_FRAME_IS_KEY) != 0; |
1029 } | 831 } |
1030 | 832 |
1031 void vpx_svc_set_keyframe(SvcContext *svc_ctx) { | 833 void vpx_svc_set_keyframe(SvcContext *svc_ctx) { |
1032 SvcInternal *const si = get_svc_internal(svc_ctx); | 834 SvcInternal *const si = get_svc_internal(svc_ctx); |
1033 if (svc_ctx == NULL || si == NULL) return; | 835 if (svc_ctx == NULL || si == NULL) return; |
1034 si->frame_within_gop = 0; | 836 si->frame_within_gop = 0; |
1035 } | 837 } |
1036 | 838 |
1037 static double calc_psnr(double d) { | 839 static double calc_psnr(double d) { |
1038 if (d == 0) return 100; | 840 if (d == 0) return 100; |
1039 return -10.0 * log(d) / log(10.0); | 841 return -10.0 * log(d) / log(10.0); |
1040 } | 842 } |
1041 | 843 |
1042 // dump accumulated statistics and reset accumulated values | 844 // dump accumulated statistics and reset accumulated values |
1043 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { | 845 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { |
1044 int number_of_frames, number_of_keyframes, encode_frame_count; | 846 int number_of_frames, encode_frame_count; |
1045 int i, j; | 847 int i, j; |
1046 uint32_t bytes_total = 0; | 848 uint32_t bytes_total = 0; |
1047 double scale[COMPONENTS]; | 849 double scale[COMPONENTS]; |
1048 double psnr[COMPONENTS]; | 850 double psnr[COMPONENTS]; |
1049 double mse[COMPONENTS]; | 851 double mse[COMPONENTS]; |
1050 double y_scale; | 852 double y_scale; |
1051 | 853 |
1052 SvcInternal *const si = get_svc_internal(svc_ctx); | 854 SvcInternal *const si = get_svc_internal(svc_ctx); |
1053 if (svc_ctx == NULL || si == NULL) return NULL; | 855 if (svc_ctx == NULL || si == NULL) return NULL; |
1054 | 856 |
1055 svc_log_reset(svc_ctx); | 857 svc_log_reset(svc_ctx); |
1056 | 858 |
1057 encode_frame_count = si->encode_frame_count; | 859 encode_frame_count = si->encode_frame_count; |
1058 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx); | 860 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx); |
1059 | 861 |
1060 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); | 862 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); |
1061 number_of_keyframes = encode_frame_count / si->kf_dist + 1; | |
1062 for (i = 0; i < si->layers; ++i) { | 863 for (i = 0; i < si->layers; ++i) { |
1063 number_of_frames = encode_frame_count; | 864 number_of_frames = encode_frame_count; |
1064 | 865 |
1065 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && | |
1066 (i == 1 || i == 3)) { | |
1067 number_of_frames -= number_of_keyframes; | |
1068 } | |
1069 svc_log(svc_ctx, SVC_LOG_INFO, | 866 svc_log(svc_ctx, SVC_LOG_INFO, |
1070 "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n", | 867 "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n", |
1071 i, (double)si->psnr_sum[i][0] / number_of_frames, | 868 i, (double)si->psnr_sum[i][0] / number_of_frames, |
1072 (double)si->psnr_sum[i][1] / number_of_frames, | 869 (double)si->psnr_sum[i][1] / number_of_frames, |
1073 (double)si->psnr_sum[i][2] / number_of_frames, | 870 (double)si->psnr_sum[i][2] / number_of_frames, |
1074 (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]); | 871 (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]); |
1075 // the following psnr calculation is deduced from ffmpeg.c#print_report | 872 // the following psnr calculation is deduced from ffmpeg.c#print_report |
1076 y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames; | 873 y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames; |
1077 scale[1] = y_scale; | 874 scale[1] = y_scale; |
1078 scale[2] = scale[3] = y_scale / 4; // U or V | 875 scale[2] = scale[3] = y_scale / 4; // U or V |
(...skipping 26 matching lines...) Expand all Loading... |
1105 return vpx_svc_get_message(svc_ctx); | 902 return vpx_svc_get_message(svc_ctx); |
1106 } | 903 } |
1107 | 904 |
1108 void vpx_svc_release(SvcContext *svc_ctx) { | 905 void vpx_svc_release(SvcContext *svc_ctx) { |
1109 SvcInternal *si; | 906 SvcInternal *si; |
1110 if (svc_ctx == NULL) return; | 907 if (svc_ctx == NULL) return; |
1111 // do not use get_svc_internal as it will unnecessarily allocate an | 908 // do not use get_svc_internal as it will unnecessarily allocate an |
1112 // SvcInternal if it was not already allocated | 909 // SvcInternal if it was not already allocated |
1113 si = (SvcInternal *)svc_ctx->internal; | 910 si = (SvcInternal *)svc_ctx->internal; |
1114 if (si != NULL) { | 911 if (si != NULL) { |
1115 free(si->buffer); | 912 fd_free(si->frame_temp); |
| 913 fd_free_list(si->frame_list); |
1116 if (si->rc_stats_buf) { | 914 if (si->rc_stats_buf) { |
1117 free(si->rc_stats_buf); | 915 free(si->rc_stats_buf); |
1118 } | 916 } |
1119 free(si); | 917 free(si); |
1120 svc_ctx->internal = NULL; | 918 svc_ctx->internal = NULL; |
1121 } | 919 } |
1122 } | 920 } |
1123 | 921 |
1124 size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx) { | 922 size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx) { |
1125 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 923 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1126 if (svc_ctx == NULL || si == NULL) return 0; | 924 if (svc_ctx == NULL || si == NULL) return 0; |
1127 return si->rc_stats_buf_used; | 925 return si->rc_stats_buf_used; |
1128 } | 926 } |
1129 | 927 |
1130 char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx) { | 928 char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx) { |
1131 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 929 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
1132 if (svc_ctx == NULL || si == NULL) return NULL; | 930 if (svc_ctx == NULL || si == NULL) return NULL; |
1133 return si->rc_stats_buf; | 931 return si->rc_stats_buf; |
1134 } | 932 } |
1135 | 933 |
1136 | 934 |
OLD | NEW |