• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012,2018 Collabora Ltd.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
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 "../gstjniutils.h"
27 #include "../gstamc-format.h"
28 #include "gstamc-internal-jni.h"
29 
30 static struct
31 {
32   jclass klass;
33   jmethodID create_audio_format;
34   jmethodID create_video_format;
35   jmethodID to_string;
36   jmethodID get_float;
37   jmethodID set_float;
38   jmethodID get_integer;
39   jmethodID set_integer;
40   jmethodID get_string;
41   jmethodID set_string;
42   jmethodID get_byte_buffer;
43   jmethodID set_byte_buffer;
44 } media_format;
45 
46 gboolean
gst_amc_format_static_init(void)47 gst_amc_format_static_init (void)
48 {
49   gboolean ret = TRUE;
50   JNIEnv *env;
51   jclass tmp;
52 
53   env = gst_amc_jni_get_env ();
54 
55   tmp = (*env)->FindClass (env, "android/media/MediaFormat");
56   if (!tmp) {
57     ret = FALSE;
58     GST_ERROR ("Failed to get format class");
59     if ((*env)->ExceptionCheck (env)) {
60       (*env)->ExceptionDescribe (env);
61       (*env)->ExceptionClear (env);
62     }
63     goto done;
64   }
65   media_format.klass = (*env)->NewGlobalRef (env, tmp);
66   if (!media_format.klass) {
67     ret = FALSE;
68     GST_ERROR ("Failed to get format class global reference");
69     if ((*env)->ExceptionCheck (env)) {
70       (*env)->ExceptionDescribe (env);
71       (*env)->ExceptionClear (env);
72     }
73     goto done;
74   }
75   (*env)->DeleteLocalRef (env, tmp);
76   tmp = NULL;
77 
78   media_format.create_audio_format =
79       (*env)->GetStaticMethodID (env, media_format.klass, "createAudioFormat",
80       "(Ljava/lang/String;II)Landroid/media/MediaFormat;");
81   media_format.create_video_format =
82       (*env)->GetStaticMethodID (env, media_format.klass, "createVideoFormat",
83       "(Ljava/lang/String;II)Landroid/media/MediaFormat;");
84   media_format.to_string =
85       (*env)->GetMethodID (env, media_format.klass, "toString",
86       "()Ljava/lang/String;");
87   media_format.get_float =
88       (*env)->GetMethodID (env, media_format.klass, "getFloat",
89       "(Ljava/lang/String;)F");
90   media_format.set_float =
91       (*env)->GetMethodID (env, media_format.klass, "setFloat",
92       "(Ljava/lang/String;F)V");
93   media_format.get_integer =
94       (*env)->GetMethodID (env, media_format.klass, "getInteger",
95       "(Ljava/lang/String;)I");
96   media_format.set_integer =
97       (*env)->GetMethodID (env, media_format.klass, "setInteger",
98       "(Ljava/lang/String;I)V");
99   media_format.get_string =
100       (*env)->GetMethodID (env, media_format.klass, "getString",
101       "(Ljava/lang/String;)Ljava/lang/String;");
102   media_format.set_string =
103       (*env)->GetMethodID (env, media_format.klass, "setString",
104       "(Ljava/lang/String;Ljava/lang/String;)V");
105   media_format.get_byte_buffer =
106       (*env)->GetMethodID (env, media_format.klass, "getByteBuffer",
107       "(Ljava/lang/String;)Ljava/nio/ByteBuffer;");
108   media_format.set_byte_buffer =
109       (*env)->GetMethodID (env, media_format.klass, "setByteBuffer",
110       "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V");
111   if (!media_format.create_audio_format || !media_format.create_video_format
112       || !media_format.get_float || !media_format.set_float
113       || !media_format.get_integer || !media_format.set_integer
114       || !media_format.get_string || !media_format.set_string
115       || !media_format.get_byte_buffer || !media_format.set_byte_buffer) {
116     ret = FALSE;
117     GST_ERROR ("Failed to get format methods");
118     if ((*env)->ExceptionCheck (env)) {
119       (*env)->ExceptionDescribe (env);
120       (*env)->ExceptionClear (env);
121     }
122     goto done;
123   }
124 
125 done:
126   if (tmp)
127     (*env)->DeleteLocalRef (env, tmp);
128   tmp = NULL;
129 
130   return ret;
131 }
132 
133 GstAmcFormat *
gst_amc_format_new_audio(const gchar * mime,gint sample_rate,gint channels,GError ** err)134 gst_amc_format_new_audio (const gchar * mime, gint sample_rate, gint channels,
135     GError ** err)
136 {
137   JNIEnv *env;
138   GstAmcFormat *format = NULL;
139   jstring mime_str;
140 
141   g_return_val_if_fail (mime != NULL, NULL);
142 
143   env = gst_amc_jni_get_env ();
144 
145   mime_str = gst_amc_jni_string_from_gchar (env, err, FALSE, mime);
146   if (!mime_str)
147     goto error;
148 
149   format = g_slice_new0 (GstAmcFormat);
150   format->object =
151       gst_amc_jni_new_object_from_static (env, err, TRUE, media_format.klass,
152       media_format.create_audio_format, mime_str, sample_rate, channels);
153   if (!format->object)
154     goto error;
155 
156 done:
157   if (mime_str)
158     gst_amc_jni_object_local_unref (env, mime_str);
159   mime_str = NULL;
160 
161   return format;
162 
163 error:
164   if (format)
165     g_slice_free (GstAmcFormat, format);
166   format = NULL;
167   goto done;
168 }
169 
170 GstAmcFormat *
gst_amc_format_new_video(const gchar * mime,gint width,gint height,GError ** err)171 gst_amc_format_new_video (const gchar * mime, gint width, gint height,
172     GError ** err)
173 {
174   JNIEnv *env;
175   GstAmcFormat *format = NULL;
176   jstring mime_str;
177 
178   g_return_val_if_fail (mime != NULL, NULL);
179 
180   env = gst_amc_jni_get_env ();
181 
182   mime_str = gst_amc_jni_string_from_gchar (env, err, FALSE, mime);
183   if (!mime_str)
184     goto error;
185 
186   format = g_slice_new0 (GstAmcFormat);
187   format->object =
188       gst_amc_jni_new_object_from_static (env, err, TRUE, media_format.klass,
189       media_format.create_video_format, mime_str, width, height);
190   if (!format->object)
191     goto error;
192 
193 done:
194   if (mime_str)
195     gst_amc_jni_object_local_unref (env, mime_str);
196   mime_str = NULL;
197 
198   return format;
199 
200 error:
201   if (format)
202     g_slice_free (GstAmcFormat, format);
203   format = NULL;
204   goto done;
205 }
206 
207 void
gst_amc_format_free(GstAmcFormat * format)208 gst_amc_format_free (GstAmcFormat * format)
209 {
210   JNIEnv *env;
211 
212   g_return_if_fail (format != NULL);
213 
214   env = gst_amc_jni_get_env ();
215   gst_amc_jni_object_unref (env, format->object);
216   g_slice_free (GstAmcFormat, format);
217 }
218 
219 gchar *
gst_amc_format_to_string(GstAmcFormat * format,GError ** err)220 gst_amc_format_to_string (GstAmcFormat * format, GError ** err)
221 {
222   JNIEnv *env;
223   jstring v_str = NULL;
224   gchar *ret = NULL;
225 
226   g_return_val_if_fail (format != NULL, FALSE);
227 
228   env = gst_amc_jni_get_env ();
229 
230   if (!gst_amc_jni_call_object_method (env, err, format->object,
231           media_format.to_string, &v_str))
232     goto done;
233   ret = gst_amc_jni_string_to_gchar (env, v_str, TRUE);
234 
235 done:
236 
237   return ret;
238 }
239 
240 gboolean
gst_amc_format_get_float(GstAmcFormat * format,const gchar * key,gfloat * value,GError ** err)241 gst_amc_format_get_float (GstAmcFormat * format, const gchar * key,
242     gfloat * value, GError ** err)
243 {
244   JNIEnv *env;
245   gboolean ret = FALSE;
246   jstring key_str = NULL;
247 
248   g_return_val_if_fail (format != NULL, FALSE);
249   g_return_val_if_fail (key != NULL, FALSE);
250   g_return_val_if_fail (value != NULL, FALSE);
251 
252   *value = 0;
253   env = gst_amc_jni_get_env ();
254 
255   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
256   if (!key_str)
257     goto done;
258 
259   if (!gst_amc_jni_call_float_method (env, err, format->object,
260           media_format.get_float, value, key_str))
261     goto done;
262   ret = TRUE;
263 
264 done:
265   if (key_str)
266     gst_amc_jni_object_local_unref (env, key_str);
267 
268   return ret;
269 }
270 
271 gboolean
gst_amc_format_set_float(GstAmcFormat * format,const gchar * key,gfloat value,GError ** err)272 gst_amc_format_set_float (GstAmcFormat * format, const gchar * key,
273     gfloat value, GError ** err)
274 {
275   JNIEnv *env;
276   jstring key_str = NULL;
277   gboolean ret = FALSE;
278 
279   g_return_val_if_fail (format != NULL, FALSE);
280   g_return_val_if_fail (key != NULL, FALSE);
281 
282   env = gst_amc_jni_get_env ();
283 
284   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
285   if (!key_str)
286     goto done;
287 
288   if (!gst_amc_jni_call_void_method (env, err, format->object,
289           media_format.set_float, key_str, value))
290     goto done;
291 
292   ret = TRUE;
293 
294 done:
295   if (key_str)
296     gst_amc_jni_object_local_unref (env, key_str);
297 
298   return ret;
299 }
300 
301 gboolean
gst_amc_format_get_int(GstAmcFormat * format,const gchar * key,gint * value,GError ** err)302 gst_amc_format_get_int (GstAmcFormat * format, const gchar * key, gint * value,
303     GError ** err)
304 {
305   JNIEnv *env;
306   gboolean ret = FALSE;
307   jstring key_str = NULL;
308 
309   g_return_val_if_fail (format != NULL, FALSE);
310   g_return_val_if_fail (key != NULL, FALSE);
311   g_return_val_if_fail (value != NULL, FALSE);
312 
313   *value = 0;
314   env = gst_amc_jni_get_env ();
315 
316   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
317   if (!key_str)
318     goto done;
319 
320   if (!gst_amc_jni_call_int_method (env, err, format->object,
321           media_format.get_integer, value, key_str))
322     goto done;
323   ret = TRUE;
324 
325 done:
326   if (key_str)
327     gst_amc_jni_object_local_unref (env, key_str);
328 
329   return ret;
330 
331 }
332 
333 gboolean
gst_amc_format_set_int(GstAmcFormat * format,const gchar * key,gint value,GError ** err)334 gst_amc_format_set_int (GstAmcFormat * format, const gchar * key, gint value,
335     GError ** err)
336 {
337   JNIEnv *env;
338   jstring key_str = NULL;
339   gboolean ret = FALSE;
340 
341   g_return_val_if_fail (format != NULL, FALSE);
342   g_return_val_if_fail (key != NULL, FALSE);
343 
344   env = gst_amc_jni_get_env ();
345 
346   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
347   if (!key_str)
348     goto done;
349 
350   if (!gst_amc_jni_call_void_method (env, err, format->object,
351           media_format.set_integer, key_str, value))
352     goto done;
353 
354   ret = TRUE;
355 
356 done:
357   if (key_str)
358     gst_amc_jni_object_local_unref (env, key_str);
359 
360   return ret;
361 }
362 
363 gboolean
gst_amc_format_get_string(GstAmcFormat * format,const gchar * key,gchar ** value,GError ** err)364 gst_amc_format_get_string (GstAmcFormat * format, const gchar * key,
365     gchar ** value, GError ** err)
366 {
367   JNIEnv *env;
368   gboolean ret = FALSE;
369   jstring key_str = NULL;
370   jstring v_str = NULL;
371 
372   g_return_val_if_fail (format != NULL, FALSE);
373   g_return_val_if_fail (key != NULL, FALSE);
374   g_return_val_if_fail (value != NULL, FALSE);
375 
376   *value = 0;
377   env = gst_amc_jni_get_env ();
378 
379   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
380   if (!key_str)
381     goto done;
382 
383   if (!gst_amc_jni_call_object_method (env, err, format->object,
384           media_format.get_string, &v_str, key_str))
385     goto done;
386 
387   *value = gst_amc_jni_string_to_gchar (env, v_str, TRUE);
388 
389   ret = TRUE;
390 
391 done:
392   if (key_str)
393     gst_amc_jni_object_local_unref (env, key_str);
394 
395   return ret;
396 }
397 
398 gboolean
gst_amc_format_set_string(GstAmcFormat * format,const gchar * key,const gchar * value,GError ** err)399 gst_amc_format_set_string (GstAmcFormat * format, const gchar * key,
400     const gchar * value, GError ** err)
401 {
402   JNIEnv *env;
403   jstring key_str = NULL;
404   jstring v_str = NULL;
405   gboolean ret = FALSE;
406 
407   g_return_val_if_fail (format != NULL, FALSE);
408   g_return_val_if_fail (key != NULL, FALSE);
409   g_return_val_if_fail (value != NULL, FALSE);
410 
411   env = gst_amc_jni_get_env ();
412 
413   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
414   if (!key_str)
415     goto done;
416 
417   v_str = gst_amc_jni_string_from_gchar (env, err, FALSE, value);
418   if (!v_str)
419     goto done;
420 
421   if (!gst_amc_jni_call_void_method (env, err, format->object,
422           media_format.set_string, key_str, v_str))
423     goto done;
424 
425   ret = TRUE;
426 
427 done:
428   if (key_str)
429     gst_amc_jni_object_local_unref (env, key_str);
430   if (v_str)
431     gst_amc_jni_object_local_unref (env, v_str);
432 
433   return ret;
434 }
435 
436 gboolean
gst_amc_format_get_buffer(GstAmcFormat * format,const gchar * key,guint8 ** data,gsize * size,GError ** err)437 gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
438     guint8 ** data, gsize * size, GError ** err)
439 {
440   JNIEnv *env;
441   gboolean ret = FALSE;
442   jstring key_str = NULL;
443   jobject v = NULL;
444   RealBuffer buf = { 0, };
445   gint position = 0, limit = 0;
446 
447   g_return_val_if_fail (format != NULL, FALSE);
448   g_return_val_if_fail (key != NULL, FALSE);
449   g_return_val_if_fail (data != NULL, FALSE);
450   g_return_val_if_fail (size != NULL, FALSE);
451 
452   *data = NULL;
453   *size = 0;
454   env = gst_amc_jni_get_env ();
455 
456   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
457   if (!key_str)
458     goto done;
459 
460   if (!gst_amc_jni_call_object_method (env, err, format->object,
461           media_format.get_byte_buffer, &v, key_str))
462     goto done;
463 
464   *data = (*env)->GetDirectBufferAddress (env, v);
465   if (*data == NULL) {
466     gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
467         GST_LIBRARY_ERROR_FAILED, "Failed get buffer address");
468     goto done;
469   }
470   *size = (*env)->GetDirectBufferCapacity (env, v);
471 
472   buf.object = v;
473   buf.data = *data;
474   buf.size = *size;
475   gst_amc_buffer_get_position_and_limit (&buf, NULL, &position, &limit);
476   *size = limit;
477 
478   *data = g_memdup2 (*data + position, limit);
479 
480   ret = TRUE;
481 
482 done:
483   if (key_str)
484     gst_amc_jni_object_local_unref (env, key_str);
485   if (v)
486     gst_amc_jni_object_local_unref (env, v);
487 
488   return ret;
489 }
490 
491 gboolean
gst_amc_format_set_buffer(GstAmcFormat * format,const gchar * key,guint8 * data,gsize size,GError ** err)492 gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
493     guint8 * data, gsize size, GError ** err)
494 {
495   JNIEnv *env;
496   jstring key_str = NULL;
497   jobject v = NULL;
498   gboolean ret = FALSE;
499   RealBuffer buf = { 0, };
500 
501   g_return_val_if_fail (format != NULL, FALSE);
502   g_return_val_if_fail (key != NULL, FALSE);
503   g_return_val_if_fail (data != NULL, FALSE);
504 
505   env = gst_amc_jni_get_env ();
506 
507   key_str = gst_amc_jni_string_from_gchar (env, err, FALSE, key);
508   if (!key_str)
509     goto done;
510 
511   /* FIXME: The memory must remain valid until the codec is stopped */
512   v = (*env)->NewDirectByteBuffer (env, data, size);
513   if (!v) {
514     gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
515         GST_LIBRARY_ERROR_FAILED, "Failed create Java byte buffer");
516     goto done;
517   }
518 
519   buf.object = v;
520   buf.data = data;
521   buf.size = size;
522 
523   gst_amc_buffer_set_position_and_limit ((GstAmcBuffer *) & buf, NULL, 0, size);
524 
525   if (!gst_amc_jni_call_void_method (env, err, format->object,
526           media_format.set_byte_buffer, key_str, v))
527     goto done;
528 
529   ret = TRUE;
530 
531 done:
532   if (key_str)
533     gst_amc_jni_object_local_unref (env, key_str);
534   if (v)
535     gst_amc_jni_object_local_unref (env, v);
536 
537   return ret;
538 }
539