• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer Intel MSDK plugin
2  * Copyright (c) 2016, Oblong Industries, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #  include <config.h>
34 #endif
35 
36 #include <mfxplugin.h>
37 #include <mfxvp8.h>
38 
39 #include "gstmsdkvp8enc.h"
40 
41 GST_DEBUG_CATEGORY_EXTERN (gst_msdkvp8enc_debug);
42 #define GST_CAT_DEFAULT gst_msdkvp8enc_debug
43 
44 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
45     GST_PAD_SRC,
46     GST_PAD_ALWAYS,
47     GST_STATIC_CAPS ("video/x-vp8, "
48         "framerate = (fraction) [0/1, MAX], "
49         "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ], "
50         "profile = (string) { 0, 1, 2, 3 }")
51     );
52 
53 #define gst_msdkvp8enc_parent_class parent_class
54 G_DEFINE_TYPE (GstMsdkVP8Enc, gst_msdkvp8enc, GST_TYPE_MSDKENC);
55 
56 static gboolean
gst_msdkvp8enc_set_format(GstMsdkEnc * encoder)57 gst_msdkvp8enc_set_format (GstMsdkEnc * encoder)
58 {
59   GstMsdkVP8Enc *thiz = GST_MSDKVP8ENC (encoder);
60   GstCaps *template_caps;
61   GstCaps *allowed_caps = NULL;
62 
63   thiz->profile = 0;
64 
65   template_caps = gst_static_pad_template_get_caps (&src_factory);
66   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
67 
68   /* If downstream has ANY caps let encoder decide profile and level */
69   if (allowed_caps == template_caps) {
70     GST_INFO_OBJECT (thiz,
71         "downstream has ANY caps, profile/level set to auto");
72   } else if (allowed_caps) {
73     GstStructure *s;
74     const gchar *profile;
75 
76     if (gst_caps_is_empty (allowed_caps)) {
77       gst_caps_unref (allowed_caps);
78       gst_caps_unref (template_caps);
79       return FALSE;
80     }
81 
82     allowed_caps = gst_caps_make_writable (allowed_caps);
83     allowed_caps = gst_caps_fixate (allowed_caps);
84     s = gst_caps_get_structure (allowed_caps, 0);
85 
86     profile = gst_structure_get_string (s, "profile");
87     if (profile) {
88       if (!strcmp (profile, "3")) {
89         thiz->profile = MFX_PROFILE_VP8_3;
90       } else if (!strcmp (profile, "2")) {
91         thiz->profile = MFX_PROFILE_VP8_2;
92       } else if (!strcmp (profile, "1")) {
93         thiz->profile = MFX_PROFILE_VP8_1;
94       } else if (!strcmp (profile, "0")) {
95         thiz->profile = MFX_PROFILE_VP8_0;
96       } else {
97         g_assert_not_reached ();
98       }
99     }
100 
101     gst_caps_unref (allowed_caps);
102   }
103 
104   gst_caps_unref (template_caps);
105 
106   return TRUE;
107 }
108 
109 static gboolean
gst_msdkvp8enc_configure(GstMsdkEnc * encoder)110 gst_msdkvp8enc_configure (GstMsdkEnc * encoder)
111 {
112   GstMsdkVP8Enc *thiz = GST_MSDKVP8ENC (encoder);
113   mfxSession session;
114   mfxStatus status;
115 
116   if (encoder->hardware) {
117     session = gst_msdk_context_get_session (encoder->context);
118     status = MFXVideoUSER_Load (session, &MFX_PLUGINID_VP8E_HW, 1);
119     if (status < MFX_ERR_NONE) {
120       GST_ERROR_OBJECT (thiz, "Media SDK Plugin load failed (%s)",
121           msdk_status_to_string (status));
122       return FALSE;
123     } else if (status > MFX_ERR_NONE) {
124       GST_WARNING_OBJECT (thiz, "Media SDK Plugin load warning: %s",
125           msdk_status_to_string (status));
126     }
127   }
128 
129   encoder->param.mfx.CodecId = MFX_CODEC_VP8;
130   encoder->param.mfx.CodecProfile = thiz->profile;
131   encoder->param.mfx.CodecLevel = 0;
132 
133   /* Enable Extended Coding options */
134   gst_msdkenc_ensure_extended_coding_options (encoder);
135 
136   return TRUE;
137 }
138 
139 static inline const gchar *
profile_to_string(gint profile)140 profile_to_string (gint profile)
141 {
142   switch (profile) {
143     case MFX_PROFILE_VP8_3:
144       return "3";
145     case MFX_PROFILE_VP8_2:
146       return "2";
147     case MFX_PROFILE_VP8_1:
148       return "1";
149     case MFX_PROFILE_VP8_0:
150       return "0";
151     default:
152       break;
153   }
154 
155   return NULL;
156 }
157 
158 static GstCaps *
gst_msdkvp8enc_set_src_caps(GstMsdkEnc * encoder)159 gst_msdkvp8enc_set_src_caps (GstMsdkEnc * encoder)
160 {
161   GstCaps *caps;
162   GstStructure *structure;
163   const gchar *profile;
164 
165   caps = gst_caps_new_empty_simple ("video/x-vp8");
166   structure = gst_caps_get_structure (caps, 0);
167 
168   profile = profile_to_string (encoder->param.mfx.CodecProfile);
169   if (profile)
170     gst_structure_set (structure, "profile", G_TYPE_STRING, profile, NULL);
171 
172   return caps;
173 }
174 
175 static void
gst_msdkvp8enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)176 gst_msdkvp8enc_set_property (GObject * object, guint prop_id,
177     const GValue * value, GParamSpec * pspec)
178 {
179   GstMsdkVP8Enc *thiz = GST_MSDKVP8ENC (object);
180 
181   if (!gst_msdkenc_set_common_property (object, prop_id, value, pspec))
182     GST_WARNING_OBJECT (thiz, "Failed to set common encode property");
183 }
184 
185 static void
gst_msdkvp8enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)186 gst_msdkvp8enc_get_property (GObject * object, guint prop_id, GValue * value,
187     GParamSpec * pspec)
188 {
189   GstMsdkVP8Enc *thiz = GST_MSDKVP8ENC (object);
190 
191   if (!gst_msdkenc_get_common_property (object, prop_id, value, pspec))
192     GST_WARNING_OBJECT (thiz, "Failed to get common encode property");
193 }
194 
195 static void
gst_msdkvp8enc_class_init(GstMsdkVP8EncClass * klass)196 gst_msdkvp8enc_class_init (GstMsdkVP8EncClass * klass)
197 {
198   GObjectClass *gobject_class;
199   GstElementClass *element_class;
200   GstMsdkEncClass *encoder_class;
201 
202   gobject_class = G_OBJECT_CLASS (klass);
203   element_class = GST_ELEMENT_CLASS (klass);
204   encoder_class = GST_MSDKENC_CLASS (klass);
205 
206   gobject_class->set_property = gst_msdkvp8enc_set_property;
207   gobject_class->get_property = gst_msdkvp8enc_get_property;
208 
209   encoder_class->set_format = gst_msdkvp8enc_set_format;
210   encoder_class->configure = gst_msdkvp8enc_configure;
211   encoder_class->set_src_caps = gst_msdkvp8enc_set_src_caps;
212 
213   gst_msdkenc_install_common_properties (encoder_class);
214 
215   gst_element_class_set_static_metadata (element_class,
216       "Intel MSDK VP8 encoder",
217       "Codec/Encoder/Video/Hardware",
218       "VP8 video encoder based on Intel Media SDK",
219       "Josep Torra <jtorra@oblong.com>");
220 
221   gst_element_class_add_static_pad_template (element_class, &src_factory);
222 }
223 
224 static void
gst_msdkvp8enc_init(GstMsdkVP8Enc * thiz)225 gst_msdkvp8enc_init (GstMsdkVP8Enc * thiz)
226 {
227 }
228