omxvideoenc: drain encoder on ALLOCATION and DRAIN queries
[platform/upstream/gstreamer.git] / omx / gstomxh265dec.c
1 /*
2  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3  * Copyright (C) 2017 Xilinx, Inc.
4  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation
9  * version 2.1 of the License.
10  *
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  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <gst/gst.h>
27
28 #include "gstomxh265dec.h"
29 #include "gstomxh265utils.h"
30
31 GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_dec_debug_category);
32 #define GST_CAT_DEFAULT gst_omx_h265_dec_debug_category
33
34 /* prototypes */
35 static gboolean gst_omx_h265_dec_is_format_change (GstOMXVideoDec * dec,
36     GstOMXPort * port, GstVideoCodecState * state);
37 static gboolean gst_omx_h265_dec_set_format (GstOMXVideoDec * dec,
38     GstOMXPort * port, GstVideoCodecState * state);
39
40 enum
41 {
42   PROP_0
43 };
44
45 /* class initialization */
46
47 #define DEBUG_INIT \
48   GST_DEBUG_CATEGORY_INIT (gst_omx_h265_dec_debug_category, "omxh265dec", 0, \
49       "debug category for gst-omx H265 video decoder");
50
51 G_DEFINE_TYPE_WITH_CODE (GstOMXH265Dec, gst_omx_h265_dec,
52     GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
53
54 static void
55 gst_omx_h265_dec_class_init (GstOMXH265DecClass * klass)
56 {
57   GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
58   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
59
60   videodec_class->is_format_change =
61       GST_DEBUG_FUNCPTR (gst_omx_h265_dec_is_format_change);
62   videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_dec_set_format);
63
64   videodec_class->cdata.default_sink_template_caps = "video/x-h265, "
65       "alignment=(string) au, "
66       "stream-format=(string) byte-stream, "
67       "width=(int) [1,MAX], " "height=(int) [1,MAX]";
68
69   gst_element_class_set_static_metadata (element_class,
70       "OpenMAX H.265 Video Decoder",
71       "Codec/Decoder/Video/Hardware",
72       "Decode H.265 video streams",
73       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
74
75   gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.hevc");
76 }
77
78 static void
79 gst_omx_h265_dec_init (GstOMXH265Dec * self)
80 {
81 }
82
83 static gboolean
84 gst_omx_h265_dec_is_format_change (GstOMXVideoDec * dec,
85     GstOMXPort * port, GstVideoCodecState * state)
86 {
87   GstCaps *old_caps = NULL;
88   GstCaps *new_caps = state->caps;
89   GstStructure *old_structure, *new_structure;
90   const gchar *old_profile, *old_level, *old_tier, *new_profile, *new_level,
91       *new_tier;
92
93   if (dec->input_state) {
94     old_caps = dec->input_state->caps;
95   }
96
97   if (!old_caps) {
98     return FALSE;
99   }
100
101   old_structure = gst_caps_get_structure (old_caps, 0);
102   new_structure = gst_caps_get_structure (new_caps, 0);
103   old_profile = gst_structure_get_string (old_structure, "profile");
104   old_level = gst_structure_get_string (old_structure, "level");
105   old_tier = gst_structure_get_string (old_structure, "tier");
106   new_profile = gst_structure_get_string (new_structure, "profile");
107   new_level = gst_structure_get_string (new_structure, "level");
108   new_tier = gst_structure_get_string (new_structure, "tier");
109
110   if (g_strcmp0 (old_profile, new_profile) != 0
111       || g_strcmp0 (old_level, new_level) != 0
112       || g_strcmp0 (old_tier, new_tier)) {
113     return TRUE;
114   }
115
116   return FALSE;
117 }
118
119 static gboolean
120 set_profile_and_level (GstOMXH265Dec * self, GstVideoCodecState * state)
121 {
122   OMX_ERRORTYPE err;
123   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
124   const gchar *profile_string, *level_string, *tier_string;
125   GstStructure *s;
126
127   GST_OMX_INIT_STRUCT (&param);
128   param.nPortIndex = GST_OMX_VIDEO_DEC (self)->dec_in_port->index;
129
130   /* Pass profile, level and tier to the decoder if we have all info from the
131    * caps. */
132   s = gst_caps_get_structure (state->caps, 0);
133   profile_string = gst_structure_get_string (s, "profile");
134   if (!profile_string)
135     return TRUE;
136
137   param.eProfile = gst_omx_h265_utils_get_profile_from_str (profile_string);
138   if (param.eProfile == OMX_VIDEO_HEVCProfileUnknown)
139     goto unsupported_profile;
140
141   level_string = gst_structure_get_string (s, "level");
142   tier_string = gst_structure_get_string (s, "tier");
143   if (!level_string || !tier_string)
144     return TRUE;
145
146   param.eLevel =
147       gst_omx_h265_utils_get_level_from_str (level_string, tier_string);
148   if (param.eLevel == OMX_VIDEO_HEVCLevelUnknown)
149     goto unsupported_level;
150
151   GST_DEBUG_OBJECT (self,
152       "Set profile (%s) level (%s) and tier (%s) on decoder", profile_string,
153       level_string, tier_string);
154
155   err =
156       gst_omx_component_set_parameter (GST_OMX_VIDEO_DEC (self)->dec,
157       OMX_IndexParamVideoProfileLevelCurrent, &param);
158   if (err == OMX_ErrorUnsupportedIndex) {
159     GST_WARNING_OBJECT (self,
160         "Setting profile/level not supported by component");
161   } else if (err != OMX_ErrorNone) {
162     GST_ERROR_OBJECT (self,
163         "Error setting profile %u and level %u: %s (0x%08x)",
164         (guint) param.eProfile, (guint) param.eLevel,
165         gst_omx_error_to_string (err), err);
166     return FALSE;
167   }
168
169   return TRUE;
170
171 unsupported_profile:
172   GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
173   return FALSE;
174
175 unsupported_level:
176   GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
177   return FALSE;
178 }
179
180 static gboolean
181 gst_omx_h265_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
182     GstVideoCodecState * state)
183 {
184   GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (dec);
185   OMX_PARAM_PORTDEFINITIONTYPE port_def;
186   OMX_ERRORTYPE err;
187
188   gst_omx_port_get_port_definition (port, &port_def);
189   port_def.format.video.eCompressionFormat =
190       (OMX_VIDEO_CODINGTYPE) OMX_VIDEO_CodingHEVC;
191   err = gst_omx_port_update_port_definition (port, &port_def);
192   if (err != OMX_ErrorNone)
193     return FALSE;
194
195   if (klass->cdata.hacks & GST_OMX_HACK_PASS_PROFILE_TO_DECODER) {
196     if (!set_profile_and_level (GST_OMX_H265_DEC (dec), state))
197       return FALSE;
198   }
199
200   return TRUE;
201 }