Fiz um aplicativo utilizando JMF que se conecta a uma camera USB e exibe sua imagem, podendo tirar ‘fotografias’ da imagem e/ou gravar o vídeo. Agora estou estudando a integração do JMF com uma Camera IP, para tanto estou estudando o jipCam http://jipcam.sourceforge.net/ que é um framework que auxilia exatamente neste tipo de comunicação: conectar uma camera ip em um aplicativo jmf. Porém, estou com dificuldades para encontrar documentação, ou código de exemplo, nem se quer um Hello World encontrei… Em fim, algo que facilite minha vida. Alguém já trabalhou, ou estudou algo a respeito?
aqui o primeiro código de minha jornada de aprendizado. retirado do livro de Deitel:
Ele executa um arquivo ou um local (dispositivo.. no caso de uma webcam na porta 3: "vfw://3" )
//Pacotes do núcleo de Javaimportjava.awt.BorderLayout;importjava.awt.Component;importjava.awt.Container;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.io.File;importjava.io.IOException;importjava.net.MalformedURLException;importjava.net.URL;importjavax.media.ControllerAdapter;importjavax.media.EndOfMediaEvent;importjavax.media.Manager;importjavax.media.MediaLocator;importjavax.media.NoPlayerException;importjavax.media.Player;importjavax.media.PrefetchCompleteEvent;importjavax.media.RealizeCompleteEvent;importjavax.media.Time;importjavax.swing.JButton;importjavax.swing.JFileChooser;importjavax.swing.JFrame;importjavax.swing.JOptionPane;importjavax.swing.JPanel;publicclassSimplePlayerextendsJFrame{/** * Default Serial Version */privatestaticfinallongserialVersionUID=1L;// declara um objeto Player para reproduzir clipes de mídiaprivatePlayerplayer;/* * objetos Component para a exibição do vídeo e para manter os controles */// componente para conteúdo visual que exibe a parte de vídeo de um clipe de// mídia (se o clipe de mídia for um vídeo).privateComponentvisualMedia;// componente de controle da mídia. permite reproduzir, fazer pausa e parar// o clipe de mídiaprivateComponentmediaControl;// contêiner principalprivateContainercontainer;/* * endereços dos clipes como referências File e URL */// arquivo de mídiaprivateFilemediaFile;// referência. pode ser uma webcam, um endereço de rede ou internetprivateURLfileURL;// construtor para SimplePlayerpublicSimplePlayer(){super("cassioso player");container=getContentPane();// painel que contém botõesJPanelbuttonPanel=newJPanel();container.add(buttonPanel,BorderLayout.NORTH);// abrindo um arquivo a partir do botão de diretórioJButtonopenFile=newJButton("Open File");buttonPanel.add(openFile);// registra um ActionListener para eventos de openFileopenFile.addActionListener(// classe interna anônima para tratar eventos de openFilenewActionListener(){// abre e cria "player" para o arquivopublicvoidactionPerformed(ActionEventevent){/* * pede ao usuário que selecione um arquivo de mídia do * computador local. */mediaFile=getFile();if(mediaFile!=null){// tenta obter uma representação como URL do nome e// endereço do arquivo selecionado.try{fileURL=mediaFile.toURL();}// caminho para o arquivo não pode ser encontradocatch(MalformedURLExceptionbadURL){badURL.printStackTrace();showErrorMessage("Bad URL");}// Método de SimplePlayer para criar um Player para// a mídia selecionada pelo usuáriomakePlayer(fileURL.toString());}}// fim do método actionPerformed}// fim do método ActionListener);// fim da chamada para o método addActionListener// botão de abertura do URLJButtonopenURL=newJButton("Open Locator");buttonPanel.add(openURL);// registra um ActionListener para eventos de openURLopenURL.addActionListener(// classe interna anônima para tratar de eventos de openURLnewActionListener(){// abre e cria um "player" para o localizador de mídiapublicvoidactionPerformed(ActionEventevent){/* * pede ao usuário que digite um string que especifica o * endereço da mídia */StringaddressName=getMediaLocation();if(addressName!=null)// Método de SimplePlayer para criar um Player para// a mídia que está no endereço especificadomakePlayer(addressName);}}// fim do método ActionListener);// fim da chamada para o método addActionListener/* * O JMF fornece geradores de vídeo peso-leve que são compatíveis com os * componentes peso-leve do Swing. A linha a baixo especifica que o * Player deve desenhar seus componentes GUI (graphical user interface) * e sua parte de vídeo (se existir uma) usando geradores peso-leve, de * modo que o reprodutor de mídia terá aparência semelhante à de outros * componentes GUI com componentes Swing */Manager.setHint(Manager.LIGHTWEIGHT_RENDERER,Boolean.TRUE);}// fim do construtor SimplePlayer// método utilitário para mensagens de erro "pop-up"publicvoidshowErrorMessage(Stringerror){JOptionPane.showMessageDialog(this,error,"Error",JOptionPane.ERROR_MESSAGE);}// obtém arquivo do computadorpublicFilegetFile(){JFileChooserfileChooser=newJFileChooser();fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);intresult=fileChooser.showOpenDialog(this);if(result==JFileChooser.CANCEL_OPTION)returnnull;elsereturnfileChooser.getSelectedFile();}// obtém endereço da mídia digitado pelo usuáriopublicStringgetMediaLocation(){Stringinput=JOptionPane.showInputDialog(this,"Enter URL");// se o usuário pressionar OK sem digitar dadosif(input!=null&&input.length()==0)returnnull;returninput;}/* * cria player com o endereço da mídia. O argumento String indica o endereço * da mídia. */publicvoidmakePlayer(StringmediaLocation){// método para remover da frame o componente visual e os controles da// GUI do Player anterior, antes de criar um novo Playerif(player!=null)removePlayerComponents();/* * O clipe de mídia precisa ser processado antes de ser reproduzido. * Para processar um clipe de mídia, o programa precisa acessar uma * fonte de mídia... */// O método makePlayer exige um ponteiro para a fonte da qual a mídia é// recuperada, o que é feito instanciando-se um novo MediaLocator para o// valor dado pelo argumento StringMediaLocatormediaLocator=newMediaLocator(mediaLocation);// Verifica a validade da fonte de mídiaif(mediaLocator==null){showErrorMessage("Error opening file");return;}// cria um player a partir de MediaLocatortry{/* * ... criar um Controller para aquela fonte ... */// createPlayer abre a fonte de mídia especificada e determina o// Player apropriado para a fonte de mídiaplayer=Manager.createPlayer(mediaLocator);// inSource = Manager.createDataSource(mediaLocator);/* * Os ControllerListeners esperam os ControllerEvents que os Players * geram, para monitorar o progresso de um Player no processo de * tratamento da mídia. */player.addControllerListener(newPlayerEventHandler());/* * ... e enviar a mídia para a saída * * para finalizar o método makePlayer invoca o método realize de * Player no estado Realizing para indicar que ele está se * conectando à sua fonte de mídia e interagindo com ela. Quando um * Player completa a realização, ele gera um Realize-CompleteEvent ? * um tipo de ControllerEvent que ocorre quando o Player completa * sua transição para o estado Realized. Este estado indica que o * Player completou todos os preparativos necessários para começar a * processar a mídia. O PlayerEventHandler invoca o método * realizeComplete quando o Player gera um RealizeCompleteEvent */player.realize();}// caso não exista nenhum player ou o formato não é suportadocatch(NoPlayerExceptionnoPlayerException){noPlayerException.printStackTrace();}// erro na leitura do arquivocatch(IOExceptionioException){ioException.printStackTrace();}}// fim do método makePlayer/** * Devolve o player para os recursos do sistema e restaura a mídia e os * controles */publicvoidremovePlayerComponents(){// remove componente de vídeo anterior, se existe umif(visualMedia!=null)container.remove(visualMedia);// remove controle de mídia anterior, se existe umif(mediaControl!=null)container.remove(mediaControl);// método para parar toda a atividade do Player e liberar recursos do// sistema mantidos pelo Player anterior.player.close();}// obtém controles visuais para mídia e playerpublicvoidgetMediaComponents(){// obtém o componente visual do clipe de vídeo e devolve null para// arquivos de áudio, porque não há componente visual// a exibir.visualMedia=player.getVisualComponent();// adiciona componente visual, se estiver presenteif(visualMedia!=null)container.add(visualMedia,BorderLayout.CENTER);// obtém a GUI de controle do playermediaControl=player.getControlPanelComponent();// adiciona componente de controles, se estiver presenteif(mediaControl!=null)container.add(mediaControl,BorderLayout.SOUTH);}// fim do método getMediaComponents/* * A classe ControllerAdapter facilita a implementação de ControllerListener * para as classes que precisam tratar de apenas alguns tipos de * ControllerEvent. */privateclassPlayerEventHandlerextendsControllerAdapter{// carrega antecipadamente a mídia assim que o player é realizado.publicvoidrealizeComplete(RealizeCompleteEventrealizeDoneEvent){/* * Quando o Player carrega antecipadamente um clipe de mídia, o * Player obtém controle exclusivo sobre certos recursos do sistema * necessários para reproduzir o clipe. O Player também começa a * colocar dados da mídia no buffer para reduzir o atraso antes da * reprodução do clipe de mídia. * * enquanto isto, o estado do player é definido como Prefetching. */player.prefetch();/* * Quando termina de carregar o estado do player mudfa para * Prefetched e fica pronto para reproduzir a mídia. É gerado então * um PrefetchCompleteEvent, automaticamente o player invoca o * método prefetchComplete de PlayerEventHandler */}// player pode começar a mostrar a mídia após a carga antecipadapublicvoidprefetchComplete(PrefetchCompleteEventprefetchDoneEvent){/* * obtém os controles da GUI e o componente visual da mídia (se a * mídia for um clipe de vídeo) e os anexa ao painel de conteúdo da * janela do aplicativo */getMediaComponents();// assegura um leiaute válido para a framevalidate();// começa a reproduzir a mídia/* * Se o Player não fez a carga antecipada nem realizou a mídia, * invocar o método start faz a carga antecipada e realiza a mídia. */player.start();/* * Quando o clipe de mídia terminar, o Player gera um * ControllerEvent do tipo EndOfMediaEvent. */}// fim do método prefetchComplete// se fim da mídia, restaura para o início e pára de reproduzir/* * Trata o evento EndOfMediaEvent e restaura o clipe de mídia para sua * posição inicial invocando o método setMediaTime de Player com um novo * Time (pacote javax.media) com valor zero. */publicvoidendOfMedia(EndOfMediaEventmediaEndEvent){// ajusta a posição da mídia para uma posição específica de tempoplayer.setMediaTime(newTime(0));// termina o processamento e faz o estado do Player = Stoppedplayer.stop();// Obs.: Invocar o método start para um Player Stopped que não tenha// sido fechado retoma a reprodução da mídia.}// fim do método endOfMedia}// fim da classe interna PlayerEventHandler// executa o aplicativopublicstaticvoidmain(Stringargs[]){SimplePlayertestPlayer=newSimplePlayer();testPlayer.setSize(300,300);testPlayer.setLocation(300,300);testPlayer.setDefaultCloseOperation(EXIT_ON_CLOSE);testPlayer.setVisible(true);}}// fim da classe SimplePlayer
C
cassioso
Saudações,
Um código simples que deveria funcionar com o jipcam, mas da um erro de dependencia com o log4j:
[color=red]Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Category
at ipcam.PlayerManager.main([/color][color=blue]PlayerManager.java:115[/color][color=red])[/color]
packageipcam;importjava.awt.Component;importjavax.media.ConfigureCompleteEvent;importjavax.media.ControllerEvent;importjavax.media.ControllerListener;importjavax.media.EndOfMediaEvent;importjavax.media.Manager;importjavax.media.MediaLocator;importjavax.media.Player;importjavax.media.PrefetchCompleteEvent;importjavax.media.Processor;importjavax.media.RealizeCompleteEvent;importjavax.media.ResourceUnavailableEvent;importjavax.media.SizeChangeEvent;importjavax.media.protocol.DataSource;importjavax.swing.JFrame;importjavax.swing.JPanel;/** * @author cassio * @since December 2007 */publicclassPlayerManagerextendsJFrameimplementsControllerListener{privatestaticfinallongserialVersionUID=1L;privatePlayerp;privateObjectwaitSync=newObject();booleanstateTransitionOK=true;publicvoidplay(DataSourceds){try{p=Manager.createPlayer(ds);}catch(Exceptione){System.err.println("Failure to create the player: "+e);}/* * turn on the listeners and realize the player */p.addControllerListener(this);p.prefetch();if(!waitForState(Processor.Prefetched)){System.err.println("Failure to realize the player: ");}JPanelpainel=newJPanel();Componentcc;// control componentComponentvc;// visual componentif((vc=p.getVisualComponent())!=null)painel.add(vc);if((cc=p.getControlPanelComponent())!=null)add(cc);this.setContentPane(painel);p.start();this.setVisible(true);}publicvoidaddNotify(){super.addNotify();pack();}privatebooleanwaitForState(intstate){synchronized(waitSync){try{while(p.getState()<state&&stateTransitionOK)waitSync.wait();}catch(Exceptione){}}returnstateTransitionOK;}/** * Controller Listener implementation */publicvoidcontrollerUpdate(ControllerEventevt){if(evtinstanceofConfigureCompleteEvent||evtinstanceofRealizeCompleteEvent||evtinstanceofPrefetchCompleteEvent){synchronized(waitSync){stateTransitionOK=true;waitSync.notifyAll();}}elseif(evtinstanceofResourceUnavailableEvent){synchronized(waitSync){stateTransitionOK=false;waitSync.notifyAll();}}elseif(evtinstanceofEndOfMediaEvent){p.close();}elseif(evtinstanceofSizeChangeEvent){}}/** * Main program */publicstaticvoidmain(String[]args){MediaLocatorml=newMediaLocator("http://192.168.0.100:80");net.sf.jipcam.axis.media.protocol.http.DataSourceds=null;try{// DataSource configurationds=newnet.sf.jipcam.axis.media.protocol.http.DataSource();ds.setLocator(ml);// i'm not using passwordds.setUsername(null);ds.setPassword(null);}catch(Exceptione){System.err.println("Imposspível criar dataSuource para: "+ml);e.printStackTrace();}PlayerManagerp=newPlayerManager();p.play(ds);}}
C
cassioso
Consegui resolver o problema do log4j. Aparentemente foi apenas uma questão de configuração de diretório… Coloquei a lib do log4j à cima dos diretórios do projeto: coloquei na pasta JAVA_HOME/jre/lib/ext. Porém me surgiu um outro erro, agora relacionado mais diretamente com o que estou tentando fazer:
[color=red]Failure to create the player: javax.media.NoPlayerException: Cannot find a Player for: net.sf.jipcam.axis.media.protocol.http.DataSource@b8c8e6
Exception in thread “main” java.lang.NullPointerException
at ipcam.PlayerManager.play(PlayerManager.java:50)
at ipcam.PlayerManager.main(PlayerManager.java:128)[/color]
Este erro ocorreu por que meu Manager.CreatePlayer(ds) não funcionou: