You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
|
Jul
(29) |
Aug
(20) |
Sep
(6) |
Oct
(89) |
Nov
(24) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(16) |
Feb
(1) |
Mar
(7) |
Apr
(32) |
May
(36) |
Jun
(21) |
Jul
(65) |
Aug
(6) |
Sep
|
Oct
(30) |
Nov
(26) |
Dec
(44) |
2006 |
Jan
(35) |
Feb
(15) |
Mar
(29) |
Apr
(24) |
May
(8) |
Jun
(2) |
Jul
(7) |
Aug
(11) |
Sep
(61) |
Oct
(36) |
Nov
(10) |
Dec
(14) |
2007 |
Jan
(6) |
Feb
(43) |
Mar
(55) |
Apr
(20) |
May
(26) |
Jun
(21) |
Jul
(24) |
Aug
(22) |
Sep
(24) |
Oct
(4) |
Nov
|
Dec
(60) |
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(51) |
Jul
(2) |
Aug
(13) |
Sep
|
Oct
(16) |
Nov
(99) |
Dec
(12) |
2009 |
Jan
(23) |
Feb
(44) |
Mar
(4) |
Apr
|
May
|
Jun
(9) |
Jul
(70) |
Aug
(14) |
Sep
(13) |
Oct
(6) |
Nov
|
Dec
(3) |
2010 |
Jan
(13) |
Feb
(17) |
Mar
(2) |
Apr
(3) |
May
(71) |
Jun
(19) |
Jul
(95) |
Aug
|
Sep
|
Oct
|
Nov
(71) |
Dec
(3) |
2011 |
Jan
(52) |
Feb
|
Mar
(34) |
Apr
(10) |
May
(8) |
Jun
(8) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
From: jreichen <jre...@us...> - 2011-01-23 18:07:24
|
Update of /cvsroot/sageplugins/webapp/WebContent/m In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv1440/WebContent/m Modified Files: extenderdetails.jsp Log Message: - Store client, extender, and placeshifter descriptive names in Sage.properties Index: extenderdetails.jsp =================================================================== RCS file: /cvsroot/sageplugins/webapp/WebContent/m/extenderdetails.jsp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** extenderdetails.jsp 5 Nov 2010 03:08:01 -0000 1.6 --- extenderdetails.jsp 23 Jan 2011 18:07:16 -0000 1.7 *************** *** 53,57 **** <div class="value"> <%--input type="text"></input--%> ! <%= sagex.webserver.UIContextTranslator.doTranslate(request.getParameter("context")) %> </div> --- 53,57 ---- <div class="value"> <%--input type="text"></input--%> ! <%= sagex.webserver.UiContextProperties.getProperty(request.getParameter("context"), "name") %> </div> |
From: jreichen <jre...@us...> - 2011-01-23 18:05:31
|
Update of /cvsroot/sageplugins/webapp/WebContent/m In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv996/WebContent/m Modified Files: details.jsp Log Message: - Store client, extender, and placeshifter descriptive names in Sage.properties Index: details.jsp =================================================================== RCS file: /cvsroot/sageplugins/webapp/WebContent/m/details.jsp,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** details.jsp 5 Nov 2010 03:08:01 -0000 1.7 --- details.jsp 23 Jan 2011 18:05:23 -0000 1.8 *************** *** 280,284 **** <sagemf:GetSegmentFiles var="segmentFiles" mediaFile="${airing}"/> <c:if test="${!empty segmentFiles}"> ! <p><b>Files:</b><br /> <c:forEach var="file" items="${segmentFiles}" varStatus="status"> <c:url var="fileSegmentUrl" value="../MediaFile"> --- 280,284 ---- <sagemf:GetSegmentFiles var="segmentFiles" mediaFile="${airing}"/> <c:if test="${!empty segmentFiles}"> ! <p><b>Files:</b><br/> <c:forEach var="file" items="${segmentFiles}" varStatus="status"> <c:url var="fileSegmentUrl" value="../MediaFile"> *************** *** 286,290 **** <c:param name="Segment" value="${status.index}"></c:param> </c:url> ! <a href="${fileSegmentUrl}">${file}</a><br /> </c:forEach> </p> --- 286,290 ---- <c:param name="Segment" value="${status.index}"></c:param> </c:url> ! <a href="${fileSegmentUrl}">${file}</a><br/> </c:forEach> </p> *************** *** 419,423 **** <c:set var="formId" value="${context}WatchNowForm"/> <form id="${formId}" method="post" action="${cp}/m/Command"> ! <c:set var="contextName" value="<%= sagex.webserver.UIContextTranslator.doTranslate(pageContext.getAttribute("context").toString()) %>"/> <c:if test="${contextName == 'SAGETV_PROCESS_LOCAL_UI'}"> <c:set var="contextName" value="SageTV"/> --- 419,423 ---- <c:set var="formId" value="${context}WatchNowForm"/> <form id="${formId}" method="post" action="${cp}/m/Command"> ! <c:set var="contextName" value="<%= sagex.webserver.UiContextProperties.getProperty(pageContext.getAttribute("context").toString(), "name") %>"/> <c:if test="${contextName == 'SAGETV_PROCESS_LOCAL_UI'}"> <c:set var="contextName" value="SageTV"/> *************** *** 454,458 **** </c:if> <input type="hidden" name="returnto" value="${cp}/m/details.jsp?${pageContext.request.queryString}"/> ! <button type="submit" name="command" value="WatchNow"><%= sagex.webserver.UIContextTranslator.doTranslate(pageContext.getAttribute("client").toString()) %></button> </form> <script language="JavaScript"> --- 454,458 ---- </c:if> <input type="hidden" name="returnto" value="${cp}/m/details.jsp?${pageContext.request.queryString}"/> ! <button type="submit" name="command" value="WatchNow"><%= sagex.webserver.UiContextProperties.getProperty(pageContext.getAttribute("client").toString(), "name") %></button> </form> <script language="JavaScript"> |
From: jreichen <jre...@us...> - 2011-01-23 18:00:31
|
Update of /cvsroot/sageplugins/webapp/src/sagex/webserver In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv31931/src/sagex/webserver Added Files: UiContextProperties.java Log Message: - Store client, extender, and placeshifter descriptive names in Sage.properties --- NEW FILE: UiContextProperties.java --- package sagex.webserver; import java.lang.reflect.InvocationTargetException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.mortbay.log.Log; import sage.SageTV; /** * Stores and retrieves descriptive names - or other properties - for Sage's UI * contexts in Sage.properties. Names used to be stored in webserver/extenders.properties * but are being moved so the file can be obsoleted and other plugins can easily use the * same properties. * The contexts ids are either MAC addresses for placeshifters and extenders, or * IP addresses for client. * */ public class UiContextProperties { private static Pattern CLIENT_CONTEXT_PATTERN = Pattern.compile("/(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}):(\\d{1,5})"); private UiContextProperties() { } public static String getProperty(String contextName, String contextPropertyName) { return getProperty(contextName, contextPropertyName, contextName); } public static String getProperty(String contextName, String contextPropertyName, String defaultValue) { String returnValue = null; try { String propertyName = createPropertyName(contextName, contextPropertyName); returnValue = (String) SageTV.api("GetServerProperty", new Object[] {propertyName, null}); // value not in Sage.properties, fallback to extenders.properties if (returnValue == null) { // copy context name from extenders.properties returnValue = UIContextTranslator.doTranslate(contextName); if ((returnValue != null) && (!returnValue.equals(contextName))) { // copy property to Sage.properties if it exists and is not the same as the context setProperty(contextName, contextPropertyName, returnValue); } else { // set a blank value so next time this won't read from extenders.properties setProperty(contextName, contextPropertyName, ""); } } } catch (InvocationTargetException e) { Log.info(e.getMessage()); Log.ignore(e); } if ((returnValue == null) || (returnValue.trim().length() == 0)) { returnValue = defaultValue; } return returnValue; } public static void setProperty(String contextName, String contextPropertyName, String value) { String propertyName = createPropertyName(contextName, contextPropertyName); try { SageTV.api("SetServerProperty", new Object[] {propertyName, value}); } catch (InvocationTargetException e) { Log.info(e.getMessage()); Log.ignore(e); } } private static String createPropertyName(String contextName, String contextPropertyName) { Matcher contextMatcher = CLIENT_CONTEXT_PATTERN.matcher(contextName); if (contextMatcher.matches()) { // if the ui context is for a SageTV Client, strip off the leading forward // slash and the trailing colon and port number contextName = contextMatcher.group(1); } String propertyName = "sagex/uicontexts/" + contextName + "/" + contextPropertyName; return propertyName; } } |
From: jreichen <jre...@us...> - 2011-01-23 17:58:08
|
Update of /cvsroot/sageplugins/webapp/WebContent/m In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv30836/WebContent/m Modified Files: home.jsp Log Message: - Add System Messages section to Home page - Store client, extender, and placeshifter descriptive names in Sage.properties Index: home.jsp =================================================================== RCS file: /cvsroot/sageplugins/webapp/WebContent/m/home.jsp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** home.jsp 5 Nov 2010 03:08:01 -0000 1.4 --- home.jsp 23 Jan 2011 17:58:00 -0000 1.5 *************** *** 10,13 **** --- 10,15 ---- <%@ taglib prefix="sagemf" tagdir="/WEB-INF/tags/sage/api/mediafile" %> <%@ taglib prefix="sagemp" tagdir="/WEB-INF/tags/sage/api/mediaplayer" %> + <%@ taglib prefix="sagemsg" tagdir="/WEB-INF/tags/sage/api/systemmessage" %> + <%@ taglib prefix="sagemsgfn" tagdir="/WEB-INF/tags/sage/functions/systemmessage" %> <%@ taglib prefix="sageutil" tagdir="/WEB-INF/tags/sage/api/utility" %> <%@ taglib prefix="sagedatefn" tagdir="/WEB-INF/tags/sage/functions/date" %> *************** *** 33,37 **** -- Now Playing --%> ! <div class="section gloss">Now Playing</div> <div class="sectionbody"> <sageglbl:GetUIContextNames var="contexts"/> --- 35,39 ---- -- Now Playing --%> ! <div class="section">Now Playing</div> <div class="sectionbody"> <sageglbl:GetUIContextNames var="contexts"/> *************** *** 45,49 **** <div class="divider"> <a href="extenderdetails.jsp?context=${context}"> ! <%= sagex.webserver.UIContextTranslator.doTranslate(pageContext.getAttribute("context").toString()) %> </a> </div> --- 47,51 ---- <div class="divider"> <a href="extenderdetails.jsp?context=${context}"> ! <%= sagex.webserver.UiContextProperties.getProperty(pageContext.getAttribute("context").toString(), "name") %> </a> </div> *************** *** 76,80 **** <div class="divider"> <a href="extenderdetails.jsp?context=${client}" style="color: #042360;"> ! <%= sagex.webserver.UIContextTranslator.doTranslate(pageContext.getAttribute("client").toString()) %> </a> </div> --- 78,82 ---- <div class="divider"> <a href="extenderdetails.jsp?context=${client}" style="color: #042360;"> ! <%= sagex.webserver.UiContextProperties.getProperty(pageContext.getAttribute("client").toString(), "name") %> </a> </div> *************** *** 111,115 **** -- Currently Recording --%> ! <div class="section gloss">Currently Recording</div> <div class="sectionbody"> <sagecd:GetActiveCaptureDevices var="capturedevices"/> --- 113,117 ---- -- Currently Recording --%> ! <div class="section">Currently Recording</div> <div class="sectionbody"> <sagecd:GetActiveCaptureDevices var="capturedevices"/> *************** *** 138,142 **** -- Next Upcoming Recordings --%> ! <div class="section gloss">Next Upcoming Recordings</div> <div class="sectionbody"> <sageglbl:GetScheduledRecordings var="scheduledRecordings"/> --- 140,144 ---- -- Next Upcoming Recordings --%> ! <div class="section">Next Upcoming Recordings</div> <div class="sectionbody"> <sageglbl:GetScheduledRecordings var="scheduledRecordings"/> *************** *** 184,190 **** </div> <%-- -- Conflicts --%> ! <div class="section gloss">Conflicts</div> <div class="sectionbody"> <%@ include file="/WEB-INF/jspf/m/conflictstats.jspf" %> --- 186,242 ---- </div> <%-- + -- System Messages + --%> + <div class="section">System Messages</div> + <div class="sectionbody"> + <sagemsgfn:SupportsSystemMessages var="supportsSystemMessages"/> + + <c:if test="${not supportsSystemMessages}"> + System messages require SageTV 6.5.17 or later. + </c:if> + + <c:if test="${supportsSystemMessages}"> + <sagemsg:GetSystemAlertLevel var="alertLevel"/> + <c:if test="${empty alertLevel}"><c:set var="alertLevel">0</c:set></c:if> + <sagemsg:GetSystemMessages var="systemMessages"/> + <sageutil:Size var="systemMessageCount" data="${systemMessages}"/> + <c:choose> + <c:when test="${alertLevel == 0}"> + <c:set var="alertLevelDesc">Status</c:set> + </c:when> + <c:when test="${alertLevel == 1}"> + <c:set var="alertLevelDesc">Information</c:set> + </c:when> + <c:when test="${alertLevel == 2}"> + <c:set var="alertLevelDesc">Warning</c:set> + </c:when> + <c:when test="${alertLevel == 3}"> + <c:set var="alertLevelDesc">Error</c:set> + </c:when> + </c:choose> + + <div class="divider">Alert Level</div> + <c:if test="${alertLevel == 0}"> + <div class="dividerbody">No new system messages have been generated since the alert level was last reset.</div> + </c:if> + <c:if test="${alertLevel > 0}"> + <div class="dividerbody"> + The system is currently at alert level ${alertLevel} - ${alertLevelDesc} + <img style="border: 0px none; width: 20px; height: 20px;" src="${cp}/images/MarkerSysAlert${alertLevel}.png" alt="Message Level ${alertLevel}" title="Message Level ${alertLevel}"/> + </div> + </c:if> + <div class="divider">System Messages</div> + <c:if test="${systemMessageCount == 1}"> + <div class="dividerbody">There is <a href="systemmessages.jsp">${systemMessageCount} system message</a></div> + </c:if> + <c:if test="${systemMessageCount != 1}"> + <div class="dividerbody">There are <a href="systemmessages.jsp">${systemMessageCount} system messages</a></div> + </c:if> + </c:if> + </div> + <%-- -- Conflicts --%> ! <div class="section">Conflicts</div> <div class="sectionbody"> <%@ include file="/WEB-INF/jspf/m/conflictstats.jspf" %> *************** *** 195,199 **** --%> <c:if test="${!empty connectedClients and !supportsClientApiUi}"> ! <div class="section gloss">Connected Clients</div> <div class="sectionbody"> <c:forEach var="client" items="${connectedClients}"> --- 247,251 ---- --%> <c:if test="${!empty connectedClients and !supportsClientApiUi}"> ! <div class="section">Connected Clients</div> <div class="sectionbody"> <c:forEach var="client" items="${connectedClients}"> *************** *** 205,209 **** -- Video Disk Space --%> ! <div class="section gloss">Video Disk Space</div> <div class="sectionbody"> <sageglbl:GetTotalDiskspaceAvailable var="diskavailable"/> --- 257,261 ---- -- Video Disk Space --%> ! <div class="section">Video Disk Space</div> <div class="sectionbody"> <sageglbl:GetTotalDiskspaceAvailable var="diskavailable"/> *************** *** 342,346 **** -- Program Guide --%> ! <div class="section gloss">Program Guide</div> <div class="sectionbody"> <sageglbl:GetLastEPGDownloadTime var="lastEPGDownloadTimeLong"/> --- 394,398 ---- -- Program Guide --%> ! <div class="section">Program Guide</div> <div class="sectionbody"> <sageglbl:GetLastEPGDownloadTime var="lastEPGDownloadTimeLong"/> |
From: jreichen <jre...@us...> - 2011-01-18 01:41:50
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv7691/src/sagex/streaming/servlet Modified Files: HTTPLiveStreamingPlaylistServlet.java HTTPLiveStreamingSegmentServlet.java Log Message: Fix java.lang.StringIndexOutOfBoundsException: String index out of range: -1 Index: HTTPLiveStreamingSegmentServlet.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet/HTTPLiveStreamingSegmentServlet.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** HTTPLiveStreamingSegmentServlet.java 15 Jan 2011 21:15:15 -0000 1.3 --- HTTPLiveStreamingSegmentServlet.java 18 Jan 2011 01:41:40 -0000 1.4 *************** *** 23,27 **** String threadName = Thread.currentThread().getName(); int i = threadName.indexOf("/stream"); ! Thread.currentThread().setName(threadName.substring(0, i)); Log.debug("HTTPLiveStreamingSegmentServlet: Request started"); --- 23,30 ---- String threadName = Thread.currentThread().getName(); int i = threadName.indexOf("/stream"); ! if (i >= 1) // the request URL is not part of the thread name when the log level is INFO ! { ! Thread.currentThread().setName(threadName.substring(0, i)); ! } Log.debug("HTTPLiveStreamingSegmentServlet: Request started"); Index: HTTPLiveStreamingPlaylistServlet.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet/HTTPLiveStreamingPlaylistServlet.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** HTTPLiveStreamingPlaylistServlet.java 15 Jan 2011 21:13:30 -0000 1.3 --- HTTPLiveStreamingPlaylistServlet.java 18 Jan 2011 01:41:40 -0000 1.4 *************** *** 26,30 **** String threadName = Thread.currentThread().getName(); int i = threadName.indexOf("/stream"); ! Thread.currentThread().setName(threadName.substring(0, i)); Object mediaFile = super.getMediaFile(req); --- 26,33 ---- String threadName = Thread.currentThread().getName(); int i = threadName.indexOf("/stream"); ! if (i >= 1) // the request URL is not part of the thread name when the log level is INFO ! { ! Thread.currentThread().setName(threadName.substring(0, i)); ! } Object mediaFile = super.getMediaFile(req); |
From: jreichen <jre...@us...> - 2011-01-18 01:40:18
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv7015/src/sagex/streaming/httpls/playlist Modified Files: SegmentPlaylist.java Log Message: Don't Log the whole segment playlist Index: SegmentPlaylist.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist/SegmentPlaylist.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SegmentPlaylist.java 16 Jan 2011 05:04:16 -0000 1.2 --- SegmentPlaylist.java 18 Jan 2011 01:40:10 -0000 1.3 *************** *** 73,78 **** long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, i); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! Log.debug("mediaFileSegmentDurationInMillis: " + mediaFileSegmentDurationInMillis); ! Log.debug("mediaFileSegmentDurationInSeconds: " + mediaFileSegmentDurationInSeconds); int sequence = 0; --- 73,78 ---- long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, i); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! Log.debug("mediaFileSegmentDurationInMillis (" + i + "): " + mediaFileSegmentDurationInMillis); ! Log.debug("mediaFileSegmentDurationInSeconds (" + i + "): " + mediaFileSegmentDurationInSeconds); int sequence = 0; *************** *** 80,84 **** { long currentDuration = Math.min(SegmentPlaylist.TARGET_DURATION, mediaFileSegmentDurationInSeconds - j); - Log.debug("currentDuration: " + currentDuration); Segment newSegment = new Segment(currentDuration, sequence, i, showName); --- 80,83 ---- *************** *** 120,127 **** for (int i = 0; i < segmentCount; i++) { ! String str = segmentList.get(i).toString(); sb.append(str); ! if ((i == 0) || (i >= segmentCount - 1)) { Log.debug(str); --- 119,135 ---- for (int i = 0; i < segmentCount; i++) { ! Segment currentSegment = segmentList.get(i); ! Segment previousSegment = (i == 0) ? null : segmentList.get(i - 1); ! Segment nextSegment = (i == segmentCount - 1) ? null : segmentList.get(i + 1); ! String str = currentSegment.toString(); sb.append(str); ! // first or last playlist segment for each media file segment ! // printing the whole playlist makes the log harder to read ! if ((previousSegment == null) || ! (nextSegment == null) || ! (previousSegment.mediaFileSegment != currentSegment.mediaFileSegment) || ! (currentSegment.mediaFileSegment != nextSegment.mediaFileSegment) ! ) { Log.debug(str); *************** *** 160,165 **** { StringBuilder sb = new StringBuilder(); sb.append("#EXTINF:" + segmentDuration + "," + showName + "\r\n"); - Log.debug("#EXTINF:" + segmentDuration + "," + showName); String url = "/stream/HTTPLiveStreamingSegment?" + --- 168,173 ---- { StringBuilder sb = new StringBuilder(); + sb.append("#EXTINF:" + segmentDuration + "," + showName + "\r\n"); String url = "/stream/HTTPLiveStreamingSegment?" + *************** *** 170,174 **** "&MediaFileSegment=" + mediaFileSegment; sb.append(url + "\r\n"); - Log.debug(url); return sb.toString(); --- 178,181 ---- |
From: jreichen <jre...@us...> - 2011-01-18 01:39:17
|
Update of /cvsroot/sageplugins/MediaStreaming In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv6589 Modified Files: build.xml Log Message: Version 1.1.2 Index: build.xml =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/build.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** build.xml 16 Jan 2011 05:04:58 -0000 1.5 --- build.xml 18 Jan 2011 01:39:10 -0000 1.6 *************** *** 6,10 **** <property file="build.properties"/> ! <property name="plugin.version" value="1.1.1"/> <property name="src.dir" location="src"/> --- 6,10 ---- <property file="build.properties"/> ! <property name="plugin.version" value="1.1.2"/> <property name="src.dir" location="src"/> |
From: jreichen <jre...@us...> - 2011-01-18 01:38:50
|
Update of /cvsroot/sageplugins/MediaStreaming/resources/plugin In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv6329/resources/plugin Modified Files: plugin.xml Log Message: Version 1.1.2 Index: plugin.xml =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/resources/plugin/plugin.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** plugin.xml 16 Jan 2011 05:05:44 -0000 1.3 --- plugin.xml 18 Jan 2011 01:38:41 -0000 1.4 *************** *** 15,18 **** --- 15,21 ---- <ReleaseNotes> <![CDATA[ + Version 1.1.2 + 1. Fix bug in HTTP Live Streaming servlets that returns HTTP 500 and results in a crossed out play button on the video thumbnail. Attempting to start playback by clicking the thumbnail or Watch Now -> On this Page was unresponsive. + Version 1.1.1 1. Fix bug in HTTP Live Streaming playlist generation |
From: jreichen <jre...@us...> - 2011-01-17 23:48:04
|
Update of /cvsroot/sageplugins/JettyStarter In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv19231 Modified Files: changelog.txt Log Message: Version 2.2 Index: changelog.txt =================================================================== RCS file: /cvsroot/sageplugins/JettyStarter/changelog.txt,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** changelog.txt 4 Jan 2011 02:01:12 -0000 1.10 --- changelog.txt 17 Jan 2011 23:47:54 -0000 1.11 *************** *** 1,2 **** --- 1,6 ---- + 2.2.0 January 15, 2011 + - Minor apps web page formatting changes + - Add user to the 'user' role if none specified in realm.properties + - Fix displayed version of installed plugin 2.1.0 January 3, 2011 - SageTV v7-style interface for 'apps' web application (switch from blue to gray as well as other style changes) |
From: jreichen <jre...@us...> - 2011-01-16 05:05:52
|
Update of /cvsroot/sageplugins/MediaStreaming/resources/plugin In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv18151/resources/plugin Modified Files: plugin.xml Log Message: Version 1.1.1 Index: plugin.xml =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/resources/plugin/plugin.xml,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** plugin.xml 15 Jan 2011 21:28:16 -0000 1.2 --- plugin.xml 16 Jan 2011 05:05:44 -0000 1.3 *************** *** 15,18 **** --- 15,21 ---- <ReleaseNotes> <![CDATA[ + Version 1.1.1 + 1. Fix bug in HTTP Live Streaming playlist generation + Version 1.1.0 1. Increase volume on HTTP Live Streaming videos. |
From: jreichen <jre...@us...> - 2011-01-16 05:05:06
|
Update of /cvsroot/sageplugins/MediaStreaming In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv17381 Modified Files: build.xml Log Message: Version 1.1.1 Index: build.xml =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/build.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** build.xml 13 Jan 2011 01:43:50 -0000 1.4 --- build.xml 16 Jan 2011 05:04:58 -0000 1.5 *************** *** 6,10 **** <property file="build.properties"/> ! <property name="plugin.version" value="1.1.0"/> <property name="src.dir" location="src"/> --- 6,10 ---- <property file="build.properties"/> ! <property name="plugin.version" value="1.1.1"/> <property name="src.dir" location="src"/> |
From: jreichen <jre...@us...> - 2011-01-16 05:04:24
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv17220/src/sagex/streaming/httpls/playlist Modified Files: SegmentPlaylist.java Log Message: Create playlist if file is not currently recording Index: SegmentPlaylist.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist/SegmentPlaylist.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** SegmentPlaylist.java 15 Jan 2011 21:09:47 -0000 1.1 --- SegmentPlaylist.java 16 Jan 2011 05:04:16 -0000 1.2 *************** *** 28,54 **** this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); ! while (this.isFileCurrentlyRecording && segmentList.size() <= 1) { - this.segmentList.clear(); - createPlaylist(); ! ! long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, 0); ! long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! ! if (this.isFileCurrentlyRecording && (mediaFileSegmentDurationInSeconds < SegmentPlaylist.TARGET_DURATION)) { ! try ! { ! // wait until we'll have a full first segment to return ! Thread.sleep((SegmentPlaylist.TARGET_DURATION - mediaFileSegmentDurationInSeconds + 1) * 1000); ! } ! catch (InterruptedException e) { ! Log.warn(e.getMessage()); } } - - this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); } } --- 28,62 ---- this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); ! if (!this.isFileCurrentlyRecording) { createPlaylist(); ! } ! else ! { ! // retry until there's at least one full segment recorded ! while (this.isFileCurrentlyRecording && segmentList.size() <= 1) { ! this.segmentList.clear(); ! ! createPlaylist(); ! ! long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, 0); ! long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! ! if (this.isFileCurrentlyRecording && (mediaFileSegmentDurationInSeconds < SegmentPlaylist.TARGET_DURATION)) { ! try ! { ! // wait until we'll have a full first segment to return ! Thread.sleep((SegmentPlaylist.TARGET_DURATION - mediaFileSegmentDurationInSeconds + 1) * 1000); ! } ! catch (InterruptedException e) ! { ! Log.warn(e.getMessage()); ! } } + + this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); } } } *************** *** 58,61 **** --- 66,70 ---- String showName = MediaFileAPI.GetMediaTitle(mediaFile); int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); + Log.debug("Number of media file segments: " + numberOfMediaFileSegments); for (int i = 0; i < numberOfMediaFileSegments; i++) *************** *** 64,73 **** long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, i); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! int sequence = 0; for (int j = 0; j < mediaFileSegmentDurationInSeconds; j += SegmentPlaylist.TARGET_DURATION) { long currentDuration = Math.min(SegmentPlaylist.TARGET_DURATION, mediaFileSegmentDurationInSeconds - j); ! Segment newSegment = new Segment(currentDuration, sequence, i, showName); --- 73,85 ---- long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, i); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds ! Log.debug("mediaFileSegmentDurationInMillis: " + mediaFileSegmentDurationInMillis); ! Log.debug("mediaFileSegmentDurationInSeconds: " + mediaFileSegmentDurationInSeconds); ! int sequence = 0; for (int j = 0; j < mediaFileSegmentDurationInSeconds; j += SegmentPlaylist.TARGET_DURATION) { long currentDuration = Math.min(SegmentPlaylist.TARGET_DURATION, mediaFileSegmentDurationInSeconds - j); ! Log.debug("currentDuration: " + currentDuration); ! Segment newSegment = new Segment(currentDuration, sequence, i, showName); *************** *** 77,80 **** --- 89,96 ---- } } + if (segmentList != null) + { + Log.debug("segmentList size: " + segmentList.size()); + } } *************** *** 90,98 **** String showName = MediaFileAPI.GetMediaTitle(mediaFile); int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); Log.debug("Show: " + showName); Log.debug("MediaFileId: " + mediaFileId); Log.debug("Number Of MediaFile segments: " + numberOfMediaFileSegments); Log.debug("Is file currently recording: " + isFileCurrentlyRecording); ! sb.append("#EXTM3U\r\n"); Log.debug("#EXTM3U"); --- 106,116 ---- String showName = MediaFileAPI.GetMediaTitle(mediaFile); int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); + int segmentCount = (isFileCurrentlyRecording) ? segmentList.size() - 1 : segmentList.size(); Log.debug("Show: " + showName); Log.debug("MediaFileId: " + mediaFileId); Log.debug("Number Of MediaFile segments: " + numberOfMediaFileSegments); Log.debug("Is file currently recording: " + isFileCurrentlyRecording); ! Log.debug("Number of playlist segments: " + segmentCount); ! sb.append("#EXTM3U\r\n"); Log.debug("#EXTM3U"); *************** *** 100,104 **** Log.debug("#EXT-X-TARGETDURATION:" + SegmentPlaylist.TARGET_DURATION); - int segmentCount = (isFileCurrentlyRecording) ? segmentList.size() - 1 : segmentList.size(); for (int i = 0; i < segmentCount; i++) { --- 118,121 ---- |
From: jreichen <jre...@us...> - 2011-01-15 21:28:24
|
Update of /cvsroot/sageplugins/MediaStreaming/resources/plugin In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv24298/resources/plugin Modified Files: plugin.xml Log Message: Version 1.1 Index: plugin.xml =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/resources/plugin/plugin.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** plugin.xml 3 Nov 2010 03:42:29 -0000 1.1 --- plugin.xml 15 Jan 2011 21:28:16 -0000 1.2 *************** *** 3,7 **** <Name>Media Streaming Services</Name> <Identifier>mediastreaming</Identifier> ! <Description>Provides HTTP Live Streaming services to the Mobile Web UI. Used for viewing SageTV recordings on iPhone, iPod, and iPad. It can be extended by plugin developers to support other clients and audio/video formats.</Description> <Author>jreichen</Author> <CreationDate>2010.10.13</CreationDate> --- 3,7 ---- <Name>Media Streaming Services</Name> <Identifier>mediastreaming</Identifier> ! <Description>Provides HTTP Live Streaming services to the Mobile Web Interface. Used for viewing SageTV recordings on iPhone, iPod, and iPad. It can be extended by plugin developers to support other clients and audio/video formats.</Description> <Author>jreichen</Author> <CreationDate>2010.10.13</CreationDate> *************** *** 15,23 **** <ReleaseNotes> <![CDATA[ ! Linux Users: ! Currently libfaac must be installed separately. This will hopefully be fixed soon. ! ! Mac OS X Users: ! This plugin is designed to support Mac OS X. It cannot be tested until SageTV releases a Mac OS X build of v7. I don't own a SageTV Mac OS X license so I may rely on users to test it. Version 1.0.0 --- 15,27 ---- <ReleaseNotes> <![CDATA[ ! Version 1.1.0 ! 1. Increase volume on HTTP Live Streaming videos. ! 2. Create a default web page to explain that this plugin is not used directly by the user. ! 3. Use SageTV's ffmpeg for transcoding. The web streaming should now support the same files as the Sage core. Some users had reported problems with playing or seeking through avi, mkv, mpeg2, and wmv files. ! 4. Fixed problems watching shows currently being recorded. ! - Playback duration was the length of the recording when playback began ! - Playback would fail if started immediately after recording started ! 5. Added a URL to allow clients to kill transcoding processes on the server. The Mobile Web Interface does not use this API. ! 6. Added more logging detail Version 1.0.0 |
From: jreichen <jre...@us...> - 2011-01-15 21:26:12
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv23748/src/sagex/streaming/httpls/segment Modified Files: SegmenterProcess.java Log Message: - Use SageTV's ffmpeg for transcoding - Fixed problems watching shows currently being recorded - Added more logging detail Index: SegmenterProcess.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment/SegmenterProcess.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SegmenterProcess.java 5 Nov 2010 02:58:36 -0000 1.2 --- SegmenterProcess.java 15 Jan 2011 21:26:03 -0000 1.3 *************** *** 8,12 **** --- 8,14 ---- import java.io.OutputStreamWriter; import java.lang.Thread.UncaughtExceptionHandler; + import java.util.ArrayList; import java.util.HashMap; + import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; *************** *** 19,34 **** import sagex.api.MediaFileAPI; import sagex.streaming.io.SegmentInputStream; import sagex.streaming.io.StreamGobbler; - import sagex.streaming.servlet.HTTPLiveStreamingPlaylistServlet; public class SegmenterProcess implements UncaughtExceptionHandler { /** ! * The ffmepg executable used for transcoding and segmenting audio and video. */ ! private static File ffmpegFile; private static final String SEGMENTER_PARAM = "segmenter"; /** * A thread pool that allows the stream gobblers to reuse threads if available */ --- 21,44 ---- import sagex.api.MediaFileAPI; + import sagex.streaming.httpls.playlist.SegmentPlaylist; import sagex.streaming.io.SegmentInputStream; import sagex.streaming.io.StreamGobbler; public class SegmenterProcess implements UncaughtExceptionHandler { /** ! * The ffmepg executable used for transcoding audio and video. */ ! private static File transcoderFile; ! /** ! * The executable used for segmenting audio and video. ! */ ! private static File segmenterFile; private static final String SEGMENTER_PARAM = "segmenter"; /** + * The command that tells the transcoder when the input file has stopped recording + */ + private String RECORDING_STOPPED = "inactivefile\r\n"; + /** * A thread pool that allows the stream gobblers to reuse threads if available */ *************** *** 48,53 **** */ private SegmentInputStream segmentInputStream = null; ! private double currentTime = 0; ! private StreamGobbler stdoutTranscoderGobbler = null; private StreamGobbler stderrTranscoderGobbler = null; --- 58,70 ---- */ private SegmentInputStream segmentInputStream = null; ! /** ! * ! */ ! private File inputFile = null; ! private boolean isCurrentlyRecording = false; ! /** ! * Input and output streams for transcoder and segmenter processes ! */ ! private OutputStream stdinTranscoder = null; private StreamGobbler stdoutTranscoderGobbler = null; private StreamGobbler stderrTranscoderGobbler = null; *************** *** 58,62 **** * Set the location of the ffmpeg executable when the web app starts */ ! public static void setProcessLocation(File f) { if (!f.exists()) --- 75,79 ---- * Set the location of the ffmpeg executable when the web app starts */ ! public static void setTranscoderProcessLocation(File f) { if (!f.exists()) *************** *** 65,70 **** } ! Log.info("SegmenterProcess for HTTPLS web streaming is " + f.getAbsolutePath()); ! ffmpegFile = f; } --- 82,101 ---- } ! Log.info("SegmenterProcess transcoder for HTTPLS web streaming is " + f.getAbsolutePath()); ! transcoderFile = f; ! } ! ! /** ! * Set the location of the ffmpeg executable when the web app starts ! */ ! public static void setSegmenterProcessLocation(File f) ! { ! if (!f.exists()) ! { ! throw new IllegalArgumentException("File does not exist."); ! } ! ! Log.info("SegmenterProcess segmenter for HTTPLS web streaming is " + f.getAbsolutePath()); ! segmenterFile = f; } *************** *** 77,82 **** try { double startTime = sequenceToStartTime(sequence); - currentTime = startTime; // get builders for the transcoding and segmenting processes --- 108,114 ---- try { + this.inputFile = inputFile; + double startTime = sequenceToStartTime(sequence); // get builders for the transcoding and segmenting processes *************** *** 88,91 **** --- 120,126 ---- segmenterProcess = segmenterProcessBuilder.start(); + // tell the transcoder if and when recording has stopped + stdinTranscoder = transcoderProcess.getOutputStream(); + // copy the transcoder's a/v output to the segmenter // if this gobbler exits, streaming cannot continue so the streams should be closed *************** *** 116,120 **** interrupt(stderrTranscoderGobbler); - Log.debug("SegmenterProcess: stop transcoder process"); if (transcoderProcess != null) { --- 151,154 ---- *************** *** 127,130 **** --- 161,165 ---- { // process has not terminated + Log.debug("SegmenterProcess: stop transcoder process"); OutputStream os = transcoderProcess.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os); *************** *** 193,202 **** // reset variables - currentTime = 0; - transcoderProcess = null; segmenterProcess = null; segmentInputStream = null; stdoutTranscoderGobbler = null; stderrTranscoderGobbler = null; --- 228,236 ---- // reset variables transcoderProcess = null; segmenterProcess = null; segmentInputStream = null; + stdinTranscoder = null; stdoutTranscoderGobbler = null; stderrTranscoderGobbler = null; *************** *** 252,256 **** public void streamNextSegment(OutputStream os) throws Exception { ! currentTime += HTTPLiveStreamingPlaylistServlet.TARGET_DURATION; try --- 286,307 ---- public void streamNextSegment(OutputStream os) throws Exception { ! if (isCurrentlyRecording) ! { ! // TODO move to getNextSegmentLength ! Object mediaFile = MediaFileAPI.GetMediaFileForFilePath(inputFile); ! isCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); ! ! if (isCurrentlyRecording) ! { ! Log.debug("inputFile " + inputFile.getName() + " is still recording"); ! } ! else ! { ! Log.debug("inputFile " + inputFile.getName() + " has finished recording. Sending message to transcoder"); ! stdinTranscoder.write(RECORDING_STOPPED.getBytes("US-ASCII")); ! stdinTranscoder.flush(); ! } ! } ! try *************** *** 297,300 **** --- 348,352 ---- Log.debug("Killing transcoder process"); stopProcess(); + // TODO not necessarily throw new Exception("SegmenterProcess: segmenter unexpectedly exited"); } *************** *** 317,332 **** private ProcessBuilder getTranscodeProcessBuilder(File inputFile, String userAgent, String quality, double startTime) { ! Object mediaFile = MediaFileAPI.GetMediaFileForFilePath(inputFile); ! String aspect = MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Video.Aspect"); // String framerate = MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Video.FPS"); ! Integer numAudioStreams = Integer.parseInt(MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Audio.NumStreams")); ! ! Log.debug("numAudioStreams " + numAudioStreams); ! ! for (int i = 0; i < numAudioStreams; i++) ! { ! Integer streamIndex = Integer.parseInt(MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Audio." + i + ".Index")); ! Log.debug("Audio Stream " + i + ", Index = " + streamIndex); ! } Map<String, String[]> qualityMap = new HashMap<String, String[]>(); --- 369,384 ---- private ProcessBuilder getTranscodeProcessBuilder(File inputFile, String userAgent, String quality, double startTime) { ! // Object mediaFile = MediaFileAPI.GetMediaFileForFilePath(inputFile); ! // String aspect = MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Video.Aspect"); // String framerate = MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Video.FPS"); ! // Integer numAudioStreams = Integer.parseInt(MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Audio.NumStreams")); ! // ! // Log.debug("numAudioStreams " + numAudioStreams); ! // ! // for (int i = 0; i < numAudioStreams; i++) ! // { ! // Integer streamIndex = Integer.parseInt(MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Audio." + i + ".Index")); ! // Log.debug("Audio Stream " + i + ", Index = " + streamIndex); ! // } Map<String, String[]> qualityMap = new HashMap<String, String[]>(); *************** *** 384,443 **** } - String cmd = ffmpegFile.getAbsolutePath(); - ProcessBuilder pb = new ProcessBuilder(); ! pb.command(cmd, ! // "--conversion-id", "A", ! // "--port-number", "46631", ! "-threads", Integer.toString(Runtime.getRuntime().availableProcessors()),//"4", ! "-flags2", "+fast", ! "-flags", "+loop", ! "-g", "30", ! "-keyint_min", "1", ! "-bf", "0", ! "-b_strategy", "0", ! "-flags2", ! "-wpred-dct8x8", ! "-cmp", "+chroma", ! "-deblockalpha", "0", ! "-deblockbeta", "0", ! "-refs", "1", ! "-coder", "0", ! "-me_range", "16", ! "-subq", "5", ! "-partitions", "+parti4x4+parti8x8+partp8x8", ! "-trellis", "0", ! "-sc_threshold", "40", ! "-i_qfactor", "0.71", ! "-qcomp", "0.6", ! // "-map", "0.0:0.0", ! // "-map", "0.1:0.1", ! // "-map", "0.1:0.0", ! // "-map", "0.0:0.1", ! "-ss", Double.toString(startTime), ! "-i", inputFile.getAbsolutePath(), ! // "-cropleft", "0", ! // "-cropright", "0", ! // "-croptop", "0", ! // "-cropbottom", "0", ! "-s", currentQuality[0], ! "-aspect", aspect, ! "-y", ! "-f", "mpegts", ! "-async", "1", ! "-vcodec", "libx264", ! "-level", "30", ! "-bufsize", "512k", ! "-b", currentQuality[1], ! "-bt", currentQuality[2], ! "-qmax", "48", ! "-qmin", "2", ! "-r", "29.97", ! // "-acodec", "libmp3lame", ! "-acodec", "libfaac", ! "-ab", currentQuality[4], ! "-ar", currentQuality[5], ! "-ac", "2", ! "-"); return pb; } --- 436,441 ---- } ProcessBuilder pb = new ProcessBuilder(); ! pb.command(getTranscoderParams(inputFile, startTime, currentQuality)); return pb; } *************** *** 446,456 **** { ProcessBuilder pb = new ProcessBuilder(); ! pb.command(ffmpegFile.getPath(), SEGMENTER_PARAM, ! Integer.toString(HTTPLiveStreamingPlaylistServlet.TARGET_DURATION), Long.toString(sequence)); return pb; } private long parseSequence(String sequence) { --- 444,526 ---- { ProcessBuilder pb = new ProcessBuilder(); ! pb.command(segmenterFile.getPath(), SEGMENTER_PARAM, ! Integer.toString(SegmentPlaylist.TARGET_DURATION), Long.toString(sequence)); return pb; } + private List<String> getTranscoderParams(File inputFile, double startTime, String[] currentQuality) + { + List<String> params = new ArrayList<String>(); + + Object mediaFile = MediaFileAPI.GetMediaFileForFilePath(inputFile); + String aspect = MediaFileAPI.GetMediaFileMetadata(mediaFile, "Format.Video.Aspect"); + isCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); + + String cmd = transcoderFile.getAbsolutePath(); + + ProcessBuilder pb = new ProcessBuilder(); + params.add(cmd); + if (isCurrentlyRecording) + { + params.add("-activefile"); + params.add("-stdinctrl"); + } + params.add("-threads"); params.add(Integer.toString(Runtime.getRuntime().availableProcessors()));//"4", + params.add("-flags2"); params.add("+fast"); + params.add("-flags"); params.add("+loop"); + params.add("-g"); params.add("30"); + params.add("-keyint_min"); params.add("1"); + params.add("-bf"); params.add("0"); + params.add("-b_strategy"); params.add("0"); + params.add("-flags2"); + params.add("-wpred-dct8x8"); + params.add("-cmp"); params.add("+chroma"); + params.add("-deblockalpha"); params.add("0"); + params.add("-deblockbeta"); params.add("0"); + params.add("-refs"); params.add("1"); + params.add("-coder"); params.add("0"); + params.add("-me_range"); params.add("16"); + params.add("-subq"); params.add("5"); + params.add("-partitions"); params.add("+parti4x4+parti8x8+partp8x8"); + params.add("-trellis"); params.add("0"); + params.add("-sc_threshold"); params.add("40"); + params.add("-i_qfactor"); params.add("0.71"); + params.add("-qcomp"); params.add("0.6"); + // "-map", "0.0:0.0", + // "-map", "0.1:0.1", + // "-map", "0.1:0.0", + // "-map", "0.0:0.1", + params.add("-ss"); params.add(Double.toString(startTime)); + params.add("-i"); params.add(inputFile.getAbsolutePath()); + // "-cropleft", "0", + // "-cropright", "0", + // "-croptop", "0", + // "-cropbottom", "0", + params.add("-s"); params.add(currentQuality[0]); + params.add("-aspect"); params.add(aspect); + params.add("-y"); + params.add("-f"); params.add("mpegts"); + params.add("-async"); params.add("1"); + params.add("-vcodec"); params.add("libx264"); + params.add("-level"); params.add("30"); + params.add("-bufsize"); params.add("512k"); + params.add("-b"); params.add(currentQuality[1]); + params.add("-bt"); params.add(currentQuality[2]); + params.add("-qmax"); params.add("48"); + params.add("-qmin"); params.add("2"); + params.add("-r"); params.add("29.97"); + // "-acodec", "libmp3lame", + params.add("-vol"); params.add("1024"); + params.add("-acodec"); params.add("libfaac"); + params.add("-ab"); params.add(currentQuality[4]); + params.add("-ar"); params.add(currentQuality[5]); + params.add("-ac"); params.add("2"); + params.add("-"); + + return params; + } + private long parseSequence(String sequence) { *************** *** 480,493 **** private double sequenceToStartTime(long sequence) { ! return sequence * HTTPLiveStreamingPlaylistServlet.TARGET_DURATION; } public static void main(String[] args) throws IOException { ! setProcessLocation(new File("bin/linux32/ffmpeg")); File f = new File("/home/jreichen/Seinfeld-TheSoupNazi-9012674-0.mp4"); File fin = new File("/home/jreichen/Seinfeld-TheSoupNazi-9012674-0.mpegts"); File fout = new File("/home/jreichen/segmenter.mpegts"); ! System.out.println(ffmpegFile.getAbsolutePath()); SegmenterProcess sp = new SegmenterProcess(); --- 550,563 ---- private double sequenceToStartTime(long sequence) { ! return sequence * SegmentPlaylist.TARGET_DURATION; } public static void main(String[] args) throws IOException { ! setTranscoderProcessLocation(new File("bin/linux32/ffmpeg")); File f = new File("/home/jreichen/Seinfeld-TheSoupNazi-9012674-0.mp4"); File fin = new File("/home/jreichen/Seinfeld-TheSoupNazi-9012674-0.mpegts"); File fout = new File("/home/jreichen/segmenter.mpegts"); ! System.out.println(transcoderFile.getAbsolutePath()); SegmenterProcess sp = new SegmenterProcess(); |
From: jreichen <jre...@us...> - 2011-01-15 21:15:25
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv20907/src/sagex/streaming/servlet Modified Files: HTTPLiveStreamingSegmentServlet.java Log Message: - Added a URL to allow clients to kill transcoding processes on the server - Added more logging detail - Refactored playlist generation code Index: HTTPLiveStreamingSegmentServlet.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet/HTTPLiveStreamingSegmentServlet.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** HTTPLiveStreamingSegmentServlet.java 5 Nov 2010 02:58:36 -0000 1.2 --- HTTPLiveStreamingSegmentServlet.java 15 Jan 2011 21:15:15 -0000 1.3 *************** *** 1,5 **** package sagex.streaming.servlet; - import java.io.IOException; import java.util.Enumeration; --- 1,4 ---- *************** *** 21,24 **** --- 20,28 ---- throws Exception { + // remove servlet URL from thread name so the SageTV log is easier to read + String threadName = Thread.currentThread().getName(); + int i = threadName.indexOf("/stream"); + Thread.currentThread().setName(threadName.substring(0, i)); + Log.debug("HTTPLiveStreamingSegmentServlet: Request started"); Object mediaFile = super.getMediaFile(req); *************** *** 48,66 **** if (range != null && range.equals("bytes=0-1".trim())) { - // System.out.println("Writing 2 bytessss"); - // resp.setStatus(416); // Range not satisfiable resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); - // resp.sendRedirect("/sagem/m/TranscodedMediaFile"); - // resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - // resp.setHeader("location", "http://friesen.homelinux.com:8080/sagem/m/TranscodedMediaFile"); - // resp.setHeader("Location", "http://friesen.homelinux.com:8080/sagem/m/TranscodedMediaFile"); - // resp.setHeader("Content-Location", "http://friesen.homelinux.com:8080/sagem/m/TranscodedMediaFile"); - // resp.setHeader("Content-Type", "text/html"); - // resp.setContentType(getServletContext().getMimeType(file.getAbsolutePath())); - // resp.setHeader("Content-Length", "0"); - // resp.setHeader("Content-Range", "0-1/*"); - // resp.setHeader("Content-Range", "bytes 0-1/2"); resp.setHeader("Content-Range", "bytes 0-1/2000000"); - // resp.setHeader("Content-Range", "bytes 0-1/" + sp.getNextSegmentLength()); resp.setHeader("Content-Length", "2"); resp.getOutputStream().write(0); --- 52,57 ---- *************** *** 77,81 **** return; } ! String sequenceString = req.getParameter("Sequence"); String qualityString = req.getParameter("Quality"); --- 68,104 ---- return; } ! ! // look for command to stop transcoder and segmenter ! String commandString = req.getParameter("Command"); ! if (commandString != null) ! { ! if (commandString.toLowerCase().equals("stop")) ! { ! ServletContext sc = getServletContext(); ! SegmentManager sm = (SegmentManager) sc.getAttribute(AppContextListener.SEGMENT_MANAGER_ATTRIBUTE_NAME); ! SegmentProducer segmentProducer = null; ! ! synchronized (sm) ! { ! segmentProducer = sm.removeSegmentProducer(conversionId); ! ! if (segmentProducer != null) ! { ! synchronized (segmentProducer) ! { ! Log.debug("Client has sent a command to stop the transcoding for conversion id " + conversionId); ! segmentProducer.stop(); ! } ! } ! } ! } ! else ! { ! Log.info("Invalid command request parameter"); ! resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); ! } ! return; // don't go any further if a command string was sent ! } ! String sequenceString = req.getParameter("Sequence"); String qualityString = req.getParameter("Quality"); *************** *** 133,141 **** resp.setStatus(HttpServletResponse.SC_OK); - // resp.setContentType(getServletContext().getMimeType(file.getAbsolutePath())); - // resp.setContentType("video/mp4"); resp.setContentType("video/MP2T"); - - // resp.setHeader("Content-Length", String.valueOf(sp.getNextSegmentLength()/*file.length()*/)); // TODO get from SegmentGobbler ServletContext sc = getServletContext(); --- 156,160 ---- *************** *** 156,190 **** synchronized (segmentProducer) { ! // TODO only call stream next segment, encapsulate the rest ! if (!segmentProducer.nextState(sequence, qualityString, mediaFileId, mediaFileSegment) /*|| (sp == null)*/) { ! try { segmentProducer.reset(); } ! catch (IOException e) ! { ! Log.info(e.getMessage()); ! Log.ignore(e); ! resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); ! return; ! } ! ! // System.out.println("HTTPLiveStreamingSegmentServlet: mime type " + getServletContext().getMimeType(f.getAbsolutePath())); } - - long len = segmentProducer.getNextSegmentLength(); - Log.debug("Content-Length: " + len); - resp.setHeader("Content-Length", Long.toString(len)); - segmentProducer.streamNextSegment(resp.getOutputStream()); } } resp.flushBuffer(); Log.debug("Request ended"); } // choose transcoder // transcode file // use time range - // return mime type video/MP2T - } --- 175,207 ---- synchronized (segmentProducer) { ! try { ! // TODO only call stream next segment, encapsulate the rest ! if (!segmentProducer.nextState(sequence, qualityString, mediaFileId, mediaFileSegment) /*|| (sp == null)*/) { segmentProducer.reset(); } ! ! long len = segmentProducer.getNextSegmentLength(); ! Log.debug("Content-Length: " + len); ! resp.setHeader("Content-Length", Long.toString(len)); ! segmentProducer.streamNextSegment(resp.getOutputStream()); ! } ! catch (Throwable t) ! { ! // explicitly print the stack trace here at any log level to try to help fix bugs ! Log.warn(t.getMessage(), t); ! // Error on the following line: Response already committed ! //resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); ! return; } } } resp.flushBuffer(); Log.debug("Request ended"); + Thread.currentThread().setName(threadName); } // choose transcoder // transcode file // use time range } |
From: jreichen <jre...@us...> - 2011-01-15 21:13:38
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv19998/src/sagex/streaming/servlet Modified Files: HTTPLiveStreamingPlaylistServlet.java Log Message: - Added more logging detail - Refactored playlist generation code Index: HTTPLiveStreamingPlaylistServlet.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/servlet/HTTPLiveStreamingPlaylistServlet.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** HTTPLiveStreamingPlaylistServlet.java 5 Nov 2010 02:58:36 -0000 1.2 --- HTTPLiveStreamingPlaylistServlet.java 15 Jan 2011 21:13:30 -0000 1.3 *************** *** 2,6 **** import java.util.Enumeration; - import java.util.UUID; import javax.servlet.http.HttpServletRequest; --- 2,5 ---- *************** *** 10,20 **** import sagex.api.MediaFileAPI; @SuppressWarnings("serial") public class HTTPLiveStreamingPlaylistServlet extends SageServlet { - public static final int TARGET_DURATION = 10; - private static String[] VARIANT_PLAYLIST_BITRATES = {"150", "1240", "840", "640", "440", "240"}; - public HTTPLiveStreamingPlaylistServlet() { --- 9,18 ---- import sagex.api.MediaFileAPI; + import sagex.streaming.httpls.playlist.SegmentPlaylist; + import sagex.streaming.httpls.playlist.VariantPlaylist; @SuppressWarnings("serial") public class HTTPLiveStreamingPlaylistServlet extends SageServlet { public HTTPLiveStreamingPlaylistServlet() { *************** *** 25,28 **** --- 23,31 ---- throws Exception { + // remove servlet URL from thread name so the SageTV log is easier to read + String threadName = Thread.currentThread().getName(); + int i = threadName.indexOf("/stream"); + Thread.currentThread().setName(threadName.substring(0, i)); + Object mediaFile = super.getMediaFile(req); if (mediaFile == null) *************** *** 30,33 **** --- 33,37 ---- throw new IllegalArgumentException("No MediaFileID passed"); } + int mediaFileId = MediaFileAPI.GetMediaFileID(mediaFile); Log.debug("----------- HTTPLiveStreamingPlaylistServlet begin request Headers ---------------"); *************** *** 44,47 **** --- 48,52 ---- Log.debug("----------- HTTPLiveStreamingPlaylistServlet end request Headers ---------------"); + // Servers that are constrained for compatibility can serve files ending in .m3u with MIME type audio/mpegURL // resp.setContentType("application/x-mpegURL"); resp.setContentType("application/vnd.apple.mpegurl"); *************** *** 50,62 **** String conversionId = req.getParameter("ConversionId"); String playlist = ""; if (conversionId == null) { ! playlist = createVariantPlaylist(req); } else { ! playlist = createSegmentPlaylist(req); } --- 55,68 ---- String conversionId = req.getParameter("ConversionId"); + String quality = req.getParameter("Quality"); String playlist = ""; if (conversionId == null) { ! playlist = new VariantPlaylist(mediaFileId).toString(); } else { ! playlist = new SegmentPlaylist(mediaFile, conversionId, quality).toString(); } *************** *** 84,222 **** catch (Exception e) { ! Log.info(e.getMessage()); ! Log.ignore(e); resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { ! Log.debug("Chars: " + playlist.length() + ", Bytes: " + playlistBytes.length); ! } ! } ! ! private String createVariantPlaylist(HttpServletRequest req) ! { ! Object mediaFile = super.getMediaFile(req); ! if (mediaFile == null) ! { ! throw new IllegalArgumentException("No MediaFileID passed"); ! } ! int mediaFileId = MediaFileAPI.GetMediaFileID(mediaFile); ! ! StringBuilder sb = new StringBuilder(); ! ! String url = null; ! String conversionId = UUID.randomUUID().toString(); ! ! // Header ! sb.append("#EXTM3U\r\n"); ! Log.debug("#EXTM3U\r\n"); ! ! for (String bitrate : VARIANT_PLAYLIST_BITRATES) ! { ! sb.append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate + "000\r\n"); ! Log.debug("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate + "000\r\n"); ! ! url = ("/stream/HTTPLiveStreamingPlaylist?" + ! "MediaFileId=" + mediaFileId + ! "&ConversionId=" + conversionId + ! "&Quality=" + bitrate + ! "\r\n"); ! sb.append(url); ! Log.debug(url); ! } ! ! return sb.toString(); ! ! // #EXTM3U ! // #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000 ! // gear1/prog_index.m3u8 ! // #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111 ! // gear2/prog_index.m3u8 ! // #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444 ! // gear3/prog_index.m3u8 ! // #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=737777 ! // gear4/prog_index.m3u8 ! ! } ! ! private String createSegmentPlaylist(HttpServletRequest req) ! { ! Object mediaFile = super.getMediaFile(req); ! if (mediaFile == null) ! { ! throw new IllegalArgumentException("No MediaFileID passed"); ! } ! ! String conversionId = req.getParameter("ConversionId"); ! String quality = req.getParameter("Quality"); ! ! String showName = MediaFileAPI.GetMediaTitle(mediaFile); ! int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); ! boolean isRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); ! ! StringBuilder sb = new StringBuilder(); ! ! Log.debug("MediaFileId = " + req.getParameter("MediaFileId")); ! Log.debug("numberOfMediaFileSegments = " + numberOfMediaFileSegments); ! Log.debug("showName = " + showName); ! ! sb.append("#EXTM3U\r\n"); ! Log.debug("#EXTM3U\r\n"); ! ! sb.append("#EXT-X-TARGETDURATION:" + TARGET_DURATION + "\r\n"); ! Log.debug("#EXT-X-TARGETDURATION:" + TARGET_DURATION + "\r\n"); ! ! // sb.append("#EXT-X-MEDIA-SEQUENCE:0\r\n"); ! // Log.debug("#EXT-X-MEDIA-SEQUENCE:0\r\n"); ! ! for (int currentMediaFileSegment = 0; currentMediaFileSegment < numberOfMediaFileSegments; currentMediaFileSegment++) ! { ! // milliseconds ! long mediaFileSegmentDuration = MediaFileAPI.GetDurationForSegment(mediaFile, currentMediaFileSegment); ! Log.debug("segmentDuration = " + mediaFileSegmentDuration); ! mediaFileSegmentDuration = mediaFileSegmentDuration / 1000; // milliseconds to seconds ! int sequence = 0; // httpls segment sequence number ! for (int i = 0; i < mediaFileSegmentDuration; i += TARGET_DURATION) ! { ! long currentDuration = Math.min(TARGET_DURATION, mediaFileSegmentDuration - i); ! ! sb.append("#EXTINF:" + currentDuration + "," + showName + "\r\n"); ! Log.debug("#EXTINF:" + currentDuration + "," + showName + "\r\n"); ! ! // each segment has header and that causes problems with iphone ! ! // start frame hh:mm:ss:ff ! // hh:mm:ss:00 ! ! // duration hh:mm:ss:ff ! // 00:00:10:00 ! ! // sb.append("/sagem/m/TranscodedHTTPLiveStreamingMediaFile?s=" + i + "&d=" + currentDuration + "&MediaFileId=" + req.getParameter("MediaFileId") + "\r\n"); ! // System.out.print("/sagem/m/TranscodedHTTPLiveStreamingMediaFile?s=" + i + "&d=" + currentDuration + "&MediaFileId=" + req.getParameter("MediaFileId") + "\r\n"); ! String url = "/stream/HTTPLiveStreamingSegment?" + ! "Sequence=" + sequence + ! "&MediaFileId=" + req.getParameter("MediaFileId") + ! "&ConversionId=" + conversionId + ! "&Quality=" + quality + ! "&MediaFileSegment=" + currentMediaFileSegment + ! "\r\n"; ! sb.append(url); ! System.out.print(url); ! sequence++; ! } ! } ! ! // #EXT-X-MEDIA-SEQUENCE:<number> ! // #EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ> ! // #EXT-X-ALLOW-CACHE:<YES|NO> ! // #EXT-X-STREAM-INF ! ! if (!isRecording) ! { ! sb.append("#EXT-X-ENDLIST\r\n"); ! Log.debug("#EXT-X-ENDLIST\r\n"); } - - return sb.toString(); } } --- 90,101 ---- catch (Exception e) { ! Log.warn(e.getMessage(), e); resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { ! Log.debug("Playlist Chars: " + playlist.length() + ", Bytes: " + playlistBytes.length); ! Thread.currentThread().setName(threadName); } } } |
From: jreichen <jre...@us...> - 2011-01-15 21:11:20
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv19275/src/sagex/streaming/httpls/segment Modified Files: SegmentManager.java Log Message: - Added a URL to allow clients to kill transcoding processes on the server - Added more logging detail Index: SegmentManager.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment/SegmentManager.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SegmentManager.java 5 Nov 2010 02:58:36 -0000 1.2 --- SegmentManager.java 15 Jan 2011 21:11:13 -0000 1.3 *************** *** 20,23 **** --- 20,24 ---- { private Map<String, SegmentProducer> segmentProducerMap = new LinkedHashMap<String, SegmentProducer>(); + private List<String> oldSegmentProducerList = new ArrayList<String>(); // TODO determine when the last segment has been sent private int currentIndex; *************** *** 26,29 **** --- 27,35 ---- public void addSegmentProducer(String conversionId, SegmentProducer segmentProducer) { + if (oldSegmentProducerList.contains(conversionId)) + { + Log.warn("SegmentManager.addSegmentProducer() Conversion Id is being reused."); + } + if (segmentProducerMap.containsKey(conversionId)) { *************** *** 33,43 **** segmentProducerMap.put(conversionId, segmentProducer); ! synchronized (this) { ! if (timer == null) ! { ! timer = new Timer("ffmpeg cleanup timer"); ! timer.schedule(new CleanupTask(), 5 * 60 * 1000, 1 * 60 * 1000); ! } } } --- 39,46 ---- segmentProducerMap.put(conversionId, segmentProducer); ! if (timer == null) { ! timer = new Timer("ffmpeg cleanup timer"); ! timer.schedule(new CleanupTask(), 5 * 60 * 1000, 1 * 60 * 1000); } } *************** *** 45,48 **** --- 48,56 ---- public SegmentProducer getSegmentProducer(String conversionId) { + if (oldSegmentProducerList.contains(conversionId)) + { + Log.warn("SegmentManager.getSegmentProducer() Conversion Id is being reused."); + } + SegmentProducer segmentProducer = segmentProducerMap.get(conversionId); *************** *** 57,65 **** } ! public List<SegmentProducer> removeSegmentProducers() { ! synchronized (this) { ! if (timer != null) { timer.cancel(); --- 65,78 ---- } ! public SegmentProducer removeSegmentProducer(String conversionId) { ! SegmentProducer segmentProducer = getSegmentProducer(conversionId); ! ! if (segmentProducer != null) { ! oldSegmentProducerList.add(conversionId); ! segmentProducerMap.remove(conversionId); ! ! if ((timer != null) && (segmentProducerMap.size() == 0)) { timer.cancel(); *************** *** 67,71 **** --- 80,97 ---- } } + + return segmentProducer; + } + + public List<SegmentProducer> removeSegmentProducers() + { + if (timer != null) + { + timer.cancel(); + timer = null; + } + List<SegmentProducer> segmentProducers = getSegmentProducers(); + oldSegmentProducerList.addAll(segmentProducerMap.keySet()); segmentProducerMap.clear(); return segmentProducers; *************** *** 93,99 **** synchronized (currentSegmentProducer) { - Log.debug("Segment Producer has been inactive for " + (now - currentSegmentProducer.getLastActivity()) / 1000 + " seconds"); if (now - currentSegmentProducer.getLastActivity() > 5 * 60 * 1000) // 5 minutes { try { --- 119,125 ---- synchronized (currentSegmentProducer) { if (now - currentSegmentProducer.getLastActivity() > 5 * 60 * 1000) // 5 minutes { + Log.debug("Segment Producer has been inactive for " + (now - currentSegmentProducer.getLastActivity()) / 1000 + " seconds. Removing producer."); try { *************** *** 106,112 **** --- 132,143 ---- } Log.debug("Map size before remove: " + segmentProducerMap.size()); + oldSegmentProducerList.add(currentEntry.getKey()); mapIterator.remove(); Log.debug("Map size after remove: " + segmentProducerMap.size()); } + else + { + Log.debug("Segment Producer has been inactive for " + (now - currentSegmentProducer.getLastActivity()) / 1000 + " seconds"); + } } } |
From: jreichen <jre...@us...> - 2011-01-15 21:09:55
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv18238/src/sagex/streaming/httpls/playlist Added Files: SegmentPlaylist.java VariantPlaylist.java Log Message: - Fixed problems watching shows currently being recorded - Refactored playlist generation code --- NEW FILE: VariantPlaylist.java --- package sagex.streaming.httpls.playlist; import java.util.UUID; import org.mortbay.log.Log; public class VariantPlaylist { public static String[] VARIANT_PLAYLIST_BITRATES = {"150", "1240", "840", "640", "440", "240"}; private int mediaFileId; private String playlist; public VariantPlaylist(int mediaFileId) { this.mediaFileId = mediaFileId; this.playlist = createPlaylist(); } private String createPlaylist() { StringBuilder sb = new StringBuilder(); String url = null; String conversionId = UUID.randomUUID().toString(); // Header sb.append("#EXTM3U\r\n"); Log.debug("#EXTM3U"); // Body for (String bitrate : VARIANT_PLAYLIST_BITRATES) { sb.append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate + "000\r\n"); Log.debug("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate + "000"); url = "/stream/HTTPLiveStreamingPlaylist?" + "MediaFileId=" + mediaFileId + "&ConversionId=" + conversionId + "&Quality=" + bitrate; sb.append(url + "\r\n"); Log.debug(url); } return sb.toString(); } public String toString() { return this.playlist; } } --- NEW FILE: SegmentPlaylist.java --- package sagex.streaming.httpls.playlist; import java.util.ArrayList; import java.util.List; import org.mortbay.log.Log; import sagex.api.MediaFileAPI; public class SegmentPlaylist { public static final int TARGET_DURATION = 10; private Object mediaFile; private int mediaFileId; private List<Segment> segmentList; private String conversionId; private String quality; private boolean isFileCurrentlyRecording; public SegmentPlaylist(Object mediaFile, String conversionId, String quality) { this.mediaFile = mediaFile; this.mediaFileId = MediaFileAPI.GetMediaFileID(mediaFile); this.segmentList = new ArrayList<Segment>(); this.conversionId = conversionId; this.quality = quality; this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); while (this.isFileCurrentlyRecording && segmentList.size() <= 1) { this.segmentList.clear(); createPlaylist(); long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, 0); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds if (this.isFileCurrentlyRecording && (mediaFileSegmentDurationInSeconds < SegmentPlaylist.TARGET_DURATION)) { try { // wait until we'll have a full first segment to return Thread.sleep((SegmentPlaylist.TARGET_DURATION - mediaFileSegmentDurationInSeconds + 1) * 1000); } catch (InterruptedException e) { Log.warn(e.getMessage()); } } this.isFileCurrentlyRecording = MediaFileAPI.IsFileCurrentlyRecording(mediaFile); } } private void createPlaylist() { String showName = MediaFileAPI.GetMediaTitle(mediaFile); int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); for (int i = 0; i < numberOfMediaFileSegments; i++) { // get length of current media file segment long mediaFileSegmentDurationInMillis = MediaFileAPI.GetDurationForSegment(mediaFile, i); long mediaFileSegmentDurationInSeconds = mediaFileSegmentDurationInMillis / 1000; // milliseconds to seconds int sequence = 0; for (int j = 0; j < mediaFileSegmentDurationInSeconds; j += SegmentPlaylist.TARGET_DURATION) { long currentDuration = Math.min(SegmentPlaylist.TARGET_DURATION, mediaFileSegmentDurationInSeconds - j); Segment newSegment = new Segment(currentDuration, sequence, i, showName); segmentList.add(newSegment); sequence++; } } } public List<Segment> getSegments() { return segmentList; } public String toString() { StringBuilder sb = new StringBuilder(); String showName = MediaFileAPI.GetMediaTitle(mediaFile); int numberOfMediaFileSegments = MediaFileAPI.GetNumberOfSegments(mediaFile); Log.debug("Show: " + showName); Log.debug("MediaFileId: " + mediaFileId); Log.debug("Number Of MediaFile segments: " + numberOfMediaFileSegments); Log.debug("Is file currently recording: " + isFileCurrentlyRecording); sb.append("#EXTM3U\r\n"); Log.debug("#EXTM3U"); sb.append("#EXT-X-TARGETDURATION:" + TARGET_DURATION + "\r\n"); Log.debug("#EXT-X-TARGETDURATION:" + SegmentPlaylist.TARGET_DURATION); int segmentCount = (isFileCurrentlyRecording) ? segmentList.size() - 1 : segmentList.size(); for (int i = 0; i < segmentCount; i++) { String str = segmentList.get(i).toString(); sb.append(str); if ((i == 0) || (i >= segmentCount - 1)) { Log.debug(str); } } // #EXT-X-MEDIA-SEQUENCE:<number> // #EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ> // #EXT-X-ALLOW-CACHE:<YES|NO> // #EXT-X-STREAM-INF if (!isFileCurrentlyRecording) { sb.append("#EXT-X-ENDLIST\r\n"); Log.debug("#EXT-X-ENDLIST"); } return sb.toString(); } public class Segment { private long segmentDuration; private int segmentSequence; private int mediaFileSegment; private String showName; public Segment(long segmentDuration, int segmentSequence, int mediaFileSegment, String showName) { this.segmentDuration = segmentDuration; this.segmentSequence = segmentSequence; this.mediaFileSegment = mediaFileSegment; this.showName = showName; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("#EXTINF:" + segmentDuration + "," + showName + "\r\n"); Log.debug("#EXTINF:" + segmentDuration + "," + showName); String url = "/stream/HTTPLiveStreamingSegment?" + "Sequence=" + segmentSequence + "&MediaFileId=" + mediaFileId + "&ConversionId=" + conversionId + "&Quality=" + quality + "&MediaFileSegment=" + mediaFileSegment; sb.append(url + "\r\n"); Log.debug(url); return sb.toString(); } } } |
From: jreichen <jre...@us...> - 2011-01-15 21:09:51
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv18212/src/sagex/streaming/httpls/playlist Log Message: Directory /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/playlist added to the repository |
From: jreichen <jre...@us...> - 2011-01-15 21:08:02
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/listener In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv17605/src/sagex/streaming/listener Modified Files: AppContextListener.java Log Message: Use SageTV's ffmpeg for transcoding. Index: AppContextListener.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/listener/AppContextListener.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** AppContextListener.java 5 Nov 2010 02:58:36 -0000 1.2 --- AppContextListener.java 15 Jan 2011 21:07:54 -0000 1.3 *************** *** 35,87 **** // System.err.println("Stderr: starting media streaming web app"); // System.out.println("Stderr class: " + System.err.getClass()); - - String ffmpegPath = ""; - if (Global.IsLinuxOS()) - { - ffmpegPath = "/WEB-INF/bin/linux32/ffmpeg"; - } - else if (Global.IsMacOS()) - { - ffmpegPath = "/WEB-INF/bin/macos/ffmpeg"; - } - else if (Global.IsWindowsOS()) - { - ffmpegPath = "/WEB-INF/bin/win32/ffmpeg.exe"; - } - - File ffmpegFile = null; - try - { - URL ffmpegUrl = event.getServletContext().getResource(ffmpegPath); - if (ffmpegUrl != null) - { - // jump through hoops to deal with spaces in the path (mainly for Windows "Program Files" directory) - // http://weblogs.java.net/blog/2007/04/25/how-convert-javaneturl-javaiofile - try - { - // convert %20 to a space - ffmpegFile = new File(ffmpegUrl.toURI()); - } - catch (URISyntaxException e) - { - ffmpegFile = new File(ffmpegUrl.getPath()); - } - Log.debug("FFmpeg executable location: " + ffmpegFile.getAbsolutePath()); - SegmenterProcess.setProcessLocation(ffmpegFile); - } - } - catch (MalformedURLException e) - { - Log.info(e.getMessage()); - Log.ignore(e); - } - catch (IllegalArgumentException e) - { - Log.info(e.getMessage()); - Log.ignore(e); - } ! setFileExecutablePermission(ffmpegFile); ! event.getServletContext().setAttribute(SEGMENT_MANAGER_ATTRIBUTE_NAME, new SegmentManager()); } --- 35,42 ---- // System.err.println("Stderr: starting media streaming web app"); // System.out.println("Stderr class: " + System.err.getClass()); ! setTranscoderLocation(event); ! setSegmenterLocation(event); ! event.getServletContext().setAttribute(SEGMENT_MANAGER_ATTRIBUTE_NAME, new SegmentManager()); } *************** *** 120,124 **** --- 75,154 ---- } } + + private void setTranscoderLocation(ServletContextEvent event) + { + String transcoderPath = ""; + File sagetvHome = new File(System.getProperty("user.dir")); + if (Global.IsLinuxOS()) + { + transcoderPath = "ffmpeg"; + } + else if (Global.IsMacOS()) + { + transcoderPath = "ffmpeg"; + } + else if (Global.IsWindowsOS()) + { + transcoderPath = "SageTVTranscoder.exe"; + } + + File transcoderFile = new File(sagetvHome, transcoderPath); + Log.debug("HTTPLS transcoder executable location: " + transcoderFile.getAbsolutePath()); + SegmenterProcess.setTranscoderProcessLocation(transcoderFile); + } + private void setSegmenterLocation(ServletContextEvent event) + { + // the segmenter is delivered in the war file + String segmenterPath = ""; + if (Global.IsLinuxOS()) + { + segmenterPath = "/WEB-INF/bin/linux32/ffmpeg"; + } + else if (Global.IsMacOS()) + { + segmenterPath = "/WEB-INF/bin/macos/ffmpeg"; + } + else if (Global.IsWindowsOS()) + { + segmenterPath = "/WEB-INF/bin/win32/ffmpeg.exe"; + } + + File segmenterFile = null; + try + { + URL segmenterUrl = event.getServletContext().getResource(segmenterPath); + if (segmenterUrl != null) + { + // jump through hoops to deal with spaces in the path (mainly for Windows "Program Files" directory) + // http://weblogs.java.net/blog/2007/04/25/how-convert-javaneturl-javaiofile + try + { + // convert %20 to a space + segmenterFile = new File(segmenterUrl.toURI()); + } + catch (URISyntaxException e) + { + segmenterFile = new File(segmenterUrl.getPath()); + } + Log.debug("HTTPLS segmenter executable location: " + segmenterFile.getAbsolutePath()); + SegmenterProcess.setSegmenterProcessLocation(segmenterFile); + } + } + catch (MalformedURLException e) + { + Log.info(e.getMessage()); + Log.ignore(e); + } + catch (IllegalArgumentException e) + { + Log.info(e.getMessage()); + Log.ignore(e); + } + + // since this is expanded from the war file + setFileExecutablePermission(segmenterFile); + } + private void setFileExecutablePermission(File file) { |
From: jreichen <jre...@us...> - 2011-01-15 21:06:36
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/io In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv17192/src/sagex/streaming/io Modified Files: SegmentInputStream.java Log Message: Added more logging detail Index: SegmentInputStream.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/io/SegmentInputStream.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SegmentInputStream.java 5 Nov 2010 02:58:36 -0000 1.2 --- SegmentInputStream.java 15 Jan 2011 21:06:28 -0000 1.3 *************** *** 137,142 **** catch (IOException e) { ! Log.info(e.getMessage()); ! Log.ignore(e); } } --- 137,141 ---- catch (IOException e) { ! Log.warn(e.getMessage(), e); } } |
From: jreichen <jre...@us...> - 2011-01-15 21:06:02
|
Update of /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv16888/src/sagex/streaming/httpls/segment Modified Files: SegmentProducer.java Log Message: Added more logging detail Index: SegmentProducer.java =================================================================== RCS file: /cvsroot/sageplugins/MediaStreaming/src/sagex/streaming/httpls/segment/SegmentProducer.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SegmentProducer.java 5 Nov 2010 02:58:36 -0000 1.2 --- SegmentProducer.java 15 Jan 2011 21:05:53 -0000 1.3 *************** *** 84,89 **** catch (Throwable t) { ! Log.info(t.getMessage()); ! Log.ignore(t); this.state.reset(); } --- 84,88 ---- catch (Throwable t) { ! Log.warn(t.getMessage(), t); this.state.reset(); } |
From: jreichen <jre...@us...> - 2011-01-14 05:41:04
|
Update of /cvsroot/sageplugins/JettyStarter/resources/plugin In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv20522/resources/plugin Modified Files: plugin.xml Log Message: Version 2.2 Index: plugin.xml =================================================================== RCS file: /cvsroot/sageplugins/JettyStarter/resources/plugin/plugin.xml,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** plugin.xml 4 Jan 2011 04:01:32 -0000 1.8 --- plugin.xml 14 Jan 2011 05:40:56 -0000 1.9 *************** *** 24,27 **** --- 24,32 ---- <ReleaseNotes> <![CDATA[ + Version 2.2.0 + 1. Minor apps web page formatting changes + 2. Add user to the 'user' role if none specified in realm.properties + 3. Fix displayed version of installed plugin + Version 2.1.0 1. SageTV v7-style interface for 'apps' web application (switch from blue to gray as well as other style changes) |
From: jreichen <jre...@us...> - 2011-01-14 05:41:04
|
Update of /cvsroot/sageplugins/JettyStarter In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv20522 Modified Files: build.xml Log Message: Version 2.2 Index: build.xml =================================================================== RCS file: /cvsroot/sageplugins/JettyStarter/build.xml,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** build.xml 4 Jan 2011 02:01:12 -0000 1.11 --- build.xml 14 Jan 2011 05:40:56 -0000 1.12 *************** *** 6,10 **** <property file="build.properties"/> ! <property name="plugin.version" value="2.1.0"/> <property name="src.dir" location="src"/> --- 6,10 ---- <property file="build.properties"/> ! <property name="plugin.version" value="2.2.0"/> <property name="src.dir" location="src"/> |
From: jreichen <jre...@us...> - 2011-01-14 05:39:11
|
Update of /cvsroot/sageplugins/JettyStarter/extlib In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv19638/extlib Added Files: sagex-api.jar Removed Files: sagex-api-7.0.7.0.jar Log Message: Update sagex-api.jar --- sagex-api-7.0.7.0.jar DELETED --- --- NEW FILE: sagex-api.jar --- (This appears to be a binary file; contents omitted.) |