r763 - in /unstable/libmms/debian: changelog patches/20_seeking-support.patch patches/series rules
lool at users.alioth.debian.org
lool at users.alioth.debian.org
Mon May 14 11:40:14 UTC 2007
Author: lool
Date: Mon May 14 11:40:14 2007
New Revision: 763
URL: http://svn.debian.org/wsvn/pkg-multimedia/?sc=1&rev=763
Log:
* New patch, 20_seeking-support, adds API permitting seeking of mms streams;
by Anon Sricharoenchai; bump shlibs to >= 0.3-4; closes: #387267.
Added:
unstable/libmms/debian/patches/20_seeking-support.patch
Modified:
unstable/libmms/debian/changelog
unstable/libmms/debian/patches/series
unstable/libmms/debian/rules
Modified: unstable/libmms/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-multimedia/unstable/libmms/debian/changelog?rev=763&op=diff
==============================================================================
--- unstable/libmms/debian/changelog (original)
+++ unstable/libmms/debian/changelog Mon May 14 11:40:14 2007
@@ -1,3 +1,10 @@
+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.
+
+ -- Loic Minier <lool at dooz.org> Mon, 14 May 2007 13:31:27 +0200
+
libmms (0.3-3) unstable; urgency=low
* Set Maintainer to pkg-multimedia-maintainers and list myself as Uploader.
Added: unstable/libmms/debian/patches/20_seeking-support.patch
URL: http://svn.debian.org/wsvn/pkg-multimedia/unstable/libmms/debian/patches/20_seeking-support.patch?rev=763&op=file
==============================================================================
--- unstable/libmms/debian/patches/20_seeking-support.patch (added)
+++ unstable/libmms/debian/patches/20_seeking-support.patch Mon May 14 11:40:14 2007
@@ -1,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);
+
Modified: unstable/libmms/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-multimedia/unstable/libmms/debian/patches/series?rev=763&op=diff
==============================================================================
--- unstable/libmms/debian/patches/series (original)
+++ unstable/libmms/debian/patches/series Mon May 14 11:40:14 2007
@@ -1,2 +1,3 @@
10_asf-header-size.patch
11_fix-stream-id-crash.patch
+20_seeking-support.patch
Modified: unstable/libmms/debian/rules
URL: http://svn.debian.org/wsvn/pkg-multimedia/unstable/libmms/debian/rules?rev=763&op=diff
==============================================================================
--- unstable/libmms/debian/rules (original)
+++ unstable/libmms/debian/rules Mon May 14 11:40:14 2007
@@ -74,7 +74,7 @@
dh_strip
dh_compress
dh_fixperms
- dh_makeshlibs -V 'libmms0 (>= 0.2)'
+ dh_makeshlibs -V 'libmms0 (>= 0.3-4)'
dh_installdeb
dh_shlibdeps
dh_gencontrol
More information about the pkg-multimedia-commits
mailing list