⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mediastoreimpl.java

📁 Its video trNSMITT FILE USING JMF
💻 JAVA
字号:
/* 	MediaStoreImpl.java
 *
 *	This file contains the implementation of the MediaStore methods
 *	for storing/accessing video to/from a database using JDBC. 
 *
 *	Methods are made synchronized so that two competing requests don't
 *	access the resources at the same time.  For example, accessing the
 *	database at the same time causes JDBC or ODBC exceptions.
 *	
 *  Copyright (C) 2002 by Frank McCown
 *  University of Arkansas at Little Rock
 *  July 2002
 */


import javax.media.*;
import javax.media.protocol.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import org.omg.PortableServer.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import rowc.*;
import rowc.event.MediaArchiveListener;
import rowc.event.MediaArchiveEvent;
import rowc.MediaStorePackage.*;

public class MediaStoreImpl extends rowc.MediaStorePOA 
{	
	private Set mediaArchiveListeners;  // Stores listeners for NewVideo events
	private Hashtable mediaListeners;  // Stores remote listeners for media events
	
	
	// NOTE: Events are not possible with CORBA unless using Event or Notification Services
	// or callback methods.  Callbacks are implemented in ROWC for sending events from
	// remote objects.
	
	public MediaStoreImpl()
	{
		mediaArchiveListeners = new HashSet(1);  // Only Media Server should get events
		mediaListeners = new Hashtable();
	}
	
	public void addMediaArchiveListener(MediaArchiveListener listener)
	{
		mediaArchiveListeners.add(listener);    // Register the listener
	}
	
	// Iterate through list of NewVideoListeners and generate a new event for each
	private void sendAddVideoEvents(String location)
	{
		Iterator i = mediaArchiveListeners.iterator();
		while (i.hasNext())
		{
			MediaArchiveListener listener = (MediaArchiveListener) i.next();
			listener.addVideo(new MediaArchiveEvent(location));
		}
	}
	
	private void sendRemoveVideoEvents(String location)
	{
		Iterator i = mediaArchiveListeners.iterator();
		while (i.hasNext())
		{
			MediaArchiveListener listener = (MediaArchiveListener) i.next();
			listener.removeVideo(new MediaArchiveEvent(location));
		}
	}	
	
	/***************************************************************************
	 *
	 *	Implementation of remote methods
	 *
	 ***************************************************************************/
	
	
	// 
	public synchronized void addMediaArchiveListener(String hostName, MediaArchiveCallback callback)
	{
		System.out.println("addMediaArchiveListener called for " + hostName);
		
		mediaListeners.put(hostName, callback);
	}
	
	// 
	public synchronized void removeMediaArchiveListener(String hostName)
	{
		System.out.println("removeMediaArchiveListener called for "+hostName);
		
		mediaListeners.remove(hostName);
	}
	
	private void notifyAddMedia(String location)
	{
		Enumeration enum = mediaListeners.elements();
    System.out.println("Notifying all cam controllers of new media from "+ location);
    while(enum.hasMoreElements())
    {
    	MediaArchiveCallback callback = (MediaArchiveCallback)enum.nextElement();
    	callback.addVideo(location);
    }
  }
	
	private void notifyDeleteMedia(String location)
	{
		Enumeration enum = mediaListeners.elements();
    System.out.println("Notifying all cam controllers to delete media from "+ location);
    while(enum.hasMoreElements())
    {
    	MediaArchiveCallback callback = (MediaArchiveCallback)enum.nextElement();
    	callback.removeVideo(location);
    }
  }
  
	public synchronized String[] getArchiveLocations() throws LocationsUnavailable
	{
		String[] loc = {""};
		
		try
		{  
			// Get unique list of locations
			Statement statement = Server.connection.createStatement();
			String query = "SELECT DISTINCT location FROM media";
			ResultSet rs = statement.executeQuery(query);

			// Since there is an unknown number of locations, store each location
			// in a vector and later convert vector to an array
			
			Vector v = new Vector(10);
			while (rs.next())
			  v.addElement(rs.getString(1));
			
			rs.close();
			statement.close();
			
			// Convert vector to array
			loc = new String[v.size()];
			v.copyInto(loc);
		} 
		catch (SQLException e)
		{
			System.err.println("Error retrieving data from database.");
			e.printStackTrace();
			throw new LocationsUnavailable();
		}
		catch (Exception e)
		{
			System.err.println("General error retrieving data from database.");
			e.printStackTrace();
			throw new LocationsUnavailable();
		}
				
		return loc;	
	}
	

