PageRenderTime 161ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Main/GStreamer/Source/gst-plugins-base/ext/gio/gstgiobasesrc.c

http://ossbuild.googlecode.com/
C | 447 lines | 328 code | 85 blank | 34 comment | 54 complexity | 0b06e12e83f07c9401e24aa06d1485e5 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, GPL-2.0, AGPL-1.0, LGPL-2.1, LGPL-2.0, GPL-3.0, LGPL-3.0, CC-BY-SA-3.0
  1. /* GStreamer
  2. *
  3. * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
  4. * Copyright (C) 2007-2009 Sebastian Dr??ge <sebastian.droege@collabora.co.uk>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  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. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public
  17. * License along with this library; if not, write to the
  18. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include "gstgiobasesrc.h"
  25. #include <gst/base/gsttypefindhelper.h>
  26. GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug);
  27. #define GST_CAT_DEFAULT gst_gio_base_src_debug
  28. static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
  29. GST_PAD_SRC,
  30. GST_PAD_ALWAYS,
  31. GST_STATIC_CAPS_ANY);
  32. GST_BOILERPLATE (GstGioBaseSrc, gst_gio_base_src, GstBaseSrc,
  33. GST_TYPE_BASE_SRC);
  34. static void gst_gio_base_src_finalize (GObject * object);
  35. static gboolean gst_gio_base_src_start (GstBaseSrc * base_src);
  36. static gboolean gst_gio_base_src_stop (GstBaseSrc * base_src);
  37. static gboolean gst_gio_base_src_get_size (GstBaseSrc * base_src,
  38. guint64 * size);
  39. static gboolean gst_gio_base_src_is_seekable (GstBaseSrc * base_src);
  40. static gboolean gst_gio_base_src_unlock (GstBaseSrc * base_src);
  41. static gboolean gst_gio_base_src_unlock_stop (GstBaseSrc * base_src);
  42. static gboolean gst_gio_base_src_check_get_range (GstBaseSrc * base_src);
  43. static GstFlowReturn gst_gio_base_src_create (GstBaseSrc * base_src,
  44. guint64 offset, guint size, GstBuffer ** buf);
  45. static gboolean gst_gio_base_src_query (GstBaseSrc * base_src,
  46. GstQuery * query);
  47. static void
  48. gst_gio_base_src_base_init (gpointer gclass)
  49. {
  50. GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
  51. GST_DEBUG_CATEGORY_INIT (gst_gio_base_src_debug, "gio_base_src", 0,
  52. "GIO base source");
  53. gst_element_class_add_pad_template (element_class,
  54. gst_static_pad_template_get (&src_factory));
  55. }
  56. static void
  57. gst_gio_base_src_class_init (GstGioBaseSrcClass * klass)
  58. {
  59. GObjectClass *gobject_class = (GObjectClass *) klass;
  60. GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass;
  61. gobject_class->finalize = gst_gio_base_src_finalize;
  62. gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_src_start);
  63. gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_src_stop);
  64. gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gio_base_src_get_size);
  65. gstbasesrc_class->is_seekable =
  66. GST_DEBUG_FUNCPTR (gst_gio_base_src_is_seekable);
  67. gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock);
  68. gstbasesrc_class->unlock_stop =
  69. GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock_stop);
  70. gstbasesrc_class->check_get_range =
  71. GST_DEBUG_FUNCPTR (gst_gio_base_src_check_get_range);
  72. gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gio_base_src_create);
  73. gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_gio_base_src_query);
  74. }
  75. static void
  76. gst_gio_base_src_init (GstGioBaseSrc * src, GstGioBaseSrcClass * gclass)
  77. {
  78. src->cancel = g_cancellable_new ();
  79. }
  80. static void
  81. gst_gio_base_src_finalize (GObject * object)
  82. {
  83. GstGioBaseSrc *src = GST_GIO_BASE_SRC (object);
  84. if (src->cancel) {
  85. g_object_unref (src->cancel);
  86. src->cancel = NULL;
  87. }
  88. if (src->stream) {
  89. g_object_unref (src->stream);
  90. src->stream = NULL;
  91. }
  92. if (src->cache) {
  93. gst_buffer_unref (src->cache);
  94. src->cache = NULL;
  95. }
  96. GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
  97. }
  98. static gboolean
  99. gst_gio_base_src_start (GstBaseSrc * base_src)
  100. {
  101. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  102. GstGioBaseSrcClass *gbsrc_class = GST_GIO_BASE_SRC_GET_CLASS (src);
  103. src->position = 0;
  104. /* FIXME: This will likely block */
  105. src->stream = gbsrc_class->get_stream (src);
  106. if (G_UNLIKELY (!G_IS_INPUT_STREAM (src->stream))) {
  107. GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
  108. ("No input stream provided by subclass"));
  109. return FALSE;
  110. } else if (G_UNLIKELY (g_input_stream_is_closed (src->stream))) {
  111. GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL),
  112. ("Input stream is already closed"));
  113. return FALSE;
  114. }
  115. if (G_IS_SEEKABLE (src->stream))
  116. src->position = g_seekable_tell (G_SEEKABLE (src->stream));
  117. GST_DEBUG_OBJECT (src, "started source");
  118. return TRUE;
  119. }
  120. static gboolean
  121. gst_gio_base_src_stop (GstBaseSrc * base_src)
  122. {
  123. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  124. GstGioBaseSrcClass *klass = GST_GIO_BASE_SRC_GET_CLASS (src);
  125. gboolean success;
  126. GError *err = NULL;
  127. if (klass->close_on_stop && G_IS_INPUT_STREAM (src->stream)) {
  128. GST_DEBUG_OBJECT (src, "closing stream");
  129. /* FIXME: can block but unfortunately we can't use async operations
  130. * here because they require a running main loop */
  131. success = g_input_stream_close (src->stream, src->cancel, &err);
  132. if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
  133. GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
  134. ("g_input_stream_close failed: %s", err->message));
  135. g_clear_error (&err);
  136. } else if (!success) {
  137. GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
  138. ("g_input_stream_close failed"));
  139. } else {
  140. GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
  141. }
  142. g_object_unref (src->stream);
  143. src->stream = NULL;
  144. } else {
  145. g_object_unref (src->stream);
  146. src->stream = NULL;
  147. }
  148. return TRUE;
  149. }
  150. static gboolean
  151. gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
  152. {
  153. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  154. if (G_IS_FILE_INPUT_STREAM (src->stream)) {
  155. GFileInfo *info;
  156. GError *err = NULL;
  157. info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream),
  158. G_FILE_ATTRIBUTE_STANDARD_SIZE, src->cancel, &err);
  159. if (info != NULL) {
  160. *size = g_file_info_get_size (info);
  161. g_object_unref (info);
  162. GST_DEBUG_OBJECT (src, "found size: %" G_GUINT64_FORMAT, *size);
  163. return TRUE;
  164. }
  165. if (!gst_gio_error (src, "g_file_input_stream_query_info", &err, NULL)) {
  166. if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
  167. GST_DEBUG_OBJECT (src, "size information not available");
  168. else
  169. GST_WARNING_OBJECT (src, "size information retrieval failed: %s",
  170. err->message);
  171. g_clear_error (&err);
  172. }
  173. }
  174. if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) {
  175. goffset old;
  176. goffset stream_size;
  177. gboolean ret;
  178. GSeekable *seekable = G_SEEKABLE (src->stream);
  179. GError *err = NULL;
  180. old = g_seekable_tell (seekable);
  181. ret = g_seekable_seek (seekable, 0, G_SEEK_END, src->cancel, &err);
  182. if (!ret) {
  183. if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
  184. if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
  185. GST_DEBUG_OBJECT (src,
  186. "Seeking to the end of stream is not supported");
  187. else
  188. GST_WARNING_OBJECT (src, "Seeking to end of stream failed: %s",
  189. err->message);
  190. g_clear_error (&err);
  191. } else {
  192. GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
  193. }
  194. return FALSE;
  195. }
  196. stream_size = g_seekable_tell (seekable);
  197. ret = g_seekable_seek (seekable, old, G_SEEK_SET, src->cancel, &err);
  198. if (!ret) {
  199. if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
  200. if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
  201. GST_ERROR_OBJECT (src, "Seeking to the old position not supported");
  202. else
  203. GST_ERROR_OBJECT (src, "Seeking to the old position failed: %s",
  204. err->message);
  205. g_clear_error (&err);
  206. } else {
  207. GST_ERROR_OBJECT (src, "Seeking to the old position faile");
  208. }
  209. return FALSE;
  210. }
  211. if (stream_size >= 0) {
  212. *size = stream_size;
  213. return TRUE;
  214. }
  215. }
  216. return FALSE;
  217. }
  218. static gboolean
  219. gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
  220. {
  221. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  222. gboolean seekable;
  223. seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
  224. GST_DEBUG_OBJECT (src, "can seek: %d", seekable);
  225. return seekable;
  226. }
  227. static gboolean
  228. gst_gio_base_src_unlock (GstBaseSrc * base_src)
  229. {
  230. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  231. GST_LOG_OBJECT (src, "triggering cancellation");
  232. g_cancellable_cancel (src->cancel);
  233. return TRUE;
  234. }
  235. static gboolean
  236. gst_gio_base_src_unlock_stop (GstBaseSrc * base_src)
  237. {
  238. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  239. GST_LOG_OBJECT (src, "resetting cancellable");
  240. g_cancellable_reset (src->cancel);
  241. return TRUE;
  242. }
  243. static gboolean
  244. gst_gio_base_src_check_get_range (GstBaseSrc * base_src)
  245. {
  246. return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS,
  247. check_get_range, (base_src), FALSE);
  248. }
  249. static GstFlowReturn
  250. gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size,
  251. GstBuffer ** buf_return)
  252. {
  253. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  254. GstBuffer *buf;
  255. GstFlowReturn ret = GST_FLOW_OK;
  256. g_return_val_if_fail (G_IS_INPUT_STREAM (src->stream), GST_FLOW_ERROR);
  257. /* If we have the requested part in our cache take a subbuffer of that,
  258. * otherwise fill the cache again with at least 4096 bytes from the
  259. * requested offset and return a subbuffer of that.
  260. *
  261. * We need caching because every read/seek operation will need to go
  262. * over DBus if our backend is GVfs and this is painfully slow. */
  263. if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) &&
  264. offset + size <= GST_BUFFER_OFFSET_END (src->cache)) {
  265. GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %"
  266. G_GUINT64_FORMAT " length %u", offset, size);
  267. buf = gst_buffer_create_sub (src->cache,
  268. offset - GST_BUFFER_OFFSET (src->cache), size);
  269. GST_BUFFER_OFFSET (buf) = offset;
  270. GST_BUFFER_OFFSET_END (buf) = offset + size;
  271. GST_BUFFER_SIZE (buf) = size;
  272. } else {
  273. guint cachesize = MAX (4096, size);
  274. gssize read, res;
  275. gboolean success, eos;
  276. GError *err = NULL;
  277. if (src->cache) {
  278. gst_buffer_unref (src->cache);
  279. src->cache = NULL;
  280. }
  281. if (G_UNLIKELY (offset != src->position)) {
  282. if (!GST_GIO_STREAM_IS_SEEKABLE (src->stream))
  283. return GST_FLOW_NOT_SUPPORTED;
  284. GST_DEBUG_OBJECT (src, "Seeking to position %" G_GUINT64_FORMAT, offset);
  285. ret = gst_gio_seek (src, G_SEEKABLE (src->stream), offset, src->cancel);
  286. if (ret == GST_FLOW_OK)
  287. src->position = offset;
  288. else
  289. return ret;
  290. }
  291. src->cache = gst_buffer_try_new_and_alloc (cachesize);
  292. if (G_UNLIKELY (src->cache == NULL)) {
  293. GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", cachesize);
  294. return GST_FLOW_ERROR;
  295. }
  296. GST_LOG_OBJECT (src, "Reading %u bytes from offset %" G_GUINT64_FORMAT,
  297. cachesize, offset);
  298. /* GIO sometimes gives less bytes than requested although
  299. * it's not at the end of file. SMB for example only
  300. * supports reads up to 64k. So we loop here until we get at
  301. * at least the requested amount of bytes or a read returns
  302. * nothing. */
  303. read = 0;
  304. while (size - read > 0 && (res =
  305. g_input_stream_read (G_INPUT_STREAM (src->stream),
  306. GST_BUFFER_DATA (src->cache) + read, cachesize - read,
  307. src->cancel, &err)) > 0) {
  308. read += res;
  309. }
  310. success = (read >= 0);
  311. eos = (cachesize > 0 && read == 0);
  312. if (!success && !gst_gio_error (src, "g_input_stream_read", &err, &ret)) {
  313. GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
  314. ("Could not read from stream: %s", err->message));
  315. g_clear_error (&err);
  316. }
  317. if (success && !eos) {
  318. src->position += read;
  319. GST_BUFFER_SIZE (src->cache) = read;
  320. GST_BUFFER_OFFSET (src->cache) = offset;
  321. GST_BUFFER_OFFSET_END (src->cache) = offset + read;
  322. GST_DEBUG_OBJECT (src, "Read successful");
  323. GST_DEBUG_OBJECT (src, "Creating subbuffer from new "
  324. "cached buffer: offset %" G_GUINT64_FORMAT " length %u", offset,
  325. size);
  326. buf = gst_buffer_create_sub (src->cache, 0, MIN (size, read));
  327. GST_BUFFER_OFFSET (buf) = offset;
  328. GST_BUFFER_OFFSET_END (buf) = offset + MIN (size, read);
  329. GST_BUFFER_SIZE (buf) = MIN (size, read);
  330. } else {
  331. GST_DEBUG_OBJECT (src, "Read not successful");
  332. gst_buffer_unref (src->cache);
  333. src->cache = NULL;
  334. buf = NULL;
  335. }
  336. if (eos)
  337. ret = GST_FLOW_UNEXPECTED;
  338. }
  339. *buf_return = buf;
  340. return ret;
  341. }
  342. static gboolean
  343. gst_gio_base_src_query (GstBaseSrc * base_src, GstQuery * query)
  344. {
  345. gboolean ret = FALSE;
  346. GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
  347. switch (GST_QUERY_TYPE (query)) {
  348. case GST_QUERY_URI:
  349. if (GST_IS_URI_HANDLER (src)) {
  350. const gchar *uri = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
  351. gst_query_set_uri (query, uri);
  352. ret = TRUE;
  353. }
  354. break;
  355. default:
  356. ret = FALSE;
  357. break;
  358. }
  359. if (!ret)
  360. ret = GST_BASE_SRC_CLASS (parent_class)->query (base_src, query);
  361. return ret;
  362. }