Android - 将视频从摄像头流式传输到另一个Android设备

时间:2017-12-07 04:55:37

标签: android sockets android-studio video streaming

已经过了一个月,我现在失去了希望。

我正在尝试从设备1捕获视频并将其流式传输到设备2.

我已经可以保存视频文件,但问题是我在设备1使用相机拍摄视频时同时将其流式传输到另一部手机。

我已经看过很多有关流媒体视频的教程并在我的视频中应用,但视频已经保存在设备中,而不是同时捕获和流式传输。

我希望你能帮助我。

UPDATE .............................................. ..................

目前我可以通过socket发送文本。我只是将图像捕获包含在那里以测试保存手机中的数据,但它还没有通过套接字发送它。

这是我现在的代码:

CameraActivity.Java(既用作服务器又用于捕获数据的那个)

package com.example.martinlloydjose.shaveyourback;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
//import android.graphics.Camera;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.provider.MediaStore.Files.FileColumns;



//import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.os.Bundle;
import android.widget.Toast;

import static android.content.ContentValues.TAG;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;

public class CameraActivity extends AppCompatActivity{

    //camera --------------------------------------------------------------------------------------------
    /*camera
    private static final int CAMERA_REQUEST = 1888;
    private ImageView imageView;
    */
    private Camera mCamera;
    private SurfaceView mPreview;
    private MediaRecorder mMediaRecorder;
    //end of camera --------------------------------------------------------------------------------------------


    //server ////////////////////////////////////////////////////////////////////////////////////////////
    EditText welcomeMsg;
    TextView infoIp;
    TextView infoMsg;
    String msgLog = "";

    ServerSocket httpServerSocket;
    //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        //camera --------------------------------------------------------------------------------------------

        /*
        this.imageView = (ImageView)this.findViewById(R.id.imageView1);
        Button photoButton = (Button) this.findViewById(R.id.button1);
        photoButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            }
        });
        */

        // Create an instance of Camera
        /** Showing current image */
        try {
            new AlertDialog.Builder(this).setTitle("Test").setMessage("Running").setNeutralButton("Close", null).show();
            mCamera = getCameraInstance();

            mCamera.setDisplayOrientation(90);

            // Create our Preview view and set it as the content of our activity.
            mPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mPreview);
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }

        /** end of Showing current image */

        /** Capturing Image */
        try {
            Button captureButton = (Button) findViewById(R.id.button_capture);
            captureButton.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // get an image from the camera
                            mCamera.takePicture(null, null, mPicture);
                        }
                    }
            );
        }catch (Exception error){
            Toast.makeText(this, "An error occured with your camera: "+error.toString(), Toast.LENGTH_LONG).show();
        }
        /** end of Capturing Image */

        //end of camera --------------------------------------------------------------------------------------------



        //server ////////////////////////////////////////////////////////////////////////////////////////////
        welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
        infoIp = (TextView) findViewById(R.id.infoip);
        infoMsg = (TextView) findViewById(R.id.msg);

        infoIp.setText(getIpAddress() + ":" + HttpServerThread.HttpServerPORT + "\n");

        HttpServerThread httpServerThread = new HttpServerThread();
        httpServerThread.start();
        //end of server ////////////////////////////////////////////////////////////////////////////////////////////

    }


    //camera --------------------------------------------------------------------------------------------
    /*
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
            Bitmap photo = (Bitmap) data.getExtras().get("data");
            imageView.setImageBitmap(photo);
        }
    }
    */

    /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }
    /** end of Check if this device has a camera */

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }
    /** end of A safe way to get an instance of the Camera object. */

    /** Capture Pictures */
    private PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
            if (pictureFile == null){
                Log.d(TAG, "Error creating media file, check storage permissions: "
                        /*e.getMessage()*/);
                return;
            }

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };

    /** end of Capture Pictures */


    /** Setting the storage */

    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;

    /** Create a file Uri for saving an image or video */
    private static Uri getOutputMediaFileUri(int type){
        return Uri.fromFile(getOutputMediaFile(type));
    }

    private static File getOutputMediaFile(int type){
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "MyCameraApp");
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                Log.d("MyCameraApp", "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE){
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_"+ timeStamp + ".jpg");
        } else if(type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_"+ timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }
    /** end of Setting the storage */


    /** releasing camera */
    @Override
    protected void onPause() {
        super.onPause();
        //releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    /*private void releaseMediaRecorder(){
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }*/

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
    /** end of releasing camera */

    //end of camera --------------------------------------------------------------------------------------------



    //server -001 ////////////////////////////////////////////////////////////////////////////////////////////
    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (httpServerSocket != null) {
            try {
                httpServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    private String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces
                        .nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface
                        .getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress.nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += "SiteLocalAddress: "
                                + inetAddress.getHostAddress() + "\n";
                    }
                }
            }

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n" +e.getMessage();
        }

        return ip;
    }


    private class HttpServerThread extends Thread {

        static final int HttpServerPORT = 8888;

        @Override
        public void run() {
            Socket socket = null;

            try {
                httpServerSocket = new ServerSocket(HttpServerPORT);

                while(true){
                    socket = httpServerSocket.accept();

                    HttpResponseThread httpResponseThread =
                            new HttpResponseThread(
                                    socket,
                                    welcomeMsg.getText().toString());
                    httpResponseThread.start();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private class HttpResponseThread extends Thread {

        Socket socket;
        String h1;

        HttpResponseThread(Socket socket, String msg){
            this.socket = socket;
            h1 = msg;
        }

        @Override
        public void run() {
            BufferedReader is;
            PrintWriter os;
            String request;


            try {
                is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                request = is.readLine();

                os = new PrintWriter(socket.getOutputStream(), true);

                String response =
                        "<html><head></head>" +
                                "<body>" +
                                "<h1>" + h1 + "</h1>" +
                                "</body></html>";

                os.print("HTTP/1.0 200" + "\r\n");
                os.print("Content type: text/html" + "\r\n");
                os.print("Content length: " + response.length() + "\r\n");
                os.print("\r\n");
                os.print(response + "\r\n");
                os.flush();
                socket.close();


                msgLog += "Request of " + request
                        + " from " + socket.getInetAddress().toString() + "\n";
                CameraActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        infoMsg.setText(msgLog);
                    }
                });

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

            return;
        }
    }
    //end of server -001 ////////////////////////////////////////////////////////////////////////////////////////////


}

ViewerActivity.java

package com.example.martinlloydjose.shaveyourback;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;

public class ViewerActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewer);

        WebView webView = (WebView)findViewById(R.id.webViewStream);
        webView.loadUrl("http://10.0.2.15:8888");
        webView.getSettings().setBuiltInZoomControls(true);
    }
}

