gstreamer_android.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. #include <jni.h>
  2. #include <gst/gst.h>
  3. #include <gio/gio.h>
  4. #include <android/log.h>
  5. #include <string.h>
  6. /* XXX: Workaround for Android <21 making signal() an inline function
  7. * around bsd_signal(), and Android >= 21 not having any bsd_signal()
  8. * symbol but only signal().
  9. * See https://bugzilla.gnome.org/show_bug.cgi?id=766235
  10. */
  11. static gpointer
  12. load_real_signal (gpointer data)
  13. {
  14. GModule *module;
  15. gpointer ret = NULL;
  16. module = g_module_open ("libc.so", G_MODULE_BIND_LOCAL);
  17. g_module_symbol (module, "signal", &ret);
  18. /* As fallback, let's try bsd_signal */
  19. if (ret == NULL) {
  20. g_warning ("Can't find signal(3) in libc.so!");
  21. g_module_symbol (module, "bsd_signal", &ret);
  22. }
  23. g_module_close (module);
  24. return ret;
  25. }
  26. __sighandler_t bsd_signal(int signum, __sighandler_t handler) __attribute__((weak));
  27. __sighandler_t bsd_signal(int signum, __sighandler_t handler)
  28. {
  29. static GOnce gonce = G_ONCE_INIT;
  30. __sighandler_t (*real_signal) (int signum, __sighandler_t handler);
  31. g_once (&gonce, load_real_signal, NULL);
  32. real_signal = gonce.retval;
  33. g_assert (real_signal != NULL);
  34. return real_signal(signum, handler);
  35. }
  36. static jobject _context = NULL;
  37. static jobject _class_loader = NULL;
  38. static JavaVM *_java_vm = NULL;
  39. static GstClockTime _priv_gst_info_start_time;
  40. #define GST_G_IO_MODULE_DECLARE(name) \
  41. extern void G_PASTE(g_io_, G_PASTE(name, _load)) (gpointer data)
  42. #define GST_G_IO_MODULE_LOAD(name) \
  43. G_PASTE(g_io_, G_PASTE(name, _load)) (NULL)
  44. /* Declaration of static plugins */
  45. GST_PLUGIN_STATIC_DECLARE(coreelements); GST_PLUGIN_STATIC_DECLARE(coretracers); GST_PLUGIN_STATIC_DECLARE(adder); GST_PLUGIN_STATIC_DECLARE(app); GST_PLUGIN_STATIC_DECLARE(audioconvert); GST_PLUGIN_STATIC_DECLARE(audiomixer); GST_PLUGIN_STATIC_DECLARE(audiorate); GST_PLUGIN_STATIC_DECLARE(audioresample); GST_PLUGIN_STATIC_DECLARE(audiotestsrc); GST_PLUGIN_STATIC_DECLARE(compositor); GST_PLUGIN_STATIC_DECLARE(gio); GST_PLUGIN_STATIC_DECLARE(overlaycomposition); GST_PLUGIN_STATIC_DECLARE(pango); GST_PLUGIN_STATIC_DECLARE(rawparse); GST_PLUGIN_STATIC_DECLARE(typefindfunctions); GST_PLUGIN_STATIC_DECLARE(videoconvert); GST_PLUGIN_STATIC_DECLARE(videorate); GST_PLUGIN_STATIC_DECLARE(videoscale); GST_PLUGIN_STATIC_DECLARE(videotestsrc); GST_PLUGIN_STATIC_DECLARE(volume); GST_PLUGIN_STATIC_DECLARE(autodetect); GST_PLUGIN_STATIC_DECLARE(videofilter); GST_PLUGIN_STATIC_DECLARE(opengl); GST_PLUGIN_STATIC_DECLARE(ipcpipeline); GST_PLUGIN_STATIC_DECLARE(opensles); GST_PLUGIN_STATIC_DECLARE(playback); GST_PLUGIN_STATIC_DECLARE(subparse); GST_PLUGIN_STATIC_DECLARE(ogg); GST_PLUGIN_STATIC_DECLARE(theora); GST_PLUGIN_STATIC_DECLARE(vorbis); GST_PLUGIN_STATIC_DECLARE(opus); GST_PLUGIN_STATIC_DECLARE(ivorbisdec); GST_PLUGIN_STATIC_DECLARE(alaw); GST_PLUGIN_STATIC_DECLARE(apetag); GST_PLUGIN_STATIC_DECLARE(audioparsers); GST_PLUGIN_STATIC_DECLARE(auparse); GST_PLUGIN_STATIC_DECLARE(avi); GST_PLUGIN_STATIC_DECLARE(dv); GST_PLUGIN_STATIC_DECLARE(flac); GST_PLUGIN_STATIC_DECLARE(flv); GST_PLUGIN_STATIC_DECLARE(flxdec); GST_PLUGIN_STATIC_DECLARE(icydemux); GST_PLUGIN_STATIC_DECLARE(id3demux); GST_PLUGIN_STATIC_DECLARE(isomp4); GST_PLUGIN_STATIC_DECLARE(jpeg); GST_PLUGIN_STATIC_DECLARE(lame); GST_PLUGIN_STATIC_DECLARE(matroska); GST_PLUGIN_STATIC_DECLARE(mpg123); GST_PLUGIN_STATIC_DECLARE(mulaw); GST_PLUGIN_STATIC_DECLARE(multipart); GST_PLUGIN_STATIC_DECLARE(png); GST_PLUGIN_STATIC_DECLARE(speex); GST_PLUGIN_STATIC_DECLARE(taglib); GST_PLUGIN_STATIC_DECLARE(vpx); GST_PLUGIN_STATIC_DECLARE(wavenc); GST_PLUGIN_STATIC_DECLARE(wavpack); GST_PLUGIN_STATIC_DECLARE(wavparse); GST_PLUGIN_STATIC_DECLARE(y4menc); GST_PLUGIN_STATIC_DECLARE(adpcmdec); GST_PLUGIN_STATIC_DECLARE(adpcmenc); GST_PLUGIN_STATIC_DECLARE(assrender); GST_PLUGIN_STATIC_DECLARE(bz2); GST_PLUGIN_STATIC_DECLARE(dash); GST_PLUGIN_STATIC_DECLARE(dvbsuboverlay); GST_PLUGIN_STATIC_DECLARE(dvdspu); GST_PLUGIN_STATIC_DECLARE(hls); GST_PLUGIN_STATIC_DECLARE(id3tag); GST_PLUGIN_STATIC_DECLARE(kate); GST_PLUGIN_STATIC_DECLARE(midi); GST_PLUGIN_STATIC_DECLARE(mxf); GST_PLUGIN_STATIC_DECLARE(openh264); GST_PLUGIN_STATIC_DECLARE(opusparse); GST_PLUGIN_STATIC_DECLARE(pcapparse); GST_PLUGIN_STATIC_DECLARE(pnm); GST_PLUGIN_STATIC_DECLARE(rfbsrc); GST_PLUGIN_STATIC_DECLARE(siren); GST_PLUGIN_STATIC_DECLARE(smoothstreaming); GST_PLUGIN_STATIC_DECLARE(subenc); GST_PLUGIN_STATIC_DECLARE(videoparsersbad); GST_PLUGIN_STATIC_DECLARE(y4mdec); GST_PLUGIN_STATIC_DECLARE(jpegformat); GST_PLUGIN_STATIC_DECLARE(gdp); GST_PLUGIN_STATIC_DECLARE(rsvg); GST_PLUGIN_STATIC_DECLARE(openjpeg); GST_PLUGIN_STATIC_DECLARE(spandsp); GST_PLUGIN_STATIC_DECLARE(sbc); GST_PLUGIN_STATIC_DECLARE(zbar); GST_PLUGIN_STATIC_DECLARE(androidmedia); GST_PLUGIN_STATIC_DECLARE(alpha); GST_PLUGIN_STATIC_DECLARE(alphacolor); GST_PLUGIN_STATIC_DECLARE(audiofx); GST_PLUGIN_STATIC_DECLARE(cairo); GST_PLUGIN_STATIC_DECLARE(cutter); GST_PLUGIN_STATIC_DECLARE(debug); GST_PLUGIN_STATIC_DECLARE(deinterlace); GST_PLUGIN_STATIC_DECLARE(dtmf); GST_PLUGIN_STATIC_DECLARE(effectv); GST_PLUGIN_STATIC_DECLARE(equalizer); GST_PLUGIN_STATIC_DECLARE(gdkpixbuf); GST_PLUGIN_STATIC_DECLARE(imagefreeze); GST_PLUGIN_STATIC_DECLARE(interleave); GST_PLUGIN_STATIC_DECLARE(level); GST_PLUGIN_STATIC_DECLARE(multifile); GST_PLUGIN_STATIC_DECLARE(replaygain); GST_PLUGIN_STATIC_DECLARE(shapewipe); GST_PLUGIN_STATIC_DECLARE(smpte); GST_PLUGIN_STATIC_DECLARE(spectrum); GST_PLUGIN_STATIC_DECLARE(videobox); GST_PLUGIN_STATIC_DECLARE(videocrop); GST_PLUGIN_STATIC_DECLARE(videomixer); GST_PLUGIN_STATIC_DECLARE(accurip); GST_PLUGIN_STATIC_DECLARE(aiff); GST_PLUGIN_STATIC_DECLARE(audiobuffersplit); GST_PLUGIN_STATIC_DECLARE(audiofxbad); GST_PLUGIN_STATIC_DECLARE(audiolatency); GST_PLUGIN_STATIC_DECLARE(audiomixmatrix); GST_PLUGIN_STATIC_DECLARE(autoconvert); GST_PLUGIN_STATIC_DECLARE(bayer); GST_PLUGIN_STATIC_DECLARE(coloreffects); GST_PLUGIN_STATIC_DECLARE(closedcaption); GST_PLUGIN_STATIC_DECLARE(debugutilsbad); GST_PLUGIN_STATIC_DECLARE(fieldanalysis); GST_PLUGIN_STATIC_DECLARE(freeverb); GST_PLUGIN_STATIC_DECLARE(frei0r); GST_PLUGIN_STATIC_DECLARE(gaudieffects); GST_PLUGIN_STATIC_DECLARE(geometrictransform); GST_PLUGIN_STATIC_DECLARE(inter); GST_PLUGIN_STATIC_DECLARE(interlace); GST_PLUGIN_STATIC_DECLARE(ivtc); GST_PLUGIN_STATIC_DECLARE(legacyrawparse); GST_PLUGIN_STATIC_DECLARE(proxy); GST_PLUGIN_STATIC_DECLARE(removesilence); GST_PLUGIN_STATIC_DECLARE(segmentclip); GST_PLUGIN_STATIC_DECLARE(smooth); GST_PLUGIN_STATIC_DECLARE(speed); GST_PLUGIN_STATIC_DECLARE(soundtouch); GST_PLUGIN_STATIC_DECLARE(timecode); GST_PLUGIN_STATIC_DECLARE(videofiltersbad); GST_PLUGIN_STATIC_DECLARE(videoframe_audiolevel); GST_PLUGIN_STATIC_DECLARE(webrtcdsp); GST_PLUGIN_STATIC_DECLARE(ladspa); GST_PLUGIN_STATIC_DECLARE(tcp); GST_PLUGIN_STATIC_DECLARE(rtsp); GST_PLUGIN_STATIC_DECLARE(rtp); GST_PLUGIN_STATIC_DECLARE(rtpmanager); GST_PLUGIN_STATIC_DECLARE(soup); GST_PLUGIN_STATIC_DECLARE(udp); GST_PLUGIN_STATIC_DECLARE(dtls); GST_PLUGIN_STATIC_DECLARE(netsim); GST_PLUGIN_STATIC_DECLARE(rist); GST_PLUGIN_STATIC_DECLARE(rtmp2); GST_PLUGIN_STATIC_DECLARE(rtpmanagerbad); GST_PLUGIN_STATIC_DECLARE(sctp); GST_PLUGIN_STATIC_DECLARE(sdpelem); GST_PLUGIN_STATIC_DECLARE(srtp); GST_PLUGIN_STATIC_DECLARE(srt); GST_PLUGIN_STATIC_DECLARE(webrtc); GST_PLUGIN_STATIC_DECLARE(nice); GST_PLUGIN_STATIC_DECLARE(rtspclientsink);
  46. /* Declaration of static gio modules */
  47. /* This is called by gst_init() to register static plugins */
  48. void
  49. gst_init_static_plugins (void)
  50. {
  51. GST_PLUGIN_STATIC_REGISTER(coreelements); GST_PLUGIN_STATIC_REGISTER(coretracers); GST_PLUGIN_STATIC_REGISTER(adder); GST_PLUGIN_STATIC_REGISTER(app); GST_PLUGIN_STATIC_REGISTER(audioconvert); GST_PLUGIN_STATIC_REGISTER(audiomixer); GST_PLUGIN_STATIC_REGISTER(audiorate); GST_PLUGIN_STATIC_REGISTER(audioresample); GST_PLUGIN_STATIC_REGISTER(audiotestsrc); GST_PLUGIN_STATIC_REGISTER(compositor); GST_PLUGIN_STATIC_REGISTER(gio); GST_PLUGIN_STATIC_REGISTER(overlaycomposition); GST_PLUGIN_STATIC_REGISTER(pango); GST_PLUGIN_STATIC_REGISTER(rawparse); GST_PLUGIN_STATIC_REGISTER(typefindfunctions); GST_PLUGIN_STATIC_REGISTER(videoconvert); GST_PLUGIN_STATIC_REGISTER(videorate); GST_PLUGIN_STATIC_REGISTER(videoscale); GST_PLUGIN_STATIC_REGISTER(videotestsrc); GST_PLUGIN_STATIC_REGISTER(volume); GST_PLUGIN_STATIC_REGISTER(autodetect); GST_PLUGIN_STATIC_REGISTER(videofilter); GST_PLUGIN_STATIC_REGISTER(opengl); GST_PLUGIN_STATIC_REGISTER(ipcpipeline); GST_PLUGIN_STATIC_REGISTER(opensles); GST_PLUGIN_STATIC_REGISTER(playback); GST_PLUGIN_STATIC_REGISTER(subparse); GST_PLUGIN_STATIC_REGISTER(ogg); GST_PLUGIN_STATIC_REGISTER(theora); GST_PLUGIN_STATIC_REGISTER(vorbis); GST_PLUGIN_STATIC_REGISTER(opus); GST_PLUGIN_STATIC_REGISTER(ivorbisdec); GST_PLUGIN_STATIC_REGISTER(alaw); GST_PLUGIN_STATIC_REGISTER(apetag); GST_PLUGIN_STATIC_REGISTER(audioparsers); GST_PLUGIN_STATIC_REGISTER(auparse); GST_PLUGIN_STATIC_REGISTER(avi); GST_PLUGIN_STATIC_REGISTER(dv); GST_PLUGIN_STATIC_REGISTER(flac); GST_PLUGIN_STATIC_REGISTER(flv); GST_PLUGIN_STATIC_REGISTER(flxdec); GST_PLUGIN_STATIC_REGISTER(icydemux); GST_PLUGIN_STATIC_REGISTER(id3demux); GST_PLUGIN_STATIC_REGISTER(isomp4); GST_PLUGIN_STATIC_REGISTER(jpeg); GST_PLUGIN_STATIC_REGISTER(lame); GST_PLUGIN_STATIC_REGISTER(matroska); GST_PLUGIN_STATIC_REGISTER(mpg123); GST_PLUGIN_STATIC_REGISTER(mulaw); GST_PLUGIN_STATIC_REGISTER(multipart); GST_PLUGIN_STATIC_REGISTER(png); GST_PLUGIN_STATIC_REGISTER(speex); GST_PLUGIN_STATIC_REGISTER(taglib); GST_PLUGIN_STATIC_REGISTER(vpx); GST_PLUGIN_STATIC_REGISTER(wavenc); GST_PLUGIN_STATIC_REGISTER(wavpack); GST_PLUGIN_STATIC_REGISTER(wavparse); GST_PLUGIN_STATIC_REGISTER(y4menc); GST_PLUGIN_STATIC_REGISTER(adpcmdec); GST_PLUGIN_STATIC_REGISTER(adpcmenc); GST_PLUGIN_STATIC_REGISTER(assrender); GST_PLUGIN_STATIC_REGISTER(bz2); GST_PLUGIN_STATIC_REGISTER(dash); GST_PLUGIN_STATIC_REGISTER(dvbsuboverlay); GST_PLUGIN_STATIC_REGISTER(dvdspu); GST_PLUGIN_STATIC_REGISTER(hls); GST_PLUGIN_STATIC_REGISTER(id3tag); GST_PLUGIN_STATIC_REGISTER(kate); GST_PLUGIN_STATIC_REGISTER(midi); GST_PLUGIN_STATIC_REGISTER(mxf); GST_PLUGIN_STATIC_REGISTER(openh264); GST_PLUGIN_STATIC_REGISTER(opusparse); GST_PLUGIN_STATIC_REGISTER(pcapparse); GST_PLUGIN_STATIC_REGISTER(pnm); GST_PLUGIN_STATIC_REGISTER(rfbsrc); GST_PLUGIN_STATIC_REGISTER(siren); GST_PLUGIN_STATIC_REGISTER(smoothstreaming); GST_PLUGIN_STATIC_REGISTER(subenc); GST_PLUGIN_STATIC_REGISTER(videoparsersbad); GST_PLUGIN_STATIC_REGISTER(y4mdec); GST_PLUGIN_STATIC_REGISTER(jpegformat); GST_PLUGIN_STATIC_REGISTER(gdp); GST_PLUGIN_STATIC_REGISTER(rsvg); GST_PLUGIN_STATIC_REGISTER(openjpeg); GST_PLUGIN_STATIC_REGISTER(spandsp); GST_PLUGIN_STATIC_REGISTER(sbc); GST_PLUGIN_STATIC_REGISTER(zbar); GST_PLUGIN_STATIC_REGISTER(androidmedia); GST_PLUGIN_STATIC_REGISTER(alpha); GST_PLUGIN_STATIC_REGISTER(alphacolor); GST_PLUGIN_STATIC_REGISTER(audiofx); GST_PLUGIN_STATIC_REGISTER(cairo); GST_PLUGIN_STATIC_REGISTER(cutter); GST_PLUGIN_STATIC_REGISTER(debug); GST_PLUGIN_STATIC_REGISTER(deinterlace); GST_PLUGIN_STATIC_REGISTER(dtmf); GST_PLUGIN_STATIC_REGISTER(effectv); GST_PLUGIN_STATIC_REGISTER(equalizer); GST_PLUGIN_STATIC_REGISTER(gdkpixbuf); GST_PLUGIN_STATIC_REGISTER(imagefreeze); GST_PLUGIN_STATIC_REGISTER(interleave); GST_PLUGIN_STATIC_REGISTER(level); GST_PLUGIN_STATIC_REGISTER(multifile); GST_PLUGIN_STATIC_REGISTER(replaygain); GST_PLUGIN_STATIC_REGISTER(shapewipe); GST_PLUGIN_STATIC_REGISTER(smpte); GST_PLUGIN_STATIC_REGISTER(spectrum); GST_PLUGIN_STATIC_REGISTER(videobox); GST_PLUGIN_STATIC_REGISTER(videocrop); GST_PLUGIN_STATIC_REGISTER(videomixer); GST_PLUGIN_STATIC_REGISTER(accurip); GST_PLUGIN_STATIC_REGISTER(aiff); GST_PLUGIN_STATIC_REGISTER(audiobuffersplit); GST_PLUGIN_STATIC_REGISTER(audiofxbad); GST_PLUGIN_STATIC_REGISTER(audiolatency); GST_PLUGIN_STATIC_REGISTER(audiomixmatrix); GST_PLUGIN_STATIC_REGISTER(autoconvert); GST_PLUGIN_STATIC_REGISTER(bayer); GST_PLUGIN_STATIC_REGISTER(coloreffects); GST_PLUGIN_STATIC_REGISTER(closedcaption); GST_PLUGIN_STATIC_REGISTER(debugutilsbad); GST_PLUGIN_STATIC_REGISTER(fieldanalysis); GST_PLUGIN_STATIC_REGISTER(freeverb); GST_PLUGIN_STATIC_REGISTER(frei0r); GST_PLUGIN_STATIC_REGISTER(gaudieffects); GST_PLUGIN_STATIC_REGISTER(geometrictransform); GST_PLUGIN_STATIC_REGISTER(inter); GST_PLUGIN_STATIC_REGISTER(interlace); GST_PLUGIN_STATIC_REGISTER(ivtc); GST_PLUGIN_STATIC_REGISTER(legacyrawparse); GST_PLUGIN_STATIC_REGISTER(proxy); GST_PLUGIN_STATIC_REGISTER(removesilence); GST_PLUGIN_STATIC_REGISTER(segmentclip); GST_PLUGIN_STATIC_REGISTER(smooth); GST_PLUGIN_STATIC_REGISTER(speed); GST_PLUGIN_STATIC_REGISTER(soundtouch); GST_PLUGIN_STATIC_REGISTER(timecode); GST_PLUGIN_STATIC_REGISTER(videofiltersbad); GST_PLUGIN_STATIC_REGISTER(videoframe_audiolevel); GST_PLUGIN_STATIC_REGISTER(webrtcdsp); GST_PLUGIN_STATIC_REGISTER(ladspa); GST_PLUGIN_STATIC_REGISTER(tcp); GST_PLUGIN_STATIC_REGISTER(rtsp); GST_PLUGIN_STATIC_REGISTER(rtp); GST_PLUGIN_STATIC_REGISTER(rtpmanager); GST_PLUGIN_STATIC_REGISTER(soup); GST_PLUGIN_STATIC_REGISTER(udp); GST_PLUGIN_STATIC_REGISTER(dtls); GST_PLUGIN_STATIC_REGISTER(netsim); GST_PLUGIN_STATIC_REGISTER(rist); GST_PLUGIN_STATIC_REGISTER(rtmp2); GST_PLUGIN_STATIC_REGISTER(rtpmanagerbad); GST_PLUGIN_STATIC_REGISTER(sctp); GST_PLUGIN_STATIC_REGISTER(sdpelem); GST_PLUGIN_STATIC_REGISTER(srtp); GST_PLUGIN_STATIC_REGISTER(srt); GST_PLUGIN_STATIC_REGISTER(webrtc); GST_PLUGIN_STATIC_REGISTER(nice); GST_PLUGIN_STATIC_REGISTER(rtspclientsink);
  52. }
  53. /* Call this function to load GIO modules */
  54. void
  55. gst_android_load_gio_modules (void)
  56. {
  57. GTlsBackend *backend;
  58. const gchar *ca_certs;
  59. ca_certs = g_getenv ("CA_CERTIFICATES");
  60. backend = g_tls_backend_get_default ();
  61. if (backend && ca_certs) {
  62. GTlsDatabase *db;
  63. GError *error = NULL;
  64. db = g_tls_file_database_new (ca_certs, &error);
  65. if (db) {
  66. g_tls_backend_set_default_database (backend, db);
  67. g_object_unref (db);
  68. } else {
  69. g_warning ("Failed to create a database from file: %s",
  70. error ? error->message : "Unknown");
  71. }
  72. }
  73. }
  74. static void
  75. glib_print_handler (const gchar * string)
  76. {
  77. __android_log_print (ANDROID_LOG_INFO, "GLib+stdout", "%s", string);
  78. }
  79. static void
  80. glib_printerr_handler (const gchar * string)
  81. {
  82. __android_log_print (ANDROID_LOG_ERROR, "GLib+stderr", "%s", string);
  83. }
  84. /* Based on GLib's default handler */
  85. #define CHAR_IS_SAFE(wc) (!((wc < 0x20 && wc != '\t' && wc != '\n' && wc != '\r') || \
  86. (wc == 0x7f) || \
  87. (wc >= 0x80 && wc < 0xa0)))
  88. #define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)
  89. #define STRING_BUFFER_SIZE (FORMAT_UNSIGNED_BUFSIZE + 32)
  90. #define ALERT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
  91. #define DEFAULT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE)
  92. #define INFO_LEVELS (G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)
  93. static void
  94. escape_string (GString * string)
  95. {
  96. const char *p = string->str;
  97. gunichar wc;
  98. while (p < string->str + string->len) {
  99. gboolean safe;
  100. wc = g_utf8_get_char_validated (p, -1);
  101. if (wc == (gunichar) - 1 || wc == (gunichar) - 2) {
  102. gchar *tmp;
  103. guint pos;
  104. pos = p - string->str;
  105. /* Emit invalid UTF-8 as hex escapes
  106. */
  107. tmp = g_strdup_printf ("\\x%02x", (guint) (guchar) * p);
  108. g_string_erase (string, pos, 1);
  109. g_string_insert (string, pos, tmp);
  110. p = string->str + (pos + 4); /* Skip over escape sequence */
  111. g_free (tmp);
  112. continue;
  113. }
  114. if (wc == '\r') {
  115. safe = *(p + 1) == '\n';
  116. } else {
  117. safe = CHAR_IS_SAFE (wc);
  118. }
  119. if (!safe) {
  120. gchar *tmp;
  121. guint pos;
  122. pos = p - string->str;
  123. /* Largest char we escape is 0x0a, so we don't have to worry
  124. * about 8-digit \Uxxxxyyyy
  125. */
  126. tmp = g_strdup_printf ("\\u%04x", wc);
  127. g_string_erase (string, pos, g_utf8_next_char (p) - p);
  128. g_string_insert (string, pos, tmp);
  129. g_free (tmp);
  130. p = string->str + (pos + 6); /* Skip over escape sequence */
  131. } else
  132. p = g_utf8_next_char (p);
  133. }
  134. }
  135. static void
  136. glib_log_handler (const gchar * log_domain, GLogLevelFlags log_level,
  137. const gchar * message, gpointer user_data)
  138. {
  139. gchar *string;
  140. GString *gstring;
  141. const gchar *domains;
  142. gint android_log_level;
  143. gchar *tag;
  144. if ((log_level & DEFAULT_LEVELS) || (log_level >> G_LOG_LEVEL_USER_SHIFT))
  145. goto emit;
  146. domains = g_getenv ("G_MESSAGES_DEBUG");
  147. if (((log_level & INFO_LEVELS) == 0) ||
  148. domains == NULL ||
  149. (strcmp (domains, "all") != 0 && (!log_domain
  150. || !strstr (domains, log_domain))))
  151. return;
  152. emit:
  153. if (log_domain)
  154. tag = g_strdup_printf ("GLib+%s", log_domain);
  155. else
  156. tag = g_strdup ("GLib");
  157. switch (log_level & G_LOG_LEVEL_MASK) {
  158. case G_LOG_LEVEL_ERROR:
  159. android_log_level = ANDROID_LOG_ERROR;
  160. break;
  161. case G_LOG_LEVEL_CRITICAL:
  162. android_log_level = ANDROID_LOG_ERROR;
  163. break;
  164. case G_LOG_LEVEL_WARNING:
  165. android_log_level = ANDROID_LOG_WARN;
  166. break;
  167. case G_LOG_LEVEL_MESSAGE:
  168. android_log_level = ANDROID_LOG_INFO;
  169. break;
  170. case G_LOG_LEVEL_INFO:
  171. android_log_level = ANDROID_LOG_INFO;
  172. break;
  173. case G_LOG_LEVEL_DEBUG:
  174. android_log_level = ANDROID_LOG_DEBUG;
  175. break;
  176. default:
  177. android_log_level = ANDROID_LOG_INFO;
  178. break;
  179. }
  180. gstring = g_string_new (NULL);
  181. if (!message) {
  182. g_string_append (gstring, "(NULL) message");
  183. } else {
  184. GString * msg = g_string_new (message);
  185. escape_string (msg);
  186. g_string_append (gstring, msg->str);
  187. g_string_free (msg, TRUE);
  188. }
  189. string = g_string_free (gstring, FALSE);
  190. __android_log_print (android_log_level, tag, "%s", string);
  191. g_free (string);
  192. g_free (tag);
  193. }
  194. static void
  195. gst_debug_logcat (GstDebugCategory * category, GstDebugLevel level,
  196. const gchar * file, const gchar * function, gint line,
  197. GObject * object, GstDebugMessage * message, gpointer unused)
  198. {
  199. GstClockTime elapsed;
  200. gint android_log_level;
  201. gchar *tag;
  202. if (level > gst_debug_category_get_threshold (category))
  203. return;
  204. elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
  205. gst_util_get_timestamp ());
  206. switch (level) {
  207. case GST_LEVEL_ERROR:
  208. android_log_level = ANDROID_LOG_ERROR;
  209. break;
  210. case GST_LEVEL_WARNING:
  211. android_log_level = ANDROID_LOG_WARN;
  212. break;
  213. case GST_LEVEL_INFO:
  214. android_log_level = ANDROID_LOG_INFO;
  215. break;
  216. case GST_LEVEL_DEBUG:
  217. android_log_level = ANDROID_LOG_DEBUG;
  218. break;
  219. default:
  220. android_log_level = ANDROID_LOG_VERBOSE;
  221. break;
  222. }
  223. tag = g_strdup_printf ("GStreamer+%s",
  224. gst_debug_category_get_name (category));
  225. if (object) {
  226. gchar *obj;
  227. if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) {
  228. obj = g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object));
  229. } else if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) {
  230. obj = g_strdup_printf ("<%s>", GST_OBJECT_NAME (object));
  231. } else if (G_IS_OBJECT (object)) {
  232. obj = g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object);
  233. } else {
  234. obj = g_strdup_printf ("<%p>", object);
  235. }
  236. __android_log_print (android_log_level, tag,
  237. "%" GST_TIME_FORMAT " %p %s:%d:%s:%s %s\n",
  238. GST_TIME_ARGS (elapsed), g_thread_self (),
  239. file, line, function, obj, gst_debug_message_get (message));
  240. g_free (obj);
  241. } else {
  242. __android_log_print (android_log_level, tag,
  243. "%" GST_TIME_FORMAT " %p %s:%d:%s %s\n",
  244. GST_TIME_ARGS (elapsed), g_thread_self (),
  245. file, line, function, gst_debug_message_get (message));
  246. }
  247. g_free (tag);
  248. }
  249. static gboolean
  250. get_application_dirs (JNIEnv * env, jobject context, gchar ** cache_dir,
  251. gchar ** files_dir)
  252. {
  253. jclass context_class;
  254. jmethodID get_cache_dir_id, get_files_dir_id;
  255. jclass file_class;
  256. jmethodID get_absolute_path_id;
  257. jobject dir;
  258. jstring abs_path;
  259. const gchar *abs_path_str;
  260. *cache_dir = *files_dir = NULL;
  261. context_class = (*env)->GetObjectClass (env, context);
  262. if (!context_class) {
  263. return FALSE;
  264. }
  265. get_cache_dir_id =
  266. (*env)->GetMethodID (env, context_class, "getCacheDir",
  267. "()Ljava/io/File;");
  268. get_files_dir_id =
  269. (*env)->GetMethodID (env, context_class, "getFilesDir",
  270. "()Ljava/io/File;");
  271. if (!get_cache_dir_id || !get_files_dir_id) {
  272. (*env)->DeleteLocalRef (env, context_class);
  273. return FALSE;
  274. }
  275. file_class = (*env)->FindClass (env, "java/io/File");
  276. if (!file_class) {
  277. (*env)->DeleteLocalRef (env, context_class);
  278. return FALSE;
  279. }
  280. get_absolute_path_id =
  281. (*env)->GetMethodID (env, file_class, "getAbsolutePath",
  282. "()Ljava/lang/String;");
  283. if (!get_absolute_path_id) {
  284. (*env)->DeleteLocalRef (env, context_class);
  285. (*env)->DeleteLocalRef (env, file_class);
  286. return FALSE;
  287. }
  288. dir = (*env)->CallObjectMethod (env, context, get_cache_dir_id);
  289. if ((*env)->ExceptionCheck (env)) {
  290. (*env)->ExceptionDescribe (env);
  291. (*env)->ExceptionClear (env);
  292. (*env)->DeleteLocalRef (env, context_class);
  293. (*env)->DeleteLocalRef (env, file_class);
  294. return FALSE;
  295. }
  296. if (dir) {
  297. abs_path = (*env)->CallObjectMethod (env, dir, get_absolute_path_id);
  298. if ((*env)->ExceptionCheck (env)) {
  299. (*env)->ExceptionDescribe (env);
  300. (*env)->ExceptionClear (env);
  301. (*env)->DeleteLocalRef (env, dir);
  302. (*env)->DeleteLocalRef (env, context_class);
  303. (*env)->DeleteLocalRef (env, file_class);
  304. return FALSE;
  305. }
  306. abs_path_str = (*env)->GetStringUTFChars (env, abs_path, NULL);
  307. if ((*env)->ExceptionCheck (env)) {
  308. (*env)->ExceptionDescribe (env);
  309. (*env)->ExceptionClear (env);
  310. (*env)->DeleteLocalRef (env, abs_path);
  311. (*env)->DeleteLocalRef (env, dir);
  312. (*env)->DeleteLocalRef (env, context_class);
  313. (*env)->DeleteLocalRef (env, file_class);
  314. return FALSE;
  315. }
  316. *cache_dir = abs_path ? g_strdup (abs_path_str) : NULL;
  317. (*env)->ReleaseStringUTFChars (env, abs_path, abs_path_str);
  318. (*env)->DeleteLocalRef (env, abs_path);
  319. (*env)->DeleteLocalRef (env, dir);
  320. }
  321. dir = (*env)->CallObjectMethod (env, context, get_files_dir_id);
  322. if ((*env)->ExceptionCheck (env)) {
  323. (*env)->ExceptionDescribe (env);
  324. (*env)->ExceptionClear (env);
  325. (*env)->DeleteLocalRef (env, context_class);
  326. (*env)->DeleteLocalRef (env, file_class);
  327. return FALSE;
  328. }
  329. if (dir) {
  330. abs_path = (*env)->CallObjectMethod (env, dir, get_absolute_path_id);
  331. if ((*env)->ExceptionCheck (env)) {
  332. (*env)->ExceptionDescribe (env);
  333. (*env)->ExceptionClear (env);
  334. (*env)->DeleteLocalRef (env, dir);
  335. (*env)->DeleteLocalRef (env, context_class);
  336. (*env)->DeleteLocalRef (env, file_class);
  337. return FALSE;
  338. }
  339. abs_path_str = (*env)->GetStringUTFChars (env, abs_path, NULL);
  340. if ((*env)->ExceptionCheck (env)) {
  341. (*env)->ExceptionDescribe (env);
  342. (*env)->ExceptionClear (env);
  343. (*env)->DeleteLocalRef (env, abs_path);
  344. (*env)->DeleteLocalRef (env, dir);
  345. (*env)->DeleteLocalRef (env, context_class);
  346. (*env)->DeleteLocalRef (env, file_class);
  347. return FALSE;
  348. }
  349. *files_dir = files_dir ? g_strdup (abs_path_str) : NULL;
  350. (*env)->ReleaseStringUTFChars (env, abs_path, abs_path_str);
  351. (*env)->DeleteLocalRef (env, abs_path);
  352. (*env)->DeleteLocalRef (env, dir);
  353. }
  354. (*env)->DeleteLocalRef (env, file_class);
  355. (*env)->DeleteLocalRef (env, context_class);
  356. return TRUE;
  357. }
  358. jobject
  359. gst_android_get_application_context (void)
  360. {
  361. return _context;
  362. }
  363. jobject
  364. gst_android_get_application_class_loader (void)
  365. {
  366. return _class_loader;
  367. }
  368. JavaVM *
  369. gst_android_get_java_vm (void)
  370. {
  371. return _java_vm;
  372. }
  373. static gboolean
  374. init (JNIEnv *env, jobject context)
  375. {
  376. jclass context_cls = NULL;
  377. jmethodID get_class_loader_id = 0;
  378. jobject class_loader = NULL;
  379. context_cls = (*env)->GetObjectClass (env, context);
  380. if (!context_cls) {
  381. return FALSE;
  382. }
  383. get_class_loader_id = (*env)->GetMethodID (env, context_cls,
  384. "getClassLoader", "()Ljava/lang/ClassLoader;");
  385. if ((*env)->ExceptionCheck (env)) {
  386. (*env)->ExceptionDescribe (env);
  387. (*env)->ExceptionClear (env);
  388. return FALSE;
  389. }
  390. class_loader = (*env)->CallObjectMethod (env, context, get_class_loader_id);
  391. if ((*env)->ExceptionCheck (env)) {
  392. (*env)->ExceptionDescribe (env);
  393. (*env)->ExceptionClear (env);
  394. return FALSE;
  395. }
  396. if (_context) {
  397. (*env)->DeleteGlobalRef (env, _context);
  398. }
  399. _context = (*env)->NewGlobalRef (env, context);
  400. if (_class_loader) {
  401. (*env)->DeleteGlobalRef (env, _class_loader);
  402. }
  403. _class_loader = (*env)->NewGlobalRef (env, class_loader);
  404. return TRUE;
  405. }
  406. void
  407. gst_android_init (JNIEnv * env, jobject context)
  408. {
  409. gchar *cache_dir;
  410. gchar *files_dir;
  411. gchar *registry;
  412. GError *error = NULL;
  413. if (!init (env, context)) {
  414. __android_log_print (ANDROID_LOG_INFO, "GStreamer",
  415. "GStreamer failed to initialize");
  416. }
  417. if (gst_is_initialized ()) {
  418. __android_log_print (ANDROID_LOG_INFO, "GStreamer",
  419. "GStreamer already initialized");
  420. return;
  421. }
  422. if (!get_application_dirs (env, context, &cache_dir, &files_dir)) {
  423. __android_log_print (ANDROID_LOG_ERROR, "GStreamer",
  424. "Failed to get application dirs");
  425. }
  426. if (cache_dir) {
  427. g_setenv ("TMP", cache_dir, TRUE);
  428. g_setenv ("TEMP", cache_dir, TRUE);
  429. g_setenv ("TMPDIR", cache_dir, TRUE);
  430. g_setenv ("XDG_RUNTIME_DIR", cache_dir, TRUE);
  431. g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE);
  432. registry = g_build_filename (cache_dir, "registry.bin", NULL);
  433. g_setenv ("GST_REGISTRY", registry, TRUE);
  434. g_free (registry);
  435. g_setenv ("GST_REGISTRY_REUSE_PLUGIN_SCANNER", "no", TRUE);
  436. /* TODO: Should probably also set GST_PLUGIN_SCANNER and GST_PLUGIN_SYSTEM_PATH */
  437. }
  438. if (files_dir) {
  439. gchar *fontconfig, *certs;
  440. g_setenv ("HOME", files_dir, TRUE);
  441. g_setenv ("XDG_DATA_DIRS", files_dir, TRUE);
  442. g_setenv ("XDG_CONFIG_DIRS", files_dir, TRUE);
  443. g_setenv ("XDG_CONFIG_HOME", files_dir, TRUE);
  444. g_setenv ("XDG_DATA_HOME", files_dir, TRUE);
  445. fontconfig = g_build_filename (files_dir, "fontconfig", NULL);
  446. g_setenv ("FONTCONFIG_PATH", fontconfig, TRUE);
  447. g_free (fontconfig);
  448. certs = g_build_filename (files_dir, "ssl", "certs", "ca-certificates.crt", NULL);
  449. g_setenv ("CA_CERTIFICATES", certs, TRUE);
  450. g_free (certs);
  451. }
  452. g_free (cache_dir);
  453. g_free (files_dir);
  454. /* Set GLib print handlers */
  455. g_set_print_handler (glib_print_handler);
  456. g_set_printerr_handler (glib_printerr_handler);
  457. g_log_set_default_handler (glib_log_handler, NULL);
  458. /* Disable this for releases if performance is important
  459. * or increase the threshold to get more information */
  460. gst_debug_set_active (TRUE);
  461. gst_debug_set_default_threshold (GST_LEVEL_WARNING);
  462. gst_debug_remove_log_function (gst_debug_log_default);
  463. gst_debug_add_log_function ((GstLogFunction) gst_debug_logcat, NULL, NULL);
  464. /* get time we started for debugging messages */
  465. _priv_gst_info_start_time = gst_util_get_timestamp ();
  466. if (!gst_init_check (NULL, NULL, &error)) {
  467. gchar *message = g_strdup_printf ("GStreamer initialization failed: %s",
  468. error && error->message ? error->message : "(no message)");
  469. jclass exception_class = (*env)->FindClass (env, "java/lang/Exception");
  470. __android_log_print (ANDROID_LOG_ERROR, "GStreamer", "%s", message);
  471. (*env)->ThrowNew (env, exception_class, message);
  472. g_free (message);
  473. return;
  474. }
  475. gst_android_load_gio_modules ();
  476. __android_log_print (ANDROID_LOG_INFO, "GStreamer",
  477. "GStreamer initialization complete");
  478. }
  479. static void
  480. gst_android_init_jni (JNIEnv * env, jobject gstreamer, jobject context)
  481. {
  482. gst_android_init (env, context);
  483. }
  484. static JNINativeMethod native_methods[] = {
  485. {"nativeInit", "(Landroid/content/Context;)V", (void *) gst_android_init_jni}
  486. };
  487. jint
  488. JNI_OnLoad (JavaVM * vm, void * reserved)
  489. {
  490. JNIEnv *env = NULL;
  491. GModule *module;
  492. if ((*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_4) != JNI_OK) {
  493. __android_log_print (ANDROID_LOG_ERROR, "GStreamer",
  494. "Could not retrieve JNIEnv");
  495. return 0;
  496. }
  497. jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/GStreamer");
  498. if (!klass) {
  499. __android_log_print (ANDROID_LOG_ERROR, "GStreamer",
  500. "Could not retrieve class org.freedesktop.gstreamer.GStreamer");
  501. return 0;
  502. }
  503. if ((*env)->RegisterNatives (env, klass, native_methods,
  504. G_N_ELEMENTS (native_methods))) {
  505. __android_log_print (ANDROID_LOG_ERROR, "GStreamer",
  506. "Could not register native methods for org.freedesktop.gstreamer.GStreamer");
  507. return 0;
  508. }
  509. /* Remember Java VM */
  510. _java_vm = vm;
  511. /* Tell the androidmedia plugin about the Java VM if we can */
  512. module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
  513. if (module) {
  514. void (*set_java_vm) (JavaVM *) = NULL;
  515. if (g_module_symbol (module, "gst_amc_jni_set_java_vm",
  516. (gpointer *) & set_java_vm) && set_java_vm) {
  517. set_java_vm (vm);
  518. }
  519. g_module_close (module);
  520. }
  521. return JNI_VERSION_1_4;
  522. }
  523. void
  524. JNI_OnUnload (JavaVM * vm, void * reversed)
  525. {
  526. JNIEnv *env = NULL;
  527. if ((*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_4) != JNI_OK) {
  528. __android_log_print (ANDROID_LOG_ERROR, "GStreamer",
  529. "Could not retrieve JNIEnv");
  530. return;
  531. }
  532. if (_context) {
  533. (*env)->DeleteGlobalRef (env, _context);
  534. _context = NULL;
  535. }
  536. if (_class_loader) {
  537. (*env)->DeleteGlobalRef (env, _class_loader);
  538. _class_loader = NULL;
  539. }
  540. _java_vm = NULL;
  541. }