Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streaming video from MediaRecorder through LocalSocket

I'm trying to send h264/AAC video from Android's MediaRecorder through a local Socket. The goal is to to send video to a WOWZA server throught RTMP or RTSP, but it's giving me a lot of trouble and for now I'm just trying to write the data to a file from the LocalServerSocket.

Here is some code. Sorry it's not really clean, but I spent hours testing many things and my project is a mess right now.

In the Camera activity, the output file setup:

LocalSocket outSocket = new LocalSocket();

try {
    outSocket.connect(new LocalSocketAddress(LOCAL_SOCKET));
} catch (Exception e) {
    Log.i(LOG_TAG, "Error connecting socket: "+e);
}
mMediaRecorder.setOutputFile(outSocket.getFileDescriptor());

The LocalServerSocket implementation:

try {
    mLocalServerSocket = new LocalServerSocket(mName);
} catch (Exception e) {
    Log.e(LOG_TAG, "Error creating server socket: "+e);
    return;
}

while (true) {

    File out = null;
    FileOutputStream fop = null;
    try {
        mLocalClientSocket = mLocalServerSocket.accept();

        InputStream in = mLocalClientSocket.getInputStream();

        out = new File(mContext.getExternalFilesDir(null), "testfile.mp4");
        fop = new FileOutputStream(out);

        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) >= 0) {

            Log.i(LOG_TAG, "Writing "+len+" bytes");
            fop.write(buffer, 0, len);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    finally{
        try {
            fop.close();
            mLocalClientSocket.close();
        } catch (Exception e2) {}
    }
}

The problem is that the file resulting from this is not readable by any media player. Do you think this is because of an encoding issue? This code should generate a binary file if I understand well?!

Thanks in advance, cheers.

like image 603
Simon Avatar asked May 23 '12 13:05

Simon


2 Answers

Ok, I've found why the files couldn't play. In MP4 and 3GPP files, there is a header containing the bytes:

ftyp3gp4 3gp43gp6 wide mdat

in HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

The 4 bytes before the 'mdat' tag represent the position of another 'moov' tag situated at the end of the file. The position is usually set when the recording is over, but as MediaRecorder can't seek sockets, it can't set these bytes to the correct value in our case.

My problem now is to find a way to make such a file streamable, as it involves for it to be played before the recording is over.

like image 174
Simon Avatar answered Nov 17 '22 08:11

Simon


You could try using mp4box to restructure your file. The moov box gives the indexes for each audio and video sample. If that is at the end of the file, it makes it difficult to stream.

This might help: http://boliston.wordpress.com/tag/moov-box/

Or this: mp4box -inter 0.5 some_file.mp4

(I don't have the chance to try currently)

If you need this to work with your app, I am not aware of any activities to port mp4box to Android.

like image 34
AOSP_junkie Avatar answered Nov 17 '22 08:11

AOSP_junkie