[MPlayer-dev-eng] Re: [PATCH] Recursively Nested ASX Playlists

Mrc Gran mrc.gran at gmail.com
Sat Mar 10 23:40:14 CET 2007


Hello,
I've updated the patch making mplayer capable of playing recursively nested
asx playlists, removing a few unused lines and letting it cleaner (see
attachment).
I have been using it for days without detecting any problem with any site.

Has any developer had a look at it? I have not received any feedback.

[]s,
Marcus Granado

Hello,
>
> I'm sending a patch to make mplayer capable of playing recursively nested
> asx playlists.
> A nested asx playlist is one whose refs point to further asx list files
> instead of real media files such as wmv.
> (This patch is not to be confused with processing of entryrefs which seems
> to be already implemented at asxparser.c.)
>
> Both asx playlists and wmv files are of mime type x-ms-asf. This patches
> modifies stream/asf_streaming.c so that it looks for a file ending with
> '.asx' which, if found, returns a demux_type_playlist to mplayer.c instead
> of the expected demuxer_type_asf. This triggers mplayer.c to synchronously
> follow the recursive nested playlists.
> A new streaming type ASF_ASXPlaylist_e is added to asf.h to control the
> new code branch. The function play_tree_parser_get_line() also receives a
> new code branch to deal with buffered streams which is necessary in order to
> parse the playlist, buffered when the asf stream was opened.
>
> I felt the necessity to develop this patch because there are sites which
> use nested asx playlists, such as video.globo.com (see discussions at http://sourceforge.net/forum/forum.php?thread_id=1668761&forum_id=242727
> <http://sourceforge.net/forum/forum.php?thread_id=1668761&forum_id=242727>and
>
> http://sourceforge.net/mailarchive/forum.php?thread_id=31642270&forum_id=21800),
> and nested playlists are part of the microsoft specification for asx (
> http://msdn2.microsoft.com/en-us/library/bb262812.aspx).
> I also tested the patch against www.bbc.co.uk, www.cnn.com,
> http://wptv.wp.pl/news.html
> (mplayer -playlist http://i.wp.pl/a/f/asx/11771/wptvnews.asx) and all
> worked fine.
> Extra care was taken to modify the minimum amount of code and to minimize
> potential regressions.
>
> In case this patch is approved for inclusion in mplayer, I would be
> grateful if my name was cited in the list of contributors. All comments
> welcome.
>
> Thanks,
> Marcus C. Granado
> mrc [d-o-t] gran [a-t] gmail [d-o-t] com
> --
>
>
-------------- next part --------------
Index: stream/asf_streaming.c
===================================================================
--- stream/asf_streaming.c	(revision 22505)
+++ stream/asf_streaming.c	(working copy)
@@ -765,11 +765,42 @@
 			mp_msg(MSGT_NETWORK,MSGL_DBG2,"Response [%s]\n", http_hdr->buffer );
 		}
 		ret = asf_http_parse_response(asf_http_ctrl, http_hdr);
+		
+		if (strstr(url->url,".asx")!=NULL) {
+		  mp_msg(MSGT_NETWORK,MSGL_V,"ASXPlaylist detected: url=%s, bodysize=%i\n",url->url,http_hdr->body_size);
+		  ret = 0;
+		  asf_http_ctrl->streaming_type=ASF_ASXPlaylist_e;
+		}
+
 		if( ret<0 ) {
 			mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_HeaderParseFailed);
 			goto err_out;
 		}
 		switch( asf_http_ctrl->streaming_type ) {
+			case ASF_ASXPlaylist_e:
+
+				//read potentially remaining
+				//asx playlist data into buffer
+				do {
+				  i = recv( fd, buffer, BUFFER_SIZE, 0 );
+				  if( i<0 ) {
+				    perror("read");
+				    goto err_out;
+				  }
+				  if (i>0) http_response_append( http_hdr, buffer, i );
+				} while(i>0);
+
+			       //move buffer from header to stream
+				if( http_hdr->body_size>0 ) {
+				  if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) {
+				    goto err_out;
+				  }
+				}
+
+				*demuxer_type = DEMUXER_TYPE_PLAYLIST;
+				done=1;
+			  break;
+	
 			case ASF_Live_e:
 			case ASF_Prerecorded_e:
 			case ASF_PlainText_e:
@@ -817,7 +848,7 @@
 	} while(!done);
 
 	stream->fd = fd;
