0

I want to record a video and save it on the sd card. Because I want to do some modification on the video (later! just now I want to save the mp4 video) I decided to work with an FileDescriptor. Here I set up the MediaRecorder:

 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
        mNextVideoAbsolutePath = getVideoFilePath(getActivity());
    }

//the output file is a FileDescriptor
  mMediaRecorder.setOutputFile(getStreamFd());

 mMediaRecorder.setVideoEncodingBitRate(10000000);
 mMediaRecorder.setVideoFrameRate(30);
 mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
 mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

the target where the video is stored:

private String getVideoFilePath(Context context) {
    return context.getExternalFilesDir(null).getAbsolutePath() + "/"
           + System.currentTimeMillis() + ".mp4";
}

FileDescriptor:

private FileDescriptor getStreamFd() {
    ParcelFileDescriptor[] pipe=null;

    try {
        pipe=ParcelFileDescriptor.createPipe();
        new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]),
        new FileOutputStream(mNextVideoAbsolutePath)).start();
    }
    catch (IOException e) {
        Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
    }

    return(pipe[1].getFileDescriptor());
}

In the transfer thread the video is saved:

static class TransferThread extends Thread {
    InputStream in;
    FileOutputStream out;

    TransferThread(InputStream in, FileOutputStream out) {
        this.in=in;
        this.out=out;
    }

    @Override
    public void run() {
        byte[] buf=new byte[8192];
        int len;

        try {
            while ((len=in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

            in.close();

            out.flush();
            out.getFD().sync();
            out.close();
        }
        catch (IOException e) {
            Log.e(getClass().getSimpleName(),
                    "Exception transferring file", e);
        }

    }
}

When I run the application, then a video is created. The video has a mp4 extentions and the size of the video seems to be alright.

But I can not play the video.

I tried different VideoEncoders or OutputFormats, but without any success.

Theres a similar question: Anyone Have MediaRecorder Working with ParcelFileDescriptor and createPipe()? But it does not match my problem. I have set all necessary permissions in the manifest.

Are there any problems with an incorrect header of the video?

Community
  • 1
  • 1
mkersche17
  • 105
  • 13
  • "But it does not match my problem" -- yes, it does. A pipe does not result in a seekable stream. Any format that requires the `MediaRecorder` to rewind to the beginning of the stream to write a header will fail with a pipe. – CommonsWare May 17 '16 at 22:13
  • do you have any advice, how i can fix the problem? How can I create an seekable stream? – mkersche17 May 17 '16 at 22:22
  • Use a file, not a pipe. Or, use a raw format, one that does not require a header (though I am not sure if there is such a format for video). – CommonsWare May 17 '16 at 22:28
  • maybe its possible to add the header information later? So I can read pure video file, coming from the pipe (without any header), add the header and transform it to a mp4 video file? – mkersche17 May 17 '16 at 22:54
  • "maybe its possible to add the header information later?" -- I doubt that you have all the data that needs to go into the header. – CommonsWare May 17 '16 at 22:55
  • well, I think I have all information. But I do not know, how to build a mp4 header..Great would be a library, which creates a blank header and I could fill it with all the informations. – mkersche17 May 22 '16 at 21:56

0 Answers0