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