Проблема MediaRecorder на Android Lollipop
Я тестирую libstreaming на новом Android Lollipop, и этот код который работал над предыдущим выпуском, похоже, запускает исключение.
try {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setVideoEncoder(mVideoEncoder);
mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
mMediaRecorder.setVideoSize(mRequestedQuality.resX,mRequestedQuality.resY);
mMediaRecorder.setVideoFrameRate(mRequestedQuality.framerate);
// The bandwidth actually consumed is often above what was requested
mMediaRecorder.setVideoEncodingBitRate((int)(mRequestedQuality.bitrate*0.8));
// We write the ouput of the camera in a local socket instead of a file !
// This one little trick makes streaming feasible quiet simply: data from the camera
// can then be manipulated at the other end of the socket
mMediaRecorder.setOutputFile(mSender.getFileDescriptor());
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
throw new ConfNotSupportedException(e.getMessage());
}
Исключенное исключение:
MediaRecorder: сбой запуска -38
11-18 09:50:21.028: W/System.err(15783): net.majorkernelpanic.streaming.exceptions.ConfNotSupportedException
11-18 09:50:21.028: W/System.err(15783): at net.majorkernelpanic.streaming.video.VideoStream.encodeWithMediaRecorder(VideoStream.java:442)
11-18 09:50:21.028: W/System.err(15783): at net.majorkernelpanic.streaming.MediaStream.start(MediaStream.java:250)
Я попытался прокомментировать:
mMediaRecorder.setOutputFile(mSender.getFileDescriptor());
не было запущено никаких исключений, но когда я начну передавать потоки, сообщите мне, что нужен выходной файл.
Помогите оценить.
Ответы
Ответ 1
Я подал сообщение об ошибке в AOSP.
https://code.google.com/p/android/issues/detail?id=80715
"Текущие политики SELinux не позволяют медиасерверу обрабатывать сгенерированные сгенерированные абстрактные сокеты домена unix.
Вместо этого я рекомендую вам создать пару-тройку (http://developer.android.com/reference/android/os/ParcelFileDescriptor.html#createPipe()), которая разрешена политикой Android 5.0.
"
Я не знаю, почему они это сделали или как мы должны были знать.
Я использую очень старую/модифицированную (не могу сказать) версию libstreaming, где mediastream все еще расширен от mediarecorder, но, глядя на текущую версию, в MediaStream вы, вероятно, захотите изменить createSockets на что-то, включая следующее:
ParcelFileDescriptor[] parcelFileDescriptors =ParcelFileDescriptor.createPipe();
parcelRead = new ParcelFileDescriptor(parcelFileDescriptors[0]);
parcelWrite = new ParcelFileDescriptor(parcelFileDescriptors[1]);
затем в вашем видео/аудиопотоке
setOutputFile(parcelWrite.getFileDescriptor());
и в том же файле
изменение
// The packetizer encapsulates the bit stream in an RTP stream and send it over the network
mPacketizer.setInputStream(mReceiver.getInputStream());
mPacketizer.start();
к
InputStream is = null;
try{ is = new ParcelFileDescriptor.AutoCloseInputStream(parcelRead);
}
catch (Exception e){}
mPacketizer.setInputStream(is);
Как отметил andreasperelli в комментарии, обязательно закройте ParcelFileDescriptors в closeSockets() или в зависимости от вашей реализации и версии перед closeSockets() и перед вызовом MediaRecorder.stop().
Ответ 2
на Android 6.0 Я разрешаю эту проблему с кодом
new Thread(new Runnable() {
@Override public void run() {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (true) {
byte[] buffer = new byte[0];
try {
buffer = new byte[inputStream.available()];
} catch (IOException e) {
e.printStackTrace();
}
try {
inputStream.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
try {
mSender.getOutputStream().write(buffer);
mSender.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
Я использую файл в качестве буфера и записываю байты в другой поток. Выход MediaRecorder в файл.