/* Derives the minimum level from the current configuration */ static gboolean ensure_level (GstVaapiEncoderMpeg2 * encoder) { const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder); const guint fps = (vip->fps_n + vip->fps_d - 1) / vip->fps_d; const guint bitrate = GST_VAAPI_ENCODER_CAST (encoder)->bitrate; const GstVaapiMPEG2LevelLimits *limits_table; guint i, num_limits, num_samples; num_samples = gst_util_uint64_scale_int_ceil (vip->width * vip->height, vip->fps_n, vip->fps_d); limits_table = gst_vaapi_utils_mpeg2_get_level_limits_table (&num_limits); for (i = 0; i < num_limits; i++) { const GstVaapiMPEG2LevelLimits *const limits = &limits_table[i]; if (vip->width <= limits->horizontal_size_value && vip->height <= limits->vertical_size_value && fps <= limits->frame_rate_value && num_samples <= limits->sample_rate && (!bitrate || bitrate <= limits->bit_rate)) break; } if (i == num_limits) goto error_unsupported_level; encoder->level = limits_table[i].level; encoder->level_idc = limits_table[i].level_idc; return TRUE; /* ERRORS */ error_unsupported_level: { GST_ERROR ("failed to find a suitable level matching codec config"); return FALSE; } }
void rg_analysis_analyze (RgAnalysisCtx * ctx, const gfloat * samples_l, const gfloat * samples_r, guint n_samples) { const gfloat *input_l, *input_r; guint n_samples_done; gint i; g_return_if_fail (ctx != NULL); g_return_if_fail (samples_l != NULL); g_return_if_fail (ctx->sample_rate != 0); if (n_samples == 0) return; if (samples_r == NULL) /* Mono. */ samples_r = samples_l; memcpy (ctx->inpre_l, samples_l, MIN (n_samples, MAX_ORDER) * sizeof (gfloat)); memcpy (ctx->inpre_r, samples_r, MIN (n_samples, MAX_ORDER) * sizeof (gfloat)); n_samples_done = 0; while (n_samples_done < n_samples) { /* Limit number of samples to be processed in this iteration to * the number needed to complete the next window: */ guint n_samples_current = MIN (n_samples - n_samples_done, ctx->window_n_samples - ctx->window_n_samples_done); if (n_samples_done < MAX_ORDER) { input_l = ctx->inpre_l + n_samples_done; input_r = ctx->inpre_r + n_samples_done; n_samples_current = MIN (n_samples_current, MAX_ORDER - n_samples_done); } else { input_l = samples_l + n_samples_done; input_r = samples_r + n_samples_done; } apply_filters (ctx, input_l, input_r, n_samples_current); /* Update the square sum. */ for (i = 0; i < n_samples_current; i++) ctx->window_square_sum += ctx->out_l[ctx->window_n_samples_done + i] * ctx->out_l[ctx->window_n_samples_done + i] + ctx->out_r[ctx->window_n_samples_done + i] * ctx->out_r[ctx->window_n_samples_done + i]; ctx->window_n_samples_done += n_samples_current; ctx->buffer_n_samples_done += n_samples_current; g_return_if_fail (ctx->window_n_samples_done <= ctx->window_n_samples); if (ctx->window_n_samples_done == ctx->window_n_samples) { /* Get the Root Mean Square (RMS) for this set of samples. */ gdouble val = STEPS_PER_DB * 10. * log10 (ctx->window_square_sum / ctx->window_n_samples * 0.5 + 1.e-37); gint ival = CLAMP ((gint) val, 0, (gint) G_N_ELEMENTS (ctx->track.histogram) - 1); /* Compute the per-window gain */ const gdouble gain = PINK_REF - (gdouble) ival / STEPS_PER_DB; const GstClockTime timestamp = ctx->buffer_timestamp + gst_util_uint64_scale_int_ceil (GST_SECOND, ctx->buffer_n_samples_done, ctx->sample_rate) - RMS_WINDOW_MSECS * GST_MSECOND; ctx->post_message (ctx->analysis, timestamp, RMS_WINDOW_MSECS * GST_MSECOND, -gain); ctx->track.histogram[ival]++; ctx->window_square_sum = 0.; ctx->window_n_samples_done = 0; /* No need for memmove here, the areas never overlap: Even for * the smallest sample rate, the number of samples needed for * the window is greater than MAX_ORDER. */ memcpy (ctx->stepbuf_l, ctx->stepbuf_l + ctx->window_n_samples, MAX_ORDER * sizeof (gfloat)); memcpy (ctx->outbuf_l, ctx->outbuf_l + ctx->window_n_samples, MAX_ORDER * sizeof (gfloat)); memcpy (ctx->stepbuf_r, ctx->stepbuf_r + ctx->window_n_samples, MAX_ORDER * sizeof (gfloat)); memcpy (ctx->outbuf_r, ctx->outbuf_r + ctx->window_n_samples, MAX_ORDER * sizeof (gfloat)); } n_samples_done += n_samples_current; } if (n_samples >= MAX_ORDER) { memcpy (ctx->inprebuf_l, samples_l + n_samples - MAX_ORDER, MAX_ORDER * sizeof (gfloat)); memcpy (ctx->inprebuf_r, samples_r + n_samples - MAX_ORDER, MAX_ORDER * sizeof (gfloat)); } else { memmove (ctx->inprebuf_l, ctx->inprebuf_l + n_samples, (MAX_ORDER - n_samples) * sizeof (gfloat)); memcpy (ctx->inprebuf_l + MAX_ORDER - n_samples, samples_l, n_samples * sizeof (gfloat)); memmove (ctx->inprebuf_r, ctx->inprebuf_r + n_samples, (MAX_ORDER - n_samples) * sizeof (gfloat)); memcpy (ctx->inprebuf_r + MAX_ORDER - n_samples, samples_r, n_samples * sizeof (gfloat)); } }