-	if( asf_http_ctrl->streaming_type==ASF_PlainText_e || asf_http_ctrl->streaming_type==ASF_Redirector_e ) {
+	if( asf_http_ctrl->streaming_type==ASF_PlainText_e || asf_http_ctrl->streaming_type==ASF_Redirector_e || asf_http_ctrl->streaming_type==ASF_ASXPlaylist_e) {
 		stream->streaming_ctrl->streaming_read = nop_streaming_read;
 		stream->streaming_ctrl->streaming_seek = nop_streaming_seek;
 	} else {
@@ -852,12 +883,13 @@
 	url_free(url);
 	
 	mp_msg(MSGT_OPEN, MSGL_INFO, MSGTR_MPDEMUX_ASF_InfoStreamASFURL, stream->url);
-	if((!strncmp(stream->url, "http", 4)) && (*file_format!=DEMUXER_TYPE_ASF && *file_format!=DEMUXER_TYPE_UNKNOWN)) {
+	if((!strncmp(stream->url, "http", 4)) && (*file_format!=DEMUXER_TYPE_ASF && *file_format!=DEMUXER_TYPE_UNKNOWN && *file_format!=DEMUXER_TYPE_PLAYLIST)) {
 		streaming_ctrl_free(stream->streaming_ctrl);
 		stream->streaming_ctrl = NULL;
 		return STREAM_UNSUPORTED;
 	}
 
+	*file_format = DEMUXER_TYPE_ASF;
 	if(asf_streaming_start(stream, file_format) < 0) {
 		mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_ASF_StreamingFailed);
 		streaming_ctrl_free(stream->streaming_ctrl);
@@ -865,7 +897,8 @@
 		return STREAM_UNSUPORTED;
 	}
 	
-	*file_format = DEMUXER_TYPE_ASF;
+	if (*file_format != DEMUXER_TYPE_PLAYLIST)	
+	  *file_format = DEMUXER_TYPE_ASF;
 	stream->type = STREAMTYPE_STREAM;
 	fixup_network_stream_cache(stream);
 	return STREAM_OK;
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 22505)
+++ mplayer.c	(working copy)
@@ -2864,6 +2864,8 @@
     mp_msg(MSGT_CPLAYER,MSGL_V,"Parsing playlist %s...\n",
 	    filename_recode(filename));
     entry = parse_playtree(mpctx->stream,0);
+    //TODO:limit depth of nested playlists
+    //to avoid following infinitely nested playlists.
     mpctx->eof=playtree_add_playlist(entry);
     goto goto_next_file;
   }
Index: playtreeparser.c
===================================================================
--- playtreeparser.c	(revision 22505)
+++ playtreeparser.c	(working copy)
@@ -51,18 +51,46 @@
 play_tree_parser_get_line(play_tree_parser_t* p) {
   char *end,*line_end;
   int r,resize = 0;
+  int buffered_stream=0;
 
+  if (p==NULL) return NULL;
+  if (p->stream !=NULL &&
+      p->stream->streaming_ctrl != NULL &&
+      p->stream->streaming_ctrl->buffer != NULL &&
+      p->stream->streaming_ctrl->buffer_size > 0) {
+    buffered_stream=1;
+  }
+
   if(p->buffer == NULL) {
-    p->buffer = malloc(BUF_STEP);
-    p->buffer_size = BUF_STEP;
+    if (!buffered_stream) {
+      p->buffer = malloc(BUF_STEP);
+      p->buffer_size = BUF_STEP;
+    } else {
+      p->buffer_size = p->stream->streaming_ctrl->buffer_size + 1;
+      p->buffer = malloc(p->buffer_size);
+      memcpy( p->buffer, p->stream->streaming_ctrl->buffer, p->stream->streaming_ctrl->buffer_size );
+      p->buffer[p->buffer_size - 1] = '\0';
+      p->buffer_end = p->buffer_size;
+      p->stream->eof = 1;
+      free(p->stream->streaming_ctrl->buffer);
+      p->stream->streaming_ctrl->buffer=NULL;
+      p->stream->streaming_ctrl->buffer_size=0;
+    }
     p->iter = p->buffer;
   }
 
   if(p->stream->eof && (p->buffer_end == 0 || p->iter[0] == '\0'))
     return NULL;
-    
-  while(1) {
 
+  if (buffered_stream) {
+
+      end = strchr(p->iter,'\n');
+      if (!end) end = p->buffer + p->buffer_end;
+
+  } else {
+
+   while(1) {
+
     if(resize) {
       r = p->iter - p->buffer;
       p->buffer = (char*)realloc(p->buffer,p->buffer_size+BUF_STEP);
@@ -91,6 +119,7 @@
       continue;
     }
     break;
+   }
   }
 
   line_end = ((*(end-1)) == '\r') ? end-1 : end;
Index: libmpdemux/asf.h
===================================================================
--- libmpdemux/asf.h	(revision 22505)
+++ libmpdemux/asf.h	(working copy)
@@ -120,7 +120,8 @@
 	ASF_Prerecorded_e,
 	ASF_Redirector_e,
 	ASF_PlainText_e,
-	ASF_Authenticate_e
+	ASF_Authenticate_e,
+	ASF_ASXPlaylist_e
 } ASF_StreamType_e;
 
 typedef struct {


More information about the MPlayer-dev-eng mailing list