23

Soy nuevo en la programación android y me he encontrado atascado. He estado investigando varias maneras de transmitir video en vivo de un teléfono a otro y parece tenerlo principalmente funcional, excepto por supuesto el la parte más importante: jugar la transmisión. Parece que está enviando la transmisión desde un teléfono, pero el segundo teléfono no puede reproducir la transmisión.Transmitir video en vivo de teléfono a teléfono usando el socket fd

Este es el código para el lado de juego

public class VideoPlayback extends Activity implements Callback { 
MediaPlayer mp; 
private SurfaceView mPreview; 
private SurfaceHolder holder; 
private TextView mTextview; 
public static final int SERVERPORT = 6775; 
public static String SERVERIP="192.168.1.126"; 
Socket clientSocket; 
private Handler handler = new Handler(); 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    mPreview = (SurfaceView) findViewById(R.id.surfaceView1); 
    mTextview = (TextView) findViewById(R.id.textView1); 
    holder = mPreview.getHolder(); 
    holder.addCallback(this); 
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    mTextview.setText("Attempting to connect"); 
    mp = new MediaPlayer(); 
    Thread t = new Thread(){ 
     public void run(){ 
      try { 
        clientSocket = new Socket(SERVERIP,SERVERPORT); 
       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         mTextview.setText("Connected to server"); 
        } 
       }); 
       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         try { 
          ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(clientSocket); 
          pfd.getFileDescriptor().sync(); 
          mp.setDataSource(pfd.getFileDescriptor()); 
          pfd.close(); 
          mp.setDisplay(holder); 
          mp.prepareAsync(); 
          mp.start(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 

        } 
       }); 

      } catch (UnknownHostException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }; 
    t.start(); 
} 

Y aquí está el código para el lado de streaming

public class VideoStreaming extends Activity{ 
// User Interface Elements 
VideoView mView; 
TextView connectionStatus; 
SurfaceHolder mHolder; 
// Video variable 
MediaRecorder recorder; 
// Networking variables 
public static String SERVERIP=""; 
public static final int SERVERPORT = 6775; 
private Handler handler = new Handler(); 
private ServerSocket serverSocket; 
/** Called when the activity is first created. */ 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    // Define UI elements 
    mView = (VideoView) findViewById(R.id.video_preview); 
    connectionStatus = (TextView) findViewById(R.id.connection_status_textview); 
    mHolder = mView.getHolder(); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    SERVERIP = "192.168.1.126"; 
    // Run new thread to handle socket communications 
    Thread sendVideo = new Thread(new SendVideoThread()); 
    sendVideo.start(); 
} 
public class SendVideoThread implements Runnable{ 
    public void run(){ 
     // From Server.java 
     try { 
      if(SERVERIP!=null){ 
       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         connectionStatus.setText("Listening on IP: " + SERVERIP); 
        } 
       }); 
       serverSocket = new ServerSocket(SERVERPORT); 
       while(true) { 
        //listen for incoming clients 
        Socket client = serverSocket.accept(); 
        handler.post(new Runnable(){ 
         @Override 
         public void run(){ 
          connectionStatus.setText("Connected."); 
         } 
        }); 
        try{ 
          // Begin video communication 
          final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(client); 
          handler.post(new Runnable(){ 
           @Override 
           public void run(){ 
            recorder = new MediaRecorder(); 
            recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
            recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);     
            recorder.setOutputFile(pfd.getFileDescriptor()); 
            recorder.setVideoFrameRate(20); 
            recorder.setVideoSize(176,144); 
            recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); 
            recorder.setPreviewDisplay(mHolder.getSurface()); 
            try { 
             recorder.prepare(); 
            } catch (IllegalStateException e) { 
             // TODO Auto-generated catch block 
             e.printStackTrace(); 
            } catch (IOException e) { 
             // TODO Auto-generated catch block 
             e.printStackTrace(); 
            } 
            recorder.start(); 
           } 
          }); 
        } catch (Exception e) { 
         handler.post(new Runnable(){ 
          @Override 
          public void run(){ 
           connectionStatus.setText("Oops.Connection interrupted. Please reconnect your phones."); 
          } 
         }); 
         e.printStackTrace(); 
        } 
       } 
      } else { 
       handler.post(new Runnable() { 
        @Override 
        public void run(){ 
         connectionStatus.setText("Couldn't detect internet connection."); 
        } 
       }); 
      } 
     } catch (Exception e){ 
      handler.post(new Runnable() { 
       @Override 
       public void run() { 
        connectionStatus.setText("Error"); 
       } 
      }); 
      e.printStackTrace(); 
     } 
     // End from server.java 
    } 
} 

recibo el siguiente error al intentar crear el MediaPlayer

