From: Jonathan Matthew Date: Sat, 3 Aug 2013 15:01:25 +0000 (+1000) Subject: gio: make better use of the cached buffer X-Git-Tag: 1.19.3~511^2~5113 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc1de5ae9403761155e24c4fe6f88cd788e92400;p=platform%2Fupstream%2Fgstreamer.git gio: make better use of the cached buffer When playing mp3 files from a smb server, we get 64k read requests that mostly overlap. Without using the cache to partially satisfy these, we send these requests straight to the server, resulting in a lot more network traffic than necessary. https://bugzilla.gnome.org/show_bug.cgi?id=705415 --- diff --git a/gst/gio/gstgiobasesrc.c b/gst/gio/gstgiobasesrc.c index 0170664..afadf38 100644 --- a/gst/gio/gstgiobasesrc.c +++ b/gst/gio/gstgiobasesrc.c @@ -320,50 +320,75 @@ gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size, } else { guint cachesize = MAX (4096, size); GstMapInfo map; - gssize read, res; + gssize read, streamread, res; + guint64 readoffset; gboolean success, eos; GError *err = NULL; + GstBuffer *newbuffer; + GstMemory *mem; + + newbuffer = gst_buffer_new (); + + /* copy any overlapping data from the cached buffer */ + if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) && + offset <= GST_BUFFER_OFFSET_END (src->cache)) { + read = GST_BUFFER_OFFSET_END (src->cache) - offset; + GST_LOG_OBJECT (src, + "Copying %" G_GUINT64_FORMAT " bytes from cached buffer at %" + G_GUINT64_FORMAT, read, offset - GST_BUFFER_OFFSET (src->cache)); + gst_buffer_copy_into (newbuffer, src->cache, GST_BUFFER_COPY_MEMORY, + offset - GST_BUFFER_OFFSET (src->cache), read); + } else { + read = 0; + } - if (src->cache) { + if (src->cache) gst_buffer_unref (src->cache); - src->cache = NULL; - } + src->cache = newbuffer; - if (G_UNLIKELY (offset != src->position)) { + readoffset = offset + read; + GST_LOG_OBJECT (src, + "Reading %u bytes from offset %" G_GUINT64_FORMAT, cachesize, + readoffset); + + if (G_UNLIKELY (readoffset != src->position)) { if (!GST_GIO_STREAM_IS_SEEKABLE (src->stream)) return GST_FLOW_NOT_SUPPORTED; - GST_DEBUG_OBJECT (src, "Seeking to position %" G_GUINT64_FORMAT, offset); - ret = gst_gio_seek (src, G_SEEKABLE (src->stream), offset, src->cancel); + GST_DEBUG_OBJECT (src, "Seeking to position %" G_GUINT64_FORMAT, + readoffset); + ret = + gst_gio_seek (src, G_SEEKABLE (src->stream), readoffset, src->cancel); if (ret == GST_FLOW_OK) - src->position = offset; + src->position = readoffset; else return ret; } - src->cache = gst_buffer_new_and_alloc (cachesize); - if (G_UNLIKELY (src->cache == NULL)) { - GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", cachesize); - return GST_FLOW_ERROR; - } - - GST_LOG_OBJECT (src, "Reading %u bytes from offset %" G_GUINT64_FORMAT, - cachesize, offset); - /* GIO sometimes gives less bytes than requested although * it's not at the end of file. SMB for example only * supports reads up to 64k. So we loop here until we get at * at least the requested amount of bytes or a read returns * nothing. */ - gst_buffer_map (src->cache, &map, GST_MAP_WRITE); - read = 0; + mem = gst_allocator_alloc (NULL, cachesize, NULL); + if (mem == NULL) { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", cachesize); + return GST_FLOW_ERROR; + } + + gst_memory_map (mem, &map, GST_MAP_WRITE); + streamread = 0; while (size - read > 0 && (res = g_input_stream_read (G_INPUT_STREAM (src->stream), - map.data + read, cachesize - read, src->cancel, &err)) > 0) { + map.data + streamread, cachesize - streamread, src->cancel, + &err)) > 0) { read += res; + streamread += res; + src->position += res; } - gst_buffer_unmap (src->cache, &map); + gst_memory_unmap (mem, &map); + gst_buffer_append_memory (src->cache, mem); success = (read >= 0); eos = (cachesize > 0 && read == 0); @@ -375,8 +400,6 @@ gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size, } if (success && !eos) { - src->position += read; - GST_BUFFER_OFFSET (src->cache) = offset; GST_BUFFER_OFFSET_END (src->cache) = offset + read;