Потоковое видео в реальном времени с телефона на телефон с помощью разъема fd

Я новичок в программировании на Android и обнаружил, что я застрял. Я изучал различные способы потокового видео в реальном времени с телефона на телефон и, похоже, в основном функционировал, за исключением, конечно, самой важной части: игры в потоке. Кажется, он отправляет поток с одного телефона, но второй телефон не может воспроизводить поток.

Вот код для игровой стороны

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();
}

И вот код для потоковой стороны

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
    }
}

При попытке создать 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)

Есть ли у кого-нибудь исправление? Спасибо заранее!

Ответ 1

Я нашел проект с открытым исходным кодом для реализации того, что я пытался. Он обрабатывает видео с помощью метаданных через IP-камеру. Хотя он не отправляет видео непосредственно на телефон, он транслирует видео на различные устройства для просмотра. Исходный код можно найти на следующей странице проекта http://code.google.com/p/ipcamera-for-android/.

В Android 4.4 есть еще один способ воспроизвести живой поток MJPEG. Поток, который вы играете, должен транслироваться другим устройством на порте через UDP. Скажем, у нас есть поток, транслируемый по 192.168.0.101:8080. Мы можем воспроизвести поток, добавив WebView в наш макет. Затем в нашей деятельности мы делаем следующее:

@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);
}

В содержании мы говорим на веб-странице, чтобы использовать dpi. Чтобы поддержать пользователя для увеличения масштаба на веб-странице, я добавил следующее начальное масштабирование = 1, минимальное value = 1, масштабируемое пользователем = да. Первоначально изображение является оригинальным размером и не может быть меньше. Теперь пользователь может масштабироваться, чтобы увеличить изображение и получить его оригинальный размер. Удаление минимальной шкалы даст пользователю полный контроль над масштабированием, но может привести к уменьшению изображения, которое вы не можете найти.

Ответ 2

Вы должны установить выходной формат рекордера 8 (MPEG-2TS, доступный только с версии для Android версии 3.0+). В этом случае запишите видео в этом формате и отправьте поток на другой телефон и сохраните его в файле. И воспроизведите его после записи некоторых данных в файл, затем вы можете увидеть прямой эфир.

Примечание. Вы не можете напрямую играть через дескриптор файла сокета, потому что сокет fd не доступен для поиска. Если вы используете сокет fd, вы получите "ошибку смещения". Запись возможна, но воспроизведение ограничено.

Ответ 3

Взгляните на Поток на Android MediaPlayer, в котором, возможно, есть несколько полезных советов о том, как сделать потоковое вещание. Я подозреваю, что проблема заключается в том, что Android пытается искать в файле, но является сетевым сокетом - он не может. Может быть, может помочь какой-то буфер диска/памяти, который поддерживает поиск?

Ответ 5

Можете ли вы объяснить это с незапамятных времен, как вы создали jni. Я использую android studio, а также новичок в android progrramming