Android フロントカメラのビデオ録画に失敗しました (MediaRecorder: start failed: -19)
エラーログ
今日、電話録画のビデオエラーに遭遇しました。mx4のフロントカメラは録画できませんが、リアカメラはOKです。エラーログは以下の通りです。
com.example E/MediaRecorder: start failed: -19
com.example W/System.err: java.lang.RuntimeException: start failed.
com.example W/System.err: at android.media.MediaRecorder.start(Native Method)
com.example W/System.err: at com.example.activity.message.media.CaptureVideoActivity.startRecorderInternal(CaptureVideoActivity.java: 448)
com.example W/System.err: at com.example.activity.message.media.CaptureVideoActivity.startRecorder(CaptureVideoActivity.java:406)
com.example W/System.err: at com.example.activity.message.media.CaptureVideoActivity.onClick(CaptureVideoActivity.java:166)
com.example W/System.err: at android.view.View.performClick(View.java:4869)
com.example W/System.err: at android.view.View$PerformClick.run(View.java:20243)
com.example W/System.err: at android.os.Handler.handleCallback(Handler.java:815)
com.example W/System.err: at android.os.Handler.dispatchMessage(Handler.java:104)
com.example W/System.err: at android.os.Looper.loop(Looper.java:194)
com.example W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5590)
com.example W/System.err: at java.lang.reflect.Method.invoke(Native Method)
com.example W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
com.example W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
com.example W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
com.example D/Camera-JNI: (tid:13619)[native_release] + context=0x9bf6afb0 camera=0x9eb867b0
com.example D/Camera-JNI: [native_release] context->getStrongCount(2) camera->getStrongCount(2)
com.example D/Camera-JNI: (tid:13619)[native_release] - context=0x9bf6afb0 camera=0x0
com.example D/Camera-JNI: (tid:13619)[release camera] - X context=0x9bf6afb0
com.example I/SurfaceView: updateWindow -- OnPreDrawListener, mHaveFrame = true, this = android.view.SurfaceView{
19c70f61 V.E..... ........ 0,82-1152,1618 #7f0e0704 app:id/videoView}
com.example D/ColorDrawable: Color = -328966canvas = android.view.GLES20RecordingCanvas@1af8758emTintMode = SRC_INmTint = nullColorDrawable = android.graphics.drawable.ColorDrawable@3832cd03
com.example D/ColorDrawable: Color = -16777216canvas = android.view.GLES20RecordingCanvas@2a207d60mTintMode = SRC_INmTint = nullColorDrawable = android.graphics.drawable.ColorDrawable@fe26d27
com.example D/IMGSRV: gralloc_register_buffer:1390: hnd=0x9a9c6be0 ID=72118 fd=135 ref=1
com.example D/GraphicBuffer: register, handle(0x9a9c6be0) (w:648 h:105 s:672 f:0x1 u:0x000b00)
com.example D/Camera-JNI: (tid:13848)[~MtkJNICameraContext] this:0x9bf6afb0
com.example D/OpenGLRenderer: Flushing caches (mode 0)
com.example D/GraphicBuffer: unregister, handle(0x9a9c6be0) (w:648 h:105 s:672 f:0x1 u:0x000b00)
com.example D/IMGSRV: gralloc_unregister_buffer:1503: ID=72118 ref=0
com.example D/OpenGLRenderer: Flushing caches (mode 0)
ログからわかるのは、オープンに失敗してエラーコードが19になったということだけですが、19の意味もわからないんです?なぜなら、MediaRecorder.start関数はネイティブ関数で、ネイティブでなければ19の意味がわからないからです!
ネイティブのスタート関数にアクセスしてみましょう。 リンク先を確認する :
static void
android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)
{
ALOGV("start");
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException", "start failed.");
}
static bool process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message)
{
ALOGV("process_media_recorder_call");
if (opStatus == (status_t)INVALID_OPERATION) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return true;
} else if (opStatus ! = (status_t)OK) {
jniThrowException(env, exception, message);
return true;
}
return false;
}
opStatusがokでない場合は例外が発生するので、opStatusの値が何であるかを確認する必要があることがわかります。mr-start関数を見てみましょう。
status_t MediaRecorder::start()
{
ALOGV("start");
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
if (! (mCurrentState & MEDIA_RECORDER_PREPARED)) {
ALOGE("start called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
status_t ret = mMediaRecorder->start();
if (OK ! = ret) {
ALOGE("start failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
return ret;
}
mCurrentState = MEDIA_RECORDER_RECORDING;
return ret;
}
一連の呼び出しの後、MediaPlayerService.cppに行き着きます。 リンクの表示 .
status_t MediaPlayerService::Client::start()
{
ALOGV("[%d] start", mConnId);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
p->setLooping(mLoop);
return p->start();
}
この時点でMediaPlayerBaseのstart関数が再度呼び出されます。コード量が多いので、時間があるときにファックソースコードを読みます。
パラメータの設定
そこで、コードのトラブルシューティングを行う必要がありましたが、その前にググって、パラメータの設定にエラーがあることを突き止めました。始める前に、MediaRecorderのパラメータをいくつか設定し、以下のようにパラメータを設定しました。
private CamcorderProfile getProfile(int cameraId, int quality) {
if (CamcorderProfile.hasProfile(cameraId, quality)) { if (CamcorderProfile.hasProfile(cameraId, quality)) {
return CamcorderProfile.get(cameraId, quality);
}
return null;
}
@SuppressLint("NewApi")
private void setCamcorderProfile() {
CamcorderProfile profile = getProfile(cameraId, CamcorderProfile.QUALITY_CIF);
if (profile == null) {
profile = getProfile(cameraId, CamcorderProfile.QUALITY_LOW);
}
if (profile ! = null) {
profile.fileFormat = MediaRecorder.OutputFormat.MPEG_4;
if (Build.MODEL.equalsIgnoreCase("MB525") || Build.MODEL.equalsIgnoreCase("C8812") || Build.MODEL
.equalsIgnoreCase("C8650")) {
profile.videoCodec = MediaRecorder.VideoEncoder.H263;
} else {
profile.videoCodec = MediaRecorder;
H264; }
if (android.os.Build.VERSION.SDK_INT >= 14) {
profile.audioCodec = MediaRecorder.AudioEncoder.AAC;
} else {
if (android.os.Build.DISPLAY ! = null && android.os.Build.DISPLAY.indexOf("MIUI") >= 0) {
profile.audioCodec = MediaRecorder.AudioEncoder.AAC;
} else {
profile.audioCodec = MediaRecorder.AudioEncoder.AMR_NB;
AMR_NB; }
}
mediaRecorder.setProfile(profile);
} else {
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
}
まず、目的のディスプレイに基づいてCamcorderProfileを取得し、ビデオ出力フォーマット、オーディオエンコーディング、ビデオエンコーディングを調整し、最後にMediaRecorder.setProfile(profile)を呼んで調整したパラメータを設定します。 setProfileのコードは以下のとおりです。
/**
* Uses the settings from a CamcorderProfile object for recording.
* This method should be called after the video AND audio sources are set, and before setOutputFile().
* If a time lapse CamcorderProfile is used, audio related source or recording
* If a time lapse CamcorderProfile is used, audio related source or recording parameters are ignored.
If a time lapse CamcorderProfile is used, audio related source or recording * parameters are ignored.
* @param profile the CamcorderProfile to use
* CamcorderProfile
CamcorderProfile */
public void setProfile(CamcorderProfile profile) {
setOutputFormat(profile.fileFormat);
setVideoFrameRate(profile.videoFrameRate);
setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
setVideoEncodingBitRate(profile.videoBitRate);
setVideoEncoder(profile.videoCodec);
if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
// Nothing needs to be done. call to setCaptureRate() enables
// time lapse video recording.
} else {
setAudioEncodingBitRate(profile.audioBitRate);
setAudioChannels(profile.audioChannels);
setAudioSamplingRate(profile.audioSampleRate);
setAudioEncoder(profile.audioCodec);
}
}
解決方法
ネット上の回答では、setVideoSizeが原因でエラーになるとのことですが、現在手元のスマホではmx4のみフロントカメラエラーになるので、setVideoSizeのところをコメントアウトして再テストしてください。コメントアウト後、録画はOKです。
Androidは大穴! プロファイルはシステムから取得した値をMediaRecorderに設定するのですが、システムから取得した値が使えませんね。
@SuppressLint("NewApi")
private void setCamcorderProfile() {
CamcorderProfile profile = getProfile(cameraId, CamcorderProfile.QUALITY_CIF);
if (profile == null) {
profile = getProfile(cameraId, CamcorderProfile.QUALITY_LOW);
}
if (profile ! = null) {
profile.videoCodec = CameraUtil.getVideoCodec();
profile.audioCodec = CameraUtil.getAudioCodec();
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoFrameRate(profile.videoFrameRate);
// mx4 front camera size is not recognized by hardware after setting, resulting in failure to open
if (Build.MODEL.equalsIgnoreCase("MX4") && cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
} else {
mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
}
mediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW && profile.quality <= CamcorderProfile
.QUALITY_TIME_LAPSE_QVGA) {
// nothing to do
} else {
mediaRecorder.setAudioEncodingBitRate(profile.audioBitRate);
mediaRecorder.setAudioChannels(profile.audioChannels);
mediaRecorder.setAudioSamplingRate(profile.audioSampleRate);
mediaRecorder.setAudioEncoder(profile.audioCodec);
}
} else {
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
}
エラー理由
問題点やパフォーマンスから推測すると、具体的な原因は、設定した録画幅と高さが、ハードウェアがサポートする幅と高さに一致せず、録画エラーになっていると思われます。本当の原因を探るには、コードのフォローアップが必要ですね。
ネットではsetVideoFrameRateもアピールエラーになると書いてありますが、私の持っているマシンではまだ起こっていません。
関連
-
adb connect device offline エラー解決
-
android:ems="10 "の意味。
-
エラーの報告です。ArrayAdapter は、リソース ID が TextView である必要があります。
-
パッケージが見つからないエラー 解決策と jdk の切り替え
-
アンドロイドのdrawableフォルダ配下の各種xmlスタイルファイルの使用方法について詳しく解説しています
-
Androidです。ListView.addHeaderView()の使用方法と注意点
-
AndroidでデータをExcelファイルに書き出す方法
-
Android Studio がエラーを報告します。指定された名前に一致するリソースが見つかりませんでした
-
Android TextViewは、あるテキストのカラー・フォント・サイズを設定する
-
Android 問題その9:AVD フォルダにコピーする ABI armeabi 用の 'userdata.img' ファイルが見つからない。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Android プロジェクトのライブラリに armeabi-v7a、armeabi、x86 が追加されました。
-
アンドロイド アルメアビ アルメアビ-v7a
-
GPSプロンプトの問題は、Callがユーザーによって拒否される可能性のある許可を必要とすることです:コードは、明示的にsをチェックする必要があります。
-
Android Studioの解決策:xxxは囲むクラスではありませんエラー
-
Android ViewPager のエラーです。NULLオブジェクトの参照で仮想メソッドxxxを呼び出そうとした
-
selectionに主な型が含まれていないエラー
-
no target device found 問題が解決した
-
AndroidのRadioButtonの中央寄せ問題(解決済み)
-
原因:android.content.res.Resources$NotFoundException。文字列リソースID #0x0
-
android AVD開始時刻エラー