--- libmms-0.3.orig/debian/rules +++ libmms-0.3/debian/rules @@ -0,0 +1,83 @@ +#!/usr/bin/make -f + +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + +confflags += \ + --build=$(DEB_BUILD_GNU_TYPE) \ + --prefix=/usr \ + --mandir=\$${prefix}/share/man \ + --infodir=\$${prefix}/share/info + +ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) +confflags += --host=$(DEB_HOST_GNU_TYPE) +endif + +PATCH_DIR := debian/patches + +CFLAGS += -Wall -g $(if $(findstring noopt,$(DEB_BUILD_OPTIONS)),-O0,-O2) + +config.status: configure patch-stamp + dh_testdir + CFLAGS="$(CFLAGS)" ./configure $(confflags) + +patch-stamp: + dh_testdir + # apply patches + QUILT_PATCHES=$(PATCH_DIR) quilt --quiltrc /dev/null push -a || test $$? = 2 + # backup the original (potentially patched) files to restore them in + # the clean target + -test -r config.sub && cp config.sub config.sub.orig + -test -r config.guess && cp config.guess config.guess.orig + -test -r /usr/share/misc/config.sub && \ + cp -f /usr/share/misc/config.sub config.sub + -test -r /usr/share/misc/config.guess && \ + cp -f /usr/share/misc/config.guess config.guess + touch $@ + +build: build-stamp +build-stamp: config.status + dh_testdir + $(MAKE) + touch build-stamp + +clean: + dh_testdir + dh_testroot + -$(MAKE) distclean + # restore files from backup (before unpatching) + -test -r config.sub.orig && mv -f config.sub.orig config.sub + -test -r config.guess.orig && mv -f config.guess.orig config.guess + # unapply patches, if any + QUILT_PATCHES=$(PATCH_DIR) quilt --quiltrc /dev/null pop -a -R || test $$? = 2 + rm -rf .pc + rm -f patch-stamp + rm -f build-stamp + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp + +binary-indep: build install + +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_install --sourcedir=debian/tmp + dh_strip + dh_compress + dh_fixperms + dh_makeshlibs -V 'libmms0 (>= 0.3-4)' + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install --- libmms-0.3.orig/debian/copyright +++ libmms-0.3/debian/copyright @@ -0,0 +1,45 @@ +This package was debianized by Søren Hansen on +Wed, 14 Sep 2005 19:44:38 +0200. + +It was downloaded from Ubuntu and uploaded to Debian with some modifications +by Loic Minier on Wed, 28 Sep 2005 21:56:25 +0200. + +It was downloaded from . + + +Current developers: + Maciej Katafiasz (Mathrick) + SĂren Hansen (shawarma) +Original implementation: + Major MMS +Other authors: + the Xine project +Enhanced and maintained by Xine project at http://xine.sf.net + +License: + + (Some of the upstream sources have Xine headers and are copyrighted under + the GPL, and some newer files have LGPL headers. However, this snipsets + were relicensed by their authors as claimed at: + + + ) + + + This package is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU Lesser General +Public License can be found in `/usr/share/common-licenses/LGPL'. + --- libmms-0.3.orig/debian/changelog +++ libmms-0.3/debian/changelog @@ -0,0 +1,145 @@ +libmms (0.3-5ubuntu1) gutsy; urgency=low + + * Merge from Debian unstable. Remaining Ubuntu changes: + - Fix handle of mms URIs + - Maintainer field + + -- Luca Falavigna Mon, 20 Aug 2007 11:32:45 +0200 + +libmms (0.3-5) unstable; urgency=low + + * Minor tweak in rules. + * Use ${binary:Version} instead of ${Source-Version}. + * New patch, 60_first-packet, fixes discarding of first package; taken from + SF #1747740; thanks Sven Arvidsson; closes: #438524. + + -- Loic Minier Fri, 17 Aug 2007 21:07:05 +0200 + +libmms (0.3-4ubuntu1) gutsy; urgency=low + + [Gabriel Velo] + * Fix handle of mms URIs (LP: #79401 LP: #101876 LP: #119641) + + [Luca Falavigna] + * Update Maintainer field in debian/control + + -- Luca Falavigna Tue, 3 Jul 2007 16:07:30 +0200 + +libmms (0.3-4) unstable; urgency=low + + * New patch, 20_seeking-support, adds API permitting seeking of mms streams; + by Anon Sricharoenchai; bump shlibs to >= 0.3-4; closes: #387267. + * Wrap build-deps and deps. + + -- Loic Minier Mon, 14 May 2007 13:41:10 +0200 + +libmms (0.3-3) unstable; urgency=low + + * Set Maintainer to pkg-multimedia-maintainers and list myself as Uploader. + * Don't pass --host to configure if DEB_BUILD_GNU_TYPE equals + DEB_HOST_GNU_TYPE. + * Misc cleanups. + * Bump up Debhelper compatibility level to 5. + - Drop usr/share/pkgconfig from libmms-dev.install. + * Stop shipping /usr/lib/libmms.la in libmms-dev; no rdep. + * New patch, 11_fix-stream-id-crash, fixes support of streams with id above + 23; see GNOME #347151 and SF bug #1521441; thanks Sven Arvidsson; + closes: #416430. + + -- Loic Minier Fri, 30 Mar 2007 14:18:38 +0200 + +libmms (0.3-2) unstable; urgency=low + + * Hook a quilt patch system in the build; build-depend on quilt. + * New patch, 10_asf-header-size, doubles the size of the ASF header to + permit decoding of some ASF streams and fixes a couple of debug messages; + thanks Sjoerd Simons; closes: #412851. + + -- Loic Minier Wed, 28 Feb 2007 17:52:13 +0100 + +libmms (0.3-1) unstable; urgency=low + + * New upstream release; closes: #392233. + - Merges all Debian changes. + + -- Loic Minier Wed, 11 Oct 2006 11:17:00 +0200 + +libmms (0.2-7) unstable; urgency=high + + * SECURITY: CVE-2006-2200: buffer overflows in mms / mmsh parsers: + additional fixes thanks to Matthias Hopf: + - even more checks on "packet_length" / "packet_len" in src/mms.c and + src/mmsh.c + - fix memset() calls in the two string_utf16() implementations in + src/mms.c to clear all bytes in dest, "len" is the UTF-16 length of the + string in wide chars, so the memset should use "2 * len". + + -- Loic Minier Tue, 11 Jul 2006 13:11:11 +0200 + +libmms (0.2-6) unstable; urgency=low + + * SECURITY: CVE-2006-2200: buffer overflows in mms / mmsh parsers: fix an + error that crept in the previous fix and use start < end instead of start + > end in src/mms.c and src/mmsh.c, thanks Martin Pitt. + + -- Loic Minier Wed, 5 Jul 2006 18:13:36 +0200 + +libmms (0.2-5) unstable; urgency=high + + * SECURITY: CVE-2006-2200: buffer overflows in mms / mmsh parsers: apply + memset() range fixes adapted from #374577 by Wesley J. Landaker. + + -- Loic Minier Thu, 22 Jun 2006 20:53:44 +0200 + +libmms (0.2-4) unstable; urgency=low + + * Apply patch from Wesley J. Landaker for the headers to be usable from C++. + (Closes: #362662) + [src/mms.h, src/mmsh.h, src/mmsio.h] + + -- Loic Minier Mon, 5 Jun 2006 16:33:29 +0200 + +libmms (0.2-3) unstable; urgency=low + + * Add a libglib2.0-dev dependency to libmms-dev. + [debian/control] + * Bump up Standards Version to 3.7.2. + [debian/control] + * Drop references to PKG_CFLAGS and PKG_LIBS and use GLIB_LIBS instead as it + seems these were not properly renamed and relibtoolize. (Closes: #362666) + [src/Makefile.am, libmms-0.2/Makefile.in, libmms-0.2/src/Makefile.in, + libmms-0.2/pkgconfig/Makefile.in] + + -- Loic Minier Mon, 22 May 2006 18:11:10 +0200 + +libmms (0.2-2) unstable; urgency=low + + * Fix shlibs to use parenthesis. + [debian/rules] + + -- Loic Minier Mon, 16 Jan 2006 22:00:16 +0100 + +libmms (0.2-1) unstable; urgency=low + + * New upstream release. + - Bump shlibs to libmms0 >= 0.2. + [debian/rules] + + -- Loic Minier Mon, 16 Jan 2006 21:19:46 +0100 + +libmms (0.1-1) unstable; urgency=low + + * Initial upload for Debian based on the Ubuntu package in version + 0.1-0ubuntu1. (Closes: #330355) + * Clarify copyright status and license. [debian/copyright] + * Clean up package descriptions. [debian/control] + * Inherit CFLAGS. [debian/rules] + * Remove useless files. [debian/dirs, libmms0.dirs, libmms-dev.dirs] + + -- Loic Minier Thu, 29 Sep 2005 21:52:44 +0200 + +libmms (0.1-0ubuntu1) breezy; urgency=low + + * Initial release + + -- Søren Hansen Thu, 15 Sep 2005 16:56:05 +0200 --- libmms-0.3.orig/debian/libmms0.install +++ libmms-0.3/debian/libmms0.install @@ -0,0 +1 @@ +usr/lib/lib*.so.* --- libmms-0.3.orig/debian/control +++ libmms-0.3/debian/control @@ -0,0 +1,37 @@ +Source: libmms +Priority: optional +Maintainer: Ubuntu MOTU Developers +XSBC-Original-Maintainer: Debian Multimedia Packages Maintainers +Uploaders: Loic Minier +Build-Depends: debhelper (>= 5), + autotools-dev, + libglib2.0-dev, + quilt +Standards-Version: 3.7.2 +Section: libs + +Package: libmms-dev +Section: libdevel +Architecture: any +Depends: libmms0 (= ${binary:Version}), + libglib2.0-dev +Description: MMS stream protocol library - development files + LibMMS is a common library for parsing mms:// and mmsh:// type network + streams. These are commonly used to stream Windows Media Video content + over the web. LibMMS itself is only for receiving MMS stream, it + doesn't handle sending at all. + . + This package holds the development files. + +Package: libmms0 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends} +Description: MMS stream protocol library - shared library + LibMMS is a common library for parsing mms:// and mmsh:// type network + streams. These are commonly used to stream Windows Media Video content + over the web. LibMMS itself is only for receiving MMS stream, it + doesn't handle sending at all. + . + This package holds the shared library. --- libmms-0.3.orig/debian/compat +++ libmms-0.3/debian/compat @@ -0,0 +1 @@ +5 --- libmms-0.3.orig/debian/libmms-dev.install +++ libmms-0.3/debian/libmms-dev.install @@ -0,0 +1,4 @@ +usr/include +usr/lib/lib*.a +usr/lib/lib*.so +usr/lib/pkgconfig --- libmms-0.3.orig/debian/docs +++ libmms-0.3/debian/docs @@ -0,0 +1,2 @@ +README +TODO --- libmms-0.3.orig/debian/patches/60_first-packet.patch +++ libmms-0.3/debian/patches/60_first-packet.patch @@ -0,0 +1,13 @@ +diff -urp ../libmms-0.3.orig/src/mmsh.c ./src/mmsh.c +--- ../libmms-0.3.orig/src/mmsh.c 2007-08-17 16:42:22.000000000 +0200 ++++ ./src/mmsh.c 2007-08-17 16:43:19.000000000 +0200 +@@ -898,7 +898,8 @@ static int mmsh_connect_int (mms_io_t *i + if (!get_header(io, this)) + goto fail; + interp_header(io, this); +- ++ this->buf_size = this->packet_length; ++ + for (i = 0; i < this->num_stream_ids; i++) { + if ((this->stream_ids[i] != audio_stream) && + (this->stream_ids[i] != video_stream)) { --- libmms-0.3.orig/debian/patches/11_fix-stream-id-crash.patch +++ libmms-0.3/debian/patches/11_fix-stream-id-crash.patch @@ -0,0 +1,177 @@ +GNOME #347151; SF #1521441; fixes support of streams with id above 23 +http://sourceforge.net/tracker/index.php?func=detail&aid=1521441&group_id=101989&atid=630609 + +Index: libmms-0.3/src/mms.c +=================================================================== +--- libmms-0.3.orig/src/mms.c 2007-03-30 14:23:54.000000000 +0200 ++++ libmms-0.3/src/mms.c 2007-03-30 14:23:55.000000000 +0200 +@@ -106,6 +106,13 @@ + uint32_t packet_seq; + }; + ++typedef struct mms_stream_s mms_stream_t; ++struct mms_stream_s { ++ int stream_id; ++ int stream_type; ++ uint32_t bitrate; ++ uint32_t bitrate_pos; ++}; + + struct mms_s { + +@@ -140,15 +147,12 @@ + uint32_t asf_header_read; + int seq_num; + int num_stream_ids; +- int stream_ids[ASF_MAX_NUM_STREAMS]; +- int stream_types[ASF_MAX_NUM_STREAMS]; ++ mms_stream_t streams[ASF_MAX_NUM_STREAMS]; + off_t start_packet_seq; /* for live streams != 0, need to keep it around */ + int need_discont; /* whether we need to set start_packet_seq */ + uint32_t asf_packet_len; + uint64_t file_len; + char guid[37]; +- uint32_t bitrates[ASF_MAX_NUM_STREAMS]; +- uint32_t bitrates_pos[ASF_MAX_NUM_STREAMS]; + int bandwidth; + + int has_audio; +@@ -777,9 +781,9 @@ + lprintf ("stream object, stream id: %d, type: %d, encrypted: %d\n", + stream_id, type, encrypted); + +- if (this->num_stream_ids < ASF_MAX_NUM_STREAMS && stream_id < ASF_MAX_NUM_STREAMS) { +- this->stream_types[stream_id] = type; +- this->stream_ids[this->num_stream_ids] = stream_id; ++ if (this->num_stream_ids < ASF_MAX_NUM_STREAMS) { ++ this->streams[this->num_stream_ids].stream_type = type; ++ this->streams[this->num_stream_ids].stream_id = stream_id; + this->num_stream_ids++; + } else { + lprintf ("too many streams, skipping\n"); +@@ -797,12 +801,19 @@ + lprintf ("streams %d\n", streams); + + for(j = 0; j < streams; j++) { ++ int stream_index; + stream_id = LE_16(this->asf_header + i + 2 + j * 6); +- lprintf ("stream id %d\n", stream_id); +- this->bitrates[stream_id] = LE_32(this->asf_header + i + 4 + j * 6); +- this->bitrates_pos[stream_id] = i + 4 + j * 6; +- lprintf ("stream id %d, bitrate %d\n", stream_id, +- this->bitrates[stream_id]); ++ lprintf ("stream id %d\n", stream_id); ++ for(stream_index = 0; stream_index < this->num_stream_ids; stream_index++) { ++ if (this->streams[stream_index].stream_id == stream_id) ++ break; ++ } ++ if (stream_index < this->num_stream_ids) { ++ this->streams[stream_index].bitrate = LE_32(this->asf_header + i + 4 + j * 6); ++ this->streams[stream_index].bitrate_pos = i + 4 + j * 6; ++ lprintf ("stream id %d, bitrate %d\n", stream_id, ++ this->[stream_index].bitrate); ++ } + } + } + break; +@@ -914,7 +925,6 @@ + int max_arate = 0; + int min_vrate = 0; + int min_bw_left = 0; +- int stream_id; + int bandwitdh_left; + int res; + +@@ -923,12 +933,11 @@ + /* i've never seen more than one audio stream */ + lprintf("num_stream_ids=%d\n", this->num_stream_ids); + for (i = 0; i < this->num_stream_ids; i++) { +- stream_id = this->stream_ids[i]; +- switch (this->stream_types[stream_id]) { ++ switch (this->streams[i].stream_type) { + case ASF_STREAM_TYPE_AUDIO: +- if (this->bitrates[stream_id] > max_arate) { +- audio_stream = stream_id; +- max_arate = this->bitrates[stream_id]; ++ if (this->streams[i].bitrate > max_arate) { ++ audio_stream = this->streams[i].stream_id; ++ max_arate = this->streams[i].bitrate; + } + break; + default: +@@ -945,13 +954,12 @@ + + min_bw_left = bandwitdh_left; + for (i = 0; i < this->num_stream_ids; i++) { +- stream_id = this->stream_ids[i]; +- switch (this->stream_types[stream_id]) { ++ switch (this->streams[i].stream_type) { + case ASF_STREAM_TYPE_VIDEO: +- if (((bandwitdh_left - this->bitrates[stream_id]) < min_bw_left) && +- (bandwitdh_left >= this->bitrates[stream_id])) { +- video_stream = stream_id; +- min_bw_left = bandwitdh_left - this->bitrates[stream_id]; ++ if (((bandwitdh_left - this->streams[i].bitrate) < min_bw_left) && ++ (bandwitdh_left >= this->streams[i].bitrate)) { ++ video_stream = this->streams[i].stream_id; ++ min_bw_left = bandwitdh_left - this->streams[i].bitrate; + } + break; + default: +@@ -962,13 +970,12 @@ + /* choose the lower bitrate of */ + if (!video_stream && this->has_video) { + for (i = 0; i < this->num_stream_ids; i++) { +- stream_id = this->stream_ids[i]; +- switch (this->stream_types[stream_id]) { ++ switch (this->streams[i].stream_type) { + case ASF_STREAM_TYPE_VIDEO: +- if ((this->bitrates[stream_id] < min_vrate) || ++ if ((this->streams[i].bitrate < min_vrate) || + (!min_vrate)) { +- video_stream = stream_id; +- min_vrate = this->bitrates[stream_id]; ++ video_stream = this->streams[i].stream_id; ++ min_vrate = this->streams[i].bitrate; + } + break; + default: +@@ -983,10 +990,10 @@ + for (i = 1; i < this->num_stream_ids; i++) { + this->scmd_body [ (i - 1) * 6 + 2 ] = 0xFF; + this->scmd_body [ (i - 1) * 6 + 3 ] = 0xFF; +- this->scmd_body [ (i - 1) * 6 + 4 ] = this->stream_ids[i] ; +- this->scmd_body [ (i - 1) * 6 + 5 ] = this->stream_ids[i] >> 8; +- if ((this->stream_ids[i] == audio_stream) || +- (this->stream_ids[i] == video_stream)) { ++ this->scmd_body [ (i - 1) * 6 + 4 ] = this->streams[i].stream_id ; ++ this->scmd_body [ (i - 1) * 6 + 5 ] = this->streams[i].stream_id >> 8; ++ if ((this->streams[i].stream_id == audio_stream) || ++ (this->streams[i].stream_id == video_stream)) { + this->scmd_body [ (i - 1) * 6 + 6 ] = 0x00; + this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; + } else { +@@ -995,17 +1002,17 @@ + this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; + + /* forces the asf demuxer to not choose this stream */ +- if (this->bitrates_pos[this->stream_ids[i]]) { +- this->asf_header[this->bitrates_pos[this->stream_ids[i]]] = 0; +- this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 1] = 0; +- this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 2] = 0; +- this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0; ++ if (this->streams[i].bitrate_pos) { ++ this->asf_header[this->streams[i].bitrate_pos ] = 0; ++ this->asf_header[this->streams[i].bitrate_pos + 1] = 0; ++ this->asf_header[this->streams[i].bitrate_pos + 2] = 0; ++ this->asf_header[this->streams[i].bitrate_pos + 3] = 0; + } + } + } + + if (!send_command (io, this, 0x33, this->num_stream_ids, +- 0xFFFF | this->stream_ids[0] << 16, ++ 0xFFFF | this->streams[0].stream_id << 16, + this->num_stream_ids * 6 + 2)) { + /* FIXME: de-xine-ification */ + lprintf ( "***LOG:*** -- " --- libmms-0.3.orig/debian/patches/21_handle_mms_uris.patch +++ libmms-0.3/debian/patches/21_handle_mms_uris.patch @@ -0,0 +1,13 @@ +--- libmms-0.3.orig/src/mmsh.c 2007-07-03 16:06:33.000000000 +0200 ++++ libmms-0.3/src/mmsh.c 2007-07-03 16:07:12.000000000 +0200 +@@ -1007,7 +1007,9 @@ mmsh_t *mmsh_connect (mms_io_t *io, void + this->proxy_password = NULL; + this->host_user =(uri->user) ? strdup(uri->user) : NULL; + this->host_password = (uri->passwd) ? strdup(uri->passwd) : NULL; +- this->uri = (uri->path) ? strdup(uri->path) : NULL; ++ char * uri_string = gnet_uri_get_string(uri); ++ this->uri = strdup(uri_string); ++ g_free(uri_string); + } + if (proxy_uri) { + gnet_uri_delete(proxy_uri); --- libmms-0.3.orig/debian/patches/20_seeking-support.patch +++ libmms-0.3/debian/patches/20_seeking-support.patch @@ -0,0 +1,431 @@ +Index: libmms-0.3/src/mms.c +=================================================================== +--- libmms-0.3.orig/src/mms.c 2007-05-14 13:35:45.000000000 +0200 ++++ libmms-0.3/src/mms.c 2007-05-14 13:37:32.000000000 +0200 +@@ -141,6 +141,8 @@ + uint8_t buf[BUF_SIZE]; + int buf_size; + int buf_read; ++ off_t buf_packet_seq_offset; /* packet sequence offset residing in ++ buf */ + + uint8_t asf_header[ASF_HEADER_LEN]; + uint32_t asf_header_len; +@@ -148,10 +150,14 @@ + int seq_num; + int num_stream_ids; + mms_stream_t streams[ASF_MAX_NUM_STREAMS]; ++ uint8_t packet_id_type; + off_t start_packet_seq; /* for live streams != 0, need to keep it around */ + int need_discont; /* whether we need to set start_packet_seq */ + uint32_t asf_packet_len; + uint64_t file_len; ++ uint64_t time_len; /* playback time in 100 nanosecs (10^-7) */ ++ uint64_t preroll; ++ uint64_t asf_num_packets; + char guid[37]; + int bandwidth; + +@@ -532,6 +538,7 @@ + header->flags = 0; + header->packet_id_type = 0; + len = io_read(io, this->s, this->buf, 8); ++ this->buf_packet_seq_offset = -1; + if (len != 8) + goto error; + +@@ -582,6 +589,7 @@ + lprintf("packet_len: %d bytes\n", packet_len); + + len = io_read(io, this->s, this->buf + 12, packet_len) ; ++ //this->buf_packet_seq_offset = -1; // already set in get_packet_header + if (len != packet_len) { + return 0; + } +@@ -741,6 +749,9 @@ + break; + } + this->file_len = LE_64(this->asf_header + i + 40 - 24); ++ this->time_len = LE_64(this->asf_header + i + 64 - 24); ++ //this->time_len = LE_64(this->asf_header + i + 72 - 24); ++ this->preroll = LE_64(this->asf_header + i + 80 - 24); + lprintf ("file object, packet length = %d (%d)\n", + this->asf_packet_len, LE_32(this->asf_header + i + 96 - 24)); + break; +@@ -818,6 +829,10 @@ + } + break; + ++ case GUID_ASF_DATA: ++ this->asf_num_packets = LE_64(this->asf_header + i + 40 - 24); ++ break; ++ + default: + lprintf ("unknown object\n"); + break; +@@ -1063,6 +1078,7 @@ + this->need_discont = 1; + this->buf_size = 0; + this->buf_read = 0; ++ this->buf_packet_seq_offset = -1; + this->has_audio = 0; + this->has_video = 0; + this->bandwidth = bandwidth; +@@ -1252,6 +1268,7 @@ + /* report_progress (stream, 80); */ + + /* command 0x07 */ ++ this->packet_id_type = ASF_MEDIA_PACKET_ID_TYPE; + { + mms_buffer_t command_buffer; + mms_buffer_init(&command_buffer, this->scmd_body); +@@ -1263,7 +1280,7 @@ + mms_buffer_put_8 (&command_buffer, 0xFF); + mms_buffer_put_8 (&command_buffer, 0xFF); + mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */ +- mms_buffer_put_32 (&command_buffer, ASF_MEDIA_PACKET_ID_TYPE); /* asf media packet id type */ ++ mms_buffer_put_32 (&command_buffer, this->packet_id_type); /* asf media packet id type */ + if (!send_command (io, this, 0x07, 1, 0x0001FFFF, command_buffer.pos)) { + /* FIXME: de-xine-ification */ + lprintf ( "***LOG:*** -- " +@@ -1414,7 +1431,8 @@ + + /* FIXME: probably needs some more sophisticated logic, but + until we do seeking, this should work */ +- if(this->need_discont) ++ if(this->need_discont && ++ header.packet_id_type == ASF_MEDIA_PACKET_ID_TYPE) + { + this->need_discont = 0; + this->start_packet_seq = header.packet_seq; +@@ -1451,11 +1469,22 @@ + (start < end) && (end < (base+BUF_SIZE-1))) { + memset(this->buf + header.packet_len, 0, this->asf_packet_len - header.packet_len); + } ++ if (header.packet_id_type == this->packet_id_type) { + if (this->asf_packet_len > BUF_SIZE) { + this->buf_size = BUF_SIZE; + } else { + this->buf_size = this->asf_packet_len; + } ++ this->buf_packet_seq_offset = ++ header.packet_seq - this->start_packet_seq; ++ } else { ++ this->buf_size = 0; ++ // Don't set this packet sequence for reuse in seek(), since the ++ // subsequence packet may be discontinued. ++ //this->buf_packet_seq_offset = header.packet_seq; ++ // already set to -1 in get_packet_header ++ //this->buf_packet_seq_offset = -1; ++ } + } + } + break; +@@ -1529,6 +1558,255 @@ + return total; + } + ++// To be inline function? ++static int mms_request_data_packet (mms_io_t *io, mms_t *this, ++ double time_sec, unsigned long first_packet, unsigned long time_msec_limit) { ++ /* command 0x07 */ ++ { ++ mms_buffer_t command_buffer; ++ //mms_buffer_init(&command_buffer, this->scmd_body); ++ //mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */ ++ //mms_buffer_put_32 (&command_buffer, 0x00000000); ++ memcpy(this->scmd_body, &time_sec, 8); ++ mms_buffer_init(&command_buffer, this->scmd_body+8); ++ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */ ++ //mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */ ++ mms_buffer_put_32 (&command_buffer, first_packet); /* first packet sequence */ ++ //mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */ ++ //mms_buffer_put_8 (&command_buffer, 0xFF); ++ //mms_buffer_put_8 (&command_buffer, 0xFF); ++ //mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */ ++ mms_buffer_put_32 (&command_buffer, time_msec_limit & 0x00FFFFFF);/* max stream time limit (3 bytes) */ ++ mms_buffer_put_32 (&command_buffer, this->packet_id_type); /* asf media packet id type */ ++ if (!send_command (io, this, 0x07, 1, 0x0001FFFF, 8+command_buffer.pos)) { ++ /* FIXME: de-xine-ification */ ++ lprintf ( "***LOG:*** -- " ++ "libmms: failed to send command 0x07\n"); ++ return 0; ++ } ++ } ++ /* TODO: adjust current_pos, considering asf_header_read */ ++ return 1; ++} ++ ++int mms_request_time_seek (mms_io_t *io, mms_t *this, double time_sec) { ++ if (++this->packet_id_type <= ASF_MEDIA_PACKET_ID_TYPE) ++ this->packet_id_type = ASF_MEDIA_PACKET_ID_TYPE+1; ++ //return mms_request_data_packet (io, this, time_sec, 0xFFFFFFFF, 0x00FFFFFF); ++ // also adjust time by preroll ++ return mms_request_data_packet (io, this, ++ time_sec+(double)(this->preroll)/1000, ++ 0xFFFFFFFF, 0x00FFFFFF); ++} ++ ++// set current_pos to the first byte of the requested packet by peeking at ++// the first packet. ++// To be inline function? ++static int peek_and_set_pos (mms_io_t *io, mms_t *this) { ++ uint8_t saved_buf[BUF_SIZE]; ++ int saved_buf_size; ++ off_t saved_buf_packet_seq_offset; ++ // save buf and buf_size that may be changed in get_media_packet() ++ memcpy(saved_buf, this->buf, this->buf_size); ++ saved_buf_size = this->buf_size; ++ saved_buf_packet_seq_offset = this->buf_packet_seq_offset; ++ //this->buf_size = this->buf_read = 0; // reset buf, only if success peeking ++ this->buf_size = 0; ++ while (!this->eos) { ++ // get_media_packet() will set current_pos if data packet is read. ++ if (!get_media_packet (io, this)) { ++ /* FIXME: de-xine-ification */ ++ lprintf ( "***LOG:*** -- " ++ "libmms: get_media_packet failed\n"); ++ // restore buf and buf_size that may be changed in get_media_packet() ++ memcpy(this->buf, saved_buf, saved_buf_size); ++ this->buf_size = saved_buf_size; ++ this->buf_packet_seq_offset = saved_buf_packet_seq_offset; ++ return 0; ++ } ++ if (this->buf_size > 0) break; ++ } ++ // flush header and reset buf_read, only if success peeking ++ this->asf_header_read = this->asf_header_len; ++ this->buf_read = 0; ++ return 1; ++ //return this->current_pos; ++} ++ ++// send time seek request, and update current_pos corresponding to the next ++// requested packet ++// Note that, the current_pos will always does not less than asf_header_len ++int mms_time_seek (mms_io_t *io, mms_t *this, double time_sec) { ++ if (!mms_request_time_seek (io, this, time_sec)) return 0; ++ return peek_and_set_pos (io, this); ++} ++ ++// http://sdp.ppona.com/zipfiles/MMSprotocol_pdf.zip said that, this ++// packet_seq value make no difference in version 9 servers. ++// But from my experiment with ++// mms://202.142.200.130/tltk/56k/tltkD2006-08-08ID-7209.wmv and ++// mms://202.142.200.130/tltk/56k/tltkD2006-09-01ID-7467.wmv (the url may valid ++// in only 2-3 months) whose server is version 9, it does response and return ++// the requested packet. ++int mms_request_packet_seek (mms_io_t *io, mms_t *this, ++ unsigned long packet_seq) { ++ if (++this->packet_id_type <= ASF_MEDIA_PACKET_ID_TYPE) ++ this->packet_id_type = ASF_MEDIA_PACKET_ID_TYPE+1; ++ return mms_request_data_packet (io, this, 0, packet_seq, 0x00FFFFFF); ++} ++ ++// send packet seek request, and update current_pos corresponding to the next ++// requested packet ++// Note that, the current_pos will always does not less than asf_header_len ++// Not export this function. Let user use mms_seek() instead? ++static int mms_packet_seek (mms_io_t *io, mms_t *this, ++ unsigned long packet_seq) { ++ if (!mms_request_packet_seek (io, this, packet_seq)) return 0; ++ return peek_and_set_pos (io, this); ++} ++ ++/* ++TODO: To use this table to calculate buf_packet_seq_offset rather than store ++and retrieve it from this->buf_packet_seq_offset? ++current_packet_seq == (current_pos - asf_header_len) / asf_packet_len ++current_packet_seq == -1 if current_pos < asf_header_len ++buf_packet_seq_offset indicating which packet sequence are residing in the buf. ++Possible status after read(), "last" means last value or unchange. ++current_packet_seq | buf_read | buf_size | buf_packet_seq_offset ++-------------------+----------------+-----------+--------------- ++<= 0 | 0 (last) | 0 (last) | none ++<= 0 | 0 (last) | 0 (last) | eos at #0 ++<= 0 | 0 (last) | 0 (last) | eos at > #0 ++<= 0 | 0 (last) | > 0 (last)| #0 ++<= 0 | buf_size (last)| > 0 (last)| > #0 ++> 0 | 0 | 0 | eos at current_packet_seq ++> 0 | 0(never happen)| > 0 | (never happen) ++> 0 | buf_size | > 0 | current_packet_seq-1 ++*/ ++// TODO: How to handle seek() in multi stream source? ++// The stream that follows 0x20 ("new stream") command. ++off_t mms_seek (mms_io_t *io, mms_t *this, off_t offset, int origin) { ++ off_t dest; ++ off_t dest_packet_seq; ++ //off_t buf_packet_seq_offset; ++ ++ switch (origin) { ++ case SEEK_SET: ++ dest = offset; ++ break; ++ case SEEK_CUR: ++ dest = this->current_pos + offset; ++ break; ++ case SEEK_END: ++ //if (this->asf_num_packets == 0) { ++ // //printf ("input_mms: unknown end position in seek!\n"); ++ // return this->current_pos; ++ //} ++ dest = mms_get_length (this) + offset; ++ default: ++ printf ("input_mms: unknown origin in seek!\n"); ++ return this->current_pos; ++ } ++ ++ dest_packet_seq = dest - this->asf_header_len; ++ //if (dest_packet_seq > 0) dest_packet_seq /= this->asf_packet_len; ++ dest_packet_seq = dest_packet_seq >= 0 ? ++ dest_packet_seq / this->asf_packet_len : -1; ++#if 0 ++ // buf_packet_seq_offset will identify which packet sequence are residing in ++ // the buf. ++#if 1 /* To show both of the alternate styles :D */ ++ buf_packet_seq_offset = this->current_pos - this->asf_header_len; ++ //if (buf_packet_seq_offset > 0) buf_packet_seq_offset /= this->asf_packet_len; ++ buf_packet_seq_offset = buf_packet_seq_offset >= 0 ? ++ buf_packet_seq_offset / this->asf_packet_len : -1; ++ // Note: buf_read == buf_size == 0 may means that it is eos, ++ // eos means that the packet has been peek'ed. ++ if (this->buf_read >= this->buf_size && this->buf_size > 0 && ++ buf_packet_seq_offset >= 0 || ++ // assuming packet not peek'ed in the following condition ++ /*this->buf_read >= this->buf_size && */this->buf_size == 0 && ++ buf_packet_seq_offset == 0) ++ // The buf is all read but the packet has not been peek'ed. ++ --buf_packet_seq_offset; ++#else ++ buf_packet_seq_offset = this->current_pos - this->asf_header_len - 1; ++ //if (buf_packet_seq_offset > 0) buf_packet_seq_offset /= this->asf_packet_len; ++ buf_packet_seq_offset = buf_packet_seq_offset >= 0 ? ++ buf_packet_seq_offset / this->asf_packet_len : -1; ++ // Note: buf_read == buf_size == 0 may means that it is eos, ++ // eos means that the packet has been peek'ed. ++ if (this->buf_read == 0/* && buf_packet_seq_offset >= 0*/) ++ // Since the packet has just been peek'ed. ++ ++buf_packet_seq_offset; ++#endif ++#endif ++ ++ if (dest_packet_seq < 0) { ++ if (this->buf_packet_seq_offset > 0) { ++ if (!mms_request_packet_seek (io, this, 0xFFFFFFFF)) ++ return this->current_pos; ++#if 1 ++ // clear buf ++ this->buf_read = this->buf_size = 0; ++ this->buf_packet_seq_offset = -1; ++ } else { ++#else ++ // clear buf ++ this->buf_read = this->buf_size; ++ // Set this packet sequence not to be reused, since the subsequence ++ // packet may be discontinued. ++ this->buf_packet_seq_offset = -1; ++ // don't reset buf_read if buf_packet_seq_offset < 0, since the previous ++ // buf may not be cleared. ++ } else if (this->buf_packet_seq_offset == 0) { ++#endif ++ // reset buf_read ++ this->buf_read = 0; ++ } ++ this->asf_header_read = dest; ++ return this->current_pos = dest; ++ } ++ // dest_packet_seq >= 0 ++ if (this->asf_num_packets > 0 && dest == this->asf_header_len + ++ this->asf_num_packets*this->asf_packet_len) { ++ // Requesting the packet beyond the last packet, can cause the server to ++ // not return any packet or any eos command. This can cause ++ // mms_packet_seek() to hang. ++ // This is to allow seeking at end of stream, and avoid hanging. ++ --dest_packet_seq; ++ } ++ if (dest_packet_seq != this->buf_packet_seq_offset) { ++ if (dest_packet_seq >= this->asf_num_packets) { ++ // Do not seek beyond the last packet. ++ return this->current_pos; ++ } ++ if (!mms_packet_seek (io, this, this->start_packet_seq + dest_packet_seq)) ++ return this->current_pos; ++ // Check if current_pos is correct. ++ // This can happen if the server ignore packet seek command. ++ // If so, just return unchanged current_pos, rather than trying to ++ // mms_read() to reach the destination pos. ++ // It should let the caller to decide to choose the alternate method, such ++ // as, mms_time_seek() and/or mms_read() until the destination pos is ++ // reached. ++ if (dest_packet_seq != this->buf_packet_seq_offset) ++ return this->current_pos; ++ // This has already been set in mms_packet_seek(). ++ //if (current_packet_seq < 0) ++ // this->asf_header_read = this->asf_header_len; ++ //this->asf_header_read = this->asf_header_len; ++ } ++ // eos is reached ? ++ //if (this->buf_size <= 0) return this->current_pos; ++ //this->buf_read = (dest - this->asf_header_len) % this->asf_packet_len; ++ this->buf_read = dest - ++ (this->asf_header_len + dest_packet_seq*this->asf_packet_len); ++ // will never happen ? ++ //if (this->buf_size <= this->buf_read) return this->current_pos; ++ return this->current_pos = dest; ++} ++ + + void mms_close (mms_t *this) { + +@@ -1550,8 +1828,18 @@ + free (this); + } + ++double mms_get_time_length (mms_t *this) { ++ return (double)(this->time_len) / 1e7; ++} ++ ++uint64_t mms_get_raw_time_length (mms_t *this) { ++ return this->time_len; ++} ++ + uint32_t mms_get_length (mms_t *this) { + return this->file_len; ++ // use this rather? ++ //return this->asf_header_len + this->asf_num_packets*this->asf_packet_len; + } + + off_t mms_get_current_pos (mms_t *this) { +Index: libmms-0.3/src/mms.h +=================================================================== +--- libmms-0.3.orig/src/mms.h 2006-06-06 11:49:15.000000000 +0200 ++++ libmms-0.3/src/mms.h 2007-05-14 13:36:05.000000000 +0200 +@@ -50,6 +50,28 @@ + mms_t* mms_connect (mms_io_t *io, void *data, const char *url, int bandwidth); + + int mms_read (mms_io_t *io, mms_t *instance, char *data, int len); ++int mms_request_time_seek (mms_io_t *io, mms_t *instance, double time_sec); ++int mms_time_seek (mms_io_t *io, mms_t *instance, double time_sec); ++int mms_request_packet_seek (mms_io_t *io, mms_t *instance, ++ unsigned long packet_seq); ++/* ++ * mms_seek() will try to seek using mms_request_packet_seek(), if the server ++ * ignore the packet seek command, it will return unchanged current_pos, rather ++ * than trying to mms_read() until the destination pos is reached. This is to ++ * let the caller, by itself, to decide to choose the alternate method, such ++ * as, mms_time_seek() and/or mms_read() until the destination pos is reached. ++ * One can do binary search using time offset (mms_time_seek()) as a search ++ * index, to approach the desired byte offset. It is to systematically guess ++ * the time offset to reach for the byte offset. ++ * ++ * Known BUG: Application must be compiled with 64-bit file offset ++ * (-D_FILE_OFFSET_BITS=64) to use this function correctly. ++ */ ++off_t mms_seek (mms_io_t *io, mms_t *instance, off_t offset, int origin); ++/* return total playback time in seconds */ ++double mms_get_time_length (mms_t *instance); ++/* return raw total playback time in 100 nanosecs (10^-7) */ ++uint64_t mms_get_raw_time_length (mms_t *instance); + uint32_t mms_get_length (mms_t *instance); + void mms_close (mms_t *instance); + --- libmms-0.3.orig/debian/patches/series +++ libmms-0.3/debian/patches/series @@ -0,0 +1,5 @@ +10_asf-header-size.patch +11_fix-stream-id-crash.patch +20_seeking-support.patch +21_handle_mms_uris.patch +60_first-packet.patch -p0 --- libmms-0.3.orig/debian/patches/10_asf-header-size.patch +++ libmms-0.3/debian/patches/10_asf-header-size.patch @@ -0,0 +1,41 @@ +--- libmms-0.3.orig/src/mms.c ++++ libmms-0.3/src/mms.c +@@ -80,7 +80,7 @@ + #define CMD_PREFIX_LEN 8 + #define CMD_BODY_LEN 1024 + +-#define ASF_HEADER_LEN 8192 ++#define ASF_HEADER_LEN (8192 * 2) + + + #define MMS_PACKET_ERR 0 +@@ -680,7 +680,8 @@ + case MMS_PACKET_ASF_PACKET: + if (header.packet_len + this->asf_header_len > ASF_HEADER_LEN) { + lprintf( "***LOG:*** -- " +- "libmms: asf packet too large\n"); ++ "libmms: asf packet too large: %d\n", ++ header.packet_len + this->asf_header_len); + return 0; + } + len = io_read(io, this->s, +--- libmms-0.3.orig/src/mmsh.c ++++ libmms-0.3/src/mmsh.c +@@ -79,7 +79,7 @@ + #define CHUNK_TYPE_END 0x4524 + #define CHUNK_TYPE_ASF_HEADER 0x4824 + #define CHUNK_SIZE 65536 /* max chunk size */ +-#define ASF_HEADER_SIZE 8192 /* max header size */ ++#define ASF_HEADER_SIZE (8192 * 2) /* max header size */ + + #define SCRATCH_SIZE 1024 + +@@ -462,7 +462,7 @@ + /* read chunk header */ + read_len = io_read(io, this->s, chunk_header, CHUNK_HEADER_LENGTH); + if (read_len != CHUNK_HEADER_LENGTH) { +- lprintf ("chunk header read failed, %d != %d\n", len, CHUNK_HEADER_LENGTH); ++ lprintf ("chunk header read failed, %d != %d\n", read_len, CHUNK_HEADER_LENGTH); + return 0; + } + this->chunk_type = LE_16 (&chunk_header[0]);