[0.6.244] Fix the bug that does not disconnect pad signal
[platform/core/multimedia/libmm-player.git] / src / mm_player_360.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <mm_attrs.h>
21 #include <mm_error.h>
22 #include "mm_player_priv.h"
23 #include "mm_player_360.h"
24 #include "mm_player_utils.h"
25 #include <gst/gst.h>
26 #include <gst/gstutils.h>
27 #include <glib.h>
28
29 static bool
30 __mmplayer_check_video_360_used(mmplayer_t *player)
31 {
32         /* check video 360 plugin is created */
33         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
34                 player->pipeline &&
35                 player->pipeline->videobin &&
36                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
37                 player->pipeline->videobin[MMPLAYER_V_360].gst,
38                 false);
39
40         return true;
41 }
42
43 static bool
44 __mmplayer_check_audio_sink(mmplayer_t *player)
45 {
46         /* check audio sink is created */
47         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
48                 player->pipeline &&
49                 player->pipeline->videobin &&
50                 player->pipeline->videobin[MMPLAYER_A_BIN].gst &&
51                 player->pipeline->videobin[MMPLAYER_A_SINK].gst,
52                 false);
53
54         return true;
55 }
56
57 int
58 _mmplayer_360_is_content_spherical(MMHandleType hplayer, bool *is_spherical)
59 {
60         mmplayer_t *player = (mmplayer_t *)hplayer;
61
62         MMPLAYER_FENTER();
63         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
64         MMPLAYER_RETURN_VAL_IF_FAIL(is_spherical, MM_ERROR_INVALID_ARGUMENT);
65
66         LOGD("state %s, spherical info %d",
67                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
68
69         if (player->state < MM_PLAYER_STATE_READY) {
70                 *is_spherical = false;
71                 return MM_ERROR_PLAYER_INVALID_STATE;
72         }
73
74         *is_spherical = (bool)player->is_content_spherical;
75
76         MMPLAYER_FLEAVE();
77         return MM_ERROR_NONE;
78 }
79
80 int
81 _mmplayer_360_set_enabled(MMHandleType hplayer, bool enabled)
82 {
83         mmplayer_t *player = (mmplayer_t *)hplayer;
84
85         MMPLAYER_FENTER();
86         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
87
88         LOGD("state %s, spherical info %d",
89                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
90
91         player->is_video360_enabled = (gboolean)enabled;
92
93         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
94                 /* We will get here if player is pending ready or ready and above */
95                 LOGD("set enabled %d", player->is_video360_enabled);
96                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
97                                 "passthrough", !player->is_video360_enabled, NULL);
98         }
99
100         MMPLAYER_FLEAVE();
101         return MM_ERROR_NONE;
102 }
103
104 int
105 _mmplayer_360_is_enabled(MMHandleType hplayer, bool *enabled)
106 {
107         mmplayer_t *player = (mmplayer_t *)hplayer;
108         gboolean is_enabled;
109
110         MMPLAYER_FENTER();
111         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
112         MMPLAYER_RETURN_VAL_IF_FAIL(enabled, MM_ERROR_INVALID_ARGUMENT);
113
114         LOGD("state %s, spherical info %d",
115                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
116
117         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
118                 g_object_get(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
119                                 "passthrough", &is_enabled, NULL);
120                 *enabled = !((bool)is_enabled);
121         } else {
122                 *enabled = (bool)player->is_video360_enabled;
123         }
124
125         LOGD("get enabled %d", *enabled);
126
127         MMPLAYER_FLEAVE();
128         return MM_ERROR_NONE;
129 }
130
131 int
132 _mmplayer_360_set_direction_of_view(MMHandleType hplayer, float yaw, float pitch)
133 {
134         mmplayer_t *player = (mmplayer_t *)hplayer;
135
136         MMPLAYER_FENTER();
137         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
138
139         if (yaw > (float)(M_PI) || yaw < (float)(-M_PI) || pitch > (float)(M_PI_2) || pitch < (float)(-M_PI_2)) {
140                 LOGE("invalid argument %f, %f", yaw, pitch);
141                 return MM_ERROR_INVALID_ARGUMENT;
142         }
143
144         LOGD("state %s, spherical info %d",
145                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
146
147         player->video360_yaw_radians = yaw;
148         player->video360_pitch_radians = pitch;
149
150         if (player->is_content_spherical) {
151                 /* We will get here if player is pending ready or ready and above */
152                 if (__mmplayer_check_video_360_used(player)) {
153                         LOGD("set yaw %f, pitch %f for video", yaw, pitch);
154                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
155                                         "pose-yaw", (int)(yaw * 180.0f / M_PI),
156                                         "pose-pitch", (int)(pitch * 180.0f / M_PI), NULL);
157                 }
158                 if (player->is_openal_plugin_used && __mmplayer_check_audio_sink(player)) {
159                         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst),
160                                         "source-orientation-y", (int)(yaw * 180.0f / M_PI),
161                                         "source-orientation-x", (int)(pitch * 180.0f / M_PI), NULL);
162                 }
163         }
164
165         MMPLAYER_FLEAVE();
166         return MM_ERROR_NONE;
167 }
168
169 int
170 _mmplayer_360_get_direction_of_view(MMHandleType hplayer, float *yaw, float *pitch)
171 {
172         mmplayer_t *player = (mmplayer_t *)hplayer;
173         int yaw_degrees = 0;
174         int pitch_degrees = 0;
175
176         MMPLAYER_FENTER();
177         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
178         MMPLAYER_RETURN_VAL_IF_FAIL(yaw && pitch, MM_ERROR_INVALID_ARGUMENT);
179
180         LOGD("state %s, spherical info %d",
181                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
182
183         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
184                 g_object_get(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
185                                 "pose-yaw", &yaw_degrees, "pose-pitch", &pitch_degrees, NULL);
186                 *yaw = M_PI * yaw_degrees / 180.0f;
187                 *pitch = M_PI * pitch_degrees / 180.0f;
188
189                 LOGD("get yaw %f, pitch %f", *yaw, *pitch);
190                 return MM_ERROR_NONE;
191         }
192
193         *yaw = player->video360_yaw_radians;
194         *pitch = player->video360_pitch_radians;
195
196         MMPLAYER_FLEAVE();
197         return MM_ERROR_NONE;
198 }
199
200 int
201 _mmplayer_360_set_zoom(MMHandleType hplayer, float level)
202 {
203         mmplayer_t *player = (mmplayer_t *)hplayer;
204
205         MMPLAYER_FENTER();
206         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
207
208         if (level < 1.0f || level > VIDEO360_MAX_ZOOM) {
209                 LOGE("invalid argument %f", level);
210                 return MM_ERROR_INVALID_ARGUMENT;
211         }
212
213         LOGD("state %s, spherical info %d",
214                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
215
216         player->video360_zoom = level;
217
218         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
219                 /* We will get here if player is pending ready or ready and above */
220
221                 LOGD("set level %f", level);
222                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
223                                 "zoom", 1.0f / level, NULL);
224         }
225
226         MMPLAYER_FLEAVE();
227         return MM_ERROR_NONE;
228 }
229
230 int
231 _mmplayer_360_get_zoom(MMHandleType hplayer, float *level)
232 {
233         mmplayer_t *player = (mmplayer_t *)hplayer;
234         float current_zoom = 0.0;
235
236         MMPLAYER_FENTER();
237         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
238         MMPLAYER_RETURN_VAL_IF_FAIL(level, MM_ERROR_INVALID_ARGUMENT);
239
240         LOGD("state %s, spherical info %d",
241                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
242
243         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
244                 g_object_get(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
245                                 "zoom", &current_zoom, NULL);
246                 *level = 1.0f / current_zoom;
247
248                 LOGD("get level %f", *level);
249                 return MM_ERROR_NONE;
250         }
251
252         *level = player->video360_zoom;
253
254         MMPLAYER_FLEAVE();
255         return MM_ERROR_NONE;
256 }
257
258 int
259 _mmplayer_360_set_field_of_view(MMHandleType hplayer, int horizontal_degrees, int vertical_degrees)
260 {
261         mmplayer_t *player = (mmplayer_t *)hplayer;
262
263         MMPLAYER_FENTER();
264         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
265
266         if (horizontal_degrees < 1 || horizontal_degrees > 360 || vertical_degrees < 1 || vertical_degrees > 180) {
267                 LOGE("invalid argument %d, %d", horizontal_degrees, vertical_degrees);
268                 return MM_ERROR_INVALID_ARGUMENT;
269         }
270
271         LOGD("state %s, spherical info %d",
272                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
273
274         player->video360_horizontal_fov = horizontal_degrees;
275         player->video360_vertical_fov = vertical_degrees;
276
277         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
278                 /* We will get here if player is pending ready or ready and above */
279                 LOGD("set h-fov %d, v-fov %d", horizontal_degrees, vertical_degrees);
280                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
281                                 "horizontal-fov", horizontal_degrees, "vertical-fov", vertical_degrees, NULL);
282         }
283
284         MMPLAYER_FLEAVE();
285         return MM_ERROR_NONE;
286 }
287
288 int
289 _mmplayer_360_get_field_of_view(MMHandleType hplayer, int *horizontal_degrees, int *vertical_degrees)
290 {
291         mmplayer_t *player = (mmplayer_t *)hplayer;
292
293         MMPLAYER_FENTER();
294         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
295         MMPLAYER_RETURN_VAL_IF_FAIL(horizontal_degrees && vertical_degrees, MM_ERROR_INVALID_ARGUMENT);
296
297         LOGD("state %s, spherical info %d",
298                         MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), player->is_content_spherical);
299
300         if (player->is_content_spherical && __mmplayer_check_video_360_used(player)) {
301                 g_object_get(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_360].gst),
302                                 "horizontal-fov", horizontal_degrees, "vertical-fov", vertical_degrees, NULL);
303
304                 LOGD("get h-fov %d, v-fov %d", *horizontal_degrees, *vertical_degrees);
305                 return MM_ERROR_NONE;
306         }
307
308         *horizontal_degrees = player->video360_horizontal_fov;
309         *vertical_degrees = player->video360_vertical_fov;
310
311         MMPLAYER_FLEAVE();
312         return MM_ERROR_NONE;
313 }