	public void getAllVideoDetails(String location, ClipsHolder videos)
	{
		// Put into videos all video data from database
		
		//VideoClip[] clips;
		
		Vector clips = new Vector();
		
		try
		{
			Statement statement = Server.connection.createStatement();
	
			String query = "SELECT name, size, length, timestamp FROM media WHERE " +
										 "location = '" + location + "' ORDER BY timestamp";
			
			ResultSet rs = statement.executeQuery(query);

			while (rs.next())
			{
				VideoClip video = new VideoClip();
				
				video.location = location;
				video.name = rs.getString(1);
				video.size = rs.getInt(2);
				video.length = rs.getInt(3);
				video.timeStamp = rs.getLong(4);
				
				clips.addElement(video);
			}
			
			rs.close();
			
			// Puts clips vector into output parameter
			
			videos.value = new VideoClip[clips.size()];	
			clips.copyInto(videos.value);
		} 
		catch (SQLException e)
		{
			System.err.println("Error retrieving data from database.");
			e.printStackTrace();
			return;
		}
		catch (Exception e)
		{
			System.err.println("General error retrieving data from database.");
			e.printStackTrace();
			return;
		}
	}
	
	
	public synchronized void storeVideo(VideoClip videoRec)
  {
  	// Store video data in database and store video as a file so it can be
  	// more quickly transported to listeners using getVideo
  	
  	System.out.println("sendVideo received new video:");
  	System.out.println("name: " + videoRec.name);
  	System.out.println("location: " + videoRec.location);
  	System.out.println("size: " + videoRec.size);
  	System.out.println("length: " + videoRec.length);
  	System.out.println("timestamp: " + videoRec.timeStamp);
  	
   	// Change name of video file according to timestamp.  
  	// Example: COMPLAB_Mon_Oct_12_02_55_13_CST_2002.mov
  	
  	// May need to wait until Server socket thread is able to completely download
  	String fileName = "video/" + videoRec.location + ".mov";
  	File videoFile = new File(fileName);
	 	String newName = "video/" + videoRec.location + "_" + videoRec.name + ".mov";
  	  	
  	boolean rename = false;
  	
  	try
  	{
  		rename = videoFile.renameTo(new File(newName));
	  	int tries = 0;
	  	while (tries < 5 && !rename)
	  	{
	  		Thread.sleep(1000);
	  		tries++;
	  		rename = videoFile.renameTo(new File(newName));
	  	}
	  }
	  catch (InterruptedException ex)
	  {
	  	System.out.println("Error while trying to wait for file to download.");
	  	ex.printStackTrace();
	  }
  	
  	if (!rename)
  	{
  		System.out.println("Error trying to rename file from " + videoFile + " to " + newName);
  		return;  // Don't save to database
  	}
  	  	
  	if (!Server.connectedToDB)
    {
      System.out.println("Can't store media file... not connected to database.");
      return;
    }

		try
		{
			String template = "insert INTO media (location, name, size, length, timestamp) " +
												"VALUES (?, ?, ?, ?, ?)";

			PreparedStatement statement = Server.connection.prepareStatement(template);
			statement.setString(1, videoRec.location);
			statement.setString(2, videoRec.name);
			statement.setInt(3, videoRec.size);
			statement.setInt(4, videoRec.length);
			statement.setLong(5, videoRec.timeStamp);
			
			statement.execute();
			statement.close();
		} 
		catch (SQLException e)
		{
			System.err.println("Error saving to database.");
			e.printStackTrace();
		}
		
		// Update MediaServer's archive video list
		sendAddVideoEvents(videoRec.location);
		
		// Notify all cam processors of new media from this location
		notifyAddMedia(videoRec.location);
		
		System.out.println("sendVideo is done.");
	}


