Je suis nouveau dans la programmation Android et je me suis retrouvé coincé. J'ai recherché différentes façons de diffuser des vidéos en direct d'un téléphone à un autre et semble l'avoir principalement fonctionnel, sauf bien sûr la partie la plus importante: lecture du flux. Il semble envoyer le flux à partir d'un téléphone, mais le deuxième téléphone ne peut pas lire le flux.
Voici le code pour le côté de jeu
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();
}
Et voici le code pour le côté 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
}
}
Je reçois l'erreur suivante lors de la tentative de création de 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)
Quelqu'un a-t-il une solution pour cela? Merci d'avance!
J'ai trouvé un projet open source pour implémenter ce que j'essayais. Il traite la vidéo avec des métadonnées via une caméra IP. Bien qu'il n'envoie pas de vidéo directement à un téléphone, il diffuse de la vidéo pour différents appareils à regarder. Le code source peut être trouvé sur la page de projet suivante http://code.google.com/p/ipcamera-for-Android/ .
Avec Android 4.4, il existe une autre façon de lire un flux MJPEG en direct. Le flux que vous lisez doit être diffusé par l'autre appareil sur un port via UDP. Disons que nous avons un flux diffusé sur 192.168.0.101:8080. Nous pouvons lire le flux en ajoutant une WebView à notre mise en page. Ensuite, dans notre activité, nous procédons comme suit:
@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);
}
Dans le contenu, nous indiquons à la page Web d'utiliser le dpi de l'appareil. Pour aider l'utilisateur à pincer le zoom sur la page Web, j'ai ajouté l'échelle initiale suivante = 1, l'échelle minimale = 1, l'échelle utilisateur = oui. Initialement, l'image a sa taille d'origine et ne peut pas devenir plus petite. L'utilisateur peut maintenant redimensionner pour zoomer sur l'image et revenir à sa taille d'origine. La suppression de l'échelle minimale donnera à l'utilisateur un contrôle complet sur le zoom, mais peut rendre l'image si petite que vous ne la trouverez pas.
Vous devez définir le format de sortie de l'enregistreur 8 (MPEG-2TS, uniquement disponible à partir de Android version 3.0+). Dans ce cas, enregistrez la vidéo dans ce format et envoyez le flux vers un autre téléphone et enregistrez-le dans un fichier. Et lisez-le après avoir écrit des données dans le fichier, puis vous pourrez voir le flux en direct.
Remarque - Vous ne pouvez pas lire directement le descripteur de fichier socket, car le socket fd n'est pas recherché. Si vous utilisez le socket fd, vous obtiendrez une "erreur de décalage". L'enregistrement est possible, mais la lecture est limitée.
Télécharger le code source depuis: http://code.google.com/p/ipcamera-for-Android/ ( https://github.com/Teaonly/Android-eye =)
Construisez d'abord le jni (utilisez ndk-build avec cygwin)
J'ai pu construire ce projet avec succès
Jetez un œil à Streaming vers le Android MediaPlayer , qui peut avoir quelques conseils utiles sur la façon de faire le streaming. Je soupçonne que le problème est qu'Android essaie de chercher le fichier, mais étant un socket réseau - il ne peut pas. Peut-être qu'une sorte de tampon disque/mémoire qui prend en charge la recherche pourrait aider?