example - mediaplayer android ejemplo
Transmite video en vivo de teléfono a teléfono usando socket fd (4)
Soy nuevo en la programación de Android y me he quedado atascado. He estado investigando varias formas de transmitir videos en vivo de un teléfono a otro y parece que la tengo prácticamente funcional, excepto por supuesto la parte más importante: reproducir la transmisión. Parece que está enviando el flujo desde un teléfono, pero el segundo teléfono no puede reproducirlo.
Aquí está 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 la transmisión.
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!
Debe 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 lo envíe a otro teléfono y guárdelo en un archivo. Y reprodúzcalo después de escribir algunos datos en el archivo, luego podrá ver la transmisión en vivo.
Nota: no se puede reproducir directamente a través del descriptor de archivo de socket, porque socket fd no se puede buscar. Si utiliza socket fd obtendrá "error de desplazamiento". La grabación es posible, pero el juego está restringido.
Descargue el código fuente de: http://code.google.com/p/ipcamera-for-android/ ( https://github.com/Teaonly/android-eye )
Primero construye el jni (usa ndk-build con cygwin)
Podría construir este proyecto exitosamente
Echa un vistazo a Streaming to Android MediaPlayer , que puede tener algunos consejos útiles sobre cómo hacer la transmisión. Sospecho que el problema es que Android está intentando buscar en el archivo, pero al ser un socket de red, no puede. Tal vez algún tipo de disco / memoria intermedia que admita la búsqueda podría ayudar?
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, transmite video para que lo vean varios dispositivos. 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 MJPEG en vivo. 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 que se transmite en 192.168.0.101:8080. Podemos reproducir la transmisión 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 dpi 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 es su tamaño original y no puede reducirse. El usuario ahora puede escalar para ampliar la imagen y su tamaño original. Eliminar la escala mínima le dará al usuario el control completo sobre el zoom, pero puede hacer que la imagen sea tan pequeña que no la pueda encontrar.