Activity_Camera.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.CameraActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Connect using the following details"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/welcomemsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Test Message"
        android:layout_below="@+id/tvTitle"
        />

    <TextView
        android:id="@+id/infoip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/welcomemsg"
        />

    <ScrollView
        android:id="@+id/scrollSlider"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:layout_below="@+id/infoip">

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>

    <!--
    <ImageView
        android:id="@+id/imageView1"
        android:layout_height="fill_parent"
        android:src="@drawable/icon"
        android:layout_width="fill_parent"
        android:layout_below="@+id/scrollSlider"
        >
    </ImageView>

    <Button
        android:id="@+id/button1"
        android:layout_below="@id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="-50sp"
        android:text="capture">
    </Button>
    -->

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_below="@+id/scrollSlider"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:text="Capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_below="@+id/camera_preview"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="-50sp"
        />

</RelativeLayout>

Activity_Viewer.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="0dp"
    tools:context="com.example.martinlloydjose.shaveyourback.ViewerActivity">

    <WebView
        android:id="@+id/webViewStream"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="0dp"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp" />

</RelativeLayout>

1 个答案:

答案 0 :(得分:0)

我假设你已经有一台服务器作为中介。在这种情况下,您可以设置NGINX服务器环境并在其上安装nginx-rtmp-module。此外,您还可以使用SRS实时流式集群,它还可以创建自己的服务器环境。

因为它们都是开源的,所以它们具有成本效益。

此外,srs 3.0比nginx-rtmp-module更加先进,因为它具有大量的功能。但是对于简单的流媒体,我认为是你的情况,两者都同样有用,但我会建议nginx-rtmo-module,因为nginx的强大功能。

这涵盖了服务器创建的所有内容。之后,您可以在Android上使用vlc,或者从github使用任何rtmp流式回购来进行流式传输。为了接收您的流,大多数主要视频播放器支持直播。所以你只需要输入你的流媒体rtmp:// ....地址。


以下是一些参考文献,虽然它们已经过时,但核心仍然是相同的。

Nginx Rtmp 1

Nginx Rtmp 2

Nginx Rtmp 3