2 * Android camera input device
4 * Copyright (C) 2017 Felix Matouschek
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <stdatomic.h>
30 #include <camera/NdkCameraDevice.h>
31 #include <camera/NdkCameraManager.h>
32 #include <media/NdkImage.h>
33 #include <media/NdkImageReader.h>
35 #include "libavformat/avformat.h"
36 #include "libavformat/internal.h"
37 #include "libavutil/avstring.h"
38 #include "libavutil/display.h"
39 #include "libavutil/imgutils.h"
40 #include "libavutil/log.h"
41 #include "libavutil/opt.h"
42 #include "libavutil/parseutils.h"
43 #include "libavutil/pixfmt.h"
44 #include "libavutil/threadmessage.h"
45 #include "libavutil/time.h"
47 /* This image format is available on all Android devices
48 * supporting the Camera2 API */
49 #define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888
51 #define MAX_BUF_COUNT 2
52 #define VIDEO_STREAM_INDEX 0
53 #define VIDEO_TIMEBASE_ANDROID 1000000000
55 #define RETURN_CASE(x) case x: return AV_STRINGIFY(x);
56 #define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x);
58 typedef struct AndroidCameraCtx {
68 int32_t sensor_orientation;
71 int32_t framerate_range[2];
74 ACameraManager *camera_mgr;
76 ACameraMetadata *camera_metadata;
77 ACameraDevice *camera_dev;
78 ACameraDevice_StateCallbacks camera_state_callbacks;
79 AImageReader *image_reader;
80 AImageReader_ImageListener image_listener;
81 ANativeWindow *image_reader_window;
82 ACaptureSessionOutputContainer *capture_session_output_container;
83 ACaptureSessionOutput *capture_session_output;
84 ACameraOutputTarget *camera_output_target;
85 ACaptureRequest *capture_request;
86 ACameraCaptureSession_stateCallbacks capture_session_state_callbacks;
87 ACameraCaptureSession *capture_session;
89 AVThreadMessageQueue *input_queue;
91 atomic_int got_image_format;
94 static const char *camera_status_string(camera_status_t val)
97 RETURN_CASE(ACAMERA_OK)
98 RETURN_CASE(ACAMERA_ERROR_UNKNOWN)
99 RETURN_CASE(ACAMERA_ERROR_INVALID_PARAMETER)
100 RETURN_CASE(ACAMERA_ERROR_CAMERA_DISCONNECTED)
101 RETURN_CASE(ACAMERA_ERROR_NOT_ENOUGH_MEMORY)
102 RETURN_CASE(ACAMERA_ERROR_METADATA_NOT_FOUND)
103 RETURN_CASE(ACAMERA_ERROR_CAMERA_DEVICE)
104 RETURN_CASE(ACAMERA_ERROR_CAMERA_SERVICE)
105 RETURN_CASE(ACAMERA_ERROR_SESSION_CLOSED)
106 RETURN_CASE(ACAMERA_ERROR_INVALID_OPERATION)
107 RETURN_CASE(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL)
108 RETURN_CASE(ACAMERA_ERROR_CAMERA_IN_USE)
109 RETURN_CASE(ACAMERA_ERROR_MAX_CAMERA_IN_USE)
110 RETURN_CASE(ACAMERA_ERROR_CAMERA_DISABLED)
111 RETURN_CASE(ACAMERA_ERROR_PERMISSION_DENIED)
112 RETURN_DEFAULT(ACAMERA_ERROR_UNKNOWN)
116 static const char *media_status_string(media_status_t val)
119 RETURN_CASE(AMEDIA_OK)
120 RETURN_CASE(AMEDIA_ERROR_UNKNOWN)
121 RETURN_CASE(AMEDIA_ERROR_MALFORMED)
122 RETURN_CASE(AMEDIA_ERROR_UNSUPPORTED)
123 RETURN_CASE(AMEDIA_ERROR_INVALID_OBJECT)
124 RETURN_CASE(AMEDIA_ERROR_INVALID_PARAMETER)
125 RETURN_CASE(AMEDIA_ERROR_INVALID_OPERATION)
126 RETURN_CASE(AMEDIA_DRM_NOT_PROVISIONED)
127 RETURN_CASE(AMEDIA_DRM_RESOURCE_BUSY)
128 RETURN_CASE(AMEDIA_DRM_DEVICE_REVOKED)
129 RETURN_CASE(AMEDIA_DRM_SHORT_BUFFER)
130 RETURN_CASE(AMEDIA_DRM_SESSION_NOT_OPENED)
131 RETURN_CASE(AMEDIA_DRM_TAMPER_DETECTED)
132 RETURN_CASE(AMEDIA_DRM_VERIFY_FAILED)
133 RETURN_CASE(AMEDIA_DRM_NEED_KEY)
134 RETURN_CASE(AMEDIA_DRM_LICENSE_EXPIRED)
135 RETURN_CASE(AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE)
136 RETURN_CASE(AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED)
137 RETURN_CASE(AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE)
138 RETURN_CASE(AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE)
139 RETURN_CASE(AMEDIA_IMGREADER_IMAGE_NOT_LOCKED)
140 RETURN_DEFAULT(AMEDIA_ERROR_UNKNOWN)
144 static const char *error_state_callback_string(int val)
147 RETURN_CASE(ERROR_CAMERA_IN_USE)
148 RETURN_CASE(ERROR_MAX_CAMERAS_IN_USE)
149 RETURN_CASE(ERROR_CAMERA_DISABLED)
150 RETURN_CASE(ERROR_CAMERA_DEVICE)
151 RETURN_CASE(ERROR_CAMERA_SERVICE)
153 return "ERROR_CAMERA_UNKNOWN";
157 static void camera_dev_disconnected(void *context, ACameraDevice *device)
159 AVFormatContext *avctx = context;
160 AndroidCameraCtx *ctx = avctx->priv_data;
161 atomic_store(&ctx->exit, 1);
162 av_log(avctx, AV_LOG_ERROR, "Camera with id %s disconnected.\n",
163 ACameraDevice_getId(device));
166 static void camera_dev_error(void *context, ACameraDevice *device, int error)
168 AVFormatContext *avctx = context;
169 AndroidCameraCtx *ctx = avctx->priv_data;
170 atomic_store(&ctx->exit, 1);
171 av_log(avctx, AV_LOG_ERROR, "Error %s on camera with id %s.\n",
172 error_state_callback_string(error), ACameraDevice_getId(device));
175 static int open_camera(AVFormatContext *avctx)
177 AndroidCameraCtx *ctx = avctx->priv_data;
179 ACameraIdList *camera_ids;
181 ret = ACameraManager_getCameraIdList(ctx->camera_mgr, &camera_ids);
182 if (ret != ACAMERA_OK) {
183 av_log(avctx, AV_LOG_ERROR, "Failed to get camera id list, error: %s.\n",
184 camera_status_string(ret));
185 return AVERROR_EXTERNAL;
188 if (ctx->camera_index < camera_ids->numCameras) {
189 ctx->camera_id = av_strdup(camera_ids->cameraIds[ctx->camera_index]);
190 if (!ctx->camera_id) {
191 av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for camera_id.\n");
192 return AVERROR(ENOMEM);
195 av_log(avctx, AV_LOG_ERROR, "No camera with index %d available.\n",
197 return AVERROR(ENXIO);
200 ACameraManager_deleteCameraIdList(camera_ids);
202 ret = ACameraManager_getCameraCharacteristics(ctx->camera_mgr,
203 ctx->camera_id, &ctx->camera_metadata);
204 if (ret != ACAMERA_OK) {
205 av_log(avctx, AV_LOG_ERROR, "Failed to get metadata for camera with id %s, error: %s.\n",
206 ctx->camera_id, camera_status_string(ret));
207 return AVERROR_EXTERNAL;
210 ctx->camera_state_callbacks.context = avctx;
211 ctx->camera_state_callbacks.onDisconnected = camera_dev_disconnected;
212 ctx->camera_state_callbacks.onError = camera_dev_error;
214 ret = ACameraManager_openCamera(ctx->camera_mgr, ctx->camera_id,
215 &ctx->camera_state_callbacks, &ctx->camera_dev);
216 if (ret != ACAMERA_OK) {
217 av_log(avctx, AV_LOG_ERROR, "Failed to open camera with id %s, error: %s.\n",
218 ctx->camera_id, camera_status_string(ret));
219 return AVERROR_EXTERNAL;
225 static void get_sensor_orientation(AVFormatContext *avctx)
227 AndroidCameraCtx *ctx = avctx->priv_data;
228 ACameraMetadata_const_entry lens_facing;
229 ACameraMetadata_const_entry sensor_orientation;
231 ACameraMetadata_getConstEntry(ctx->camera_metadata,
232 ACAMERA_LENS_FACING, &lens_facing);
233 ACameraMetadata_getConstEntry(ctx->camera_metadata,
234 ACAMERA_SENSOR_ORIENTATION, &sensor_orientation);
236 ctx->lens_facing = lens_facing.data.u8[0];
237 ctx->sensor_orientation = sensor_orientation.data.i32[0];
240 static void match_video_size(AVFormatContext *avctx)
242 AndroidCameraCtx *ctx = avctx->priv_data;
243 ACameraMetadata_const_entry available_configs;
246 ACameraMetadata_getConstEntry(ctx->camera_metadata,
247 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
250 for (int i = 0; i < available_configs.count; i++) {
251 int32_t input = available_configs.data.i32[i * 4 + 3];
252 int32_t format = available_configs.data.i32[i * 4 + 0];
258 if (format == IMAGE_FORMAT_ANDROID) {
259 int32_t width = available_configs.data.i32[i * 4 + 1];
260 int32_t height = available_configs.data.i32[i * 4 + 2];
263 if ((ctx->requested_width == width && ctx->requested_height == height) ||
264 (ctx->requested_width == height && ctx->requested_height == width)) {
266 ctx->height = height;
273 if (!found || ctx->width == 0 || ctx->height == 0) {
274 ctx->width = available_configs.data.i32[1];
275 ctx->height = available_configs.data.i32[2];
277 av_log(avctx, AV_LOG_WARNING,
278 "Requested video_size %dx%d not available, falling back to %dx%d\n",
279 ctx->requested_width, ctx->requested_height, ctx->width, ctx->height);
285 static void match_framerate(AVFormatContext *avctx)
287 AndroidCameraCtx *ctx = avctx->priv_data;
288 ACameraMetadata_const_entry available_framerates;
290 int current_best_match = -1;
291 int requested_framerate = av_q2d(ctx->framerate);
293 ACameraMetadata_getConstEntry(ctx->camera_metadata,
294 ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
295 &available_framerates);
297 for (int i = 0; i < available_framerates.count; i++) {
298 int32_t min = available_framerates.data.i32[i * 2 + 0];
299 int32_t max = available_framerates.data.i32[i * 2 + 1];
301 if (requested_framerate == max) {
303 ctx->framerate_range[0] = min;
304 ctx->framerate_range[1] = max;
307 } else if (current_best_match >= 0) {
308 int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0];
309 if (min > current_best_match_min) {
310 current_best_match = i;
313 current_best_match = i;
319 if (current_best_match >= 0) {
320 ctx->framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0];
321 ctx->framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1];
324 ctx->framerate_range[0] = available_framerates.data.i32[0];
325 ctx->framerate_range[1] = available_framerates.data.i32[1];
328 av_log(avctx, AV_LOG_WARNING,
329 "Requested framerate %d not available, falling back to min: %d and max: %d fps\n",
330 requested_framerate, ctx->framerate_range[0], ctx->framerate_range[1]);
336 static int get_image_format(AVFormatContext *avctx, AImage *image)
338 AndroidCameraCtx *ctx = avctx->priv_data;
339 int32_t image_pixelstrides[2];
340 uint8_t *image_plane_data[2];
341 int plane_data_length[2];
343 for (int i = 0; i < 2; i++) {
344 AImage_getPlanePixelStride(image, i + 1, &image_pixelstrides[i]);
345 AImage_getPlaneData(image, i + 1, &image_plane_data[i], &plane_data_length[i]);
348 if (image_pixelstrides[0] != image_pixelstrides[1]) {
349 av_log(avctx, AV_LOG_ERROR,
350 "Pixel strides of U and V plane should have been the same.\n");
351 return AVERROR_EXTERNAL;
354 switch (image_pixelstrides[0]) {
356 ctx->image_format = AV_PIX_FMT_YUV420P;
359 if (image_plane_data[0] < image_plane_data[1]) {
360 ctx->image_format = AV_PIX_FMT_NV12;
362 ctx->image_format = AV_PIX_FMT_NV21;
366 av_log(avctx, AV_LOG_ERROR,
367 "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n",
368 image_pixelstrides[0]);
369 return AVERROR(ENOSYS);
375 static void image_available(void *context, AImageReader *reader)
377 AVFormatContext *avctx = context;
378 AndroidCameraCtx *ctx = avctx->priv_data;
379 media_status_t media_status;
383 int64_t image_timestamp;
384 int32_t image_linestrides[4];
385 uint8_t *image_plane_data[4];
386 int plane_data_length[4];
389 int pkt_buffer_size = 0;
391 media_status = AImageReader_acquireLatestImage(reader, &image);
392 if (media_status != AMEDIA_OK) {
393 if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
394 av_log(avctx, AV_LOG_WARNING,
395 "An image reader frame was discarded");
397 av_log(avctx, AV_LOG_ERROR,
398 "Failed to acquire latest image from image reader, error: %s.\n",
399 media_status_string(media_status));
400 ret = AVERROR_EXTERNAL;
405 // Silently drop frames when exit is set
406 if (atomic_load(&ctx->exit)) {
410 // Determine actual image format
411 if (!atomic_load(&ctx->got_image_format)) {
412 ret = get_image_format(avctx, image);
414 av_log(avctx, AV_LOG_ERROR,
415 "Could not get image format of camera.\n");
418 atomic_store(&ctx->got_image_format, 1);
422 pkt_buffer_size = av_image_get_buffer_size(ctx->image_format, ctx->width, ctx->height, 32);
423 AImage_getTimestamp(image, &image_timestamp);
425 AImage_getPlaneRowStride(image, 0, &image_linestrides[0]);
426 AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]);
428 switch (ctx->image_format) {
429 case AV_PIX_FMT_YUV420P:
430 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
431 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
432 AImage_getPlaneRowStride(image, 2, &image_linestrides[2]);
433 AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]);
435 case AV_PIX_FMT_NV12:
436 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
437 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
439 case AV_PIX_FMT_NV21:
440 AImage_getPlaneRowStride(image, 2, &image_linestrides[1]);
441 AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]);
444 av_log(avctx, AV_LOG_ERROR, "Unsupported camera image format.\n");
445 ret = AVERROR(ENOSYS);
449 ret = av_new_packet(&pkt, pkt_buffer_size);
451 av_log(avctx, AV_LOG_ERROR,
452 "Failed to create new av packet, error: %s.\n", av_err2str(ret));
456 pkt.stream_index = VIDEO_STREAM_INDEX;
457 pkt.pts = image_timestamp;
458 av_image_copy_to_buffer(pkt.data, pkt_buffer_size,
459 (const uint8_t * const *) image_plane_data,
460 image_linestrides, ctx->image_format,
461 ctx->width, ctx->height, 32);
463 ret = av_thread_message_queue_send(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK);
467 if (ret != AVERROR(EAGAIN)) {
468 av_log(avctx, AV_LOG_ERROR,
469 "Error while processing new image, error: %s.\n", av_err2str(ret));
470 av_thread_message_queue_set_err_recv(ctx->input_queue, ret);
471 atomic_store(&ctx->exit, 1);
473 av_log(avctx, AV_LOG_WARNING,
474 "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n",
475 ctx->input_queue_size);
477 if (pkt_buffer_size) {
478 av_packet_unref(&pkt);
482 AImage_delete(image);
487 static int create_image_reader(AVFormatContext *avctx)
489 AndroidCameraCtx *ctx = avctx->priv_data;
492 ret = AImageReader_new(ctx->width, ctx->height, IMAGE_FORMAT_ANDROID,
493 MAX_BUF_COUNT, &ctx->image_reader);
494 if (ret != AMEDIA_OK) {
495 av_log(avctx, AV_LOG_ERROR,
496 "Failed to create image reader, error: %s.\n", media_status_string(ret));
497 return AVERROR_EXTERNAL;
500 ctx->image_listener.context = avctx;
501 ctx->image_listener.onImageAvailable = image_available;
503 ret = AImageReader_setImageListener(ctx->image_reader, &ctx->image_listener);
504 if (ret != AMEDIA_OK) {
505 av_log(avctx, AV_LOG_ERROR,
506 "Failed to set image listener on image reader, error: %s.\n",
507 media_status_string(ret));
508 return AVERROR_EXTERNAL;
511 ret = AImageReader_getWindow(ctx->image_reader, &ctx->image_reader_window);
512 if (ret != AMEDIA_OK) {
513 av_log(avctx, AV_LOG_ERROR,
514 "Could not get image reader window, error: %s.\n",
515 media_status_string(ret));
516 return AVERROR_EXTERNAL;
522 static void capture_session_closed(void *context, ACameraCaptureSession *session)
524 av_log(context, AV_LOG_INFO, "Android camera capture session was closed.\n");
527 static void capture_session_ready(void *context, ACameraCaptureSession *session)
529 av_log(context, AV_LOG_INFO, "Android camera capture session is ready.\n");
532 static void capture_session_active(void *context, ACameraCaptureSession *session)
534 av_log(context, AV_LOG_INFO, "Android camera capture session is active.\n");
537 static int create_capture_session(AVFormatContext *avctx)
539 AndroidCameraCtx *ctx = avctx->priv_data;
542 ret = ACaptureSessionOutputContainer_create(&ctx->capture_session_output_container);
543 if (ret != ACAMERA_OK) {
544 av_log(avctx, AV_LOG_ERROR,
545 "Failed to create capture session output container, error: %s.\n",
546 camera_status_string(ret));
547 return AVERROR_EXTERNAL;
550 ANativeWindow_acquire(ctx->image_reader_window);
552 ret = ACaptureSessionOutput_create(ctx->image_reader_window, &ctx->capture_session_output);
553 if (ret != ACAMERA_OK) {
554 av_log(avctx, AV_LOG_ERROR,
555 "Failed to create capture session container, error: %s.\n",
556 camera_status_string(ret));
557 return AVERROR_EXTERNAL;
560 ret = ACaptureSessionOutputContainer_add(ctx->capture_session_output_container,
561 ctx->capture_session_output);
562 if (ret != ACAMERA_OK) {
563 av_log(avctx, AV_LOG_ERROR,
564 "Failed to add output to output container, error: %s.\n",
565 camera_status_string(ret));
566 return AVERROR_EXTERNAL;
569 ret = ACameraOutputTarget_create(ctx->image_reader_window, &ctx->camera_output_target);
570 if (ret != ACAMERA_OK) {
571 av_log(avctx, AV_LOG_ERROR,
572 "Failed to create camera output target, error: %s.\n",
573 camera_status_string(ret));
574 return AVERROR_EXTERNAL;
577 ret = ACameraDevice_createCaptureRequest(ctx->camera_dev, TEMPLATE_RECORD, &ctx->capture_request);
578 if (ret != ACAMERA_OK) {
579 av_log(avctx, AV_LOG_ERROR,
580 "Failed to create capture request, error: %s.\n",
581 camera_status_string(ret));
582 return AVERROR_EXTERNAL;
585 ret = ACaptureRequest_setEntry_i32(ctx->capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,
586 2, ctx->framerate_range);
587 if (ret != ACAMERA_OK) {
588 av_log(avctx, AV_LOG_ERROR,
589 "Failed to set target fps range in capture request, error: %s.\n",
590 camera_status_string(ret));
591 return AVERROR_EXTERNAL;
594 ret = ACaptureRequest_addTarget(ctx->capture_request, ctx->camera_output_target);
595 if (ret != ACAMERA_OK) {
596 av_log(avctx, AV_LOG_ERROR,
597 "Failed to add capture request capture request, error: %s.\n",
598 camera_status_string(ret));
599 return AVERROR_EXTERNAL;
602 ctx->capture_session_state_callbacks.context = avctx;
603 ctx->capture_session_state_callbacks.onClosed = capture_session_closed;
604 ctx->capture_session_state_callbacks.onReady = capture_session_ready;
605 ctx->capture_session_state_callbacks.onActive = capture_session_active;
607 ret = ACameraDevice_createCaptureSession(ctx->camera_dev, ctx->capture_session_output_container,
608 &ctx->capture_session_state_callbacks, &ctx->capture_session);
609 if (ret != ACAMERA_OK) {
610 av_log(avctx, AV_LOG_ERROR,
611 "Failed to create capture session, error: %s.\n",
612 camera_status_string(ret));
613 return AVERROR_EXTERNAL;
616 ret = ACameraCaptureSession_setRepeatingRequest(ctx->capture_session, NULL, 1, &ctx->capture_request, NULL);
617 if (ret != ACAMERA_OK) {
618 av_log(avctx, AV_LOG_ERROR,
619 "Failed to set repeating request on capture session, error: %s.\n",
620 camera_status_string(ret));
621 return AVERROR_EXTERNAL;
627 static int wait_for_image_format(AVFormatContext *avctx)
629 AndroidCameraCtx *ctx = avctx->priv_data;
631 while (!atomic_load(&ctx->got_image_format) && !atomic_load(&ctx->exit)) {
632 //Wait until first frame arrived and actual image format was determined
636 return atomic_load(&ctx->got_image_format);
639 static int add_display_matrix(AVFormatContext *avctx, AVStream *st)
641 AndroidCameraCtx *ctx = avctx->priv_data;
642 AVPacketSideData *side_data;
643 int32_t display_matrix[9];
645 av_display_rotation_set(display_matrix, ctx->sensor_orientation);
647 if (ctx->lens_facing == ACAMERA_LENS_FACING_FRONT) {
648 av_display_matrix_flip(display_matrix, 1, 0);
651 side_data = av_packet_side_data_new(&st->codecpar->coded_side_data,
652 &st->codecpar->nb_coded_side_data,
653 AV_PKT_DATA_DISPLAYMATRIX,
654 sizeof(display_matrix), 0);
657 return AVERROR(ENOMEM);
660 memcpy(side_data->data, display_matrix, sizeof(display_matrix));
665 static int add_video_stream(AVFormatContext *avctx)
667 AndroidCameraCtx *ctx = avctx->priv_data;
669 AVCodecParameters *codecpar;
671 st = avformat_new_stream(avctx, NULL);
673 return AVERROR(ENOMEM);
676 st->id = VIDEO_STREAM_INDEX;
677 st->avg_frame_rate = (AVRational) { ctx->framerate_range[1], 1 };
678 st->r_frame_rate = (AVRational) { ctx->framerate_range[1], 1 };
680 if (!wait_for_image_format(avctx)) {
681 return AVERROR_EXTERNAL;
684 codecpar = st->codecpar;
685 codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
686 codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
687 codecpar->format = ctx->image_format;
688 codecpar->width = ctx->width;
689 codecpar->height = ctx->height;
691 avpriv_set_pts_info(st, 64, 1, VIDEO_TIMEBASE_ANDROID);
693 return add_display_matrix(avctx, st);
696 static int android_camera_read_close(AVFormatContext *avctx)
698 AndroidCameraCtx *ctx = avctx->priv_data;
700 atomic_store(&ctx->exit, 1);
702 if (ctx->capture_session) {
703 ACameraCaptureSession_stopRepeating(ctx->capture_session);
704 // Following warning is emitted, after capture session closed callback is received:
705 // ACameraCaptureSession: Device is closed but session 0 is not notified
706 // Seems to be a bug in Android, we can ignore this
707 ACameraCaptureSession_close(ctx->capture_session);
708 ctx->capture_session = NULL;
711 if (ctx->capture_request) {
712 ACaptureRequest_removeTarget(ctx->capture_request, ctx->camera_output_target);
713 ACaptureRequest_free(ctx->capture_request);
714 ctx->capture_request = NULL;
717 if (ctx->camera_output_target) {
718 ACameraOutputTarget_free(ctx->camera_output_target);
719 ctx->camera_output_target = NULL;
722 if (ctx->capture_session_output) {
723 ACaptureSessionOutputContainer_remove(ctx->capture_session_output_container,
724 ctx->capture_session_output);
725 ACaptureSessionOutput_free(ctx->capture_session_output);
726 ctx->capture_session_output = NULL;
729 if (ctx->image_reader_window) {
730 ANativeWindow_release(ctx->image_reader_window);
731 ctx->image_reader_window = NULL;
734 if (ctx->capture_session_output_container) {
735 ACaptureSessionOutputContainer_free(ctx->capture_session_output_container);
736 ctx->capture_session_output_container = NULL;
739 if (ctx->camera_dev) {
740 ACameraDevice_close(ctx->camera_dev);
741 ctx->camera_dev = NULL;
744 if (ctx->image_reader) {
745 AImageReader_delete(ctx->image_reader);
746 ctx->image_reader = NULL;
749 if (ctx->camera_metadata) {
750 ACameraMetadata_free(ctx->camera_metadata);
751 ctx->camera_metadata = NULL;
754 av_freep(&ctx->camera_id);
756 if (ctx->camera_mgr) {
757 ACameraManager_delete(ctx->camera_mgr);
758 ctx->camera_mgr = NULL;
761 if (ctx->input_queue) {
763 av_thread_message_queue_set_err_send(ctx->input_queue, AVERROR_EOF);
764 while (av_thread_message_queue_recv(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK) >= 0) {
765 av_packet_unref(&pkt);
767 av_thread_message_queue_free(&ctx->input_queue);
773 static int android_camera_read_header(AVFormatContext *avctx)
775 AndroidCameraCtx *ctx = avctx->priv_data;
778 atomic_init(&ctx->got_image_format, 0);
779 atomic_init(&ctx->exit, 0);
781 ret = av_thread_message_queue_alloc(&ctx->input_queue, ctx->input_queue_size, sizeof(AVPacket));
783 av_log(avctx, AV_LOG_ERROR,
784 "Failed to allocate input queue, error: %s.\n", av_err2str(ret));
788 ctx->camera_mgr = ACameraManager_create();
789 if (!ctx->camera_mgr) {
790 av_log(avctx, AV_LOG_ERROR, "Failed to create Android camera manager.\n");
791 ret = AVERROR_EXTERNAL;
795 ret = open_camera(avctx);
797 av_log(avctx, AV_LOG_ERROR, "Failed to open camera.\n");
801 get_sensor_orientation(avctx);
802 match_video_size(avctx);
803 match_framerate(avctx);
805 ret = create_image_reader(avctx);
810 ret = create_capture_session(avctx);
815 ret = add_video_stream(avctx);
819 android_camera_read_close(avctx);
820 av_log(avctx, AV_LOG_ERROR, "Failed to open android_camera.\n");
826 static int android_camera_read_packet(AVFormatContext *avctx, AVPacket *pkt)
828 AndroidCameraCtx *ctx = avctx->priv_data;
831 if (!atomic_load(&ctx->exit)) {
832 ret = av_thread_message_queue_recv(ctx->input_queue, pkt,
833 avctx->flags & AVFMT_FLAG_NONBLOCK ? AV_THREAD_MESSAGE_NONBLOCK : 0);
845 #define OFFSET(x) offsetof(AndroidCameraCtx, x)
846 #define DEC AV_OPT_FLAG_DECODING_PARAM
847 static const AVOption options[] = {
848 { "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 },
849 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "30"}, 0, INT_MAX, DEC },
850 { "camera_index", "set index of camera to use", OFFSET(camera_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
851 { "input_queue_size", "set maximum number of frames to buffer", OFFSET(input_queue_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, DEC },
855 static const AVClass android_camera_class = {
856 .class_name = "android_camera indev",
857 .item_name = av_default_item_name,
859 .version = LIBAVUTIL_VERSION_INT,
860 .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
863 const AVInputFormat ff_android_camera_demuxer = {
864 .name = "android_camera",
865 .long_name = NULL_IF_CONFIG_SMALL("Android camera input device"),
866 .priv_data_size = sizeof(AndroidCameraCtx),
867 .read_header = android_camera_read_header,
868 .read_packet = android_camera_read_packet,
869 .read_close = android_camera_read_close,
870 .flags = AVFMT_NOFILE,
871 .priv_class = &android_camera_class,