1

MediaRecorder を使用してビデオ (H264/3gpp) のみを記録しようとしており、LocalSocket 記述子を MediaRecorder に渡しました。データは受信できますが、動画を再生できません。オーディオ(AMR)でも同じコードが機能します。

LocalSocket クラス

public class MediaStreamer extends MediaRecorder{

    private static int id = 0;

    private LocalServerSocket lss = null;
    private LocalSocket receiver, sender = null;

    public void prepare() throws IllegalStateException,IOException {

        receiver = new LocalSocket();
        try {
            lss = new LocalServerSocket("librtp-"+id);
            receiver.connect(new LocalSocketAddress("librtp-"+id));
            receiver.setReceiveBufferSize(4096);
            receiver.setSendBufferSize(4096);
            sender = lss.accept();
            sender.setReceiveBufferSize(4096);
            sender.setSendBufferSize(4096); 
            id++;
        } catch (IOException e1) {
            throw new IOException("Can't create local socket !");
        }

        setOutputFile(sender.getFileDescriptor());

        try {
            super.prepare();
        } catch (IllegalStateException e) {
            closeSockets();
            throw e;
        } catch (IOException e) {
            closeSockets();
            throw e;
        }

    }

    public InputStream getInputStream() {

        InputStream out = null;

        try {
            out = receiver.getInputStream();
        } catch (IOException e) {
        }

        return out;

    }


    public void stop() {
        closeSockets();
        super.stop();
    }

    private void closeSockets() {
        if (lss!=null) {
            try {
                lss.close();
                sender.close();
                receiver.close();
            }
            catch (IOException e) {

            }
            lss = null; sender = null; receiver = null;
        }
    }
}

メディアレコーダー

video = new MediaStreamer();
video.reset();

video.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
video.setPreviewDisplay(holder.getSurface());
video.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
video.setVideoFrameRate(VideoConstants.frameRate);
video.setVideoEncodingBitRate(VideoConstants.bitRate*1000);
video.setVideoSize(VideoConstants.resolationX, VideoConstants.resolationY);
video.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

try {
   video.prepare();
   videoWriter = new Writer(Environment.getExternalStorageDirectory()+"/video.mp4",video.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
video.start();
videoWriter.startWriting();
4

3 に答える 3

1

この質問は少し古いですが、私は現在この分野でいくつかの作業を行っているので、このようにつまずいた人を助けるかもしれない答えを追加しようと考えました.

ここでの根本的な問題は、3GPP (MP4 など) がライブでストリーミング可能な形式ではないことです。そのため、データがソケット経由でキャプチャされたとしても、オーディオまたはビデオのキャプチャの最後に通常書き込まれる重要なファイル ヘッダーが欠落しています (ソケットはローカル ファイルのようにシークできないため) - したがって、データを再生できません。

AMR にはこのファイル ヘッダーの制限がないため、OP のオーディオ録音は上記のコードで正常に機能します。

データに対して後処理を実行して手動でファイル ヘッダーを追加する簡単な方法はありません。したがって、解決策は次のいずれかです。

  1. 記録形式として 3GPP または MP4 を使用しないでください
  2. Spydroid プロジェクトで使用されているものと同様のパケッタイザーを作成します。

お役に立てれば。

于 2013-08-30T05:10:28.560 に答える
1

MPEG4 形式のヘッダーを削除する必要があります。localscoket からの入力ストリームには、ビデオにアクセスするために削除する必要がある MPEG4 ヘッダーが含まれています。

同様のことを行うSpydroidを確認してください

于 2014-01-09T06:05:52.307 に答える
1

You could use this example to remove the MP4 header:

InputStream reader = video.getInputStream();
byte buffer[] = new byte[4];
while (!Thread.interrupted()) {
   while (reader.read() != 'm');
      reader.read(buffer,0,3);
      if (buffer[0] == 'd' && buffer[1] == 'a' && buffer[2] == 't') break;
}

I have seen this code in lib libstreaming (VideoStream.java). Is the same lib used in Spydroid.

于 2014-06-10T12:00:45.677 に答える