05-24 16:25:39.360: ERROR/MediaPlayerService(88): offset error 
05-24 16:25:39.360: ERROR/MediaPlayer(11895): Unable to to create media player 
05-24 16:25:39.360: WARN/System.err(11895): java.io.IOException: setDataSourceFD failed.: status=0x80000000 
05-24 16:25:39.360: WARN/System.err(11895):  at android.media.MediaPlayer.setDataSource(Native Method) 
05-24 16:25:39.360: WARN/System.err(11895):  at android.media.MediaPlayer.setDataSource(MediaPlayer.java:811) 
05-24 16:25:39.360: WARN/System.err(11895):  at com.conti.VideoPlayBack.VideoPlayback$1$2.run(VideoPlayback.java:63) 
05-24 16:25:39.360: WARN/System.err(11895):  at android.os.Handler.handleCallback(Handler.java:587) 
05-24 16:25:39.360: WARN/System.err(11895):  at android.os.Handler.dispatchMessage(Handler.java:92) 
05-24 16:25:39.360: WARN/System.err(11895):  at android.os.Looper.loop(Looper.java:132) 
05-24 16:25:39.360: WARN/System.err(11895):  at android.app.ActivityThread.main(ActivityThread.java:4025) 
05-24 16:25:39.360: WARN/System.err(11895):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-24 16:25:39.360: WARN/System.err(11895):  at java.lang.reflect.Method.invoke(Method.java:491) 
05-24 16:25:39.360: WARN/System.err(11895):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841) 
05-24 16:25:39.360: WARN/System.err(11895):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599) 
05-24 16:25:39.360: WARN/System.err(11895):  at dalvik.system.NativeStart.main(Native Method) 

¿Alguien tiene una solución para esto? ¡Gracias por adelantado!

+0

lo has sacado de trabajo? – B770

+0

¿funciona para usted?si funciona, por favor dime cómo resolver este problema. – Aravi

+0

hay varias preguntas sobre este tema y todas terminan de la misma manera, alguien diciendo que debería ser posible pero sin respuestas reales, sin ejemplos de código de trabajo, es muy frustrante. – steveh

Respuesta

6

Encontré un proyecto de código abierto para implementar lo que estaba intentando. Procesa el video con metadatos a través de una cámara IP. Aunque no envía video directamente a un teléfono, sí transmite video para que varios dispositivos lo miren. El código fuente se puede encontrar en la siguiente página del proyecto http://code.google.com/p/ipcamera-for-android/.

Con Android 4.4 hay otra forma de reproducir una transmisión en vivo de MJPEG. La transmisión que está reproduciendo debe ser transmitida por el otro dispositivo en un puerto a través de UDP. Digamos que tenemos una transmisión en 192.168.0.101:8080. Podemos reproducir la secuencia agregando un WebView a nuestro diseño. Luego, en nuestra actividad hacemos lo siguiente:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.mjpeg_activity); 
    // Grab instance of WebView 
    WebView webView = (WebView)findViewById(R.id.webViewStream); 
    // Set page content for webview 
    webView.loadData("<html><head><meta name='viewport' content='target-densitydpi=device-dpi,initial-scale=1,minimum-scale=1,user-scalable=yes'/></head><body><center><img src=\"http://192.168.0.101:8080/\" alt=\"Stream\" align=\"middle\"></center></body></html>", "text/html", null); 
    webView.getSettings().setBuiltInZoomControls(true); 
} 

En el contenido, le decimos a la página web que utilice los ppp del dispositivo. Para ayudar al usuario a pellizcar el zoom en la página web, he agregado la siguiente escala inicial = 1, escala mínima = 1, escalable por el usuario = sí. Inicialmente, la imagen tiene su tamaño original y no puede achicarse. El usuario ahora puede escalar para acercar y alejar la imagen hasta su tamaño original. La eliminación de la escala mínima le dará al usuario control total sobre el zoom, pero puede hacer que la imagen sea tan pequeña que no pueda encontrarla.

+1

no se puede ejecutar este proyecto. ¿puedes escribir los pasos para ello? –

+0

Entonces termina no usando el MediaPlayer entonces. – lifelogger

0

Echa un vistazo a Streaming to the Android MediaPlayer, que puede tener algunos consejos útiles sobre cómo hacer la transmisión. Sospecho que el problema es que Android está tratando de buscar en el archivo, pero al ser un conector de red, no puede. ¿Tal vez algún tipo de búfer de disco/memoria que admita búsqueda podría ayudar?

+0

Parece que voy a tener que hacer algo con un búfer como se sugiere. Lo intentaré por la mañana y veré qué pasa. Gracias por la publicacion. –

+0

Parece que el archivo que se está transmitiendo no está en el formato correcto para que el reproductor multimedia lo reproduzca. No estoy seguro de cómo resolver este problema. –

+1

Una forma en que el reproductor de medios tiene problemas con la transmisión de medios es si los metadatos no se envían primero. Normalmente, utilizas una herramienta como qt-faststart de ffmpeg para poner los metadatos antes del contenido, pero no estoy seguro de cómo lo harías al generar la transmisión en cualquier lugar. –

3

Tiene que configurar el formato de salida de la grabadora 8 (MPEG-2TS, solo disponible desde la versión de Android 3.0+). En este caso, grabe el video en este formato y envíelo a otro teléfono y guárdelo en un archivo. Y juega después de escribir algunos datos en el archivo, luego puedes ver transmisión en vivo.

Nota- No se puede reproducir directamente el descriptor de archivo de socket, porque socket fd no es buscable. Si usa socket fd obtendrá "error de desplazamiento". La grabación es posible, pero el juego está restringido.

Cuestiones relacionadas