1 /*
2 * Android camera input device
3 *
4 * Copyright (C) 2017 Felix Matouschek
5 *
6 * This file is part of FFmpeg.
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include <errno.h>
24 #include <pthread.h>
25 #include <stdatomic.h>
26 #include <stdbool.h>
27 #include <stdint.h>
28
29 #include <camera/NdkCameraDevice.h>
30 #include <camera/NdkCameraManager.h>
31 #include <media/NdkImage.h>
32 #include <media/NdkImageReader.h>
33
45
46 /* This image format is available on all Android devices
47 * supporting the Camera2 API */
48 #define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888
49
50 #define MAX_BUF_COUNT 2
51 #define VIDEO_STREAM_INDEX 0
52 #define VIDEO_TIMEBASE_ANDROID 1000000000
53
54 #define RETURN_CASE(x) case x: return AV_STRINGIFY(x);
55 #define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x);
56
59
65
72
87
92
94 {
112 }
113 }
114
116 {
140 }
141 }
142
144 {
151 default:
152 return "ERROR_CAMERA_UNKNOWN";
153 }
154 }
155
157 {
162 ACameraDevice_getId(device));
163 }
164
166 {
172 }
173
175 {
178 ACameraIdList *camera_ids;
179
180 ret = ACameraManager_getCameraIdList(
ctx->camera_mgr, &camera_ids);
181 if (
ret != ACAMERA_OK) {
185 }
186
187 if (
ctx->camera_index < camera_ids->numCameras) {
189 if (!
ctx->camera_id) {
192 }
193 } else {
197 }
198
199 ACameraManager_deleteCameraIdList(camera_ids);
200
201 ret = ACameraManager_getCameraCharacteristics(
ctx->camera_mgr,
202 ctx->camera_id, &
ctx->camera_metadata);
203 if (
ret != ACAMERA_OK) {
204 av_log(avctx,
AV_LOG_ERROR,
"Failed to get metadata for camera with id %s, error: %s.\n",
207 }
208
209 ctx->camera_state_callbacks.context = avctx;
212
213 ret = ACameraManager_openCamera(
ctx->camera_mgr,
ctx->camera_id,
214 &
ctx->camera_state_callbacks, &
ctx->camera_dev);
215 if (
ret != ACAMERA_OK) {
219 }
220
221 return 0;
222 }
223
225 {
227 ACameraMetadata_const_entry lens_facing;
228 ACameraMetadata_const_entry sensor_orientation;
229
230 ACameraMetadata_getConstEntry(
ctx->camera_metadata,
231 ACAMERA_LENS_FACING, &lens_facing);
232 ACameraMetadata_getConstEntry(
ctx->camera_metadata,
233 ACAMERA_SENSOR_ORIENTATION, &sensor_orientation);
234
235 ctx->lens_facing = lens_facing.data.u8[0];
236 ctx->sensor_orientation = sensor_orientation.data.i32[0];
237 }
238
240 {
242 ACameraMetadata_const_entry available_configs;
243 int found = 0;
244
245 ACameraMetadata_getConstEntry(
ctx->camera_metadata,
246 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
247 &available_configs);
248
249 for (
int i = 0;
i < available_configs.count;
i++) {
252
254 continue;
255 }
256
260
261 //Same ratio
266 found = 1;
267 break;
268 }
269 }
270 }
271
272 if (!found ||
ctx->width == 0 ||
ctx->height == 0) {
273 ctx->width = available_configs.data.i32[1];
274 ctx->height = available_configs.data.i32[2];
275
277 "Requested video_size %dx%d not available, falling back to %dx%d\n",
278 ctx->requested_width,
ctx->requested_height,
ctx->width,
ctx->height);
279 }
280
281 return;
282 }
283
285 {
287 ACameraMetadata_const_entry available_framerates;
288 int found = 0;
289 int current_best_match = -1;
290 int requested_framerate =
av_q2d(
ctx->framerate);
291
292 ACameraMetadata_getConstEntry(
ctx->camera_metadata,
293 ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
294 &available_framerates);
295
296 for (
int i = 0;
i < available_framerates.count;
i++) {
297 int32_t min = available_framerates.data.i32[
i * 2 + 0];
298 int32_t max = available_framerates.data.i32[
i * 2 + 1];
299
300 if (requested_framerate ==
max) {
302 ctx->framerate_range[0] =
min;
303 ctx->framerate_range[1] =
max;
304 found = 1;
305 break;
306 } else if (current_best_match >= 0) {
307 int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0];
308 if (
min > current_best_match_min) {
309 current_best_match =
i;
310 }
311 } else {
312 current_best_match =
i;
313 }
314 }
315 }
316
317 if (!found) {
318 if (current_best_match >= 0) {
319 ctx->framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0];
320 ctx->framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1];
321
322 } else {
323 ctx->framerate_range[0] = available_framerates.data.i32[0];
324 ctx->framerate_range[1] = available_framerates.data.i32[1];
325 }
326
328 "Requested framerate %d not available, falling back to min: %d and max: %d fps\n",
329 requested_framerate,
ctx->framerate_range[0],
ctx->framerate_range[1]);
330 }
331
332 return;
333 }
334
336 {
339 uint8_t *image_plane_data[2];
340 int plane_data_length[2];
341
342 for (
int i = 0;
i < 2;
i++) {
343 AImage_getPlanePixelStride(image,
i + 1, &image_pixelstrides[
i]);
344 AImage_getPlaneData(image,
i + 1, &image_plane_data[
i], &plane_data_length[
i]);
345 }
346
347 if (image_pixelstrides[0] != image_pixelstrides[1]) {
349 "Pixel strides of U and V plane should have been the same.\n");
351 }
352
353 switch (image_pixelstrides[0]) {
354 case 1:
356 break;
357 case 2:
358 if (image_plane_data[0] < image_plane_data[1]) {
360 } else {
362 }
363 break;
364 default:
366 "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n",
367 image_pixelstrides[0]);
369 }
370
371 return 0;
372 }
373
375 {
378 media_status_t media_status;
380
381 AImage *image;
382 int64_t image_timestamp;
384 uint8_t *image_plane_data[4];
385 int plane_data_length[4];
386
388 int pkt_buffer_size = 0;
389
390 media_status = AImageReader_acquireLatestImage(reader, &image);
391 if (media_status != AMEDIA_OK) {
392 if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
394 "An image reader frame was discarded");
395 } else {
397 "Failed to acquire latest image from image reader, error: %s.\n",
400 }
402 }
403
404 // Silently drop frames when exit is set
407 }
408
409 // Determine actual image format
414 "Could not get image format of camera.\n");
416 } else {
418 }
419 }
420
422 AImage_getTimestamp(image, &image_timestamp);
423
424 AImage_getPlaneRowStride(image, 0, &image_linestrides[0]);
425 AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]);
426
427 switch (
ctx->image_format) {
429 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
430 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
431 AImage_getPlaneRowStride(image, 2, &image_linestrides[2]);
432 AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]);
433 break;
435 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
436 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
437 break;
439 AImage_getPlaneRowStride(image, 2, &image_linestrides[1]);
440 AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]);
441 break;
442 default:
446 }
447
451 "Failed to create new av packet, error: %s.\n",
av_err2str(
ret));
453 }
454
456 pkt.
pts = image_timestamp;
458 (const uint8_t * const *) image_plane_data,
459 image_linestrides,
ctx->image_format,
460 ctx->width,
ctx->height, 32);
461
463
468 "Error while processing new image, error: %s.\n",
av_err2str(
ret));
471 } else {
473 "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n",
474 ctx->input_queue_size);
475 }
476 if (pkt_buffer_size) {
478 }
479 }
480
481 AImage_delete(image);
482
483 return;
484 }
485
487 {
490
493 if (
ret != AMEDIA_OK) {
497 }
498
499 ctx->image_listener.context = avctx;
501
502 ret = AImageReader_setImageListener(
ctx->image_reader, &
ctx->image_listener);
503 if (
ret != AMEDIA_OK) {
505 "Failed to set image listener on image reader, error: %s.\n",
508 }
509
510 ret = AImageReader_getWindow(
ctx->image_reader, &
ctx->image_reader_window);
511 if (
ret != AMEDIA_OK) {
513 "Could not get image reader window, error: %s.\n",
516 }
517
518 return 0;
519 }
520
522 {
524 }
525
527 {
529 }
530
532 {
534 }
535
537 {
540
541 ret = ACaptureSessionOutputContainer_create(&
ctx->capture_session_output_container);
542 if (
ret != ACAMERA_OK) {
544 "Failed to create capture session output container, error: %s.\n",
547 }
548
549 ANativeWindow_acquire(
ctx->image_reader_window);
550
551 ret = ACaptureSessionOutput_create(
ctx->image_reader_window, &
ctx->capture_session_output);
552 if (
ret != ACAMERA_OK) {
554 "Failed to create capture session container, error: %s.\n",
557 }
558
559 ret = ACaptureSessionOutputContainer_add(
ctx->capture_session_output_container,
560 ctx->capture_session_output);
561 if (
ret != ACAMERA_OK) {
563 "Failed to add output to output container, error: %s.\n",
566 }
567
568 ret = ACameraOutputTarget_create(
ctx->image_reader_window, &
ctx->camera_output_target);
569 if (
ret != ACAMERA_OK) {
571 "Failed to create camera output target, error: %s.\n",
574 }
575
576 ret = ACameraDevice_createCaptureRequest(
ctx->camera_dev, TEMPLATE_RECORD, &
ctx->capture_request);
577 if (
ret != ACAMERA_OK) {
579 "Failed to create capture request, error: %s.\n",
582 }
583
584 ret = ACaptureRequest_setEntry_i32(
ctx->capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,
585 2,
ctx->framerate_range);
586 if (
ret != ACAMERA_OK) {
588 "Failed to set target fps range in capture request, error: %s.\n",
591 }
592
593 ret = ACaptureRequest_addTarget(
ctx->capture_request,
ctx->camera_output_target);
594 if (
ret != ACAMERA_OK) {
596 "Failed to add capture request capture request, error: %s.\n",
599 }
600
601 ctx->capture_session_state_callbacks.context = avctx;
605
606 ret = ACameraDevice_createCaptureSession(
ctx->camera_dev,
ctx->capture_session_output_container,
607 &
ctx->capture_session_state_callbacks, &
ctx->capture_session);
608 if (
ret != ACAMERA_OK) {
610 "Failed to create capture session, error: %s.\n",
613 }
614
615 ret = ACameraCaptureSession_setRepeatingRequest(
ctx->capture_session,
NULL, 1, &
ctx->capture_request,
NULL);
616 if (
ret != ACAMERA_OK) {
618 "Failed to set repeating request on capture session, error: %s.\n",
621 }
622
623 return 0;
624 }
625
627 {
629
631 //Wait until first frame arrived and actual image format was determined
632 usleep(1000);
633 }
634
636 }
637
639 {
641 uint8_t *side_data;
643
645
646 if (
ctx->lens_facing == ACAMERA_LENS_FACING_FRONT) {
648 }
649
652
653 if (!side_data) {
655 }
656
657 memcpy(side_data, display_matrix, sizeof(display_matrix));
658
659 return 0;
660 }
661
663 {
667
669 if (!st) {
671 }
672
676
679 }
680
687
689
691 }
692
694 {
696
698
699 if (
ctx->capture_session) {
700 ACameraCaptureSession_stopRepeating(
ctx->capture_session);
701 // Following warning is emitted, after capture session closed callback is received:
702 // ACameraCaptureSession: Device is closed but session 0 is not notified
703 // Seems to be a bug in Android, we can ignore this
704 ACameraCaptureSession_close(
ctx->capture_session);
706 }
707
708 if (
ctx->capture_request) {
709 ACaptureRequest_removeTarget(
ctx->capture_request,
ctx->camera_output_target);
710 ACaptureRequest_free(
ctx->capture_request);
712 }
713
714 if (
ctx->camera_output_target) {
715 ACameraOutputTarget_free(
ctx->camera_output_target);
716 ctx->camera_output_target =
NULL;
717 }
718
719 if (
ctx->capture_session_output) {
720 ACaptureSessionOutputContainer_remove(
ctx->capture_session_output_container,
721 ctx->capture_session_output);
722 ACaptureSessionOutput_free(
ctx->capture_session_output);
723 ctx->capture_session_output =
NULL;
724 }
725
726 if (
ctx->image_reader_window) {
727 ANativeWindow_release(
ctx->image_reader_window);
728 ctx->image_reader_window =
NULL;
729 }
730
731 if (
ctx->capture_session_output_container) {
732 ACaptureSessionOutputContainer_free(
ctx->capture_session_output_container);
733 ctx->capture_session_output_container =
NULL;
734 }
735
736 if (
ctx->camera_dev) {
737 ACameraDevice_close(
ctx->camera_dev);
739 }
740
741 if (
ctx->image_reader) {
742 AImageReader_delete(
ctx->image_reader);
744 }
745
746 if (
ctx->camera_metadata) {
747 ACameraMetadata_free(
ctx->camera_metadata);
749 }
750
752
753 if (
ctx->camera_mgr) {
754 ACameraManager_delete(
ctx->camera_mgr);
756 }
757
758 if (
ctx->input_queue) {
763 }
765 }
766
767 return 0;
768 }
769
771 {
774
777
781 "Failed to allocate input queue, error: %s.\n",
av_err2str(
ret));
783 }
784
785 ctx->camera_mgr = ACameraManager_create();
786 if (!
ctx->camera_mgr) {
790 }
791
796 }
797
801
805 }
806
810 }
811
813
818 }
819
821 }
822
824 {
827
831 } else {
833 }
834
837 } else {
839 }
840 }
841
842 #define OFFSET(x) offsetof(AndroidCameraCtx, x)
843 #define DEC AV_OPT_FLAG_DECODING_PARAM
847 {
"camera_index",
"set index of camera to use",
OFFSET(camera_index),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
DEC },
848 {
"input_queue_size",
"set maximum number of frames to buffer",
OFFSET(input_queue_size),
AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX,
DEC },
850 };
851
858 };
859
861 .
name =
"android_camera",
869 };