I am trying to write video to socket (with ParcelFileDescriptor). But when calling mediaPlayer.start() method - an IllegalStateException occurs with this message - "E/MediaRecorder: start failed: -38".
Code for file descriptor (Socket is 100% properly connected by the time programm calls it):
public ParcelFileDescriptor getFileDescriptorToSocket() {
return ParcelFileDescriptor.fromSocket(socket);
}
Preparing media recorder:
private boolean prepareMediaRecorder() {
mediaRecorder = new MediaRecorder();
camera.unlock();
mediaRecorder.setCamera(camera);
// mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setPreviewDisplay(cameraSurface.getHolder().getSurface());
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setVideoSize(320, 240);
mediaRecorder.setVideoFrameRate(30);
//mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P));
mediaRecorder.setOutputFile(MainActivity.socketClient.getFileDescriptorToSocket().getFileDescriptor());
try {
mediaRecorder.prepare();
} catch (IllegalStateException ise) {
// TODO Delete test code
Log.d(TAG, "Error during MediaRecorder preparing: " + ise.getMessage());
ise.printStackTrace();
releaseMediaRecorder();
return false;
} catch (IOException ioe) {
// TODO Delete test code
Log.d(TAG, "Error during MediaRecorder preparing: " + ioe.getMessage());
ioe.printStackTrace();
releaseMediaRecorder();
return false;
}
return true;
}
and call for start recording:
private void startRecording() {
if (!prepareMediaRecorder()) {
// TODO Delete test code
Log.d(TAG, "Error starting recording process");
finish();
} else {
new Thread(new Runnable() {
#Override
public void run() {
try {
mediaRecorder.start();
} catch (Exception e) {
// TODO Delete test code
Log.d(TAG, "Error in recording thread: " + e.getMessage());
e.printStackTrace();
}
}
}).start();
recordingStatus = true;
}
}
I should note that when i disable start recording method - camera works fine - i can properly see camera preview surface.
Related
I am making an app where i can record something and then play it back but when i try to record again my APP crashes.
In the logs I get
01-18 16:51:39.368 27426-27426/com.example.se414011.musicapp1
W/MediaRecorder﹕ mediarecorder went away with unhandled events 01-18
16:51:42.598 27426-27426/com.example.se414011.musicapp1 A/libc﹕ Fatal
signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 27426
(14011.musicapp1)
Any help would be great thanks!
This is my code
public void start(View view) {
try {
myRecorder.prepare();
myRecorder.start();
} catch (IllegalStateException e) {
// start:it is called before prepare()
// prepare: it is called after start() or before setOutputFormat()
e.printStackTrace();
} catch (IOException e) {
// prepare() fails
e.printStackTrace();
}
text.setText("Recording Status: Recording");
stopBtn.setEnabled(true);
startBtn.setEnabled(false);
Toast.makeText(getApplicationContext(), "Start recording...",
Toast.LENGTH_SHORT).show();
}
public void stop(View view) {
try {
myRecorder.stop();
myRecorder.release();
text.setText("Recording Status: Stop recording");
stopBtn.setEnabled(false);
startBtn.setEnabled(true);
Toast.makeText(getApplicationContext(), "Stop recording...",
Toast.LENGTH_SHORT).show();
} catch (IllegalStateException e) {
// it is called before start()
e.printStackTrace();
} catch (RuntimeException e) {
// no valid audio/video data has been received
e.printStackTrace();
}
}
public void play(View view) {
try {
myPlayer = new MediaPlayer();
myPlayer.setDataSource(outputFile);
myPlayer.prepare();
myPlayer.start();
text.setText("Recording Status: Playing");
Toast.makeText(getApplicationContext(), "Start play the recording...",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stopPlay(View view) {
try {
if (myPlayer != null) {
myPlayer.stop();
myPlayer.release();
myPlayer = null;
playBtn.setEnabled(true);
startBtn.setEnabled(true);
stopPlayBtn.setEnabled(false);
text.setText("Recording Status: Stop playing");
Toast.makeText(getApplicationContext(), "Stop playing the recording...",
Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
As you can see in documentation, you can reuse your MediaRecorder only if you don't release it, snippet:
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(PATH_NAME);
recorder.prepare();
recorder.start(); // Recording is now started
...
recorder.stop();
recorder.reset(); // You can reuse the object by going back to setAudioSource() step
recorder.release(); // Now the object cannot be reused
You didn't post where you set your object myRecorder, and if you create a new one when you want to record again, but if you're reusing the same object after calling release() you'll be in problems, my suggestions are don't release it until you're finished or create a new MediaRecorder for each record.
boolean stopped = false;
public void start(View view) {
//your code...
stopped = false;
}
public void stop(View view) {
try {
myRecorder.stop();
//myRecorder.release();
stopped = true;
//your code
}
}
public void onDestroy(){
if(stopped)
myRecorder.release();
}
Hi I am trying to work on a hardware camera control in android,
I am able to get the preview of the camera on the surface view,
however I am unable to record any video, as on starting the video recording I get the following error:
Media server died
Camera server died
ICamera died
error 100
the code for capture is as under
public void onCaptureClick(View view){
if(!isRecording)
new MediaPrepareTask().execute(null,null,null);
else{
mMediaRecorder.stop();
releaseMediaRecorder();
mCamera.lock();
setCaptureButtonText("Start");
isRecording = false ;
releaseCamera();
}
}
This is the media prepare task
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean>{
#Override
protected Boolean doInBackground(Void... arg0) {
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
Log.i(TAG,"Media recording started");
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
return false;
}
return true;
}
#Override
protected void onPostExecute(Boolean result){
if(!result){
MainActivity.this.finish();
}
setCaptureButtonText("Stop");
}
}
This is where I set the property for recording
private boolean prepareVideoRecorder(){
Log.i(TAG,"Starting to prepare");
Camera.Parameters parameters = mCamera.getParameters() ;
Log.i(TAG,"Got Property");
List<Camera.Size> mSupportedPreviewSize = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSize,
mPreview.getWidth(), mPreview.getHeight());
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
profile.videoFrameWidth = optimalSize.width ;
profile.videoFrameHeight = optimalSize.height ;
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
Log.i(TAG,"Set Parameters");
try{
// // mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
mCamera.setPreviewDisplay(mPreview.getHolder());
}catch(IOException iOEx){
iOEx.printStackTrace();
Log.e(TAG, "Failed to set preview display ");
return false ;
}
////////////////////////////////now for the media recorder ///////////////////////
mMediaRecorder = new MediaRecorder();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
Log.i(TAG,"Set camera for recorder");
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
mMediaRecorder.setProfile(profile);
Log.i(TAG,CameraHelper.getOutputMediaFile(CameraHelper.MEDIA_TYPE_VIDEO).toString());
mMediaRecorder.setOutputFile(CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
Log.i(TAG,"Set the ouptut format");
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
Log.i(TAG,"All is well");
return true;
}
this is for anyone reading the question
the issue is with the surface to be added to the media recorder as well,
just add the surface to the media recorder and it works
Following code is not allowing to record a video. This code is invoked through a button but the button freezes. I am trying to use the camcorder profile to record the video.
public void startRecording() {
mCamera.unlock();
mrec.setCamera(mCamera);
CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mrec.setProfile(cpHigh);
File dir = new File(SdCardPath + Directory);
if (!dir.exists()) {
if (dir.mkdir()) {
Log.v(STORAGE_SERVICE, "Created directory");
} else {
Log.v(STORAGE_SERVICE, "Failed to create Directory");
}
}
FullFilePath = SdCardPath + Directory + RecordFileName;
mrec.setOutputFile(FullFilePath);
mrec.setPreviewDisplay(surfaceHolder.getSurface());
try {
mrec.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mrec.start();
}
Always do you best to catch exceptions thrown:
public void startRecording() {
try {
mCamera.unlock();
catch (RuntimeException ex){
// looks like camera was locked in the first place, who is using it?
}
mrec.setCamera(mCamera);
///...the rest of your code.
}
I'm trying to create a video recorder on Android, and I've prepared my code which is supposed to be working - but I constantly get an error message start failed: -19.
Here's my code:
public boolean startRecording() {
try {
camera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.i(TAG, "Error");
}
});
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
Log.i(TAG, "a");
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
Log.i(TAG, "b");
mediaRecorder.setMaxDuration(maxDurationInMs); // set to 20000
String uniqueOutFile = OUTPUT_FILE + System.currentTimeMillis() + ".3gp";
File outFile = new File(uniqueOutFile);
if (outFile.exists()) {
outFile.delete();
}
mediaRecorder.setOutputFile(uniqueOutFile);
mediaRecorder.setVideoFrameRate(videoFramesPerSecond); // set to 20
mediaRecorder.setVideoSize(sView.getWidth(), sView.getHeight());
Log.i(TAG, "c");
mediaRecorder.setPreviewDisplay(holder.getSurface());
mediaRecorder.setMaxFileSize(maxFileSizeInBytes); // set to 50000
mediaRecorder.prepare();
Log.i(TAG, "d");
mediaRecorder.start();
Log.i(TAG, "e");
return true;
} catch (IllegalStateException e) {
Log.i(TAG, "f");
Log.e(TAG, e.getMessage());
e.printStackTrace();
camera.lock();
return false;
} catch (IOException e) {
Log.i(TAG, "g");
Log.e(TAG, e.getMessage());
e.printStackTrace();
camera.lock();
return false;
} catch (RuntimeException e) {
Log.i(TAG, "h");
Log.e(TAG, e.getMessage());
camera.lock();
return false;
}
}
All the debug logs (from "a" through "d") are printed in log, so it seems that all the steps upto mediaRecorder.prepare() are properly done. Then it catches a RuntimeException with message start failed: -19. There is a similar question, but that doesn't solve my problem.
Is there any other reason to get such an error?
Just found out the bug, in this line:
mediaRecorder.setVideoSize(sView.getWidth(), sView.getHeight());
after commenting out this line, the code runs perfectly!
I solved my problem once i added this for video recording
/**
* Start video recording by cleaning the old camera preview
*/
private void startVideoRecorder() {
// THIS IS NEEDED BECAUSE THE GLASS CURRENTLY THROWS AN ERROR OF
// "MediaRecorder start failed: -19"
// THIS WONT BE NEEDED INCASE OF PHONE AND TABLET
// This causes crash in glass kitkat version so remove it
// try {
// mCamera.setPreviewDisplay(null);
// } catch (java.io.IOException ioe) {
// Log.d(TAG,
// "IOException nullifying preview display: "
// + ioe.getMessage());
// }
// mCamera.stopPreview();
// mCamera.unlock();
recorder = new MediaRecorder();
// Let's initRecorder so we can record again
initRecorder();
}
/**
* Initialize video recorder to record video
*/
private void initRecorder() {
try {
File dir = new File(folderPath);
if (!dir.exists()) {
dir.mkdirs();
}
mCamera.stopPreview();
mCamera.unlock();
videofile = new File(dir, fileName + ".mp4");
recorder.setCamera(mCamera);
// Step 2: Set sources
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
recorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
recorder.setOutputFile(videofile.getAbsolutePath());
// Step 5: Set the preview output
recorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
recorder.setMaxDuration(video_duration * 1000);
recorder.setOnInfoListener(new OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
mCamera.stopPreview();
releaseMediaRecorder();
/*
* initiate media scan and put the new things into the
* path array to make the scanner aware of the location
* and the files you want to see
*/MediaScannerConnection.scanFile(
CuxtomCamActivity.this,
new String[] { videofile.getPath() }, null,
null);
Intent intent = new Intent();
intent.putExtra(CuxtomIntent.FILE_PATH,
videofile.getPath());
intent.putExtra(CuxtomIntent.FILE_TYPE, FILE_TYPE.VIDEO);
setResult(RESULT_OK, intent);
finish();
}
}
});
recorder.prepare();
recorder.start();
} catch (Exception e) {
Log.e("Error Stating CuXtom Camera", e.getMessage());
}
}
private void releaseMediaRecorder() {
if (recorder != null) {
recorder.reset(); // clear recorder configuration
recorder.release(); // release the recorder object
recorder = null;
}
}
For detailed guide refer to this Open Source Cuxtom Cam
the problem is in your setVideoSize() code .
and why this code error ...
From the research I have done, error code -19 comes about when there is a problem with the size of the video as set by MediaRecorder#setVideoSize()
run this code , and see whitch screen that your camera in your device can support :
final List<Camera.Size> mSupportedVideoSizes = getSupportedVideoSizes(mCamera);
for (Camera.Size str : mSupportedVideoSizes)
Log.e(TAG, "mSupportedVideoSizes "+str.width + ":" + str.height + " ... "
+ ((float) str.width / str.height));
and method is :
public List<Size> getSupportedVideoSizes(Camera camera) {
if (camera.getParameters().getSupportedVideoSizes() != null) {
return camera.getParameters().getSupportedVideoSizes();
} else {
// Video sizes may be null, which indicates that all the supported
// preview sizes are supported for video recording.
return camera.getParameters().getSupportedPreviewSizes();
}
}
I had that problem with some specific phones, I've found out that I couldn't set camcoder profile sizes in some of them. But when that worked for the problematic androids it stopped working on the previous working devices.
So in the end my implemented logic was something like:
Set width/height
Try to start the merdia recorder
In case of exception, try again without setting width/height
Kind of a trash logic, but that worked.
I've setup a github project with that implementation, try it out: https://github.com/rafaelsilverio/MediaRecorder
I also encountered this problem and annotated the following two ways, because the hardware does not support the two configurations.
MediaRecorder .setVideoSize()
MediaRecorder .setVideoFrameRate()
How to implement sound waves during recording sound in android??
in the below code
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
resultView = (TextView) findViewById(R.id.output);
try {
// the soundfile
File storageDir = new File(Environment
.getExternalStorageDirectory(), "com.hascode.recorders");
storageDir.mkdir();
Log.d(APP_TAG, "Storage directory set to " + storageDir);
outfile = File.createTempFile("hascode", ".3gp", storageDir);
// init recorder
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(outfile.getAbsolutePath());
// init player
player.setDataSource(outfile.getAbsolutePath());
} catch (IOException e) {
Log.w(APP_TAG, "File not accessible ", e);
} catch (IllegalArgumentException e) {
Log.w(APP_TAG, "Illegal argument ", e);
} catch (IllegalStateException e) {
Log.w(APP_TAG, "Illegal state, call reset/restore", e);
}
btRecord = (Button) findViewById(R.id.btRecord);
btRecord.setOnClickListener(handleRecordClick);
btPlay = (Button) findViewById(R.id.btPlay);
btPlay.setOnClickListener(handlePlayClick);
}
private final OnClickListener handleRecordClick = new OnClickListener() {
#Override
public void onClick(View view) {
if (!recording) {
startRecord();
} else {
stopRecord();
}
}
};
private final OnClickListener handlePlayClick = new OnClickListener() {
#Override
public void onClick(View view) {
if (!playing) {
startPlay();
} else {
stopPlay();
}
}
};
private void startRecord() {
Log.d(APP_TAG, "start recording..");
printResult("start recording..");
try {
recorder.prepare();
recorder.start();
recording = true;
} catch (IllegalStateException e) {
Log
.w(APP_TAG,
"Invalid recorder state .. reset/release should have been called");
} catch (IOException e) {
Log.w(APP_TAG, "Could not write to sd card");
}
}
private void stopRecord() {
Log.d(APP_TAG, "stop recording..");
printResult("stop recording..");
recorder.stop();
recorder.reset();
recorder.release();
recording = false;
}
private void startPlay() {
Log.d(APP_TAG, "starting playback..");
printResult("start playing..");
try {
playing = true;
player.prepare();
player.start();
} catch (IllegalStateException e) {
Log.w(APP_TAG, "illegal state .. player should be reset");
} catch (IOException e) {
Log.w(APP_TAG, "Could not write to sd card");
}
}
private void stopPlay() {
Log.d(APP_TAG, "stopping playback..");
printResult("stop playing..");
player.stop();
player.reset();
player.release();
playing = false;
}
private void printResult(String result) {
resultView.setText(result);
}
Do you want to merge your recorded sound with a pre-recorded sound of waves?
If so, maybe you could try to create two sound objects of the different sources. Then you maybe could write to the output file in intervals. One interval for the pre-recorded and one for the fresh one.
I actually don't know if that's even a valid way to do this. Just what my general approach would've been facing this problem.