1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Android camera input device 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (C) 2017 Felix Matouschek 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <errno.h> 24cabdff1aSopenharmony_ci#include <pthread.h> 25cabdff1aSopenharmony_ci#include <stdatomic.h> 26cabdff1aSopenharmony_ci#include <stdbool.h> 27cabdff1aSopenharmony_ci#include <stdint.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include <camera/NdkCameraDevice.h> 30cabdff1aSopenharmony_ci#include <camera/NdkCameraManager.h> 31cabdff1aSopenharmony_ci#include <media/NdkImage.h> 32cabdff1aSopenharmony_ci#include <media/NdkImageReader.h> 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#include "libavformat/avformat.h" 35cabdff1aSopenharmony_ci#include "libavformat/internal.h" 36cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 37cabdff1aSopenharmony_ci#include "libavutil/display.h" 38cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 39cabdff1aSopenharmony_ci#include "libavutil/log.h" 40cabdff1aSopenharmony_ci#include "libavutil/opt.h" 41cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 42cabdff1aSopenharmony_ci#include "libavutil/pixfmt.h" 43cabdff1aSopenharmony_ci#include "libavutil/threadmessage.h" 44cabdff1aSopenharmony_ci#include "libavutil/time.h" 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci/* This image format is available on all Android devices 47cabdff1aSopenharmony_ci * supporting the Camera2 API */ 48cabdff1aSopenharmony_ci#define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci#define MAX_BUF_COUNT 2 51cabdff1aSopenharmony_ci#define VIDEO_STREAM_INDEX 0 52cabdff1aSopenharmony_ci#define VIDEO_TIMEBASE_ANDROID 1000000000 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci#define RETURN_CASE(x) case x: return AV_STRINGIFY(x); 55cabdff1aSopenharmony_ci#define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x); 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_citypedef struct AndroidCameraCtx { 58cabdff1aSopenharmony_ci const AVClass *class; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci int requested_width; 61cabdff1aSopenharmony_ci int requested_height; 62cabdff1aSopenharmony_ci AVRational framerate; 63cabdff1aSopenharmony_ci int camera_index; 64cabdff1aSopenharmony_ci int input_queue_size; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci uint8_t lens_facing; 67cabdff1aSopenharmony_ci int32_t sensor_orientation; 68cabdff1aSopenharmony_ci int width; 69cabdff1aSopenharmony_ci int height; 70cabdff1aSopenharmony_ci int32_t framerate_range[2]; 71cabdff1aSopenharmony_ci int image_format; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci ACameraManager *camera_mgr; 74cabdff1aSopenharmony_ci char *camera_id; 75cabdff1aSopenharmony_ci ACameraMetadata *camera_metadata; 76cabdff1aSopenharmony_ci ACameraDevice *camera_dev; 77cabdff1aSopenharmony_ci ACameraDevice_StateCallbacks camera_state_callbacks; 78cabdff1aSopenharmony_ci AImageReader *image_reader; 79cabdff1aSopenharmony_ci AImageReader_ImageListener image_listener; 80cabdff1aSopenharmony_ci ANativeWindow *image_reader_window; 81cabdff1aSopenharmony_ci ACaptureSessionOutputContainer *capture_session_output_container; 82cabdff1aSopenharmony_ci ACaptureSessionOutput *capture_session_output; 83cabdff1aSopenharmony_ci ACameraOutputTarget *camera_output_target; 84cabdff1aSopenharmony_ci ACaptureRequest *capture_request; 85cabdff1aSopenharmony_ci ACameraCaptureSession_stateCallbacks capture_session_state_callbacks; 86cabdff1aSopenharmony_ci ACameraCaptureSession *capture_session; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci AVThreadMessageQueue *input_queue; 89cabdff1aSopenharmony_ci atomic_int exit; 90cabdff1aSopenharmony_ci atomic_int got_image_format; 91cabdff1aSopenharmony_ci} AndroidCameraCtx; 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_cistatic const char *camera_status_string(camera_status_t val) 94cabdff1aSopenharmony_ci{ 95cabdff1aSopenharmony_ci switch(val) { 96cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_OK) 97cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_UNKNOWN) 98cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_INVALID_PARAMETER) 99cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_CAMERA_DISCONNECTED) 100cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_NOT_ENOUGH_MEMORY) 101cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_METADATA_NOT_FOUND) 102cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_CAMERA_DEVICE) 103cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_CAMERA_SERVICE) 104cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_SESSION_CLOSED) 105cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_INVALID_OPERATION) 106cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL) 107cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_CAMERA_IN_USE) 108cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_MAX_CAMERA_IN_USE) 109cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_CAMERA_DISABLED) 110cabdff1aSopenharmony_ci RETURN_CASE(ACAMERA_ERROR_PERMISSION_DENIED) 111cabdff1aSopenharmony_ci RETURN_DEFAULT(ACAMERA_ERROR_UNKNOWN) 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci} 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_cistatic const char *media_status_string(media_status_t val) 116cabdff1aSopenharmony_ci{ 117cabdff1aSopenharmony_ci switch(val) { 118cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_OK) 119cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_UNKNOWN) 120cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_MALFORMED) 121cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_UNSUPPORTED) 122cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_INVALID_OBJECT) 123cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_INVALID_PARAMETER) 124cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_ERROR_INVALID_OPERATION) 125cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_NOT_PROVISIONED) 126cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_RESOURCE_BUSY) 127cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_DEVICE_REVOKED) 128cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_SHORT_BUFFER) 129cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_SESSION_NOT_OPENED) 130cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_TAMPER_DETECTED) 131cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_VERIFY_FAILED) 132cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_NEED_KEY) 133cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_DRM_LICENSE_EXPIRED) 134cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) 135cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED) 136cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE) 137cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE) 138cabdff1aSopenharmony_ci RETURN_CASE(AMEDIA_IMGREADER_IMAGE_NOT_LOCKED) 139cabdff1aSopenharmony_ci RETURN_DEFAULT(AMEDIA_ERROR_UNKNOWN) 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci} 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_cistatic const char *error_state_callback_string(int val) 144cabdff1aSopenharmony_ci{ 145cabdff1aSopenharmony_ci switch(val) { 146cabdff1aSopenharmony_ci RETURN_CASE(ERROR_CAMERA_IN_USE) 147cabdff1aSopenharmony_ci RETURN_CASE(ERROR_MAX_CAMERAS_IN_USE) 148cabdff1aSopenharmony_ci RETURN_CASE(ERROR_CAMERA_DISABLED) 149cabdff1aSopenharmony_ci RETURN_CASE(ERROR_CAMERA_DEVICE) 150cabdff1aSopenharmony_ci RETURN_CASE(ERROR_CAMERA_SERVICE) 151cabdff1aSopenharmony_ci default: 152cabdff1aSopenharmony_ci return "ERROR_CAMERA_UNKNOWN"; 153cabdff1aSopenharmony_ci } 154cabdff1aSopenharmony_ci} 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_cistatic void camera_dev_disconnected(void *context, ACameraDevice *device) 157cabdff1aSopenharmony_ci{ 158cabdff1aSopenharmony_ci AVFormatContext *avctx = context; 159cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 160cabdff1aSopenharmony_ci atomic_store(&ctx->exit, 1); 161cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Camera with id %s disconnected.\n", 162cabdff1aSopenharmony_ci ACameraDevice_getId(device)); 163cabdff1aSopenharmony_ci} 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_cistatic void camera_dev_error(void *context, ACameraDevice *device, int error) 166cabdff1aSopenharmony_ci{ 167cabdff1aSopenharmony_ci AVFormatContext *avctx = context; 168cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 169cabdff1aSopenharmony_ci atomic_store(&ctx->exit, 1); 170cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error %s on camera with id %s.\n", 171cabdff1aSopenharmony_ci error_state_callback_string(error), ACameraDevice_getId(device)); 172cabdff1aSopenharmony_ci} 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_cistatic int open_camera(AVFormatContext *avctx) 175cabdff1aSopenharmony_ci{ 176cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 177cabdff1aSopenharmony_ci camera_status_t ret; 178cabdff1aSopenharmony_ci ACameraIdList *camera_ids; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci ret = ACameraManager_getCameraIdList(ctx->camera_mgr, &camera_ids); 181cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 182cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to get camera id list, error: %s.\n", 183cabdff1aSopenharmony_ci camera_status_string(ret)); 184cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci if (ctx->camera_index < camera_ids->numCameras) { 188cabdff1aSopenharmony_ci ctx->camera_id = av_strdup(camera_ids->cameraIds[ctx->camera_index]); 189cabdff1aSopenharmony_ci if (!ctx->camera_id) { 190cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for camera_id.\n"); 191cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci } else { 194cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "No camera with index %d available.\n", 195cabdff1aSopenharmony_ci ctx->camera_index); 196cabdff1aSopenharmony_ci return AVERROR(ENXIO); 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci ACameraManager_deleteCameraIdList(camera_ids); 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci ret = ACameraManager_getCameraCharacteristics(ctx->camera_mgr, 202cabdff1aSopenharmony_ci ctx->camera_id, &ctx->camera_metadata); 203cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 204cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to get metadata for camera with id %s, error: %s.\n", 205cabdff1aSopenharmony_ci ctx->camera_id, camera_status_string(ret)); 206cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci ctx->camera_state_callbacks.context = avctx; 210cabdff1aSopenharmony_ci ctx->camera_state_callbacks.onDisconnected = camera_dev_disconnected; 211cabdff1aSopenharmony_ci ctx->camera_state_callbacks.onError = camera_dev_error; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci ret = ACameraManager_openCamera(ctx->camera_mgr, ctx->camera_id, 214cabdff1aSopenharmony_ci &ctx->camera_state_callbacks, &ctx->camera_dev); 215cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 216cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to open camera with id %s, error: %s.\n", 217cabdff1aSopenharmony_ci ctx->camera_id, camera_status_string(ret)); 218cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 219cabdff1aSopenharmony_ci } 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci return 0; 222cabdff1aSopenharmony_ci} 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_cistatic void get_sensor_orientation(AVFormatContext *avctx) 225cabdff1aSopenharmony_ci{ 226cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 227cabdff1aSopenharmony_ci ACameraMetadata_const_entry lens_facing; 228cabdff1aSopenharmony_ci ACameraMetadata_const_entry sensor_orientation; 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci ACameraMetadata_getConstEntry(ctx->camera_metadata, 231cabdff1aSopenharmony_ci ACAMERA_LENS_FACING, &lens_facing); 232cabdff1aSopenharmony_ci ACameraMetadata_getConstEntry(ctx->camera_metadata, 233cabdff1aSopenharmony_ci ACAMERA_SENSOR_ORIENTATION, &sensor_orientation); 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci ctx->lens_facing = lens_facing.data.u8[0]; 236cabdff1aSopenharmony_ci ctx->sensor_orientation = sensor_orientation.data.i32[0]; 237cabdff1aSopenharmony_ci} 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_cistatic void match_video_size(AVFormatContext *avctx) 240cabdff1aSopenharmony_ci{ 241cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 242cabdff1aSopenharmony_ci ACameraMetadata_const_entry available_configs; 243cabdff1aSopenharmony_ci int found = 0; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci ACameraMetadata_getConstEntry(ctx->camera_metadata, 246cabdff1aSopenharmony_ci ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, 247cabdff1aSopenharmony_ci &available_configs); 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_ci for (int i = 0; i < available_configs.count; i++) { 250cabdff1aSopenharmony_ci int32_t input = available_configs.data.i32[i * 4 + 3]; 251cabdff1aSopenharmony_ci int32_t format = available_configs.data.i32[i * 4 + 0]; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci if (input) { 254cabdff1aSopenharmony_ci continue; 255cabdff1aSopenharmony_ci } 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci if (format == IMAGE_FORMAT_ANDROID) { 258cabdff1aSopenharmony_ci int32_t width = available_configs.data.i32[i * 4 + 1]; 259cabdff1aSopenharmony_ci int32_t height = available_configs.data.i32[i * 4 + 2]; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci //Same ratio 262cabdff1aSopenharmony_ci if ((ctx->requested_width == width && ctx->requested_height == height) || 263cabdff1aSopenharmony_ci (ctx->requested_width == height && ctx->requested_height == width)) { 264cabdff1aSopenharmony_ci ctx->width = width; 265cabdff1aSopenharmony_ci ctx->height = height; 266cabdff1aSopenharmony_ci found = 1; 267cabdff1aSopenharmony_ci break; 268cabdff1aSopenharmony_ci } 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci } 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci if (!found || ctx->width == 0 || ctx->height == 0) { 273cabdff1aSopenharmony_ci ctx->width = available_configs.data.i32[1]; 274cabdff1aSopenharmony_ci ctx->height = available_configs.data.i32[2]; 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 277cabdff1aSopenharmony_ci "Requested video_size %dx%d not available, falling back to %dx%d\n", 278cabdff1aSopenharmony_ci ctx->requested_width, ctx->requested_height, ctx->width, ctx->height); 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci return; 282cabdff1aSopenharmony_ci} 283cabdff1aSopenharmony_ci 284cabdff1aSopenharmony_cistatic void match_framerate(AVFormatContext *avctx) 285cabdff1aSopenharmony_ci{ 286cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 287cabdff1aSopenharmony_ci ACameraMetadata_const_entry available_framerates; 288cabdff1aSopenharmony_ci int found = 0; 289cabdff1aSopenharmony_ci int current_best_match = -1; 290cabdff1aSopenharmony_ci int requested_framerate = av_q2d(ctx->framerate); 291cabdff1aSopenharmony_ci 292cabdff1aSopenharmony_ci ACameraMetadata_getConstEntry(ctx->camera_metadata, 293cabdff1aSopenharmony_ci ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 294cabdff1aSopenharmony_ci &available_framerates); 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci for (int i = 0; i < available_framerates.count; i++) { 297cabdff1aSopenharmony_ci int32_t min = available_framerates.data.i32[i * 2 + 0]; 298cabdff1aSopenharmony_ci int32_t max = available_framerates.data.i32[i * 2 + 1]; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci if (requested_framerate == max) { 301cabdff1aSopenharmony_ci if (min == max) { 302cabdff1aSopenharmony_ci ctx->framerate_range[0] = min; 303cabdff1aSopenharmony_ci ctx->framerate_range[1] = max; 304cabdff1aSopenharmony_ci found = 1; 305cabdff1aSopenharmony_ci break; 306cabdff1aSopenharmony_ci } else if (current_best_match >= 0) { 307cabdff1aSopenharmony_ci int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0]; 308cabdff1aSopenharmony_ci if (min > current_best_match_min) { 309cabdff1aSopenharmony_ci current_best_match = i; 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci } else { 312cabdff1aSopenharmony_ci current_best_match = i; 313cabdff1aSopenharmony_ci } 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci } 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci if (!found) { 318cabdff1aSopenharmony_ci if (current_best_match >= 0) { 319cabdff1aSopenharmony_ci ctx->framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0]; 320cabdff1aSopenharmony_ci ctx->framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1]; 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci } else { 323cabdff1aSopenharmony_ci ctx->framerate_range[0] = available_framerates.data.i32[0]; 324cabdff1aSopenharmony_ci ctx->framerate_range[1] = available_framerates.data.i32[1]; 325cabdff1aSopenharmony_ci } 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 328cabdff1aSopenharmony_ci "Requested framerate %d not available, falling back to min: %d and max: %d fps\n", 329cabdff1aSopenharmony_ci requested_framerate, ctx->framerate_range[0], ctx->framerate_range[1]); 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci return; 333cabdff1aSopenharmony_ci} 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_cistatic int get_image_format(AVFormatContext *avctx, AImage *image) 336cabdff1aSopenharmony_ci{ 337cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 338cabdff1aSopenharmony_ci int32_t image_pixelstrides[2]; 339cabdff1aSopenharmony_ci uint8_t *image_plane_data[2]; 340cabdff1aSopenharmony_ci int plane_data_length[2]; 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci for (int i = 0; i < 2; i++) { 343cabdff1aSopenharmony_ci AImage_getPlanePixelStride(image, i + 1, &image_pixelstrides[i]); 344cabdff1aSopenharmony_ci AImage_getPlaneData(image, i + 1, &image_plane_data[i], &plane_data_length[i]); 345cabdff1aSopenharmony_ci } 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci if (image_pixelstrides[0] != image_pixelstrides[1]) { 348cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 349cabdff1aSopenharmony_ci "Pixel strides of U and V plane should have been the same.\n"); 350cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci switch (image_pixelstrides[0]) { 354cabdff1aSopenharmony_ci case 1: 355cabdff1aSopenharmony_ci ctx->image_format = AV_PIX_FMT_YUV420P; 356cabdff1aSopenharmony_ci break; 357cabdff1aSopenharmony_ci case 2: 358cabdff1aSopenharmony_ci if (image_plane_data[0] < image_plane_data[1]) { 359cabdff1aSopenharmony_ci ctx->image_format = AV_PIX_FMT_NV12; 360cabdff1aSopenharmony_ci } else { 361cabdff1aSopenharmony_ci ctx->image_format = AV_PIX_FMT_NV21; 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci break; 364cabdff1aSopenharmony_ci default: 365cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 366cabdff1aSopenharmony_ci "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n", 367cabdff1aSopenharmony_ci image_pixelstrides[0]); 368cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci 371cabdff1aSopenharmony_ci return 0; 372cabdff1aSopenharmony_ci} 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_cistatic void image_available(void *context, AImageReader *reader) 375cabdff1aSopenharmony_ci{ 376cabdff1aSopenharmony_ci AVFormatContext *avctx = context; 377cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 378cabdff1aSopenharmony_ci media_status_t media_status; 379cabdff1aSopenharmony_ci int ret = 0; 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci AImage *image; 382cabdff1aSopenharmony_ci int64_t image_timestamp; 383cabdff1aSopenharmony_ci int32_t image_linestrides[4]; 384cabdff1aSopenharmony_ci uint8_t *image_plane_data[4]; 385cabdff1aSopenharmony_ci int plane_data_length[4]; 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci AVPacket pkt; 388cabdff1aSopenharmony_ci int pkt_buffer_size = 0; 389cabdff1aSopenharmony_ci 390cabdff1aSopenharmony_ci media_status = AImageReader_acquireLatestImage(reader, &image); 391cabdff1aSopenharmony_ci if (media_status != AMEDIA_OK) { 392cabdff1aSopenharmony_ci if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) { 393cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 394cabdff1aSopenharmony_ci "An image reader frame was discarded"); 395cabdff1aSopenharmony_ci } else { 396cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 397cabdff1aSopenharmony_ci "Failed to acquire latest image from image reader, error: %s.\n", 398cabdff1aSopenharmony_ci media_status_string(media_status)); 399cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci goto error; 402cabdff1aSopenharmony_ci } 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci // Silently drop frames when exit is set 405cabdff1aSopenharmony_ci if (atomic_load(&ctx->exit)) { 406cabdff1aSopenharmony_ci goto error; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci // Determine actual image format 410cabdff1aSopenharmony_ci if (!atomic_load(&ctx->got_image_format)) { 411cabdff1aSopenharmony_ci ret = get_image_format(avctx, image); 412cabdff1aSopenharmony_ci if (ret < 0) { 413cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 414cabdff1aSopenharmony_ci "Could not get image format of camera.\n"); 415cabdff1aSopenharmony_ci goto error; 416cabdff1aSopenharmony_ci } else { 417cabdff1aSopenharmony_ci atomic_store(&ctx->got_image_format, 1); 418cabdff1aSopenharmony_ci } 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci pkt_buffer_size = av_image_get_buffer_size(ctx->image_format, ctx->width, ctx->height, 32); 422cabdff1aSopenharmony_ci AImage_getTimestamp(image, &image_timestamp); 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci AImage_getPlaneRowStride(image, 0, &image_linestrides[0]); 425cabdff1aSopenharmony_ci AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]); 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci switch (ctx->image_format) { 428cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 429cabdff1aSopenharmony_ci AImage_getPlaneRowStride(image, 1, &image_linestrides[1]); 430cabdff1aSopenharmony_ci AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]); 431cabdff1aSopenharmony_ci AImage_getPlaneRowStride(image, 2, &image_linestrides[2]); 432cabdff1aSopenharmony_ci AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]); 433cabdff1aSopenharmony_ci break; 434cabdff1aSopenharmony_ci case AV_PIX_FMT_NV12: 435cabdff1aSopenharmony_ci AImage_getPlaneRowStride(image, 1, &image_linestrides[1]); 436cabdff1aSopenharmony_ci AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]); 437cabdff1aSopenharmony_ci break; 438cabdff1aSopenharmony_ci case AV_PIX_FMT_NV21: 439cabdff1aSopenharmony_ci AImage_getPlaneRowStride(image, 2, &image_linestrides[1]); 440cabdff1aSopenharmony_ci AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]); 441cabdff1aSopenharmony_ci break; 442cabdff1aSopenharmony_ci default: 443cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unsupported camera image format.\n"); 444cabdff1aSopenharmony_ci ret = AVERROR(ENOSYS); 445cabdff1aSopenharmony_ci goto error; 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci ret = av_new_packet(&pkt, pkt_buffer_size); 449cabdff1aSopenharmony_ci if (ret < 0) { 450cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 451cabdff1aSopenharmony_ci "Failed to create new av packet, error: %s.\n", av_err2str(ret)); 452cabdff1aSopenharmony_ci goto error; 453cabdff1aSopenharmony_ci } 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci pkt.stream_index = VIDEO_STREAM_INDEX; 456cabdff1aSopenharmony_ci pkt.pts = image_timestamp; 457cabdff1aSopenharmony_ci av_image_copy_to_buffer(pkt.data, pkt_buffer_size, 458cabdff1aSopenharmony_ci (const uint8_t * const *) image_plane_data, 459cabdff1aSopenharmony_ci image_linestrides, ctx->image_format, 460cabdff1aSopenharmony_ci ctx->width, ctx->height, 32); 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci ret = av_thread_message_queue_send(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK); 463cabdff1aSopenharmony_ci 464cabdff1aSopenharmony_cierror: 465cabdff1aSopenharmony_ci if (ret < 0) { 466cabdff1aSopenharmony_ci if (ret != AVERROR(EAGAIN)) { 467cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 468cabdff1aSopenharmony_ci "Error while processing new image, error: %s.\n", av_err2str(ret)); 469cabdff1aSopenharmony_ci av_thread_message_queue_set_err_recv(ctx->input_queue, ret); 470cabdff1aSopenharmony_ci atomic_store(&ctx->exit, 1); 471cabdff1aSopenharmony_ci } else { 472cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 473cabdff1aSopenharmony_ci "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n", 474cabdff1aSopenharmony_ci ctx->input_queue_size); 475cabdff1aSopenharmony_ci } 476cabdff1aSopenharmony_ci if (pkt_buffer_size) { 477cabdff1aSopenharmony_ci av_packet_unref(&pkt); 478cabdff1aSopenharmony_ci } 479cabdff1aSopenharmony_ci } 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci AImage_delete(image); 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci return; 484cabdff1aSopenharmony_ci} 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_cistatic int create_image_reader(AVFormatContext *avctx) 487cabdff1aSopenharmony_ci{ 488cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 489cabdff1aSopenharmony_ci media_status_t ret; 490cabdff1aSopenharmony_ci 491cabdff1aSopenharmony_ci ret = AImageReader_new(ctx->width, ctx->height, IMAGE_FORMAT_ANDROID, 492cabdff1aSopenharmony_ci MAX_BUF_COUNT, &ctx->image_reader); 493cabdff1aSopenharmony_ci if (ret != AMEDIA_OK) { 494cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 495cabdff1aSopenharmony_ci "Failed to create image reader, error: %s.\n", media_status_string(ret)); 496cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci 499cabdff1aSopenharmony_ci ctx->image_listener.context = avctx; 500cabdff1aSopenharmony_ci ctx->image_listener.onImageAvailable = image_available; 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci ret = AImageReader_setImageListener(ctx->image_reader, &ctx->image_listener); 503cabdff1aSopenharmony_ci if (ret != AMEDIA_OK) { 504cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 505cabdff1aSopenharmony_ci "Failed to set image listener on image reader, error: %s.\n", 506cabdff1aSopenharmony_ci media_status_string(ret)); 507cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 508cabdff1aSopenharmony_ci } 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_ci ret = AImageReader_getWindow(ctx->image_reader, &ctx->image_reader_window); 511cabdff1aSopenharmony_ci if (ret != AMEDIA_OK) { 512cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 513cabdff1aSopenharmony_ci "Could not get image reader window, error: %s.\n", 514cabdff1aSopenharmony_ci media_status_string(ret)); 515cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 516cabdff1aSopenharmony_ci } 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_ci return 0; 519cabdff1aSopenharmony_ci} 520cabdff1aSopenharmony_ci 521cabdff1aSopenharmony_cistatic void capture_session_closed(void *context, ACameraCaptureSession *session) 522cabdff1aSopenharmony_ci{ 523cabdff1aSopenharmony_ci av_log(context, AV_LOG_INFO, "Android camera capture session was closed.\n"); 524cabdff1aSopenharmony_ci} 525cabdff1aSopenharmony_ci 526cabdff1aSopenharmony_cistatic void capture_session_ready(void *context, ACameraCaptureSession *session) 527cabdff1aSopenharmony_ci{ 528cabdff1aSopenharmony_ci av_log(context, AV_LOG_INFO, "Android camera capture session is ready.\n"); 529cabdff1aSopenharmony_ci} 530cabdff1aSopenharmony_ci 531cabdff1aSopenharmony_cistatic void capture_session_active(void *context, ACameraCaptureSession *session) 532cabdff1aSopenharmony_ci{ 533cabdff1aSopenharmony_ci av_log(context, AV_LOG_INFO, "Android camera capture session is active.\n"); 534cabdff1aSopenharmony_ci} 535cabdff1aSopenharmony_ci 536cabdff1aSopenharmony_cistatic int create_capture_session(AVFormatContext *avctx) 537cabdff1aSopenharmony_ci{ 538cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 539cabdff1aSopenharmony_ci camera_status_t ret; 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci ret = ACaptureSessionOutputContainer_create(&ctx->capture_session_output_container); 542cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 543cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 544cabdff1aSopenharmony_ci "Failed to create capture session output container, error: %s.\n", 545cabdff1aSopenharmony_ci camera_status_string(ret)); 546cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 547cabdff1aSopenharmony_ci } 548cabdff1aSopenharmony_ci 549cabdff1aSopenharmony_ci ANativeWindow_acquire(ctx->image_reader_window); 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_ci ret = ACaptureSessionOutput_create(ctx->image_reader_window, &ctx->capture_session_output); 552cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 553cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 554cabdff1aSopenharmony_ci "Failed to create capture session container, error: %s.\n", 555cabdff1aSopenharmony_ci camera_status_string(ret)); 556cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 557cabdff1aSopenharmony_ci } 558cabdff1aSopenharmony_ci 559cabdff1aSopenharmony_ci ret = ACaptureSessionOutputContainer_add(ctx->capture_session_output_container, 560cabdff1aSopenharmony_ci ctx->capture_session_output); 561cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 562cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 563cabdff1aSopenharmony_ci "Failed to add output to output container, error: %s.\n", 564cabdff1aSopenharmony_ci camera_status_string(ret)); 565cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 566cabdff1aSopenharmony_ci } 567cabdff1aSopenharmony_ci 568cabdff1aSopenharmony_ci ret = ACameraOutputTarget_create(ctx->image_reader_window, &ctx->camera_output_target); 569cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 570cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 571cabdff1aSopenharmony_ci "Failed to create camera output target, error: %s.\n", 572cabdff1aSopenharmony_ci camera_status_string(ret)); 573cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 574cabdff1aSopenharmony_ci } 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci ret = ACameraDevice_createCaptureRequest(ctx->camera_dev, TEMPLATE_RECORD, &ctx->capture_request); 577cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 578cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 579cabdff1aSopenharmony_ci "Failed to create capture request, error: %s.\n", 580cabdff1aSopenharmony_ci camera_status_string(ret)); 581cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 582cabdff1aSopenharmony_ci } 583cabdff1aSopenharmony_ci 584cabdff1aSopenharmony_ci ret = ACaptureRequest_setEntry_i32(ctx->capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, 585cabdff1aSopenharmony_ci 2, ctx->framerate_range); 586cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 587cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 588cabdff1aSopenharmony_ci "Failed to set target fps range in capture request, error: %s.\n", 589cabdff1aSopenharmony_ci camera_status_string(ret)); 590cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 591cabdff1aSopenharmony_ci } 592cabdff1aSopenharmony_ci 593cabdff1aSopenharmony_ci ret = ACaptureRequest_addTarget(ctx->capture_request, ctx->camera_output_target); 594cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 595cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 596cabdff1aSopenharmony_ci "Failed to add capture request capture request, error: %s.\n", 597cabdff1aSopenharmony_ci camera_status_string(ret)); 598cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 599cabdff1aSopenharmony_ci } 600cabdff1aSopenharmony_ci 601cabdff1aSopenharmony_ci ctx->capture_session_state_callbacks.context = avctx; 602cabdff1aSopenharmony_ci ctx->capture_session_state_callbacks.onClosed = capture_session_closed; 603cabdff1aSopenharmony_ci ctx->capture_session_state_callbacks.onReady = capture_session_ready; 604cabdff1aSopenharmony_ci ctx->capture_session_state_callbacks.onActive = capture_session_active; 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_ci ret = ACameraDevice_createCaptureSession(ctx->camera_dev, ctx->capture_session_output_container, 607cabdff1aSopenharmony_ci &ctx->capture_session_state_callbacks, &ctx->capture_session); 608cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 609cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 610cabdff1aSopenharmony_ci "Failed to create capture session, error: %s.\n", 611cabdff1aSopenharmony_ci camera_status_string(ret)); 612cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 613cabdff1aSopenharmony_ci } 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci ret = ACameraCaptureSession_setRepeatingRequest(ctx->capture_session, NULL, 1, &ctx->capture_request, NULL); 616cabdff1aSopenharmony_ci if (ret != ACAMERA_OK) { 617cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 618cabdff1aSopenharmony_ci "Failed to set repeating request on capture session, error: %s.\n", 619cabdff1aSopenharmony_ci camera_status_string(ret)); 620cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 621cabdff1aSopenharmony_ci } 622cabdff1aSopenharmony_ci 623cabdff1aSopenharmony_ci return 0; 624cabdff1aSopenharmony_ci} 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_cistatic int wait_for_image_format(AVFormatContext *avctx) 627cabdff1aSopenharmony_ci{ 628cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 629cabdff1aSopenharmony_ci 630cabdff1aSopenharmony_ci while (!atomic_load(&ctx->got_image_format) && !atomic_load(&ctx->exit)) { 631cabdff1aSopenharmony_ci //Wait until first frame arrived and actual image format was determined 632cabdff1aSopenharmony_ci usleep(1000); 633cabdff1aSopenharmony_ci } 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci return atomic_load(&ctx->got_image_format); 636cabdff1aSopenharmony_ci} 637cabdff1aSopenharmony_ci 638cabdff1aSopenharmony_cistatic int add_display_matrix(AVFormatContext *avctx, AVStream *st) 639cabdff1aSopenharmony_ci{ 640cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 641cabdff1aSopenharmony_ci uint8_t *side_data; 642cabdff1aSopenharmony_ci int32_t display_matrix[9]; 643cabdff1aSopenharmony_ci 644cabdff1aSopenharmony_ci av_display_rotation_set(display_matrix, ctx->sensor_orientation); 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_ci if (ctx->lens_facing == ACAMERA_LENS_FACING_FRONT) { 647cabdff1aSopenharmony_ci av_display_matrix_flip(display_matrix, 1, 0); 648cabdff1aSopenharmony_ci } 649cabdff1aSopenharmony_ci 650cabdff1aSopenharmony_ci side_data = av_stream_new_side_data(st, 651cabdff1aSopenharmony_ci AV_PKT_DATA_DISPLAYMATRIX, sizeof(display_matrix)); 652cabdff1aSopenharmony_ci 653cabdff1aSopenharmony_ci if (!side_data) { 654cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 655cabdff1aSopenharmony_ci } 656cabdff1aSopenharmony_ci 657cabdff1aSopenharmony_ci memcpy(side_data, display_matrix, sizeof(display_matrix)); 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci return 0; 660cabdff1aSopenharmony_ci} 661cabdff1aSopenharmony_ci 662cabdff1aSopenharmony_cistatic int add_video_stream(AVFormatContext *avctx) 663cabdff1aSopenharmony_ci{ 664cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 665cabdff1aSopenharmony_ci AVStream *st; 666cabdff1aSopenharmony_ci AVCodecParameters *codecpar; 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci st = avformat_new_stream(avctx, NULL); 669cabdff1aSopenharmony_ci if (!st) { 670cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 671cabdff1aSopenharmony_ci } 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_ci st->id = VIDEO_STREAM_INDEX; 674cabdff1aSopenharmony_ci st->avg_frame_rate = (AVRational) { ctx->framerate_range[1], 1 }; 675cabdff1aSopenharmony_ci st->r_frame_rate = (AVRational) { ctx->framerate_range[1], 1 }; 676cabdff1aSopenharmony_ci 677cabdff1aSopenharmony_ci if (!wait_for_image_format(avctx)) { 678cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 679cabdff1aSopenharmony_ci } 680cabdff1aSopenharmony_ci 681cabdff1aSopenharmony_ci codecpar = st->codecpar; 682cabdff1aSopenharmony_ci codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 683cabdff1aSopenharmony_ci codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; 684cabdff1aSopenharmony_ci codecpar->format = ctx->image_format; 685cabdff1aSopenharmony_ci codecpar->width = ctx->width; 686cabdff1aSopenharmony_ci codecpar->height = ctx->height; 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, VIDEO_TIMEBASE_ANDROID); 689cabdff1aSopenharmony_ci 690cabdff1aSopenharmony_ci return add_display_matrix(avctx, st); 691cabdff1aSopenharmony_ci} 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_cistatic int android_camera_read_close(AVFormatContext *avctx) 694cabdff1aSopenharmony_ci{ 695cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_ci atomic_store(&ctx->exit, 1); 698cabdff1aSopenharmony_ci 699cabdff1aSopenharmony_ci if (ctx->capture_session) { 700cabdff1aSopenharmony_ci ACameraCaptureSession_stopRepeating(ctx->capture_session); 701cabdff1aSopenharmony_ci // Following warning is emitted, after capture session closed callback is received: 702cabdff1aSopenharmony_ci // ACameraCaptureSession: Device is closed but session 0 is not notified 703cabdff1aSopenharmony_ci // Seems to be a bug in Android, we can ignore this 704cabdff1aSopenharmony_ci ACameraCaptureSession_close(ctx->capture_session); 705cabdff1aSopenharmony_ci ctx->capture_session = NULL; 706cabdff1aSopenharmony_ci } 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci if (ctx->capture_request) { 709cabdff1aSopenharmony_ci ACaptureRequest_removeTarget(ctx->capture_request, ctx->camera_output_target); 710cabdff1aSopenharmony_ci ACaptureRequest_free(ctx->capture_request); 711cabdff1aSopenharmony_ci ctx->capture_request = NULL; 712cabdff1aSopenharmony_ci } 713cabdff1aSopenharmony_ci 714cabdff1aSopenharmony_ci if (ctx->camera_output_target) { 715cabdff1aSopenharmony_ci ACameraOutputTarget_free(ctx->camera_output_target); 716cabdff1aSopenharmony_ci ctx->camera_output_target = NULL; 717cabdff1aSopenharmony_ci } 718cabdff1aSopenharmony_ci 719cabdff1aSopenharmony_ci if (ctx->capture_session_output) { 720cabdff1aSopenharmony_ci ACaptureSessionOutputContainer_remove(ctx->capture_session_output_container, 721cabdff1aSopenharmony_ci ctx->capture_session_output); 722cabdff1aSopenharmony_ci ACaptureSessionOutput_free(ctx->capture_session_output); 723cabdff1aSopenharmony_ci ctx->capture_session_output = NULL; 724cabdff1aSopenharmony_ci } 725cabdff1aSopenharmony_ci 726cabdff1aSopenharmony_ci if (ctx->image_reader_window) { 727cabdff1aSopenharmony_ci ANativeWindow_release(ctx->image_reader_window); 728cabdff1aSopenharmony_ci ctx->image_reader_window = NULL; 729cabdff1aSopenharmony_ci } 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci if (ctx->capture_session_output_container) { 732cabdff1aSopenharmony_ci ACaptureSessionOutputContainer_free(ctx->capture_session_output_container); 733cabdff1aSopenharmony_ci ctx->capture_session_output_container = NULL; 734cabdff1aSopenharmony_ci } 735cabdff1aSopenharmony_ci 736cabdff1aSopenharmony_ci if (ctx->camera_dev) { 737cabdff1aSopenharmony_ci ACameraDevice_close(ctx->camera_dev); 738cabdff1aSopenharmony_ci ctx->camera_dev = NULL; 739cabdff1aSopenharmony_ci } 740cabdff1aSopenharmony_ci 741cabdff1aSopenharmony_ci if (ctx->image_reader) { 742cabdff1aSopenharmony_ci AImageReader_delete(ctx->image_reader); 743cabdff1aSopenharmony_ci ctx->image_reader = NULL; 744cabdff1aSopenharmony_ci } 745cabdff1aSopenharmony_ci 746cabdff1aSopenharmony_ci if (ctx->camera_metadata) { 747cabdff1aSopenharmony_ci ACameraMetadata_free(ctx->camera_metadata); 748cabdff1aSopenharmony_ci ctx->camera_metadata = NULL; 749cabdff1aSopenharmony_ci } 750cabdff1aSopenharmony_ci 751cabdff1aSopenharmony_ci av_freep(&ctx->camera_id); 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_ci if (ctx->camera_mgr) { 754cabdff1aSopenharmony_ci ACameraManager_delete(ctx->camera_mgr); 755cabdff1aSopenharmony_ci ctx->camera_mgr = NULL; 756cabdff1aSopenharmony_ci } 757cabdff1aSopenharmony_ci 758cabdff1aSopenharmony_ci if (ctx->input_queue) { 759cabdff1aSopenharmony_ci AVPacket pkt; 760cabdff1aSopenharmony_ci av_thread_message_queue_set_err_send(ctx->input_queue, AVERROR_EOF); 761cabdff1aSopenharmony_ci while (av_thread_message_queue_recv(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK) >= 0) { 762cabdff1aSopenharmony_ci av_packet_unref(&pkt); 763cabdff1aSopenharmony_ci } 764cabdff1aSopenharmony_ci av_thread_message_queue_free(&ctx->input_queue); 765cabdff1aSopenharmony_ci } 766cabdff1aSopenharmony_ci 767cabdff1aSopenharmony_ci return 0; 768cabdff1aSopenharmony_ci} 769cabdff1aSopenharmony_ci 770cabdff1aSopenharmony_cistatic int android_camera_read_header(AVFormatContext *avctx) 771cabdff1aSopenharmony_ci{ 772cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 773cabdff1aSopenharmony_ci int ret; 774cabdff1aSopenharmony_ci 775cabdff1aSopenharmony_ci atomic_init(&ctx->got_image_format, 0); 776cabdff1aSopenharmony_ci atomic_init(&ctx->exit, 0); 777cabdff1aSopenharmony_ci 778cabdff1aSopenharmony_ci ret = av_thread_message_queue_alloc(&ctx->input_queue, ctx->input_queue_size, sizeof(AVPacket)); 779cabdff1aSopenharmony_ci if (ret < 0) { 780cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 781cabdff1aSopenharmony_ci "Failed to allocate input queue, error: %s.\n", av_err2str(ret)); 782cabdff1aSopenharmony_ci goto error; 783cabdff1aSopenharmony_ci } 784cabdff1aSopenharmony_ci 785cabdff1aSopenharmony_ci ctx->camera_mgr = ACameraManager_create(); 786cabdff1aSopenharmony_ci if (!ctx->camera_mgr) { 787cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to create Android camera manager.\n"); 788cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 789cabdff1aSopenharmony_ci goto error; 790cabdff1aSopenharmony_ci } 791cabdff1aSopenharmony_ci 792cabdff1aSopenharmony_ci ret = open_camera(avctx); 793cabdff1aSopenharmony_ci if (ret < 0) { 794cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to open camera.\n"); 795cabdff1aSopenharmony_ci goto error; 796cabdff1aSopenharmony_ci } 797cabdff1aSopenharmony_ci 798cabdff1aSopenharmony_ci get_sensor_orientation(avctx); 799cabdff1aSopenharmony_ci match_video_size(avctx); 800cabdff1aSopenharmony_ci match_framerate(avctx); 801cabdff1aSopenharmony_ci 802cabdff1aSopenharmony_ci ret = create_image_reader(avctx); 803cabdff1aSopenharmony_ci if (ret < 0) { 804cabdff1aSopenharmony_ci goto error; 805cabdff1aSopenharmony_ci } 806cabdff1aSopenharmony_ci 807cabdff1aSopenharmony_ci ret = create_capture_session(avctx); 808cabdff1aSopenharmony_ci if (ret < 0) { 809cabdff1aSopenharmony_ci goto error; 810cabdff1aSopenharmony_ci } 811cabdff1aSopenharmony_ci 812cabdff1aSopenharmony_ci ret = add_video_stream(avctx); 813cabdff1aSopenharmony_ci 814cabdff1aSopenharmony_cierror: 815cabdff1aSopenharmony_ci if (ret < 0) { 816cabdff1aSopenharmony_ci android_camera_read_close(avctx); 817cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to open android_camera.\n"); 818cabdff1aSopenharmony_ci } 819cabdff1aSopenharmony_ci 820cabdff1aSopenharmony_ci return ret; 821cabdff1aSopenharmony_ci} 822cabdff1aSopenharmony_ci 823cabdff1aSopenharmony_cistatic int android_camera_read_packet(AVFormatContext *avctx, AVPacket *pkt) 824cabdff1aSopenharmony_ci{ 825cabdff1aSopenharmony_ci AndroidCameraCtx *ctx = avctx->priv_data; 826cabdff1aSopenharmony_ci int ret; 827cabdff1aSopenharmony_ci 828cabdff1aSopenharmony_ci if (!atomic_load(&ctx->exit)) { 829cabdff1aSopenharmony_ci ret = av_thread_message_queue_recv(ctx->input_queue, pkt, 830cabdff1aSopenharmony_ci avctx->flags & AVFMT_FLAG_NONBLOCK ? AV_THREAD_MESSAGE_NONBLOCK : 0); 831cabdff1aSopenharmony_ci } else { 832cabdff1aSopenharmony_ci ret = AVERROR_EOF; 833cabdff1aSopenharmony_ci } 834cabdff1aSopenharmony_ci 835cabdff1aSopenharmony_ci if (ret < 0) { 836cabdff1aSopenharmony_ci return ret; 837cabdff1aSopenharmony_ci } else { 838cabdff1aSopenharmony_ci return pkt->size; 839cabdff1aSopenharmony_ci } 840cabdff1aSopenharmony_ci} 841cabdff1aSopenharmony_ci 842cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(AndroidCameraCtx, x) 843cabdff1aSopenharmony_ci#define DEC AV_OPT_FLAG_DECODING_PARAM 844cabdff1aSopenharmony_cistatic const AVOption options[] = { 845cabdff1aSopenharmony_ci { "video_size", "set video size given as a string such as 640x480 or hd720", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, 846cabdff1aSopenharmony_ci { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "30"}, 0, INT_MAX, DEC }, 847cabdff1aSopenharmony_ci { "camera_index", "set index of camera to use", OFFSET(camera_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC }, 848cabdff1aSopenharmony_ci { "input_queue_size", "set maximum number of frames to buffer", OFFSET(input_queue_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, DEC }, 849cabdff1aSopenharmony_ci { NULL }, 850cabdff1aSopenharmony_ci}; 851cabdff1aSopenharmony_ci 852cabdff1aSopenharmony_cistatic const AVClass android_camera_class = { 853cabdff1aSopenharmony_ci .class_name = "android_camera indev", 854cabdff1aSopenharmony_ci .item_name = av_default_item_name, 855cabdff1aSopenharmony_ci .option = options, 856cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 857cabdff1aSopenharmony_ci .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, 858cabdff1aSopenharmony_ci}; 859cabdff1aSopenharmony_ci 860cabdff1aSopenharmony_ciconst AVInputFormat ff_android_camera_demuxer = { 861cabdff1aSopenharmony_ci .name = "android_camera", 862cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Android camera input device"), 863cabdff1aSopenharmony_ci .priv_data_size = sizeof(AndroidCameraCtx), 864cabdff1aSopenharmony_ci .read_header = android_camera_read_header, 865cabdff1aSopenharmony_ci .read_packet = android_camera_read_packet, 866cabdff1aSopenharmony_ci .read_close = android_camera_read_close, 867cabdff1aSopenharmony_ci .flags = AVFMT_NOFILE, 868cabdff1aSopenharmony_ci .priv_class = &android_camera_class, 869cabdff1aSopenharmony_ci}; 870