2 * Copyright (C) 2019 Thibault Saunier <tsaunier@igalia.com>
4 * gstencoderbitrateprofilemanager.c
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include "gstencoderbitrateprofilemanager.h"
27 GST_DEBUG_CATEGORY_STATIC (encoderbitratemanager_debug);
28 #define GST_CAT_DEFAULT encoderbitratemanager_debug
34 GstEncoderBitrateTargetForPixelsMap *map;
35 } GstEncoderBitrateProfile;
37 struct _GstEncoderBitrateProfileManager
43 gboolean setting_preset;
44 gboolean user_bitrate;
48 /* Copied from https://support.google.com/youtube/answer/1722171?hl=en */
49 static const GstEncoderBitrateTargetForPixelsMap youtube_bitrate_profiles[] = {
51 .n_pixels = 3840 * 2160,
52 .low_framerate_bitrate = 40000,
53 .high_framerate_bitrate = 60000,
56 .n_pixels = 2560 * 1440,
57 .low_framerate_bitrate = 16000,
58 .high_framerate_bitrate = 24000,
61 .n_pixels = 1920 * 1080,
62 .low_framerate_bitrate = 8000,
63 .high_framerate_bitrate = 12000,
66 .n_pixels = 1080 * 720,
67 .low_framerate_bitrate = 5000,
68 .high_framerate_bitrate = 7500,
71 .n_pixels = 640 * 480,
72 .low_framerate_bitrate = 2500,
73 .high_framerate_bitrate = 4000,
77 .low_framerate_bitrate = 2500,
78 .high_framerate_bitrate = 4000,
82 .low_framerate_bitrate = 0,
83 .high_framerate_bitrate = 0,
89 gst_encoder_bitrate_profile_free (GstEncoderBitrateProfile * profile)
91 g_free (profile->name);
92 g_free (profile->map);
97 gst_encoder_bitrate_profile_manager_add_profile (GstEncoderBitrateProfileManager
98 * self, const gchar * profile_name,
99 const GstEncoderBitrateTargetForPixelsMap * map)
102 GstEncoderBitrateProfile *profile;
105 map[n_vals].low_framerate_bitrate != 0
106 && map[n_vals].high_framerate_bitrate != 0; n_vals++);
109 profile = g_new0 (GstEncoderBitrateProfile, 1);
110 profile->name = g_strdup (profile_name);
111 profile->n_vals = n_vals;
113 = g_memdup2 (map, sizeof (GstEncoderBitrateTargetForPixelsMap) * n_vals);
114 self->profiles = g_list_prepend (self->profiles, profile);
118 gst_encoder_bitrate_profile_manager_get_bitrate (GstEncoderBitrateProfileManager
119 * self, GstVideoInfo * info)
126 GstEncoderBitrateProfile *profile = NULL;
128 g_return_val_if_fail (self != NULL, -1);
130 if (!info || info->finfo == NULL
131 || info->finfo->format == GST_VIDEO_FORMAT_UNKNOWN) {
132 GST_INFO ("Video info %p not usable, returning current bitrate", info);
133 return self->bitrate;
137 GST_INFO ("No preset used, returning current bitrate");
138 return self->bitrate;
142 for (tmp = self->profiles; tmp; tmp = tmp->next) {
143 GstEncoderBitrateProfile *tmpprof = tmp->data;
144 if (!g_strcmp0 (tmpprof->name, self->preset)) {
151 GST_INFO ("Could not find map for profile: %s", self->preset);
153 return self->bitrate;
156 high_fps = GST_VIDEO_INFO_FPS_N (info) / GST_VIDEO_INFO_FPS_D (info) > 30.0;
157 num_pix = GST_VIDEO_INFO_WIDTH (info) * GST_VIDEO_INFO_HEIGHT (info);
158 for (i = 0; i < profile->n_vals; i++) {
159 GstEncoderBitrateTargetForPixelsMap *bitrate_values = &profile->map[i];
161 if (num_pix < bitrate_values->n_pixels)
165 high_fps ? bitrate_values->
166 high_framerate_bitrate : bitrate_values->low_framerate_bitrate;
167 GST_INFO ("Using %s bitrate! %d", self->preset, self->bitrate);
168 return self->bitrate;
174 void gst_encoder_bitrate_profile_manager_start_loading_preset
175 (GstEncoderBitrateProfileManager * self)
177 self->setting_preset = TRUE;
180 void gst_encoder_bitrate_profile_manager_end_loading_preset
181 (GstEncoderBitrateProfileManager * self, const gchar * preset)
183 self->setting_preset = FALSE;
184 g_free (self->preset);
185 self->preset = g_strdup (preset);
189 gst_encoder_bitrate_profile_manager_set_bitrate (GstEncoderBitrateProfileManager
190 * self, guint bitrate)
192 self->bitrate = bitrate;
193 self->user_bitrate = !self->setting_preset;
197 gst_encoder_bitrate_profile_manager_free (GstEncoderBitrateProfileManager *
200 g_free (self->preset);
201 g_list_free_full (self->profiles,
202 (GDestroyNotify) gst_encoder_bitrate_profile_free);
206 GstEncoderBitrateProfileManager *
207 gst_encoder_bitrate_profile_manager_new (guint default_bitrate)
209 GstEncoderBitrateProfileManager *self =
210 g_new0 (GstEncoderBitrateProfileManager, 1);
211 static gsize _init = 0;
213 if (g_once_init_enter (&_init)) {
214 GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "encoderbitratemanager", 0,
215 "Encoder bitrate manager");
216 g_once_init_leave (&_init, 1);
219 self->bitrate = default_bitrate;
220 gst_encoder_bitrate_profile_manager_add_profile (self,
221 "Profile YouTube", youtube_bitrate_profiles);