当前位置:网站首页>Android platform camera Development Practice Guide, 2021 Lifting interviewer Series

Android platform camera Development Practice Guide, 2021 Lifting interviewer Series

2022-01-15 02:36:22 Mb61c1dbbb44788

MediaRecorderUtilisé principalement pour l'enregistrement audio et vidéo,Initialisation et paramètres connexes à définir avant utilisation,Comme suit:

protected boolean preparemediaRecorder() {
mediaRecorder = new MediaRecorder();
try {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

//Format de sortie
mediaRecorder.setOutputFormat(camcorderProfile.fileFormat);
//Taux de trame vidéo
mediaRecorder.setVideoFrameRate(camcorderProfile.videoFrameRate);
//Taille de la vidéo
mediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight());
//Débit vidéo
mediaRecorder.setVideoEncodingBitRate(camcorderProfile.videoBitRate);
//Encodeur vidéo
mediaRecorder.setVideoEncoder(camcorderProfile.videoCodec);

//Taux de codage audio
mediaRecorder.setAudioEncodingBitRate(camcorderProfile.audioBitRate);
//Canal audio
mediaRecorder.setAudioChannels(camcorderProfile.audioChannels);
//Taux d'échantillonnage audio
mediaRecorder.setAudioSamplingRate(camcorderProfile.audioSampleRate);
//Encodeur audio
mediaRecorder.setAudioEncoder(camcorderProfile.audioCodec);

File outputFile = outputPath;
String outputFilePath = outputFile.toString();
//Chemin de sortie
mediaRecorder.setOutputFile(outputFilePath);

//Définir la taille maximale de la sortie vidéo
if (mCameraConfigProvider.getVideoFileSize() > 0) {
mediaRecorder.setMaxFileSize(mCameraConfigProvider.getVideoFileSize());
mediaRecorder.setOnInfoListener(this);
}

//Définir la durée maximale de sortie vidéo
if (mCameraConfigProvider.getVideoDuration() > 0) {
mediaRecorder.setMaxDuration(mCameraConfigProvider.getVideoDuration());
mediaRecorder.setOnInfoListener(this);
}
mediaRecorder.setOrientationHint(getVideoOrientation(mCameraConfigProvider.getSensorPosition()));

//Préparez - vous.
mediaRecorder.prepare();

return true;
} catch (IllegalStateException error) {
Log.e(TAG, "IllegalStateException preparing MediaRecorder: " + error.getMessage());
} catch (IOException error) {
Log.e(TAG, "IOException preparing MediaRecorder: " + error.getMessage());
} catch (Throwable error) {
Log.e(TAG, "Error during preparing MediaRecorder: " + error.getMessage());
}
releasemediaRecorder();
return false;
}

Il convient de mentionner que,La durée ou la taille de la vidéo est souvent requise dans les affaires quotidiennes.,Ça peut passer parmediaRecorder.setOnInfoListener()Pour s'en occuper.,OnInfoListenerécouter la vidéo enregistrée,Et nous Peut être traité dans sa méthode de rappel.

@Override
public void onInfo(MediaRecorder mediaRecorder, int what, int extra) {
if (MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED == what) {
//Durée maximale d'arrivée
} else if (MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED == what) {
//Taille maximale atteinte
}
}

En savoir plusMediaRecorderPour une introduction à MediaRecorderDocuments officiels.

1.7 Fin de l'enregistrement vidéo

La fin de l'enregistrement vidéo est aussi simple,Il suffit d'appelermediaRecorder.stop()La méthode est juste.

mediaRecorder.stop();

En outre,Si vous n'utilisez plus la caméra,Notez également la libération des ressources de la caméra.

C'est tout ce qui précède.CameraTout le contenu de,C'est plus simple.,Passons à autre chose.Camera2Contenu pertinent,Faites attention à la différence..

2. Camera2Guide pratique

Camera2 APILes principales catégories sont les suivantes::

  • CameraManager:Gestionnaire de caméra,Pour activer et désactiver la caméra système
  • CameraCharacteristics:Décrire les différentes caractéristiques de la caméra,On peut passer parCameraManagerDegetCameraCharacteristics(@NonNull String cameraId)Comment obtenir.
  • CameraDevice:Décrire la caméra du système,Similaire à l'ancienCamera.
  • CameraCaptureSession:SessionCatégorie,Quand une photo est nécessaire、Lors de l'aperçu et d'autres fonctions,Vous devez d'abord créer une instance de cette classe,Ensuite, le contrôle est effectué par la méthode de l'exemple(Par exemple:Prendre des photos capture()).
  • CaptureRequest:Décrit une demande d'action,Prendre des photos、L'aperçu et d'autres opérations doivent être passés en premierCaptureRequestParamètres,Les paramètres spécifiques sont également contrôlés parCameraRequestVariable membre pour définir.
  • CaptureResult:Décrire les résultats après la prise de photos.

Camera2Le processus de prise de photos est le suivant::

AndroidPlate - formeCamera Guide des pratiques de développement ,2021Comme une percée primaire_Android

Les développeurs créentCaptureRequestÀ la caméraCaptureDemande,Ces demandes sont mises en file d'attente pour le traitement de la caméra,La caméra emballe les résultats dansCaptureMetadataRetour au développeur.L'ensemble du processus repose sur unCameraCaptureSessionDans la session.

2.1 Allumez la caméra

Avant d'allumer la caméra,Nous devons d'abord obtenirCameraManager,Puis obtenir la liste des caméras,Et obtenir des caméras individuelles(Principalement les caméras avant et arrière)Paramètres pour.

mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
try {
final String[] ids = mCameraManager.getCameraIdList();
numberOfCameras = ids.length;
for (String id : ids) {
final CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(id);

final int orientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (orientation == CameraCharacteristics.LENS_FACING_FRONT) {
faceFrontCameraId = id;
faceFrontCameraOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
frontCameraCharacteristics = characteristics;
} else {
faceBackCameraId = id;
faceBackCameraOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
backCameraCharacteristics = characteristics;
}
}
} catch (Exception e) {
Log.e(TAG, “Error during camera initialize”);
}

Camera2AvecCameraC'est pareil.cameraIdLe concept de,Nous passonsmCameraManager.getCameraIdList()Pour obtenircameraIdListe,Et à traversmCameraManager.getCameraCharacteristics(id) Obtenir chaqueidParamètres de la caméra correspondante.

À propos deCameraCharacteristicsParamètres à l'intérieur,Les principales utilisations sont les suivantes::

  • LENS_FACING:Caméra frontale(LENS_FACING_FRONT)Ou une caméra arrière(LENS_FACING_BACK).
  • SENSOR_ORIENTATION:Direction de la caméra.
  • FLASH_INFO_AVAILABLE:Si flash est pris en charge.
  • CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL:Obtient les propriétés de la caméra supportées par l'appareil courant.

Note::En fait,De chaque fabricantAndroidSur l'équipement,Camera2Toutes les fonctionnalités ne sont pas disponibles,Besoin de passercharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)Méthodes Pour obtenir un niveau de soutien basé sur la valeur de retour,Plus précisément,:

  • INFO_SUPPORTED_HARDWARE_LEVEL_FULL:Support matériel complet,Permet le contrôle manuel de la caméra HD complète、Prise en charge du mode Beat et d'autres nouvelles fonctionnalités.
  • INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:Soutien limité,Ceci nécessite une requête séparée.
  • INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY:Tous les appareils seront pris en charge,C'est - à - dire qu'il est désuetCamera APILes caractéristiques supportées sont cohérentes.

Utilise çaINFO_SUPPORTED_HARDWARE_LEVELParamètres,Nous pouvons juger si nous utilisonsCameraToujours utiliserCamera2,Les méthodes spécifiques sont les suivantes:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static boolean hasCamera2(Context mContext) {
if (mContext == null) return false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return false;
try {
CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
String[] idList = manager.getCameraIdList();
boolean notFull = true;
if (idList.length == 0) {
notFull = false;
} else {
for (final String str : idList) {
if (str == null || str.trim().isEmpty()) {
notFull = false;
break;
}
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(str);

final int supportLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (supportLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
notFull = false;
break;
}
}
}
return notFull;
} catch (Throwable ignore) {
return false;
}
}

PlusameraCharacteristicsParamètres,Voir CameraCharacteristicsDocuments officiels.

L'ouverture de la caméra appelle principalementmCameraManager.openCamera(currentCameraId, stateCallback, backgroundHandler)Méthodes,Comme vous pouvez le voir,Il a trois paramètres:

  • String cameraId:La seule caméraID.
  • CameraDevice.StateCallback callback:Rappel associé à l'ouverture de la caméra.
  • Handler handler:StateCallbackAppeléHandler,Nous pouvons généralement utiliser le thread actuelHandler.

mCameraManager.openCamera(currentCameraId, stateCallback, backgroundHandler);

Comme nous l'avons mentionné ci - dessusCameraDevice.StateCallback,C'est un rappel de la caméra allumée.,Ouverture définie,Diverses méthodes de rappel telles que l'arrêt et les erreurs,Nous pouvons Effectuer les opérations correspondantes dans ces méthodes de rappel.

private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
//AccèsCameraDevice
mcameraDevice = cameraDevice;
}

@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
//FermerCameraDevice
cameraDevice.close();

}

@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
//FermerCameraDevice
cameraDevice.close();
}
};

2.2 Éteignez la caméra.

Par la description ci - dessus,C'est facile de fermer..

//FermerCameraDevice
cameraDevice.close();

2.3 Ouvrir l'aperçu

Camera2Est appelé en créant une session de demande,Plus précisément,:

  1. AppelezmCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)Création de méthodesCaptureRequest,Appelez
  2. mCameraDevice.createCaptureSession()Création de méthodesCaptureSession.

CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType)

createCaptureRequest()Paramètres de la méthodetemplateTypeReprésente le type de demande,Il existe six types de demandes,Respectivement::

  • TEMPLATE_PREVIEW:Demande de création d'un aperçu
  • TEMPLATE_STILL_CAPTURE:Créer une demande adaptée à la capture d'images fixes,La qualité de l'image a priorité sur le taux de trame.
  • TEMPLATE_RECORD:Demande de création d'un enregistrement vidéo
  • TEMPLATE_VIDEO_SNAPSHOT:Demande de capture d'écran lors de la création d'un enregistrement vidéo
  • TEMPLATE_ZERO_SHUTTER_LAG:Créer une demande pour un délai d'obturation nul.Maximiser la qualité de l'image sans affecter le taux d'aperçu.
  • TEMPLATE_MANUAL:Créer une demande de capture de base,Toutes les commandes automatiques de cette demande sont désactivées(Exposition automatique,Balance blanche automatique、Autofocus).

createCaptureSession(@NonNull List<Surface> outputs, @NonNull CameraCaptureSession.StateCallback callback, @Nullable Handler handler)

createCaptureSession()La méthode contient trois paramètres:

  • List outputs:Nous devons exporter versSurfaceListe.
  • CameraCaptureSession.StateCallback callback:Rappel lié à l'état de la session.
  • Handler handler:callbackIl peut y en avoir plusieurs.(De différents fils),C'esthandlerPour distinguercallbackDevrait être rappelé,Écrivez généralement le thread courantHandlerC'est tout..

À propos deCameraCaptureSession.StateCallbackMéthode de rappel:

  • onConfigured(@NonNull CameraCaptureSession session); Configuration complète de la caméra,On peut s'en occuper.CaptureC'est demandé..
  • onConfigureFailed(@NonNull CameraCaptureSession session); La configuration de la caméra a échoué
  • onReady(@NonNull CameraCaptureSession session); Caméra prête,Il n'y a actuellement aucune demande à traiter.
  • onActive(@NonNull CameraCaptureSession session); La caméra traite la demande.
  • onClosed(@NonNull CameraCaptureSession session); Session close
  • onSurfacePrepared(@NonNull CameraCaptureSession session, @NonNull Surface surface); SurfacePrêt

J'ai compris.,Il est facile de créer une demande d'aperçu.

previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(workingSurface);

//Notez qu'en plus de l'aperçuSurface,Nous avons ajoutéimageReader.getSurface()C'est ce qu'il fait pour obtenir des données après avoir pris des photos.
mCameraDevice.createCaptureSession(Arrays.asList(workingSurface, imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
cameraCaptureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler);
}

@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Log.d(TAG, "Fail while starting preview: ");
}
}, null);

On peut le découvrir.,InonConfigured()J'ai appelé.cameraCaptureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler),Pour que nous puissions Aperçu continu.

Note::C'est ce qu'on a dit.imageReader.getSurface()Et c'est ce qu'il fait pour obtenir des données après avoir pris des photos.,Les opérations spécifiques sont les suivantes:ImageReaderConfigurer unOnImageAvailableListener,Et dans sononImageAvailable() Méthode d'acquisition.

mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {

@Override
public void onImageAvailable(ImageReader reader) {
//Obtenir une image et l'enregistrer lorsque l'image est disponible
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
}

};

2.4 Fermer l'aperçu

Fermer l'aperçu ferme la session actuellement prévue,Ouvrir l'aperçu en combinaison avec le contenu ci - dessus,La réalisation concrète est la suivante:

if (captureSession != null) {
captureSession.close();
try {
captureSession.abortCaptures();
} catch (Exception ignore) {
} finally {
captureSession = null;
}
}

2.5 Prendre des photos

La photographie est divisée en trois étapes.:

  1. Focus

try {
//Mise au point de la caméra
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
//Modifier l'état
previewState = STATE_WAITING_LOCK;
//Envoyer une demande de mise au point
captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);
} catch (Exception ignore) {
}

Nous avons défini unCameraCaptureSession.CaptureCallbackPour traiter les résultats retournés par la demande de mise au point.

private CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {

@Override
public void onCaptureProgressed(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull CaptureResult partialResult) {
}

@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
//En attente de mise au point
final Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null) {
//Échec de la mise au point,Photographie directe
captureStillPicture();
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
|| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState
|| CaptureResult.CONTROL_AF_STATE_INACTIVE == afState
|| CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN == afState) {
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
previewState = STATE_PICTURE_TAKEN;
//Focus terminé,Prendre des photos
captureStillPicture();
} else {
runPreCaptureSequence();
}
}
}
};

  1. Prendre des photos

Nous avons défini uncaptureStillPicture()Pour prendre des photos.

private void captureStillPicture() {
try {
if (null == mCameraDevice) {
return;
}

//Construit pour prendre des photosCaptureRequest
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(imageReader.getSurface());

//Utiliser le mêmeAREtAFMode comme Aperçu
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
//Définir la direction
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getPhotoOrientation(mCameraConfigProvider.getSensorPosition()));

//Créer une session
CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
Log.d(TAG, "onCaptureCompleted: ");
}
};
//Arrêter le tournage continu
captureSession.stopRepeating();
//Capture de photos
captureSession.capture(captureBuilder.build(), CaptureCallback, null);

} catch (CameraAccessException e) {
Log.e(TAG, “Error during capturing picture”);
}
}

  1. Annuler la mise au point

Après avoir pris la photo,On doit déverrouiller la caméra.,Ramener la caméra à l'état d'aperçu.

try {
//Réinitialiser la mise au point automatique
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);
//La caméra retourne à son état d'aperçu normal
previewState = STATE_PREVIEW;
//Activer le mode de visualisation continue
captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler);
} catch (Exception e) {
Log.e(TAG, “Error during focus unlocking”);
}

2.6 Démarrer l'enregistrement vidéo

//Fermez d'abord l'aperçu,Parce que vous devez ajouter unSurface,C'est - à - diremediaRecorder.getSurface()
closePreviewSession();

//InitialisationMediaRecorder,Définir les paramètres pertinents
if (preparemediaRecorder()) {

final SurfaceTexture texture = Camera2Manager.this.texture;
texture.setDefaultBufferSize(videoSize.getWidth(), videoSize.getHeight());

try {
//Construire un enregistrement vidéoaptureRequest
previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
final List<Surface> surfaces = new ArrayList<>();

//Définir l'aperçuSurface
final Surface previewSurface = workingSurface;
surfaces.add(previewSurface);
previewRequestBuilder.addTarget(previewSurface);

//Définir la sortie d'aperçuSurface
workingSurface = mediaRecorder.getSurface();
surfaces.add(workingSurface);
previewRequestBuilder.addTarget(workingSurface);

mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
captureSession = cameraCaptureSession;

previewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
//Envoi continuCaptureDemande,Réaliser un aperçu en temps réel.
captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, backgroundHandler);
} catch (Exception e) {
}

try {
//Commencez la vidéo.
mediaRecorder.start();
} catch (Exception ignore) {
Log.e(TAG, "mediaRecorder.start(): ", ignore);
}

isVideoRecording = true;

uiHandler.post(new Runnable() {
@Override
public void run() {
cameraVideoListener.onVideoRecordStarted(videoSize);
}
});
}

@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Log.d(TAG, “onConfigureFailed”);
}
}, backgroundHandler);
} catch (Exception e) {
Log.e(TAG, "startVideoRecord: ", e);
}
}

À propos deMediaRecorderÇa dit:CameraOn l'a déjà dit.,Je n'en parlerai plus ici..

C'est tout l'enregistrement vidéo.,C'est simple.APIUtiliser,C'est plus simple..

2.7 Fin de l'enregistrement vidéo

La fin de l'enregistrement vidéo consiste principalement à fermer la session et à libérer des ressources ,Plus précisément,:

  1. Fermer la session d'aperçu
  2. Arrêtez!mediaRecorder
  3. ReleasemediaRecorder

// Fermer la session d'aperçu
if (captureSession != null) {
captureSession.close();
try {
captureSession.abortCaptures();
} catch (Exception ignore) {
} finally {
captureSession = null;
}
}

Enfin, pour vous aider à comprendreAndroidPrincipes des points de connaissance pertinents et connaissances pertinentes pour l'entrevue,C'est là que j'ai rassemblé les informations pertinentes.24EnsembleTencent、Byte Runout、Ali!、Baidu2020-2021Analyse des vrais problèmes d'entrevue,J'ai rassemblé les points techniquesVidéo etPDF(Il a fallu plus d'énergie que prévu),SacLe contexte de la connaissance + Beaucoup de détails.

Et?Technologie architecturale avancée cerveau、AndroidÉlaboration d'un profil d'entrevue?Aider tout le monde à apprendre à progresser,Vous économisez également du temps en recherchant des documents en ligne pour apprendre,Peut également partager avec les amis autour d'apprendre ensemble.

AndroidPlate - formeCamera Guide des pratiques de développement ,2021Comme une percée primaire_Programmeur_02

AndroidPlate - formeCamera Guide des pratiques de développement ,2021Comme une percée primaire_Programmeur_03

AndroidPlate - formeCamera Guide des pratiques de développement ,2021Comme une percée primaire_Développement mobile_04

Cliquez sur:

 AndroidVidéo de schéma+BATSujet de l'entrevuePDF+Notes d'étude》Disponible gratuitement~

Apprentissage en ligne AndroidUn tas d'informations.,Mais si les connaissances acquises ne sont pas structurées,Quand vous rencontrez des problèmes, vous n'avez qu'à essayer.,Plus d'étude approfondie,Il est donc difficile d'obtenir une véritable amélioration technologique.J'espère que ce système technologique systématique vous donnera une orientation.

版权声明
本文为[Mb61c1dbbb44788]所创,转载请带上原文链接,感谢
https://chowdera.com/2022/01/202201150232489574.html

随机推荐