	public synchronized boolean deleteVideos(String location, String[] names)
	{
		System.out.println("deleteVideos with location: " +location);
		
		boolean success = true;
		
		try
		{  
			// Get unique list of locations
			String template = "DELETE FROM media WHERE location=? AND name=?";
			PreparedStatement statement = Server.connection.prepareStatement(template);
		
			for (int i=0; i < names.length && success; i++)
			{
				statement.setString(1, location);
				statement.setString(2, names[i]);
				
				int rowsAffected = statement.executeUpdate();
				if (rowsAffected != 1)
					success = false;
				
				if (success)
				{
					// Delete file from video directory
					File f = new File("video/" + location + "_" + names[i] + ".mov");
					success = f.delete();
					if (!success)	
						System.err.println("Error deleting file: " + f.getAbsolutePath());
				}
				else
					System.err.println("Error trying to delete from database using command: "+
						template + "\nDeleted " + rowsAffected + " rows.");
			}
			
			statement.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		// Notify the MediaServer
		sendRemoveVideoEvents(location);  
		
		// Notify all cam processors of deleted media from this location
		notifyDeleteMedia(location);
		
		return success;
	}
		
	// Return the RTP URL for accessing the streaming video that is sent to the 
	// given destination IP address.	
	public synchronized String getVideoStream(String location, String name, String destIPaddr)
	{		
		// Find a free port number on which to stream video			
		int port = findOpenPort();
		
		String rtp = "rtp://" + destIPaddr + ":" + port + "/video";
		
		// Get current directory.  File is named like this: c:/rowc/video/location_name.mov
		String currentDir = System.getProperty("user.dir");
		
		String fileName = currentDir + "/video/" + location + "_" + name + ".mov";
		System.out.println("About to transmit file: " + fileName);
		
		// Start tansmitting this video to this IP address
		TransmitterThread transThread = new TransmitterThread(destIPaddr, port, fileName);
		transThread.start();
		
		return rtp;
	}
	
	// Finds a port number on the server which is not being used.  This would not
	// be necessary if only one CamController was running at a time on the same
	// computer as the server.  But since 2 or more CamControllers could be running
	// and accessing video at the same time, they would both need to access video
	// on different ports.
	
	/* NOTE: Actually it's not the server's port that we need to find but a free
	 * port on the CamController that we need to find.  Implement this later.
	 *
	 */
	 
	private int findOpenPort()
	{
		int port = 0;
		boolean freePort = false;
		
		while (!freePort)
		{
			try
			{
				// Test each port until we find one that is open for rtp transmission
				//java.net.ServerSocket s = new java.net.ServerSocket(port);
				
				// Get free port from the system automatically
				java.net.ServerSocket s = new java.net.ServerSocket(0);
				port = s.getLocalPort();
				s.close();
				
				// Port is only acceptable if it's even.  Odd numbered ports don't work with JMF video.
				if (port % 2 == 0)
					freePort = true;
			}
			catch (Exception e)
			{
				System.out.println(e);
				System.out.println("Port " + port + " is taken.  Try next one...");
				// Try next one
				port += 2;
			}
		}
	
		System.out.println("Free port: " + port);
		return port;
	}
	
	
	/*********************** Inner class *********************************/
	
	class TransmitterThread extends Thread 
	{
		private String ipAddr;
		private int port;
		private String fileName;
		
		TransmitterThread(String ipAddr, int port, String fileName)
		{
			this.ipAddr = ipAddr;
			this.port = port;
			this.fileName = fileName;
		}
		
		public void run()
		{
			System.out.println("About to start VideoTransmitter...");
			
			DataSource ds;
			try 
			{
	    	ds = Manager.createDataSource(new MediaLocator("file:/" + fileName));
			} 
			catch (Exception e) 
			{
				System.out.println("Error creating data source from file: " + fileName);
	    	e.printStackTrace();
	    	return;
			}	
		
			VideoTransmitter vt = new VideoTransmitter(ds, ipAddr, Integer.toString(port));
			
			String result = vt.start();
			if (result != null) 
		  	System.err.println("Failed to start VideoTransmitter: " + result);
		  else	  
				System.out.println("Started VideoTransmitter.");  	
						
			javax.media.Time duration = vt.processor.getDuration();
			if (duration == javax.media.Duration.DURATION_UNKNOWN)
			{
				System.out.println("Unknown duration... run for 20 seconds.");
				duration = new javax.media.Time(duration.ONE_SECOND * 20);
			}	
			
			System.out.println("getDuration  = " + duration.getNanoseconds());
	
			// Loop until we've exceeded the media's duration or media time is no longer incerementing.
			// This happens ofter when media time stops just short of duration time
			// NOTE: There's probobaly a better way to do this when RTPing a video file, but I haven't
			// been able to figure it out.
			
			long oldNano = -1;
			long nanos = vt.processor.getMediaNanoseconds();
			int numStucks = 0;

			while (nanos < duration.getNanoseconds() && oldNano != nanos && numStucks < 5)
			{
				System.out.println("getMediaTime = " + nanos);
				oldNano = vt.processor.getMediaNanoseconds();
				
				try 
				{
					Thread.currentThread().sleep(1000);
				} 
				catch (InterruptedException ie) {}
				 
				nanos = vt.processor.getMediaNanoseconds();
				
				if (nanos == 0)
				{
					// Taking a bit longer to get going
					nanos = 1;
					
					// Keep track of how many times we try this.  If we do it 5 times, there must
					// be something really wrong, and we should terminate the loop.
					numStucks++;  
				} 
			}
			
			// Must disconnect in order to release system lock on file.  Otherwise we won't be able to
			// delete the file later if the user wants the video deleted.
			ds.disconnect();
			ds = null;
	
	    System.out.println("About to stop vt...");
	    vt.stop();	// Stop transmission thread  CAUSING PROBLEMS
	    	    
	    System.out.println("Stopped transThread");
		}	
	}  // end TransmitterThread class
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -