[ 
http://opencast.jira.com/browse/MH-3708?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=30365#comment-30365
 ] 

Greg Logan commented on MH-3708:
--------------------------------

Per 
http://opencast.3480289.n2.nabble.com/JIRA-Ticket-Cleanup-proposal-td7475080.html,
 this has been bulk resolved as won't fix. If this is still important to you 
please reopen and we can triage as appropriate.
                
> It would be nice to be able to seek in lectures without a streaming server or 
> using progressive download
> --------------------------------------------------------------------------------------------------------
>
>                 Key: MH-3708
>                 URL: http://opencast.jira.com/browse/MH-3708
>             Project: Matterhorn Project
>          Issue Type: Community Feature Request
>          Components: Architecture & Services, Engage Tools
>    Affects Versions: None
>            Reporter: Christopher Brooks
>            Priority: Minor
>             Fix For: None
>
>
> This can be done using flvtool to inject metadata into the flv giving byte 
> offset headers.  This would need to be added to the workflow after the flv 
> creation.  Here is some java code (servlet) that then allows for the 
> navigation using a get parameter indicating the byte offset the client is 
> requesting:
> package ca.recollect.player;
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.IOException;
> import java.io.OutputStream;
> import java.sql.Connection;
> import java.sql.DriverManager;
> import java.sql.PreparedStatement;
> import java.sql.SQLException;
> import java.util.concurrent.ConcurrentLinkedQueue;
> import javax.persistence.EntityManager;
> import javax.persistence.EntityManagerFactory;
> import javax.persistence.Persistence;
> import javax.persistence.PersistenceUnit;
> import javax.servlet.ServletException;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> import org.apache.log4j.Logger;
> import ca.recollect.entities.Episode;
> import ca.recollect.shared.util.PropertyLoader;
> /**
>  * This is a quick port of the code described at 
> http://flashforever.blogspot.com/2005/11/flv-seeking-for-progressive-download.html
>  * Use it however you feel like it.  Also, check here for full specs: 
> http://osflash.org/flv
>  */
> public class Streamer extends HttpServlet {
>       private static final long serialVersionUID = 1L;
>       private static final Logger _logger = Logger.getLogger(Streamer.class);
>       public static ConcurrentLinkedQueue<String[]> loggingData = null;
>       //private static DBLogger datalogger = null;
>       protected static final byte[] header = new byte[]{0x46, 0x4c, 0x56, 
> 0x01, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00};
>       private byte[] data = new byte[10240];
>       private String _fileRoot = "";
>       private static final String PERSISTENCE_UNIT = "StreamerPU";
>       @PersistenceUnit(unitName = PERSISTENCE_UNIT)
>       private EntityManagerFactory emf = null;
>       @Override
>       public void init() throws ServletException {
>               PropertyLoader loader = new 
> PropertyLoader("/META-INF/streamer.properties");
>               _fileRoot = loader.getStringProperty("video.fileroot");
>               super.init();
>               emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
>               _logger.info("Streamer started successfully");
>       }
>       /** Processes requests for both HTTP <code>GET</code> and 
> <code>POST</code> methods.
>        * @param request servlet request
>        * @param response servlet response
>        * @throws IOException
>        */
>       protected void processRequest(HttpServletRequest request, 
> HttpServletResponse response) throws IOException {
>               if (_logger.isDebugEnabled()) {
>                       _logger.debug("processRequest()");
>               }
>               boolean throttled = true;
>               String throttling = request.getParameter("throttled");
>               if (throttling != null && throttling.equals("false")) {
>                       throttled = false;
>               }
>               FileInputStream fileStream = null;
>               long file = 0;
>               OutputStream out = null;
>               long position = 0;
>               long filelength = 0;
>               int eof = 0;
>               try {
>                       response.setContentType("video/x-flv");
>                       //get the file parameter from the request
>                       try {
>                               file = 
> Long.parseLong(request.getParameter("file"));
>                       } catch (NumberFormatException ex) {
>                               _logger.error("No episode specified!");
>                               response.setContentLength(0);
>                               return;
>                       }
>                       _logger.debug("processRequest(): Getting video id=" + 
> file);
>                       //Create the entity manager
>                       EntityManager em = emf.createEntityManager();
>                       Episode ep = em.find(Episode.class, file);
>                       if (ep == null) {
>                               _logger.info("No result found");
>                               return;
>                       }
>                       //Check to make sure the file exists
>                       File inputFile = new File(_fileRoot, ep.getFilename());
>                       if (!inputFile.isFile()) {
>                               _logger.info("Episode: " + 
> inputFile.getAbsolutePath() + " not found in filesystem");
>                               response.setContentLength(0);
>                               return;
>                       }
>                       //Start sending stuff to the client
>                       fileStream = new FileInputStream(inputFile);
>                       //seek to the position indicated by the stream
>                       position = 0;
>                       //seek to the position indicated by the stream
>                       try {
>                               position += 
> Long.parseLong(request.getParameter("position"));
>                       } catch (NumberFormatException e) {
>                               //we'll just assume they want to start at the 
> begining, so do nothing
>                       }
>                       fileStream.skip(position);
>                       //set the http header for content length
>                       //this is needed for flash player 9, so it knows max on 
> the timeline
>                       filelength = inputFile.length();
>                       if (position > 0) {
>                               response.setContentLength((int) (filelength - 
> position + 1));
>                       } else {
>                               response.setContentLength((int) (filelength));
>                       }
>                       //get the output stream to respond with
>                       out = response.getOutputStream();
>                       //write out the header
>                       eof = data.length;
>                       if (position != 0) {
>                               out.write(header);
>                       }
>                       //cur = position;
>                       //write out the data
>                       while (eof == data.length) {
>                               eof = fileStream.read(data);
>                               long start = System.currentTimeMillis();
>                               out.write(data, 0, eof);
>                               out.flush();
>                               long end = System.currentTimeMillis();
>                               if (throttled && end - start < 25) {
>                                       try {
>                                               Thread.sleep(25);
>                                       } catch (InterruptedException e) {}
>                               }
>                       }
>                       //close connection
>                       out.close();
>                       out = null;
>               } catch (IOException ex) {
>                       _logger.error(ex);
>               } finally {
>                       //close the file stream
>                       if (fileStream != null) {
>                               fileStream.close();
>                       }
>                       fileStream = null;
>                       //close the response stream in case
>                       if (out != null) {
>                               out.close();
>                       }
>               }
>       }
>       // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. 
> Click on the + sign on the left to edit the code.">
>       /** Handles the HTTP <code>GET</code> method.
>        * @param request servlet request
>        * @param response servlet response
>        * @throws ServletException
>        * @throws IOException
>        */
>       @Override
>       protected void doGet(HttpServletRequest request, HttpServletResponse 
> response)
>       throws ServletException, IOException {
>               processRequest(request, response);
>       }
>       /** Handles the HTTP <code>POST</code> method.
>        * @param request servlet request
>        * @param response servlet response
>        * @throws ServletException
>        * @throws IOException
>        */
>       @Override
>       protected void doPost(HttpServletRequest request, HttpServletResponse 
> response)
>       throws ServletException, IOException {
>               processRequest(request, response);
>       }
>       /** Returns a short description of the servlet.
>        * @return A description of the servlet
>        */
>       @Override
>       public String getServletInfo() {
>               return "Streams video files";
>       }
>       // </editor-fold>
> }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
http://opencast.jira.com/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        
_______________________________________________
Matterhorn mailing list
[email protected]
http://lists.opencastproject.org/mailman/listinfo/matterhorn


To unsubscribe please email
[email protected]
_______________________________________________

Reply via email to